source: ntrip/trunk/rtcm3torinex/rtcm3torinex.c@ 2427

Last change on this file since 2427 was 2422, checked in by stoecker, 14 years ago

added cross-correlation patch by Edgar Johansen

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