source: ntrip/trunk/BNS/RTCM/rtcm3torinex.c@ 2236

Last change on this file since 2236 was 2236, checked in by mervart, 14 years ago

* empty log message *

File size: 78.4 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.28 2010/01/12 12:13:23 mervart Exp $
4 Copyright (C) 2005-2008 by Dirk Stöcker <stoecker@alberding.eu>
5
6 This software is a complete NTRIP-RTCM3 to RINEX converter as well as
7 a module of the BNC tool for multiformat conversion. Contact Dirk
8 Stöcker for suggestions and bug reports related to the RTCM3 to RINEX
9 conversion problems and the author of BNC for all the other problems.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 or read http://www.gnu.org/licenses/gpl.txt
25*/
26
27#include <ctype.h>
28#include <errno.h>
29#include <math.h>
30#include <signal.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/types.h>
36#include <time.h>
37#include <unistd.h>
38
39#ifndef NO_RTCM3_MAIN
40#include <getopt.h>
41#include <netdb.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44#endif
45
46#ifndef sparc
47#include <stdint.h>
48#endif
49
50#ifndef isinf
51# define isinf(x) 0
52#endif
53
54#include "rtcm3torinex.h"
55
56/* CVS revision and version */
57static char revisionstr[] = "$Revision: 1.28 $";
58
59#ifndef COMPILEDATE
60#define COMPILEDATE " built " __DATE__
61#endif
62
63static uint32_t CRC24(long size, const unsigned char *buf)
64{
65 uint32_t crc = 0;
66 int i;
67
68 while(size--)
69 {
70 crc ^= (*buf++) << (16);
71 for(i = 0; i < 8; i++)
72 {
73 crc <<= 1;
74 if(crc & 0x1000000)
75 crc ^= 0x01864cfb;
76 }
77 }
78 return crc;
79}
80
81static int GetMessage(struct RTCM3ParserData *handle)
82{
83 unsigned char *m, *e;
84 int i;
85
86 m = handle->Message+handle->SkipBytes;
87 e = handle->Message+handle->MessageSize;
88 handle->NeedBytes = handle->SkipBytes = 0;
89 while(e-m >= 3)
90 {
91 if(m[0] == 0xD3)
92 {
93 handle->size = ((m[1]&3)<<8)|m[2];
94 if(e-m >= handle->size+6)
95 {
96 if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8)
97 |(m[3+handle->size+2])) == CRC24(handle->size+3, m))
98 {
99 handle->SkipBytes = handle->size;
100 break;
101 }
102 else
103 ++m;
104 }
105 else
106 {
107 handle->NeedBytes = handle->size+6;
108 break;
109 }
110 }
111 else
112 ++m;
113 }
114 if(e-m < 3)
115 handle->NeedBytes = 3;
116
117 /* copy buffer to front */
118 i = m - handle->Message;
119 if(i && m < e)
120 memmove(handle->Message, m, (size_t)(handle->MessageSize-i));
121 handle->MessageSize -= i;
122
123 return !handle->NeedBytes;
124}
125
126#define LOADBITS(a) \
127{ \
128 while((a) > numbits) \
129 { \
130 if(!size--) break; \
131 bitfield = (bitfield<<8)|*(data++); \
132 numbits += 8; \
133 } \
134}
135
136/* extract bits from data stream
137 b = variable to store result, a = number of bits */
138#define GETBITS(b, a) \
139{ \
140 LOADBITS(a) \
141 b = (bitfield<<(64-numbits))>>(64-(a)); \
142 numbits -= (a); \
143}
144
145/* extract floating value from data stream
146 b = variable to store result, a = number of bits */
147#define GETFLOAT(b, a, c) \
148{ \
149 LOADBITS(a) \
150 b = ((double)((bitfield<<(64-numbits))>>(64-(a))))*(c); \
151 numbits -= (a); \
152}
153
154/* extract signed floating value from data stream
155 b = variable to store result, a = number of bits */
156#define GETFLOATSIGN(b, a, c) \
157{ \
158 LOADBITS(a) \
159 b = ((double)(((int64_t)(bitfield<<(64-numbits)))>>(64-(a))))*(c); \
160 numbits -= (a); \
161}
162
163/* extract bits from data stream
164 b = variable to store result, a = number of bits */
165#define GETBITSSIGN(b, a) \
166{ \
167 LOADBITS(a) \
168 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
169 numbits -= (a); \
170}
171
172#define GETFLOATSIGNM(b, a, c) \
173{ int l; \
174 LOADBITS(a) \
175 l = (bitfield<<(64-numbits))>>(64-1); \
176 b = ((double)(((bitfield<<(64-(numbits-1))))>>(64-(a-1))))*(c); \
177 numbits -= (a); \
178 if(l) b *= -1.0; \
179}
180
181#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
182
183/* extract byte-aligned byte from data stream,
184 b = variable to store size, s = variable to store string pointer */
185#define GETSTRING(b, s) \
186{ \
187 b = *(data++); \
188 s = (char *) data; \
189 data += b; \
190 size -= b+1; \
191}
192
193struct leapseconds { /* specify the day of leap second */
194 int day; /* this is the day, where 23:59:59 exists 2 times */
195 int month; /* not the next day! */
196 int year;
197 int taicount;
198};
199static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
200static const struct leapseconds leap[] = {
201/*{31, 12, 1971, 11},*/
202/*{31, 12, 1972, 12},*/
203/*{31, 12, 1973, 13},*/
204/*{31, 12, 1974, 14},*/
205/*{31, 12, 1975, 15},*/
206/*{31, 12, 1976, 16},*/
207/*{31, 12, 1977, 17},*/
208/*{31, 12, 1978, 18},*/
209/*{31, 12, 1979, 19},*/
210{30, 06, 1981,20},
211{30, 06, 1982,21},
212{30, 06, 1983,22},
213{30, 06, 1985,23},
214{31, 12, 1987,24},
215{31, 12, 1989,25},
216{31, 12, 1990,26},
217{30, 06, 1992,27},
218{30, 06, 1993,28},
219{30, 06, 1994,29},
220{31, 12, 1995,30},
221{30, 06, 1997,31},
222{31, 12, 1998,32},
223{31, 12, 2005,33},
224{31, 12, 2008,34},
225{0,0,0,0} /* end marker */
226};
227#define LEAPSECONDS 14 /* only needed for approx. time */
228#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
229
230static int longyear(int year, int month)
231{
232 if(!(year % 4) && (!(year % 400) || (year % 100)))
233 {
234 if(!month || month == 2)
235 return 1;
236 }
237 return 0;
238}
239
240int gnumleap(int year, int month, int day)
241{
242 int ls = 0;
243 const struct leapseconds *l;
244
245 for(l = leap; l->taicount && year >= l->year; ++l)
246 {
247 if(year > l->year || month > l->month || (month == l->month && day > l->day))
248 ls = l->taicount - GPSLEAPSTART;
249 }
250 return ls;
251}
252
253void updatetime(int *week, int *tow, int tk, int fixnumleap)
254{
255 int y,m,d,k,l, nul;
256 unsigned int j = *week*(7*24*60*60) + *tow + 5*24*60*60+3*60*60;
257 int glo_daynumber = 0, glo_timeofday;
258 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
259 + gnumleap(y+1,1,1); ++y)
260 {
261 j -= k; glo_daynumber += l;
262 }
263 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
264 + gnumleap(y, m+1, 1); ++m)
265 {
266 j -= k; glo_daynumber += l;
267 }
268 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
269 j -= 24*60*60;
270 glo_daynumber -= 16*365+4-d;
271 nul = gnumleap(y, m, d);
272 glo_timeofday = j-nul;
273
274 if(tk < 5*60*1000 && glo_timeofday > 23*60*60)
275 *tow += 24*60*60;
276 else if(glo_timeofday < 5*60 && tk > 23*60*60*1000)
277 *tow -= 24*60*60;
278 *tow += tk/1000-glo_timeofday;
279 if(fixnumleap)
280 *tow -= nul;
281 if(*tow < 0) {*tow += 24*60*60*7; --*week; }
282 if(*tow >= 24*60*60*7) {*tow -= 24*60*60*7; ++*week; }
283}
284
285int RTCM3Parser(struct RTCM3ParserData *handle)
286{
287 int ret=0;
288
289#ifdef NO_RTCM3_MAIN
290 if(GetMessage(handle)) /* don't repeat */
291#else
292 while(!ret && GetMessage(handle))
293#endif /* NO_RTCM3_MAIN */
294 {
295 /* using 64 bit integer types, as it is much easier than handling
296 the long datatypes in 32 bit */
297 uint64_t numbits = 0, bitfield = 0;
298 int size = handle->size, type;
299 int syncf, old = 0;
300 unsigned char *data = handle->Message+3;
301
302 GETBITS(type,12)
303#ifdef NO_RTCM3_MAIN
304 handle->blocktype = type;
305#endif /* NO_RTCM3_MAIN */
306 switch(type)
307 {
308#ifdef NO_RTCM3_MAIN
309 default:
310 ret = type;
311 break;
312 case 1005: case 1006:
313 {
314 SKIPBITS(22)
315 GETBITSSIGN(handle->antX, 38)
316 SKIPBITS(2)
317 GETBITSSIGN(handle->antY, 38)
318 SKIPBITS(2)
319 GETBITSSIGN(handle->antZ, 38)
320 if(type == 1006)
321 GETBITS(handle->antH, 16)
322 ret = type;
323 }
324 break;
325 case 1007: case 1008: case 1033:
326 {
327 char *antenna;
328 int antnum;
329
330 SKIPBITS(12)
331 GETSTRING(antnum,antenna)
332 memcpy(handle->antenna, antenna, antnum);
333 handle->antenna[antnum] = 0;
334 ret = type;
335 }
336 break;
337#endif /* NO_RTCM3_MAIN */
338 case 1019:
339 {
340 struct gpsephemeris *ge;
341 int sv;
342
343 ge = &handle->ephemerisGPS;
344 memset(ge, 0, sizeof(*ge));
345
346 GETBITS(sv, 6)
347 ge->satellite = (sv < 40 ? sv : sv+80);
348 GETBITS(ge->GPSweek, 10)
349 ge->GPSweek += 1024;
350 GETBITS(ge->URAindex, 4)
351 GETBITS(sv, 2)
352 if(sv & 1)
353 ge->flags |= GPSEPHF_L2PCODE;
354 if(sv & 2)
355 ge->flags |= GPSEPHF_L2CACODE;
356 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
357 GETBITS(ge->IODE, 8)
358 GETBITS(ge->TOC, 16)
359 ge->TOC <<= 4;
360 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
361 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
362 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
363 GETBITS(ge->IODC, 10)
364 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
365 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
366 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
367 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
368 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
369 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
370 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
371 GETBITS(ge->TOE, 16)
372 ge->TOE <<= 4;
373
374 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
375 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
376 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
377 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
378 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
379 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
380 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
381 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
382 GETBITS(ge->SVhealth, 6)
383 GETBITS(sv, 1)
384 if(sv)
385 ge->flags |= GPSEPHF_L2PCODEDATA;
386
387 ret = 1019;
388 }
389 break;
390 case 1020:
391 {
392 struct glonassephemeris *ge;
393 int i;
394
395 ge = &handle->ephemerisGLONASS;
396 memset(ge, 0, sizeof(*ge));
397
398 ge->flags |= GLOEPHF_PAVAILABLE;
399 GETBITS(ge->almanac_number, 6)
400 GETBITS(i, 5)
401 ge->frequency_number = i-7;
402 GETBITS(i, 1)
403 if(i)
404 ge->flags |= GLOEPHF_ALMANACHEALTHY;
405 GETBITS(i, 1)
406 if(i)
407 ge->flags |= GLOEPHF_ALMANACHEALTHOK;
408 GETBITS(i, 2)
409 if(i & 1)
410 ge->flags |= GLOEPHF_P10TRUE;
411 if(i & 2)
412 ge->flags |= GLOEPHF_P11TRUE;
413 GETBITS(i, 5)
414 ge->tk = i*60*60;
415 GETBITS(i, 6)
416 ge->tk += i*60;
417 GETBITS(i, 1)
418 ge->tk += i*30;
419 GETBITS(i, 1)
420 if(i)
421 ge->flags |= GLOEPHF_UNHEALTHY;
422 GETBITS(i, 1)
423 if(i)
424 ge->flags |= GLOEPHF_P2TRUE;
425 GETBITS(i, 7)
426 ge->tb = i*15*60;
427 GETFLOATSIGNM(ge->x_velocity, 24, 1.0/(double)(1<<20))
428 GETFLOATSIGNM(ge->x_pos, 27, 1.0/(double)(1<<11))
429 GETFLOATSIGNM(ge->x_acceleration, 5, 1.0/(double)(1<<30))
430 GETFLOATSIGNM(ge->y_velocity, 24, 1.0/(double)(1<<20))
431 GETFLOATSIGNM(ge->y_pos, 27, 1.0/(double)(1<<11))
432 GETFLOATSIGNM(ge->y_acceleration, 5, 1.0/(double)(1<<30))
433 GETFLOATSIGNM(ge->z_velocity, 24, 1.0/(double)(1<<20))
434 GETFLOATSIGNM(ge->z_pos, 27, 1.0/(double)(1<<11))
435 GETFLOATSIGNM(ge->z_acceleration, 5, 1.0/(double)(1<<30))
436 GETBITS(i, 1)
437 if(i)
438 ge->flags |= GLOEPHF_P3TRUE;
439 GETFLOATSIGNM(ge->gamma, 11, 1.0/(double)(1<<30)/(double)(1<<10))
440 SKIPBITS(3) /* GLONASS-M P, GLONASS-M ln (third string) */
441 GETFLOATSIGNM(ge->tau, 22, 1.0/(double)(1<<30)) /* GLONASS tau n(tb) */
442 SKIPBITS(5) /* GLONASS-M delta tau n(tb) */
443 GETBITS(ge->E, 5)
444 /* GETBITS(b, 1) / * GLONASS-M P4 */
445 /* GETBITS(b, 4) / * GLONASS-M Ft */
446 /* GETBITS(b, 11) / * GLONASS-M Nt */
447 /* GETBITS(b, 2) / * GLONASS-M M */
448 /* GETBITS(b, 1) / * GLONASS-M The Availability of Additional Data */
449 /* GETBITS(b, 11) / * GLONASS-M Na */
450 /* GETFLOATSIGNM(b, 32, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS tau c */
451 /* GETBITS(b, 5) / * GLONASS-M N4 */
452 /* GETFLOATSIGNM(b, 22, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS-M tau GPS */
453 /* GETBITS(b, 1) / * GLONASS-M ln (fifth string) */
454 ge->GPSWeek = handle->GPSWeek;
455 ge->GPSTOW = handle->GPSTOW;
456 ret = 1020;
457 }
458 break;
459 case 1001: case 1002: case 1003: case 1004:
460 if(handle->GPSWeek)
461 {
462 int lastlockl1[64];
463 int lastlockl2[64];
464 struct gnssdata *gnss;
465 int i, numsats, wasamb=0;
466
467 for(i = 0; i < 64; ++i)
468 lastlockl1[i] = lastlockl2[i] = 0;
469
470 gnss = &handle->DataNew;
471
472 SKIPBITS(12) /* id */
473 GETBITS(i,30)
474 if(i/1000 < (int)handle->GPSTOW - 86400)
475 ++handle->GPSWeek;
476 handle->GPSTOW = i/1000;
477 if(gnss->week && (gnss->timeofweek != i || gnss->week
478 != handle->GPSWeek))
479 {
480 handle->Data = *gnss;
481 memset(gnss, 0, sizeof(*gnss));
482 old = 1;
483 }
484 gnss->timeofweek = i;
485 gnss->week = handle->GPSWeek;
486
487 GETBITS(syncf,1) /* sync */
488 GETBITS(numsats,5)
489 SKIPBITS(4) /* smind, smint */
490
491 while(numsats--)
492 {
493 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
494 int fullsat, num;
495
496 GETBITS(sv, 6)
497 fullsat = sv < 40 ? sv : sv+80;
498 for(num = 0; num < gnss->numsats
499 && fullsat != gnss->satellites[num]; ++num)
500 ;
501
502 if(num == gnss->numsats)
503 gnss->satellites[gnss->numsats++] = fullsat;
504
505 /* L1 */
506 GETBITS(code, 1);
507 if(code)
508 {
509 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
510 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
511 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
512 }
513 else
514 {
515 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
516 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
517 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
518 }
519 GETBITS(l1range, 24);
520 GETBITSSIGN(i, 20);
521 if((i&((1<<20)-1)) != 0x80000)
522 {
523 gnss->dataflags[num] |= (c|l);
524 gnss->measdata[num][ce] = l1range*0.02;
525 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
526 }
527 GETBITS(i, 7);
528 lastlockl1[sv] = i;
529 if(handle->lastlockl1[sv] > i)
530 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
531 if(type == 1002 || type == 1004)
532 {
533 GETBITS(amb,8);
534 if(amb && (gnss->dataflags[num] & c))
535 {
536 gnss->measdata[num][ce] += amb*299792.458;
537 gnss->measdata[num][le] += amb*299792.458;
538 ++wasamb;
539 }
540 GETBITS(i, 8);
541 if(i)
542 {
543 gnss->dataflags[num] |= s;
544 gnss->measdata[num][se] = i*0.25;
545 i /= 4*4;
546 if(i > 9) i = 9;
547 else if(i < 1) i = 1;
548 gnss->snrL1[num] = i;
549 }
550 }
551 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
552 if(type == 1003 || type == 1004)
553 {
554 /* L2 */
555 GETBITS(code,2);
556 if(code)
557 {
558 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
559 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
560 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
561 }
562 else
563 {
564 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
565 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
566 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
567 }
568 GETBITSSIGN(i,14);
569 if((i&((1<<14)-1)) != 0x2000)
570 {
571 gnss->dataflags[num] |= c;
572 gnss->measdata[num][ce] = l1range*0.02+i*0.02
573 +amb*299792.458;
574 }
575 GETBITSSIGN(i,20);
576 if((i&((1<<20)-1)) != 0x80000)
577 {
578 gnss->dataflags[num] |= l;
579 gnss->measdata[num][le] = l1range*0.02+i*0.0005
580 +amb*299792.458;
581 }
582 GETBITS(i,7);
583 lastlockl2[sv] = i;
584 if(handle->lastlockl2[sv] > i)
585 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
586 if(type == 1004)
587 {
588 GETBITS(i, 8);
589 if(i)
590 {
591 gnss->dataflags[num] |= s;
592 gnss->measdata[num][se] = i*0.25;
593 i /= 4*4;
594 if(i > 9) i = 9;
595 else if(i < 1) i = 1;
596 gnss->snrL2[num] = i;
597 }
598 }
599 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
600 }
601 }
602 for(i = 0; i < 64; ++i)
603 {
604 handle->lastlockl1[i] = lastlockl1[i];
605 handle->lastlockl2[i] = lastlockl2[i];
606 }
607 if(!syncf && !old)
608 {
609 handle->Data = *gnss;
610 memset(gnss, 0, sizeof(*gnss));
611 }
612 if(!syncf || old)
613 {
614 if(wasamb) /* not RINEX compatible without */
615 ret = 1;
616 else
617 ret = 2;
618 }
619#ifdef NO_RTCM3_MAIN
620 else
621 ret = type;
622#endif /* NO_RTCM3_MAIN */
623 }
624 break;
625 case 1009: case 1010: case 1011: case 1012:
626 {
627 int lastlockl1[64];
628 int lastlockl2[64];
629 struct gnssdata *gnss;
630 int i, numsats;
631 int wasamb=0;
632
633 for(i = 0; i < 64; ++i)
634 lastlockl1[i] = lastlockl2[i] = 0;
635
636 gnss = &handle->DataNew;
637
638 SKIPBITS(12) /* id */;
639 GETBITS(i,27) /* tk */
640
641 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0);
642 i = handle->GPSTOW*1000;
643 if(gnss->week && (gnss->timeofweek != i || gnss->week
644 != handle->GPSWeek))
645 {
646 handle->Data = *gnss;
647 memset(gnss, 0, sizeof(*gnss));
648 old = 1;
649 }
650
651 gnss->timeofweek = i;
652 gnss->week = handle->GPSWeek;
653
654 GETBITS(syncf,1) /* sync */
655 GETBITS(numsats,5)
656
657 SKIPBITS(4) /* smind, smint */
658
659 while(numsats--)
660 {
661 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
662 int freq;
663 int fullsat, num;
664
665 GETBITS(sv, 6)
666 fullsat = sv-1 + PRN_GLONASS_START;
667 for(num = 0; num < gnss->numsats
668 && fullsat != gnss->satellites[num]; ++num)
669 ;
670
671 if(num == gnss->numsats)
672 gnss->satellites[gnss->numsats++] = fullsat;
673
674 /* L1 */
675 GETBITS(code, 1)
676 GETBITS(freq, 5)
677
678 gnss->channels[num] = freq - 7;
679
680 if(code)
681 {
682 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
683 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
684 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
685 }
686 else
687 {
688 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
689 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
690 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
691 }
692 GETBITS(l1range, 25)
693 GETBITSSIGN(i, 20)
694 if((i&((1<<20)-1)) != 0x80000)
695 {
696 /* Handle this like GPS. Actually for GLONASS L1 range is always
697 valid. To be on the save side, we handle it as invalid like we
698 do for GPS and also remove range in case of 0x80000. */
699 gnss->dataflags[num] |= (c|l);
700 gnss->measdata[num][ce] = l1range*0.02;
701 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
702 }
703 GETBITS(i, 7)
704 lastlockl1[sv] = i;
705 if(handle->lastlockl1[sv] > i)
706 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
707 if(type == 1010 || type == 1012)
708 {
709 GETBITS(amb,7)
710 if(amb && (gnss->dataflags[num] & c))
711 {
712 gnss->measdata[num][ce] += amb*599584.916;
713 gnss->measdata[num][le] += amb*599584.916;
714 ++wasamb;
715 }
716 GETBITS(i, 8)
717 if(i)
718 {
719 gnss->dataflags[num] |= s;
720 gnss->measdata[num][se] = i*0.25;
721 i /= 4*4;
722 if(i > 9) i = 9;
723 else if(i < 1) i = 1;
724 gnss->snrL1[num] = i;
725 }
726 }
727 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
728 if(type == 1011 || type == 1012)
729 {
730 /* L2 */
731 GETBITS(code,2)
732 if(code)
733 {
734 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
735 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
736 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
737 }
738 else
739 {
740 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
741 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
742 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
743 }
744 GETBITSSIGN(i,14)
745 if((i&((1<<14)-1)) != 0x2000)
746 {
747 gnss->dataflags[num] |= c;
748 gnss->measdata[num][ce] = l1range*0.02+i*0.02
749 +amb*599584.916;
750 }
751 GETBITSSIGN(i,20)
752 if((i&((1<<20)-1)) != 0x80000)
753 {
754 gnss->dataflags[num] |= l;
755 gnss->measdata[num][le] = l1range*0.02+i*0.0005
756 +amb*599584.916;
757 }
758 GETBITS(i,7)
759 lastlockl2[sv] = i;
760 if(handle->lastlockl2[sv] > i)
761 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
762 if(type == 1012)
763 {
764 GETBITS(i, 8)
765 if(i)
766 {
767 gnss->dataflags[num] |= s;
768 gnss->measdata[num][se] = i*0.25;
769 i /= 4*4;
770 if(i > 9) i = 9;
771 else if(i < 1) i = 1;
772 gnss->snrL2[num] = i;
773 }
774 }
775 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
776 }
777 if(!sv || sv > 24) /* illegal, remove it again */
778 --gnss->numsats;
779 }
780 for(i = 0; i < 64; ++i)
781 {
782 handle->lastlockl1[i] = lastlockl1[i];
783 handle->lastlockl2[i] = lastlockl2[i];
784 }
785 if(!syncf && !old)
786 {
787 handle->Data = *gnss;
788 memset(gnss, 0, sizeof(*gnss));
789 }
790 if(!syncf || old)
791 {
792 if(wasamb) /* not RINEX compatible without */
793 ret = 1;
794 else
795 ret = 2;
796 }
797#ifdef NO_RTCM3_MAIN
798 else
799 ret = type;
800#endif /* NO_RTCM3_MAIN */
801 }
802 break;
803 }
804 }
805 return ret;
806}
807
808struct Header
809{
810 const char *version;
811 const char *pgm;
812 const char *marker;
813 const char *markertype;
814 const char *observer;
815 const char *receiver;
816 const char *antenna;
817 const char *position;
818 const char *antennaposition;
819 const char *wavelength;
820 const char *typesofobs; /* should not be modified outside */
821 const char *typesofobsG; /* should not be modified outside */
822 const char *typesofobsR; /* should not be modified outside */
823 const char *typesofobsS; /* should not be modified outside */
824 const char *timeoffirstobs; /* should not be modified outside */
825};
826
827#define MAXHEADERLINES 50
828#define MAXHEADERBUFFERSIZE 4096
829struct HeaderData
830{
831 union
832 {
833 struct Header named;
834 const char *unnamed[MAXHEADERLINES];
835 } data;
836 int numheaders;
837};
838
839void converttime(struct converttimeinfo *c, int week, int tow)
840{
841 int i, k, doy, j; /* temporary variables */
842 j = week*(7*24*60*60) + tow + 5*24*60*60;
843 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
844 j -= k;
845 c->year = i;
846 doy = 1+ (j / (24*60*60));
847 j %= (24*60*60);
848 c->hour = j / (60*60);
849 j %= (60*60);
850 c->minute = j / 60;
851 c->second = j % 60;
852 j = 0;
853 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
854 j += k;
855 c->month = i;
856 c->day = doy - j;
857}
858
859#ifndef NO_RTCM3_MAIN
860void RTCM3Error(const char *fmt, ...)
861{
862 va_list v;
863 va_start(v, fmt);
864 vfprintf(stderr, fmt, v);
865 va_end(v);
866}
867#endif
868
869void RTCM3Text(const char *fmt, ...)
870{
871 va_list v;
872 va_start(v, fmt);
873 vprintf(fmt, v);
874 va_end(v);
875}
876
877static int HandleRunBy(char *buffer, int buffersize, const char **u,
878int rinex3)
879{
880 const char *user;
881 time_t t;
882 struct tm * t2;
883
884#ifdef NO_RTCM3_MAIN
885 if(revisionstr[0] == '$')
886 {
887 char *a;
888 int i=0;
889 for(a = revisionstr+11; *a && *a != ' '; ++a)
890 revisionstr[i++] = *a;
891 revisionstr[i] = 0;
892 }
893#endif
894
895 user= getenv("USER");
896 if(!user) user = "";
897 t = time(&t);
898 t2 = gmtime(&t);
899 if(u) *u = user;
900 return 1+snprintf(buffer, buffersize,
901 rinex3 ?
902 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
903 "PGM / RUN BY / DATE" :
904 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
905 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
906 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
907}
908
909#ifdef NO_RTCM3_MAIN
910#define NUMSTARTSKIP 1
911#else
912#define NUMSTARTSKIP 3
913#endif
914
915void HandleHeader(struct RTCM3ParserData *Parser)
916{
917#ifdef NO_RTCM3_MAIN
918 int i;
919 if(Parser->rinex3)
920 {
921#define CHECKFLAGSNEW(a, b, c) \
922 { \
923 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
924 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
925 ++Parser->numdatatypes##a; \
926 }
927
928 CHECKFLAGSNEW(GPS, C1, C1C)
929 CHECKFLAGSNEW(GPS, L1C, L1C)
930 CHECKFLAGSNEW(GPS, D1C, D1C)
931 CHECKFLAGSNEW(GPS, S1C, S1C)
932 CHECKFLAGSNEW(GPS, P1, C1P)
933 CHECKFLAGSNEW(GPS, L1P, L1P)
934 CHECKFLAGSNEW(GPS, D1P, D1P)
935 CHECKFLAGSNEW(GPS, S1P, S1P)
936 CHECKFLAGSNEW(GPS, P2, C2P)
937 CHECKFLAGSNEW(GPS, L2P, L2P)
938 CHECKFLAGSNEW(GPS, D2P, D2P)
939 CHECKFLAGSNEW(GPS, S2P, S2P)
940 CHECKFLAGSNEW(GPS, C2, C2X)
941 CHECKFLAGSNEW(GPS, L2C, L2X)
942 CHECKFLAGSNEW(GPS, D2C, D2X)
943 CHECKFLAGSNEW(GPS, S2C, S2X)
944 CHECKFLAGSNEW(GLO, C1, C1C)
945 CHECKFLAGSNEW(GLO, L1C, L1C)
946 CHECKFLAGSNEW(GLO, D1C, D1C)
947 CHECKFLAGSNEW(GLO, S1C, S1C)
948 CHECKFLAGSNEW(GLO, P1, C1P)
949 CHECKFLAGSNEW(GLO, L1P, L1P)
950 CHECKFLAGSNEW(GLO, D1P, D1P)
951 CHECKFLAGSNEW(GLO, S1P, S1P)
952 CHECKFLAGSNEW(GLO, P2, C2P)
953 CHECKFLAGSNEW(GLO, L2P, L2P)
954 CHECKFLAGSNEW(GLO, D2P, D2P)
955 CHECKFLAGSNEW(GLO, S2P, S2P)
956 CHECKFLAGSNEW(GLO, C2, C2C)
957 CHECKFLAGSNEW(GLO, L2C, L2C)
958 CHECKFLAGSNEW(GLO, D2C, D2C)
959 CHECKFLAGSNEW(GLO, S2C, S2C)
960 }
961 else
962 {
963#define CHECKFLAGS(a, b) \
964 { \
965 if(data[RINEXENTRY_##b##DATA]) \
966 { \
967 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
968 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
969 } \
970 else \
971 { \
972 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
973 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
974 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
975 } \
976 }
977
978 int data[RINEXENTRY_NUMBER];
979 for(i = 0; i < RINEXENTRY_NUMBER; ++i) data[i] = 0;
980
981 CHECKFLAGS(C1,C1)
982 CHECKFLAGS(C2,C2)
983 CHECKFLAGS(P1,P1)
984 CHECKFLAGS(P2,P2)
985 CHECKFLAGS(L1C,L1)
986 CHECKFLAGS(L1P,L1)
987 CHECKFLAGS(L2C,L2)
988 CHECKFLAGS(L2P,L2)
989 CHECKFLAGS(D1C,D1)
990 CHECKFLAGS(D1P,D1)
991 CHECKFLAGS(D2C,D2)
992 CHECKFLAGS(D2P,D2)
993 CHECKFLAGS(S1C,S1)
994 CHECKFLAGS(S1P,S1)
995 CHECKFLAGS(S2C,S2)
996 CHECKFLAGS(S2P,S2)
997 }
998#else /* NO_RTCM3_MAIN */
999 struct HeaderData hdata;
1000 char thebuffer[MAXHEADERBUFFERSIZE];
1001 char *buffer = thebuffer;
1002 size_t buffersize = sizeof(thebuffer);
1003 int i;
1004
1005 memset(&hdata, 0, sizeof(hdata));
1006
1007 hdata.data.named.version = buffer;
1008 i = 1+snprintf(buffer, buffersize,
1009 "%9.2f OBSERVATION DATA M (Mixed)"
1010 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
1011 buffer += i; buffersize -= i;
1012
1013 {
1014 const char *str;
1015 hdata.data.named.pgm = buffer;
1016 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
1017 buffer += i; buffersize -= i;
1018 hdata.data.named.observer = buffer;
1019 i = 1+snprintf(buffer, buffersize,
1020 "%-20.20s "
1021 "OBSERVER / AGENCY", str);
1022 buffer += i; buffersize -= i;
1023 }
1024
1025 hdata.data.named.marker =
1026 "RTCM3TORINEX "
1027 "MARKER NAME";
1028
1029 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
1030 "GEODETIC "
1031 "MARKER TYPE";
1032
1033 hdata.data.named.receiver =
1034 " "
1035 "REC # / TYPE / VERS";
1036
1037 hdata.data.named.antenna =
1038 " "
1039 "ANT # / TYPE";
1040
1041 hdata.data.named.position =
1042 " .0000 .0000 .0000 "
1043 "APPROX POSITION XYZ";
1044
1045 hdata.data.named.antennaposition =
1046 " .0000 .0000 .0000 "
1047 "ANTENNA: DELTA H/E/N";
1048
1049 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
1050 " 1 1 "
1051 "WAVELENGTH FACT L1/2";
1052
1053 if(Parser->rinex3)
1054 {
1055#define CHECKFLAGSNEW(a, b, c) \
1056 if(flags & GNSSDF_##b##DATA) \
1057 { \
1058 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1059 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1060 ++Parser->numdatatypes##a; \
1061 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#c); \
1062 tbufferpos += 4; \
1063 }
1064
1065 int flags = Parser->startflags;
1066 char tbuffer[6*RINEXENTRY_NUMBER+1];
1067 int tbufferpos = 0;
1068 for(i = 0; i < Parser->Data.numsats; ++i)
1069 flags |= Parser->Data.dataflags[i];
1070
1071 CHECKFLAGSNEW(GPS, C1, C1C)
1072 CHECKFLAGSNEW(GPS, L1C, L1C)
1073 CHECKFLAGSNEW(GPS, D1C, D1C)
1074 CHECKFLAGSNEW(GPS, S1C, S1C)
1075 CHECKFLAGSNEW(GPS, P1, C1P)
1076 CHECKFLAGSNEW(GPS, L1P, L1P)
1077 CHECKFLAGSNEW(GPS, D1P, D1P)
1078 CHECKFLAGSNEW(GPS, S1P, S1P)
1079
1080 hdata.data.named.typesofobsS = buffer;
1081 i = 1+snprintf(buffer, buffersize,
1082 "S %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1083 buffer += i; buffersize -= i;
1084
1085 CHECKFLAGSNEW(GPS, P2, C2P)
1086 CHECKFLAGSNEW(GPS, L2P, L2P)
1087 CHECKFLAGSNEW(GPS, D2P, D2P)
1088 CHECKFLAGSNEW(GPS, S2P, S2P)
1089 CHECKFLAGSNEW(GPS, C2, C2X)
1090 CHECKFLAGSNEW(GPS, L2C, L2X)
1091 CHECKFLAGSNEW(GPS, D2C, D2X)
1092 CHECKFLAGSNEW(GPS, S2C, S2X)
1093
1094 hdata.data.named.typesofobsG = buffer;
1095 i = 1+snprintf(buffer, buffersize,
1096 "G %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1097 if(Parser->numdatatypesGPS>13)
1098 {
1099 i += snprintf(buffer+i-1, buffersize,
1100 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1101 }
1102 buffer += i; buffersize -= i;
1103
1104 tbufferpos = 0;
1105
1106 CHECKFLAGSNEW(GLO, C1, C1C)
1107 CHECKFLAGSNEW(GLO, L1C, L1C)
1108 CHECKFLAGSNEW(GLO, D1C, D1C)
1109 CHECKFLAGSNEW(GLO, S1C, S1C)
1110 CHECKFLAGSNEW(GLO, P1, C1P)
1111 CHECKFLAGSNEW(GLO, L1P, L1P)
1112 CHECKFLAGSNEW(GLO, D1P, D1P)
1113 CHECKFLAGSNEW(GLO, S1P, S1P)
1114 CHECKFLAGSNEW(GLO, P2, C2P)
1115 CHECKFLAGSNEW(GLO, L2P, L2P)
1116 CHECKFLAGSNEW(GLO, D2P, D2P)
1117 CHECKFLAGSNEW(GLO, S2P, S2P)
1118 CHECKFLAGSNEW(GLO, C2, C2C)
1119 CHECKFLAGSNEW(GLO, L2C, L2C)
1120 CHECKFLAGSNEW(GLO, D2C, D2C)
1121 CHECKFLAGSNEW(GLO, S2C, S2C)
1122
1123 hdata.data.named.typesofobsR = buffer;
1124 i = 1+snprintf(buffer, buffersize,
1125 "R %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGLO, tbuffer);
1126 if(Parser->numdatatypesGLO>13)
1127 {
1128 i += snprintf(buffer+i-1, buffersize,
1129 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1130 }
1131 buffer += i; buffersize -= i;
1132 }
1133 else
1134 {
1135#define CHECKFLAGS(a, b) \
1136 if(flags & GNSSDF_##a##DATA) \
1137 { \
1138 if(data[RINEXENTRY_##b##DATA]) \
1139 { \
1140 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1141 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1142 } \
1143 else \
1144 { \
1145 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1146 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1147 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1148 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
1149 tbufferpos += 6; \
1150 } \
1151 }
1152
1153 int flags = Parser->startflags;
1154 int data[RINEXENTRY_NUMBER];
1155 char tbuffer[6*RINEXENTRY_NUMBER+1];
1156 int tbufferpos = 0;
1157 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
1158 data[i] = 0;
1159 for(i = 0; i < Parser->Data.numsats; ++i)
1160 flags |= Parser->Data.dataflags[i];
1161
1162 CHECKFLAGS(C1,C1)
1163 CHECKFLAGS(C2,C2)
1164 CHECKFLAGS(P1,P1)
1165 CHECKFLAGS(P2,P2)
1166 CHECKFLAGS(L1C,L1)
1167 CHECKFLAGS(L1P,L1)
1168 CHECKFLAGS(L2C,L2)
1169 CHECKFLAGS(L2P,L2)
1170 CHECKFLAGS(D1C,D1)
1171 CHECKFLAGS(D1P,D1)
1172 CHECKFLAGS(D2C,D2)
1173 CHECKFLAGS(D2P,D2)
1174 CHECKFLAGS(S1C,S1)
1175 CHECKFLAGS(S1P,S1)
1176 CHECKFLAGS(S2C,S2)
1177 CHECKFLAGS(S2P,S2)
1178
1179 hdata.data.named.typesofobs = buffer;
1180 i = 1+snprintf(buffer, buffersize,
1181 "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer);
1182 if(Parser->numdatatypesGPS>9)
1183 {
1184 i += snprintf(buffer+i-1, buffersize,
1185 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
1186 }
1187 buffer += i; buffersize -= i;
1188 }
1189
1190 {
1191 struct converttimeinfo cti;
1192 converttime(&cti, Parser->Data.week,
1193 (int)floor(Parser->Data.timeofweek/1000.0));
1194 hdata.data.named.timeoffirstobs = buffer;
1195 i = 1+snprintf(buffer, buffersize,
1196 " %4d %2d %2d %2d %2d %10.7f GPS "
1197 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
1198 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
1199
1200 buffer += i; buffersize -= i;
1201 }
1202
1203 hdata.numheaders = 15;
1204
1205 if(Parser->headerfile)
1206 {
1207 FILE *fh;
1208 if((fh = fopen(Parser->headerfile, "r")))
1209 {
1210 size_t siz;
1211 char *lastblockstart;
1212 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
1213 {
1214 buffer[siz] = '\n';
1215 if(siz == buffersize)
1216 {
1217 RTCM3Error("Header file is too large. Only %d bytes read.",
1218 (int)siz);
1219 }
1220 /* scan the file line by line and enter the entries in the list */
1221 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
1222 /* overwrites entries, except for comments */
1223 lastblockstart = buffer;
1224 for(i = 0; i < (int)siz; ++i)
1225 {
1226 if(buffer[i] == '\n')
1227 { /* we found a line */
1228 char *end;
1229 while(buffer[i+1] == '\r')
1230 ++i; /* skip \r in case there are any */
1231 end = buffer+i;
1232 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
1233 *(end--) = 0;
1234 if(end-lastblockstart < 60+5) /* short line */
1235 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
1236 else
1237 {
1238 int pos;
1239 if(!strcmp("COMMENT", lastblockstart+60))
1240 pos = hdata.numheaders;
1241 else
1242 {
1243 for(pos = 0; pos < hdata.numheaders; ++pos)
1244 {
1245 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
1246 break;
1247 }
1248 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
1249 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
1250 {
1251 RTCM3Error("Overwriting header '%s' is dangerous.\n",
1252 lastblockstart+60);
1253 }
1254 }
1255 if(pos >= MAXHEADERLINES)
1256 {
1257 RTCM3Error("Maximum number of header lines of %d reached.\n",
1258 MAXHEADERLINES);
1259 }
1260 else if(!strcmp("END OF HEADER", lastblockstart+60))
1261 {
1262 RTCM3Error("End of header ignored.\n");
1263 }
1264 else
1265 {
1266 hdata.data.unnamed[pos] = lastblockstart;
1267 if(pos == hdata.numheaders)
1268 ++hdata.numheaders;
1269 }
1270 }
1271 lastblockstart = buffer+i+1;
1272 }
1273 }
1274 }
1275 else
1276 {
1277 RTCM3Error("Could not read data from headerfile '%s'.\n",
1278 Parser->headerfile);
1279 }
1280 fclose(fh);
1281 }
1282 else
1283 {
1284 RTCM3Error("Could not open header datafile '%s'.\n",
1285 Parser->headerfile);
1286 }
1287 }
1288
1289 for(i = 0; i < hdata.numheaders; ++i)
1290 {
1291 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
1292 RTCM3Text("%s\n", hdata.data.unnamed[i]);
1293 }
1294 RTCM3Text(" "
1295 "END OF HEADER\n");
1296#endif
1297}
1298
1299static void ConvLine(FILE *file, const char *fmt, ...)
1300{
1301 char buffer[100], *b;
1302 va_list v;
1303 va_start(v, fmt);
1304 vsnprintf(buffer, sizeof(buffer), fmt, v);
1305 for(b = buffer; *b; ++b)
1306 {
1307 if(*b == 'e') *b = 'D';
1308 }
1309 fprintf(file, "%s", buffer);
1310 va_end(v);
1311}
1312
1313void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
1314{
1315 Parser->Message[Parser->MessageSize++] = byte;
1316 if(Parser->MessageSize >= Parser->NeedBytes)
1317 {
1318 int r;
1319 while((r = RTCM3Parser(Parser)))
1320 {
1321 if(r == 1020 || r == 1019)
1322 {
1323 FILE *file = 0;
1324
1325 if(Parser->rinex3 && !(file = Parser->gpsfile))
1326 {
1327 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
1328 if(n)
1329 {
1330 if(!(Parser->gpsfile = fopen(n, "w")))
1331 {
1332 RTCM3Error("Could not open ephemeris output file.\n");
1333 }
1334 else
1335 {
1336 char buffer[100];
1337 fprintf(Parser->gpsfile,
1338 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
1339 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1340 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1341 }
1342 Parser->gpsephemeris = 0;
1343 Parser->glonassephemeris = 0;
1344 file = Parser->gpsfile;
1345 }
1346 }
1347 else
1348 {
1349 if(r == 1020)
1350 {
1351 if(Parser->glonassephemeris)
1352 {
1353 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
1354 {
1355 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
1356 }
1357 else
1358 {
1359 char buffer[100];
1360 fprintf(Parser->glonassfile,
1361 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
1362 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1363 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1364 }
1365 Parser->glonassephemeris = 0;
1366 }
1367 file = Parser->glonassfile;
1368 }
1369 else if(r == 1019)
1370 {
1371 if(Parser->gpsephemeris)
1372 {
1373 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
1374 {
1375 RTCM3Error("Could not open GPS ephemeris output file.\n");
1376 }
1377 else
1378 {
1379 char buffer[100];
1380 fprintf(Parser->gpsfile,
1381 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
1382 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1383 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1384 }
1385 Parser->gpsephemeris = 0;
1386 }
1387 file = Parser->gpsfile;
1388 }
1389 }
1390 if(file)
1391 {
1392 if(r == 1020)
1393 {
1394 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
1395 int w = e->GPSWeek, tow = e->GPSTOW, i;
1396 struct converttimeinfo cti;
1397
1398 updatetime(&w, &tow, e->tb*1000, 1);
1399 converttime(&cti, w, tow);
1400
1401 i = e->tk-3*60*60; if(i < 0) i += 86400;
1402
1403 if(Parser->rinex3)
1404 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
1405 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
1406 cti.second, -e->tau, e->gamma, (double) i);
1407 else
1408 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
1409 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
1410 (double) cti.second, -e->tau, e->gamma, (double) i);
1411 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
1412 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
1413 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
1414 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
1415 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
1416 e->z_velocity, e->z_acceleration, (double) e->E);
1417 }
1418 else /* if(r == 1019) */
1419 {
1420 struct gpsephemeris *e = &Parser->ephemerisGPS;
1421 double d; /* temporary variable */
1422 unsigned long int i; /* temporary variable */
1423 struct converttimeinfo cti;
1424 converttime(&cti, e->GPSweek, e->TOC);
1425
1426 if(Parser->rinex3)
1427 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
1428 e->satellite, cti.year, cti.month, cti.day, cti.hour,
1429 cti.minute, cti.second, e->clock_bias, e->clock_drift,
1430 e->clock_driftrate);
1431 else
1432 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
1433 e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
1434 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
1435 e->clock_driftrate);
1436 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
1437 e->Crs, e->Delta_n, e->M0);
1438 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
1439 e->e, e->Cus, e->sqrt_A);
1440 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n",
1441 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
1442 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0,
1443 e->Crc, e->omega, e->OMEGADOT);
1444 d = 0;
1445 i = e->flags;
1446 if(i & GPSEPHF_L2CACODE)
1447 d += 2.0;
1448 if(i & GPSEPHF_L2PCODE)
1449 d += 1.0;
1450 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
1451 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
1452 if(e->URAindex <= 6) /* URA index */
1453 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
1454 else
1455 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
1456 /* 15 indicates not to use satellite. We can't handle this special
1457 case, so we create a high "non"-accuracy value. */
1458 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d,
1459 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
1460
1461 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0);
1462 /* TOW */
1463 }
1464 }
1465 }
1466 else
1467 {
1468 int i, j, o;
1469 struct converttimeinfo cti;
1470
1471 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
1472 {
1473 ++Parser->init;
1474
1475 if(Parser->init == NUMSTARTSKIP)
1476 HandleHeader(Parser);
1477 else
1478 {
1479 for(i = 0; i < Parser->Data.numsats; ++i)
1480 Parser->startflags |= Parser->Data.dataflags[i];
1481 continue;
1482 }
1483 }
1484 if(r == 2 && !Parser->validwarning)
1485 {
1486 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
1487 " COMMENT\n");
1488 Parser->validwarning = 1;
1489 }
1490
1491 converttime(&cti, Parser->Data.week,
1492 (int)floor(Parser->Data.timeofweek/1000.0));
1493 if(Parser->rinex3)
1494 {
1495 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n",
1496 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
1497 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
1498 for(i = 0; i < Parser->Data.numsats; ++i)
1499 {
1500 int glo = 0;
1501 if(Parser->Data.satellites[i] <= PRN_GPS_END)
1502 RTCM3Text("G%02d", Parser->Data.satellites[i]);
1503 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
1504 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
1505 {
1506 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
1507 glo = 1;
1508 }
1509 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
1510 && Parser->Data.satellites[i] <= PRN_WAAS_END)
1511 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
1512 else
1513 RTCM3Text("%3d", Parser->Data.satellites[i]);
1514
1515 if(glo)
1516 {
1517 for(j = 0; j < Parser->numdatatypesGLO; ++j)
1518 {
1519 int df = Parser->dataflagGLO[j];
1520 int pos = Parser->dataposGLO[j];
1521 if((Parser->Data.dataflags[i] & df)
1522 && !isnan(Parser->Data.measdata[i][pos])
1523 && !isinf(Parser->Data.measdata[i][pos]))
1524 {
1525 char lli = ' ';
1526 char snr = ' ';
1527 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1528 {
1529 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1530 lli = '1';
1531 snr = '0'+Parser->Data.snrL1[i];
1532 }
1533 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1534 {
1535 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1536 lli = '1';
1537 snr = '0'+Parser->Data.snrL2[i];
1538 }
1539 RTCM3Text("%14.3f%c%c",
1540 Parser->Data.measdata[i][pos],lli,snr);
1541 }
1542 else
1543 { /* no or illegal data */
1544 RTCM3Text(" ");
1545 }
1546 }
1547 }
1548 else
1549 {
1550 for(j = 0; j < Parser->numdatatypesGPS; ++j)
1551 {
1552 int df = Parser->dataflagGPS[j];
1553 int pos = Parser->dataposGPS[j];
1554 if((Parser->Data.dataflags[i] & df)
1555 && !isnan(Parser->Data.measdata[i][pos])
1556 && !isinf(Parser->Data.measdata[i][pos]))
1557 {
1558 char lli = ' ';
1559 char snr = ' ';
1560 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1561 {
1562 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1563 lli = '1';
1564 snr = '0'+Parser->Data.snrL1[i];
1565 }
1566 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1567 {
1568 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1569 lli = '1';
1570 snr = '0'+Parser->Data.snrL2[i];
1571 }
1572 RTCM3Text("%14.3f%c%c",
1573 Parser->Data.measdata[i][pos],lli,snr);
1574 }
1575 else
1576 { /* no or illegal data */
1577 RTCM3Text(" ");
1578 }
1579 }
1580 }
1581 RTCM3Text("\n");
1582 }
1583 }
1584 else
1585 {
1586 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
1587 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
1588 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
1589 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
1590 {
1591 if(Parser->Data.satellites[i] <= PRN_GPS_END)
1592 RTCM3Text("G%02d", Parser->Data.satellites[i]);
1593 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
1594 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
1595 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
1596 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
1597 && Parser->Data.satellites[i] <= PRN_WAAS_END)
1598 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
1599 else
1600 RTCM3Text("%3d", Parser->Data.satellites[i]);
1601 }
1602 RTCM3Text("\n");
1603 o = 12;
1604 j = Parser->Data.numsats - 12;
1605 while(j > 0)
1606 {
1607 RTCM3Text(" ");
1608 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
1609 {
1610 if(Parser->Data.satellites[i] <= PRN_GPS_END)
1611 RTCM3Text("G%02d", Parser->Data.satellites[i]);
1612 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
1613 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
1614 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
1615 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
1616 && Parser->Data.satellites[i] <= PRN_WAAS_END)
1617 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
1618 else
1619 RTCM3Text("%3d", Parser->Data.satellites[i]);
1620 }
1621 RTCM3Text("\n");
1622 j -= 12;
1623 o += 12;
1624 }
1625 for(i = 0; i < Parser->Data.numsats; ++i)
1626 {
1627 for(j = 0; j < Parser->numdatatypesGPS; ++j)
1628 {
1629 int v = 0;
1630 int df = Parser->dataflag[j];
1631 int pos = Parser->datapos[j];
1632 if((Parser->Data.dataflags[i] & df)
1633 && !isnan(Parser->Data.measdata[i][pos])
1634 && !isinf(Parser->Data.measdata[i][pos]))
1635 {
1636 v = 1;
1637 }
1638 else
1639 {
1640 df = Parser->dataflagGPS[j];
1641 pos = Parser->dataposGPS[j];
1642
1643 if((Parser->Data.dataflags[i] & df)
1644 && !isnan(Parser->Data.measdata[i][pos])
1645 && !isinf(Parser->Data.measdata[i][pos]))
1646 {
1647 v = 1;
1648 }
1649 }
1650
1651 if(!v)
1652 { /* no or illegal data */
1653 RTCM3Text(" ");
1654 }
1655 else
1656 {
1657 char lli = ' ';
1658 char snr = ' ';
1659 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1660 {
1661 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1662 lli = '1';
1663 snr = '0'+Parser->Data.snrL1[i];
1664 }
1665 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1666 {
1667 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1668 lli = '1';
1669 snr = '0'+Parser->Data.snrL2[i];
1670 }
1671 RTCM3Text("%14.3f%c%c",
1672 Parser->Data.measdata[i][pos],lli,snr);
1673 }
1674 if(j%5 == 4 || j == Parser->numdatatypesGPS-1)
1675 RTCM3Text("\n");
1676 }
1677 }
1678 }
1679 }
1680 }
1681 }
1682}
1683
1684#ifndef NO_RTCM3_MAIN
1685static char datestr[] = "$Date: 2010/01/12 12:13:23 $";
1686
1687/* The string, which is send as agent in HTTP request */
1688#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
1689
1690#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
1691
1692static const char encodingTable [64] = {
1693 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1694 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1695 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1696 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1697};
1698
1699/* does not buffer overrun, but breaks directly after an error */
1700/* returns the number of required bytes */
1701static int encode(char *buf, int size, const char *user, const char *pwd)
1702{
1703 unsigned char inbuf[3];
1704 char *out = buf;
1705 int i, sep = 0, fill = 0, bytes = 0;
1706
1707 while(*user || *pwd)
1708 {
1709 i = 0;
1710 while(i < 3 && *user) inbuf[i++] = *(user++);
1711 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
1712 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
1713 while(i < 3) {inbuf[i++] = 0; ++fill; }
1714 if(out-buf < size-1)
1715 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
1716 if(out-buf < size-1)
1717 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
1718 | ((inbuf [1] & 0xF0) >> 4)];
1719 if(out-buf < size-1)
1720 {
1721 if(fill == 2)
1722 *(out++) = '=';
1723 else
1724 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
1725 | ((inbuf [2] & 0xC0) >> 6)];
1726 }
1727 if(out-buf < size-1)
1728 {
1729 if(fill >= 1)
1730 *(out++) = '=';
1731 else
1732 *(out++) = encodingTable[inbuf [2] & 0x3F];
1733 }
1734 bytes += 4;
1735 }
1736 if(out-buf < size)
1737 *out = 0;
1738 return bytes;
1739}
1740
1741static int stop = 0;
1742
1743struct Args
1744{
1745 const char *server;
1746 const char *port;
1747 int mode;
1748 int timeout;
1749 int rinex3;
1750 const char *user;
1751 const char *password;
1752 const char *proxyhost;
1753 const char *proxyport;
1754 const char *nmea;
1755 const char *data;
1756 const char *headerfile;
1757 const char *gpsephemeris;
1758 const char *glonassephemeris;
1759};
1760
1761/* option parsing */
1762#ifdef NO_LONG_OPTS
1763#define LONG_OPT(a)
1764#else
1765#define LONG_OPT(a) a
1766static struct option opts[] = {
1767{ "data", required_argument, 0, 'd'},
1768{ "server", required_argument, 0, 's'},
1769{ "password", required_argument, 0, 'p'},
1770{ "port", required_argument, 0, 'r'},
1771{ "timeout", required_argument, 0, 't'},
1772{ "header", required_argument, 0, 'f'},
1773{ "user", required_argument, 0, 'u'},
1774{ "gpsephemeris", required_argument, 0, 'E'},
1775{ "glonassephemeris", required_argument, 0, 'G'},
1776{ "rinex3", no_argument, 0, '3'},
1777{ "proxyport", required_argument, 0, 'R'},
1778{ "proxyhost", required_argument, 0, 'S'},
1779{ "nmea", required_argument, 0, 'n'},
1780{ "mode", required_argument, 0, 'M'},
1781{ "help", no_argument, 0, 'h'},
1782{0,0,0,0}};
1783#endif
1784#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
1785
1786enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
1787
1788static const char *geturl(const char *url, struct Args *args)
1789{
1790 static char buf[1000];
1791 static char *Buffer = buf;
1792 static char *Bufend = buf+sizeof(buf);
1793
1794 if(strncmp("ntrip:", url, 6))
1795 return "URL must start with 'ntrip:'.";
1796 url += 6; /* skip ntrip: */
1797
1798 if(*url != '@' && *url != '/')
1799 {
1800 /* scan for mountpoint */
1801 args->data = Buffer;
1802 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
1803 *(Buffer++) = *(url++);
1804 if(Buffer == args->data)
1805 return "Mountpoint required.";
1806 else if(Buffer >= Bufend-1)
1807 return "Parsing buffer too short.";
1808 *(Buffer++) = 0;
1809 }
1810
1811 if(*url == '/') /* username and password */
1812 {
1813 ++url;
1814 args->user = Buffer;
1815 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
1816 *(Buffer++) = *(url++);
1817 if(Buffer == args->user)
1818 return "Username cannot be empty.";
1819 else if(Buffer >= Bufend-1)
1820 return "Parsing buffer too short.";
1821 *(Buffer++) = 0;
1822
1823 if(*url == ':') ++url;
1824
1825 args->password = Buffer;
1826 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
1827 *(Buffer++) = *(url++);
1828 if(Buffer == args->password)
1829 return "Password cannot be empty.";
1830 else if(Buffer >= Bufend-1)
1831 return "Parsing buffer too short.";
1832 *(Buffer++) = 0;
1833 }
1834
1835 if(*url == '@') /* server */
1836 {
1837 ++url;
1838 if(*url != '@' && *url != ':')
1839 {
1840 args->server = Buffer;
1841 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
1842 *(Buffer++) = *(url++);
1843 if(Buffer == args->server)
1844 return "Servername cannot be empty.";
1845 else if(Buffer >= Bufend-1)
1846 return "Parsing buffer too short.";
1847 *(Buffer++) = 0;
1848 }
1849
1850 if(*url == ':')
1851 {
1852 ++url;
1853 args->port = Buffer;
1854 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
1855 *(Buffer++) = *(url++);
1856 if(Buffer == args->port)
1857 return "Port cannot be empty.";
1858 else if(Buffer >= Bufend-1)
1859 return "Parsing buffer too short.";
1860 *(Buffer++) = 0;
1861 }
1862
1863 if(*url == '@') /* proxy */
1864 {
1865 ++url;
1866 args->proxyhost = Buffer;
1867 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
1868 *(Buffer++) = *(url++);
1869 if(Buffer == args->proxyhost)
1870 return "Proxy servername cannot be empty.";
1871 else if(Buffer >= Bufend-1)
1872 return "Parsing buffer too short.";
1873 *(Buffer++) = 0;
1874
1875 if(*url == ':')
1876 {
1877 ++url;
1878 args->proxyport = Buffer;
1879 while(*url && *url != ';' && Buffer != Bufend)
1880 *(Buffer++) = *(url++);
1881 if(Buffer == args->proxyport)
1882 return "Proxy port cannot be empty.";
1883 else if(Buffer >= Bufend-1)
1884 return "Parsing buffer too short.";
1885 *(Buffer++) = 0;
1886 }
1887 }
1888 }
1889 if(*url == ';') /* NMEA */
1890 {
1891 args->nmea = ++url;
1892 while(*url)
1893 ++url;
1894 }
1895
1896 return *url ? "Garbage at end of server string." : 0;
1897}
1898
1899static int getargs(int argc, char **argv, struct Args *args)
1900{
1901 int res = 1;
1902 int getoptr;
1903 int help = 0;
1904 char *t;
1905
1906 args->server = "www.euref-ip.net";
1907 args->port = "2101";
1908 args->timeout = 60;
1909 args->user = "";
1910 args->password = "";
1911 args->data = 0;
1912 args->headerfile = 0;
1913 args->gpsephemeris = 0;
1914 args->glonassephemeris = 0;
1915 args->rinex3 = 0;
1916 args->nmea = 0;
1917 args->proxyhost = 0;
1918 args->proxyport = "2101";
1919 args->mode = AUTO;
1920 help = 0;
1921
1922 do
1923 {
1924
1925#ifdef NO_LONG_OPTS
1926 switch((getoptr = getopt(argc, argv, ARGOPT)))
1927#else
1928 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
1929#endif
1930 {
1931 case 's': args->server = optarg; break;
1932 case 'u': args->user = optarg; break;
1933 case 'p': args->password = optarg; break;
1934 case 'd': args->data = optarg; break;
1935 case 'f': args->headerfile = optarg; break;
1936 case 'E': args->gpsephemeris = optarg; break;
1937 case 'G': args->glonassephemeris = optarg; break;
1938 case 'r': args->port = optarg; break;
1939 case '3': args->rinex3 = 1; break;
1940 case 'S': args->proxyhost = optarg; break;
1941 case 'n': args->nmea = optarg; break;
1942 case 'R': args->proxyport = optarg; break;
1943 case 'h': help=1; break;
1944 case 'M':
1945 args->mode = 0;
1946 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
1947 args->mode = NTRIP1;
1948 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
1949 args->mode = HTTP;
1950 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
1951 args->mode = RTSP;
1952 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
1953 args->mode = AUTO;
1954 else args->mode = atoi(optarg);
1955 if((args->mode == 0) || (args->mode >= END))
1956 {
1957 fprintf(stderr, "Mode %s unknown\n", optarg);
1958 res = 0;
1959 }
1960 break;
1961 case 't':
1962 args->timeout = strtoul(optarg, &t, 10);
1963 if((t && *t) || args->timeout < 0)
1964 res = 0;
1965 break;
1966
1967 case 1:
1968 {
1969 const char *err;
1970 if((err = geturl(optarg, args)))
1971 {
1972 RTCM3Error("%s\n\n", err);
1973 res = 0;
1974 }
1975 }
1976 break;
1977 case -1: break;
1978 }
1979 } while(getoptr != -1 || !res);
1980
1981 datestr[0] = datestr[7];
1982 datestr[1] = datestr[8];
1983 datestr[2] = datestr[9];
1984 datestr[3] = datestr[10];
1985 datestr[5] = datestr[12];
1986 datestr[6] = datestr[13];
1987 datestr[8] = datestr[15];
1988 datestr[9] = datestr[16];
1989 datestr[4] = datestr[7] = '-';
1990 datestr[10] = 0;
1991
1992 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
1993 {
1994 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
1995 "Please specify only one navigation file.\n");
1996 res = 0;
1997 }
1998 else if(!res || help)
1999 {
2000 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
2001 "\nUsage: %s -s server -u user ...\n"
2002 " -d " LONG_OPT("--data ") "the requested data set\n"
2003 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
2004 " -s " LONG_OPT("--server ") "the server name or address\n"
2005 " -p " LONG_OPT("--password ") "the login password\n"
2006 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
2007 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
2008 " -u " LONG_OPT("--user ") "the user name\n"
2009 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
2010 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
2011 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
2012 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
2013 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
2014 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
2015 " -M " LONG_OPT("--mode ") "mode for data request\n"
2016 " Valid modes are:\n"
2017 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
2018 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
2019 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
2020 " 4, a, auto automatic detection (default)\n"
2021 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
2022 , revisionstr, datestr, argv[0], argv[0]);
2023 exit(1);
2024 }
2025 return res;
2026}
2027
2028/* let the output complete a block if necessary */
2029static void signalhandler(int sig)
2030{
2031 if(!stop)
2032 {
2033 RTCM3Error("Stop signal number %d received. "
2034 "Trying to terminate gentle.\n", sig);
2035 stop = 1;
2036 alarm(1);
2037 }
2038}
2039
2040#ifndef WINDOWSVERSION
2041static void WaitMicro(int mic)
2042{
2043 struct timeval tv;
2044 tv.tv_sec = mic/1000000;
2045 tv.tv_usec = mic%1000000;
2046#ifdef DEBUG
2047 fprintf(stderr, "Waiting %d micro seconds\n", mic);
2048#endif
2049 select(0, 0, 0, 0, &tv);
2050}
2051#else /* WINDOWSVERSION */
2052void WaitMicro(int mic)
2053{
2054 Sleep(mic/1000);
2055}
2056#endif /* WINDOWSVERSION */
2057
2058#define ALARMTIME (2*60)
2059
2060/* for some reason we had to abort hard (maybe waiting for data */
2061#ifdef __GNUC__
2062static __attribute__ ((noreturn)) void signalhandler_alarm(
2063int sig __attribute__((__unused__)))
2064#else /* __GNUC__ */
2065static void signalhandler_alarm(int sig)
2066#endif /* __GNUC__ */
2067{
2068 RTCM3Error("Programm forcefully terminated.\n");
2069 exit(1);
2070}
2071
2072int main(int argc, char **argv)
2073{
2074 struct Args args;
2075 struct RTCM3ParserData Parser;
2076
2077 setbuf(stdout, 0);
2078 setbuf(stdin, 0);
2079 setbuf(stderr, 0);
2080
2081 {
2082 char *a;
2083 int i=0;
2084 for(a = revisionstr+11; *a && *a != ' '; ++a)
2085 revisionstr[i++] = *a;
2086 revisionstr[i] = 0;
2087 }
2088
2089 signal(SIGINT, signalhandler);
2090 signal(SIGALRM,signalhandler_alarm);
2091 signal(SIGQUIT,signalhandler);
2092 signal(SIGTERM,signalhandler);
2093 signal(SIGPIPE,signalhandler);
2094 memset(&Parser, 0, sizeof(Parser));
2095 {
2096 time_t tim;
2097 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
2098 Parser.GPSWeek = tim/(7*24*60*60);
2099 Parser.GPSTOW = tim%(7*24*60*60);
2100 }
2101
2102 if(getargs(argc, argv, &args))
2103 {
2104 int sockfd, numbytes;
2105 char buf[MAXDATASIZE];
2106 struct sockaddr_in their_addr; /* connector's address information */
2107 struct hostent *he;
2108 struct servent *se;
2109 const char *server, *port, *proxyserver = 0;
2110 char proxyport[6];
2111 char *b;
2112 long i;
2113 struct timeval tv;
2114
2115 alarm(ALARMTIME);
2116
2117 Parser.headerfile = args.headerfile;
2118 Parser.glonassephemeris = args.glonassephemeris;
2119 Parser.gpsephemeris = args.gpsephemeris;
2120 Parser.rinex3 = args.rinex3;
2121
2122 if(args.proxyhost)
2123 {
2124 int p;
2125 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
2126 p = i;
2127 else if(!(se = getservbyname(args.port, 0)))
2128 {
2129 RTCM3Error("Can't resolve port %s.", args.port);
2130 exit(1);
2131 }
2132 else
2133 {
2134 p = ntohs(se->s_port);
2135 }
2136 snprintf(proxyport, sizeof(proxyport), "%d", p);
2137 port = args.proxyport;
2138 proxyserver = args.server;
2139 server = args.proxyhost;
2140 }
2141 else
2142 {
2143 server = args.server;
2144 port = args.port;
2145 }
2146
2147 memset(&their_addr, 0, sizeof(struct sockaddr_in));
2148 if((i = strtol(port, &b, 10)) && (!b || !*b))
2149 their_addr.sin_port = htons(i);
2150 else if(!(se = getservbyname(port, 0)))
2151 {
2152 RTCM3Error("Can't resolve port %s.", port);
2153 exit(1);
2154 }
2155 else
2156 {
2157 their_addr.sin_port = se->s_port;
2158 }
2159 if(!(he=gethostbyname(server)))
2160 {
2161 RTCM3Error("Server name lookup failed for '%s'.\n", server);
2162 exit(1);
2163 }
2164 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2165 {
2166 perror("socket");
2167 exit(1);
2168 }
2169
2170 tv.tv_sec = args.timeout;
2171 tv.tv_usec = 0;
2172 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
2173 {
2174 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
2175 exit(1);
2176 }
2177
2178 their_addr.sin_family = AF_INET;
2179 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
2180
2181 if(args.data && args.mode == RTSP)
2182 {
2183 struct sockaddr_in local;
2184 int sockudp, localport;
2185 int cseq = 1;
2186 socklen_t len;
2187
2188 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2189 {
2190 perror("socket");
2191 exit(1);
2192 }
2193 /* fill structure with local address information for UDP */
2194 memset(&local, 0, sizeof(local));
2195 local.sin_family = AF_INET;
2196 local.sin_port = htons(0);
2197 local.sin_addr.s_addr = htonl(INADDR_ANY);
2198 len = sizeof(local);
2199 /* bind() in order to get a random RTP client_port */
2200 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
2201 {
2202 perror("bind");
2203 exit(1);
2204 }
2205 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
2206 {
2207 localport = ntohs(local.sin_port);
2208 }
2209 else
2210 {
2211 perror("local access failed");
2212 exit(1);
2213 }
2214 if(connect(sockfd, (struct sockaddr *)&their_addr,
2215 sizeof(struct sockaddr)) == -1)
2216 {
2217 perror("connect");
2218 exit(1);
2219 }
2220 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
2221 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
2222 "CSeq: %d\r\n"
2223 "Ntrip-Version: Ntrip/2.0\r\n"
2224 "Ntrip-Component: Ntripclient\r\n"
2225 "User-Agent: %s/%s\r\n"
2226 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
2227 "Authorization: Basic ",
2228 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2229 args.data, cseq++, AGENTSTRING, revisionstr, localport);
2230 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
2231 {
2232 RTCM3Error("Requested data too long\n");
2233 exit(1);
2234 }
2235 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
2236 if(i > MAXDATASIZE-4)
2237 {
2238 RTCM3Error("Username and/or password too long\n");
2239 exit(1);
2240 }
2241 buf[i++] = '\r';
2242 buf[i++] = '\n';
2243 buf[i++] = '\r';
2244 buf[i++] = '\n';
2245 if(args.nmea)
2246 {
2247 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
2248 if(j >= 0 && j < MAXDATASIZE-i)
2249 i += j;
2250 else
2251 {
2252 RTCM3Error("NMEA string too long\n");
2253 exit(1);
2254 }
2255 }
2256 if(send(sockfd, buf, (size_t)i, 0) != i)
2257 {
2258 perror("send");
2259 exit(1);
2260 }
2261 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2262 {
2263 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
2264 {
2265 int serverport = 0, session = 0;
2266 const char *portcheck = "server_port=";
2267 const char *sessioncheck = "session: ";
2268 int l = strlen(portcheck)-1;
2269 int j=0;
2270 for(i = 0; j != l && i < numbytes-l; ++i)
2271 {
2272 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
2273 ;
2274 }
2275 if(i == numbytes-l)
2276 {
2277 RTCM3Error("No server port number found\n");
2278 exit(1);
2279 }
2280 else
2281 {
2282 i+=l;
2283 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
2284 serverport = serverport * 10 + buf[i++]-'0';
2285 if(buf[i] != '\r' && buf[i] != ';')
2286 {
2287 RTCM3Error("Could not extract server port\n");
2288 exit(1);
2289 }
2290 }
2291 l = strlen(sessioncheck)-1;
2292 j=0;
2293 for(i = 0; j != l && i < numbytes-l; ++i)
2294 {
2295 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
2296 ;
2297 }
2298 if(i == numbytes-l)
2299 {
2300 RTCM3Error("No session number found\n");
2301 exit(1);
2302 }
2303 else
2304 {
2305 i+=l;
2306 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
2307 session = session * 10 + buf[i++]-'0';
2308 if(buf[i] != '\r')
2309 {
2310 RTCM3Error("Could not extract session number\n");
2311 exit(1);
2312 }
2313 }
2314
2315 i = snprintf(buf, MAXDATASIZE,
2316 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
2317 "CSeq: %d\r\n"
2318 "Session: %d\r\n"
2319 "\r\n",
2320 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2321 args.data, cseq++, session);
2322
2323 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
2324 {
2325 RTCM3Error("Requested data too long\n");
2326 exit(1);
2327 }
2328 if(send(sockfd, buf, (size_t)i, 0) != i)
2329 {
2330 perror("send");
2331 exit(1);
2332 }
2333 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2334 {
2335 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
2336 {
2337 struct sockaddr_in addrRTP;
2338 /* fill structure with caster address information for UDP */
2339 memset(&addrRTP, 0, sizeof(addrRTP));
2340 addrRTP.sin_family = AF_INET;
2341 addrRTP.sin_port = htons(serverport);
2342 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
2343 len = sizeof(addrRTP);
2344 int ts = 0;
2345 int sn = 0;
2346 int ssrc = 0;
2347 int init = 0;
2348 int u, v, w;
2349 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
2350 (struct sockaddr*) &addrRTP, &len)) > 0)
2351 {
2352 alarm(ALARMTIME);
2353 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
2354 {
2355 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
2356 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
2357 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
2358 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
2359 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
2360
2361 if(init)
2362 {
2363 int z;
2364 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
2365 if(ssrc != w || ts > v)
2366 {
2367 RTCM3Error("Illegal UDP data received.\n");
2368 exit(1);
2369 }
2370 if(u > sn) /* don't show out-of-order packets */
2371 for(z = 12; z < i && !stop; ++z)
2372 HandleByte(&Parser, (unsigned int) buf[z]);
2373 }
2374 sn = u; ts = v; ssrc = w; init = 1;
2375 }
2376 else
2377 {
2378 RTCM3Error("Illegal UDP header.\n");
2379 exit(1);
2380 }
2381 }
2382 }
2383 i = snprintf(buf, MAXDATASIZE,
2384 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
2385 "CSeq: %d\r\n"
2386 "Session: %d\r\n"
2387 "\r\n",
2388 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2389 args.data, cseq++, session);
2390
2391 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
2392 {
2393 RTCM3Error("Requested data too long\n");
2394 exit(1);
2395 }
2396 if(send(sockfd, buf, (size_t)i, 0) != i)
2397 {
2398 perror("send");
2399 exit(1);
2400 }
2401 }
2402 else
2403 {
2404 RTCM3Error("Could not start data stream.\n");
2405 exit(1);
2406 }
2407 }
2408 else
2409 {
2410 RTCM3Error("Could not setup initial control connection.\n");
2411 exit(1);
2412 }
2413 }
2414 else
2415 {
2416 perror("recv");
2417 exit(1);
2418 }
2419 }
2420 else
2421 {
2422 if(connect(sockfd, (struct sockaddr *)&their_addr,
2423 sizeof(struct sockaddr)) == -1)
2424 {
2425 perror("connect");
2426 exit(1);
2427 }
2428 if(!args.data)
2429 {
2430 i = snprintf(buf, MAXDATASIZE,
2431 "GET %s%s%s%s/ HTTP/1.0\r\n"
2432 "Host: %s\r\n%s"
2433 "User-Agent: %s/%s\r\n"
2434 "Connection: close\r\n"
2435 "\r\n"
2436 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
2437 proxyserver ? ":" : "", proxyserver ? proxyport : "",
2438 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
2439 AGENTSTRING, revisionstr);
2440 }
2441 else
2442 {
2443 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
2444 "GET %s%s%s%s/%s HTTP/1.0\r\n"
2445 "Host: %s\r\n%s"
2446 "User-Agent: %s/%s\r\n"
2447 "Connection: close\r\n"
2448 "Authorization: Basic "
2449 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
2450 proxyserver ? ":" : "", proxyserver ? proxyport : "",
2451 args.data, args.server,
2452 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
2453 AGENTSTRING, revisionstr);
2454 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
2455 {
2456 RTCM3Error("Requested data too long\n");
2457 exit(1);
2458 }
2459 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
2460 if(i > MAXDATASIZE-4)
2461 {
2462 RTCM3Error("Username and/or password too long\n");
2463 exit(1);
2464 }
2465 buf[i++] = '\r';
2466 buf[i++] = '\n';
2467 buf[i++] = '\r';
2468 buf[i++] = '\n';
2469 if(args.nmea)
2470 {
2471 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
2472 if(j >= 0 && j < MAXDATASIZE-i)
2473 i += j;
2474 else
2475 {
2476 RTCM3Error("NMEA string too long\n");
2477 exit(1);
2478 }
2479 }
2480 }
2481 if(send(sockfd, buf, (size_t)i, 0) != i)
2482 {
2483 perror("send");
2484 exit(1);
2485 }
2486 if(args.data)
2487 {
2488 int k = 0;
2489 int chunkymode = 0;
2490 int starttime = time(0);
2491 int lastout = starttime;
2492 int totalbytes = 0;
2493 int chunksize = 0;
2494
2495 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2496 {
2497 if(numbytes > 0)
2498 alarm(ALARMTIME);
2499 else
2500 {
2501 WaitMicro(100);
2502 continue;
2503 }
2504 if(!k)
2505 {
2506 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
2507 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
2508 {
2509 const char *datacheck = "Content-Type: gnss/data\r\n";
2510 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
2511 int l = strlen(datacheck)-1;
2512 int j=0;
2513 for(i = 0; j != l && i < numbytes-l; ++i)
2514 {
2515 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
2516 ;
2517 }
2518 if(i == numbytes-l)
2519 {
2520 RTCM3Error("No 'Content-Type: gnss/data' found\n");
2521 exit(1);
2522 }
2523 l = strlen(chunkycheck)-1;
2524 j=0;
2525 for(i = 0; j != l && i < numbytes-l; ++i)
2526 {
2527 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
2528 ;
2529 }
2530 if(i < numbytes-l)
2531 chunkymode = 1;
2532 }
2533 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
2534 {
2535 RTCM3Error("Could not get the requested data: ");
2536 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
2537 {
2538 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
2539 }
2540 RTCM3Error("\n");
2541 exit(1);
2542 }
2543 else if(args.mode != NTRIP1)
2544 {
2545 if(args.mode != AUTO)
2546 {
2547 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
2548 args.mode == AUTO ? ", falling back to NTRIP1" : "");
2549 }
2550 if(args.mode == HTTP)
2551 exit(1);
2552 }
2553 ++k;
2554 }
2555 else
2556 {
2557 if(chunkymode)
2558 {
2559 int stop = 0;
2560 int pos = 0;
2561 while(!stop && pos < numbytes)
2562 {
2563 switch(chunkymode)
2564 {
2565 case 1: /* reading number starts */
2566 chunksize = 0;
2567 ++chunkymode; /* no break */
2568 case 2: /* during reading number */
2569 i = buf[pos++];
2570 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
2571 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
2572 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
2573 else if(i == '\r') ++chunkymode;
2574 else if(i == ';') chunkymode = 5;
2575 else stop = 1;
2576 break;
2577 case 3: /* scanning for return */
2578 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
2579 else stop = 1;
2580 break;
2581 case 4: /* output data */
2582 i = numbytes-pos;
2583 if(i > chunksize) i = chunksize;
2584 {
2585 int z;
2586 for(z = 0; z < i && !stop; ++z)
2587 HandleByte(&Parser, (unsigned int) buf[pos+z]);
2588 }
2589 totalbytes += i;
2590 chunksize -= i;
2591 pos += i;
2592 if(!chunksize)
2593 chunkymode = 1;
2594 break;
2595 case 5:
2596 if(i == '\r') chunkymode = 3;
2597 break;
2598 }
2599 }
2600 if(stop)
2601 {
2602 RTCM3Error("Error in chunky transfer encoding\n");
2603 break;
2604 }
2605 }
2606 else
2607 {
2608 totalbytes += numbytes;
2609 {
2610 int z;
2611 for(z = 0; z < numbytes && !stop; ++z)
2612 HandleByte(&Parser, (unsigned int) buf[z]);
2613 }
2614 }
2615 if(totalbytes < 0) /* overflow */
2616 {
2617 totalbytes = 0;
2618 starttime = time(0);
2619 lastout = starttime;
2620 }
2621 }
2622 }
2623 }
2624 else
2625 {
2626 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
2627 {
2628 alarm(ALARMTIME);
2629 fwrite(buf, (size_t)numbytes, 1, stdout);
2630 }
2631 }
2632 close(sockfd);
2633 }
2634 }
2635 return 0;
2636}
2637#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.