source: ntrip/trunk/rtcm3torinex/lib/rtcm3torinex.c@ 4365

Last change on this file since 4365 was 4365, checked in by stoecker, 12 years ago

fix leap sec

  • Property svn:keywords set to Id Revision Date
File size: 111.7 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c 4365 2012-06-25 16:08:27Z stoecker $
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: 4365 $";
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 GETBITS64(b, a) \
139{ \
140 if(((a) > 56) && ((a)-56) > numbits) \
141 { \
142 uint64_t x; \
143 GETBITS(x, 56) \
144 LOADBITS((a)-56) \
145 b = ((x<<((a)-56)) | (bitfield<<(sizeof(bitfield)*8-numbits)) \
146 >>(sizeof(bitfield)*8-((a)-56))); \
147 numbits -= ((a)-56); \
148 } \
149 else \
150 { \
151 GETBITS(b, a) \
152 } \
153}
154
155/* extract bits from data stream
156 b = variable to store result, a = number of bits */
157#define GETBITS(b, a) \
158{ \
159 LOADBITS(a) \
160 b = (bitfield<<(64-numbits))>>(64-(a)); \
161 numbits -= (a); \
162}
163
164/* extract bits from data stream
165 b = variable to store result, a = number of bits */
166#define GETBITSFACTOR(b, a, c) \
167{ \
168 LOADBITS(a) \
169 b = ((bitfield<<(sizeof(bitfield)*8-numbits))>>(sizeof(bitfield)*8-(a)))*(c); \
170 numbits -= (a); \
171}
172
173/* extract floating value from data stream
174 b = variable to store result, a = number of bits */
175#define GETFLOAT(b, a, c) \
176{ \
177 LOADBITS(a) \
178 b = ((double)((bitfield<<(64-numbits))>>(64-(a))))*(c); \
179 numbits -= (a); \
180}
181
182/* extract signed floating value from data stream
183 b = variable to store result, a = number of bits */
184#define GETFLOATSIGN(b, a, c) \
185{ \
186 LOADBITS(a) \
187 b = ((double)(((int64_t)(bitfield<<(64-numbits)))>>(64-(a))))*(c); \
188 numbits -= (a); \
189}
190
191/* extract bits from data stream
192 b = variable to store result, a = number of bits */
193#define GETBITSSIGN(b, a) \
194{ \
195 LOADBITS(a) \
196 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
197 numbits -= (a); \
198}
199
200#define GETFLOATSIGNM(b, a, c) \
201{ int l; \
202 LOADBITS(a) \
203 l = (bitfield<<(64-numbits))>>(64-1); \
204 b = ((double)(((bitfield<<(64-(numbits-1))))>>(64-(a-1))))*(c); \
205 numbits -= (a); \
206 if(l) b *= -1.0; \
207}
208
209#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
210
211/* extract byte-aligned byte from data stream,
212 b = variable to store size, s = variable to store string pointer */
213#define GETSTRING(b, s) \
214{ \
215 b = *(data++); \
216 s = (char *) data; \
217 data += b; \
218 size -= b+1; \
219}
220
221struct leapseconds { /* specify the day of leap second */
222 int day; /* this is the day, where 23:59:59 exists 2 times */
223 int month; /* not the next day! */
224 int year;
225 int taicount;
226};
227static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
228static const struct leapseconds leap[] = {
229/*{31, 12, 1971, 11},*/
230/*{31, 12, 1972, 12},*/
231/*{31, 12, 1973, 13},*/
232/*{31, 12, 1974, 14},*/
233/*{31, 12, 1975, 15},*/
234/*{31, 12, 1976, 16},*/
235/*{31, 12, 1977, 17},*/
236/*{31, 12, 1978, 18},*/
237/*{31, 12, 1979, 19},*/
238{30, 06, 1981,20},
239{30, 06, 1982,21},
240{30, 06, 1983,22},
241{30, 06, 1985,23},
242{31, 12, 1987,24},
243{31, 12, 1989,25},
244{31, 12, 1990,26},
245{30, 06, 1992,27},
246{30, 06, 1993,28},
247{30, 06, 1994,29},
248{31, 12, 1995,30},
249{30, 06, 1997,31},
250{31, 12, 1998,32},
251{31, 12, 2005,33},
252{31, 12, 2008,34},
253{30, 06, 2012,35},
254{0,0,0,0} /* end marker */
255};
256#define LEAPSECONDS 15 /* only needed for approx. time */
257#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
258
259static int longyear(int year, int month)
260{
261 if(!(year % 4) && (!(year % 400) || (year % 100)))
262 {
263 if(!month || month == 2)
264 return 1;
265 }
266 return 0;
267}
268
269int gnumleap(int year, int month, int day)
270{
271 int ls = 0;
272 const struct leapseconds *l;
273
274 for(l = leap; l->taicount && year >= l->year; ++l)
275 {
276 if(year > l->year || month > l->month || (month == l->month && day > l->day))
277 ls = l->taicount - GPSLEAPSTART;
278 }
279 return ls;
280}
281
282/* Convert Moscow time into UTC (fixnumleap == 1) or GPS (fixnumleap == 0) */
283void updatetime(int *week, int *secOfWeek, int mSecOfWeek, int fixnumleap)
284{
285 int y,m,d,k,l, nul;
286 unsigned int j = *week*(7*24*60*60) + *secOfWeek + 5*24*60*60+3*60*60;
287 int glo_daynumber = 0, glo_timeofday;
288 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
289 + gnumleap(y+1,1,1); ++y)
290 {
291 j -= k; glo_daynumber += l;
292 }
293 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
294 + gnumleap(y, m+1, 1); ++m)
295 {
296 j -= k; glo_daynumber += l;
297 }
298 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
299 j -= 24*60*60;
300 glo_daynumber -= 16*365+4-d;
301 nul = gnumleap(y, m, d);
302 glo_timeofday = j-nul;
303
304 // original version
305 // if(mSecOfWeek < 5*60*1000 && glo_timeofday > 23*60*60)
306 // *secOfWeek += 24*60*60;
307 // else if(glo_timeofday < 5*60 && mSecOfWeek > 23*60*60*1000)
308 // *secOfWeek -= 24*60*60;
309
310 // new version
311 if(mSecOfWeek < 4*60*60*1000 && glo_timeofday > 20*60*60)
312 *secOfWeek += 24*60*60;
313 else if(glo_timeofday < 4*60*60 && mSecOfWeek > 20*60*60*1000)
314 *secOfWeek -= 24*60*60;
315
316 *secOfWeek += mSecOfWeek/1000-glo_timeofday;
317 if(fixnumleap)
318 *secOfWeek -= nul;
319 if(*secOfWeek < 0) {*secOfWeek += 24*60*60*7; --*week; }
320 if(*secOfWeek >= 24*60*60*7) {*secOfWeek -= 24*60*60*7; ++*week; }
321}
322
323int RTCM3Parser(struct RTCM3ParserData *handle)
324{
325 int ret=0;
326
327#ifdef NO_RTCM3_MAIN
328 if(GetMessage(handle)) /* don't repeat */
329#else
330 while(!ret && GetMessage(handle))
331#endif /* NO_RTCM3_MAIN */
332 {
333 /* using 64 bit integer types, as it is much easier than handling
334 the long datatypes in 32 bit */
335 uint64_t numbits = 0, bitfield = 0;
336 int size = handle->size, type;
337 int syncf, old = 0;
338 unsigned char *data = handle->Message+3;
339
340 GETBITS(type,12)
341#ifdef NO_RTCM3_MAIN
342 handle->blocktype = type;
343#endif /* NO_RTCM3_MAIN */
344 switch(type)
345 {
346#ifdef NO_RTCM3_MAIN
347 default:
348 ret = type;
349 break;
350 case 1005: case 1006:
351 {
352 SKIPBITS(22)
353 GETBITSSIGN(handle->antX, 38)
354 SKIPBITS(2)
355 GETBITSSIGN(handle->antY, 38)
356 SKIPBITS(2)
357 GETBITSSIGN(handle->antZ, 38)
358 if(type == 1006)
359 GETBITS(handle->antH, 16)
360 ret = type;
361 }
362 break;
363 case 1007: case 1008: case 1033:
364 {
365 char *antenna;
366 int antnum;
367
368 SKIPBITS(12)
369 GETSTRING(antnum,antenna)
370 memcpy(handle->antenna, antenna, antnum);
371 handle->antenna[antnum] = 0;
372 ret = type;
373 }
374 break;
375 case 1013:
376 {
377 SKIPBITS(12);
378 GETBITS(handle->modjulday, 16);
379 GETBITS(handle->secofday, 17);
380 SKIPBITS(5);
381 GETBITS(handle->leapsec, 8);
382 ret = 1013;
383 }
384 break;
385#endif /* NO_RTCM3_MAIN */
386 case 1019:
387 {
388 struct gpsephemeris *ge;
389 int sv, i;
390
391 ge = &handle->ephemerisGPS;
392 memset(ge, 0, sizeof(*ge));
393
394 GETBITS(sv, 6)
395 ge->satellite = (sv < 40 ? sv : sv+80);
396 GETBITS(ge->GPSweek, 10)
397 ge->GPSweek += 1024;
398 GETBITS(ge->URAindex, 4)
399 GETBITS(sv, 2)
400 if(sv & 1)
401 ge->flags |= GPSEPHF_L2PCODE;
402 if(sv & 2)
403 ge->flags |= GPSEPHF_L2CACODE;
404 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
405 GETBITS(ge->IODE, 8)
406 GETBITS(ge->TOC, 16)
407 ge->TOC <<= 4;
408 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
409 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
410 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
411 GETBITS(ge->IODC, 10)
412 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
413 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
414 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
415 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
416 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
417 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
418 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
419 GETBITS(ge->TOE, 16)
420 ge->TOE <<= 4;
421
422 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
423 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
424 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
425 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
426 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
427 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
428 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
429 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
430 GETBITS(ge->SVhealth, 6)
431 GETBITS(sv, 1)
432 if(sv)
433 ge->flags |= GPSEPHF_L2PCODEDATA;
434
435 i = ((int)ge->GPSweek - (int)handle->GPSWeek)*7*24*60*60
436 + ((int)ge->TOE - (int)handle->GPSTOW) - 2*60*60;
437 if(i > 5*60*60 && i < 8*60*60)
438 {
439 handle->GPSTOW = ge->TOE;
440 handle->GPSWeek = ge->GPSweek;
441 }
442 ge->TOW = 0.9999E9;
443 ret = 1019;
444 }
445 break;
446 case 1045:
447 {
448 struct galileoephemeris *ge;
449 int sv;
450
451 ge = &handle->ephemerisGALILEO;
452 memset(ge, 0, sizeof(*ge));
453
454 GETBITS(sv, 6)
455 ge->satellite = sv;
456 GETBITS(ge->Week, 12)
457 GETBITS(ge->IODnav, 10)
458 GETBITS(ge->SISA, 8)
459 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
460 GETBITSFACTOR(ge->TOC, 14, 60)
461 GETFLOATSIGN(ge->clock_driftrate, 6, 1.0/(double)(1<<30)/(double)(1<<29))
462 GETFLOATSIGN(ge->clock_drift, 21, 1.0/(double)(1<<30)/(double)(1<<16))
463 GETFLOATSIGN(ge->clock_bias, 31, 1.0/(double)(1<<30)/(double)(1<<4))
464 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
465 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
466 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
467 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
468 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
469 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
470 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
471 GETBITSFACTOR(ge->TOE, 14, 60)
472 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
473 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
474 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
475 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
476 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
477 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
478 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
479 GETFLOATSIGN(ge->BGD_1_5A, 10, 1.0/(double)(1<<30)/(double)(1<<2))
480 GETFLOATSIGN(ge->BGD_1_5B, 10, 1.0/(double)(1<<30)/(double)(1<<2))
481 GETBITS(ge->E5aHS, 2)
482 GETBITS(sv, 1)
483 if(sv)
484 ge->flags |= GALEPHF_E5ADINVALID;
485 ret = 1045;
486 }
487 break;
488 case 1020:
489 {
490 struct glonassephemeris *ge;
491 int i;
492
493 ge = &handle->ephemerisGLONASS;
494 memset(ge, 0, sizeof(*ge));
495
496 ge->flags |= GLOEPHF_PAVAILABLE;
497 GETBITS(ge->almanac_number, 6)
498 GETBITS(i, 5)
499 ge->frequency_number = i-7;
500 if(ge->almanac_number >= 1 && ge->almanac_number <= PRN_GLONASS_NUM)
501 handle->GLOFreq[ge->almanac_number-1] = 100+ge->frequency_number;
502 GETBITS(i, 1)
503 if(i)
504 ge->flags |= GLOEPHF_ALMANACHEALTHY;
505 GETBITS(i, 1)
506 if(i)
507 ge->flags |= GLOEPHF_ALMANACHEALTHOK;
508 GETBITS(i, 2)
509 if(i & 1)
510 ge->flags |= GLOEPHF_P10TRUE;
511 if(i & 2)
512 ge->flags |= GLOEPHF_P11TRUE;
513 GETBITS(i, 5)
514 ge->tk = i*60*60;
515 GETBITS(i, 6)
516 ge->tk += i*60;
517 GETBITS(i, 1)
518 ge->tk += i*30;
519 GETBITS(i, 1)
520 if(i)
521 ge->flags |= GLOEPHF_UNHEALTHY;
522 GETBITS(i, 1)
523 if(i)
524 ge->flags |= GLOEPHF_P2TRUE;
525 GETBITS(i, 7)
526 ge->tb = i*15*60;
527 GETFLOATSIGNM(ge->x_velocity, 24, 1.0/(double)(1<<20))
528 GETFLOATSIGNM(ge->x_pos, 27, 1.0/(double)(1<<11))
529 GETFLOATSIGNM(ge->x_acceleration, 5, 1.0/(double)(1<<30))
530 GETFLOATSIGNM(ge->y_velocity, 24, 1.0/(double)(1<<20))
531 GETFLOATSIGNM(ge->y_pos, 27, 1.0/(double)(1<<11))
532 GETFLOATSIGNM(ge->y_acceleration, 5, 1.0/(double)(1<<30))
533 GETFLOATSIGNM(ge->z_velocity, 24, 1.0/(double)(1<<20))
534 GETFLOATSIGNM(ge->z_pos, 27, 1.0/(double)(1<<11))
535 GETFLOATSIGNM(ge->z_acceleration, 5, 1.0/(double)(1<<30))
536 GETBITS(i, 1)
537 if(i)
538 ge->flags |= GLOEPHF_P3TRUE;
539 GETFLOATSIGNM(ge->gamma, 11, 1.0/(double)(1<<30)/(double)(1<<10))
540 SKIPBITS(3) /* GLONASS-M P, GLONASS-M ln (third string) */
541 GETFLOATSIGNM(ge->tau, 22, 1.0/(double)(1<<30)) /* GLONASS tau n(tb) */
542 SKIPBITS(5) /* GLONASS-M delta tau n(tb) */
543 GETBITS(ge->E, 5)
544 /* GETBITS(b, 1) / * GLONASS-M P4 */
545 /* GETBITS(b, 4) / * GLONASS-M Ft */
546 /* GETBITS(b, 11) / * GLONASS-M Nt */
547 /* GETBITS(b, 2) / * GLONASS-M M */
548 /* GETBITS(b, 1) / * GLONASS-M The Availability of Additional Data */
549 /* GETBITS(b, 11) / * GLONASS-M Na */
550 /* GETFLOATSIGNM(b, 32, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS tau c */
551 /* GETBITS(b, 5) / * GLONASS-M N4 */
552 /* GETFLOATSIGNM(b, 22, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS-M tau GPS */
553 /* GETBITS(b, 1) / * GLONASS-M ln (fifth string) */
554 ge->GPSWeek = handle->GPSWeek;
555 ge->GPSTOW = handle->GPSTOW;
556 ret = 1020;
557 }
558 break;
559 case 1001: case 1002: case 1003: case 1004:
560 if(handle->GPSWeek)
561 {
562 int lastlockl1[64];
563 int lastlockl2[64];
564 struct gnssdata *gnss;
565 int i, numsats, wasamb=0;
566
567 for(i = 0; i < 64; ++i)
568 lastlockl1[i] = lastlockl2[i] = 0;
569
570 gnss = &handle->DataNew;
571
572 SKIPBITS(12) /* id */
573 GETBITS(i,30)
574 if(i/1000 < (int)handle->GPSTOW - 86400)
575 ++handle->GPSWeek;
576 handle->GPSTOW = i/1000;
577 if(gnss->week && (gnss->timeofweek != i || gnss->week
578 != handle->GPSWeek))
579 {
580 handle->Data = *gnss;
581 memset(gnss, 0, sizeof(*gnss));
582 old = 1;
583 }
584 gnss->timeofweek = i;
585 gnss->week = handle->GPSWeek;
586
587 GETBITS(syncf,1) /* sync */
588 GETBITS(numsats,5)
589 SKIPBITS(4) /* smind, smint */
590
591 while(numsats-- && gnss->numsats < GNSS_MAXSATS)
592 {
593 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
594 int fullsat, num;
595
596 GETBITS(sv, 6)
597 fullsat = sv < 40 ? sv : sv+80;
598 for(num = 0; num < gnss->numsats
599 && fullsat != gnss->satellites[num]; ++num)
600 ;
601
602 if(num == gnss->numsats)
603 gnss->satellites[gnss->numsats++] = fullsat;
604
605 /* L1 */
606 GETBITS(code, 1);
607 if(code)
608 {
609 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
610 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
611 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
612 }
613 else
614 {
615 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
616 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
617 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
618 }
619 GETBITS(l1range, 24);
620 GETBITSSIGN(i, 20);
621 if((i&((1<<20)-1)) != 0x80000)
622 {
623 gnss->dataflags[num] |= (c|l);
624 gnss->measdata[num][ce] = l1range*0.02;
625 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
626 }
627 GETBITS(i, 7);
628 lastlockl1[sv] = i;
629 if(handle->lastlockGPSl1[sv] > i || i == 0)
630 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
631 if(type == 1002 || type == 1004)
632 {
633 GETBITS(amb,8);
634 if(amb && (gnss->dataflags[num] & c))
635 {
636 gnss->measdata[num][ce] += amb*299792.458;
637 gnss->measdata[num][le] += amb*299792.458;
638 ++wasamb;
639 }
640 GETBITS(i, 8);
641 if(i)
642 {
643 gnss->dataflags[num] |= s;
644 gnss->measdata[num][se] = i*0.25;
645 i /= 4*4;
646 if(i > 9) i = 9;
647 else if(i < 1) i = 1;
648 gnss->snrL1[num] = i;
649 }
650 }
651 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
652 if(type == 1003 || type == 1004)
653 {
654 /* L2 */
655 GETBITS(code,2);
656 if(code)
657 {
658 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
659 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
660 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
661 if(code >= 2)
662 gnss->dataflags2[num] |= GNSSDF2_XCORRL2;
663 }
664 else
665 {
666 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
667 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
668 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
669 }
670 GETBITSSIGN(i,14);
671 if((i&((1<<14)-1)) != 0x2000)
672 {
673 gnss->dataflags[num] |= c;
674 gnss->measdata[num][ce] = l1range*0.02+i*0.02
675 +amb*299792.458;
676 }
677 GETBITSSIGN(i,20);
678 if((i&((1<<20)-1)) != 0x80000)
679 {
680 gnss->dataflags[num] |= l;
681 gnss->measdata[num][le] = l1range*0.02+i*0.0005
682 +amb*299792.458;
683 }
684 GETBITS(i,7);
685 lastlockl2[sv] = i;
686 if(handle->lastlockGPSl2[sv] > i || i == 0)
687 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
688 if(type == 1004)
689 {
690 GETBITS(i, 8);
691 if(i)
692 {
693 gnss->dataflags[num] |= s;
694 gnss->measdata[num][se] = i*0.25;
695 i /= 4*4;
696 if(i > 9) i = 9;
697 else if(i < 1) i = 1;
698 gnss->snrL2[num] = i;
699 }
700 }
701 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
702 }
703 }
704 for(i = 0; i < 64; ++i)
705 {
706 handle->lastlockGPSl1[i] = lastlockl1[i];
707 handle->lastlockGPSl2[i] = lastlockl2[i];
708 }
709 if(!syncf && !old)
710 {
711 handle->Data = *gnss;
712 memset(gnss, 0, sizeof(*gnss));
713 }
714 if(!syncf || old)
715 {
716 if(wasamb) /* not RINEX compatible without */
717 ret = 1;
718 else
719 ret = 2;
720 }
721#ifdef NO_RTCM3_MAIN
722 else
723 ret = type;
724#endif /* NO_RTCM3_MAIN */
725 }
726 break;
727 case 1009: case 1010: case 1011: case 1012:
728 {
729 int lastlockl1[64];
730 int lastlockl2[64];
731 struct gnssdata *gnss;
732 int i, numsats;
733 int wasamb=0;
734
735 for(i = 0; i < 64; ++i)
736 lastlockl1[i] = lastlockl2[i] = 0;
737
738 gnss = &handle->DataNew;
739
740 SKIPBITS(12) /* id */;
741 GETBITS(i,27) /* tk */
742
743 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
744 i = handle->GPSTOW*1000;
745 if(gnss->week && (gnss->timeofweek != i || gnss->week
746 != handle->GPSWeek))
747 {
748 handle->Data = *gnss;
749 memset(gnss, 0, sizeof(*gnss));
750 old = 1;
751 }
752
753 gnss->timeofweek = i;
754 gnss->week = handle->GPSWeek;
755
756 GETBITS(syncf,1) /* sync */
757 GETBITS(numsats,5)
758
759 SKIPBITS(4) /* smind, smint */
760
761 while(numsats-- && gnss->numsats < GNSS_MAXSATS)
762 {
763 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
764 int freq;
765 int fullsat, num;
766
767 GETBITS(sv, 6)
768 fullsat = sv-1 + PRN_GLONASS_START;
769 for(num = 0; num < gnss->numsats
770 && fullsat != gnss->satellites[num]; ++num)
771 ;
772
773 if(num == gnss->numsats)
774 gnss->satellites[gnss->numsats++] = fullsat;
775
776 /* L1 */
777 GETBITS(code, 1)
778 GETBITS(freq, 5)
779
780 if(sv >= 1 && sv <= PRN_GLONASS_NUM)
781 handle->GLOFreq[sv-1] = 100+freq-7;
782
783 if(code)
784 {
785 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
786 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
787 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
788 }
789 else
790 {
791 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
792 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
793 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
794 }
795 GETBITS(l1range, 25)
796 GETBITSSIGN(i, 20)
797 if((i&((1<<20)-1)) != 0x80000)
798 {
799 /* Handle this like GPS. Actually for GLONASS L1 range is always
800 valid. To be on the save side, we handle it as invalid like we
801 do for GPS and also remove range in case of 0x80000. */
802 gnss->dataflags[num] |= (c|l);
803 gnss->measdata[num][ce] = l1range*0.02;
804 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
805 }
806 GETBITS(i, 7)
807 lastlockl1[sv] = i;
808 if(handle->lastlockGLOl1[sv] > i || i == 0)
809 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
810 if(type == 1010 || type == 1012)
811 {
812 GETBITS(amb,7)
813 if(amb && (gnss->dataflags[num] & c))
814 {
815 gnss->measdata[num][ce] += amb*599584.916;
816 gnss->measdata[num][le] += amb*599584.916;
817 ++wasamb;
818 }
819 GETBITS(i, 8)
820 if(i)
821 {
822 gnss->dataflags[num] |= s;
823 gnss->measdata[num][se] = i*0.25;
824 i /= 4*4;
825 if(i > 9) i = 9;
826 else if(i < 1) i = 1;
827 gnss->snrL1[num] = i;
828 }
829 }
830 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
831 if(type == 1011 || type == 1012)
832 {
833 /* L2 */
834 GETBITS(code,2)
835 if(code)
836 {
837 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
838 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
839 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
840 }
841 else
842 {
843 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
844 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
845 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
846 }
847 GETBITSSIGN(i,14)
848 if((i&((1<<14)-1)) != 0x2000)
849 {
850 gnss->dataflags[num] |= c;
851 gnss->measdata[num][ce] = l1range*0.02+i*0.02
852 +amb*599584.916;
853 }
854 GETBITSSIGN(i,20)
855 if((i&((1<<20)-1)) != 0x80000)
856 {
857 gnss->dataflags[num] |= l;
858 gnss->measdata[num][le] = l1range*0.02+i*0.0005
859 +amb*599584.916;
860 }
861 GETBITS(i,7)
862 lastlockl2[sv] = i;
863 if(handle->lastlockGLOl2[sv] > i || i == 0)
864 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
865 if(type == 1012)
866 {
867 GETBITS(i, 8)
868 if(i)
869 {
870 gnss->dataflags[num] |= s;
871 gnss->measdata[num][se] = i*0.25;
872 i /= 4*4;
873 if(i > 9) i = 9;
874 else if(i < 1) i = 1;
875 gnss->snrL2[num] = i;
876 }
877 }
878 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
879 }
880 if(!sv || sv > 24) /* illegal, remove it again */
881 --gnss->numsats;
882 }
883 for(i = 0; i < 64; ++i)
884 {
885 handle->lastlockGLOl1[i] = lastlockl1[i];
886 handle->lastlockGLOl2[i] = lastlockl2[i];
887 }
888 if(!syncf && !old)
889 {
890 handle->Data = *gnss;
891 memset(gnss, 0, sizeof(*gnss));
892 }
893 if(!syncf || old)
894 {
895 if(wasamb) /* not RINEX compatible without */
896 ret = 1;
897 else
898 ret = 2;
899 }
900#ifdef NO_RTCM3_MAIN
901 else
902 ret = type;
903#endif /* NO_RTCM3_MAIN */
904 }
905 break;
906 case 1071: case 1081: case 1091:
907 case 1072: case 1082: case 1092:
908 case 1073: case 1083: case 1093:
909 case 1074: case 1084: case 1094:
910 case 1075: case 1085: case 1095:
911 case 1076: case 1086: case 1096:
912 case 1077: case 1087: case 1097:
913 if(handle->GPSWeek)
914 {
915 struct CodeData {
916 int typeR;
917 int typeP;
918 int typeD;
919 int typeS;
920 int lock;
921 double wl;
922 const char *code; /* currently unused */
923 };
924 struct CodeData gps[RTCM3_MSM_NUMSIG] =
925 {
926 {0,0,0,0,0,0,0},
927 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
928 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1C"},
929 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
930 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1P"},
931 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
932 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1W"},
933 {0,0,0,0,0,0,0}/*{GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
934 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1Y"}*/,
935 {0,0,0,0,0,0,0},
936 {0,0,0,0,0,0,0},
937 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
938 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2C"},
939 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
940 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2P"},
941 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
942 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2W"},
943 {0,0,0,0,0,0,0}/*{GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
944 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2Y"}*/,
945 {0,0,0,0,0,0,0},
946 {0,0,0,0,0,0,0},
947 {0,0,0,0,0,0,0},
948 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
949 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2S"},
950 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
951 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2L"},
952 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
953 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2X"},
954 {0,0,0,0,0,0,0},
955 {0,0,0,0,0,0,0},
956 {0,0,0,0,0,0,0},
957 {0,0,0,0,0,0,0},
958 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
959 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5I"},
960 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
961 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5Q"},
962 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
963 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5X"},
964 {0,0,0,0,0,0,0},
965 {0,0,0,0,0,0,0},
966 {0,0,0,0,0,0,0},
967 {0,0,0,0,0,0,0},
968 {0,0,0,0,0,0,0},
969 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
970 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1S"},
971 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
972 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1L"},
973 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
974 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1X"}
975 };
976 /* NOTE: Uses 0.0, 1.0 for wavelength as sat index dependence is done later! */
977 struct CodeData glo[RTCM3_MSM_NUMSIG] =
978 {
979 {0,0,0,0,0,0,0},
980 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
981 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1C"},
982 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
983 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,0.0,"1P"},
984 {0,0,0,0,0,0,0},
985 {0,0,0,0,0,0,0},
986 {0,0,0,0,0,0,0},
987 {0,0,0,0,0,0,0},
988 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
989 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,1.0,"2C"},
990 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
991 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,1.0,"2P"},
992 {0,0,0,0,0,0,0},
993 {0,0,0,0,0,0,0},
994 {0,0,0,0,0,0,0},
995 {0,0,0,0,0,0,0},
996 {0,0,0,0,0,0,0},
997 {0,0,0,0,0,0,0},
998 {0,0,0,0,0,0,0},
999 {0,0,0,0,0,0,0},
1000 {0,0,0,0,0,0,0},
1001 {0,0,0,0,0,0,0},
1002 {0,0,0,0,0,0,0},
1003 {0,0,0,0,0,0,0},
1004 {0,0,0,0,0,0,0},
1005 {0,0,0,0,0,0,0},
1006 {0,0,0,0,0,0,0},
1007 {0,0,0,0,0,0,0},
1008 {0,0,0,0,0,0,0},
1009 {0,0,0,0,0,0,0},
1010 {0,0,0,0,0,0,0},
1011 {0,0,0,0,0,0,0},
1012 {0,0,0,0,0,0,0},
1013 {0,0,0,0,0,0,0},
1014 {0,0,0,0,0,0,0}
1015 };
1016 struct CodeData gal[RTCM3_MSM_NUMSIG] =
1017 {
1018 {0,0,0,0,0,0,0},
1019 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1020 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1C"},
1021 {0,0,0,0,0,0,0}/*{GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1022 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1A"}*/,
1023 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1024 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1B"},
1025 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1026 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1X"}/**/,
1027 {0,0,0,0,0,0,0}/*{GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1028 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1Z"}*/,
1029 {0,0,0,0,0,0,0},
1030 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1031 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6C"},
1032 {0,0,0,0,0,0,0}/*{GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1033 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6A"}*/,
1034 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1035 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6B"},
1036 {0,0,0,0,0,0,0}/*{GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1037 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6X"}*/,
1038 {0,0,0,0,0,0,0}/*{GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1039 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6Z"}*/,
1040 {0,0,0,0,0,0,0},
1041 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1042 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7I"},
1043 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1044 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7Q"},
1045 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1046 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7X"}/**/,
1047 {0,0,0,0,0,0,0},
1048 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1049 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8I"},
1050 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1051 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8Q"},
1052 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1053 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8X"}/**/,
1054 {0,0,0,0,0,0,0},
1055 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1056 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5I"},
1057 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1058 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5Q"},
1059 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1060 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5X"}/**/,
1061 {0,0,0,0,0,0,0},
1062 {0,0,0,0,0,0,0},
1063 {0,0,0,0,0,0,0},
1064 {0,0,0,0,0,0,0},
1065 {0,0,0,0,0,0,0},
1066 {0,0,0,0,0,0,0},
1067 {0,0,0,0,0,0,0},
1068 {0,0,0,0,0,0,0},
1069 };
1070
1071 int sys = RTCM3_MSM_GPS, i=0, count, j, old = 0, wasnoamb = 0;
1072 int syncf, sigmask, numsat = 0, numsig = 0, numcells;
1073 uint64_t satmask, cellmask, ui;
1074 double rrmod[RTCM3_MSM_NUMSAT];
1075 int rrint[RTCM3_MSM_NUMSAT], rdop[RTCM3_MSM_NUMSAT],
1076 extsat[RTCM3_MSM_NUMSAT];
1077 int ll[RTCM3_MSM_NUMCELLS], hc[RTCM3_MSM_NUMCELLS];
1078 double cnr[RTCM3_MSM_NUMCELLS];
1079 double cp[RTCM3_MSM_NUMCELLS], psr[RTCM3_MSM_NUMCELLS],
1080 dop[RTCM3_MSM_NUMCELLS];
1081 struct gnssdata *gnss = &handle->DataNew;
1082
1083 SKIPBITS(12)
1084 if(type >= 1091)
1085 sys = RTCM3_MSM_GALILEO;
1086 else if(type >= 1081)
1087 sys = RTCM3_MSM_GLONASS;
1088
1089 switch(sys)
1090 {
1091 case RTCM3_MSM_GALILEO: /* use DF004 instead of DF248 */
1092 case RTCM3_MSM_GPS:
1093 GETBITS(i,30)
1094 if(i/1000 < (int)handle->GPSTOW - 86400)
1095 ++handle->GPSWeek;
1096 handle->GPSTOW = i/1000;
1097 break;
1098 case RTCM3_MSM_GLONASS:
1099 SKIPBITS(3)
1100 GETBITS(i,27) /* tk */
1101
1102 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
1103 i = handle->GPSTOW*1000;
1104 break;
1105 }
1106
1107 if(gnss->week && (gnss->timeofweek != i || gnss->week
1108 != handle->GPSWeek))
1109 {
1110 handle->Data = *gnss;
1111 memset(gnss, 0, sizeof(*gnss));
1112 old = 1;
1113 }
1114 gnss->timeofweek = i;
1115 gnss->week = handle->GPSWeek;
1116
1117 GETBITS(syncf, 1)
1118 SKIPBITS(3+7+2+2+1+3)
1119 GETBITS64(satmask, RTCM3_MSM_NUMSAT)
1120
1121 /* http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/ */
1122 for(ui = satmask; ui; ui &= (ui - 1) /* remove rightmost bit */)
1123 ++numsat;
1124 GETBITS(sigmask, RTCM3_MSM_NUMSIG)
1125 for(i = sigmask; i; i &= (i - 1) /* remove rightmost bit */)
1126 ++numsig;
1127 i = numsat*numsig;
1128 GETBITS64(cellmask, (unsigned)i)
1129
1130 switch(type % 10)
1131 {
1132 case 1: case 2: case 3:
1133 ++wasnoamb;
1134 for(j = numsat; j--;)
1135 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1136 break;
1137 case 4: case 6:
1138 for(j = numsat; j--;)
1139 GETBITS(rrint[j], 8)
1140 for(j = numsat; j--;)
1141 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1142 break;
1143 case 5: case 7:
1144 for(j = numsat; j--;)
1145 GETBITS(rrint[j], 8)
1146 for(j = numsat; j--;)
1147 GETBITS(extsat[j], 4)
1148 for(j = numsat; j--;)
1149 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1150 for(j = numsat; j--;)
1151 GETBITSSIGN(rdop[j], 14)
1152 break;
1153 }
1154
1155 numcells = numsat*numsig;
1156 if(numcells <= RTCM3_MSM_NUMCELLS)
1157 {
1158 switch(type % 10)
1159 {
1160 case 1:
1161 for(count = numcells; count--;)
1162 if(cellmask & (UINT64(1)<<count))
1163 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1164 break;
1165 case 2:
1166 for(count = numcells; count--;)
1167 if(cellmask & (UINT64(1)<<count))
1168 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1169 for(count = numcells; count--;)
1170 if(cellmask & (UINT64(1)<<count))
1171 GETBITS(ll[count], 4)
1172 for(count = numcells; count--;)
1173 if(cellmask & (UINT64(1)<<count))
1174 GETBITS(hc[count], 1)
1175 break;
1176 case 3:
1177 for(count = numcells; count--;)
1178 if(cellmask & (UINT64(1)<<count))
1179 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1180 for(count = numcells; count--;)
1181 if(cellmask & (UINT64(1)<<count))
1182 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1183 for(count = numcells; count--;)
1184 if(cellmask & (UINT64(1)<<count))
1185 GETBITS(ll[count], 4)
1186 for(count = numcells; count--;)
1187 if(cellmask & (UINT64(1)<<count))
1188 GETBITS(hc[count], 1)
1189 break;
1190 case 4:
1191 for(count = numcells; count--;)
1192 if(cellmask & (UINT64(1)<<count))
1193 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1194 for(count = numcells; count--;)
1195 if(cellmask & (UINT64(1)<<count))
1196 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1197 for(count = numcells; count--;)
1198 if(cellmask & (UINT64(1)<<count))
1199 GETBITS(ll[count], 4)
1200 for(count = numcells; count--;)
1201 if(cellmask & (UINT64(1)<<count))
1202 GETBITS(hc[count], 1)
1203 for(count = numcells; count--;)
1204 if(cellmask & (UINT64(1)<<count))
1205 GETBITS(cnr[count], 6)
1206 break;
1207 case 5:
1208 for(count = numcells; count--;)
1209 if(cellmask & (UINT64(1)<<count))
1210 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1211 for(count = numcells; count--;)
1212 if(cellmask & (UINT64(1)<<count))
1213 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1214 for(count = numcells; count--;)
1215 if(cellmask & (UINT64(1)<<count))
1216 GETBITS(ll[count], 4)
1217 for(count = numcells; count--;)
1218 if(cellmask & (UINT64(1)<<count))
1219 GETBITS(hc[count], 1)
1220 for(count = numcells; count--;)
1221 if(cellmask & (UINT64(1)<<count))
1222 GETFLOAT(cnr[count], 6, 1.0)
1223 for(count = numcells; count--;)
1224 if(cellmask & (UINT64(1)<<count))
1225 GETFLOATSIGN(dop[count], 15, 0.0001)
1226 break;
1227 case 6:
1228 for(count = numcells; count--;)
1229 if(cellmask & (UINT64(1)<<count))
1230 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1231 for(count = numcells; count--;)
1232 if(cellmask & (UINT64(1)<<count))
1233 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1234 for(count = numcells; count--;)
1235 if(cellmask & (UINT64(1)<<count))
1236 GETBITS(ll[count], 10)
1237 for(count = numcells; count--;)
1238 if(cellmask & (UINT64(1)<<count))
1239 GETBITS(hc[count], 1)
1240 for(count = numcells; count--;)
1241 if(cellmask & (UINT64(1)<<count))
1242 GETFLOAT(cnr[count], 10, 1.0/(1<<4))
1243 break;
1244 case 7:
1245 for(count = numcells; count--;)
1246 if(cellmask & (UINT64(1)<<count))
1247 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1248 for(count = numcells; count--;)
1249 if(cellmask & (UINT64(1)<<count))
1250 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1251 for(count = numcells; count--;)
1252 if(cellmask & (UINT64(1)<<count))
1253 GETBITS(ll[count], 10)
1254 for(count = numcells; count--;)
1255 if(cellmask & (UINT64(1)<<count))
1256 GETBITS(hc[count], 1)
1257 for(count = numcells; count--;)
1258 if(cellmask & (UINT64(1)<<count))
1259 GETFLOAT(cnr[count], 10, 1.0/(1<<4))
1260 for(count = numcells; count--;)
1261 if(cellmask & (UINT64(1)<<count))
1262 GETFLOATSIGN(dop[count], 15, 0.0001)
1263 break;
1264 }
1265 i = RTCM3_MSM_NUMSAT;
1266 j = -1;
1267 for(count = numcells; count--;)
1268 {
1269 while(j >= 0 && !(sigmask&(1<<--j)))
1270 ;
1271 if(j < 0)
1272 {
1273 while(!(satmask&(UINT64(1)<<(--i)))) /* next satellite */
1274 ;
1275 j = RTCM3_MSM_NUMSIG;
1276 while(!(sigmask&(1<<--j)))
1277 ;
1278 --numsat;
1279 }
1280 if(cellmask & (UINT64(1)<<count))
1281 {
1282 struct CodeData cd = {0,0,0,0,0,0,0};
1283 double wl = 0.0;
1284 switch(sys)
1285 {
1286 case RTCM3_MSM_GPS: cd = gps[RTCM3_MSM_NUMSIG-j-1];
1287 wl = cd.wl;
1288 break;
1289 case RTCM3_MSM_GLONASS: cd = glo[RTCM3_MSM_NUMSIG-j-1];
1290 {
1291 int k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1];
1292 if(!k && extsat[count] < 14)
1293 {
1294 k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1]
1295 = 100+extsat[count]-7;
1296 }
1297 if(k)
1298 {
1299 if(cd.wl == 0.0)
1300 wl = GLO_WAVELENGTH_L1(k-100);
1301 else if(cd.wl == 1.0)
1302 wl = GLO_WAVELENGTH_L2(k-100);
1303 }
1304 }
1305 break;
1306 case RTCM3_MSM_GALILEO: cd = gal[RTCM3_MSM_NUMSIG-j-1];
1307 wl = cd.wl;
1308 break;
1309 }
1310 if(cd.lock && wl) /* lock cannot have a valid zero value */
1311 {
1312 int fullsat = RTCM3_MSM_NUMSAT-i-1, num;
1313
1314 if(sys == RTCM3_MSM_GALILEO && fullsat >= 50 && fullsat <= 51)
1315 fullsat += PRN_GIOVE_START-50;
1316 else
1317 fullsat += sys;
1318
1319 for(num = 0; num < gnss->numsats
1320 && fullsat != gnss->satellites[num]; ++num)
1321 ;
1322
1323 if(num == gnss->numsats)
1324 gnss->satellites[gnss->numsats++] = fullsat;
1325
1326 switch(type % 10)
1327 {
1328 case 1:
1329 if(psr[count] > -1.0/(1<<10))
1330 {
1331 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1332 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1333 gnss->dataflags[num] |= (1<<cd.typeR);
1334 }
1335 break;
1336 case 2:
1337 if(wl && cp[count] > -1.0/(1<<8))
1338 {
1339 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1340 +(rrmod[numsat])*LIGHTSPEED/1000.0/wl;
1341 if(handle->lastlockmsm[j][i] != ll[count])
1342 {
1343 gnss->dataflags2[num] |= cd.lock;
1344 handle->lastlockmsm[j][i] = ll[count];
1345 }
1346 gnss->dataflags[num] |= (1<<cd.typeP);
1347 }
1348 break;
1349 case 3:
1350 if(psr[count] > -1.0/(1<<10))
1351 {
1352 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1353 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1354 gnss->dataflags[num] |= (1<<cd.typeR);
1355 }
1356
1357 if(wl && cp[count] > -1.0/(1<<8))
1358 {
1359 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1360 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1361 if(handle->lastlockmsm[j][i] != ll[count])
1362 {
1363 gnss->dataflags2[num] |= cd.lock;
1364 handle->lastlockmsm[j][i] = ll[count];
1365 }
1366 gnss->dataflags[num] |= (1<<cd.typeP);
1367 }
1368 break;
1369 case 4:
1370 if(psr[count] > -1.0/(1<<10))
1371 {
1372 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1373 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1374 gnss->dataflags[num] |= (1<<cd.typeR);
1375 }
1376
1377 if(wl && cp[count] > -1.0/(1<<8))
1378 {
1379 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1380 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1381 if(handle->lastlockmsm[j][i] != ll[count])
1382 {
1383 gnss->dataflags2[num] |= cd.lock;
1384 handle->lastlockmsm[j][i] = ll[count];
1385 }
1386 gnss->dataflags[num] |= (1<<cd.typeP);
1387 }
1388
1389 gnss->measdata[num][cd.typeS] = cnr[count];
1390 gnss->dataflags[num] |= (1<<cd.typeS);
1391 break;
1392 case 5:
1393 if(psr[count] > -1.0/(1<<10))
1394 {
1395 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1396 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1397 gnss->dataflags[num] |= (1<<cd.typeR);
1398 }
1399
1400 if(wl && cp[count] > -1.0/(1<<8))
1401 {
1402 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1403 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1404 if(handle->lastlockmsm[j][i] != ll[count])
1405 {
1406 gnss->dataflags2[num] |= cd.lock;
1407 handle->lastlockmsm[j][i] = ll[count];
1408 }
1409 gnss->dataflags[num] |= (1<<cd.typeP);
1410 }
1411
1412 gnss->measdata[num][cd.typeS] = cnr[count];
1413 gnss->dataflags[num] |= (1<<cd.typeS);
1414
1415 if(dop[count] > -1.6384)
1416 {
1417 gnss->measdata[num][cd.typeD] = -(dop[count]
1418 +rdop[numsat])/wl;
1419 gnss->dataflags[num] |= (1<<cd.typeD);
1420 }
1421 break;
1422 case 6:
1423 if(psr[count] > -1.0/(1<<10))
1424 {
1425 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1426 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1427 gnss->dataflags[num] |= (1<<cd.typeR);
1428 }
1429
1430 if(wl && cp[count] > -1.0/(1<<8))
1431 {
1432 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1433 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1434 if(handle->lastlockmsm[j][i] != ll[count])
1435 {
1436 gnss->dataflags2[num] |= cd.lock;
1437 handle->lastlockmsm[j][i] = ll[count];
1438 }
1439 gnss->dataflags[num] |= (1<<cd.typeP);
1440 }
1441
1442 gnss->measdata[num][cd.typeS] = cnr[count];
1443 gnss->dataflags[num] |= (1<<cd.typeS);
1444 break;
1445 case 7:
1446 if(psr[count] > -1.0/(1<<10))
1447 {
1448 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1449 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1450 gnss->dataflags[num] |= (1<<cd.typeR);
1451 }
1452
1453 if(wl && cp[count] > -1.0/(1<<8))
1454 {
1455 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1456 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1457 if(handle->lastlockmsm[j][i] != ll[count])
1458 {
1459 gnss->dataflags2[num] |= cd.lock;
1460 handle->lastlockmsm[j][i] = ll[count];
1461 }
1462 gnss->dataflags[num] |= (1<<cd.typeP);
1463 }
1464
1465 gnss->measdata[num][cd.typeS] = cnr[count];
1466 gnss->dataflags[num] |= (1<<cd.typeS);
1467
1468 if(dop[count] > -1.6384)
1469 {
1470 gnss->measdata[num][cd.typeD] = -(dop[count]
1471 +rdop[numsat])/wl;
1472 gnss->dataflags[num] |= (1<<cd.typeD);
1473 }
1474 break;
1475 }
1476 }
1477 }
1478 }
1479 }
1480 if(!syncf && !old)
1481 {
1482 handle->Data = *gnss;
1483 memset(gnss, 0, sizeof(*gnss));
1484 }
1485 if(!syncf || old)
1486 {
1487 if(!wasnoamb) /* not RINEX compatible without */
1488 ret = 1;
1489 else
1490 ret = 2;
1491 }
1492#ifdef NO_RTCM3_MAIN
1493 else
1494 ret = type;
1495#endif /* NO_RTCM3_MAIN */
1496 }
1497 break;
1498 }
1499 }
1500 return ret;
1501}
1502
1503struct Header
1504{
1505 const char *version;
1506 const char *pgm;
1507 const char *marker;
1508 const char *markertype;
1509 const char *observer;
1510 const char *receiver;
1511 const char *antenna;
1512 const char *position;
1513 const char *antennaposition;
1514 const char *wavelength;
1515 const char *typesofobs; /* should not be modified outside */
1516 const char *typesofobsG; /* should not be modified outside */
1517 const char *typesofobsR; /* should not be modified outside */
1518 const char *typesofobsS; /* should not be modified outside */
1519 const char *typesofobsE; /* should not be modified outside */
1520 const char *timeoffirstobs; /* should not be modified outside */
1521};
1522
1523#define MAXHEADERLINES 50
1524#define MAXHEADERBUFFERSIZE 4096
1525struct HeaderData
1526{
1527 union
1528 {
1529 struct Header named;
1530 const char *unnamed[MAXHEADERLINES];
1531 } data;
1532 int numheaders;
1533};
1534
1535void converttime(struct converttimeinfo *c, int week, int tow)
1536{
1537 int i, k, doy, j; /* temporary variables */
1538 j = week*(7*24*60*60) + tow + 5*24*60*60;
1539 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
1540 j -= k;
1541 c->year = i;
1542 doy = 1+ (j / (24*60*60));
1543 j %= (24*60*60);
1544 c->hour = j / (60*60);
1545 j %= (60*60);
1546 c->minute = j / 60;
1547 c->second = j % 60;
1548 j = 0;
1549 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
1550 j += k;
1551 c->month = i;
1552 c->day = doy - j;
1553}
1554
1555#ifndef NO_RTCM3_MAIN
1556void RTCM3Error(const char *fmt, ...)
1557{
1558 va_list v;
1559 va_start(v, fmt);
1560 vfprintf(stderr, fmt, v);
1561 va_end(v);
1562}
1563#endif
1564
1565void RTCM3Text(const char *fmt, ...)
1566{
1567 va_list v;
1568 va_start(v, fmt);
1569 vprintf(fmt, v);
1570 va_end(v);
1571}
1572
1573static void fixrevision(void)
1574{
1575 if(revisionstr[0] == '$')
1576 {
1577 char *a;
1578 int i=sizeof(RTCM3TORINEX_VERSION); /* set version to 1.<revision> */
1579 strcpy(revisionstr, RTCM3TORINEX_VERSION ".");
1580 for(a = revisionstr+11; *a && *a != ' '; ++a)
1581 revisionstr[i++] = *a;
1582 revisionstr[i] = 0;
1583 }
1584}
1585
1586static int HandleRunBy(char *buffer, int buffersize, const char **u,
1587int rinex3)
1588{
1589 const char *user;
1590 time_t t;
1591 struct tm * t2;
1592
1593#ifdef NO_RTCM3_MAIN
1594 fixrevision();
1595#endif
1596
1597 user= getenv("USER");
1598 if(!user) user = "";
1599 t = time(&t);
1600 t2 = gmtime(&t);
1601 if(u) *u = user;
1602 return 1+snprintf(buffer, buffersize,
1603 rinex3 ?
1604 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
1605 "PGM / RUN BY / DATE" :
1606 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
1607 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1608 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
1609}
1610
1611#ifdef NO_RTCM3_MAIN
1612#define NUMSTARTSKIP 1
1613#else
1614#define NUMSTARTSKIP 3
1615#endif
1616
1617void HandleHeader(struct RTCM3ParserData *Parser)
1618{
1619#ifdef NO_RTCM3_MAIN
1620 int i;
1621 if(Parser->allflags == 0)
1622 Parser->allflags = ~0;
1623 if(Parser->rinex3)
1624 {
1625#define CHECKFLAGSNEW(a, b, c) \
1626 if(Parser->allflags & GNSSDF_##b##DATA) \
1627 { \
1628 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1629 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1630 ++Parser->numdatatypes##a; \
1631 }
1632
1633 CHECKFLAGSNEW(GPS, C1, C1C)
1634 CHECKFLAGSNEW(GPS, L1C, L1C)
1635 CHECKFLAGSNEW(GPS, D1C, D1C)
1636 CHECKFLAGSNEW(GPS, S1C, S1C)
1637 CHECKFLAGSNEW(GPS, P1, C1P)
1638 CHECKFLAGSNEW(GPS, L1P, L1P)
1639 CHECKFLAGSNEW(GPS, D1P, D1P)
1640 CHECKFLAGSNEW(GPS, S1P, S1P)
1641 CHECKFLAGSNEW(GPS, P2, C2P)
1642 CHECKFLAGSNEW(GPS, L2P, L2P)
1643 CHECKFLAGSNEW(GPS, D2P, D2P)
1644 CHECKFLAGSNEW(GPS, S2P, S2P)
1645 CHECKFLAGSNEW(GPS, C2, C2X)
1646 CHECKFLAGSNEW(GPS, L2C, L2X)
1647 CHECKFLAGSNEW(GPS, D2C, D2X)
1648 CHECKFLAGSNEW(GPS, S2C, S2X)
1649 CHECKFLAGSNEW(GLO, C1, C1C)
1650 CHECKFLAGSNEW(GLO, L1C, L1C)
1651 CHECKFLAGSNEW(GLO, D1C, D1C)
1652 CHECKFLAGSNEW(GLO, S1C, S1C)
1653 CHECKFLAGSNEW(GLO, P1, C1P)
1654 CHECKFLAGSNEW(GLO, L1P, L1P)
1655 CHECKFLAGSNEW(GLO, D1P, D1P)
1656 CHECKFLAGSNEW(GLO, S1P, S1P)
1657 CHECKFLAGSNEW(GLO, P2, C2P)
1658 CHECKFLAGSNEW(GLO, L2P, L2P)
1659 CHECKFLAGSNEW(GLO, D2P, D2P)
1660 CHECKFLAGSNEW(GLO, S2P, S2P)
1661 CHECKFLAGSNEW(GLO, C2, C2C)
1662 CHECKFLAGSNEW(GLO, L2C, L2C)
1663 CHECKFLAGSNEW(GLO, D2C, D2C)
1664 CHECKFLAGSNEW(GLO, S2C, S2C)
1665 }
1666 else
1667 {
1668#define CHECKFLAGS(a, b) \
1669 if(Parser->allflags & GNSSDF_##a##DATA) \
1670 { \
1671 if(data[RINEXENTRY_##b##DATA]) \
1672 { \
1673 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1674 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1675 } \
1676 else \
1677 { \
1678 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1679 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1680 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1681 } \
1682 }
1683
1684 int data[RINEXENTRY_NUMBER];
1685 for(i = 0; i < RINEXENTRY_NUMBER; ++i) data[i] = 0;
1686
1687 CHECKFLAGS(C1,C1)
1688 CHECKFLAGS(C2,C2)
1689 CHECKFLAGS(P1,P1)
1690 CHECKFLAGS(P2,P2)
1691 CHECKFLAGS(L1C,L1)
1692 CHECKFLAGS(L1P,L1)
1693 CHECKFLAGS(L2C,L2)
1694 CHECKFLAGS(L2P,L2)
1695 CHECKFLAGS(D1C,D1)
1696 CHECKFLAGS(D1P,D1)
1697 CHECKFLAGS(D2C,D2)
1698 CHECKFLAGS(D2P,D2)
1699 CHECKFLAGS(S1C,S1)
1700 CHECKFLAGS(S1P,S1)
1701 CHECKFLAGS(S2C,S2)
1702 CHECKFLAGS(S2P,S2)
1703 CHECKFLAGS(C5,C5)
1704 CHECKFLAGS(L5,L5)
1705 CHECKFLAGS(D5,D5)
1706 CHECKFLAGS(S5,S5)
1707 CHECKFLAGS(C5AB,C5AB)
1708 CHECKFLAGS(L5AB,L5AB)
1709 CHECKFLAGS(D5AB,D5AB)
1710 CHECKFLAGS(S5AB,S5AB)
1711 CHECKFLAGS(C5B,C5B)
1712 CHECKFLAGS(L5B,L5B)
1713 CHECKFLAGS(D5B,D5B)
1714 CHECKFLAGS(S5B,S5B)
1715 CHECKFLAGS(C6,C6)
1716 CHECKFLAGS(L6,L6)
1717 CHECKFLAGS(D6,D6)
1718 CHECKFLAGS(S6,S6)
1719 }
1720#else /* NO_RTCM3_MAIN */
1721 struct HeaderData hdata;
1722 char thebuffer[MAXHEADERBUFFERSIZE];
1723 char *buffer = thebuffer;
1724 size_t buffersize = sizeof(thebuffer);
1725 int i;
1726
1727 memset(&hdata, 0, sizeof(hdata));
1728
1729 hdata.data.named.version = buffer;
1730 i = 1+snprintf(buffer, buffersize,
1731 "%9.2f OBSERVATION DATA M (Mixed)"
1732 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
1733 buffer += i; buffersize -= i;
1734
1735 {
1736 const char *str;
1737 hdata.data.named.pgm = buffer;
1738 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
1739 buffer += i; buffersize -= i;
1740 hdata.data.named.observer = buffer;
1741 i = 1+snprintf(buffer, buffersize,
1742 "%-20.20s "
1743 "OBSERVER / AGENCY", str);
1744 buffer += i; buffersize -= i;
1745 }
1746
1747 hdata.data.named.marker =
1748 "RTCM3TORINEX "
1749 "MARKER NAME";
1750
1751 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
1752 "GEODETIC "
1753 "MARKER TYPE";
1754
1755 hdata.data.named.receiver =
1756 " "
1757 "REC # / TYPE / VERS";
1758
1759 hdata.data.named.antenna =
1760 " "
1761 "ANT # / TYPE";
1762
1763 hdata.data.named.position =
1764 " .0000 .0000 .0000 "
1765 "APPROX POSITION XYZ";
1766
1767 hdata.data.named.antennaposition =
1768 " .0000 .0000 .0000 "
1769 "ANTENNA: DELTA H/E/N";
1770
1771 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
1772 " 1 1 "
1773 "WAVELENGTH FACT L1/2";
1774
1775 if(Parser->rinex3)
1776 {
1777#define CHECKFLAGSNEW(a, b, c) \
1778 if(flags & GNSSDF_##b##DATA) \
1779 { \
1780 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1781 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1782 ++Parser->numdatatypes##a; \
1783 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " %-3s", #c); \
1784 tbufferpos += 4; \
1785 }
1786
1787 int flags = Parser->startflags;
1788 char tbuffer[6*RINEXENTRY_NUMBER+1];
1789 int tbufferpos = 0;
1790 for(i = 0; i < Parser->Data.numsats; ++i)
1791 flags |= Parser->Data.dataflags[i];
1792
1793 CHECKFLAGSNEW(GPS, C1, C1C)
1794 CHECKFLAGSNEW(GPS, L1C, L1C)
1795 CHECKFLAGSNEW(GPS, D1C, D1C)
1796 CHECKFLAGSNEW(GPS, S1C, S1C)
1797 CHECKFLAGSNEW(GPS, P1, C1W)
1798 CHECKFLAGSNEW(GPS, L1P, L1W)
1799 CHECKFLAGSNEW(GPS, D1P, D1W)
1800 CHECKFLAGSNEW(GPS, S1P, S1W)
1801
1802 hdata.data.named.typesofobsS = buffer;
1803 i = 1+snprintf(buffer, buffersize,
1804 "S %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1805 buffer += i; buffersize -= i;
1806
1807 CHECKFLAGSNEW(GPS, P2, C2P)
1808 CHECKFLAGSNEW(GPS, L2P, L2P)
1809 CHECKFLAGSNEW(GPS, D2P, D2P)
1810 CHECKFLAGSNEW(GPS, S2P, S2P)
1811 CHECKFLAGSNEW(GPS, C2, C2X)
1812 CHECKFLAGSNEW(GPS, L2C, L2X)
1813 CHECKFLAGSNEW(GPS, D2C, D2X)
1814 CHECKFLAGSNEW(GPS, S2C, S2X)
1815 CHECKFLAGSNEW(GPS, C5, C5)
1816 CHECKFLAGSNEW(GPS, L5, L5)
1817 CHECKFLAGSNEW(GPS, D5, D5)
1818 CHECKFLAGSNEW(GPS, S5, S5)
1819
1820 hdata.data.named.typesofobsG = buffer;
1821 i = 1+snprintf(buffer, buffersize,
1822 "G %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1823 if(Parser->numdatatypesGPS>13)
1824 {
1825 i += snprintf(buffer+i-1, buffersize,
1826 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1827 }
1828 buffer += i; buffersize -= i;
1829
1830 tbufferpos = 0;
1831
1832 CHECKFLAGSNEW(GLO, C1, C1C)
1833 CHECKFLAGSNEW(GLO, L1C, L1C)
1834 CHECKFLAGSNEW(GLO, D1C, D1C)
1835 CHECKFLAGSNEW(GLO, S1C, S1C)
1836 CHECKFLAGSNEW(GLO, P1, C1P)
1837 CHECKFLAGSNEW(GLO, L1P, L1P)
1838 CHECKFLAGSNEW(GLO, D1P, D1P)
1839 CHECKFLAGSNEW(GLO, S1P, S1P)
1840 CHECKFLAGSNEW(GLO, P2, C2P)
1841 CHECKFLAGSNEW(GLO, L2P, L2P)
1842 CHECKFLAGSNEW(GLO, D2P, D2P)
1843 CHECKFLAGSNEW(GLO, S2P, S2P)
1844 CHECKFLAGSNEW(GLO, C2, C2C)
1845 CHECKFLAGSNEW(GLO, L2C, L2C)
1846 CHECKFLAGSNEW(GLO, D2C, D2C)
1847 CHECKFLAGSNEW(GLO, S2C, S2C)
1848
1849 hdata.data.named.typesofobsR = buffer;
1850 i = 1+snprintf(buffer, buffersize,
1851 "R %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGLO, tbuffer);
1852 if(Parser->numdatatypesGLO>13)
1853 {
1854 i += snprintf(buffer+i-1, buffersize,
1855 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1856 }
1857 buffer += i; buffersize -= i;
1858
1859 tbufferpos = 0;
1860
1861 CHECKFLAGSNEW(GAL, C1, C1)
1862 CHECKFLAGSNEW(GAL, L1C, L1)
1863 CHECKFLAGSNEW(GAL, D1C, D1)
1864 CHECKFLAGSNEW(GAL, S1C, S1)
1865 CHECKFLAGSNEW(GAL, C6, C6)
1866 CHECKFLAGSNEW(GAL, L6, L6)
1867 CHECKFLAGSNEW(GAL, D6, D6)
1868 CHECKFLAGSNEW(GAL, S6, S6)
1869 CHECKFLAGSNEW(GAL, C5, C5)
1870 CHECKFLAGSNEW(GAL, L5, L5)
1871 CHECKFLAGSNEW(GAL, D5, D5)
1872 CHECKFLAGSNEW(GAL, S5, S5)
1873 CHECKFLAGSNEW(GAL, C5B, C7)
1874 CHECKFLAGSNEW(GAL, L5B, L7)
1875 CHECKFLAGSNEW(GAL, D5B, D7)
1876 CHECKFLAGSNEW(GAL, S5B, S7)
1877 CHECKFLAGSNEW(GAL, C5AB, C8)
1878 CHECKFLAGSNEW(GAL, L5AB, L8)
1879 CHECKFLAGSNEW(GAL, D5AB, D8)
1880 CHECKFLAGSNEW(GAL, S5AB, S8)
1881
1882 hdata.data.named.typesofobsE = buffer;
1883 i = 1+snprintf(buffer, buffersize,
1884 "E %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGAL, tbuffer);
1885 if(Parser->numdatatypesGAL>13)
1886 {
1887 i += snprintf(buffer+i-1, buffersize,
1888 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1889 }
1890 buffer += i; buffersize -= i;
1891 }
1892 else
1893 {
1894#define CHECKFLAGS(a, b) \
1895 if(flags & GNSSDF_##a##DATA) \
1896 { \
1897 if(data[RINEXENTRY_##b##DATA]) \
1898 { \
1899 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1900 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1901 } \
1902 else \
1903 { \
1904 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1905 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1906 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1907 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
1908 tbufferpos += 6; \
1909 } \
1910 }
1911
1912 int flags = Parser->startflags;
1913 int data[RINEXENTRY_NUMBER];
1914 char tbuffer[6*RINEXENTRY_NUMBER+1];
1915 int tbufferpos = 0;
1916 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
1917 data[i] = 0;
1918 for(i = 0; i < Parser->Data.numsats; ++i)
1919 flags |= Parser->Data.dataflags[i];
1920
1921 CHECKFLAGS(C1,C1)
1922 CHECKFLAGS(C2,C2)
1923 CHECKFLAGS(P1,P1)
1924 CHECKFLAGS(P2,P2)
1925 CHECKFLAGS(L1C,L1)
1926 CHECKFLAGS(L1P,L1)
1927 CHECKFLAGS(L2C,L2)
1928 CHECKFLAGS(L2P,L2)
1929 CHECKFLAGS(D1C,D1)
1930 CHECKFLAGS(D1P,D1)
1931 CHECKFLAGS(D2C,D2)
1932 CHECKFLAGS(D2P,D2)
1933 CHECKFLAGS(S1C,S1)
1934 CHECKFLAGS(S1P,S1)
1935 CHECKFLAGS(S2C,S2)
1936 CHECKFLAGS(S2P,S2)
1937 CHECKFLAGS(C5,C5)
1938 CHECKFLAGS(L5,L5)
1939 CHECKFLAGS(D5,D5)
1940 CHECKFLAGS(S5,S5)
1941 CHECKFLAGS(C5AB,C5AB)
1942 CHECKFLAGS(L5AB,L5AB)
1943 CHECKFLAGS(D5AB,D5AB)
1944 CHECKFLAGS(S5AB,S5AB)
1945 CHECKFLAGS(C5B,C5B)
1946 CHECKFLAGS(L5B,L5B)
1947 CHECKFLAGS(D5B,D5B)
1948 CHECKFLAGS(S5B,S5B)
1949 CHECKFLAGS(C6,C6)
1950 CHECKFLAGS(L6,L6)
1951 CHECKFLAGS(D6,D6)
1952 CHECKFLAGS(S6,S6)
1953
1954 hdata.data.named.typesofobs = buffer;
1955 i = 1+snprintf(buffer, buffersize,
1956 "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer);
1957 if(Parser->numdatatypesGPS>9)
1958 {
1959 i += snprintf(buffer+i-1, buffersize,
1960 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
1961 }
1962 buffer += i; buffersize -= i;
1963 }
1964
1965 {
1966 struct converttimeinfo cti;
1967 converttime(&cti, Parser->Data.week,
1968 (int)floor(Parser->Data.timeofweek/1000.0));
1969 hdata.data.named.timeoffirstobs = buffer;
1970 i = 1+snprintf(buffer, buffersize,
1971 " %4d %2d %2d %2d %2d %10.7f GPS "
1972 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
1973 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
1974
1975 buffer += i; buffersize -= i;
1976 }
1977
1978 hdata.numheaders = 15;
1979
1980 if(Parser->headerfile)
1981 {
1982 FILE *fh;
1983 if((fh = fopen(Parser->headerfile, "r")))
1984 {
1985 size_t siz;
1986 char *lastblockstart;
1987 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
1988 {
1989 buffer[siz] = '\n';
1990 if(siz == buffersize)
1991 {
1992 RTCM3Error("Header file is too large. Only %d bytes read.",
1993 (int)siz);
1994 }
1995 /* scan the file line by line and enter the entries in the list */
1996 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
1997 /* overwrites entries, except for comments */
1998 lastblockstart = buffer;
1999 for(i = 0; i < (int)siz; ++i)
2000 {
2001 if(buffer[i] == '\n')
2002 { /* we found a line */
2003 char *end;
2004 while(buffer[i+1] == '\r')
2005 ++i; /* skip \r in case there are any */
2006 end = buffer+i;
2007 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
2008 *(end--) = 0;
2009 if(end-lastblockstart < 60+5) /* short line */
2010 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
2011 else
2012 {
2013 int pos;
2014 if(!strcmp("COMMENT", lastblockstart+60))
2015 pos = hdata.numheaders;
2016 else
2017 {
2018 for(pos = 0; pos < hdata.numheaders; ++pos)
2019 {
2020 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
2021 break;
2022 }
2023 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
2024 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
2025 {
2026 RTCM3Error("Overwriting header '%s' is dangerous.\n",
2027 lastblockstart+60);
2028 }
2029 }
2030 if(pos >= MAXHEADERLINES)
2031 {
2032 RTCM3Error("Maximum number of header lines of %d reached.\n",
2033 MAXHEADERLINES);
2034 }
2035 else if(!strcmp("END OF HEADER", lastblockstart+60))
2036 {
2037 RTCM3Error("End of header ignored.\n");
2038 }
2039 else
2040 {
2041 hdata.data.unnamed[pos] = lastblockstart;
2042 if(pos == hdata.numheaders)
2043 ++hdata.numheaders;
2044 }
2045 }
2046 lastblockstart = buffer+i+1;
2047 }
2048 }
2049 }
2050 else
2051 {
2052 RTCM3Error("Could not read data from headerfile '%s'.\n",
2053 Parser->headerfile);
2054 }
2055 fclose(fh);
2056 }
2057 else
2058 {
2059 RTCM3Error("Could not open header datafile '%s'.\n",
2060 Parser->headerfile);
2061 }
2062 }
2063
2064 for(i = 0; i < hdata.numheaders; ++i)
2065 {
2066 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
2067 RTCM3Text("%s\n", hdata.data.unnamed[i]);
2068 }
2069 RTCM3Text(" "
2070 "END OF HEADER\n");
2071#endif
2072}
2073
2074static void ConvLine(FILE *file, const char *fmt, ...)
2075{
2076 char buffer[100], *b;
2077 va_list v;
2078 va_start(v, fmt);
2079 vsnprintf(buffer, sizeof(buffer), fmt, v);
2080 for(b = buffer; *b; ++b)
2081 {
2082 if(*b == 'e') *b = 'D';
2083 }
2084 fprintf(file, "%s", buffer);
2085 va_end(v);
2086}
2087
2088void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
2089{
2090 Parser->Message[Parser->MessageSize++] = byte;
2091 if(Parser->MessageSize >= Parser->NeedBytes)
2092 {
2093 int r;
2094 while((r = RTCM3Parser(Parser)))
2095 {
2096 if(r == 1020 || r == 1019)
2097 {
2098 FILE *file = 0;
2099
2100 if(Parser->rinex3 && !(file = Parser->gpsfile))
2101 {
2102 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
2103 if(n)
2104 {
2105 if(!(Parser->gpsfile = fopen(n, "w")))
2106 {
2107 RTCM3Error("Could not open ephemeris output file.\n");
2108 }
2109 else
2110 {
2111 char buffer[100];
2112 fprintf(Parser->gpsfile,
2113 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
2114 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2115 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2116 }
2117 Parser->gpsephemeris = 0;
2118 Parser->glonassephemeris = 0;
2119 file = Parser->gpsfile;
2120 }
2121 }
2122 else
2123 {
2124 if(r == 1020)
2125 {
2126 if(Parser->glonassephemeris)
2127 {
2128 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
2129 {
2130 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
2131 }
2132 else
2133 {
2134 char buffer[100];
2135 fprintf(Parser->glonassfile,
2136 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
2137 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2138 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2139 }
2140 Parser->glonassephemeris = 0;
2141 }
2142 file = Parser->glonassfile;
2143 }
2144 else if(r == 1019)
2145 {
2146 if(Parser->gpsephemeris)
2147 {
2148 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2149 {
2150 RTCM3Error("Could not open GPS ephemeris output file.\n");
2151 }
2152 else
2153 {
2154 char buffer[100];
2155 fprintf(Parser->gpsfile,
2156 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
2157 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2158 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2159 }
2160 Parser->gpsephemeris = 0;
2161 }
2162 file = Parser->gpsfile;
2163 }
2164 }
2165 if(file)
2166 {
2167 if(r == 1020)
2168 {
2169 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2170 int w = e->GPSWeek, tow = e->GPSTOW, i;
2171 struct converttimeinfo cti;
2172
2173 updatetime(&w, &tow, e->tb*1000, 1); /* Moscow - > UTC */
2174 converttime(&cti, w, tow);
2175
2176 i = e->tk-3*60*60; if(i < 0) i += 86400;
2177
2178 if(Parser->rinex3)
2179 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2180 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2181 cti.second, -e->tau, e->gamma, (double) i);
2182 else
2183 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2184 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2185 (double) cti.second, -e->tau, e->gamma, (double) i);
2186 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
2187 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2188 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
2189 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2190 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
2191 e->z_velocity, e->z_acceleration, (double) e->E);
2192 }
2193 else /* if(r == 1019) */
2194 {
2195 struct gpsephemeris *e = &Parser->ephemerisGPS;
2196 double d; /* temporary variable */
2197 unsigned long int i; /* temporary variable */
2198 struct converttimeinfo cti;
2199 converttime(&cti, e->GPSweek, e->TOC);
2200
2201 if(Parser->rinex3)
2202 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2203 e->satellite, cti.year, cti.month, cti.day, cti.hour,
2204 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2205 e->clock_driftrate);
2206 else
2207 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2208 e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
2209 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2210 e->clock_driftrate);
2211 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
2212 e->Crs, e->Delta_n, e->M0);
2213 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
2214 e->e, e->Cus, e->sqrt_A);
2215 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n",
2216 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2217 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0,
2218 e->Crc, e->omega, e->OMEGADOT);
2219 d = 0;
2220 i = e->flags;
2221 if(i & GPSEPHF_L2CACODE)
2222 d += 2.0;
2223 if(i & GPSEPHF_L2PCODE)
2224 d += 1.0;
2225 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
2226 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2227 if(e->URAindex <= 6) /* URA index */
2228 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2229 else
2230 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2231 /* 15 indicates not to use satellite. We can't handle this special
2232 case, so we create a high "non"-accuracy value. */
2233 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d,
2234 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2235
2236 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0);
2237 /* TOW */
2238 }
2239 }
2240 }
2241 else if (r == 1 || r == 2)
2242 {
2243 int i, j, o;
2244 struct converttimeinfo cti;
2245
2246 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
2247 {
2248 ++Parser->init;
2249
2250 if(Parser->init == NUMSTARTSKIP)
2251 HandleHeader(Parser);
2252 else
2253 {
2254 for(i = 0; i < Parser->Data.numsats; ++i)
2255 Parser->startflags |= Parser->Data.dataflags[i];
2256 continue;
2257 }
2258 }
2259 if(r == 2 && !Parser->validwarning)
2260 {
2261 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2262 " COMMENT\n");
2263 Parser->validwarning = 1;
2264 }
2265
2266 converttime(&cti, Parser->Data.week,
2267 (int)floor(Parser->Data.timeofweek/1000.0));
2268 if(Parser->rinex3)
2269 {
2270 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n",
2271 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2272 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2273 for(i = 0; i < Parser->Data.numsats; ++i)
2274 {
2275 int glo = 0, gal = 0;
2276 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2277 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2278 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2279 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2280 {
2281 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
2282 glo = 1;
2283 }
2284 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2285 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2286 {
2287 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
2288 gal = 1;
2289 }
2290 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2291 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2292 {
2293 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2294 gal = 1;
2295 }
2296 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2297 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2298 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
2299 else
2300 RTCM3Text("%3d", Parser->Data.satellites[i]);
2301
2302 if(glo)
2303 {
2304 for(j = 0; j < Parser->numdatatypesGLO; ++j)
2305 {
2306 int df = Parser->dataflagGLO[j];
2307 int pos = Parser->dataposGLO[j];
2308 if((Parser->Data.dataflags[i] & df)
2309 && !isnan(Parser->Data.measdata[i][pos])
2310 && !isinf(Parser->Data.measdata[i][pos]))
2311 {
2312 char lli = ' ';
2313 char snr = ' ';
2314 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2315 {
2316 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2317 lli = '1';
2318 snr = '0'+Parser->Data.snrL1[i];
2319 }
2320 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2321 {
2322 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2323 lli = '1';
2324 snr = '0'+Parser->Data.snrL2[i];
2325 }
2326 RTCM3Text("%14.3f%c%c",
2327 Parser->Data.measdata[i][pos],lli,snr);
2328 }
2329 else
2330 { /* no or illegal data */
2331 RTCM3Text(" ");
2332 }
2333 }
2334 }
2335 else if(gal)
2336 {
2337 for(j = 0; j < Parser->numdatatypesGAL; ++j)
2338 {
2339 int df = Parser->dataflagGAL[j];
2340 int pos = Parser->dataposGAL[j];
2341 if((Parser->Data.dataflags[i] & df)
2342 && !isnan(Parser->Data.measdata[i][pos])
2343 && !isinf(Parser->Data.measdata[i][pos]))
2344 {
2345 char lli = ' ';
2346 char snr = ' ';
2347 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2348 {
2349 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2350 lli = '1';
2351 snr = '0'+Parser->Data.snrL1[i];
2352 }
2353 if(df & GNSSDF_L6DATA)
2354 {
2355 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
2356 lli = '1';
2357 snr = ' ';
2358 }
2359 if(df & GNSSDF_L5DATA)
2360 {
2361 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2362 lli = '1';
2363 snr = ' ';
2364 }
2365 if(df & GNSSDF_L5BDATA)
2366 {
2367 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
2368 lli = '1';
2369 snr = ' ';
2370 }
2371 if(df & GNSSDF_L5ABDATA)
2372 {
2373 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
2374 lli = '1';
2375 snr = ' ';
2376 }
2377 RTCM3Text("%14.3f%c%c",
2378 Parser->Data.measdata[i][pos],lli,snr);
2379 }
2380 else
2381 { /* no or illegal data */
2382 RTCM3Text(" ");
2383 }
2384 }
2385 }
2386 else
2387 {
2388 for(j = 0; j < Parser->numdatatypesGPS; ++j)
2389 {
2390 int df = Parser->dataflagGPS[j];
2391 int pos = Parser->dataposGPS[j];
2392 if((Parser->Data.dataflags[i] & df)
2393 && !isnan(Parser->Data.measdata[i][pos])
2394 && !isinf(Parser->Data.measdata[i][pos]))
2395 {
2396 char lli = ' ';
2397 char snr = ' ';
2398 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2399 {
2400 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2401 lli = '1';
2402 snr = '0'+Parser->Data.snrL1[i];
2403 }
2404 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2405 {
2406 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2407 lli = '1';
2408 snr = '0'+Parser->Data.snrL2[i];
2409 }
2410 if(df & GNSSDF_L5DATA)
2411 {
2412 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2413 lli = '1';
2414 snr = ' ';
2415 }
2416 RTCM3Text("%14.3f%c%c",
2417 Parser->Data.measdata[i][pos],lli,snr);
2418 }
2419 else
2420 { /* no or illegal data */
2421 RTCM3Text(" ");
2422 }
2423 }
2424 }
2425 RTCM3Text("\n");
2426 }
2427 }
2428 else
2429 {
2430 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
2431 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
2432 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2433 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
2434 {
2435 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2436 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2437 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2438 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2439 RTCM3Text("R%02d", Parser->Data.satellites[i]
2440 - (PRN_GLONASS_START-1));
2441 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2442 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2443 RTCM3Text("S%02d", Parser->Data.satellites[i]
2444 - PRN_WAAS_START+20);
2445 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2446 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2447 RTCM3Text("E%02d", Parser->Data.satellites[i]
2448 - (PRN_GALILEO_START-1));
2449 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2450 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2451 RTCM3Text("E%02d", Parser->Data.satellites[i]
2452 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2453 else
2454 RTCM3Text("%3d", Parser->Data.satellites[i]);
2455 }
2456 RTCM3Text("\n");
2457 o = 12;
2458 j = Parser->Data.numsats - 12;
2459 while(j > 0)
2460 {
2461 RTCM3Text(" ");
2462 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
2463 {
2464 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2465 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2466 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2467 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2468 RTCM3Text("R%02d", Parser->Data.satellites[i]
2469 - (PRN_GLONASS_START-1));
2470 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2471 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2472 RTCM3Text("S%02d", Parser->Data.satellites[i]
2473 - PRN_WAAS_START+20);
2474 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2475 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2476 RTCM3Text("E%02d", Parser->Data.satellites[i]
2477 - (PRN_GALILEO_START-1));
2478 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2479 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2480 RTCM3Text("E%02d", Parser->Data.satellites[i]
2481 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2482 else
2483 RTCM3Text("%3d", Parser->Data.satellites[i]);
2484 }
2485 RTCM3Text("\n");
2486 j -= 12;
2487 o += 12;
2488 }
2489 for(i = 0; i < Parser->Data.numsats; ++i)
2490 {
2491 for(j = 0; j < Parser->numdatatypesGPS; ++j)
2492 {
2493 int v = 0;
2494 int df = Parser->dataflag[j];
2495 int pos = Parser->datapos[j];
2496 if((Parser->Data.dataflags[i] & df)
2497 && !isnan(Parser->Data.measdata[i][pos])
2498 && !isinf(Parser->Data.measdata[i][pos]))
2499 {
2500 v = 1;
2501 }
2502 else
2503 {
2504 df = Parser->dataflagGPS[j];
2505 pos = Parser->dataposGPS[j];
2506
2507 if((Parser->Data.dataflags[i] & df)
2508 && !isnan(Parser->Data.measdata[i][pos])
2509 && !isinf(Parser->Data.measdata[i][pos]))
2510 {
2511 v = 1;
2512 }
2513 }
2514
2515 if(!v)
2516 { /* no or illegal data */
2517 RTCM3Text(" ");
2518 }
2519 else
2520 {
2521 char lli = ' ';
2522 char snr = ' ';
2523 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2524 {
2525 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2526 lli = '1';
2527 snr = '0'+Parser->Data.snrL1[i];
2528 }
2529 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2530 {
2531 if(Parser->Data.dataflags2[i]
2532 & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
2533 {
2534 lli = '0';
2535 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2536 lli += 1;
2537 if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
2538 lli += 4;
2539 }
2540 snr = '0'+Parser->Data.snrL2[i];
2541 }
2542 if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
2543 & GNSSDF2_XCORRL2))
2544 lli = '4';
2545 RTCM3Text("%14.3f%c%c",
2546 Parser->Data.measdata[i][pos],lli,snr);
2547 }
2548 if(j%5 == 4 || j == Parser->numdatatypesGPS-1)
2549 RTCM3Text("\n");
2550 }
2551 }
2552 }
2553 }
2554 }
2555 }
2556}
2557
2558#ifndef NO_RTCM3_MAIN
2559static char datestr[] = "$Date: 2012-06-25 16:08:27 +0000 (Mon, 25 Jun 2012) $";
2560
2561/* The string, which is send as agent in HTTP request */
2562#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
2563
2564#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
2565
2566static const char encodingTable [64] = {
2567 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
2568 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
2569 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
2570 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
2571};
2572
2573/* does not buffer overrun, but breaks directly after an error */
2574/* returns the number of required bytes */
2575static int encode(char *buf, int size, const char *user, const char *pwd)
2576{
2577 unsigned char inbuf[3];
2578 char *out = buf;
2579 int i, sep = 0, fill = 0, bytes = 0;
2580
2581 while(*user || *pwd)
2582 {
2583 i = 0;
2584 while(i < 3 && *user) inbuf[i++] = *(user++);
2585 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
2586 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
2587 while(i < 3) {inbuf[i++] = 0; ++fill; }
2588 if(out-buf < size-1)
2589 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
2590 if(out-buf < size-1)
2591 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
2592 | ((inbuf [1] & 0xF0) >> 4)];
2593 if(out-buf < size-1)
2594 {
2595 if(fill == 2)
2596 *(out++) = '=';
2597 else
2598 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
2599 | ((inbuf [2] & 0xC0) >> 6)];
2600 }
2601 if(out-buf < size-1)
2602 {
2603 if(fill >= 1)
2604 *(out++) = '=';
2605 else
2606 *(out++) = encodingTable[inbuf [2] & 0x3F];
2607 }
2608 bytes += 4;
2609 }
2610 if(out-buf < size)
2611 *out = 0;
2612 return bytes;
2613}
2614
2615static int stop = 0;
2616
2617struct Args
2618{
2619 const char *server;
2620 const char *port;
2621 int mode;
2622 int timeout;
2623 int rinex3;
2624 const char *user;
2625 const char *password;
2626 const char *proxyhost;
2627 const char *proxyport;
2628 const char *nmea;
2629 const char *data;
2630 const char *headerfile;
2631 const char *gpsephemeris;
2632 const char *glonassephemeris;
2633};
2634
2635/* option parsing */
2636#ifdef NO_LONG_OPTS
2637#define LONG_OPT(a)
2638#else
2639#define LONG_OPT(a) a
2640static struct option opts[] = {
2641{ "data", required_argument, 0, 'd'},
2642{ "server", required_argument, 0, 's'},
2643{ "password", required_argument, 0, 'p'},
2644{ "port", required_argument, 0, 'r'},
2645{ "timeout", required_argument, 0, 't'},
2646{ "header", required_argument, 0, 'f'},
2647{ "user", required_argument, 0, 'u'},
2648{ "gpsephemeris", required_argument, 0, 'E'},
2649{ "glonassephemeris", required_argument, 0, 'G'},
2650{ "rinex3", no_argument, 0, '3'},
2651{ "proxyport", required_argument, 0, 'R'},
2652{ "proxyhost", required_argument, 0, 'S'},
2653{ "nmea", required_argument, 0, 'n'},
2654{ "mode", required_argument, 0, 'M'},
2655{ "help", no_argument, 0, 'h'},
2656{0,0,0,0}};
2657#endif
2658#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
2659
2660enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
2661
2662static const char *geturl(const char *url, struct Args *args)
2663{
2664 static char buf[1000];
2665 static char *Buffer = buf;
2666 static char *Bufend = buf+sizeof(buf);
2667
2668 if(strncmp("ntrip:", url, 6))
2669 return "URL must start with 'ntrip:'.";
2670 url += 6; /* skip ntrip: */
2671
2672 if(*url != '@' && *url != '/')
2673 {
2674 /* scan for mountpoint */
2675 args->data = Buffer;
2676 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
2677 *(Buffer++) = *(url++);
2678 if(Buffer == args->data)
2679 return "Mountpoint required.";
2680 else if(Buffer >= Bufend-1)
2681 return "Parsing buffer too short.";
2682 *(Buffer++) = 0;
2683 }
2684
2685 if(*url == '/') /* username and password */
2686 {
2687 ++url;
2688 args->user = Buffer;
2689 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
2690 *(Buffer++) = *(url++);
2691 if(Buffer == args->user)
2692 return "Username cannot be empty.";
2693 else if(Buffer >= Bufend-1)
2694 return "Parsing buffer too short.";
2695 *(Buffer++) = 0;
2696
2697 if(*url == ':') ++url;
2698
2699 args->password = Buffer;
2700 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2701 *(Buffer++) = *(url++);
2702 if(Buffer == args->password)
2703 return "Password cannot be empty.";
2704 else if(Buffer >= Bufend-1)
2705 return "Parsing buffer too short.";
2706 *(Buffer++) = 0;
2707 }
2708
2709 if(*url == '@') /* server */
2710 {
2711 ++url;
2712 if(*url != '@' && *url != ':')
2713 {
2714 args->server = Buffer;
2715 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
2716 *(Buffer++) = *(url++);
2717 if(Buffer == args->server)
2718 return "Servername cannot be empty.";
2719 else if(Buffer >= Bufend-1)
2720 return "Parsing buffer too short.";
2721 *(Buffer++) = 0;
2722 }
2723
2724 if(*url == ':')
2725 {
2726 ++url;
2727 args->port = Buffer;
2728 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2729 *(Buffer++) = *(url++);
2730 if(Buffer == args->port)
2731 return "Port cannot be empty.";
2732 else if(Buffer >= Bufend-1)
2733 return "Parsing buffer too short.";
2734 *(Buffer++) = 0;
2735 }
2736
2737 if(*url == '@') /* proxy */
2738 {
2739 ++url;
2740 args->proxyhost = Buffer;
2741 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
2742 *(Buffer++) = *(url++);
2743 if(Buffer == args->proxyhost)
2744 return "Proxy servername cannot be empty.";
2745 else if(Buffer >= Bufend-1)
2746 return "Parsing buffer too short.";
2747 *(Buffer++) = 0;
2748
2749 if(*url == ':')
2750 {
2751 ++url;
2752 args->proxyport = Buffer;
2753 while(*url && *url != ';' && Buffer != Bufend)
2754 *(Buffer++) = *(url++);
2755 if(Buffer == args->proxyport)
2756 return "Proxy port cannot be empty.";
2757 else if(Buffer >= Bufend-1)
2758 return "Parsing buffer too short.";
2759 *(Buffer++) = 0;
2760 }
2761 }
2762 }
2763 if(*url == ';') /* NMEA */
2764 {
2765 args->nmea = ++url;
2766 while(*url)
2767 ++url;
2768 }
2769
2770 return *url ? "Garbage at end of server string." : 0;
2771}
2772
2773static int getargs(int argc, char **argv, struct Args *args)
2774{
2775 int res = 1;
2776 int getoptr;
2777 int help = 0;
2778 char *t;
2779
2780 args->server = "www.euref-ip.net";
2781 args->port = "2101";
2782 args->timeout = 60;
2783 args->user = "";
2784 args->password = "";
2785 args->data = 0;
2786 args->headerfile = 0;
2787 args->gpsephemeris = 0;
2788 args->glonassephemeris = 0;
2789 args->rinex3 = 0;
2790 args->nmea = 0;
2791 args->proxyhost = 0;
2792 args->proxyport = "2101";
2793 args->mode = AUTO;
2794 help = 0;
2795
2796 do
2797 {
2798
2799#ifdef NO_LONG_OPTS
2800 switch((getoptr = getopt(argc, argv, ARGOPT)))
2801#else
2802 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
2803#endif
2804 {
2805 case 's': args->server = optarg; break;
2806 case 'u': args->user = optarg; break;
2807 case 'p': args->password = optarg; break;
2808 case 'd': args->data = optarg; break;
2809 case 'f': args->headerfile = optarg; break;
2810 case 'E': args->gpsephemeris = optarg; break;
2811 case 'G': args->glonassephemeris = optarg; break;
2812 case 'r': args->port = optarg; break;
2813 case '3': args->rinex3 = 1; break;
2814 case 'S': args->proxyhost = optarg; break;
2815 case 'n': args->nmea = optarg; break;
2816 case 'R': args->proxyport = optarg; break;
2817 case 'h': help=1; break;
2818 case 'M':
2819 args->mode = 0;
2820 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
2821 args->mode = NTRIP1;
2822 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
2823 args->mode = HTTP;
2824 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
2825 args->mode = RTSP;
2826 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
2827 args->mode = AUTO;
2828 else args->mode = atoi(optarg);
2829 if((args->mode == 0) || (args->mode >= END))
2830 {
2831 fprintf(stderr, "Mode %s unknown\n", optarg);
2832 res = 0;
2833 }
2834 break;
2835 case 't':
2836 args->timeout = strtoul(optarg, &t, 10);
2837 if((t && *t) || args->timeout < 0)
2838 res = 0;
2839 break;
2840
2841 case 1:
2842 {
2843 const char *err;
2844 if((err = geturl(optarg, args)))
2845 {
2846 RTCM3Error("%s\n\n", err);
2847 res = 0;
2848 }
2849 }
2850 break;
2851 case -1: break;
2852 }
2853 } while(getoptr != -1 || !res);
2854
2855 datestr[0] = datestr[7];
2856 datestr[1] = datestr[8];
2857 datestr[2] = datestr[9];
2858 datestr[3] = datestr[10];
2859 datestr[5] = datestr[12];
2860 datestr[6] = datestr[13];
2861 datestr[8] = datestr[15];
2862 datestr[9] = datestr[16];
2863 datestr[4] = datestr[7] = '-';
2864 datestr[10] = 0;
2865
2866 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
2867 {
2868 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
2869 "Please specify only one navigation file.\n");
2870 res = 0;
2871 }
2872 else if(!res || help)
2873 {
2874 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
2875 "\nUsage: %s -s server -u user ...\n"
2876 " -d " LONG_OPT("--data ") "the requested data set\n"
2877 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
2878 " -s " LONG_OPT("--server ") "the server name or address\n"
2879 " -p " LONG_OPT("--password ") "the login password\n"
2880 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
2881 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
2882 " -u " LONG_OPT("--user ") "the user name\n"
2883 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
2884 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
2885 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
2886 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
2887 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
2888 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
2889 " -M " LONG_OPT("--mode ") "mode for data request\n"
2890 " Valid modes are:\n"
2891 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
2892 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
2893 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
2894 " 4, a, auto automatic detection (default)\n"
2895 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
2896 , revisionstr, datestr, argv[0], argv[0]);
2897 exit(1);
2898 }
2899 return res;
2900}
2901
2902/* let the output complete a block if necessary */
2903static void signalhandler(int sig)
2904{
2905 if(!stop)
2906 {
2907 RTCM3Error("Stop signal number %d received. "
2908 "Trying to terminate gentle.\n", sig);
2909 stop = 1;
2910 alarm(1);
2911 }
2912}
2913
2914#ifndef WINDOWSVERSION
2915static void WaitMicro(int mic)
2916{
2917 struct timeval tv;
2918 tv.tv_sec = mic/1000000;
2919 tv.tv_usec = mic%1000000;
2920#ifdef DEBUG
2921 fprintf(stderr, "Waiting %d micro seconds\n", mic);
2922#endif
2923 select(0, 0, 0, 0, &tv);
2924}
2925#else /* WINDOWSVERSION */
2926void WaitMicro(int mic)
2927{
2928 Sleep(mic/1000);
2929}
2930#endif /* WINDOWSVERSION */
2931
2932#define ALARMTIME (2*60)
2933
2934/* for some reason we had to abort hard (maybe waiting for data */
2935#ifdef __GNUC__
2936static __attribute__ ((noreturn)) void signalhandler_alarm(
2937int sig __attribute__((__unused__)))
2938#else /* __GNUC__ */
2939static void signalhandler_alarm(int sig)
2940#endif /* __GNUC__ */
2941{
2942 RTCM3Error("Programm forcefully terminated.\n");
2943 exit(1);
2944}
2945
2946int main(int argc, char **argv)
2947{
2948 struct Args args;
2949 struct RTCM3ParserData Parser;
2950
2951 setbuf(stdout, 0);
2952 setbuf(stdin, 0);
2953 setbuf(stderr, 0);
2954
2955 fixrevision();
2956
2957 signal(SIGINT, signalhandler);
2958 signal(SIGALRM,signalhandler_alarm);
2959 signal(SIGQUIT,signalhandler);
2960 signal(SIGTERM,signalhandler);
2961 signal(SIGPIPE,signalhandler);
2962 memset(&Parser, 0, sizeof(Parser));
2963 {
2964 time_t tim;
2965 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
2966 Parser.GPSWeek = tim/(7*24*60*60);
2967 Parser.GPSTOW = tim%(7*24*60*60);
2968 }
2969
2970 if(getargs(argc, argv, &args))
2971 {
2972 int sockfd, numbytes;
2973 char buf[MAXDATASIZE];
2974 struct sockaddr_in their_addr; /* connector's address information */
2975 struct hostent *he;
2976 struct servent *se;
2977 const char *server, *port, *proxyserver = 0;
2978 char proxyport[6];
2979 char *b;
2980 long i;
2981 struct timeval tv;
2982
2983 alarm(ALARMTIME);
2984
2985 Parser.headerfile = args.headerfile;
2986 Parser.glonassephemeris = args.glonassephemeris;
2987 Parser.gpsephemeris = args.gpsephemeris;
2988 Parser.rinex3 = args.rinex3;
2989
2990 if(args.proxyhost)
2991 {
2992 int p;
2993 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
2994 p = i;
2995 else if(!(se = getservbyname(args.port, 0)))
2996 {
2997 RTCM3Error("Can't resolve port %s.", args.port);
2998 exit(1);
2999 }
3000 else
3001 {
3002 p = ntohs(se->s_port);
3003 }
3004 snprintf(proxyport, sizeof(proxyport), "%d", p);
3005 port = args.proxyport;
3006 proxyserver = args.server;
3007 server = args.proxyhost;
3008 }
3009 else
3010 {
3011 server = args.server;
3012 port = args.port;
3013 }
3014
3015 memset(&their_addr, 0, sizeof(struct sockaddr_in));
3016 if((i = strtol(port, &b, 10)) && (!b || !*b))
3017 their_addr.sin_port = htons(i);
3018 else if(!(se = getservbyname(port, 0)))
3019 {
3020 RTCM3Error("Can't resolve port %s.", port);
3021 exit(1);
3022 }
3023 else
3024 {
3025 their_addr.sin_port = se->s_port;
3026 }
3027 if(!(he=gethostbyname(server)))
3028 {
3029 RTCM3Error("Server name lookup failed for '%s'.\n", server);
3030 exit(1);
3031 }
3032 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
3033 {
3034 perror("socket");
3035 exit(1);
3036 }
3037
3038 tv.tv_sec = args.timeout;
3039 tv.tv_usec = 0;
3040 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
3041 {
3042 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
3043 exit(1);
3044 }
3045
3046 their_addr.sin_family = AF_INET;
3047 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3048
3049 if(args.data && args.mode == RTSP)
3050 {
3051 struct sockaddr_in local;
3052 int sockudp, localport;
3053 int cseq = 1;
3054 socklen_t len;
3055
3056 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3057 {
3058 perror("socket");
3059 exit(1);
3060 }
3061 /* fill structure with local address information for UDP */
3062 memset(&local, 0, sizeof(local));
3063 local.sin_family = AF_INET;
3064 local.sin_port = htons(0);
3065 local.sin_addr.s_addr = htonl(INADDR_ANY);
3066 len = sizeof(local);
3067 /* bind() in order to get a random RTP client_port */
3068 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
3069 {
3070 perror("bind");
3071 exit(1);
3072 }
3073 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
3074 {
3075 localport = ntohs(local.sin_port);
3076 }
3077 else
3078 {
3079 perror("local access failed");
3080 exit(1);
3081 }
3082 if(connect(sockfd, (struct sockaddr *)&their_addr,
3083 sizeof(struct sockaddr)) == -1)
3084 {
3085 perror("connect");
3086 exit(1);
3087 }
3088 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3089 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
3090 "CSeq: %d\r\n"
3091 "Ntrip-Version: Ntrip/2.0\r\n"
3092 "Ntrip-Component: Ntripclient\r\n"
3093 "User-Agent: %s/%s\r\n"
3094 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
3095 "Authorization: Basic ",
3096 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3097 args.data, cseq++, AGENTSTRING, revisionstr, localport);
3098 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3099 {
3100 RTCM3Error("Requested data too long\n");
3101 exit(1);
3102 }
3103 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3104 if(i > MAXDATASIZE-4)
3105 {
3106 RTCM3Error("Username and/or password too long\n");
3107 exit(1);
3108 }
3109 buf[i++] = '\r';
3110 buf[i++] = '\n';
3111 buf[i++] = '\r';
3112 buf[i++] = '\n';
3113 if(args.nmea)
3114 {
3115 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3116 if(j >= 0 && j < MAXDATASIZE-i)
3117 i += j;
3118 else
3119 {
3120 RTCM3Error("NMEA string too long\n");
3121 exit(1);
3122 }
3123 }
3124 if(send(sockfd, buf, (size_t)i, 0) != i)
3125 {
3126 perror("send");
3127 exit(1);
3128 }
3129 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3130 {
3131 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3132 {
3133 int serverport = 0, session = 0;
3134 const char *portcheck = "server_port=";
3135 const char *sessioncheck = "session: ";
3136 int l = strlen(portcheck)-1;
3137 int j=0;
3138 for(i = 0; j != l && i < numbytes-l; ++i)
3139 {
3140 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
3141 ;
3142 }
3143 if(i == numbytes-l)
3144 {
3145 RTCM3Error("No server port number found\n");
3146 exit(1);
3147 }
3148 else
3149 {
3150 i+=l;
3151 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3152 serverport = serverport * 10 + buf[i++]-'0';
3153 if(buf[i] != '\r' && buf[i] != ';')
3154 {
3155 RTCM3Error("Could not extract server port\n");
3156 exit(1);
3157 }
3158 }
3159 l = strlen(sessioncheck)-1;
3160 j=0;
3161 for(i = 0; j != l && i < numbytes-l; ++i)
3162 {
3163 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
3164 ;
3165 }
3166 if(i == numbytes-l)
3167 {
3168 RTCM3Error("No session number found\n");
3169 exit(1);
3170 }
3171 else
3172 {
3173 i+=l;
3174 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3175 session = session * 10 + buf[i++]-'0';
3176 if(buf[i] != '\r')
3177 {
3178 RTCM3Error("Could not extract session number\n");
3179 exit(1);
3180 }
3181 }
3182
3183 i = snprintf(buf, MAXDATASIZE,
3184 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
3185 "CSeq: %d\r\n"
3186 "Session: %d\r\n"
3187 "\r\n",
3188 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3189 args.data, cseq++, session);
3190
3191 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3192 {
3193 RTCM3Error("Requested data too long\n");
3194 exit(1);
3195 }
3196 if(send(sockfd, buf, (size_t)i, 0) != i)
3197 {
3198 perror("send");
3199 exit(1);
3200 }
3201 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3202 {
3203 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3204 {
3205 struct sockaddr_in addrRTP;
3206 /* fill structure with caster address information for UDP */
3207 memset(&addrRTP, 0, sizeof(addrRTP));
3208 addrRTP.sin_family = AF_INET;
3209 addrRTP.sin_port = htons(serverport);
3210 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3211 len = sizeof(addrRTP);
3212 int ts = 0;
3213 int sn = 0;
3214 int ssrc = 0;
3215 int init = 0;
3216 int u, v, w;
3217 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
3218 (struct sockaddr*) &addrRTP, &len)) > 0)
3219 {
3220 alarm(ALARMTIME);
3221 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
3222 {
3223 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
3224 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
3225 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
3226 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
3227 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
3228
3229 if(init)
3230 {
3231 int z;
3232 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
3233 if(ssrc != w || ts > v)
3234 {
3235 RTCM3Error("Illegal UDP data received.\n");
3236 exit(1);
3237 }
3238 if(u > sn) /* don't show out-of-order packets */
3239 for(z = 12; z < i && !stop; ++z)
3240 HandleByte(&Parser, (unsigned int) buf[z]);
3241 }
3242 sn = u; ts = v; ssrc = w; init = 1;
3243 }
3244 else
3245 {
3246 RTCM3Error("Illegal UDP header.\n");
3247 exit(1);
3248 }
3249 }
3250 }
3251 i = snprintf(buf, MAXDATASIZE,
3252 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
3253 "CSeq: %d\r\n"
3254 "Session: %d\r\n"
3255 "\r\n",
3256 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3257 args.data, cseq++, session);
3258
3259 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3260 {
3261 RTCM3Error("Requested data too long\n");
3262 exit(1);
3263 }
3264 if(send(sockfd, buf, (size_t)i, 0) != i)
3265 {
3266 perror("send");
3267 exit(1);
3268 }
3269 }
3270 else
3271 {
3272 RTCM3Error("Could not start data stream.\n");
3273 exit(1);
3274 }
3275 }
3276 else
3277 {
3278 RTCM3Error("Could not setup initial control connection.\n");
3279 exit(1);
3280 }
3281 }
3282 else
3283 {
3284 perror("recv");
3285 exit(1);
3286 }
3287 }
3288 else
3289 {
3290 if(connect(sockfd, (struct sockaddr *)&their_addr,
3291 sizeof(struct sockaddr)) == -1)
3292 {
3293 perror("connect");
3294 exit(1);
3295 }
3296 if(!args.data)
3297 {
3298 i = snprintf(buf, MAXDATASIZE,
3299 "GET %s%s%s%s/ HTTP/1.0\r\n"
3300 "Host: %s\r\n%s"
3301 "User-Agent: %s/%s\r\n"
3302 "Connection: close\r\n"
3303 "\r\n"
3304 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3305 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3306 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3307 AGENTSTRING, revisionstr);
3308 }
3309 else
3310 {
3311 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3312 "GET %s%s%s%s/%s HTTP/1.0\r\n"
3313 "Host: %s\r\n%s"
3314 "User-Agent: %s/%s\r\n"
3315 "Connection: close\r\n"
3316 "Authorization: Basic "
3317 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3318 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3319 args.data, args.server,
3320 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3321 AGENTSTRING, revisionstr);
3322 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3323 {
3324 RTCM3Error("Requested data too long\n");
3325 exit(1);
3326 }
3327 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3328 if(i > MAXDATASIZE-4)
3329 {
3330 RTCM3Error("Username and/or password too long\n");
3331 exit(1);
3332 }
3333 buf[i++] = '\r';
3334 buf[i++] = '\n';
3335 buf[i++] = '\r';
3336 buf[i++] = '\n';
3337 if(args.nmea)
3338 {
3339 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3340 if(j >= 0 && j < MAXDATASIZE-i)
3341 i += j;
3342 else
3343 {
3344 RTCM3Error("NMEA string too long\n");
3345 exit(1);
3346 }
3347 }
3348 }
3349 if(send(sockfd, buf, (size_t)i, 0) != i)
3350 {
3351 perror("send");
3352 exit(1);
3353 }
3354 if(args.data)
3355 {
3356 int k = 0;
3357 int chunkymode = 0;
3358 int starttime = time(0);
3359 int lastout = starttime;
3360 int totalbytes = 0;
3361 int chunksize = 0;
3362
3363 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3364 {
3365 if(numbytes > 0)
3366 alarm(ALARMTIME);
3367 else
3368 {
3369 WaitMicro(100);
3370 continue;
3371 }
3372 if(!k)
3373 {
3374 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
3375 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
3376 {
3377 const char *datacheck = "Content-Type: gnss/data\r\n";
3378 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
3379 int l = strlen(datacheck)-1;
3380 int j=0;
3381 for(i = 0; j != l && i < numbytes-l; ++i)
3382 {
3383 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
3384 ;
3385 }
3386 if(i == numbytes-l)
3387 {
3388 RTCM3Error("No 'Content-Type: gnss/data' found\n");
3389 exit(1);
3390 }
3391 l = strlen(chunkycheck)-1;
3392 j=0;
3393 for(i = 0; j != l && i < numbytes-l; ++i)
3394 {
3395 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
3396 ;
3397 }
3398 if(i < numbytes-l)
3399 chunkymode = 1;
3400 }
3401 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
3402 {
3403 RTCM3Error("Could not get the requested data: ");
3404 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
3405 {
3406 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
3407 }
3408 RTCM3Error("\n");
3409 exit(1);
3410 }
3411 else if(args.mode != NTRIP1)
3412 {
3413 if(args.mode != AUTO)
3414 {
3415 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
3416 args.mode == AUTO ? ", falling back to NTRIP1" : "");
3417 }
3418 if(args.mode == HTTP)
3419 exit(1);
3420 }
3421 ++k;
3422 }
3423 else
3424 {
3425 if(chunkymode)
3426 {
3427 int stop = 0;
3428 int pos = 0;
3429 while(!stop && pos < numbytes)
3430 {
3431 switch(chunkymode)
3432 {
3433 case 1: /* reading number starts */
3434 chunksize = 0;
3435 ++chunkymode; /* no break */
3436 case 2: /* during reading number */
3437 i = buf[pos++];
3438 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
3439 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
3440 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
3441 else if(i == '\r') ++chunkymode;
3442 else if(i == ';') chunkymode = 5;
3443 else stop = 1;
3444 break;
3445 case 3: /* scanning for return */
3446 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
3447 else stop = 1;
3448 break;
3449 case 4: /* output data */
3450 i = numbytes-pos;
3451 if(i > chunksize) i = chunksize;
3452 {
3453 int z;
3454 for(z = 0; z < i && !stop; ++z)
3455 HandleByte(&Parser, (unsigned int) buf[pos+z]);
3456 }
3457 totalbytes += i;
3458 chunksize -= i;
3459 pos += i;
3460 if(!chunksize)
3461 chunkymode = 1;
3462 break;
3463 case 5:
3464 if(i == '\r') chunkymode = 3;
3465 break;
3466 }
3467 }
3468 if(stop)
3469 {
3470 RTCM3Error("Error in chunky transfer encoding\n");
3471 break;
3472 }
3473 }
3474 else
3475 {
3476 totalbytes += numbytes;
3477 {
3478 int z;
3479 for(z = 0; z < numbytes && !stop; ++z)
3480 HandleByte(&Parser, (unsigned int) buf[z]);
3481 }
3482 }
3483 if(totalbytes < 0) /* overflow */
3484 {
3485 totalbytes = 0;
3486 starttime = time(0);
3487 lastout = starttime;
3488 }
3489 }
3490 }
3491 }
3492 else
3493 {
3494 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
3495 {
3496 alarm(ALARMTIME);
3497 fwrite(buf, (size_t)numbytes, 1, stdout);
3498 }
3499 }
3500 close(sockfd);
3501 }
3502 }
3503 return 0;
3504}
3505#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.