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

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

update MSM data format to current layout

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