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

Last change on this file since 689 was 689, checked in by weber, 16 years ago

* empty log message *

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