source: ntrip/trunk/rtcm3torinex/rtcm3torinex.c@ 1265

Last change on this file since 1265 was 1265, checked in by stoecker, 15 years ago

minor fix for BNC

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