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

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

reactivate X datatypes for Galileo

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