source: ntrip/trunk/BNC/RTCM3/rtcm3torinex.c@ 1003

Last change on this file since 1003 was 746, checked in by mervart, 17 years ago

* empty log message *

File size: 76.7 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.27 2008/03/25 15:10:48 stoecker Exp $
4 Copyright (C) 2005-2008 by Dirk Stöcker <stoecker@alberding.eu>
5
6 This software is a complete NTRIP-RTCM3 to RINEX converter as well as
7 a module of the BNC tool for multiformat conversion. Contact Dirk
8 Stöcker for suggestions and bug reports related to the RTCM3 to RINEX
9 conversion problems and the author of BNC for all the other problems.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 or read http://www.gnu.org/licenses/gpl.txt
25*/
26
27#include <ctype.h>
28#include <errno.h>
29#include <math.h>
30#include <signal.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/types.h>
36#include <time.h>
37#include <unistd.h>
38
39#ifndef NO_RTCM3_MAIN
40#include <getopt.h>
41#include <netdb.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44#endif
45
46#ifndef sparc
47#include <stdint.h>
48#endif
49
50#include "rtcm3torinex.h"
51
52/* CVS revision and version */
53static char revisionstr[] = "$Revision: 1.27 $";
54
55#ifndef COMPILEDATE
56#define COMPILEDATE " built " __DATE__
57#endif
58
59static uint32_t CRC24(long size, const unsigned char *buf)
60{
61 uint32_t crc = 0;
62 int i;
63
64 while(size--)
65 {
66 crc ^= (*buf++) << (16);
67 for(i = 0; i < 8; i++)
68 {
69 crc <<= 1;
70 if(crc & 0x1000000)
71 crc ^= 0x01864cfb;
72 }
73 }
74 return crc;
75}
76
77static int GetMessage(struct RTCM3ParserData *handle)
78{
79 unsigned char *m, *e;
80 int i;
81
82 m = handle->Message+handle->SkipBytes;
83 e = handle->Message+handle->MessageSize;
84 handle->NeedBytes = handle->SkipBytes = 0;
85 while(e-m >= 3)
86 {
87 if(m[0] == 0xD3)
88 {
89 handle->size = ((m[1]&3)<<8)|m[2];
90 if(e-m >= handle->size+6)
91 {
92 if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8)
93 |(m[3+handle->size+2])) == CRC24(handle->size+3, m))
94 {
95 handle->SkipBytes = handle->size;
96 break;
97 }
98 else
99 ++m;
100 }
101 else
102 {
103 handle->NeedBytes = handle->size+6;
104 break;
105 }
106 }
107 else
108 ++m;
109 }
110 if(e-m < 3)
111 handle->NeedBytes = 3;
112
113 /* copy buffer to front */
114 i = m - handle->Message;
115 if(i && m < e)
116 memmove(handle->Message, m, (size_t)(handle->MessageSize-i));
117 handle->MessageSize -= i;
118
119 return !handle->NeedBytes;
120}
121
122#define LOADBITS(a) \
123{ \
124 while((a) > numbits) \
125 { \
126 if(!size--) break; \
127 bitfield = (bitfield<<8)|*(data++); \
128 numbits += 8; \
129 } \
130}
131
132/* extract bits from data stream
133 b = variable to store result, a = number of bits */
134#define GETBITS(b, a) \
135{ \
136 LOADBITS(a) \
137 b = (bitfield<<(64-numbits))>>(64-(a)); \
138 numbits -= (a); \
139}
140
141/* extract floating value from data stream
142 b = variable to store result, a = number of bits */
143#define GETFLOAT(b, a, c) \
144{ \
145 LOADBITS(a) \
146 b = ((double)((bitfield<<(64-numbits))>>(64-(a))))*(c); \
147 numbits -= (a); \
148}
149
150/* extract signed floating value from data stream
151 b = variable to store result, a = number of bits */
152#define GETFLOATSIGN(b, a, c) \
153{ \
154 LOADBITS(a) \
155 b = ((double)(((int64_t)(bitfield<<(64-numbits)))>>(64-(a))))*(c); \
156 numbits -= (a); \
157}
158
159/* extract bits from data stream
160 b = variable to store result, a = number of bits */
161#define GETBITSSIGN(b, a) \
162{ \
163 LOADBITS(a) \
164 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
165 numbits -= (a); \
166}
167
168#define GETFLOATSIGNM(b, a, c) \
169{ int l; \
170 LOADBITS(a) \
171 l = (bitfield<<(64-numbits))>>(64-1); \
172 b = ((double)(((bitfield<<(64-(numbits-1))))>>(64-(a-1))))*(c); \
173 numbits -= (a); \
174 if(l) b *= -1.0; \
175}
176
177#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
178
179struct leapseconds { /* specify the day of leap second */
180 int day; /* this is the day, where 23:59:59 exists 2 times */
181 int month; /* not the next day! */
182 int year;
183 int taicount;
184};
185static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
186static const struct leapseconds leap[] = {
187/*{31, 12, 1971, 11},*/
188/*{31, 12, 1972, 12},*/
189/*{31, 12, 1973, 13},*/
190/*{31, 12, 1974, 14},*/
191/*{31, 12, 1975, 15},*/
192/*{31, 12, 1976, 16},*/
193/*{31, 12, 1977, 17},*/
194/*{31, 12, 1978, 18},*/
195/*{31, 12, 1979, 19},*/
196{30, 06, 1981,20},
197{30, 06, 1982,21},
198{30, 06, 1983,22},
199{30, 06, 1985,23},
200{31, 12, 1987,24},
201{31, 12, 1989,25},
202{31, 12, 1990,26},
203{30, 06, 1992,27},
204{30, 06, 1993,28},
205{30, 06, 1994,29},
206{31, 12, 1995,30},
207{30, 06, 1997,31},
208{31, 12, 1998,32},
209{31, 12, 2005,33},
210{0,0,0,0} /* end marker */
211};
212#define LEAPSECONDS 14 /* only needed for approx. time */
213#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
214
215static int longyear(int year, int month)
216{
217 if(!(year % 4) && (!(year % 400) || (year % 100)))
218 {
219 if(!month || month == 2)
220 return 1;
221 }
222 return 0;
223}
224
225static int gnumleap(int year, int month, int day)
226{
227 int ls = 0;
228 const struct leapseconds *l;
229
230 for(l = leap; l->taicount && year >= l->year; ++l)
231 {
232 if(year > l->year || month > l->month || day > l->day)
233 ls = l->taicount - GPSLEAPSTART;
234 }
235 return ls;
236}
237
238void updatetime(int *week, int *tow, int tk, int fixnumleap)
239{
240 int y,m,d,k,l, nul;
241 unsigned int j = *week*(7*24*60*60) + *tow + 5*24*60*60+3*60*60;
242 int glo_daynumber = 0, glo_timeofday;
243 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
244 + gnumleap(y+1,1,1); ++y)
245 {
246 j -= k; glo_daynumber += l;
247 }
248 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
249 + gnumleap(y, m+1, 1); ++m)
250 {
251 j -= k; glo_daynumber += l;
252 }
253 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
254 j -= 24*60*60;
255 glo_daynumber -= 16*365+4-d;
256 nul = gnumleap(y, m, d);
257 glo_timeofday = j-nul;
258
259 if(tk < 5*60*1000 && glo_timeofday > 23*60*60)
260 *tow += 24*60*60;
261 else if(glo_timeofday < 5*60 && tk > 23*60*60*1000)
262 *tow -= 24*60*60;
263 *tow += tk/1000-glo_timeofday;
264 if(fixnumleap)
265 *tow -= nul;
266 if(*tow < 0) {*tow += 24*60*60*7; --*week; }
267 if(*tow >= 24*60*60*7) {*tow -= 24*60*60*7; ++*week; }
268}
269
270int RTCM3Parser(struct RTCM3ParserData *handle)
271{
272 int ret=0;
273
274 while(!ret && GetMessage(handle))
275 {
276 /* using 64 bit integer types, as it is much easier than handling
277 the long datatypes in 32 bit */
278 uint64_t numbits = 0, bitfield = 0;
279 int size = handle->size, type;
280 int syncf, old = 0;
281 unsigned char *data = handle->Message+3;
282
283 GETBITS(type,12)
284 switch(type)
285 {
286 case 1019:
287 {
288 struct gpsephemeris *ge;
289 int sv;
290
291 ge = &handle->ephemerisGPS;
292 memset(ge, 0, sizeof(*ge));
293
294 GETBITS(sv, 6)
295 ge->satellite = (sv < 40 ? sv : sv+80);
296 GETBITS(ge->GPSweek, 10)
297 ge->GPSweek += 1024;
298 GETBITS(ge->URAindex, 4)
299 GETBITS(sv, 2)
300 if(sv & 1)
301 ge->flags |= GPSEPHF_L2PCODE;
302 if(sv & 2)
303 ge->flags |= GPSEPHF_L2CACODE;
304 GETFLOATSIGN(ge->IDOT, 14, PI/(double)(1<<30)/(double)(1<<13))
305 GETBITS(ge->IODE, 8)
306 GETBITS(ge->TOC, 16)
307 ge->TOC <<= 4;
308 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
309 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
310 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
311 GETBITS(ge->IODC, 10)
312 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
313 GETFLOATSIGN(ge->Delta_n, 16, PI/(double)(1<<30)/(double)(1<<13))
314 GETFLOATSIGN(ge->M0, 32, PI/(double)(1<<30)/(double)(1<<1))
315 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
316 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
317 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
318 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
319 GETBITS(ge->TOE, 16)
320 ge->TOE <<= 4;
321
322 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
323 GETFLOATSIGN(ge->OMEGA0, 32, PI/(double)(1<<30)/(double)(1<<1))
324 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
325 GETFLOATSIGN(ge->i0, 32, PI/(double)(1<<30)/(double)(1<<1))
326 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
327 GETFLOATSIGN(ge->omega, 32, PI/(double)(1<<30)/(double)(1<<1))
328 GETFLOATSIGN(ge->OMEGADOT, 24, PI/(double)(1<<30)/(double)(1<<13))
329 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
330 GETBITS(ge->SVhealth, 6)
331 GETBITS(sv, 1)
332 if(sv)
333 ge->flags |= GPSEPHF_L2PCODEDATA;
334
335 ret = 1019;
336 }
337 break;
338 case 1020:
339 {
340 struct glonassephemeris *ge;
341 int i;
342
343 ge = &handle->ephemerisGLONASS;
344 memset(ge, 0, sizeof(*ge));
345
346 ge->flags |= GLOEPHF_PAVAILABLE;
347 GETBITS(ge->almanac_number, 6)
348 GETBITS(i, 5)
349 ge->frequency_number = i-7;
350 GETBITS(i, 1)
351 if(i)
352 ge->flags |= GLOEPHF_ALMANACHEALTHY;
353 GETBITS(i, 1)
354 if(i)
355 ge->flags |= GLOEPHF_ALMANACHEALTHOK;
356 GETBITS(i, 2)
357 if(i & 1)
358 ge->flags |= GLOEPHF_P10TRUE;
359 if(i & 2)
360 ge->flags |= GLOEPHF_P11TRUE;
361 GETBITS(i, 5)
362 ge->tk = i*60*60;
363 GETBITS(i, 6)
364 ge->tk += i*60;
365 GETBITS(i, 1)
366 ge->tk += i*30;
367 GETBITS(i, 1)
368 if(i)
369 ge->flags |= GLOEPHF_UNHEALTHY;
370 GETBITS(i, 1)
371 if(i)
372 ge->flags |= GLOEPHF_P2TRUE;
373 GETBITS(i, 7)
374 ge->tb = i*15*60;
375 GETFLOATSIGNM(ge->x_velocity, 24, 1.0/(double)(1<<20))
376 GETFLOATSIGNM(ge->x_pos, 27, 1.0/(double)(1<<11))
377 GETFLOATSIGNM(ge->x_acceleration, 5, 1.0/(double)(1<<30))
378 GETFLOATSIGNM(ge->y_velocity, 24, 1.0/(double)(1<<20))
379 GETFLOATSIGNM(ge->y_pos, 27, 1.0/(double)(1<<11))
380 GETFLOATSIGNM(ge->y_acceleration, 5, 1.0/(double)(1<<30))
381 GETFLOATSIGNM(ge->z_velocity, 24, 1.0/(double)(1<<20))
382 GETFLOATSIGNM(ge->z_pos, 27, 1.0/(double)(1<<11))
383 GETFLOATSIGNM(ge->z_acceleration, 5, 1.0/(double)(1<<30))
384 GETBITS(i, 1)
385 if(i)
386 ge->flags |= GLOEPHF_P3TRUE;
387 GETFLOATSIGNM(ge->gamma, 11, 1.0/(double)(1<<30)/(double)(1<<10))
388 SKIPBITS(3) /* GLONASS-M P, GLONASS-M ln (third string) */
389 GETFLOATSIGNM(ge->tau, 22, 1.0/(double)(1<<30)) /* GLONASS tau n(tb) */
390 SKIPBITS(5) /* GLONASS-M delta tau n(tb) */
391 GETBITS(ge->E, 5)
392 /* GETBITS(b, 1) / * GLONASS-M P4 */
393 /* GETBITS(b, 4) / * GLONASS-M Ft */
394 /* GETBITS(b, 11) / * GLONASS-M Nt */
395 /* GETBITS(b, 2) / * GLONASS-M M */
396 /* GETBITS(b, 1) / * GLONASS-M The Availability of Additional Data */
397 /* GETBITS(b, 11) / * GLONASS-M Na */
398 /* GETFLOATSIGNM(b, 32, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS tau c */
399 /* GETBITS(b, 5) / * GLONASS-M N4 */
400 /* GETFLOATSIGNM(b, 22, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS-M tau GPS */
401 /* GETBITS(b, 1) / * GLONASS-M ln (fifth string) */
402 ge->GPSWeek = handle->GPSWeek;
403 ge->GPSTOW = handle->GPSTOW;
404 ret = 1020;
405 }
406 break;
407 case 1001: case 1002: case 1003: case 1004:
408 if(handle->GPSWeek)
409 {
410 int lastlockl1[64];
411 int lastlockl2[64];
412 struct gnssdata *gnss;
413 int i, num, wasamb=0;
414
415 for(i = 0; i < 64; ++i)
416 lastlockl1[i] = lastlockl2[i] = 0;
417
418 gnss = &handle->DataNew;
419
420 SKIPBITS(12) /* id */
421 GETBITS(i,30)
422 if(i/1000 < (int)handle->GPSTOW - 86400)
423 ++handle->GPSWeek;
424 handle->GPSTOW = i/1000;
425 if(gnss->week && (gnss->timeofweek != i || gnss->week
426 != handle->GPSWeek))
427 {
428 handle->Data = *gnss;
429 memset(gnss, 0, sizeof(*gnss));
430 old = 1;
431 }
432 gnss->timeofweek = i;
433 gnss->week = handle->GPSWeek;
434
435 GETBITS(syncf,1) /* sync */
436 GETBITS(i,5)
437 gnss->numsats = i;
438 SKIPBITS(4) /* smind, smint */
439
440 for(num = 0; num < gnss->numsats; ++num)
441 {
442 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
443
444 GETBITS(sv, 6);
445 gnss->satellites[num] = (sv < 40 ? sv : sv+80);
446 /* L1 */
447 GETBITS(code, 1);
448 if(code)
449 {
450 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
451 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
452 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
453 }
454 else
455 {
456 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
457 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
458 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
459 }
460 GETBITS(l1range, 24);
461 GETBITSSIGN(i, 20);
462 if((i&((1<<20)-1)) != 0x80000)
463 {
464 gnss->dataflags[num] |= (c|l);
465 gnss->measdata[num][ce] = l1range*0.02;
466 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
467 }
468 GETBITS(i, 7);
469 lastlockl1[sv] = i;
470 if(handle->lastlockl1[sv] > i)
471 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
472 if(type == 1002 || type == 1004)
473 {
474 GETBITS(amb,8);
475 if(amb && (gnss->dataflags[num] & c))
476 {
477 gnss->measdata[num][ce] += amb*299792.458;
478 gnss->measdata[num][le] += amb*299792.458;
479 ++wasamb;
480 }
481 GETBITS(i, 8);
482 if(i)
483 {
484 gnss->dataflags[num] |= s;
485 gnss->measdata[num][se] = i*0.25;
486 i /= 4*4;
487 if(i > 9) i = 9;
488 else if(i < 1) i = 1;
489 gnss->snrL1[num] = i;
490 }
491 }
492 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
493 if(type == 1003 || type == 1004)
494 {
495 /* L2 */
496 GETBITS(code,2);
497 if(code)
498 {
499 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
500 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
501 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
502 }
503 else
504 {
505 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
506 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
507 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
508 }
509 GETBITSSIGN(i,14);
510 if((i&((1<<14)-1)) != 0x2000)
511 {
512 gnss->dataflags[num] |= c;
513 gnss->measdata[num][ce] = l1range*0.02+i*0.02
514 +amb*299792.458;
515 }
516 GETBITSSIGN(i,20);
517 if((i&((1<<20)-1)) != 0x80000)
518 {
519 gnss->dataflags[num] |= l;
520 gnss->measdata[num][le] = l1range*0.02+i*0.0005
521 +amb*299792.458;
522 }
523 GETBITS(i,7);
524 lastlockl2[sv] = i;
525 if(handle->lastlockl2[sv] > i)
526 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
527 if(type == 1004)
528 {
529 GETBITS(i, 8);
530 if(i)
531 {
532 gnss->dataflags[num] |= s;
533 gnss->measdata[num][se] = i*0.25;
534 i /= 4*4;
535 if(i > 9) i = 9;
536 else if(i < 1) i = 1;
537 gnss->snrL2[num] = i;
538 }
539 }
540 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
541 }
542 }
543 for(i = 0; i < 64; ++i)
544 {
545 handle->lastlockl1[i] = lastlockl1[i];
546 handle->lastlockl2[i] = lastlockl2[i];
547 }
548 if(!syncf && !old)
549 {
550 handle->Data = *gnss;
551 memset(gnss, 0, sizeof(*gnss));
552 }
553 if(!syncf || old)
554 {
555 if(wasamb) /* not RINEX compatible without */
556 ret = 1;
557 else
558 ret = 2;
559 }
560 }
561 break;
562 case 1009: case 1010: case 1011: case 1012:
563 {
564 int lastlockl1[64];
565 int lastlockl2[64];
566 struct gnssdata *gnss;
567 int i, num;
568 int wasamb=0;
569
570 for(i = 0; i < 64; ++i)
571 lastlockl1[i] = lastlockl2[i] = 0;
572
573 gnss = &handle->DataNew;
574
575 SKIPBITS(12) /* id */;
576 GETBITS(i,27) /* tk */
577
578 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0);
579 i = handle->GPSTOW*1000;
580 if(gnss->week && (gnss->timeofweek != i || gnss->week
581 != handle->GPSWeek))
582 {
583 handle->Data = *gnss;
584 memset(gnss, 0, sizeof(*gnss));
585 old = 1;
586 }
587
588 gnss->timeofweek = i;
589 gnss->week = handle->GPSWeek;
590
591 GETBITS(syncf,1) /* sync */
592 GETBITS(i,5)
593 gnss->numsats += i;
594
595 SKIPBITS(4) /* smind, smint */
596
597 for(num = gnss->numsats-i; num < gnss->numsats; ++num)
598 {
599 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
600 int freq;
601
602 GETBITS(sv, 6)
603 gnss->satellites[num] = sv-1 + PRN_GLONASS_START;
604 /* L1 */
605 GETBITS(code, 1)
606 GETBITS(freq, 5)
607 if(code)
608 {
609 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
610 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
611 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
612 }
613 else
614 {
615 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
616 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
617 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
618 }
619 GETBITS(l1range, 25)
620 GETBITSSIGN(i, 20)
621 if((i&((1<<20)-1)) != 0x80000)
622 {
623 /* Handle this like GPS. Actually for GLONASS L1 range is always
624 valid. To be on the save side, we handle it as invalid like we
625 do for GPS and also remove range in case of 0x80000. */
626 gnss->dataflags[num] |= (c|l);
627 gnss->measdata[num][ce] = l1range*0.02;
628 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
629 }
630 GETBITS(i, 7)
631 lastlockl1[sv] = i;
632 if(handle->lastlockl1[sv] > i)
633 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
634 if(type == 1010 || type == 1012)
635 {
636 GETBITS(amb,7)
637 if(amb && (gnss->dataflags[num] & c))
638 {
639 gnss->measdata[num][ce] += amb*599584.916;
640 gnss->measdata[num][le] += amb*599584.916;
641 ++wasamb;
642 }
643 GETBITS(i, 8)
644 if(i)
645 {
646 gnss->dataflags[num] |= s;
647 gnss->measdata[num][se] = i*0.25;
648 i /= 4*4;
649 if(i > 9) i = 9;
650 else if(i < 1) i = 1;
651 gnss->snrL1[num] = i;
652 }
653 }
654 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
655 if(type == 1011 || type == 1012)
656 {
657 /* L2 */
658 GETBITS(code,2)
659 if(code)
660 {
661 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
662 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
663 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
664 }
665 else
666 {
667 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
668 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
669 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
670 }
671 GETBITSSIGN(i,14)
672 if((i&((1<<14)-1)) != 0x2000)
673 {
674 gnss->dataflags[num] |= c;
675 gnss->measdata[num][ce] = l1range*0.02+i*0.02
676 +amb*599584.916;
677 }
678 GETBITSSIGN(i,20)
679 if((i&((1<<20)-1)) != 0x80000)
680 {
681 gnss->dataflags[num] |= l;
682 gnss->measdata[num][le] = l1range*0.02+i*0.0005
683 +amb*599584.915;
684 }
685 GETBITS(i,7)
686 lastlockl2[sv] = i;
687 if(handle->lastlockl2[sv] > i)
688 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
689 if(type == 1012)
690 {
691 GETBITS(i, 8)
692 if(i)
693 {
694 gnss->dataflags[num] |= s;
695 gnss->measdata[num][se] = i*0.25;
696 i /= 4*4;
697 if(i > 9) i = 9;
698 else if(i < 1) i = 1;
699 gnss->snrL2[num] = i;
700 }
701 }
702 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
703 }
704 if(!sv || sv > 24)
705 {
706 --num; --gnss->numsats;
707 }
708 }
709 for(i = 0; i < 64; ++i)
710 {
711 handle->lastlockl1[i] = lastlockl1[i];
712 handle->lastlockl2[i] = lastlockl2[i];
713 }
714 if(!syncf && !old)
715 {
716 handle->Data = *gnss;
717 memset(gnss, 0, sizeof(*gnss));
718 }
719 if(!syncf || old)
720 {
721 if(wasamb) /* not RINEX compatible without */
722 ret = 1;
723 else
724 ret = 2;
725 }
726 }
727 break;
728 }
729 }
730 return ret;
731}
732
733struct Header
734{
735 const char *version;
736 const char *pgm;
737 const char *marker;
738 const char *markertype;
739 const char *observer;
740 const char *receiver;
741 const char *antenna;
742 const char *position;
743 const char *antennaposition;
744 const char *wavelength;
745 const char *typesofobs; /* should not be modified outside */
746 const char *typesofobsG; /* should not be modified outside */
747 const char *typesofobsR; /* should not be modified outside */
748 const char *typesofobsS; /* should not be modified outside */
749 const char *timeoffirstobs; /* should not be modified outside */
750};
751
752#define MAXHEADERLINES 50
753#define MAXHEADERBUFFERSIZE 4096
754struct HeaderData
755{
756 union
757 {
758 struct Header named;
759 const char *unnamed[MAXHEADERLINES];
760 } data;
761 int numheaders;
762};
763
764struct converttimeinfo {
765 int second; /* seconds of GPS time [0..59] */
766 int minute; /* minutes of GPS time [0..59] */
767 int hour; /* hour of GPS time [0..24] */
768 int day; /* day of GPS time [1..28..30(31)*/
769 int month; /* month of GPS time [1..12]*/
770 int year; /* year of GPS time [1980..] */
771};
772
773void converttime(struct converttimeinfo *c, int week, int tow)
774{
775 int i, k, doy, j; /* temporary variables */
776 j = week*(7*24*60*60) + tow + 5*24*60*60;
777 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
778 j -= k;
779 c->year = i;
780 doy = 1+ (j / (24*60*60));
781 j %= (24*60*60);
782 c->hour = j / (60*60);
783 j %= (60*60);
784 c->minute = j / 60;
785 c->second = j % 60;
786 j = 0;
787 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
788 j += k;
789 c->month = i;
790 c->day = doy - j;
791}
792
793#ifndef NO_RTCM3_MAIN
794void RTCM3Error(const char *fmt, ...)
795{
796 va_list v;
797 va_start(v, fmt);
798 vfprintf(stderr, fmt, v);
799 va_end(v);
800}
801#endif
802
803void RTCM3Text(const char *fmt, ...)
804{
805 va_list v;
806 va_start(v, fmt);
807 vprintf(fmt, v);
808 va_end(v);
809}
810
811int HandleRunBy(char *buffer, int buffersize, const char **u,
812int rinex3)
813{
814 const char *user;
815 time_t t;
816 struct tm * t2;
817
818#ifdef NO_RTCM3_MAIN
819 if(revisionstr[0] == '$')
820 {
821 char *a;
822 int i=0;
823 for(a = revisionstr+11; *a && *a != ' '; ++a)
824 revisionstr[i++] = *a;
825 revisionstr[i] = 0;
826 }
827#endif
828
829 user= getenv("USER");
830 if(!user) user = "";
831 t = time(&t);
832 t2 = gmtime(&t);
833 if(u) *u = user;
834 return 1+snprintf(buffer, buffersize,
835 rinex3 ?
836 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
837 "PGM / RUN BY / DATE" :
838 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
839 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
840 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
841}
842
843// Inserted parts for BNC Perlt
844#ifdef NO_RTCM3_MAIN
845#define NUMSTARTSKIP 1
846#else
847#define NUMSTARTSKIP 3
848#endif
849
850void HandleHeader(struct RTCM3ParserData *Parser)
851{
852#ifdef NO_RTCM3_MAIN
853// Part of Handle Header for data request for BNC (independently on actually delivered data), original is commented out by ifndef NO_RTCM3_MAIN. Perlt
854 int i;
855 if(Parser->rinex3)
856 {
857#define CHECKFLAGSNEW(a, b, c) \
858 { \
859 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
860 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
861 ++Parser->numdatatypes##a; \
862 }
863
864 CHECKFLAGSNEW(GPS, C1, C1C)
865 CHECKFLAGSNEW(GPS, L1C, L1C)
866 CHECKFLAGSNEW(GPS, D1C, D1C)
867 CHECKFLAGSNEW(GPS, S1C, S1C)
868 CHECKFLAGSNEW(GPS, P1, C1P)
869 CHECKFLAGSNEW(GPS, L1P, L1P)
870 CHECKFLAGSNEW(GPS, D1P, D1P)
871 CHECKFLAGSNEW(GPS, S1P, S1P)
872 CHECKFLAGSNEW(GPS, P2, C2P)
873 CHECKFLAGSNEW(GPS, L2P, L2P)
874 CHECKFLAGSNEW(GPS, D2P, D2P)
875 CHECKFLAGSNEW(GPS, S2P, S2P)
876 CHECKFLAGSNEW(GPS, C2, C2X)
877 CHECKFLAGSNEW(GPS, L2C, L2X)
878 CHECKFLAGSNEW(GPS, D2C, D2X)
879 CHECKFLAGSNEW(GPS, S2C, S2X)
880 CHECKFLAGSNEW(GLO, C1, C1C)
881 CHECKFLAGSNEW(GLO, L1C, L1C)
882 CHECKFLAGSNEW(GLO, D1C, D1C)
883 CHECKFLAGSNEW(GLO, S1C, S1C)
884 CHECKFLAGSNEW(GLO, P1, C1P)
885 CHECKFLAGSNEW(GLO, L1P, L1P)
886 CHECKFLAGSNEW(GLO, D1P, D1P)
887 CHECKFLAGSNEW(GLO, S1P, S1P)
888 CHECKFLAGSNEW(GLO, P2, C2P)
889 CHECKFLAGSNEW(GLO, L2P, L2P)
890 CHECKFLAGSNEW(GLO, D2P, D2P)
891 CHECKFLAGSNEW(GLO, S2P, S2P)
892 CHECKFLAGSNEW(GLO, C2, C2C)
893 CHECKFLAGSNEW(GLO, L2C, L2C)
894 CHECKFLAGSNEW(GLO, D2C, D2C)
895 CHECKFLAGSNEW(GLO, S2C, S2C)
896
897 }
898 else
899 {
900#define CHECKFLAGS(a, b) \
901 { \
902 if(data[RINEXENTRY_##b##DATA]) \
903 { \
904 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
905 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
906 } \
907 else \
908 { \
909 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
910 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
911 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
912 } \
913 }
914
915 int data[RINEXENTRY_NUMBER];
916 for(i = 0; i < RINEXENTRY_NUMBER; ++i) data[i] = 0;
917
918 CHECKFLAGS(C1,C1)
919 CHECKFLAGS(C2,C2)
920 CHECKFLAGS(P1,P1)
921 CHECKFLAGS(P2,P2)
922 CHECKFLAGS(L1C,L1)
923 CHECKFLAGS(L1P,L1)
924 CHECKFLAGS(L2C,L2)
925 CHECKFLAGS(L2P,L2)
926 CHECKFLAGS(D1C,D1)
927 CHECKFLAGS(D1P,D1)
928 CHECKFLAGS(D2C,D2)
929 CHECKFLAGS(D2P,D2)
930 CHECKFLAGS(S1C,S1)
931 CHECKFLAGS(S1P,S1)
932 CHECKFLAGS(S2C,S2)
933 CHECKFLAGS(S2P,S2)
934 }
935// End Part of Handle Header for BNC Perlt
936#endif
937
938#ifndef NO_RTCM3_MAIN
939 struct HeaderData hdata;
940 char thebuffer[MAXHEADERBUFFERSIZE];
941 char *buffer = thebuffer;
942 size_t buffersize = sizeof(thebuffer);
943 int i;
944
945 memset(&hdata, 0, sizeof(hdata));
946
947 hdata.data.named.version = buffer;
948 i = 1+snprintf(buffer, buffersize,
949 "%9.2f OBSERVATION DATA M (Mixed)"
950 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
951 buffer += i; buffersize -= i;
952
953 {
954 const char *str;
955 hdata.data.named.pgm = buffer;
956 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
957 buffer += i; buffersize -= i;
958 hdata.data.named.observer = buffer;
959 i = 1+snprintf(buffer, buffersize,
960 "%-20.20s "
961 "OBSERVER / AGENCY", str);
962 buffer += i; buffersize -= i;
963 }
964
965 hdata.data.named.marker =
966 "RTCM3TORINEX "
967 "MARKER NAME";
968
969 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
970 "GEODETIC "
971 "MARKER TYPE";
972
973 hdata.data.named.receiver =
974 " "
975 "REC # / TYPE / VERS";
976
977 hdata.data.named.antenna =
978 " "
979 "ANT # / TYPE";
980
981 hdata.data.named.position =
982 " .0000 .0000 .0000 "
983 "APPROX POSITION XYZ";
984
985 hdata.data.named.antennaposition =
986 " .0000 .0000 .0000 "
987 "ANTENNA: DELTA H/E/N";
988
989 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
990 " 1 1 "
991 "WAVELENGTH FACT L1/2";
992
993 if(Parser->rinex3)
994 {
995#define CHECKFLAGSNEW(a, b, c) \
996 if(flags & GNSSDF_##b##DATA) \
997 { \
998 Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
999 Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1000 ++Parser->numdatatypes##a; \
1001 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#c); \
1002 tbufferpos += 4; \
1003 }
1004
1005 int flags = Parser->startflags;
1006 char tbuffer[6*RINEXENTRY_NUMBER+1];
1007 int tbufferpos = 0;
1008 for(i = 0; i < Parser->Data.numsats; ++i)
1009 flags |= Parser->Data.dataflags[i];
1010
1011 CHECKFLAGSNEW(GPS, C1, C1C)
1012 CHECKFLAGSNEW(GPS, L1C, L1C)
1013 CHECKFLAGSNEW(GPS, D1C, D1C)
1014 CHECKFLAGSNEW(GPS, S1C, S1C)
1015 CHECKFLAGSNEW(GPS, P1, C1P)
1016 CHECKFLAGSNEW(GPS, L1P, L1P)
1017 CHECKFLAGSNEW(GPS, D1P, D1P)
1018 CHECKFLAGSNEW(GPS, S1P, S1P)
1019
1020 hdata.data.named.typesofobsS = buffer;
1021 i = 1+snprintf(buffer, buffersize,
1022 "S %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1023 buffer += i; buffersize -= i;
1024
1025 CHECKFLAGSNEW(GPS, P2, C2P)
1026 CHECKFLAGSNEW(GPS, L2P, L2P)
1027 CHECKFLAGSNEW(GPS, D2P, D2P)
1028 CHECKFLAGSNEW(GPS, S2P, S2P)
1029 CHECKFLAGSNEW(GPS, C2, C2X)
1030 CHECKFLAGSNEW(GPS, L2C, L2X)
1031 CHECKFLAGSNEW(GPS, D2C, D2X)
1032 CHECKFLAGSNEW(GPS, S2C, S2X)
1033
1034 hdata.data.named.typesofobsG = buffer;
1035 i = 1+snprintf(buffer, buffersize,
1036 "G %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1037 if(Parser->numdatatypesGPS>13)
1038 {
1039 i += snprintf(buffer+i-1, buffersize,
1040 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1041 }
1042 buffer += i; buffersize -= i;
1043
1044 tbufferpos = 0;
1045
1046 CHECKFLAGSNEW(GLO, C1, C1C)
1047 CHECKFLAGSNEW(GLO, L1C, L1C)
1048 CHECKFLAGSNEW(GLO, D1C, D1C)
1049 CHECKFLAGSNEW(GLO, S1C, S1C)
1050 CHECKFLAGSNEW(GLO, P1, C1P)
1051 CHECKFLAGSNEW(GLO, L1P, L1P)
1052 CHECKFLAGSNEW(GLO, D1P, D1P)
1053 CHECKFLAGSNEW(GLO, S1P, S1P)
1054 CHECKFLAGSNEW(GLO, P2, C2P)
1055 CHECKFLAGSNEW(GLO, L2P, L2P)
1056 CHECKFLAGSNEW(GLO, D2P, D2P)
1057 CHECKFLAGSNEW(GLO, S2P, S2P)
1058 CHECKFLAGSNEW(GLO, C2, C2C)
1059 CHECKFLAGSNEW(GLO, L2C, L2C)
1060 CHECKFLAGSNEW(GLO, D2C, D2C)
1061 CHECKFLAGSNEW(GLO, S2C, S2C)
1062
1063 hdata.data.named.typesofobsR = buffer;
1064 i = 1+snprintf(buffer, buffersize,
1065 "R %3d%-52.52s SYS / # / OBS TYPES", Parser->numdatatypesGLO, tbuffer);
1066 if(Parser->numdatatypesGLO>13)
1067 {
1068 i += snprintf(buffer+i-1, buffersize,
1069 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1070 }
1071 buffer += i; buffersize -= i;
1072 }
1073 else
1074 {
1075#define CHECKFLAGS(a, b) \
1076 if(flags & GNSSDF_##a##DATA) \
1077 { \
1078 if(data[RINEXENTRY_##b##DATA]) \
1079 { \
1080 Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1081 Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1082 } \
1083 else \
1084 { \
1085 Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1086 Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1087 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1088 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
1089 tbufferpos += 6; \
1090 } \
1091 }
1092
1093 int flags = Parser->startflags;
1094 int data[RINEXENTRY_NUMBER];
1095 char tbuffer[6*RINEXENTRY_NUMBER+1];
1096 int tbufferpos = 0;
1097 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
1098 data[i] = 0;
1099 for(i = 0; i < Parser->Data.numsats; ++i)
1100 flags |= Parser->Data.dataflags[i];
1101
1102 CHECKFLAGS(C1,C1)
1103 CHECKFLAGS(C2,C2)
1104 CHECKFLAGS(P1,P1)
1105 CHECKFLAGS(P2,P2)
1106 CHECKFLAGS(L1C,L1)
1107 CHECKFLAGS(L1P,L1)
1108 CHECKFLAGS(L2C,L2)
1109 CHECKFLAGS(L2P,L2)
1110 CHECKFLAGS(D1C,D1)
1111 CHECKFLAGS(D1P,D1)
1112 CHECKFLAGS(D2C,D2)
1113 CHECKFLAGS(D2P,D2)
1114 CHECKFLAGS(S1C,S1)
1115 CHECKFLAGS(S1P,S1)
1116 CHECKFLAGS(S2C,S2)
1117 CHECKFLAGS(S2P,S2)
1118
1119 hdata.data.named.typesofobs = buffer;
1120 i = 1+snprintf(buffer, buffersize,
1121 "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer);
1122 if(Parser->numdatatypesGPS>9)
1123 {
1124 i += snprintf(buffer+i-1, buffersize,
1125 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
1126 }
1127 buffer += i; buffersize -= i;
1128 }
1129
1130 {
1131 struct converttimeinfo cti;
1132 converttime(&cti, Parser->Data.week,
1133 (int)floor(Parser->Data.timeofweek/1000.0));
1134 hdata.data.named.timeoffirstobs = buffer;
1135 i = 1+snprintf(buffer, buffersize,
1136 " %4d %2d %2d %2d %2d %10.7f GPS "
1137 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
1138 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
1139
1140 buffer += i; buffersize -= i;
1141 }
1142
1143 hdata.numheaders = 15;
1144
1145 if(Parser->headerfile)
1146 {
1147 FILE *fh;
1148 if((fh = fopen(Parser->headerfile, "r")))
1149 {
1150 size_t siz;
1151 char *lastblockstart;
1152 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
1153 {
1154 buffer[siz] = '\n';
1155 if(siz == buffersize)
1156 {
1157 RTCM3Error("Header file is too large. Only %d bytes read.",
1158 (int)siz);
1159 }
1160 /* scan the file line by line and enter the entries in the list */
1161 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
1162 /* overwrites entries, except for comments */
1163 lastblockstart = buffer;
1164 for(i = 0; i < (int)siz; ++i)
1165 {
1166 if(buffer[i] == '\n')
1167 { /* we found a line */
1168 char *end;
1169 while(buffer[i+1] == '\r')
1170 ++i; /* skip \r in case there are any */
1171 end = buffer+i;
1172 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
1173 *(end--) = 0;
1174 if(end-lastblockstart < 60+5) /* short line */
1175 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
1176 else
1177 {
1178 int pos;
1179 if(!strcmp("COMMENT", lastblockstart+60))
1180 pos = hdata.numheaders;
1181 else
1182 {
1183 for(pos = 0; pos < hdata.numheaders; ++pos)
1184 {
1185 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
1186 break;
1187 }
1188 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
1189 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
1190 {
1191 RTCM3Error("Overwriting header '%s' is dangerous.\n",
1192 lastblockstart+60);
1193 }
1194 }
1195 if(pos >= MAXHEADERLINES)
1196 {
1197 RTCM3Error("Maximum number of header lines of %d reached.\n",
1198 MAXHEADERLINES);
1199 }
1200 else if(!strcmp("END OF HEADER", lastblockstart+60))
1201 {
1202 RTCM3Error("End of header ignored.\n");
1203 }
1204 else
1205 {
1206 hdata.data.unnamed[pos] = lastblockstart;
1207 if(pos == hdata.numheaders)
1208 ++hdata.numheaders;
1209 }
1210 }
1211 lastblockstart = buffer+i+1;
1212 }
1213 }
1214 }
1215 else
1216 {
1217 RTCM3Error("Could not read data from headerfile '%s'.\n",
1218 Parser->headerfile);
1219 }
1220 fclose(fh);
1221 }
1222 else
1223 {
1224 RTCM3Error("Could not open header datafile '%s'.\n",
1225 Parser->headerfile);
1226 }
1227 }
1228
1229 for(i = 0; i < hdata.numheaders; ++i)
1230 {
1231 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
1232 RTCM3Text("%s\n", hdata.data.unnamed[i]);
1233 }
1234 RTCM3Text(" "
1235 "END OF HEADER\n");
1236#endif
1237}
1238
1239static void ConvLine(FILE *file, const char *fmt, ...)
1240{
1241 char buffer[100], *b;
1242 va_list v;
1243 va_start(v, fmt);
1244 vsnprintf(buffer, sizeof(buffer), fmt, v);
1245 for(b = buffer; *b; ++b)
1246 {
1247 if(*b == 'e') *b = 'D';
1248 }
1249 fprintf(file, "%s", buffer);
1250 va_end(v);
1251}
1252
1253void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
1254{
1255 Parser->Message[Parser->MessageSize++] = byte;
1256 if(Parser->MessageSize >= Parser->NeedBytes)
1257 {
1258 int r;
1259 while((r = RTCM3Parser(Parser)))
1260 {
1261 if(r == 1020 || r == 1019)
1262 {
1263 FILE *file = 0;
1264
1265 if(Parser->rinex3 && !(file = Parser->gpsfile))
1266 {
1267 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
1268 if(n)
1269 {
1270 if(!(Parser->gpsfile = fopen(n, "w")))
1271 {
1272 RTCM3Error("Could not open ephemeris output file.\n");
1273 }
1274 else
1275 {
1276 char buffer[100];
1277 fprintf(Parser->gpsfile,
1278 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
1279 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1280 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1281 }
1282 Parser->gpsephemeris = 0;
1283 Parser->glonassephemeris = 0;
1284 file = Parser->gpsfile;
1285 }
1286 }
1287 else
1288 {
1289 if(r == 1020)
1290 {
1291 if(Parser->glonassephemeris)
1292 {
1293 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
1294 {
1295 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
1296 }
1297 else
1298 {
1299 char buffer[100];
1300 fprintf(Parser->glonassfile,
1301 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
1302 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1303 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1304 }
1305 Parser->glonassephemeris = 0;
1306 }
1307 file = Parser->glonassfile;
1308 }
1309 else if(r == 1019)
1310 {
1311 if(Parser->gpsephemeris)
1312 {
1313 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
1314 {
1315 RTCM3Error("Could not open GPS ephemeris output file.\n");
1316 }
1317 else
1318 {
1319 char buffer[100];
1320 fprintf(Parser->gpsfile,
1321 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
1322 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
1323 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
1324 }
1325 Parser->gpsephemeris = 0;
1326 }
1327 file = Parser->gpsfile;
1328 }
1329 }
1330 if(file)
1331 {
1332 if(r == 1020)
1333 {
1334 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
1335 int w = e->GPSWeek, tow = e->GPSTOW, i;
1336 struct converttimeinfo cti;
1337
1338 updatetime(&w, &tow, e->tb*1000, 1);
1339 converttime(&cti, w, tow);
1340
1341 i = e->tk-3*60*60; if(i < 0) i += 86400;
1342
1343 if(Parser->rinex3)
1344 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
1345 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
1346 cti.second, -e->tau, e->gamma, (double) i);
1347 else
1348 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
1349 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
1350 (double) cti.second, -e->tau, e->gamma, (double) i);
1351 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
1352 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
1353 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
1354 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
1355 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
1356 e->z_velocity, e->z_acceleration, (double) e->E);
1357 }
1358 else /* if(r == 1019) */
1359 {
1360 struct gpsephemeris *e = &Parser->ephemerisGPS;
1361 double d; /* temporary variable */
1362 unsigned long int i; /* temporary variable */
1363 struct converttimeinfo cti;
1364 converttime(&cti, e->GPSweek, e->TOC);
1365
1366 if(Parser->rinex3)
1367 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
1368 e->satellite, cti.year, cti.month, cti.day, cti.hour,
1369 cti.minute, cti.second, e->clock_bias, e->clock_drift,
1370 e->clock_driftrate);
1371 else
1372 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
1373 e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
1374 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
1375 e->clock_driftrate);
1376 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
1377 e->Crs, e->Delta_n, e->M0);
1378 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
1379 e->e, e->Cus, e->sqrt_A);
1380 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n",
1381 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
1382 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0,
1383 e->Crc, e->omega, e->OMEGADOT);
1384 d = 0;
1385 i = e->flags;
1386 if(i & GPSEPHF_L2CACODE)
1387 d += 2.0;
1388 if(i & GPSEPHF_L2PCODE)
1389 d += 1.0;
1390 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
1391 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
1392 if(e->URAindex <= 6) /* URA index */
1393 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
1394 else
1395 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
1396 /* 15 indicates not to use satellite. We can't handle this special
1397 case, so we create a high "non"-accuracy value. */
1398 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d,
1399 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
1400
1401 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0);
1402 /* TOW */
1403 }
1404 }
1405 }
1406 else
1407 {
1408 int i, j, o;
1409 struct converttimeinfo cti;
1410
1411 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
1412 {
1413 ++Parser->init;
1414
1415 if(Parser->init == NUMSTARTSKIP)
1416 HandleHeader(Parser);
1417 else
1418 {
1419 for(i = 0; i < Parser->Data.numsats; ++i)
1420 Parser->startflags |= Parser->Data.dataflags[i];
1421 continue;
1422 }
1423 }
1424 if(r == 2 && !Parser->validwarning)
1425 {
1426 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
1427 " COMMENT\n");
1428 Parser->validwarning = 1;
1429 }
1430
1431 converttime(&cti, Parser->Data.week,
1432 (int)floor(Parser->Data.timeofweek/1000.0));
1433 if(Parser->rinex3)
1434 {
1435 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n",
1436 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
1437 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
1438 for(i = 0; i < Parser->Data.numsats; ++i)
1439 {
1440 int glo = 0;
1441 if(Parser->Data.satellites[i] <= PRN_GPS_END)
1442 RTCM3Text("G%02d", Parser->Data.satellites[i]);
1443 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
1444 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
1445 {
1446 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
1447 glo = 1;
1448 }
1449 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
1450 && Parser->Data.satellites[i] <= PRN_WAAS_END)
1451 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
1452 else
1453 RTCM3Text("%3d", Parser->Data.satellites[i]);
1454
1455 if(glo)
1456 {
1457 for(j = 0; j < Parser->numdatatypesGLO; ++j)
1458 {
1459 int df = Parser->dataflagGLO[j];
1460 int pos = Parser->dataposGLO[j];
1461 if((Parser->Data.dataflags[i] & df)
1462 && !isnan(Parser->Data.measdata[i][pos])
1463 && !isinf(Parser->Data.measdata[i][pos]))
1464 {
1465 char lli = ' ';
1466 char snr = ' ';
1467 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1468 {
1469 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1470 lli = '1';
1471 snr = '0'+Parser->Data.snrL1[i];
1472 }
1473 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1474 {
1475 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1476 lli = '1';
1477 snr = '0'+Parser->Data.snrL2[i];
1478 }
1479 RTCM3Text("%14.3f%c%c",
1480 Parser->Data.measdata[i][pos],lli,snr);
1481 }
1482 else
1483 { /* no or illegal data */
1484 RTCM3Text(" ");
1485 }
1486 }
1487 }
1488 else
1489 {
1490 for(j = 0; j < Parser->numdatatypesGPS; ++j)
1491 {
1492 int df = Parser->dataflagGPS[j];
1493 int pos = Parser->dataposGPS[j];
1494 if((Parser->Data.dataflags[i] & df)
1495 && !isnan(Parser->Data.measdata[i][pos])
1496 && !isinf(Parser->Data.measdata[i][pos]))
1497 {
1498 char lli = ' ';
1499 char snr = ' ';
1500 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1501 {
1502 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1503 lli = '1';
1504 snr = '0'+Parser->Data.snrL1[i];
1505 }
1506 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1507 {
1508 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1509 lli = '1';
1510 snr = '0'+Parser->Data.snrL2[i];
1511 }
1512 RTCM3Text("%14.3f%c%c",
1513 Parser->Data.measdata[i][pos],lli,snr);
1514 }
1515 else
1516 { /* no or illegal data */
1517 RTCM3Text(" ");
1518 }
1519 }
1520 }
1521 RTCM3Text("\n");
1522 }
1523 }
1524 else
1525 {
1526 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
1527 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
1528 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
1529 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
1530 {
1531 if(Parser->Data.satellites[i] <= PRN_GPS_END)
1532 RTCM3Text("G%02d", Parser->Data.satellites[i]);
1533 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
1534 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
1535 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
1536 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
1537 && Parser->Data.satellites[i] <= PRN_WAAS_END)
1538 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
1539 else
1540 RTCM3Text("%3d", Parser->Data.satellites[i]);
1541 }
1542 RTCM3Text("\n");
1543 o = 12;
1544 j = Parser->Data.numsats - 12;
1545 while(j > 0)
1546 {
1547 RTCM3Text(" ");
1548 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
1549 {
1550 if(Parser->Data.satellites[i] <= PRN_GPS_END)
1551 RTCM3Text("G%02d", Parser->Data.satellites[i]);
1552 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
1553 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
1554 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
1555 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
1556 && Parser->Data.satellites[i] <= PRN_WAAS_END)
1557 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
1558 else
1559 RTCM3Text("%3d", Parser->Data.satellites[i]);
1560 }
1561 RTCM3Text("\n");
1562 j -= 12;
1563 o += 12;
1564 }
1565 for(i = 0; i < Parser->Data.numsats; ++i)
1566 {
1567 for(j = 0; j < Parser->numdatatypesGPS; ++j)
1568 {
1569 int v = 0;
1570 int df = Parser->dataflag[j];
1571 int pos = Parser->datapos[j];
1572 if((Parser->Data.dataflags[i] & df)
1573 && !isnan(Parser->Data.measdata[i][pos])
1574 && !isinf(Parser->Data.measdata[i][pos]))
1575 {
1576 v = 1;
1577 }
1578 else
1579 {
1580 df = Parser->dataflagGPS[j];
1581 pos = Parser->dataposGPS[j];
1582
1583 if((Parser->Data.dataflags[i] & df)
1584 && !isnan(Parser->Data.measdata[i][pos])
1585 && !isinf(Parser->Data.measdata[i][pos]))
1586 {
1587 v = 1;
1588 }
1589 }
1590
1591 if(!v)
1592 { /* no or illegal data */
1593 RTCM3Text(" ");
1594 }
1595 else
1596 {
1597 char lli = ' ';
1598 char snr = ' ';
1599 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1600 {
1601 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1602 lli = '1';
1603 snr = '0'+Parser->Data.snrL1[i];
1604 }
1605 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1606 {
1607 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1608 lli = '1';
1609 snr = '0'+Parser->Data.snrL2[i];
1610 }
1611 RTCM3Text("%14.3f%c%c",
1612 Parser->Data.measdata[i][pos],lli,snr);
1613 }
1614 if(j%5 == 4 || j == Parser->numdatatypesGPS-1)
1615 RTCM3Text("\n");
1616 }
1617 }
1618 }
1619 }
1620 }
1621 }
1622}
1623
1624#ifndef NO_RTCM3_MAIN
1625static char datestr[] = "$Date: 2008/03/25 15:10:48 $";
1626
1627/* The string, which is send as agent in HTTP request */
1628#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
1629
1630#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
1631
1632static const char encodingTable [64] = {
1633 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1634 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1635 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1636 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1637};
1638
1639/* does not buffer overrun, but breaks directly after an error */
1640/* returns the number of required bytes */
1641static int encode(char *buf, int size, const char *user, const char *pwd)
1642{
1643 unsigned char inbuf[3];
1644 char *out = buf;
1645 int i, sep = 0, fill = 0, bytes = 0;
1646
1647 while(*user || *pwd)
1648 {
1649 i = 0;
1650 while(i < 3 && *user) inbuf[i++] = *(user++);
1651 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
1652 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
1653 while(i < 3) {inbuf[i++] = 0; ++fill; }
1654 if(out-buf < size-1)
1655 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
1656 if(out-buf < size-1)
1657 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
1658 | ((inbuf [1] & 0xF0) >> 4)];
1659 if(out-buf < size-1)
1660 {
1661 if(fill == 2)
1662 *(out++) = '=';
1663 else
1664 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
1665 | ((inbuf [2] & 0xC0) >> 6)];
1666 }
1667 if(out-buf < size-1)
1668 {
1669 if(fill >= 1)
1670 *(out++) = '=';
1671 else
1672 *(out++) = encodingTable[inbuf [2] & 0x3F];
1673 }
1674 bytes += 4;
1675 }
1676 if(out-buf < size)
1677 *out = 0;
1678 return bytes;
1679}
1680
1681static int stop = 0;
1682
1683struct Args
1684{
1685 const char *server;
1686 const char *port;
1687 int mode;
1688 int timeout;
1689 int rinex3;
1690 const char *user;
1691 const char *password;
1692 const char *proxyhost;
1693 const char *proxyport;
1694 const char *nmea;
1695 const char *data;
1696 const char *headerfile;
1697 const char *gpsephemeris;
1698 const char *glonassephemeris;
1699};
1700
1701/* option parsing */
1702#ifdef NO_LONG_OPTS
1703#define LONG_OPT(a)
1704#else
1705#define LONG_OPT(a) a
1706static struct option opts[] = {
1707{ "data", required_argument, 0, 'd'},
1708{ "server", required_argument, 0, 's'},
1709{ "password", required_argument, 0, 'p'},
1710{ "port", required_argument, 0, 'r'},
1711{ "timeout", required_argument, 0, 't'},
1712{ "header", required_argument, 0, 'f'},
1713{ "user", required_argument, 0, 'u'},
1714{ "gpsephemeris", required_argument, 0, 'E'},
1715{ "glonassephemeris", required_argument, 0, 'G'},
1716{ "rinex3", no_argument, 0, '3'},
1717{ "proxyport", required_argument, 0, 'R'},
1718{ "proxyhost", required_argument, 0, 'S'},
1719{ "nmea", required_argument, 0, 'n'},
1720{ "mode", required_argument, 0, 'M'},
1721{ "help", no_argument, 0, 'h'},
1722{0,0,0,0}};
1723#endif
1724#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
1725
1726enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
1727
1728static const char *geturl(const char *url, struct Args *args)
1729{
1730 static char buf[1000];
1731 static char *Buffer = buf;
1732 static char *Bufend = buf+sizeof(buf);
1733
1734 if(strncmp("ntrip:", url, 6))
1735 return "URL must start with 'ntrip:'.";
1736 url += 6; /* skip ntrip: */
1737
1738 if(*url != '@' && *url != '/')
1739 {
1740 /* scan for mountpoint */
1741 args->data = Buffer;
1742 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
1743 *(Buffer++) = *(url++);
1744 if(Buffer == args->data)
1745 return "Mountpoint required.";
1746 else if(Buffer >= Bufend-1)
1747 return "Parsing buffer too short.";
1748 *(Buffer++) = 0;
1749 }
1750
1751 if(*url == '/') /* username and password */
1752 {
1753 ++url;
1754 args->user = Buffer;
1755 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
1756 *(Buffer++) = *(url++);
1757 if(Buffer == args->user)
1758 return "Username cannot be empty.";
1759 else if(Buffer >= Bufend-1)
1760 return "Parsing buffer too short.";
1761 *(Buffer++) = 0;
1762
1763 if(*url == ':') ++url;
1764
1765 args->password = Buffer;
1766 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
1767 *(Buffer++) = *(url++);
1768 if(Buffer == args->password)
1769 return "Password cannot be empty.";
1770 else if(Buffer >= Bufend-1)
1771 return "Parsing buffer too short.";
1772 *(Buffer++) = 0;
1773 }
1774
1775 if(*url == '@') /* server */
1776 {
1777 ++url;
1778 if(*url != '@' && *url != ':')
1779 {
1780 args->server = Buffer;
1781 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
1782 *(Buffer++) = *(url++);
1783 if(Buffer == args->server)
1784 return "Servername cannot be empty.";
1785 else if(Buffer >= Bufend-1)
1786 return "Parsing buffer too short.";
1787 *(Buffer++) = 0;
1788 }
1789
1790 if(*url == ':')
1791 {
1792 ++url;
1793 args->port = Buffer;
1794 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
1795 *(Buffer++) = *(url++);
1796 if(Buffer == args->port)
1797 return "Port cannot be empty.";
1798 else if(Buffer >= Bufend-1)
1799 return "Parsing buffer too short.";
1800 *(Buffer++) = 0;
1801 }
1802
1803 if(*url == '@') /* proxy */
1804 {
1805 ++url;
1806 args->proxyhost = Buffer;
1807 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
1808 *(Buffer++) = *(url++);
1809 if(Buffer == args->proxyhost)
1810 return "Proxy servername cannot be empty.";
1811 else if(Buffer >= Bufend-1)
1812 return "Parsing buffer too short.";
1813 *(Buffer++) = 0;
1814
1815 if(*url == ':')
1816 {
1817 ++url;
1818 args->proxyport = Buffer;
1819 while(*url && *url != ';' && Buffer != Bufend)
1820 *(Buffer++) = *(url++);
1821 if(Buffer == args->proxyport)
1822 return "Proxy port cannot be empty.";
1823 else if(Buffer >= Bufend-1)
1824 return "Parsing buffer too short.";
1825 *(Buffer++) = 0;
1826 }
1827 }
1828 }
1829 if(*url == ';') /* NMEA */
1830 {
1831 args->nmea = ++url;
1832 while(*url)
1833 ++url;
1834 }
1835
1836 return *url ? "Garbage at end of server string." : 0;
1837}
1838
1839static int getargs(int argc, char **argv, struct Args *args)
1840{
1841 int res = 1;
1842 int getoptr;
1843 int help = 0;
1844 char *t;
1845
1846 args->server = "www.euref-ip.net";
1847 args->port = "2101";
1848 args->timeout = 60;
1849 args->user = "";
1850 args->password = "";
1851 args->data = 0;
1852 args->headerfile = 0;
1853 args->gpsephemeris = 0;
1854 args->glonassephemeris = 0;
1855 args->rinex3 = 0;
1856 args->nmea = 0;
1857 args->proxyhost = 0;
1858 args->proxyport = "2101";
1859 args->mode = AUTO;
1860 help = 0;
1861
1862 do
1863 {
1864
1865#ifdef NO_LONG_OPTS
1866 switch((getoptr = getopt(argc, argv, ARGOPT)))
1867#else
1868 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
1869#endif
1870 {
1871 case 's': args->server = optarg; break;
1872 case 'u': args->user = optarg; break;
1873 case 'p': args->password = optarg; break;
1874 case 'd': args->data = optarg; break;
1875 case 'f': args->headerfile = optarg; break;
1876 case 'E': args->gpsephemeris = optarg; break;
1877 case 'G': args->glonassephemeris = optarg; break;
1878 case 'r': args->port = optarg; break;
1879 case '3': args->rinex3 = 1; break;
1880 case 'S': args->proxyhost = optarg; break;
1881 case 'n': args->nmea = optarg; break;
1882 case 'R': args->proxyport = optarg; break;
1883 case 'h': help=1; break;
1884 case 'M':
1885 args->mode = 0;
1886 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
1887 args->mode = NTRIP1;
1888 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
1889 args->mode = HTTP;
1890 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
1891 args->mode = RTSP;
1892 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
1893 args->mode = AUTO;
1894 else args->mode = atoi(optarg);
1895 if((args->mode == 0) || (args->mode >= END))
1896 {
1897 fprintf(stderr, "Mode %s unknown\n", optarg);
1898 res = 0;
1899 }
1900 break;
1901 case 't':
1902 args->timeout = strtoul(optarg, &t, 10);
1903 if((t && *t) || args->timeout < 0)
1904 res = 0;
1905 break;
1906
1907 case 1:
1908 {
1909 const char *err;
1910 if((err = geturl(optarg, args)))
1911 {
1912 RTCM3Error("%s\n\n", err);
1913 res = 0;
1914 }
1915 }
1916 break;
1917 case -1: break;
1918 }
1919 } while(getoptr != -1 || !res);
1920
1921 datestr[0] = datestr[7];
1922 datestr[1] = datestr[8];
1923 datestr[2] = datestr[9];
1924 datestr[3] = datestr[10];
1925 datestr[5] = datestr[12];
1926 datestr[6] = datestr[13];
1927 datestr[8] = datestr[15];
1928 datestr[9] = datestr[16];
1929 datestr[4] = datestr[7] = '-';
1930 datestr[10] = 0;
1931
1932 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
1933 {
1934 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
1935 "Please specify only one navigation file.\n");
1936 res = 0;
1937 }
1938 else if(!res || help)
1939 {
1940 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
1941 "\nUsage: %s -s server -u user ...\n"
1942 " -d " LONG_OPT("--data ") "the requested data set\n"
1943 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
1944 " -s " LONG_OPT("--server ") "the server name or address\n"
1945 " -p " LONG_OPT("--password ") "the login password\n"
1946 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
1947 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
1948 " -u " LONG_OPT("--user ") "the user name\n"
1949 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
1950 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
1951 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
1952 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
1953 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
1954 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
1955 " -M " LONG_OPT("--mode ") "mode for data request\n"
1956 " Valid modes are:\n"
1957 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
1958 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
1959 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
1960 " 4, a, auto automatic detection (default)\n"
1961 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
1962 , revisionstr, datestr, argv[0], argv[0]);
1963 exit(1);
1964 }
1965 return res;
1966}
1967
1968/* let the output complete a block if necessary */
1969static void signalhandler(int sig)
1970{
1971 if(!stop)
1972 {
1973 RTCM3Error("Stop signal number %d received. "
1974 "Trying to terminate gentle.\n", sig);
1975 stop = 1;
1976 alarm(1);
1977 }
1978}
1979
1980#define ALARMTIME (2*60)
1981
1982/* for some reason we had to abort hard (maybe waiting for data */
1983#ifdef __GNUC__
1984static __attribute__ ((noreturn)) void signalhandler_alarm(
1985int sig __attribute__((__unused__)))
1986#else /* __GNUC__ */
1987static void signalhandler_alarm(int sig)
1988#endif /* __GNUC__ */
1989{
1990 RTCM3Error("Programm forcefully terminated.\n");
1991 exit(1);
1992}
1993
1994int main(int argc, char **argv)
1995{
1996 struct Args args;
1997 struct RTCM3ParserData Parser;
1998
1999 setbuf(stdout, 0);
2000 setbuf(stdin, 0);
2001 setbuf(stderr, 0);
2002
2003 {
2004 char *a;
2005 int i=0;
2006 for(a = revisionstr+11; *a && *a != ' '; ++a)
2007 revisionstr[i++] = *a;
2008 revisionstr[i] = 0;
2009 }
2010
2011 signal(SIGINT, signalhandler);
2012 signal(SIGALRM,signalhandler_alarm);
2013 signal(SIGQUIT,signalhandler);
2014 signal(SIGTERM,signalhandler);
2015 signal(SIGPIPE,signalhandler);
2016 memset(&Parser, 0, sizeof(Parser));
2017 {
2018 time_t tim;
2019 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
2020 Parser.GPSWeek = tim/(7*24*60*60);
2021 Parser.GPSTOW = tim%(7*24*60*60);
2022 }
2023
2024 if(getargs(argc, argv, &args))
2025 {
2026 int sockfd, numbytes;
2027 char buf[MAXDATASIZE];
2028 struct sockaddr_in their_addr; /* connector's address information */
2029 struct hostent *he;
2030 struct servent *se;
2031 const char *server, *port, *proxyserver = 0;
2032 char proxyport[6];
2033 char *b;
2034 long i;
2035 struct timeval tv;
2036
2037 alarm(ALARMTIME);
2038
2039 Parser.headerfile = args.headerfile;
2040 Parser.glonassephemeris = args.glonassephemeris;
2041 Parser.gpsephemeris = args.gpsephemeris;
2042 Parser.rinex3 = args.rinex3;
2043
2044 if(args.proxyhost)
2045 {
2046 int p;
2047 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
2048 p = i;
2049 else if(!(se = getservbyname(args.port, 0)))
2050 {
2051 RTCM3Error("Can't resolve port %s.", args.port);
2052 exit(1);
2053 }
2054 else
2055 {
2056 p = ntohs(se->s_port);
2057 }
2058 snprintf(proxyport, sizeof(proxyport), "%d", p);
2059 port = args.proxyport;
2060 proxyserver = args.server;
2061 server = args.proxyhost;
2062 }
2063 else
2064 {
2065 server = args.server;
2066 port = args.port;
2067 }
2068
2069 memset(&their_addr, 0, sizeof(struct sockaddr_in));
2070 if((i = strtol(port, &b, 10)) && (!b || !*b))
2071 their_addr.sin_port = htons(i);
2072 else if(!(se = getservbyname(port, 0)))
2073 {
2074 RTCM3Error("Can't resolve port %s.", port);
2075 exit(1);
2076 }
2077 else
2078 {
2079 their_addr.sin_port = se->s_port;
2080 }
2081 if(!(he=gethostbyname(server)))
2082 {
2083 RTCM3Error("Server name lookup failed for '%s'.\n", server);
2084 exit(1);
2085 }
2086 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
2087 {
2088 perror("socket");
2089 exit(1);
2090 }
2091
2092 tv.tv_sec = args.timeout;
2093 tv.tv_usec = 0;
2094 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
2095 {
2096 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
2097 exit(1);
2098 }
2099
2100 their_addr.sin_family = AF_INET;
2101 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
2102
2103 if(args.data && args.mode == RTSP)
2104 {
2105 struct sockaddr_in local;
2106 int sockudp, localport;
2107 int cseq = 1;
2108 socklen_t len;
2109
2110 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2111 {
2112 perror("socket");
2113 exit(1);
2114 }
2115 /* fill structure with local address information for UDP */
2116 memset(&local, 0, sizeof(local));
2117 local.sin_family = AF_INET;
2118 local.sin_port = htons(0);
2119 local.sin_addr.s_addr = htonl(INADDR_ANY);
2120 len = sizeof(local);
2121 /* bind() in order to get a random RTP client_port */
2122 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
2123 {
2124 perror("bind");
2125 exit(1);
2126 }
2127 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
2128 {
2129 localport = ntohs(local.sin_port);
2130 }
2131 else
2132 {
2133 perror("local access failed");
2134 exit(1);
2135 }
2136 if(connect(sockfd, (struct sockaddr *)&their_addr,
2137 sizeof(struct sockaddr)) == -1)
2138 {
2139 perror("connect");
2140 exit(1);
2141 }
2142 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
2143 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
2144 "CSeq: %d\r\n"
2145 "Ntrip-Version: Ntrip/2.0\r\n"
2146 "Ntrip-Component: Ntripclient\r\n"
2147 "User-Agent: %s/%s\r\n"
2148 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
2149 "Authorization: Basic ",
2150 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2151 args.data, cseq++, AGENTSTRING, revisionstr, localport);
2152 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
2153 {
2154 RTCM3Error("Requested data too long\n");
2155 exit(1);
2156 }
2157 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
2158 if(i > MAXDATASIZE-4)
2159 {
2160 RTCM3Error("Username and/or password too long\n");
2161 exit(1);
2162 }
2163 buf[i++] = '\r';
2164 buf[i++] = '\n';
2165 buf[i++] = '\r';
2166 buf[i++] = '\n';
2167 if(args.nmea)
2168 {
2169 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
2170 if(j >= 0 && j < MAXDATASIZE-i)
2171 i += j;
2172 else
2173 {
2174 RTCM3Error("NMEA string too long\n");
2175 exit(1);
2176 }
2177 }
2178 if(send(sockfd, buf, (size_t)i, 0) != i)
2179 {
2180 perror("send");
2181 exit(1);
2182 }
2183 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2184 {
2185 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
2186 {
2187 int serverport = 0, session = 0;
2188 const char *portcheck = "server_port=";
2189 const char *sessioncheck = "session: ";
2190 int l = strlen(portcheck)-1;
2191 int j=0;
2192 for(i = 0; j != l && i < numbytes-l; ++i)
2193 {
2194 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
2195 ;
2196 }
2197 if(i == numbytes-l)
2198 {
2199 RTCM3Error("No server port number found\n");
2200 exit(1);
2201 }
2202 else
2203 {
2204 i+=l;
2205 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
2206 serverport = serverport * 10 + buf[i++]-'0';
2207 if(buf[i] != '\r' && buf[i] != ';')
2208 {
2209 RTCM3Error("Could not extract server port\n");
2210 exit(1);
2211 }
2212 }
2213 l = strlen(sessioncheck)-1;
2214 j=0;
2215 for(i = 0; j != l && i < numbytes-l; ++i)
2216 {
2217 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
2218 ;
2219 }
2220 if(i == numbytes-l)
2221 {
2222 RTCM3Error("No session number found\n");
2223 exit(1);
2224 }
2225 else
2226 {
2227 i+=l;
2228 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
2229 session = session * 10 + buf[i++]-'0';
2230 if(buf[i] != '\r')
2231 {
2232 RTCM3Error("Could not extract session number\n");
2233 exit(1);
2234 }
2235 }
2236
2237 i = snprintf(buf, MAXDATASIZE,
2238 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
2239 "CSeq: %d\r\n"
2240 "Session: %d\r\n"
2241 "\r\n",
2242 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2243 args.data, cseq++, session);
2244
2245 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
2246 {
2247 RTCM3Error("Requested data too long\n");
2248 exit(1);
2249 }
2250 if(send(sockfd, buf, (size_t)i, 0) != i)
2251 {
2252 perror("send");
2253 exit(1);
2254 }
2255 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2256 {
2257 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
2258 {
2259 struct sockaddr_in addrRTP;
2260 /* fill structure with caster address information for UDP */
2261 memset(&addrRTP, 0, sizeof(addrRTP));
2262 addrRTP.sin_family = AF_INET;
2263 addrRTP.sin_port = htons(serverport);
2264 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
2265 len = sizeof(addrRTP);
2266 int ts = 0;
2267 int sn = 0;
2268 int ssrc = 0;
2269 int init = 0;
2270 int u, v, w;
2271 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
2272 (struct sockaddr*) &addrRTP, &len)) > 0)
2273 {
2274 alarm(ALARMTIME);
2275 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
2276 {
2277 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
2278 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
2279 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
2280 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
2281 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
2282
2283 if(init)
2284 {
2285 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
2286 if(ssrc != w || ts > v)
2287 {
2288 RTCM3Error("Illegal UDP data received.\n");
2289 exit(1);
2290 }
2291 if(u > sn) /* don't show out-of-order packets */
2292 fwrite(buf+12, (size_t)i-12, 1, stdout);
2293 }
2294 sn = u; ts = v; ssrc = w; init = 1;
2295 }
2296 else
2297 {
2298 RTCM3Error("Illegal UDP header.\n");
2299 exit(1);
2300 }
2301 }
2302 }
2303 i = snprintf(buf, MAXDATASIZE,
2304 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
2305 "CSeq: %d\r\n"
2306 "Session: %d\r\n"
2307 "\r\n",
2308 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
2309 args.data, cseq++, session);
2310
2311 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
2312 {
2313 RTCM3Error("Requested data too long\n");
2314 exit(1);
2315 }
2316 if(send(sockfd, buf, (size_t)i, 0) != i)
2317 {
2318 perror("send");
2319 exit(1);
2320 }
2321 }
2322 else
2323 {
2324 RTCM3Error("Could not start data stream.\n");
2325 exit(1);
2326 }
2327 }
2328 else
2329 {
2330 RTCM3Error("Could not setup initial control connection.\n");
2331 exit(1);
2332 }
2333 }
2334 else
2335 {
2336 perror("recv");
2337 exit(1);
2338 }
2339 }
2340 else
2341 {
2342 if(connect(sockfd, (struct sockaddr *)&their_addr,
2343 sizeof(struct sockaddr)) == -1)
2344 {
2345 perror("connect");
2346 exit(1);
2347 }
2348 if(!args.data)
2349 {
2350 i = snprintf(buf, MAXDATASIZE,
2351 "GET %s%s%s%s/ HTTP/1.0\r\n"
2352 "Host: %s\r\n%s"
2353 "User-Agent: %s/%s\r\n"
2354 "Connection: close\r\n"
2355 "\r\n"
2356 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
2357 proxyserver ? ":" : "", proxyserver ? proxyport : "",
2358 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
2359 AGENTSTRING, revisionstr);
2360 }
2361 else
2362 {
2363 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
2364 "GET %s%s%s%s/%s HTTP/1.0\r\n"
2365 "Host: %s\r\n%s"
2366 "User-Agent: %s/%s\r\n"
2367 "Connection: close\r\n"
2368 "Authorization: Basic "
2369 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
2370 proxyserver ? ":" : "", proxyserver ? proxyport : "",
2371 args.data, args.server,
2372 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
2373 AGENTSTRING, revisionstr);
2374 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
2375 {
2376 RTCM3Error("Requested data too long\n");
2377 exit(1);
2378 }
2379 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
2380 if(i > MAXDATASIZE-4)
2381 {
2382 RTCM3Error("Username and/or password too long\n");
2383 exit(1);
2384 }
2385 buf[i++] = '\r';
2386 buf[i++] = '\n';
2387 buf[i++] = '\r';
2388 buf[i++] = '\n';
2389 if(args.nmea)
2390 {
2391 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
2392 if(j >= 0 && j < MAXDATASIZE-i)
2393 i += j;
2394 else
2395 {
2396 RTCM3Error("NMEA string too long\n");
2397 exit(1);
2398 }
2399 }
2400 }
2401 if(send(sockfd, buf, (size_t)i, 0) != i)
2402 {
2403 perror("send");
2404 exit(1);
2405 }
2406 if(args.data)
2407 {
2408 int k = 0;
2409 int chunkymode = 0;
2410 int starttime = time(0);
2411 int lastout = starttime;
2412 int totalbytes = 0;
2413 int chunksize = 0;
2414
2415 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
2416 {
2417 alarm(ALARMTIME);
2418 if(!k)
2419 {
2420 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
2421 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
2422 {
2423 const char *datacheck = "Content-Type: gnss/data\r\n";
2424 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
2425 int l = strlen(datacheck)-1;
2426 int j=0;
2427 for(i = 0; j != l && i < numbytes-l; ++i)
2428 {
2429 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
2430 ;
2431 }
2432 if(i == numbytes-l)
2433 {
2434 RTCM3Error("No 'Content-Type: gnss/data' found\n");
2435 exit(1);
2436 }
2437 l = strlen(chunkycheck)-1;
2438 j=0;
2439 for(i = 0; j != l && i < numbytes-l; ++i)
2440 {
2441 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
2442 ;
2443 }
2444 if(i < numbytes-l)
2445 chunkymode = 1;
2446 }
2447 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
2448 {
2449 RTCM3Error("Could not get the requested data: ");
2450 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
2451 {
2452 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
2453 }
2454 RTCM3Error("\n");
2455 exit(1);
2456 }
2457 else if(args.mode != NTRIP1)
2458 {
2459 if(args.mode != AUTO)
2460 {
2461 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
2462 args.mode == AUTO ? ", falling back to NTRIP1" : "");
2463 }
2464 if(args.mode == HTTP)
2465 exit(1);
2466 }
2467 ++k;
2468 }
2469 else
2470 {
2471 if(chunkymode)
2472 {
2473 int stop = 0;
2474 int pos = 0;
2475 while(!stop && pos < numbytes)
2476 {
2477 switch(chunkymode)
2478 {
2479 case 1: /* reading number starts */
2480 chunksize = 0;
2481 ++chunkymode; /* no break */
2482 case 2: /* during reading number */
2483 i = buf[pos++];
2484 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
2485 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
2486 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
2487 else if(i == '\r') ++chunkymode;
2488 else if(i == ';') chunkymode = 5;
2489 else stop = 1;
2490 break;
2491 case 3: /* scanning for return */
2492 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
2493 else stop = 1;
2494 break;
2495 case 4: /* output data */
2496 i = numbytes-pos;
2497 if(i > chunksize) i = chunksize;
2498 {
2499 int z;
2500 for(z = 0; z < i && !stop; ++z)
2501 HandleByte(&Parser, (unsigned int) buf[pos+z]);
2502 }
2503 totalbytes += i;
2504 chunksize -= i;
2505 pos += i;
2506 if(!chunksize)
2507 chunkymode = 1;
2508 break;
2509 case 5:
2510 if(i == '\r') chunkymode = 3;
2511 break;
2512 }
2513 }
2514 if(stop)
2515 {
2516 RTCM3Error("Error in chunky transfer encoding\n");
2517 break;
2518 }
2519 }
2520 else
2521 {
2522 totalbytes += numbytes;
2523 {
2524 int z;
2525 for(z = 0; z < numbytes && !stop; ++z)
2526 HandleByte(&Parser, (unsigned int) buf[z]);
2527 }
2528 }
2529 if(totalbytes < 0) /* overflow */
2530 {
2531 totalbytes = 0;
2532 starttime = time(0);
2533 lastout = starttime;
2534 }
2535 }
2536 }
2537 }
2538 else
2539 {
2540 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
2541 {
2542 alarm(ALARMTIME);
2543 fwrite(buf, (size_t)numbytes, 1, stdout);
2544 }
2545 }
2546 close(sockfd);
2547 }
2548 }
2549 return 0;
2550}
2551#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.