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

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

* empty log message *

File size: 78.7 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.27 2009/11/04 16:40:16 zdenek 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.27 $";
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
839struct converttimeinfo {
840 int second; /* seconds of GPS time [0..59] */
841 int minute; /* minutes of GPS time [0..59] */
842 int hour; /* hour of GPS time [0..24] */
843 int day; /* day of GPS time [1..28..30(31)*/
844 int month; /* month of GPS time [1..12]*/
845 int year; /* year of GPS time [1980..] */
846};
847
848void converttime(struct converttimeinfo *c, int week, int tow)
849{
850 int i, k, doy, j; /* temporary variables */
851 j = week*(7*24*60*60) + tow + 5*24*60*60;
852 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
853 j -= k;
854 c->year = i;
855 doy = 1+ (j / (24*60*60));
856 j %= (24*60*60);
857 c->hour = j / (60*60);
858 j %= (60*60);
859 c->minute = j / 60;
860 c->second = j % 60;
861 j = 0;
862 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
863 j += k;
864 c->month = i;
865 c->day = doy - j;
866}
867
868#ifndef NO_RTCM3_MAIN
869void RTCM3Error(const char *fmt, ...)
870{
871 va_list v;
872 va_start(v, fmt);
873 vfprintf(stderr, fmt, v);
874 va_end(v);
875}
876#endif
877
878void RTCM3Text(const char *fmt, ...)
879{
880 va_list v;
881 va_start(v, fmt);
882 vprintf(fmt, v);
883 va_end(v);
884}
885
886static int HandleRunBy(char *buffer, int buffersize, const char **u,
887int rinex3)
888{
889 const char *user;
890 time_t t;
891 struct tm * t2;
892
893#ifdef NO_RTCM3_MAIN
894 if(revisionstr[0] == '$')
895 {
896 char *a;
897 int i=0;
898 for(a = revisionstr+11; *a && *a != ' '; ++a)
899 revisionstr[i++] = *a;
900 revisionstr[i] = 0;
901 }
902#endif
903
904 user= getenv("USER");
905 if(!user) user = "";
906 t = time(&t);
907 t2 = gmtime(&t);
908 if(u) *u = user;
909 return 1+snprintf(buffer, buffersize,
910 rinex3 ?
911 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
912 "PGM / RUN BY / DATE" :
913 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
914 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
915 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
916}
917
918#ifdef NO_RTCM3_MAIN
919#define NUMSTARTSKIP 1
920#else
921#define NUMSTARTSKIP 3
922#endif
923
924void HandleHeader(struct RTCM3ParserData *Parser)
925{
926#ifdef NO_RTCM3_MAIN
927 int i;
928 if(Parser->rinex3)
929 {
930#define CHECKFLAGSNEW(a, b, c) \
931 { \
932 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
933 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
934 ++Parser->numdatatypes##a; \
935 }
936
937 CHECKFLAGSNEW(GPS, C1, C1C)
938 CHECKFLAGSNEW(GPS, L1C, L1C)
939 CHECKFLAGSNEW(GPS, D1C, D1C)
940 CHECKFLAGSNEW(GPS, S1C, S1C)
941 CHECKFLAGSNEW(GPS, P1, C1P)
942 CHECKFLAGSNEW(GPS, L1P, L1P)
943 CHECKFLAGSNEW(GPS, D1P, D1P)
944 CHECKFLAGSNEW(GPS, S1P, S1P)
945 CHECKFLAGSNEW(GPS, P2, C2P)
946 CHECKFLAGSNEW(GPS, L2P, L2P)
947 CHECKFLAGSNEW(GPS, D2P, D2P)
948 CHECKFLAGSNEW(GPS, S2P, S2P)
949 CHECKFLAGSNEW(GPS, C2, C2X)
950 CHECKFLAGSNEW(GPS, L2C, L2X)
951 CHECKFLAGSNEW(GPS, D2C, D2X)
952 CHECKFLAGSNEW(GPS, S2C, S2X)
953 CHECKFLAGSNEW(GLO, C1, C1C)
954 CHECKFLAGSNEW(GLO, L1C, L1C)
955 CHECKFLAGSNEW(GLO, D1C, D1C)
956 CHECKFLAGSNEW(GLO, S1C, S1C)
957 CHECKFLAGSNEW(GLO, P1, C1P)
958 CHECKFLAGSNEW(GLO, L1P, L1P)
959 CHECKFLAGSNEW(GLO, D1P, D1P)
960 CHECKFLAGSNEW(GLO, S1P, S1P)
961 CHECKFLAGSNEW(GLO, P2, C2P)
962 CHECKFLAGSNEW(GLO, L2P, L2P)
963 CHECKFLAGSNEW(GLO, D2P, D2P)
964 CHECKFLAGSNEW(GLO, S2P, S2P)
965 CHECKFLAGSNEW(GLO, C2, C2C)
966 CHECKFLAGSNEW(GLO, L2C, L2C)
967 CHECKFLAGSNEW(GLO, D2C, D2C)
968 CHECKFLAGSNEW(GLO, S2C, S2C)
969 }
970 else
971 {
972#define CHECKFLAGS(a, b) \
973 { \
974 if(data[RINEXENTRY_##b##DATA]) \
975 { \
976 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
977 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
978 } \
979 else \
980 { \
981 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
982 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
983 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
984 } \
985 }
986
987 int data[RINEXENTRY_NUMBER];
988 for(i = 0; i < RINEXENTRY_NUMBER; ++i) data[i] = 0;
989
990 CHECKFLAGS(C1,C1)
991 CHECKFLAGS(C2,C2)
992 CHECKFLAGS(P1,P1)
993 CHECKFLAGS(P2,P2)
994 CHECKFLAGS(L1C,L1)
995 CHECKFLAGS(L1P,L1)
996 CHECKFLAGS(L2C,L2)
997 CHECKFLAGS(L2P,L2)
998 CHECKFLAGS(D1C,D1)
999 CHECKFLAGS(D1P,D1)
1000 CHECKFLAGS(D2C,D2)
1001 CHECKFLAGS(D2P,D2)
1002 CHECKFLAGS(S1C,S1)
1003 CHECKFLAGS(S1P,S1)
1004 CHECKFLAGS(S2C,S2)
1005 CHECKFLAGS(S2P,S2)
1006 }
1007#else /* NO_RTCM3_MAIN */
1008 struct HeaderData hdata;
1009 char thebuffer[MAXHEADERBUFFERSIZE];
1010 char *buffer = thebuffer;
1011 size_t buffersize = sizeof(thebuffer);
1012 int i;
1013
1014 memset(&hdata, 0, sizeof(hdata));
1015
1016 hdata.data.named.version = buffer;
1017 i = 1+snprintf(buffer, buffersize,
1018 "%9.2f OBSERVATION DATA M (Mixed)"
1019 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
1020 buffer += i; buffersize -= i;
1021
1022 {
1023 const char *str;
1024 hdata.data.named.pgm = buffer;
1025 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
1026 buffer += i; buffersize -= i;
1027 hdata.data.named.observer = buffer;
1028 i = 1+snprintf(buffer, buffersize,
1029 "%-20.20s "
1030 "OBSERVER / AGENCY", str);
1031 buffer += i; buffersize -= i;
1032 }
1033
1034 hdata.data.named.marker =
1035 "RTCM3TORINEX "
1036 "MARKER NAME";
1037
1038 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
1039 "GEODETIC "
1040 "MARKER TYPE";
1041
1042 hdata.data.named.receiver =
1043 " "
1044 "REC # / TYPE / VERS";
1045
1046 hdata.data.named.antenna =
1047 " "
1048 "ANT # / TYPE";
1049
1050 hdata.data.named.position =
1051 " .0000 .0000 .0000 "
1052 "APPROX POSITION XYZ";
1053
1054 hdata.data.named.antennaposition =
1055 " .0000 .0000 .0000 "
1056 "ANTENNA: DELTA H/E/N";
1057
1058 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
1059 " 1 1 "
1060 "WAVELENGTH FACT L1/2";
1061
1062 if(Parser->rinex3)
1063 {
1064#define CHECKFLAGSNEW(a, b, c) \
1065 if(flags & GNSSDF_##b##DATA) \
1066 { \
1067 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1068 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1069 ++Parser->numdatatypes##a; \
1070 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#c); \
1071 tbufferpos += 4; \
1072 }
1073
1074 int flags = Parser->startflags;
1075 char tbuffer[6*RINEXENTRY_NUMBER+1];
1076 int tbufferpos = 0;
1077 for(i = 0; i < Parser->Data.numsats; ++i)
1078 flags |= Parser->Data.dataflags[i];
1079
1080 CHECKFLAGSNEW(GPS, C1, C1C)
1081 CHECKFLAGSNEW(GPS, L1C, L1C)
1082 CHECKFLAGSNEW(GPS, D1C, D1C)
1083 CHECKFLAGSNEW(GPS, S1C, S1C)
1084 CHECKFLAGSNEW(GPS, P1, C1P)
1085 CHECKFLAGSNEW(GPS, L1P, L1P)
1086 CHECKFLAGSNEW(GPS, D1P, D1P)
1087 CHECKFLAGSNEW(GPS, S1P, S1P)
1088
1089 hdata.data.named.typesofobsS = buffer;
1090 i = 1+snprintf(buffer, buffersize,
1091 "S %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1092 buffer += i; buffersize -= i;
1093
1094 CHECKFLAGSNEW(GPS, P2, C2P)
1095 CHECKFLAGSNEW(GPS, L2P, L2P)
1096 CHECKFLAGSNEW(GPS, D2P, D2P)
1097 CHECKFLAGSNEW(GPS, S2P, S2P)
1098 CHECKFLAGSNEW(GPS, C2, C2X)
1099 CHECKFLAGSNEW(GPS, L2C, L2X)
1100 CHECKFLAGSNEW(GPS, D2C, D2X)
1101 CHECKFLAGSNEW(GPS, S2C, S2X)
1102
1103 hdata.data.named.typesofobsG = buffer;
1104 i = 1+snprintf(buffer, buffersize,
1105 "G %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1106 if(Parser->numdatatypesGPS>13)
1107 {
1108 i += snprintf(buffer+i-1, buffersize,
1109 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1110 }
1111 buffer += i; buffersize -= i;
1112
1113 tbufferpos = 0;
1114
1115 CHECKFLAGSNEW(GLO, C1, C1C)
1116 CHECKFLAGSNEW(GLO, L1C, L1C)
1117 CHECKFLAGSNEW(GLO, D1C, D1C)
1118 CHECKFLAGSNEW(GLO, S1C, S1C)
1119 CHECKFLAGSNEW(GLO, P1, C1P)
1120 CHECKFLAGSNEW(GLO, L1P, L1P)
1121 CHECKFLAGSNEW(GLO, D1P, D1P)
1122 CHECKFLAGSNEW(GLO, S1P, S1P)
1123 CHECKFLAGSNEW(GLO, P2, C2P)
1124 CHECKFLAGSNEW(GLO, L2P, L2P)
1125 CHECKFLAGSNEW(GLO, D2P, D2P)
1126 CHECKFLAGSNEW(GLO, S2P, S2P)
1127 CHECKFLAGSNEW(GLO, C2, C2C)
1128 CHECKFLAGSNEW(GLO, L2C, L2C)
1129 CHECKFLAGSNEW(GLO, D2C, D2C)
1130 CHECKFLAGSNEW(GLO, S2C, S2C)
1131
1132 hdata.data.named.typesofobsR = buffer;
1133 i = 1+snprintf(buffer, buffersize,
1134 "R %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGLO, tbuffer);
1135 if(Parser->numdatatypesGLO>13)
1136 {
1137 i += snprintf(buffer+i-1, buffersize,
1138 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1139 }
1140 buffer += i; buffersize -= i;
1141 }
1142 else
1143 {
1144#define CHECKFLAGS(a, b) \
1145 if(flags & GNSSDF_##a##DATA) \
1146 { \
1147 if(data[RINEXENTRY_##b##DATA]) \
1148 { \
1149 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1150 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1151 } \
1152 else \
1153 { \
1154 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1155 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1156 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1157 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
1158 tbufferpos += 6; \
1159 } \
1160 }
1161
1162 int flags = Parser->startflags;
1163 int data[RINEXENTRY_NUMBER];
1164 char tbuffer[6*RINEXENTRY_NUMBER+1];
1165 int tbufferpos = 0;
1166 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
1167 data[i] = 0;
1168 for(i = 0; i < Parser->Data.numsats; ++i)
1169 flags |= Parser->Data.dataflags[i];
1170
1171 CHECKFLAGS(C1,C1)
1172 CHECKFLAGS(C2,C2)
1173 CHECKFLAGS(P1,P1)
1174 CHECKFLAGS(P2,P2)
1175 CHECKFLAGS(L1C,L1)
1176 CHECKFLAGS(L1P,L1)
1177 CHECKFLAGS(L2C,L2)
1178 CHECKFLAGS(L2P,L2)
1179 CHECKFLAGS(D1C,D1)
1180 CHECKFLAGS(D1P,D1)
1181 CHECKFLAGS(D2C,D2)
1182 CHECKFLAGS(D2P,D2)
1183 CHECKFLAGS(S1C,S1)
1184 CHECKFLAGS(S1P,S1)
1185 CHECKFLAGS(S2C,S2)
1186 CHECKFLAGS(S2P,S2)
1187
1188 hdata.data.named.typesofobs = buffer;
1189 i = 1+snprintf(buffer, buffersize,
1190 "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer);
1191 if(Parser->numdatatypesGPS>9)
1192 {
1193 i += snprintf(buffer+i-1, buffersize,
1194 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
1195 }
1196 buffer += i; buffersize -= i;
1197 }
1198
1199 {
1200 struct converttimeinfo cti;
1201 converttime(&cti, Parser->Data.week,
1202 (int)floor(Parser->Data.timeofweek/1000.0));
1203 hdata.data.named.timeoffirstobs = buffer;
1204 i = 1+snprintf(buffer, buffersize,
1205 " %4d %2d %2d %2d %2d %10.7f GPS "
1206 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
1207 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
1208
1209 buffer += i; buffersize -= i;
1210 }
1211
1212 hdata.numheaders = 15;
1213
1214 if(Parser->headerfile)
1215 {
1216 FILE *fh;
1217 if((fh = fopen(Parser->headerfile, "r")))
1218 {
1219 size_t siz;
1220 char *lastblockstart;
1221 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
1222 {
1223 buffer[siz] = '\n';
1224 if(siz == buffersize)
1225 {
1226 RTCM3Error("Header file is too large. Only %d bytes read.",
1227 (int)siz);
1228 }
1229 /* scan the file line by line and enter the entries in the list */
1230 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
1231 /* overwrites entries, except for comments */
1232 lastblockstart = buffer;
1233 for(i = 0; i < (int)siz; ++i)
1234 {
1235 if(buffer[i] == '\n')
1236 { /* we found a line */
1237 char *end;
1238 while(buffer[i+1] == '\r')
1239 ++i; /* skip \r in case there are any */
1240 end = buffer+i;
1241 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
1242 *(end--) = 0;
1243 if(end-lastblockstart < 60+5) /* short line */
1244 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
1245 else
1246 {
1247 int pos;
1248 if(!strcmp("COMMENT", lastblockstart+60))
1249 pos = hdata.numheaders;
1250 else
1251 {
1252 for(pos = 0; pos < hdata.numheaders; ++pos)
1253 {
1254 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
1255 break;
1256 }
1257 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
1258 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
1259 {
1260 RTCM3Error("Overwriting header '%s' is dangerous.\n",
1261 lastblockstart+60);
1262 }
1263 }
1264 if(pos >= MAXHEADERLINES)
1265 {
1266 RTCM3Error("Maximum number of header lines of %d reached.\n",
1267 MAXHEADERLINES);
1268 }
1269 else if(!strcmp("END OF HEADER", lastblockstart+60))
1270 {
1271 RTCM3Error("End of header ignored.\n");
1272 }
1273 else
1274 {
1275 hdata.data.unnamed[pos] = lastblockstart;
1276 if(pos == hdata.numheaders)
1277 ++hdata.numheaders;
1278 }
1279 }
1280 lastblockstart = buffer+i+1;
1281 }
1282 }
1283 }
1284 else
1285 {
1286 RTCM3Error("Could not read data from headerfile '%s'.\n",
1287 Parser->headerfile);
1288 }
1289 fclose(fh);
1290 }
1291 else
1292 {
1293 RTCM3Error("Could not open header datafile '%s'.\n",
1294 Parser->headerfile);
1295 }
1296 }
1297
1298 for(i = 0; i < hdata.numheaders; ++i)
1299 {
1300 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
1301 RTCM3Text("%s\n", hdata.data.unnamed[i]);
1302 }
1303 RTCM3Text(" "
1304 "END OF HEADER\n");
1305#endif
1306}
1307
1308static void ConvLine(FILE *file, const char *fmt, ...)
1309{
1310 char buffer[100], *b;
1311 va_list v;
1312 va_start(v, fmt);
1313 vsnprintf(buffer, sizeof(buffer), fmt, v);
1314 for(b = buffer; *b; ++b)
1315 {
1316 if(*b == 'e') *b = 'D';
1317 }
1318 fprintf(file, "%s", buffer);
1319 va_end(v);
1320}
1321
1322void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
1323{
1324 Parser->Message[Parser->MessageSize++] = byte;
1325 if(Parser->MessageSize >= Parser->NeedBytes)
1326 {
1327 int r;
1328 while((r = RTCM3Parser(Parser)))
1329 {
1330 if(r == 1020 || r == 1019)
1331 {
1332 FILE *file = 0;
1333
1334 if(Parser->rinex3 && !(file = Parser->gpsfile))
1335 {
1336 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
1337 if(n)
1338 {
1339 if(!(Parser->gpsfile = fopen(n, "w")))
1340 {
1341 RTCM3Error("Could not open ephemeris output file.\n");
1342 }
1343 else
1344 {
1345 char buffer[100];
1346 fprintf(Parser->gpsfile,
1347 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
1348 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1349 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1350 }
1351 Parser->gpsephemeris = 0;
1352 Parser->glonassephemeris = 0;
1353 file = Parser->gpsfile;
1354 }
1355 }
1356 else
1357 {
1358 if(r == 1020)
1359 {
1360 if(Parser->glonassephemeris)
1361 {
1362 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
1363 {
1364 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
1365 }
1366 else
1367 {
1368 char buffer[100];
1369 fprintf(Parser->glonassfile,
1370 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
1371 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1372 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1373 }
1374 Parser->glonassephemeris = 0;
1375 }
1376 file = Parser->glonassfile;
1377 }
1378 else if(r == 1019)
1379 {
1380 if(Parser->gpsephemeris)
1381 {
1382 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
1383 {
1384 RTCM3Error("Could not open GPS ephemeris output file.\n");
1385 }
1386 else
1387 {
1388 char buffer[100];
1389 fprintf(Parser->gpsfile,
1390 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
1391 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1392 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1393 }
1394 Parser->gpsephemeris = 0;
1395 }
1396 file = Parser->gpsfile;
1397 }
1398 }
1399 if(file)
1400 {
1401 if(r == 1020)
1402 {
1403 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
1404 int w = e->GPSWeek, tow = e->GPSTOW, i;
1405 struct converttimeinfo cti;
1406
1407 updatetime(&w, &tow, e->tb*1000, 1);
1408 converttime(&cti, w, tow);
1409
1410 i = e->tk-3*60*60; if(i < 0) i += 86400;
1411
1412 if(Parser->rinex3)
1413 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
1414 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
1415 cti.second, -e->tau, e->gamma, (double) i);
1416 else
1417 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
1418 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
1419 (double) cti.second, -e->tau, e->gamma, (double) i);
1420 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
1421 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
1422 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
1423 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
1424 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
1425 e->z_velocity, e->z_acceleration, (double) e->E);
1426 }
1427 else /* if(r == 1019) */
1428 {
1429 struct gpsephemeris *e = &Parser->ephemerisGPS;
1430 double d; /* temporary variable */
1431 unsigned long int i; /* temporary variable */
1432 struct converttimeinfo cti;
1433 converttime(&cti, e->GPSweek, e->TOC);
1434
1435 if(Parser->rinex3)
1436 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
1437 e->satellite, cti.year, cti.month, cti.day, cti.hour,
1438 cti.minute, cti.second, e->clock_bias, e->clock_drift,
1439 e->clock_driftrate);
1440 else
1441 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
1442 e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
1443 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
1444 e->clock_driftrate);
1445 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
1446 e->Crs, e->Delta_n, e->M0);
1447 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
1448 e->e, e->Cus, e->sqrt_A);
1449 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n",
1450 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
1451 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0,
1452 e->Crc, e->omega, e->OMEGADOT);
1453 d = 0;
1454 i = e->flags;
1455 if(i & GPSEPHF_L2CACODE)
1456 d += 2.0;
1457 if(i & GPSEPHF_L2PCODE)
1458 d += 1.0;
1459 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
1460 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
1461 if(e->URAindex <= 6) /* URA index */
1462 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
1463 else
1464 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
1465 /* 15 indicates not to use satellite. We can't handle this special
1466 case, so we create a high "non"-accuracy value. */
1467 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d,
1468 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
1469
1470 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0);
1471 /* TOW */
1472 }
1473 }
1474 }
1475 else
1476 {
1477 int i, j, o;
1478 struct converttimeinfo cti;
1479
1480 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
1481 {
1482 ++Parser->init;
1483
1484 if(Parser->init == NUMSTARTSKIP)
1485 HandleHeader(Parser);
1486 else
1487 {
1488 for(i = 0; i < Parser->Data.numsats; ++i)
1489 Parser->startflags |= Parser->Data.dataflags[i];
1490 continue;
1491 }
1492 }
1493 if(r == 2 && !Parser->validwarning)
1494 {
1495 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
1496 " COMMENT\n");
1497 Parser->validwarning = 1;
1498 }
1499
1500 converttime(&cti, Parser->Data.week,
1501 (int)floor(Parser->Data.timeofweek/1000.0));
1502 if(Parser->rinex3)
1503 {
1504 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n",
1505 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
1506 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
1507 for(i = 0; i < Parser->Data.numsats; ++i)
1508 {
1509 int glo = 0;
1510 if(Parser->Data.satellites[i] <= PRN_GPS_END)
1511 RTCM3Text("G%02d", Parser->Data.satellites[i]);
1512 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
1513 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
1514 {
1515 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
1516 glo = 1;
1517 }
1518 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
1519 && Parser->Data.satellites[i] <= PRN_WAAS_END)
1520 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
1521 else
1522 RTCM3Text("%3d", Parser->Data.satellites[i]);
1523
1524 if(glo)
1525 {
1526 for(j = 0; j < Parser->numdatatypesGLO; ++j)
1527 {
1528 int df = Parser->dataflagGLO[j];
1529 int pos = Parser->dataposGLO[j];
1530 if((Parser->Data.dataflags[i] & df)
1531 && !isnan(Parser->Data.measdata[i][pos])
1532 && !isinf(Parser->Data.measdata[i][pos]))
1533 {
1534 char lli = ' ';
1535 char snr = ' ';
1536 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1537 {
1538 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1539 lli = '1';
1540 snr = '0'+Parser->Data.snrL1[i];
1541 }
1542 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1543 {
1544 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1545 lli = '1';
1546 snr = '0'+Parser->Data.snrL2[i];
1547 }
1548 RTCM3Text("%14.3f%c%c",
1549 Parser->Data.measdata[i][pos],lli,snr);
1550 }
1551 else
1552 { /* no or illegal data */
1553 RTCM3Text(" ");
1554 }
1555 }
1556 }
1557 else
1558 {
1559 for(j = 0; j < Parser->numdatatypesGPS; ++j)
1560 {
1561 int df = Parser->dataflagGPS[j];
1562 int pos = Parser->dataposGPS[j];
1563 if((Parser->Data.dataflags[i] & df)
1564 && !isnan(Parser->Data.measdata[i][pos])
1565 && !isinf(Parser->Data.measdata[i][pos]))
1566 {
1567 char lli = ' ';
1568 char snr = ' ';
1569 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1570 {
1571 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1572 lli = '1';
1573 snr = '0'+Parser->Data.snrL1[i];
1574 }
1575 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1576 {
1577 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1578 lli = '1';
1579 snr = '0'+Parser->Data.snrL2[i];
1580 }
1581 RTCM3Text("%14.3f%c%c",
1582 Parser->Data.measdata[i][pos],lli,snr);
1583 }
1584 else
1585 { /* no or illegal data */
1586 RTCM3Text(" ");
1587 }
1588 }
1589 }
1590 RTCM3Text("\n");
1591 }
1592 }
1593 else
1594 {
1595 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
1596 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
1597 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
1598 for(i = 0; i < 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 o = 12;
1613 j = Parser->Data.numsats - 12;
1614 while(j > 0)
1615 {
1616 RTCM3Text(" ");
1617 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
1618 {
1619 if(Parser->Data.satellites[i] <= PRN_GPS_END)
1620 RTCM3Text("G%02d", Parser->Data.satellites[i]);
1621 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
1622 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
1623 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
1624 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
1625 && Parser->Data.satellites[i] <= PRN_WAAS_END)
1626 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
1627 else
1628 RTCM3Text("%3d", Parser->Data.satellites[i]);
1629 }
1630 RTCM3Text("\n");
1631 j -= 12;
1632 o += 12;
1633 }
1634 for(i = 0; i < Parser->Data.numsats; ++i)
1635 {
1636 for(j = 0; j < Parser->numdatatypesGPS; ++j)
1637 {
1638 int v = 0;
1639 int df = Parser->dataflag[j];
1640 int pos = Parser->datapos[j];
1641 if((Parser->Data.dataflags[i] & df)
1642 && !isnan(Parser->Data.measdata[i][pos])
1643 && !isinf(Parser->Data.measdata[i][pos]))
1644 {
1645 v = 1;
1646 }
1647 else
1648 {
1649 df = Parser->dataflagGPS[j];
1650 pos = Parser->dataposGPS[j];
1651
1652 if((Parser->Data.dataflags[i] & df)
1653 && !isnan(Parser->Data.measdata[i][pos])
1654 && !isinf(Parser->Data.measdata[i][pos]))
1655 {
1656 v = 1;
1657 }
1658 }
1659
1660 if(!v)
1661 { /* no or illegal data */
1662 RTCM3Text(" ");
1663 }
1664 else
1665 {
1666 char lli = ' ';
1667 char snr = ' ';
1668 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1669 {
1670 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1671 lli = '1';
1672 snr = '0'+Parser->Data.snrL1[i];
1673 }
1674 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1675 {
1676 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1677 lli = '1';
1678 snr = '0'+Parser->Data.snrL2[i];
1679 }
1680 RTCM3Text("%14.3f%c%c",
1681 Parser->Data.measdata[i][pos],lli,snr);
1682 }
1683 if(j%5 == 4 || j == Parser->numdatatypesGPS-1)
1684 RTCM3Text("\n");
1685 }
1686 }
1687 }
1688 }
1689 }
1690 }
1691}
1692
1693#ifndef NO_RTCM3_MAIN
1694static char datestr[] = "$Date: 2009/11/04 16:40:16 $";
1695
1696/* The string, which is send as agent in HTTP request */
1697#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
1698
1699#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
1700
1701static const char encodingTable [64] = {
1702 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1703 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1704 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1705 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1706};
1707
1708/* does not buffer overrun, but breaks directly after an error */
1709/* returns the number of required bytes */
1710static int encode(char *buf, int size, const char *user, const char *pwd)
1711{
1712 unsigned char inbuf[3];
1713 char *out = buf;
1714 int i, sep = 0, fill = 0, bytes = 0;
1715
1716 while(*user || *pwd)
1717 {
1718 i = 0;
1719 while(i < 3 && *user) inbuf[i++] = *(user++);
1720 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
1721 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
1722 while(i < 3) {inbuf[i++] = 0; ++fill; }
1723 if(out-buf < size-1)
1724 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
1725 if(out-buf < size-1)
1726 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
1727 | ((inbuf [1] & 0xF0) >> 4)];
1728 if(out-buf < size-1)
1729 {
1730 if(fill == 2)
1731 *(out++) = '=';
1732 else
1733 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
1734 | ((inbuf [2] & 0xC0) >> 6)];
1735 }
1736 if(out-buf < size-1)
1737 {
1738 if(fill >= 1)
1739 *(out++) = '=';
1740 else
1741 *(out++) = encodingTable[inbuf [2] & 0x3F];
1742 }
1743 bytes += 4;
1744 }
1745 if(out-buf < size)
1746 *out = 0;
1747 return bytes;
1748}
1749
1750static int stop = 0;
1751
1752struct Args
1753{
1754 const char *server;
1755 const char *port;
1756 int mode;
1757 int timeout;
1758 int rinex3;
1759 const char *user;
1760 const char *password;
1761 const char *proxyhost;
1762 const char *proxyport;
1763 const char *nmea;
1764 const char *data;
1765 const char *headerfile;
1766 const char *gpsephemeris;
1767 const char *glonassephemeris;
1768};
1769
1770/* option parsing */
1771#ifdef NO_LONG_OPTS
1772#define LONG_OPT(a)
1773#else
1774#define LONG_OPT(a) a
1775static struct option opts[] = {
1776{ "data", required_argument, 0, 'd'},
1777{ "server", required_argument, 0, 's'},
1778{ "password", required_argument, 0, 'p'},
1779{ "port", required_argument, 0, 'r'},
1780{ "timeout", required_argument, 0, 't'},
1781{ "header", required_argument, 0, 'f'},
1782{ "user", required_argument, 0, 'u'},
1783{ "gpsephemeris", required_argument, 0, 'E'},
1784{ "glonassephemeris", required_argument, 0, 'G'},
1785{ "rinex3", no_argument, 0, '3'},
1786{ "proxyport", required_argument, 0, 'R'},
1787{ "proxyhost", required_argument, 0, 'S'},
1788{ "nmea", required_argument, 0, 'n'},
1789{ "mode", required_argument, 0, 'M'},
1790{ "help", no_argument, 0, 'h'},
1791{0,0,0,0}};
1792#endif
1793#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
1794
1795enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
1796
1797static const char *geturl(const char *url, struct Args *args)
1798{
1799 static char buf[1000];
1800 static char *Buffer = buf;
1801 static char *Bufend = buf+sizeof(buf);
1802
1803 if(strncmp("ntrip:", url, 6))
1804 return "URL must start with 'ntrip:'.";
1805 url += 6; /* skip ntrip: */
1806
1807 if(*url != '@' && *url != '/')
1808 {
1809 /* scan for mountpoint */
1810 args->data = Buffer;
1811 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
1812 *(Buffer++) = *(url++);
1813 if(Buffer == args->data)
1814 return "Mountpoint required.";
1815 else if(Buffer >= Bufend-1)
1816 return "Parsing buffer too short.";
1817 *(Buffer++) = 0;
1818 }
1819
1820 if(*url == '/') /* username and password */
1821 {
1822 ++url;
1823 args->user = Buffer;
1824 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
1825 *(Buffer++) = *(url++);
1826 if(Buffer == args->user)
1827 return "Username cannot be empty.";
1828 else if(Buffer >= Bufend-1)
1829 return "Parsing buffer too short.";
1830 *(Buffer++) = 0;
1831
1832 if(*url == ':') ++url;
1833
1834 args->password = Buffer;
1835 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
1836 *(Buffer++) = *(url++);
1837 if(Buffer == args->password)
1838 return "Password cannot be empty.";
1839 else if(Buffer >= Bufend-1)
1840 return "Parsing buffer too short.";
1841 *(Buffer++) = 0;
1842 }
1843
1844 if(*url == '@') /* server */
1845 {
1846 ++url;
1847 if(*url != '@' && *url != ':')
1848 {
1849 args->server = Buffer;
1850 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
1851 *(Buffer++) = *(url++);
1852 if(Buffer == args->server)
1853 return "Servername cannot be empty.";
1854 else if(Buffer >= Bufend-1)
1855 return "Parsing buffer too short.";
1856 *(Buffer++) = 0;
1857 }
1858
1859 if(*url == ':')
1860 {
1861 ++url;
1862 args->port = Buffer;
1863 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
1864 *(Buffer++) = *(url++);
1865 if(Buffer == args->port)
1866 return "Port cannot be empty.";
1867 else if(Buffer >= Bufend-1)
1868 return "Parsing buffer too short.";
1869 *(Buffer++) = 0;
1870 }
1871
1872 if(*url == '@') /* proxy */
1873 {
1874 ++url;
1875 args->proxyhost = Buffer;
1876 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
1877 *(Buffer++) = *(url++);
1878 if(Buffer == args->proxyhost)
1879 return "Proxy servername cannot be empty.";
1880 else if(Buffer >= Bufend-1)
1881 return "Parsing buffer too short.";
1882 *(Buffer++) = 0;
1883
1884 if(*url == ':')
1885 {
1886 ++url;
1887 args->proxyport = Buffer;
1888 while(*url && *url != ';' && Buffer != Bufend)
1889 *(Buffer++) = *(url++);
1890 if(Buffer == args->proxyport)
1891 return "Proxy port cannot be empty.";
1892 else if(Buffer >= Bufend-1)
1893 return "Parsing buffer too short.";
1894 *(Buffer++) = 0;
1895 }
1896 }
1897 }
1898 if(*url == ';') /* NMEA */
1899 {
1900 args->nmea = ++url;
1901 while(*url)
1902 ++url;
1903 }
1904
1905 return *url ? "Garbage at end of server string." : 0;
1906}
1907
1908static int getargs(int argc, char **argv, struct Args *args)
1909{
1910 int res = 1;
1911 int getoptr;
1912 int help = 0;
1913 char *t;
1914
1915 args->server = "www.euref-ip.net";
1916 args->port = "2101";
1917 args->timeout = 60;
1918 args->user = "";
1919 args->password = "";
1920 args->data = 0;
1921 args->headerfile = 0;
1922 args->gpsephemeris = 0;
1923 args->glonassephemeris = 0;
1924 args->rinex3 = 0;
1925 args->nmea = 0;
1926 args->proxyhost = 0;
1927 args->proxyport = "2101";
1928 args->mode = AUTO;
1929 help = 0;
1930
1931 do
1932 {
1933
1934#ifdef NO_LONG_OPTS
1935 switch((getoptr = getopt(argc, argv, ARGOPT)))
1936#else
1937 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
1938#endif
1939 {
1940 case 's': args->server = optarg; break;
1941 case 'u': args->user = optarg; break;
1942 case 'p': args->password = optarg; break;
1943 case 'd': args->data = optarg; break;
1944 case 'f': args->headerfile = optarg; break;
1945 case 'E': args->gpsephemeris = optarg; break;
1946 case 'G': args->glonassephemeris = optarg; break;
1947 case 'r': args->port = optarg; break;
1948 case '3': args->rinex3 = 1; break;
1949 case 'S': args->proxyhost = optarg; break;
1950 case 'n': args->nmea = optarg; break;
1951 case 'R': args->proxyport = optarg; break;
1952 case 'h': help=1; break;
1953 case 'M':
1954 args->mode = 0;
1955 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
1956 args->mode = NTRIP1;
1957 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
1958 args->mode = HTTP;
1959 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
1960 args->mode = RTSP;
1961 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
1962 args->mode = AUTO;
1963 else args->mode = atoi(optarg);
1964 if((args->mode == 0) || (args->mode >= END))
1965 {
1966 fprintf(stderr, "Mode %s unknown\n", optarg);
1967 res = 0;
1968 }
1969 break;
1970 case 't':
1971 args->timeout = strtoul(optarg, &t, 10);
1972 if((t && *t) || args->timeout < 0)
1973 res = 0;
1974 break;
1975
1976 case 1:
1977 {
1978 const char *err;
1979 if((err = geturl(optarg, args)))
1980 {
1981 RTCM3Error("%s\n\n", err);
1982 res = 0;
1983 }
1984 }
1985 break;
1986 case -1: break;
1987 }
1988 } while(getoptr != -1 || !res);
1989
1990 datestr[0] = datestr[7];
1991 datestr[1] = datestr[8];
1992 datestr[2] = datestr[9];
1993 datestr[3] = datestr[10];
1994 datestr[5] = datestr[12];
1995 datestr[6] = datestr[13];
1996 datestr[8] = datestr[15];
1997 datestr[9] = datestr[16];
1998 datestr[4] = datestr[7] = '-';
1999 datestr[10] = 0;
2000
2001 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
2002 {
2003 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
2004 "Please specify only one navigation file.\n");
2005 res = 0;
2006 }
2007 else if(!res || help)
2008 {
2009 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
2010 "\nUsage: %s -s server -u user ...\n"
2011 " -d " LONG_OPT("--data ") "the requested data set\n"
2012 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
2013 " -s " LONG_OPT("--server ") "the server name or address\n"
2014 " -p " LONG_OPT("--password ") "the login password\n"
2015 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
2016 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
2017 " -u " LONG_OPT("--user ") "the user name\n"
2018 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
2019 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
2020 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
2021 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
2022 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
2023 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
2024 " -M " LONG_OPT("--mode ") "mode for data request\n"
2025 " Valid modes are:\n"
2026 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
2027 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
2028 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
2029 " 4, a, auto automatic detection (default)\n"
2030 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
2031 , revisionstr, datestr, argv[0], argv[0]);
2032 exit(1);
2033 }
2034 return res;
2035}
2036
2037/* let the output complete a block if necessary */
2038static void signalhandler(int sig)
2039{
2040 if(!stop)
2041 {
2042 RTCM3Error("Stop signal number %d received. "
2043 "Trying to terminate gentle.\n", sig);
2044 stop = 1;
2045 alarm(1);
2046 }
2047}
2048
2049#ifndef WINDOWSVERSION
2050static void WaitMicro(int mic)
2051{
2052 struct timeval tv;
2053 tv.tv_sec = mic/1000000;
2054 tv.tv_usec = mic%1000000;
2055#ifdef DEBUG
2056 fprintf(stderr, "Waiting %d micro seconds\n", mic);
2057#endif
2058 select(0, 0, 0, 0, &tv);
2059}
2060#else /* WINDOWSVERSION */
2061void WaitMicro(int mic)
2062{
2063 Sleep(mic/1000);
2064}
2065#endif /* WINDOWSVERSION */
2066
2067#define ALARMTIME (2*60)
2068
2069/* for some reason we had to abort hard (maybe waiting for data */
2070#ifdef __GNUC__
2071static __attribute__ ((noreturn)) void signalhandler_alarm(
2072int sig __attribute__((__unused__)))
2073#else /* __GNUC__ */
2074static void signalhandler_alarm(int sig)
2075#endif /* __GNUC__ */
2076{
2077 RTCM3Error("Programm forcefully terminated.\n");
2078 exit(1);
2079}
2080
2081int main(int argc, char **argv)
2082{
2083 struct Args args;
2084 struct RTCM3ParserData Parser;
2085
2086 setbuf(stdout, 0);
2087 setbuf(stdin, 0);
2088 setbuf(stderr, 0);
2089
2090 {
2091 char *a;
2092 int i=0;
2093 for(a = revisionstr+11; *a && *a != ' '; ++a)
2094 revisionstr[i++] = *a;
2095 revisionstr[i] = 0;
2096 }
2097
2098 signal(SIGINT, signalhandler);
2099 signal(SIGALRM,signalhandler_alarm);
2100 signal(SIGQUIT,signalhandler);
2101 signal(SIGTERM,signalhandler);
2102 signal(SIGPIPE,signalhandler);
2103 memset(&Parser, 0, sizeof(Parser));
2104 {
2105 time_t tim;
2106 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
2107 Parser.GPSWeek = tim/(7*24*60*60);
2108 Parser.GPSTOW = tim%(7*24*60*60);
2109 }
2110
2111 if(getargs(argc, argv, &args))
2112 {
2113 int sockfd, numbytes;
2114 char buf[MAXDATASIZE];
2115 struct sockaddr_in their_addr; /* connector's address information */
2116 struct hostent *he;
2117 struct servent *se;
2118 const char *server, *port, *proxyserver = 0;
2119 char proxyport[6];
2120 char *b;
2121 long i;
2122 struct timeval tv;
2123
2124 alarm(ALARMTIME);
2125
2126 Parser.headerfile = args.headerfile;
2127 Parser.glonassephemeris = args.glonassephemeris;
2128 Parser.gpsephemeris = args.gpsephemeris;
2129 Parser.rinex3 = args.rinex3;
2130
2131 if(args.proxyhost)
2132 {
2133 int p;
2134 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
2135 p = i;
2136 else if(!(se = getservbyname(args.port, 0)))
2137 {
2138 RTCM3Error("Can't resolve port %s.", args.port);
2139 exit(1);
2140 }
2141 else
2142 {
2143 p = ntohs(se->s_port);
2144 }
2145 snprintf(proxyport, sizeof(proxyport), "%d", p);
2146 port = args.proxyport;
2147 proxyserver = args.server;
2148 server = args.proxyhost;
2149 }
2150 else
2151 {
2152 server = args.server;
2153 port = args.port;
2154 }
2155
2156 memset(&their_addr, 0, sizeof(struct sockaddr_in));
2157 if((i = strtol(port, &b, 10)) && (!b || !*b))
2158 their_addr.sin_port = htons(i);
2159 else if(!(se = getservbyname(port, 0)))
2160 {
2161 RTCM3Error("Can't resolve port %s.", port);
2162 exit(1);
2163 }
2164 else
2165 {
2166 their_addr.sin_port = se->s_port;
2167 }
2168 if(!(he=gethostbyname(server)))
2169 {
2170 RTCM3Error("Server name lookup failed for '%s'.\n", server);
2171 exit(1);
2172 }
2173 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2174 {
2175 perror("socket");
2176 exit(1);
2177 }
2178
2179 tv.tv_sec = args.timeout;
2180 tv.tv_usec = 0;
2181 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
2182 {
2183 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
2184 exit(1);
2185 }
2186
2187 their_addr.sin_family = AF_INET;
2188 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
2189
2190 if(args.data && args.mode == RTSP)
2191 {
2192 struct sockaddr_in local;
2193 int sockudp, localport;
2194 int cseq = 1;
2195 socklen_t len;
2196
2197 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2198 {
2199 perror("socket");
2200 exit(1);
2201 }
2202 /* fill structure with local address information for UDP */
2203 memset(&local, 0, sizeof(local));
2204 local.sin_family = AF_INET;
2205 local.sin_port = htons(0);
2206 local.sin_addr.s_addr = htonl(INADDR_ANY);
2207 len = sizeof(local);
2208 /* bind() in order to get a random RTP client_port */
2209 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
2210 {
2211 perror("bind");
2212 exit(1);
2213 }
2214 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
2215 {
2216 localport = ntohs(local.sin_port);
2217 }
2218 else
2219 {
2220 perror("local access failed");
2221 exit(1);
2222 }
2223 if(connect(sockfd, (struct sockaddr *)&their_addr,
2224 sizeof(struct sockaddr)) == -1)
2225 {
2226 perror("connect");
2227 exit(1);
2228 }
2229 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
2230 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
2231 "CSeq: %d\r\n"
2232 "Ntrip-Version: Ntrip/2.0\r\n"
2233 "Ntrip-Component: Ntripclient\r\n"
2234 "User-Agent: %s/%s\r\n"
2235 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
2236 "Authorization: Basic ",
2237 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2238 args.data, cseq++, AGENTSTRING, revisionstr, localport);
2239 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
2240 {
2241 RTCM3Error("Requested data too long\n");
2242 exit(1);
2243 }
2244 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
2245 if(i > MAXDATASIZE-4)
2246 {
2247 RTCM3Error("Username and/or password too long\n");
2248 exit(1);
2249 }
2250 buf[i++] = '\r';
2251 buf[i++] = '\n';
2252 buf[i++] = '\r';
2253 buf[i++] = '\n';
2254 if(args.nmea)
2255 {
2256 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
2257 if(j >= 0 && j < MAXDATASIZE-i)
2258 i += j;
2259 else
2260 {
2261 RTCM3Error("NMEA string too long\n");
2262 exit(1);
2263 }
2264 }
2265 if(send(sockfd, buf, (size_t)i, 0) != i)
2266 {
2267 perror("send");
2268 exit(1);
2269 }
2270 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2271 {
2272 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
2273 {
2274 int serverport = 0, session = 0;
2275 const char *portcheck = "server_port=";
2276 const char *sessioncheck = "session: ";
2277 int l = strlen(portcheck)-1;
2278 int j=0;
2279 for(i = 0; j != l && i < numbytes-l; ++i)
2280 {
2281 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
2282 ;
2283 }
2284 if(i == numbytes-l)
2285 {
2286 RTCM3Error("No server port number found\n");
2287 exit(1);
2288 }
2289 else
2290 {
2291 i+=l;
2292 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
2293 serverport = serverport * 10 + buf[i++]-'0';
2294 if(buf[i] != '\r' && buf[i] != ';')
2295 {
2296 RTCM3Error("Could not extract server port\n");
2297 exit(1);
2298 }
2299 }
2300 l = strlen(sessioncheck)-1;
2301 j=0;
2302 for(i = 0; j != l && i < numbytes-l; ++i)
2303 {
2304 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
2305 ;
2306 }
2307 if(i == numbytes-l)
2308 {
2309 RTCM3Error("No session number found\n");
2310 exit(1);
2311 }
2312 else
2313 {
2314 i+=l;
2315 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
2316 session = session * 10 + buf[i++]-'0';
2317 if(buf[i] != '\r')
2318 {
2319 RTCM3Error("Could not extract session number\n");
2320 exit(1);
2321 }
2322 }
2323
2324 i = snprintf(buf, MAXDATASIZE,
2325 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
2326 "CSeq: %d\r\n"
2327 "Session: %d\r\n"
2328 "\r\n",
2329 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2330 args.data, cseq++, session);
2331
2332 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
2333 {
2334 RTCM3Error("Requested data too long\n");
2335 exit(1);
2336 }
2337 if(send(sockfd, buf, (size_t)i, 0) != i)
2338 {
2339 perror("send");
2340 exit(1);
2341 }
2342 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2343 {
2344 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
2345 {
2346 struct sockaddr_in addrRTP;
2347 /* fill structure with caster address information for UDP */
2348 memset(&addrRTP, 0, sizeof(addrRTP));
2349 addrRTP.sin_family = AF_INET;
2350 addrRTP.sin_port = htons(serverport);
2351 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
2352 len = sizeof(addrRTP);
2353 int ts = 0;
2354 int sn = 0;
2355 int ssrc = 0;
2356 int init = 0;
2357 int u, v, w;
2358 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
2359 (struct sockaddr*) &addrRTP, &len)) > 0)
2360 {
2361 alarm(ALARMTIME);
2362 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
2363 {
2364 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
2365 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
2366 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
2367 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
2368 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
2369
2370 if(init)
2371 {
2372 int z;
2373 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
2374 if(ssrc != w || ts > v)
2375 {
2376 RTCM3Error("Illegal UDP data received.\n");
2377 exit(1);
2378 }
2379 if(u > sn) /* don't show out-of-order packets */
2380 for(z = 12; z < i && !stop; ++z)
2381 HandleByte(&Parser, (unsigned int) buf[z]);
2382 }
2383 sn = u; ts = v; ssrc = w; init = 1;
2384 }
2385 else
2386 {
2387 RTCM3Error("Illegal UDP header.\n");
2388 exit(1);
2389 }
2390 }
2391 }
2392 i = snprintf(buf, MAXDATASIZE,
2393 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
2394 "CSeq: %d\r\n"
2395 "Session: %d\r\n"
2396 "\r\n",
2397 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2398 args.data, cseq++, session);
2399
2400 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
2401 {
2402 RTCM3Error("Requested data too long\n");
2403 exit(1);
2404 }
2405 if(send(sockfd, buf, (size_t)i, 0) != i)
2406 {
2407 perror("send");
2408 exit(1);
2409 }
2410 }
2411 else
2412 {
2413 RTCM3Error("Could not start data stream.\n");
2414 exit(1);
2415 }
2416 }
2417 else
2418 {
2419 RTCM3Error("Could not setup initial control connection.\n");
2420 exit(1);
2421 }
2422 }
2423 else
2424 {
2425 perror("recv");
2426 exit(1);
2427 }
2428 }
2429 else
2430 {
2431 if(connect(sockfd, (struct sockaddr *)&their_addr,
2432 sizeof(struct sockaddr)) == -1)
2433 {
2434 perror("connect");
2435 exit(1);
2436 }
2437 if(!args.data)
2438 {
2439 i = snprintf(buf, MAXDATASIZE,
2440 "GET %s%s%s%s/ HTTP/1.0\r\n"
2441 "Host: %s\r\n%s"
2442 "User-Agent: %s/%s\r\n"
2443 "Connection: close\r\n"
2444 "\r\n"
2445 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
2446 proxyserver ? ":" : "", proxyserver ? proxyport : "",
2447 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
2448 AGENTSTRING, revisionstr);
2449 }
2450 else
2451 {
2452 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
2453 "GET %s%s%s%s/%s HTTP/1.0\r\n"
2454 "Host: %s\r\n%s"
2455 "User-Agent: %s/%s\r\n"
2456 "Connection: close\r\n"
2457 "Authorization: Basic "
2458 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
2459 proxyserver ? ":" : "", proxyserver ? proxyport : "",
2460 args.data, args.server,
2461 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
2462 AGENTSTRING, revisionstr);
2463 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
2464 {
2465 RTCM3Error("Requested data too long\n");
2466 exit(1);
2467 }
2468 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
2469 if(i > MAXDATASIZE-4)
2470 {
2471 RTCM3Error("Username and/or password too long\n");
2472 exit(1);
2473 }
2474 buf[i++] = '\r';
2475 buf[i++] = '\n';
2476 buf[i++] = '\r';
2477 buf[i++] = '\n';
2478 if(args.nmea)
2479 {
2480 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
2481 if(j >= 0 && j < MAXDATASIZE-i)
2482 i += j;
2483 else
2484 {
2485 RTCM3Error("NMEA string too long\n");
2486 exit(1);
2487 }
2488 }
2489 }
2490 if(send(sockfd, buf, (size_t)i, 0) != i)
2491 {
2492 perror("send");
2493 exit(1);
2494 }
2495 if(args.data)
2496 {
2497 int k = 0;
2498 int chunkymode = 0;
2499 int starttime = time(0);
2500 int lastout = starttime;
2501 int totalbytes = 0;
2502 int chunksize = 0;
2503
2504 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2505 {
2506 if(numbytes > 0)
2507 alarm(ALARMTIME);
2508 else
2509 {
2510 WaitMicro(100);
2511 continue;
2512 }
2513 if(!k)
2514 {
2515 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
2516 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
2517 {
2518 const char *datacheck = "Content-Type: gnss/data\r\n";
2519 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
2520 int l = strlen(datacheck)-1;
2521 int j=0;
2522 for(i = 0; j != l && i < numbytes-l; ++i)
2523 {
2524 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
2525 ;
2526 }
2527 if(i == numbytes-l)
2528 {
2529 RTCM3Error("No 'Content-Type: gnss/data' found\n");
2530 exit(1);
2531 }
2532 l = strlen(chunkycheck)-1;
2533 j=0;
2534 for(i = 0; j != l && i < numbytes-l; ++i)
2535 {
2536 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
2537 ;
2538 }
2539 if(i < numbytes-l)
2540 chunkymode = 1;
2541 }
2542 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
2543 {
2544 RTCM3Error("Could not get the requested data: ");
2545 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
2546 {
2547 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
2548 }
2549 RTCM3Error("\n");
2550 exit(1);
2551 }
2552 else if(args.mode != NTRIP1)
2553 {
2554 if(args.mode != AUTO)
2555 {
2556 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
2557 args.mode == AUTO ? ", falling back to NTRIP1" : "");
2558 }
2559 if(args.mode == HTTP)
2560 exit(1);
2561 }
2562 ++k;
2563 }
2564 else
2565 {
2566 if(chunkymode)
2567 {
2568 int stop = 0;
2569 int pos = 0;
2570 while(!stop && pos < numbytes)
2571 {
2572 switch(chunkymode)
2573 {
2574 case 1: /* reading number starts */
2575 chunksize = 0;
2576 ++chunkymode; /* no break */
2577 case 2: /* during reading number */
2578 i = buf[pos++];
2579 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
2580 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
2581 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
2582 else if(i == '\r') ++chunkymode;
2583 else if(i == ';') chunkymode = 5;
2584 else stop = 1;
2585 break;
2586 case 3: /* scanning for return */
2587 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
2588 else stop = 1;
2589 break;
2590 case 4: /* output data */
2591 i = numbytes-pos;
2592 if(i > chunksize) i = chunksize;
2593 {
2594 int z;
2595 for(z = 0; z < i && !stop; ++z)
2596 HandleByte(&Parser, (unsigned int) buf[pos+z]);
2597 }
2598 totalbytes += i;
2599 chunksize -= i;
2600 pos += i;
2601 if(!chunksize)
2602 chunkymode = 1;
2603 break;
2604 case 5:
2605 if(i == '\r') chunkymode = 3;
2606 break;
2607 }
2608 }
2609 if(stop)
2610 {
2611 RTCM3Error("Error in chunky transfer encoding\n");
2612 break;
2613 }
2614 }
2615 else
2616 {
2617 totalbytes += numbytes;
2618 {
2619 int z;
2620 for(z = 0; z < numbytes && !stop; ++z)
2621 HandleByte(&Parser, (unsigned int) buf[z]);
2622 }
2623 }
2624 if(totalbytes < 0) /* overflow */
2625 {
2626 totalbytes = 0;
2627 starttime = time(0);
2628 lastout = starttime;
2629 }
2630 }
2631 }
2632 }
2633 else
2634 {
2635 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
2636 {
2637 alarm(ALARMTIME);
2638 fwrite(buf, (size_t)numbytes, 1, stdout);
2639 }
2640 }
2641 close(sockfd);
2642 }
2643 }
2644 return 0;
2645}
2646#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.