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

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

use extsat data for glonass conversion

  • Property svn:keywords set to Id Revision Date
File size: 110.9 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c 3653 2012-01-26 15:47:26Z 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: 3653 $";
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 {0,0,0,0,0,0,0}/*{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 {0,0,0,0,0,0,0}/*{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 {0,0,0,0,0,0,0}/*{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 {0,0,0,0,0,0,0}/*{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];
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 break;
1172 case 3:
1173 for(count = numcells; count--;)
1174 if(cellmask & (UINT64(1)<<count))
1175 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1176 for(count = numcells; count--;)
1177 if(cellmask & (UINT64(1)<<count))
1178 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1179 for(count = numcells; count--;)
1180 if(cellmask & (UINT64(1)<<count))
1181 GETBITS(ll[count], 4)
1182 break;
1183 case 4:
1184 for(count = numcells; count--;)
1185 if(cellmask & (UINT64(1)<<count))
1186 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1187 for(count = numcells; count--;)
1188 if(cellmask & (UINT64(1)<<count))
1189 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1190 for(count = numcells; count--;)
1191 if(cellmask & (UINT64(1)<<count))
1192 GETBITS(ll[count], 4)
1193 for(count = numcells; count--;)
1194 if(cellmask & (UINT64(1)<<count))
1195 GETBITS(cnr[count], 6)
1196 break;
1197 case 5:
1198 for(count = numcells; count--;)
1199 if(cellmask & (UINT64(1)<<count))
1200 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1201 for(count = numcells; count--;)
1202 if(cellmask & (UINT64(1)<<count))
1203 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1204 for(count = numcells; count--;)
1205 if(cellmask & (UINT64(1)<<count))
1206 GETBITS(ll[count], 4)
1207 for(count = numcells; count--;)
1208 if(cellmask & (UINT64(1)<<count))
1209 GETFLOAT(cnr[count], 6, 1.0)
1210 for(count = numcells; count--;)
1211 if(cellmask & (UINT64(1)<<count))
1212 GETFLOATSIGN(dop[count], 15, 0.0001)
1213 break;
1214 case 6:
1215 for(count = numcells; count--;)
1216 if(cellmask & (UINT64(1)<<count))
1217 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1218 for(count = numcells; count--;)
1219 if(cellmask & (UINT64(1)<<count))
1220 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1221 for(count = numcells; count--;)
1222 if(cellmask & (UINT64(1)<<count))
1223 GETBITS(ll[count], 10)
1224 for(count = numcells; count--;)
1225 if(cellmask & (UINT64(1)<<count))
1226 GETFLOAT(cnr[count], 10, 0.1)
1227 break;
1228 case 7:
1229 for(count = numcells; count--;)
1230 if(cellmask & (UINT64(1)<<count))
1231 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1232 for(count = numcells; count--;)
1233 if(cellmask & (UINT64(1)<<count))
1234 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1235 for(count = numcells; count--;)
1236 if(cellmask & (UINT64(1)<<count))
1237 GETBITS(ll[count], 10)
1238 for(count = numcells; count--;)
1239 if(cellmask & (UINT64(1)<<count))
1240 GETFLOAT(cnr[count], 10, 0.1)
1241 for(count = numcells; count--;)
1242 if(cellmask & (UINT64(1)<<count))
1243 GETFLOATSIGN(dop[count], 15, 0.0001)
1244 break;
1245 }
1246 i = RTCM3_MSM_NUMSAT;
1247 j = -1;
1248 for(count = numcells; count--;)
1249 {
1250 while(j >= 0 && !(sigmask&(1<<--j)))
1251 ;
1252 if(j < 0)
1253 {
1254 while(!(satmask&(UINT64(1)<<(--i)))) /* next satellite */
1255 ;
1256 j = RTCM3_MSM_NUMSIG;
1257 while(!(sigmask&(1<<--j)))
1258 ;
1259 --numsat;
1260 }
1261 if(cellmask & (UINT64(1)<<count))
1262 {
1263 struct CodeData cd = {0,0,0,0,0,0,0};
1264 double wl = 0.0;
1265 switch(sys)
1266 {
1267 case RTCM3_MSM_GPS: cd = gps[RTCM3_MSM_NUMSIG-j-1];
1268 wl = cd.wl;
1269 break;
1270 case RTCM3_MSM_GLONASS: cd = glo[RTCM3_MSM_NUMSIG-j-1];
1271 {
1272 int k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1];
1273 if(!k && extsat[count] < 14)
1274 {
1275 k = handle->Main.GLOFreq[RTCM3_MSM_NUMSAT-i-1]
1276 = 100+extsat[count]-7;
1277 }
1278 if(k)
1279 {
1280 if(cd.wl == 0.0)
1281 wl = GLO_WAVELENGTH_L1(k-100);
1282 else if(cd.wl == 1.0)
1283 wl = GLO_WAVELENGTH_L2(k-100);
1284 }
1285 }
1286 break;
1287 case RTCM3_MSM_GALILEO: cd = gal[RTCM3_MSM_NUMSIG-j-1];
1288 wl = cd.wl;
1289 break;
1290 }
1291 if(cd.lock && wl) /* lock cannot have a valid zero value */
1292 {
1293 int fullsat = RTCM3_MSM_NUMSAT-i-1, num;
1294
1295 if(sys == RTCM3_MSM_GALILEO && fullsat >= 50 && fullsat <= 51)
1296 fullsat += PRN_GIOVE_START-50;
1297 else
1298 fullsat += sys;
1299
1300 for(num = 0; num < gnss->numsats
1301 && fullsat != gnss->satellites[num]; ++num)
1302 ;
1303
1304 if(num == gnss->numsats)
1305 gnss->satellites[gnss->numsats++] = fullsat;
1306
1307 switch(type % 10)
1308 {
1309 case 1:
1310 if(psr[count] > -1.0/(1<<10))
1311 {
1312 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1313 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1314 gnss->dataflags[num] |= (1<<cd.typeR);
1315 }
1316 break;
1317 case 2:
1318 if(wl && cp[count] > -1.0/(1<<8))
1319 {
1320 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1321 +(rrmod[numsat])*LIGHTSPEED/1000.0/wl;
1322 if(handle->lastlockmsm[j][i] != ll[count])
1323 {
1324 gnss->dataflags2[num] |= cd.lock;
1325 handle->lastlockmsm[j][i] = ll[count];
1326 }
1327 gnss->dataflags[num] |= (1<<cd.typeP);
1328 }
1329 break;
1330 case 3:
1331 if(psr[count] > -1.0/(1<<10))
1332 {
1333 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1334 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1335 gnss->dataflags[num] |= (1<<cd.typeR);
1336 }
1337
1338 if(wl && cp[count] > -1.0/(1<<8))
1339 {
1340 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1341 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1342 if(handle->lastlockmsm[j][i] != ll[count])
1343 {
1344 gnss->dataflags2[num] |= cd.lock;
1345 handle->lastlockmsm[j][i] = ll[count];
1346 }
1347 gnss->dataflags[num] |= (1<<cd.typeP);
1348 }
1349 break;
1350 case 4:
1351 if(psr[count] > -1.0/(1<<10))
1352 {
1353 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1354 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1355 gnss->dataflags[num] |= (1<<cd.typeR);
1356 }
1357
1358 if(wl && cp[count] > -1.0/(1<<8))
1359 {
1360 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1361 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1362 if(handle->lastlockmsm[j][i] != ll[count])
1363 {
1364 gnss->dataflags2[num] |= cd.lock;
1365 handle->lastlockmsm[j][i] = ll[count];
1366 }
1367 gnss->dataflags[num] |= (1<<cd.typeP);
1368 }
1369
1370 gnss->measdata[num][cd.typeS] = cnr[count];
1371 gnss->dataflags[num] |= (1<<cd.typeS);
1372 break;
1373 case 5:
1374 if(psr[count] > -1.0/(1<<10))
1375 {
1376 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1377 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1378 gnss->dataflags[num] |= (1<<cd.typeR);
1379 }
1380
1381 if(wl && cp[count] > -1.0/(1<<8))
1382 {
1383 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1384 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1385 if(handle->lastlockmsm[j][i] != ll[count])
1386 {
1387 gnss->dataflags2[num] |= cd.lock;
1388 handle->lastlockmsm[j][i] = ll[count];
1389 }
1390 gnss->dataflags[num] |= (1<<cd.typeP);
1391 }
1392
1393 gnss->measdata[num][cd.typeS] = cnr[count];
1394 gnss->dataflags[num] |= (1<<cd.typeS);
1395
1396 if(dop[count] > -1.6384)
1397 {
1398 gnss->measdata[num][cd.typeD] = -(dop[count]
1399 +rdop[numsat])/wl;
1400 gnss->dataflags[num] |= (1<<cd.typeD);
1401 }
1402 break;
1403 case 6:
1404 if(psr[count] > -1.0/(1<<10))
1405 {
1406 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1407 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1408 gnss->dataflags[num] |= (1<<cd.typeR);
1409 }
1410
1411 if(wl && cp[count] > -1.0/(1<<8))
1412 {
1413 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1414 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1415 if(handle->lastlockmsm[j][i] != ll[count])
1416 {
1417 gnss->dataflags2[num] |= cd.lock;
1418 handle->lastlockmsm[j][i] = ll[count];
1419 }
1420 gnss->dataflags[num] |= (1<<cd.typeP);
1421 }
1422
1423 gnss->measdata[num][cd.typeS] = cnr[count];
1424 gnss->dataflags[num] |= (1<<cd.typeS);
1425 break;
1426 case 7:
1427 if(psr[count] > -1.0/(1<<10))
1428 {
1429 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1430 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1431 gnss->dataflags[num] |= (1<<cd.typeR);
1432 }
1433
1434 if(wl && cp[count] > -1.0/(1<<8))
1435 {
1436 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1437 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1438 if(handle->lastlockmsm[j][i] != ll[count])
1439 {
1440 gnss->dataflags2[num] |= cd.lock;
1441 handle->lastlockmsm[j][i] = ll[count];
1442 }
1443 gnss->dataflags[num] |= (1<<cd.typeP);
1444 }
1445
1446 gnss->measdata[num][cd.typeS] = cnr[count];
1447 gnss->dataflags[num] |= (1<<cd.typeS);
1448
1449 if(dop[count] > -1.6384)
1450 {
1451 gnss->measdata[num][cd.typeD] = -(dop[count]
1452 +rdop[numsat])/wl;
1453 gnss->dataflags[num] |= (1<<cd.typeD);
1454 }
1455 break;
1456 }
1457 }
1458 }
1459 }
1460 }
1461 if(!syncf && !old)
1462 {
1463 handle->Data = *gnss;
1464 memset(gnss, 0, sizeof(*gnss));
1465 }
1466 if(!syncf || old)
1467 {
1468 if(!wasnoamb) /* not RINEX compatible without */
1469 ret = 1;
1470 else
1471 ret = 2;
1472 }
1473#ifdef NO_RTCM3_MAIN
1474 else
1475 ret = type;
1476#endif /* NO_RTCM3_MAIN */
1477 }
1478 break;
1479 }
1480 }
1481 return ret;
1482}
1483
1484struct Header
1485{
1486 const char *version;
1487 const char *pgm;
1488 const char *marker;
1489 const char *markertype;
1490 const char *observer;
1491 const char *receiver;
1492 const char *antenna;
1493 const char *position;
1494 const char *antennaposition;
1495 const char *wavelength;
1496 const char *typesofobs; /* should not be modified outside */
1497 const char *typesofobsG; /* should not be modified outside */
1498 const char *typesofobsR; /* should not be modified outside */
1499 const char *typesofobsS; /* should not be modified outside */
1500 const char *typesofobsE; /* should not be modified outside */
1501 const char *timeoffirstobs; /* should not be modified outside */
1502};
1503
1504#define MAXHEADERLINES 50
1505#define MAXHEADERBUFFERSIZE 4096
1506struct HeaderData
1507{
1508 union
1509 {
1510 struct Header named;
1511 const char *unnamed[MAXHEADERLINES];
1512 } data;
1513 int numheaders;
1514};
1515
1516void converttime(struct converttimeinfo *c, int week, int tow)
1517{
1518 int i, k, doy, j; /* temporary variables */
1519 j = week*(7*24*60*60) + tow + 5*24*60*60;
1520 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
1521 j -= k;
1522 c->year = i;
1523 doy = 1+ (j / (24*60*60));
1524 j %= (24*60*60);
1525 c->hour = j / (60*60);
1526 j %= (60*60);
1527 c->minute = j / 60;
1528 c->second = j % 60;
1529 j = 0;
1530 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
1531 j += k;
1532 c->month = i;
1533 c->day = doy - j;
1534}
1535
1536#ifndef NO_RTCM3_MAIN
1537void RTCM3Error(const char *fmt, ...)
1538{
1539 va_list v;
1540 va_start(v, fmt);
1541 vfprintf(stderr, fmt, v);
1542 va_end(v);
1543}
1544#endif
1545
1546void RTCM3Text(const char *fmt, ...)
1547{
1548 va_list v;
1549 va_start(v, fmt);
1550 vprintf(fmt, v);
1551 va_end(v);
1552}
1553
1554static void fixrevision(void)
1555{
1556 if(revisionstr[0] == '$')
1557 {
1558 char *a;
1559 int i=sizeof(RTCM3TORINEX_VERSION); /* set version to 1.<revision> */
1560 strcpy(revisionstr, RTCM3TORINEX_VERSION ".");
1561 for(a = revisionstr+11; *a && *a != ' '; ++a)
1562 revisionstr[i++] = *a;
1563 revisionstr[i] = 0;
1564 }
1565}
1566
1567static int HandleRunBy(char *buffer, int buffersize, const char **u,
1568int rinex3)
1569{
1570 const char *user;
1571 time_t t;
1572 struct tm * t2;
1573
1574#ifdef NO_RTCM3_MAIN
1575 fixrevision();
1576#endif
1577
1578 user= getenv("USER");
1579 if(!user) user = "";
1580 t = time(&t);
1581 t2 = gmtime(&t);
1582 if(u) *u = user;
1583 return 1+snprintf(buffer, buffersize,
1584 rinex3 ?
1585 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
1586 "PGM / RUN BY / DATE" :
1587 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
1588 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1589 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
1590}
1591
1592#ifdef NO_RTCM3_MAIN
1593#define NUMSTARTSKIP 1
1594#else
1595#define NUMSTARTSKIP 3
1596#endif
1597
1598void HandleHeader(struct RTCM3ParserData *Parser)
1599{
1600#ifdef NO_RTCM3_MAIN
1601 int i;
1602 if(Parser->allflags == 0)
1603 Parser->allflags = ~0;
1604 if(Parser->rinex3)
1605 {
1606#define CHECKFLAGSNEW(a, b, c) \
1607 if(Parser->allflags & GNSSDF_##b##DATA) \
1608 { \
1609 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1610 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1611 ++Parser->numdatatypes##a; \
1612 }
1613
1614 CHECKFLAGSNEW(GPS, C1, C1C)
1615 CHECKFLAGSNEW(GPS, L1C, L1C)
1616 CHECKFLAGSNEW(GPS, D1C, D1C)
1617 CHECKFLAGSNEW(GPS, S1C, S1C)
1618 CHECKFLAGSNEW(GPS, P1, C1P)
1619 CHECKFLAGSNEW(GPS, L1P, L1P)
1620 CHECKFLAGSNEW(GPS, D1P, D1P)
1621 CHECKFLAGSNEW(GPS, S1P, S1P)
1622 CHECKFLAGSNEW(GPS, P2, C2P)
1623 CHECKFLAGSNEW(GPS, L2P, L2P)
1624 CHECKFLAGSNEW(GPS, D2P, D2P)
1625 CHECKFLAGSNEW(GPS, S2P, S2P)
1626 CHECKFLAGSNEW(GPS, C2, C2X)
1627 CHECKFLAGSNEW(GPS, L2C, L2X)
1628 CHECKFLAGSNEW(GPS, D2C, D2X)
1629 CHECKFLAGSNEW(GPS, S2C, S2X)
1630 CHECKFLAGSNEW(GLO, C1, C1C)
1631 CHECKFLAGSNEW(GLO, L1C, L1C)
1632 CHECKFLAGSNEW(GLO, D1C, D1C)
1633 CHECKFLAGSNEW(GLO, S1C, S1C)
1634 CHECKFLAGSNEW(GLO, P1, C1P)
1635 CHECKFLAGSNEW(GLO, L1P, L1P)
1636 CHECKFLAGSNEW(GLO, D1P, D1P)
1637 CHECKFLAGSNEW(GLO, S1P, S1P)
1638 CHECKFLAGSNEW(GLO, P2, C2P)
1639 CHECKFLAGSNEW(GLO, L2P, L2P)
1640 CHECKFLAGSNEW(GLO, D2P, D2P)
1641 CHECKFLAGSNEW(GLO, S2P, S2P)
1642 CHECKFLAGSNEW(GLO, C2, C2C)
1643 CHECKFLAGSNEW(GLO, L2C, L2C)
1644 CHECKFLAGSNEW(GLO, D2C, D2C)
1645 CHECKFLAGSNEW(GLO, S2C, S2C)
1646 }
1647 else
1648 {
1649#define CHECKFLAGS(a, b) \
1650 if(Parser->allflags & GNSSDF_##a##DATA) \
1651 { \
1652 if(data[RINEXENTRY_##b##DATA]) \
1653 { \
1654 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1655 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1656 } \
1657 else \
1658 { \
1659 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1660 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1661 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1662 } \
1663 }
1664
1665 int data[RINEXENTRY_NUMBER];
1666 for(i = 0; i < RINEXENTRY_NUMBER; ++i) data[i] = 0;
1667
1668 CHECKFLAGS(C1,C1)
1669 CHECKFLAGS(C2,C2)
1670 CHECKFLAGS(P1,P1)
1671 CHECKFLAGS(P2,P2)
1672 CHECKFLAGS(L1C,L1)
1673 CHECKFLAGS(L1P,L1)
1674 CHECKFLAGS(L2C,L2)
1675 CHECKFLAGS(L2P,L2)
1676 CHECKFLAGS(D1C,D1)
1677 CHECKFLAGS(D1P,D1)
1678 CHECKFLAGS(D2C,D2)
1679 CHECKFLAGS(D2P,D2)
1680 CHECKFLAGS(S1C,S1)
1681 CHECKFLAGS(S1P,S1)
1682 CHECKFLAGS(S2C,S2)
1683 CHECKFLAGS(S2P,S2)
1684 CHECKFLAGS(C5,C5)
1685 CHECKFLAGS(L5,L5)
1686 CHECKFLAGS(D5,D5)
1687 CHECKFLAGS(S5,S5)
1688 CHECKFLAGS(C5AB,C5AB)
1689 CHECKFLAGS(L5AB,L5AB)
1690 CHECKFLAGS(D5AB,D5AB)
1691 CHECKFLAGS(S5AB,S5AB)
1692 CHECKFLAGS(C5B,C5B)
1693 CHECKFLAGS(L5B,L5B)
1694 CHECKFLAGS(D5B,D5B)
1695 CHECKFLAGS(S5B,S5B)
1696 CHECKFLAGS(C6,C6)
1697 CHECKFLAGS(L6,L6)
1698 CHECKFLAGS(D6,D6)
1699 CHECKFLAGS(S6,S6)
1700 }
1701#else /* NO_RTCM3_MAIN */
1702 struct HeaderData hdata;
1703 char thebuffer[MAXHEADERBUFFERSIZE];
1704 char *buffer = thebuffer;
1705 size_t buffersize = sizeof(thebuffer);
1706 int i;
1707
1708 memset(&hdata, 0, sizeof(hdata));
1709
1710 hdata.data.named.version = buffer;
1711 i = 1+snprintf(buffer, buffersize,
1712 "%9.2f OBSERVATION DATA M (Mixed)"
1713 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
1714 buffer += i; buffersize -= i;
1715
1716 {
1717 const char *str;
1718 hdata.data.named.pgm = buffer;
1719 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
1720 buffer += i; buffersize -= i;
1721 hdata.data.named.observer = buffer;
1722 i = 1+snprintf(buffer, buffersize,
1723 "%-20.20s "
1724 "OBSERVER / AGENCY", str);
1725 buffer += i; buffersize -= i;
1726 }
1727
1728 hdata.data.named.marker =
1729 "RTCM3TORINEX "
1730 "MARKER NAME";
1731
1732 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
1733 "GEODETIC "
1734 "MARKER TYPE";
1735
1736 hdata.data.named.receiver =
1737 " "
1738 "REC # / TYPE / VERS";
1739
1740 hdata.data.named.antenna =
1741 " "
1742 "ANT # / TYPE";
1743
1744 hdata.data.named.position =
1745 " .0000 .0000 .0000 "
1746 "APPROX POSITION XYZ";
1747
1748 hdata.data.named.antennaposition =
1749 " .0000 .0000 .0000 "
1750 "ANTENNA: DELTA H/E/N";
1751
1752 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
1753 " 1 1 "
1754 "WAVELENGTH FACT L1/2";
1755
1756 if(Parser->rinex3)
1757 {
1758#define CHECKFLAGSNEW(a, b, c) \
1759 if(flags & GNSSDF_##b##DATA) \
1760 { \
1761 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1762 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1763 ++Parser->numdatatypes##a; \
1764 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " %-3s", #c); \
1765 tbufferpos += 4; \
1766 }
1767
1768 int flags = Parser->startflags;
1769 char tbuffer[6*RINEXENTRY_NUMBER+1];
1770 int tbufferpos = 0;
1771 for(i = 0; i < Parser->Data.numsats; ++i)
1772 flags |= Parser->Data.dataflags[i];
1773
1774 CHECKFLAGSNEW(GPS, C1, C1C)
1775 CHECKFLAGSNEW(GPS, L1C, L1C)
1776 CHECKFLAGSNEW(GPS, D1C, D1C)
1777 CHECKFLAGSNEW(GPS, S1C, S1C)
1778 CHECKFLAGSNEW(GPS, P1, C1W)
1779 CHECKFLAGSNEW(GPS, L1P, L1W)
1780 CHECKFLAGSNEW(GPS, D1P, D1W)
1781 CHECKFLAGSNEW(GPS, S1P, S1W)
1782
1783 hdata.data.named.typesofobsS = buffer;
1784 i = 1+snprintf(buffer, buffersize,
1785 "S %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1786 buffer += i; buffersize -= i;
1787
1788 CHECKFLAGSNEW(GPS, P2, C2P)
1789 CHECKFLAGSNEW(GPS, L2P, L2P)
1790 CHECKFLAGSNEW(GPS, D2P, D2P)
1791 CHECKFLAGSNEW(GPS, S2P, S2P)
1792 CHECKFLAGSNEW(GPS, C2, C2X)
1793 CHECKFLAGSNEW(GPS, L2C, L2X)
1794 CHECKFLAGSNEW(GPS, D2C, D2X)
1795 CHECKFLAGSNEW(GPS, S2C, S2X)
1796 CHECKFLAGSNEW(GPS, C5, C5)
1797 CHECKFLAGSNEW(GPS, L5, L5)
1798 CHECKFLAGSNEW(GPS, D5, D5)
1799 CHECKFLAGSNEW(GPS, S5, S5)
1800
1801 hdata.data.named.typesofobsG = buffer;
1802 i = 1+snprintf(buffer, buffersize,
1803 "G %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1804 if(Parser->numdatatypesGPS>13)
1805 {
1806 i += snprintf(buffer+i-1, buffersize,
1807 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1808 }
1809 buffer += i; buffersize -= i;
1810
1811 tbufferpos = 0;
1812
1813 CHECKFLAGSNEW(GLO, C1, C1C)
1814 CHECKFLAGSNEW(GLO, L1C, L1C)
1815 CHECKFLAGSNEW(GLO, D1C, D1C)
1816 CHECKFLAGSNEW(GLO, S1C, S1C)
1817 CHECKFLAGSNEW(GLO, P1, C1P)
1818 CHECKFLAGSNEW(GLO, L1P, L1P)
1819 CHECKFLAGSNEW(GLO, D1P, D1P)
1820 CHECKFLAGSNEW(GLO, S1P, S1P)
1821 CHECKFLAGSNEW(GLO, P2, C2P)
1822 CHECKFLAGSNEW(GLO, L2P, L2P)
1823 CHECKFLAGSNEW(GLO, D2P, D2P)
1824 CHECKFLAGSNEW(GLO, S2P, S2P)
1825 CHECKFLAGSNEW(GLO, C2, C2C)
1826 CHECKFLAGSNEW(GLO, L2C, L2C)
1827 CHECKFLAGSNEW(GLO, D2C, D2C)
1828 CHECKFLAGSNEW(GLO, S2C, S2C)
1829
1830 hdata.data.named.typesofobsR = buffer;
1831 i = 1+snprintf(buffer, buffersize,
1832 "R %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGLO, tbuffer);
1833 if(Parser->numdatatypesGLO>13)
1834 {
1835 i += snprintf(buffer+i-1, buffersize,
1836 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1837 }
1838 buffer += i; buffersize -= i;
1839
1840 tbufferpos = 0;
1841
1842 CHECKFLAGSNEW(GAL, C1, C1)
1843 CHECKFLAGSNEW(GAL, L1C, L1)
1844 CHECKFLAGSNEW(GAL, D1C, D1)
1845 CHECKFLAGSNEW(GAL, S1C, S1)
1846 CHECKFLAGSNEW(GAL, C6, C6)
1847 CHECKFLAGSNEW(GAL, L6, L6)
1848 CHECKFLAGSNEW(GAL, D6, D6)
1849 CHECKFLAGSNEW(GAL, S6, S6)
1850 CHECKFLAGSNEW(GAL, C5, C5)
1851 CHECKFLAGSNEW(GAL, L5, L5)
1852 CHECKFLAGSNEW(GAL, D5, D5)
1853 CHECKFLAGSNEW(GAL, S5, S5)
1854 CHECKFLAGSNEW(GAL, C5B, C7)
1855 CHECKFLAGSNEW(GAL, L5B, L7)
1856 CHECKFLAGSNEW(GAL, D5B, D7)
1857 CHECKFLAGSNEW(GAL, S5B, S7)
1858 CHECKFLAGSNEW(GAL, C5AB, C8)
1859 CHECKFLAGSNEW(GAL, L5AB, L8)
1860 CHECKFLAGSNEW(GAL, D5AB, D8)
1861 CHECKFLAGSNEW(GAL, S5AB, S8)
1862
1863 hdata.data.named.typesofobsE = buffer;
1864 i = 1+snprintf(buffer, buffersize,
1865 "E %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGAL, tbuffer);
1866 if(Parser->numdatatypesGAL>13)
1867 {
1868 i += snprintf(buffer+i-1, buffersize,
1869 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1870 }
1871 buffer += i; buffersize -= i;
1872 }
1873 else
1874 {
1875#define CHECKFLAGS(a, b) \
1876 if(flags & GNSSDF_##a##DATA) \
1877 { \
1878 if(data[RINEXENTRY_##b##DATA]) \
1879 { \
1880 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1881 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1882 } \
1883 else \
1884 { \
1885 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1886 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1887 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1888 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
1889 tbufferpos += 6; \
1890 } \
1891 }
1892
1893 int flags = Parser->startflags;
1894 int data[RINEXENTRY_NUMBER];
1895 char tbuffer[6*RINEXENTRY_NUMBER+1];
1896 int tbufferpos = 0;
1897 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
1898 data[i] = 0;
1899 for(i = 0; i < Parser->Data.numsats; ++i)
1900 flags |= Parser->Data.dataflags[i];
1901
1902 CHECKFLAGS(C1,C1)
1903 CHECKFLAGS(C2,C2)
1904 CHECKFLAGS(P1,P1)
1905 CHECKFLAGS(P2,P2)
1906 CHECKFLAGS(L1C,L1)
1907 CHECKFLAGS(L1P,L1)
1908 CHECKFLAGS(L2C,L2)
1909 CHECKFLAGS(L2P,L2)
1910 CHECKFLAGS(D1C,D1)
1911 CHECKFLAGS(D1P,D1)
1912 CHECKFLAGS(D2C,D2)
1913 CHECKFLAGS(D2P,D2)
1914 CHECKFLAGS(S1C,S1)
1915 CHECKFLAGS(S1P,S1)
1916 CHECKFLAGS(S2C,S2)
1917 CHECKFLAGS(S2P,S2)
1918 CHECKFLAGS(C5,C5)
1919 CHECKFLAGS(L5,L5)
1920 CHECKFLAGS(D5,D5)
1921 CHECKFLAGS(S5,S5)
1922 CHECKFLAGS(C5AB,C5AB)
1923 CHECKFLAGS(L5AB,L5AB)
1924 CHECKFLAGS(D5AB,D5AB)
1925 CHECKFLAGS(S5AB,S5AB)
1926 CHECKFLAGS(C5B,C5B)
1927 CHECKFLAGS(L5B,L5B)
1928 CHECKFLAGS(D5B,D5B)
1929 CHECKFLAGS(S5B,S5B)
1930 CHECKFLAGS(C6,C6)
1931 CHECKFLAGS(L6,L6)
1932 CHECKFLAGS(D6,D6)
1933 CHECKFLAGS(S6,S6)
1934
1935 hdata.data.named.typesofobs = buffer;
1936 i = 1+snprintf(buffer, buffersize,
1937 "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer);
1938 if(Parser->numdatatypesGPS>9)
1939 {
1940 i += snprintf(buffer+i-1, buffersize,
1941 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
1942 }
1943 buffer += i; buffersize -= i;
1944 }
1945
1946 {
1947 struct converttimeinfo cti;
1948 converttime(&cti, Parser->Data.week,
1949 (int)floor(Parser->Data.timeofweek/1000.0));
1950 hdata.data.named.timeoffirstobs = buffer;
1951 i = 1+snprintf(buffer, buffersize,
1952 " %4d %2d %2d %2d %2d %10.7f GPS "
1953 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
1954 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
1955
1956 buffer += i; buffersize -= i;
1957 }
1958
1959 hdata.numheaders = 15;
1960
1961 if(Parser->headerfile)
1962 {
1963 FILE *fh;
1964 if((fh = fopen(Parser->headerfile, "r")))
1965 {
1966 size_t siz;
1967 char *lastblockstart;
1968 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
1969 {
1970 buffer[siz] = '\n';
1971 if(siz == buffersize)
1972 {
1973 RTCM3Error("Header file is too large. Only %d bytes read.",
1974 (int)siz);
1975 }
1976 /* scan the file line by line and enter the entries in the list */
1977 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
1978 /* overwrites entries, except for comments */
1979 lastblockstart = buffer;
1980 for(i = 0; i < (int)siz; ++i)
1981 {
1982 if(buffer[i] == '\n')
1983 { /* we found a line */
1984 char *end;
1985 while(buffer[i+1] == '\r')
1986 ++i; /* skip \r in case there are any */
1987 end = buffer+i;
1988 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
1989 *(end--) = 0;
1990 if(end-lastblockstart < 60+5) /* short line */
1991 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
1992 else
1993 {
1994 int pos;
1995 if(!strcmp("COMMENT", lastblockstart+60))
1996 pos = hdata.numheaders;
1997 else
1998 {
1999 for(pos = 0; pos < hdata.numheaders; ++pos)
2000 {
2001 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
2002 break;
2003 }
2004 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
2005 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
2006 {
2007 RTCM3Error("Overwriting header '%s' is dangerous.\n",
2008 lastblockstart+60);
2009 }
2010 }
2011 if(pos >= MAXHEADERLINES)
2012 {
2013 RTCM3Error("Maximum number of header lines of %d reached.\n",
2014 MAXHEADERLINES);
2015 }
2016 else if(!strcmp("END OF HEADER", lastblockstart+60))
2017 {
2018 RTCM3Error("End of header ignored.\n");
2019 }
2020 else
2021 {
2022 hdata.data.unnamed[pos] = lastblockstart;
2023 if(pos == hdata.numheaders)
2024 ++hdata.numheaders;
2025 }
2026 }
2027 lastblockstart = buffer+i+1;
2028 }
2029 }
2030 }
2031 else
2032 {
2033 RTCM3Error("Could not read data from headerfile '%s'.\n",
2034 Parser->headerfile);
2035 }
2036 fclose(fh);
2037 }
2038 else
2039 {
2040 RTCM3Error("Could not open header datafile '%s'.\n",
2041 Parser->headerfile);
2042 }
2043 }
2044
2045 for(i = 0; i < hdata.numheaders; ++i)
2046 {
2047 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
2048 RTCM3Text("%s\n", hdata.data.unnamed[i]);
2049 }
2050 RTCM3Text(" "
2051 "END OF HEADER\n");
2052#endif
2053}
2054
2055static void ConvLine(FILE *file, const char *fmt, ...)
2056{
2057 char buffer[100], *b;
2058 va_list v;
2059 va_start(v, fmt);
2060 vsnprintf(buffer, sizeof(buffer), fmt, v);
2061 for(b = buffer; *b; ++b)
2062 {
2063 if(*b == 'e') *b = 'D';
2064 }
2065 fprintf(file, "%s", buffer);
2066 va_end(v);
2067}
2068
2069void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
2070{
2071 Parser->Message[Parser->MessageSize++] = byte;
2072 if(Parser->MessageSize >= Parser->NeedBytes)
2073 {
2074 int r;
2075 while((r = RTCM3Parser(Parser)))
2076 {
2077 if(r == 1020 || r == 1019)
2078 {
2079 FILE *file = 0;
2080
2081 if(Parser->rinex3 && !(file = Parser->gpsfile))
2082 {
2083 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
2084 if(n)
2085 {
2086 if(!(Parser->gpsfile = fopen(n, "w")))
2087 {
2088 RTCM3Error("Could not open ephemeris output file.\n");
2089 }
2090 else
2091 {
2092 char buffer[100];
2093 fprintf(Parser->gpsfile,
2094 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
2095 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2096 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2097 }
2098 Parser->gpsephemeris = 0;
2099 Parser->glonassephemeris = 0;
2100 file = Parser->gpsfile;
2101 }
2102 }
2103 else
2104 {
2105 if(r == 1020)
2106 {
2107 if(Parser->glonassephemeris)
2108 {
2109 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
2110 {
2111 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
2112 }
2113 else
2114 {
2115 char buffer[100];
2116 fprintf(Parser->glonassfile,
2117 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
2118 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2119 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2120 }
2121 Parser->glonassephemeris = 0;
2122 }
2123 file = Parser->glonassfile;
2124 }
2125 else if(r == 1019)
2126 {
2127 if(Parser->gpsephemeris)
2128 {
2129 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2130 {
2131 RTCM3Error("Could not open GPS ephemeris output file.\n");
2132 }
2133 else
2134 {
2135 char buffer[100];
2136 fprintf(Parser->gpsfile,
2137 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
2138 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2139 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2140 }
2141 Parser->gpsephemeris = 0;
2142 }
2143 file = Parser->gpsfile;
2144 }
2145 }
2146 if(file)
2147 {
2148 if(r == 1020)
2149 {
2150 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2151 int w = e->GPSWeek, tow = e->GPSTOW, i;
2152 struct converttimeinfo cti;
2153
2154 updatetime(&w, &tow, e->tb*1000, 1); /* Moscow - > UTC */
2155 converttime(&cti, w, tow);
2156
2157 i = e->tk-3*60*60; if(i < 0) i += 86400;
2158
2159 if(Parser->rinex3)
2160 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2161 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2162 cti.second, -e->tau, e->gamma, (double) i);
2163 else
2164 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2165 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2166 (double) cti.second, -e->tau, e->gamma, (double) i);
2167 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
2168 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2169 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
2170 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2171 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
2172 e->z_velocity, e->z_acceleration, (double) e->E);
2173 }
2174 else /* if(r == 1019) */
2175 {
2176 struct gpsephemeris *e = &Parser->ephemerisGPS;
2177 double d; /* temporary variable */
2178 unsigned long int i; /* temporary variable */
2179 struct converttimeinfo cti;
2180 converttime(&cti, e->GPSweek, e->TOC);
2181
2182 if(Parser->rinex3)
2183 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2184 e->satellite, cti.year, cti.month, cti.day, cti.hour,
2185 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2186 e->clock_driftrate);
2187 else
2188 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2189 e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
2190 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2191 e->clock_driftrate);
2192 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
2193 e->Crs, e->Delta_n, e->M0);
2194 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
2195 e->e, e->Cus, e->sqrt_A);
2196 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n",
2197 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2198 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0,
2199 e->Crc, e->omega, e->OMEGADOT);
2200 d = 0;
2201 i = e->flags;
2202 if(i & GPSEPHF_L2CACODE)
2203 d += 2.0;
2204 if(i & GPSEPHF_L2PCODE)
2205 d += 1.0;
2206 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
2207 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2208 if(e->URAindex <= 6) /* URA index */
2209 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2210 else
2211 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2212 /* 15 indicates not to use satellite. We can't handle this special
2213 case, so we create a high "non"-accuracy value. */
2214 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d,
2215 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2216
2217 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0);
2218 /* TOW */
2219 }
2220 }
2221 }
2222 else if (r == 1 || r == 2)
2223 {
2224 int i, j, o;
2225 struct converttimeinfo cti;
2226
2227 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
2228 {
2229 ++Parser->init;
2230
2231 if(Parser->init == NUMSTARTSKIP)
2232 HandleHeader(Parser);
2233 else
2234 {
2235 for(i = 0; i < Parser->Data.numsats; ++i)
2236 Parser->startflags |= Parser->Data.dataflags[i];
2237 continue;
2238 }
2239 }
2240 if(r == 2 && !Parser->validwarning)
2241 {
2242 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2243 " COMMENT\n");
2244 Parser->validwarning = 1;
2245 }
2246
2247 converttime(&cti, Parser->Data.week,
2248 (int)floor(Parser->Data.timeofweek/1000.0));
2249 if(Parser->rinex3)
2250 {
2251 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n",
2252 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2253 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2254 for(i = 0; i < Parser->Data.numsats; ++i)
2255 {
2256 int glo = 0, gal = 0;
2257 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2258 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2259 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2260 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2261 {
2262 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
2263 glo = 1;
2264 }
2265 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2266 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2267 {
2268 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
2269 gal = 1;
2270 }
2271 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2272 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2273 {
2274 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2275 gal = 1;
2276 }
2277 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2278 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2279 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
2280 else
2281 RTCM3Text("%3d", Parser->Data.satellites[i]);
2282
2283 if(glo)
2284 {
2285 for(j = 0; j < Parser->numdatatypesGLO; ++j)
2286 {
2287 int df = Parser->dataflagGLO[j];
2288 int pos = Parser->dataposGLO[j];
2289 if((Parser->Data.dataflags[i] & df)
2290 && !isnan(Parser->Data.measdata[i][pos])
2291 && !isinf(Parser->Data.measdata[i][pos]))
2292 {
2293 char lli = ' ';
2294 char snr = ' ';
2295 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2296 {
2297 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2298 lli = '1';
2299 snr = '0'+Parser->Data.snrL1[i];
2300 }
2301 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2302 {
2303 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2304 lli = '1';
2305 snr = '0'+Parser->Data.snrL2[i];
2306 }
2307 RTCM3Text("%14.3f%c%c",
2308 Parser->Data.measdata[i][pos],lli,snr);
2309 }
2310 else
2311 { /* no or illegal data */
2312 RTCM3Text(" ");
2313 }
2314 }
2315 }
2316 else if(gal)
2317 {
2318 for(j = 0; j < Parser->numdatatypesGAL; ++j)
2319 {
2320 int df = Parser->dataflagGAL[j];
2321 int pos = Parser->dataposGAL[j];
2322 if((Parser->Data.dataflags[i] & df)
2323 && !isnan(Parser->Data.measdata[i][pos])
2324 && !isinf(Parser->Data.measdata[i][pos]))
2325 {
2326 char lli = ' ';
2327 char snr = ' ';
2328 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2329 {
2330 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2331 lli = '1';
2332 snr = '0'+Parser->Data.snrL1[i];
2333 }
2334 if(df & GNSSDF_L6DATA)
2335 {
2336 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
2337 lli = '1';
2338 snr = ' ';
2339 }
2340 if(df & GNSSDF_L5DATA)
2341 {
2342 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2343 lli = '1';
2344 snr = ' ';
2345 }
2346 if(df & GNSSDF_L5BDATA)
2347 {
2348 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
2349 lli = '1';
2350 snr = ' ';
2351 }
2352 if(df & GNSSDF_L5ABDATA)
2353 {
2354 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
2355 lli = '1';
2356 snr = ' ';
2357 }
2358 RTCM3Text("%14.3f%c%c",
2359 Parser->Data.measdata[i][pos],lli,snr);
2360 }
2361 else
2362 { /* no or illegal data */
2363 RTCM3Text(" ");
2364 }
2365 }
2366 }
2367 else
2368 {
2369 for(j = 0; j < Parser->numdatatypesGPS; ++j)
2370 {
2371 int df = Parser->dataflagGPS[j];
2372 int pos = Parser->dataposGPS[j];
2373 if((Parser->Data.dataflags[i] & df)
2374 && !isnan(Parser->Data.measdata[i][pos])
2375 && !isinf(Parser->Data.measdata[i][pos]))
2376 {
2377 char lli = ' ';
2378 char snr = ' ';
2379 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2380 {
2381 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2382 lli = '1';
2383 snr = '0'+Parser->Data.snrL1[i];
2384 }
2385 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2386 {
2387 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2388 lli = '1';
2389 snr = '0'+Parser->Data.snrL2[i];
2390 }
2391 if(df & GNSSDF_L5DATA)
2392 {
2393 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2394 lli = '1';
2395 snr = ' ';
2396 }
2397 RTCM3Text("%14.3f%c%c",
2398 Parser->Data.measdata[i][pos],lli,snr);
2399 }
2400 else
2401 { /* no or illegal data */
2402 RTCM3Text(" ");
2403 }
2404 }
2405 }
2406 RTCM3Text("\n");
2407 }
2408 }
2409 else
2410 {
2411 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
2412 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
2413 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2414 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
2415 {
2416 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2417 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2418 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2419 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2420 RTCM3Text("R%02d", Parser->Data.satellites[i]
2421 - (PRN_GLONASS_START-1));
2422 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2423 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2424 RTCM3Text("S%02d", Parser->Data.satellites[i]
2425 - PRN_WAAS_START+20);
2426 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2427 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2428 RTCM3Text("E%02d", Parser->Data.satellites[i]
2429 - (PRN_GALILEO_START-1));
2430 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2431 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2432 RTCM3Text("E%02d", Parser->Data.satellites[i]
2433 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2434 else
2435 RTCM3Text("%3d", Parser->Data.satellites[i]);
2436 }
2437 RTCM3Text("\n");
2438 o = 12;
2439 j = Parser->Data.numsats - 12;
2440 while(j > 0)
2441 {
2442 RTCM3Text(" ");
2443 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
2444 {
2445 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2446 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2447 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2448 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2449 RTCM3Text("R%02d", Parser->Data.satellites[i]
2450 - (PRN_GLONASS_START-1));
2451 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2452 && Parser->Data.satellites[i] <= PRN_WAAS_END)
2453 RTCM3Text("S%02d", Parser->Data.satellites[i]
2454 - PRN_WAAS_START+20);
2455 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2456 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2457 RTCM3Text("E%02d", Parser->Data.satellites[i]
2458 - (PRN_GALILEO_START-1));
2459 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2460 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2461 RTCM3Text("E%02d", Parser->Data.satellites[i]
2462 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2463 else
2464 RTCM3Text("%3d", Parser->Data.satellites[i]);
2465 }
2466 RTCM3Text("\n");
2467 j -= 12;
2468 o += 12;
2469 }
2470 for(i = 0; i < Parser->Data.numsats; ++i)
2471 {
2472 for(j = 0; j < Parser->numdatatypesGPS; ++j)
2473 {
2474 int v = 0;
2475 int df = Parser->dataflag[j];
2476 int pos = Parser->datapos[j];
2477 if((Parser->Data.dataflags[i] & df)
2478 && !isnan(Parser->Data.measdata[i][pos])
2479 && !isinf(Parser->Data.measdata[i][pos]))
2480 {
2481 v = 1;
2482 }
2483 else
2484 {
2485 df = Parser->dataflagGPS[j];
2486 pos = Parser->dataposGPS[j];
2487
2488 if((Parser->Data.dataflags[i] & df)
2489 && !isnan(Parser->Data.measdata[i][pos])
2490 && !isinf(Parser->Data.measdata[i][pos]))
2491 {
2492 v = 1;
2493 }
2494 }
2495
2496 if(!v)
2497 { /* no or illegal data */
2498 RTCM3Text(" ");
2499 }
2500 else
2501 {
2502 char lli = ' ';
2503 char snr = ' ';
2504 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2505 {
2506 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2507 lli = '1';
2508 snr = '0'+Parser->Data.snrL1[i];
2509 }
2510 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2511 {
2512 if(Parser->Data.dataflags2[i]
2513 & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
2514 {
2515 lli = '0';
2516 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2517 lli += 1;
2518 if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
2519 lli += 4;
2520 }
2521 snr = '0'+Parser->Data.snrL2[i];
2522 }
2523 if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
2524 & GNSSDF2_XCORRL2))
2525 lli = '4';
2526 RTCM3Text("%14.3f%c%c",
2527 Parser->Data.measdata[i][pos],lli,snr);
2528 }
2529 if(j%5 == 4 || j == Parser->numdatatypesGPS-1)
2530 RTCM3Text("\n");
2531 }
2532 }
2533 }
2534 }
2535 }
2536 }
2537}
2538
2539#ifndef NO_RTCM3_MAIN
2540static char datestr[] = "$Date: 2012-01-26 15:47:26 +0000 (Thu, 26 Jan 2012) $";
2541
2542/* The string, which is send as agent in HTTP request */
2543#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
2544
2545#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
2546
2547static const char encodingTable [64] = {
2548 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
2549 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
2550 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
2551 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
2552};
2553
2554/* does not buffer overrun, but breaks directly after an error */
2555/* returns the number of required bytes */
2556static int encode(char *buf, int size, const char *user, const char *pwd)
2557{
2558 unsigned char inbuf[3];
2559 char *out = buf;
2560 int i, sep = 0, fill = 0, bytes = 0;
2561
2562 while(*user || *pwd)
2563 {
2564 i = 0;
2565 while(i < 3 && *user) inbuf[i++] = *(user++);
2566 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
2567 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
2568 while(i < 3) {inbuf[i++] = 0; ++fill; }
2569 if(out-buf < size-1)
2570 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
2571 if(out-buf < size-1)
2572 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
2573 | ((inbuf [1] & 0xF0) >> 4)];
2574 if(out-buf < size-1)
2575 {
2576 if(fill == 2)
2577 *(out++) = '=';
2578 else
2579 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
2580 | ((inbuf [2] & 0xC0) >> 6)];
2581 }
2582 if(out-buf < size-1)
2583 {
2584 if(fill >= 1)
2585 *(out++) = '=';
2586 else
2587 *(out++) = encodingTable[inbuf [2] & 0x3F];
2588 }
2589 bytes += 4;
2590 }
2591 if(out-buf < size)
2592 *out = 0;
2593 return bytes;
2594}
2595
2596static int stop = 0;
2597
2598struct Args
2599{
2600 const char *server;
2601 const char *port;
2602 int mode;
2603 int timeout;
2604 int rinex3;
2605 const char *user;
2606 const char *password;
2607 const char *proxyhost;
2608 const char *proxyport;
2609 const char *nmea;
2610 const char *data;
2611 const char *headerfile;
2612 const char *gpsephemeris;
2613 const char *glonassephemeris;
2614};
2615
2616/* option parsing */
2617#ifdef NO_LONG_OPTS
2618#define LONG_OPT(a)
2619#else
2620#define LONG_OPT(a) a
2621static struct option opts[] = {
2622{ "data", required_argument, 0, 'd'},
2623{ "server", required_argument, 0, 's'},
2624{ "password", required_argument, 0, 'p'},
2625{ "port", required_argument, 0, 'r'},
2626{ "timeout", required_argument, 0, 't'},
2627{ "header", required_argument, 0, 'f'},
2628{ "user", required_argument, 0, 'u'},
2629{ "gpsephemeris", required_argument, 0, 'E'},
2630{ "glonassephemeris", required_argument, 0, 'G'},
2631{ "rinex3", no_argument, 0, '3'},
2632{ "proxyport", required_argument, 0, 'R'},
2633{ "proxyhost", required_argument, 0, 'S'},
2634{ "nmea", required_argument, 0, 'n'},
2635{ "mode", required_argument, 0, 'M'},
2636{ "help", no_argument, 0, 'h'},
2637{0,0,0,0}};
2638#endif
2639#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
2640
2641enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
2642
2643static const char *geturl(const char *url, struct Args *args)
2644{
2645 static char buf[1000];
2646 static char *Buffer = buf;
2647 static char *Bufend = buf+sizeof(buf);
2648
2649 if(strncmp("ntrip:", url, 6))
2650 return "URL must start with 'ntrip:'.";
2651 url += 6; /* skip ntrip: */
2652
2653 if(*url != '@' && *url != '/')
2654 {
2655 /* scan for mountpoint */
2656 args->data = Buffer;
2657 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
2658 *(Buffer++) = *(url++);
2659 if(Buffer == args->data)
2660 return "Mountpoint required.";
2661 else if(Buffer >= Bufend-1)
2662 return "Parsing buffer too short.";
2663 *(Buffer++) = 0;
2664 }
2665
2666 if(*url == '/') /* username and password */
2667 {
2668 ++url;
2669 args->user = Buffer;
2670 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
2671 *(Buffer++) = *(url++);
2672 if(Buffer == args->user)
2673 return "Username cannot be empty.";
2674 else if(Buffer >= Bufend-1)
2675 return "Parsing buffer too short.";
2676 *(Buffer++) = 0;
2677
2678 if(*url == ':') ++url;
2679
2680 args->password = Buffer;
2681 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2682 *(Buffer++) = *(url++);
2683 if(Buffer == args->password)
2684 return "Password cannot be empty.";
2685 else if(Buffer >= Bufend-1)
2686 return "Parsing buffer too short.";
2687 *(Buffer++) = 0;
2688 }
2689
2690 if(*url == '@') /* server */
2691 {
2692 ++url;
2693 if(*url != '@' && *url != ':')
2694 {
2695 args->server = Buffer;
2696 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
2697 *(Buffer++) = *(url++);
2698 if(Buffer == args->server)
2699 return "Servername cannot be empty.";
2700 else if(Buffer >= Bufend-1)
2701 return "Parsing buffer too short.";
2702 *(Buffer++) = 0;
2703 }
2704
2705 if(*url == ':')
2706 {
2707 ++url;
2708 args->port = Buffer;
2709 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2710 *(Buffer++) = *(url++);
2711 if(Buffer == args->port)
2712 return "Port cannot be empty.";
2713 else if(Buffer >= Bufend-1)
2714 return "Parsing buffer too short.";
2715 *(Buffer++) = 0;
2716 }
2717
2718 if(*url == '@') /* proxy */
2719 {
2720 ++url;
2721 args->proxyhost = Buffer;
2722 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
2723 *(Buffer++) = *(url++);
2724 if(Buffer == args->proxyhost)
2725 return "Proxy servername cannot be empty.";
2726 else if(Buffer >= Bufend-1)
2727 return "Parsing buffer too short.";
2728 *(Buffer++) = 0;
2729
2730 if(*url == ':')
2731 {
2732 ++url;
2733 args->proxyport = Buffer;
2734 while(*url && *url != ';' && Buffer != Bufend)
2735 *(Buffer++) = *(url++);
2736 if(Buffer == args->proxyport)
2737 return "Proxy port cannot be empty.";
2738 else if(Buffer >= Bufend-1)
2739 return "Parsing buffer too short.";
2740 *(Buffer++) = 0;
2741 }
2742 }
2743 }
2744 if(*url == ';') /* NMEA */
2745 {
2746 args->nmea = ++url;
2747 while(*url)
2748 ++url;
2749 }
2750
2751 return *url ? "Garbage at end of server string." : 0;
2752}
2753
2754static int getargs(int argc, char **argv, struct Args *args)
2755{
2756 int res = 1;
2757 int getoptr;
2758 int help = 0;
2759 char *t;
2760
2761 args->server = "www.euref-ip.net";
2762 args->port = "2101";
2763 args->timeout = 60;
2764 args->user = "";
2765 args->password = "";
2766 args->data = 0;
2767 args->headerfile = 0;
2768 args->gpsephemeris = 0;
2769 args->glonassephemeris = 0;
2770 args->rinex3 = 0;
2771 args->nmea = 0;
2772 args->proxyhost = 0;
2773 args->proxyport = "2101";
2774 args->mode = AUTO;
2775 help = 0;
2776
2777 do
2778 {
2779
2780#ifdef NO_LONG_OPTS
2781 switch((getoptr = getopt(argc, argv, ARGOPT)))
2782#else
2783 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
2784#endif
2785 {
2786 case 's': args->server = optarg; break;
2787 case 'u': args->user = optarg; break;
2788 case 'p': args->password = optarg; break;
2789 case 'd': args->data = optarg; break;
2790 case 'f': args->headerfile = optarg; break;
2791 case 'E': args->gpsephemeris = optarg; break;
2792 case 'G': args->glonassephemeris = optarg; break;
2793 case 'r': args->port = optarg; break;
2794 case '3': args->rinex3 = 1; break;
2795 case 'S': args->proxyhost = optarg; break;
2796 case 'n': args->nmea = optarg; break;
2797 case 'R': args->proxyport = optarg; break;
2798 case 'h': help=1; break;
2799 case 'M':
2800 args->mode = 0;
2801 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
2802 args->mode = NTRIP1;
2803 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
2804 args->mode = HTTP;
2805 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
2806 args->mode = RTSP;
2807 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
2808 args->mode = AUTO;
2809 else args->mode = atoi(optarg);
2810 if((args->mode == 0) || (args->mode >= END))
2811 {
2812 fprintf(stderr, "Mode %s unknown\n", optarg);
2813 res = 0;
2814 }
2815 break;
2816 case 't':
2817 args->timeout = strtoul(optarg, &t, 10);
2818 if((t && *t) || args->timeout < 0)
2819 res = 0;
2820 break;
2821
2822 case 1:
2823 {
2824 const char *err;
2825 if((err = geturl(optarg, args)))
2826 {
2827 RTCM3Error("%s\n\n", err);
2828 res = 0;
2829 }
2830 }
2831 break;
2832 case -1: break;
2833 }
2834 } while(getoptr != -1 || !res);
2835
2836 datestr[0] = datestr[7];
2837 datestr[1] = datestr[8];
2838 datestr[2] = datestr[9];
2839 datestr[3] = datestr[10];
2840 datestr[5] = datestr[12];
2841 datestr[6] = datestr[13];
2842 datestr[8] = datestr[15];
2843 datestr[9] = datestr[16];
2844 datestr[4] = datestr[7] = '-';
2845 datestr[10] = 0;
2846
2847 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
2848 {
2849 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
2850 "Please specify only one navigation file.\n");
2851 res = 0;
2852 }
2853 else if(!res || help)
2854 {
2855 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
2856 "\nUsage: %s -s server -u user ...\n"
2857 " -d " LONG_OPT("--data ") "the requested data set\n"
2858 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
2859 " -s " LONG_OPT("--server ") "the server name or address\n"
2860 " -p " LONG_OPT("--password ") "the login password\n"
2861 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
2862 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
2863 " -u " LONG_OPT("--user ") "the user name\n"
2864 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
2865 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
2866 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
2867 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
2868 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
2869 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
2870 " -M " LONG_OPT("--mode ") "mode for data request\n"
2871 " Valid modes are:\n"
2872 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
2873 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
2874 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
2875 " 4, a, auto automatic detection (default)\n"
2876 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
2877 , revisionstr, datestr, argv[0], argv[0]);
2878 exit(1);
2879 }
2880 return res;
2881}
2882
2883/* let the output complete a block if necessary */
2884static void signalhandler(int sig)
2885{
2886 if(!stop)
2887 {
2888 RTCM3Error("Stop signal number %d received. "
2889 "Trying to terminate gentle.\n", sig);
2890 stop = 1;
2891 alarm(1);
2892 }
2893}
2894
2895#ifndef WINDOWSVERSION
2896static void WaitMicro(int mic)
2897{
2898 struct timeval tv;
2899 tv.tv_sec = mic/1000000;
2900 tv.tv_usec = mic%1000000;
2901#ifdef DEBUG
2902 fprintf(stderr, "Waiting %d micro seconds\n", mic);
2903#endif
2904 select(0, 0, 0, 0, &tv);
2905}
2906#else /* WINDOWSVERSION */
2907void WaitMicro(int mic)
2908{
2909 Sleep(mic/1000);
2910}
2911#endif /* WINDOWSVERSION */
2912
2913#define ALARMTIME (2*60)
2914
2915/* for some reason we had to abort hard (maybe waiting for data */
2916#ifdef __GNUC__
2917static __attribute__ ((noreturn)) void signalhandler_alarm(
2918int sig __attribute__((__unused__)))
2919#else /* __GNUC__ */
2920static void signalhandler_alarm(int sig)
2921#endif /* __GNUC__ */
2922{
2923 RTCM3Error("Programm forcefully terminated.\n");
2924 exit(1);
2925}
2926
2927int main(int argc, char **argv)
2928{
2929 struct Args args;
2930 struct RTCM3ParserData Parser;
2931
2932 setbuf(stdout, 0);
2933 setbuf(stdin, 0);
2934 setbuf(stderr, 0);
2935
2936 fixrevision();
2937
2938 signal(SIGINT, signalhandler);
2939 signal(SIGALRM,signalhandler_alarm);
2940 signal(SIGQUIT,signalhandler);
2941 signal(SIGTERM,signalhandler);
2942 signal(SIGPIPE,signalhandler);
2943 memset(&Parser, 0, sizeof(Parser));
2944 {
2945 time_t tim;
2946 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
2947 Parser.GPSWeek = tim/(7*24*60*60);
2948 Parser.GPSTOW = tim%(7*24*60*60);
2949 }
2950
2951 if(getargs(argc, argv, &args))
2952 {
2953 int sockfd, numbytes;
2954 char buf[MAXDATASIZE];
2955 struct sockaddr_in their_addr; /* connector's address information */
2956 struct hostent *he;
2957 struct servent *se;
2958 const char *server, *port, *proxyserver = 0;
2959 char proxyport[6];
2960 char *b;
2961 long i;
2962 struct timeval tv;
2963
2964 alarm(ALARMTIME);
2965
2966 Parser.headerfile = args.headerfile;
2967 Parser.glonassephemeris = args.glonassephemeris;
2968 Parser.gpsephemeris = args.gpsephemeris;
2969 Parser.rinex3 = args.rinex3;
2970
2971 if(args.proxyhost)
2972 {
2973 int p;
2974 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
2975 p = i;
2976 else if(!(se = getservbyname(args.port, 0)))
2977 {
2978 RTCM3Error("Can't resolve port %s.", args.port);
2979 exit(1);
2980 }
2981 else
2982 {
2983 p = ntohs(se->s_port);
2984 }
2985 snprintf(proxyport, sizeof(proxyport), "%d", p);
2986 port = args.proxyport;
2987 proxyserver = args.server;
2988 server = args.proxyhost;
2989 }
2990 else
2991 {
2992 server = args.server;
2993 port = args.port;
2994 }
2995
2996 memset(&their_addr, 0, sizeof(struct sockaddr_in));
2997 if((i = strtol(port, &b, 10)) && (!b || !*b))
2998 their_addr.sin_port = htons(i);
2999 else if(!(se = getservbyname(port, 0)))
3000 {
3001 RTCM3Error("Can't resolve port %s.", port);
3002 exit(1);
3003 }
3004 else
3005 {
3006 their_addr.sin_port = se->s_port;
3007 }
3008 if(!(he=gethostbyname(server)))
3009 {
3010 RTCM3Error("Server name lookup failed for '%s'.\n", server);
3011 exit(1);
3012 }
3013 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
3014 {
3015 perror("socket");
3016 exit(1);
3017 }
3018
3019 tv.tv_sec = args.timeout;
3020 tv.tv_usec = 0;
3021 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
3022 {
3023 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
3024 exit(1);
3025 }
3026
3027 their_addr.sin_family = AF_INET;
3028 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3029
3030 if(args.data && args.mode == RTSP)
3031 {
3032 struct sockaddr_in local;
3033 int sockudp, localport;
3034 int cseq = 1;
3035 socklen_t len;
3036
3037 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3038 {
3039 perror("socket");
3040 exit(1);
3041 }
3042 /* fill structure with local address information for UDP */
3043 memset(&local, 0, sizeof(local));
3044 local.sin_family = AF_INET;
3045 local.sin_port = htons(0);
3046 local.sin_addr.s_addr = htonl(INADDR_ANY);
3047 len = sizeof(local);
3048 /* bind() in order to get a random RTP client_port */
3049 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
3050 {
3051 perror("bind");
3052 exit(1);
3053 }
3054 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
3055 {
3056 localport = ntohs(local.sin_port);
3057 }
3058 else
3059 {
3060 perror("local access failed");
3061 exit(1);
3062 }
3063 if(connect(sockfd, (struct sockaddr *)&their_addr,
3064 sizeof(struct sockaddr)) == -1)
3065 {
3066 perror("connect");
3067 exit(1);
3068 }
3069 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3070 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
3071 "CSeq: %d\r\n"
3072 "Ntrip-Version: Ntrip/2.0\r\n"
3073 "Ntrip-Component: Ntripclient\r\n"
3074 "User-Agent: %s/%s\r\n"
3075 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
3076 "Authorization: Basic ",
3077 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3078 args.data, cseq++, AGENTSTRING, revisionstr, localport);
3079 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3080 {
3081 RTCM3Error("Requested data too long\n");
3082 exit(1);
3083 }
3084 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3085 if(i > MAXDATASIZE-4)
3086 {
3087 RTCM3Error("Username and/or password too long\n");
3088 exit(1);
3089 }
3090 buf[i++] = '\r';
3091 buf[i++] = '\n';
3092 buf[i++] = '\r';
3093 buf[i++] = '\n';
3094 if(args.nmea)
3095 {
3096 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3097 if(j >= 0 && j < MAXDATASIZE-i)
3098 i += j;
3099 else
3100 {
3101 RTCM3Error("NMEA string too long\n");
3102 exit(1);
3103 }
3104 }
3105 if(send(sockfd, buf, (size_t)i, 0) != i)
3106 {
3107 perror("send");
3108 exit(1);
3109 }
3110 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3111 {
3112 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3113 {
3114 int serverport = 0, session = 0;
3115 const char *portcheck = "server_port=";
3116 const char *sessioncheck = "session: ";
3117 int l = strlen(portcheck)-1;
3118 int j=0;
3119 for(i = 0; j != l && i < numbytes-l; ++i)
3120 {
3121 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
3122 ;
3123 }
3124 if(i == numbytes-l)
3125 {
3126 RTCM3Error("No server port number found\n");
3127 exit(1);
3128 }
3129 else
3130 {
3131 i+=l;
3132 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3133 serverport = serverport * 10 + buf[i++]-'0';
3134 if(buf[i] != '\r' && buf[i] != ';')
3135 {
3136 RTCM3Error("Could not extract server port\n");
3137 exit(1);
3138 }
3139 }
3140 l = strlen(sessioncheck)-1;
3141 j=0;
3142 for(i = 0; j != l && i < numbytes-l; ++i)
3143 {
3144 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
3145 ;
3146 }
3147 if(i == numbytes-l)
3148 {
3149 RTCM3Error("No session number found\n");
3150 exit(1);
3151 }
3152 else
3153 {
3154 i+=l;
3155 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3156 session = session * 10 + buf[i++]-'0';
3157 if(buf[i] != '\r')
3158 {
3159 RTCM3Error("Could not extract session number\n");
3160 exit(1);
3161 }
3162 }
3163
3164 i = snprintf(buf, MAXDATASIZE,
3165 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
3166 "CSeq: %d\r\n"
3167 "Session: %d\r\n"
3168 "\r\n",
3169 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3170 args.data, cseq++, session);
3171
3172 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3173 {
3174 RTCM3Error("Requested data too long\n");
3175 exit(1);
3176 }
3177 if(send(sockfd, buf, (size_t)i, 0) != i)
3178 {
3179 perror("send");
3180 exit(1);
3181 }
3182 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3183 {
3184 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3185 {
3186 struct sockaddr_in addrRTP;
3187 /* fill structure with caster address information for UDP */
3188 memset(&addrRTP, 0, sizeof(addrRTP));
3189 addrRTP.sin_family = AF_INET;
3190 addrRTP.sin_port = htons(serverport);
3191 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3192 len = sizeof(addrRTP);
3193 int ts = 0;
3194 int sn = 0;
3195 int ssrc = 0;
3196 int init = 0;
3197 int u, v, w;
3198 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
3199 (struct sockaddr*) &addrRTP, &len)) > 0)
3200 {
3201 alarm(ALARMTIME);
3202 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
3203 {
3204 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
3205 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
3206 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
3207 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
3208 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
3209
3210 if(init)
3211 {
3212 int z;
3213 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
3214 if(ssrc != w || ts > v)
3215 {
3216 RTCM3Error("Illegal UDP data received.\n");
3217 exit(1);
3218 }
3219 if(u > sn) /* don't show out-of-order packets */
3220 for(z = 12; z < i && !stop; ++z)
3221 HandleByte(&Parser, (unsigned int) buf[z]);
3222 }
3223 sn = u; ts = v; ssrc = w; init = 1;
3224 }
3225 else
3226 {
3227 RTCM3Error("Illegal UDP header.\n");
3228 exit(1);
3229 }
3230 }
3231 }
3232 i = snprintf(buf, MAXDATASIZE,
3233 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
3234 "CSeq: %d\r\n"
3235 "Session: %d\r\n"
3236 "\r\n",
3237 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3238 args.data, cseq++, session);
3239
3240 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3241 {
3242 RTCM3Error("Requested data too long\n");
3243 exit(1);
3244 }
3245 if(send(sockfd, buf, (size_t)i, 0) != i)
3246 {
3247 perror("send");
3248 exit(1);
3249 }
3250 }
3251 else
3252 {
3253 RTCM3Error("Could not start data stream.\n");
3254 exit(1);
3255 }
3256 }
3257 else
3258 {
3259 RTCM3Error("Could not setup initial control connection.\n");
3260 exit(1);
3261 }
3262 }
3263 else
3264 {
3265 perror("recv");
3266 exit(1);
3267 }
3268 }
3269 else
3270 {
3271 if(connect(sockfd, (struct sockaddr *)&their_addr,
3272 sizeof(struct sockaddr)) == -1)
3273 {
3274 perror("connect");
3275 exit(1);
3276 }
3277 if(!args.data)
3278 {
3279 i = snprintf(buf, MAXDATASIZE,
3280 "GET %s%s%s%s/ HTTP/1.0\r\n"
3281 "Host: %s\r\n%s"
3282 "User-Agent: %s/%s\r\n"
3283 "Connection: close\r\n"
3284 "\r\n"
3285 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3286 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3287 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3288 AGENTSTRING, revisionstr);
3289 }
3290 else
3291 {
3292 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3293 "GET %s%s%s%s/%s HTTP/1.0\r\n"
3294 "Host: %s\r\n%s"
3295 "User-Agent: %s/%s\r\n"
3296 "Connection: close\r\n"
3297 "Authorization: Basic "
3298 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3299 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3300 args.data, args.server,
3301 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3302 AGENTSTRING, revisionstr);
3303 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3304 {
3305 RTCM3Error("Requested data too long\n");
3306 exit(1);
3307 }
3308 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3309 if(i > MAXDATASIZE-4)
3310 {
3311 RTCM3Error("Username and/or password too long\n");
3312 exit(1);
3313 }
3314 buf[i++] = '\r';
3315 buf[i++] = '\n';
3316 buf[i++] = '\r';
3317 buf[i++] = '\n';
3318 if(args.nmea)
3319 {
3320 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3321 if(j >= 0 && j < MAXDATASIZE-i)
3322 i += j;
3323 else
3324 {
3325 RTCM3Error("NMEA string too long\n");
3326 exit(1);
3327 }
3328 }
3329 }
3330 if(send(sockfd, buf, (size_t)i, 0) != i)
3331 {
3332 perror("send");
3333 exit(1);
3334 }
3335 if(args.data)
3336 {
3337 int k = 0;
3338 int chunkymode = 0;
3339 int starttime = time(0);
3340 int lastout = starttime;
3341 int totalbytes = 0;
3342 int chunksize = 0;
3343
3344 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3345 {
3346 if(numbytes > 0)
3347 alarm(ALARMTIME);
3348 else
3349 {
3350 WaitMicro(100);
3351 continue;
3352 }
3353 if(!k)
3354 {
3355 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
3356 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
3357 {
3358 const char *datacheck = "Content-Type: gnss/data\r\n";
3359 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
3360 int l = strlen(datacheck)-1;
3361 int j=0;
3362 for(i = 0; j != l && i < numbytes-l; ++i)
3363 {
3364 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
3365 ;
3366 }
3367 if(i == numbytes-l)
3368 {
3369 RTCM3Error("No 'Content-Type: gnss/data' found\n");
3370 exit(1);
3371 }
3372 l = strlen(chunkycheck)-1;
3373 j=0;
3374 for(i = 0; j != l && i < numbytes-l; ++i)
3375 {
3376 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
3377 ;
3378 }
3379 if(i < numbytes-l)
3380 chunkymode = 1;
3381 }
3382 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
3383 {
3384 RTCM3Error("Could not get the requested data: ");
3385 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
3386 {
3387 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
3388 }
3389 RTCM3Error("\n");
3390 exit(1);
3391 }
3392 else if(args.mode != NTRIP1)
3393 {
3394 if(args.mode != AUTO)
3395 {
3396 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
3397 args.mode == AUTO ? ", falling back to NTRIP1" : "");
3398 }
3399 if(args.mode == HTTP)
3400 exit(1);
3401 }
3402 ++k;
3403 }
3404 else
3405 {
3406 if(chunkymode)
3407 {
3408 int stop = 0;
3409 int pos = 0;
3410 while(!stop && pos < numbytes)
3411 {
3412 switch(chunkymode)
3413 {
3414 case 1: /* reading number starts */
3415 chunksize = 0;
3416 ++chunkymode; /* no break */
3417 case 2: /* during reading number */
3418 i = buf[pos++];
3419 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
3420 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
3421 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
3422 else if(i == '\r') ++chunkymode;
3423 else if(i == ';') chunkymode = 5;
3424 else stop = 1;
3425 break;
3426 case 3: /* scanning for return */
3427 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
3428 else stop = 1;
3429 break;
3430 case 4: /* output data */
3431 i = numbytes-pos;
3432 if(i > chunksize) i = chunksize;
3433 {
3434 int z;
3435 for(z = 0; z < i && !stop; ++z)
3436 HandleByte(&Parser, (unsigned int) buf[pos+z]);
3437 }
3438 totalbytes += i;
3439 chunksize -= i;
3440 pos += i;
3441 if(!chunksize)
3442 chunkymode = 1;
3443 break;
3444 case 5:
3445 if(i == '\r') chunkymode = 3;
3446 break;
3447 }
3448 }
3449 if(stop)
3450 {
3451 RTCM3Error("Error in chunky transfer encoding\n");
3452 break;
3453 }
3454 }
3455 else
3456 {
3457 totalbytes += numbytes;
3458 {
3459 int z;
3460 for(z = 0; z < numbytes && !stop; ++z)
3461 HandleByte(&Parser, (unsigned int) buf[z]);
3462 }
3463 }
3464 if(totalbytes < 0) /* overflow */
3465 {
3466 totalbytes = 0;
3467 starttime = time(0);
3468 lastout = starttime;
3469 }
3470 }
3471 }
3472 }
3473 else
3474 {
3475 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
3476 {
3477 alarm(ALARMTIME);
3478 fwrite(buf, (size_t)numbytes, 1, stdout);
3479 }
3480 }
3481 close(sockfd);
3482 }
3483 }
3484 return 0;
3485}
3486#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.