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

Last change on this file since 498 was 498, checked in by stoecker, 15 years ago

minor SBAS fix

File size: 39.0 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.21 2007/08/14 10:14:37 stoecker Exp $
4 Copyright (C) 2005-2006 by Dirk Stoecker <stoecker@euronik.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.21 $";
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 bits from data stream
142 b = variable to store result, a = number of bits */
143#define GETBITSSIGN(b, a) \
144{ \
145 LOADBITS(a) \
146 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
147 numbits -= (a); \
148}
149
150#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
151
152struct leapseconds { /* specify the day of leap second */
153 int day; /* this is the day, where 23:59:59 exists 2 times */
154 int month; /* not the next day! */
155 int year;
156 int taicount;
157};
158static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
159static const struct leapseconds leap[] = {
160/*{31, 12, 1971, 11},*/
161/*{31, 12, 1972, 12},*/
162/*{31, 12, 1973, 13},*/
163/*{31, 12, 1974, 14},*/
164/*{31, 12, 1975, 15},*/
165/*{31, 12, 1976, 16},*/
166/*{31, 12, 1977, 17},*/
167/*{31, 12, 1978, 18},*/
168/*{31, 12, 1979, 19},*/
169{30, 06, 1981,20},
170{30, 06, 1982,21},
171{30, 06, 1983,22},
172{30, 06, 1985,23},
173{31, 12, 1987,24},
174{31, 12, 1989,25},
175{31, 12, 1990,26},
176{30, 06, 1992,27},
177{30, 06, 1993,28},
178{30, 06, 1994,29},
179{31, 12, 1995,30},
180{30, 06, 1997,31},
181{31, 12, 1998,32},
182{31, 12, 2005,33},
183{0,0,0,0} /* end marker */
184};
185#define LEAPSECONDS 14 /* only needed for approx. time */
186#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
187
188static int longyear(int year, int month)
189{
190 if(!(year % 4) && (!(year % 400) || (year % 100)))
191 {
192 if(!month || month == 2)
193 return 1;
194 }
195 return 0;
196}
197
198static int gnumleap(int year, int month, int day)
199{
200 int ls = 0;
201 const struct leapseconds *l;
202
203 for(l = leap; l->taicount && year >= l->year; ++l)
204 {
205 if(year > l->year || month > l->month || day > l->day)
206 ls = l->taicount - GPSLEAPSTART;
207 }
208 return ls;
209}
210
211static void updatetime(int *week, int *tow, int tk)
212{
213 int y,m,d,k,l;
214 unsigned int j = *week*(7*24*60*60) + *tow + 5*24*60*60+3*60*60;
215 int glo_daynumber = 0, glo_timeofday;
216 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
217 + gnumleap(y+1,1,1); ++y)
218 {
219 j -= k; glo_daynumber += l;
220 }
221 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
222 + gnumleap(y, m+1, 1); ++m)
223 {
224 j -= k; glo_daynumber += l;
225 }
226 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
227 j -= 24*60*60;
228 glo_daynumber -= 16*365+4-d;
229 glo_timeofday = j-gnumleap(y, m, d);
230
231 if(tk < 5*60*1000 && glo_timeofday > 23*60*60)
232 *tow += 24*60*60;
233 else if(glo_timeofday < 5*60 && tk > 23*60*60*1000)
234 *tow -= 24*60*60;
235 *tow += tk/1000-glo_timeofday;
236 if(*tow < 0) {*tow += 24*60*60*7; --*week; }
237 if(*tow >= 24*60*60*7) {*tow -= 24*60*60*7; ++*week; }
238}
239
240int RTCM3Parser(struct RTCM3ParserData *handle)
241{
242 int ret=0;
243
244 while(!ret && GetMessage(handle))
245 {
246 /* using 64 bit integer types, as it is much easier than handling
247 the long datatypes in 32 bit */
248 uint64_t numbits = 0, bitfield = 0;
249 int size = handle->size, type;
250 int syncf, old = 0;
251 unsigned char *data = handle->Message+3;
252
253 GETBITS(type,12)
254 switch(type)
255 {
256 case 1001: case 1002: case 1003: case 1004:
257 if(handle->GPSWeek)
258 {
259 int lastlockl1[64];
260 int lastlockl2[64];
261 struct gnssdata *gnss;
262 int i, num, wasamb=0;
263
264 for(i = 0; i < 64; ++i)
265 lastlockl1[i] = lastlockl2[i] = 0;
266
267 gnss = &handle->DataNew;
268
269 SKIPBITS(12) /* id */
270 GETBITS(i,30)
271 if(i/1000 < (int)handle->GPSTOW - 86400)
272 ++handle->GPSWeek;
273 handle->GPSTOW = i/1000;
274 if(gnss->week && (gnss->timeofweek != i || gnss->week
275 != handle->GPSWeek))
276 {
277 handle->Data = *gnss;
278 memset(gnss, 0, sizeof(*gnss));
279 old = 1;
280 }
281 gnss->timeofweek = i;
282 gnss->week = handle->GPSWeek;
283
284 GETBITS(syncf,1) /* sync */
285 GETBITS(i,5)
286 gnss->numsats = i;
287 SKIPBITS(4) /* smind, smint */
288
289 for(num = 0; num < gnss->numsats; ++num)
290 {
291 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
292
293 GETBITS(sv, 6);
294 gnss->satellites[num] = (sv < 40 ? sv : sv+80);
295 /* L1 */
296 GETBITS(code, 1);
297 if(code)
298 {
299 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
300 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
301 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
302 }
303 else
304 {
305 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
306 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
307 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
308 }
309 GETBITS(l1range, 24);
310 if((l1range&((1<<24)-1)) != 0x80000)
311 {
312 gnss->dataflags[num] |= c;
313 gnss->measdata[num][ce] = l1range*0.02;
314 }
315 GETBITSSIGN(i, 20);
316 if((i&((1<<20)-1)) != 0x80000)
317 {
318 gnss->dataflags[num] |= l;
319 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
320 }
321 GETBITS(i, 7);
322 lastlockl1[sv] = i;
323 if(handle->lastlockl1[sv] > i)
324 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
325 if(type == 1002 || type == 1004)
326 {
327 GETBITS(amb,8);
328 if(amb && (gnss->dataflags[num] & c))
329 {
330 gnss->measdata[num][ce] += amb*299792.458;
331 gnss->measdata[num][le] += amb*299792.458;
332 ++wasamb;
333 }
334 GETBITS(i, 8);
335 if(i)
336 {
337 gnss->dataflags[num] |= s;
338 gnss->measdata[num][se] = i*0.25;
339 i /= 4*4;
340 if(i > 9) i = 9;
341 else if(i < 1) i = 1;
342 gnss->snrL1[num] = i;
343 }
344 }
345 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
346 if(type == 1003 || type == 1004)
347 {
348 /* L2 */
349 GETBITS(code,2);
350 if(code)
351 {
352 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
353 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
354 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
355 }
356 else
357 {
358 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
359 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
360 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
361 }
362 GETBITSSIGN(i,14);
363 if((i&((1<<14)-1)) != 0x2000)
364 {
365 gnss->dataflags[num] |= c;
366 gnss->measdata[num][ce] = l1range*0.02+i*0.02
367 +amb*299792.458;
368 }
369 GETBITSSIGN(i,20);
370 if((i&((1<<20)-1)) != 0x80000)
371 {
372 gnss->dataflags[num] |= l;
373 gnss->measdata[num][le] = l1range*0.02+i*0.0005
374 +amb*299792.458;
375 }
376 GETBITS(i,7);
377 lastlockl2[sv] = i;
378 if(handle->lastlockl2[sv] > i)
379 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
380 if(type == 1004)
381 {
382 GETBITS(i, 8);
383 if(i)
384 {
385 gnss->dataflags[num] |= s;
386 gnss->measdata[num][se] = i*0.25;
387 i /= 4*4;
388 if(i > 9) i = 9;
389 else if(i < 1) i = 1;
390 gnss->snrL2[num] = i;
391 }
392 }
393 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
394 }
395 }
396 for(i = 0; i < 64; ++i)
397 {
398 handle->lastlockl1[i] = lastlockl1[i];
399 handle->lastlockl2[i] = lastlockl2[i];
400 }
401 if(!syncf && !old)
402 {
403 handle->Data = *gnss;
404 memset(gnss, 0, sizeof(*gnss));
405 }
406 if(!syncf || old)
407 {
408 if(wasamb) /* not RINEX compatible without */
409 ret = 1;
410 else
411 ret = 2;
412 }
413 }
414 break;
415 case 1009: case 1010: case 1011: case 1012:
416 {
417 int lastlockl1[64];
418 int lastlockl2[64];
419 struct gnssdata *gnss;
420 int i, num;
421 int wasamb=0;
422
423 for(i = 0; i < 64; ++i)
424 lastlockl1[i] = lastlockl2[i] = 0;
425
426 gnss = &handle->DataNew;
427
428 SKIPBITS(12) /* id */;
429 GETBITS(i,27) /* tk */
430
431 updatetime(&handle->GPSWeek, &handle->GPSTOW, i);
432 i = handle->GPSTOW*1000;
433 if(gnss->week && (gnss->timeofweek != i || gnss->week
434 != handle->GPSWeek))
435 {
436 handle->Data = *gnss;
437 memset(gnss, 0, sizeof(*gnss));
438 old = 1;
439 }
440
441 gnss->timeofweek = i;
442 gnss->week = handle->GPSWeek;
443
444 GETBITS(syncf,1) /* sync */
445 GETBITS(i,5)
446 gnss->numsats += i;
447
448 SKIPBITS(4) /* smind, smint */
449
450 for(num = gnss->numsats-i; num < gnss->numsats; ++num)
451 {
452 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
453 int freq;
454
455 GETBITS(sv, 6)
456 gnss->satellites[num] = sv-1 + PRN_GLONASS_START;
457 /* L1 */
458 GETBITS(code, 1)
459 GETBITS(freq, 5)
460 if(code)
461 {
462 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
463 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
464 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
465 }
466 else
467 {
468 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
469 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
470 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
471 }
472 GETBITS(l1range, 25)
473 if((l1range&((1<<25)-1)) != 0x80000)
474 {
475 gnss->dataflags[num] |= c;
476 gnss->measdata[num][ce] = l1range*0.02;
477 }
478 GETBITSSIGN(i, 20)
479 if((i&((1<<20)-1)) != 0x80000)
480 {
481 gnss->dataflags[num] |= l;
482 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
483 }
484 GETBITS(i, 7)
485 lastlockl1[sv] = i;
486 if(handle->lastlockl1[sv] > i)
487 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
488 if(type == 1010 || type == 1012)
489 {
490 GETBITS(amb,7)
491 if(amb && (gnss->dataflags[num] & c))
492 {
493 gnss->measdata[num][ce] += amb*599584.916;
494 gnss->measdata[num][le] += amb*599584.916;
495 ++wasamb;
496 }
497 GETBITS(i, 8)
498 if(i)
499 {
500 gnss->dataflags[num] |= s;
501 gnss->measdata[num][se] = i*0.25;
502 i /= 4*4;
503 if(i > 9) i = 9;
504 else if(i < 1) i = 1;
505 gnss->snrL1[num] = i;
506 }
507 }
508 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
509 if(type == 1011 || type == 1012)
510 {
511 /* L2 */
512 GETBITS(code,2)
513 if(code)
514 {
515 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
516 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
517 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
518 }
519 else
520 {
521 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
522 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
523 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
524 }
525 GETBITSSIGN(i,14)
526 if((i&((1<<14)-1)) != 0x2000)
527 {
528 gnss->dataflags[num] |= c;
529 gnss->measdata[num][ce] = l1range*0.02+i*0.02
530 +amb*599584.916;
531 }
532 GETBITSSIGN(i,20)
533 if((i&((1<<20)-1)) != 0x80000)
534 {
535 gnss->dataflags[num] |= l;
536 gnss->measdata[num][le] = l1range*0.02+i*0.0005
537 +amb*599584.915;
538 }
539 GETBITS(i,7)
540 lastlockl2[sv] = i;
541 if(handle->lastlockl2[sv] > i)
542 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
543 if(type == 1012)
544 {
545 GETBITS(i, 8)
546 if(i)
547 {
548 gnss->dataflags[num] |= s;
549 gnss->measdata[num][se] = i*0.25;
550 i /= 4*4;
551 if(i > 9) i = 9;
552 else if(i < 1) i = 1;
553 gnss->snrL2[num] = i;
554 }
555 }
556 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
557 }
558 if(!sv || sv > 24)
559 {
560 --num; --gnss->numsats;
561 }
562 }
563 for(i = 0; i < 64; ++i)
564 {
565 handle->lastlockl1[i] = lastlockl1[i];
566 handle->lastlockl2[i] = lastlockl2[i];
567 }
568 if(!syncf && !old)
569 {
570 handle->Data = *gnss;
571 memset(gnss, 0, sizeof(*gnss));
572 }
573 if(!syncf || old)
574 {
575 if(wasamb) /* not RINEX compatible without */
576 ret = 1;
577 else
578 ret = 2;
579 }
580 }
581 break;
582 }
583 }
584 return ret;
585}
586
587struct Header
588{
589 const char *version;
590 const char *pgm;
591 const char *marker;
592 const char *observer;
593 const char *receiver;
594 const char *antenna;
595 const char *position;
596 const char *antennaposition;
597 const char *wavelength;
598 const char *typesofobs; /* should not be modified outside */
599 const char *timeoffirstobs; /* should not be modified outside */
600};
601
602#define MAXHEADERLINES 50
603#define MAXHEADERBUFFERSIZE 4096
604struct HeaderData
605{
606 union
607 {
608 struct Header named;
609 const char *unnamed[MAXHEADERLINES];
610 } data;
611 int numheaders;
612};
613
614struct converttimeinfo {
615 int second; /* seconds of GPS time [0..59] */
616 int minute; /* minutes of GPS time [0..59] */
617 int hour; /* hour of GPS time [0..24] */
618 int day; /* day of GPS time [1..28..30(31)*/
619 int month; /* month of GPS time [1..12]*/
620 int year; /* year of GPS time [1980..] */
621};
622
623static void converttime(struct converttimeinfo *c, int week, int tow)
624{
625 int i, k, doy, j; /* temporary variables */
626 j = week*(7*24*60*60) + tow + 5*24*60*60;
627 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
628 j -= k;
629 c->year = i;
630 doy = 1+ (j / (24*60*60));
631 j %= (24*60*60);
632 c->hour = j / (60*60);
633 j %= (60*60);
634 c->minute = j / 60;
635 c->second = j % 60;
636 j = 0;
637 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
638 j += k;
639 c->month = i;
640 c->day = doy - j;
641}
642
643#ifndef NO_RTCM3_MAIN
644void RTCM3Error(const char *fmt, ...)
645{
646 va_list v;
647 va_start(v, fmt);
648 vfprintf(stderr, fmt, v);
649 va_end(v);
650}
651#endif
652
653void RTCM3Text(const char *fmt, ...)
654{
655 va_list v;
656 va_start(v, fmt);
657 vprintf(fmt, v);
658 va_end(v);
659}
660
661#define NUMSTARTSKIP 3
662void HandleHeader(struct RTCM3ParserData *Parser)
663{
664 struct HeaderData hdata;
665 char thebuffer[MAXHEADERBUFFERSIZE];
666 char *buffer = thebuffer;
667 size_t buffersize = sizeof(thebuffer);
668 int i;
669
670 hdata.data.named.version =
671 " 2.11 OBSERVATION DATA M (Mixed)"
672 " RINEX VERSION / TYPE";
673
674 {
675 const char *str;
676 time_t t;
677 struct tm * t2;
678
679#ifdef NO_RTCM3_MAIN
680 if(revisionstr[0] == '$')
681 {
682 char *a;
683 int i=0;
684 for(a = revisionstr+11; *a && *a != ' '; ++a)
685 revisionstr[i++] = *a;
686 revisionstr[i] = 0;
687 }
688#endif
689
690 str = getenv("USER");
691 if(!str) str = "";
692 t = time(&t);
693 t2 = gmtime(&t);
694 hdata.data.named.pgm = buffer;
695 i = 1+snprintf(buffer, buffersize,
696 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
697 "PGM / RUN BY / DATE",
698 revisionstr, str, 1900+t2->tm_year, t2->tm_mon+1, t2->tm_mday, t2->tm_hour,
699 t2->tm_min);
700 buffer += i; buffersize -= i;
701
702 hdata.data.named.observer = buffer;
703 i = 1+snprintf(buffer, buffersize,
704 "%-20.20s "
705 "OBSERVER / AGENCY", str);
706 buffer += i; buffersize -= i;
707 }
708
709 hdata.data.named.marker =
710 "RTCM3TORINEX "
711 "MARKER NAME";
712
713 hdata.data.named.receiver =
714 " "
715 "REC # / TYPE / VERS";
716
717 hdata.data.named.antenna =
718 " "
719 "ANT # / TYPE";
720
721 hdata.data.named.position =
722 " .0000 .0000 .0000 "
723 "APPROX POSITION XYZ";
724
725 hdata.data.named.antennaposition =
726 " .0000 .0000 .0000 "
727 "ANTENNA: DELTA H/E/N";
728
729 hdata.data.named.wavelength =
730 " 1 1 "
731 "WAVELENGTH FACT L1/2";
732
733 {
734#define CHECKFLAGS(a, b) \
735 if(flags & GNSSDF_##a##DATA) \
736 { \
737 if(data[RINEXENTRY_##b##DATA]) \
738 { \
739 Parser->dataflag2[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
740 Parser->datapos2[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
741 } \
742 else \
743 { \
744 Parser->dataflag[Parser->numdatatypes] = GNSSDF_##a##DATA; \
745 Parser->datapos[Parser->numdatatypes] = GNSSENTRY_##a##DATA; \
746 data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypes; \
747 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
748 tbufferpos += 6; \
749 } \
750 }
751
752 int flags = Parser->startflags;
753 int data[RINEXENTRY_NUMBER];
754 char tbuffer[6*RINEXENTRY_NUMBER+1];
755 int tbufferpos = 0;
756 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
757 data[i] = 0;
758 for(i = 0; i < Parser->Data.numsats; ++i)
759 flags |= Parser->Data.dataflags[i];
760
761 CHECKFLAGS(C1,C1)
762 CHECKFLAGS(C2,C2)
763 CHECKFLAGS(P1,P1)
764 CHECKFLAGS(P2,P2)
765 CHECKFLAGS(L1C,L1)
766 CHECKFLAGS(L1P,L1)
767 CHECKFLAGS(L2C,L2)
768 CHECKFLAGS(L2P,L2)
769 CHECKFLAGS(D1C,D1)
770 CHECKFLAGS(D1P,D1)
771 CHECKFLAGS(D2C,D2)
772 CHECKFLAGS(D2P,D2)
773 CHECKFLAGS(S1C,S1)
774 CHECKFLAGS(S1P,S1)
775 CHECKFLAGS(S2C,S2)
776 CHECKFLAGS(S2P,S2)
777
778 hdata.data.named.typesofobs = buffer;
779 i = 1+snprintf(buffer, buffersize,
780 "%6i%-54.54s# / TYPES OF OBSERV", Parser->numdatatypes, tbuffer);
781 if(Parser->numdatatypes>9)
782 {
783 i += snprintf(buffer+i-1, buffersize,
784 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
785 }
786 buffer += i; buffersize -= i;
787 }
788
789 {
790 struct converttimeinfo cti;
791 converttime(&cti, Parser->Data.week,
792 (int)floor(Parser->Data.timeofweek/1000.0));
793 hdata.data.named.timeoffirstobs = buffer;
794 i = 1+snprintf(buffer, buffersize,
795 " %4d %2d %2d %2d %2d %10.7f GPS "
796 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
797 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
798
799 buffer += i; buffersize -= i;
800 }
801
802 hdata.numheaders = 11;
803
804 if(Parser->headerfile)
805 {
806 FILE *fh;
807 if((fh = fopen(Parser->headerfile, "r")))
808 {
809 size_t siz;
810 char *lastblockstart;
811 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
812 {
813 buffer[siz] = '\n';
814 if(siz == buffersize)
815 {
816 RTCM3Error("Header file is too large. Only %d bytes read.",
817 (int)siz);
818 }
819 /* scan the file line by line and enter the entries in the list */
820 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
821 /* overwrites entries, except for comments */
822 lastblockstart = buffer;
823 for(i = 0; i < (int)siz; ++i)
824 {
825 if(buffer[i] == '\n')
826 { /* we found a line */
827 char *end;
828 while(buffer[i+1] == '\r')
829 ++i; /* skip \r in case there are any */
830 end = buffer+i;
831 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
832 *(end--) = 0;
833 if(end-lastblockstart < 60+5) /* short line */
834 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
835 else
836 {
837 int pos;
838 if(!strcmp("COMMENT", lastblockstart+60))
839 pos = hdata.numheaders;
840 else
841 {
842 for(pos = 0; pos < hdata.numheaders; ++pos)
843 {
844 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
845 break;
846 }
847 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
848 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
849 {
850 RTCM3Error("Overwriting header '%s' is dangerous.\n",
851 lastblockstart+60);
852 }
853 }
854 if(pos >= MAXHEADERLINES)
855 {
856 RTCM3Error("Maximum number of header lines of %d reached.\n",
857 MAXHEADERLINES);
858 }
859 else if(!strcmp("END OF HEADER", lastblockstart+60))
860 {
861 RTCM3Error("End of header ignored.\n");
862 }
863 else
864 {
865 hdata.data.unnamed[pos] = lastblockstart;
866 if(pos == hdata.numheaders)
867 ++hdata.numheaders;
868 }
869 }
870 lastblockstart = buffer+i+1;
871 }
872 }
873 }
874 else
875 {
876 RTCM3Error("Could not read data from headerfile '%s'.\n",
877 Parser->headerfile);
878 }
879 fclose(fh);
880 }
881 else
882 {
883 RTCM3Error("Could not open header datafile '%s'.\n",
884 Parser->headerfile);
885 }
886 }
887
888#ifndef NO_RTCM3_MAIN
889 for(i = 0; i < hdata.numheaders; ++i)
890 RTCM3Text("%s\n", hdata.data.unnamed[i]);
891 RTCM3Text(" "
892 "END OF HEADER\n");
893#endif
894}
895
896void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
897{
898 Parser->Message[Parser->MessageSize++] = byte;
899 if(Parser->MessageSize >= Parser->NeedBytes)
900 {
901 int r;
902 while((r = RTCM3Parser(Parser)))
903 {
904 int i, j, o;
905 struct converttimeinfo cti;
906
907 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
908 {
909 ++Parser->init;
910
911 if(Parser->init == NUMSTARTSKIP)
912 HandleHeader(Parser);
913 else
914 {
915 for(i = 0; i < Parser->Data.numsats; ++i)
916 Parser->startflags |= Parser->Data.dataflags[i];
917 continue;
918 }
919 }
920 if(r == 2 && !Parser->validwarning)
921 {
922 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
923 " COMMENT\n");
924 Parser->validwarning = 1;
925 }
926
927 converttime(&cti, Parser->Data.week,
928 (int)floor(Parser->Data.timeofweek/1000.0));
929 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
930 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
931 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
932 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
933 {
934 if(Parser->Data.satellites[i] <= PRN_GPS_END)
935 RTCM3Text("G%02d", Parser->Data.satellites[i]);
936 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
937 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
938 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
939 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
940 && Parser->Data.satellites[i] <= PRN_WAAS_END)
941 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
942 else
943 RTCM3Text("%3d", Parser->Data.satellites[i]);
944 }
945 RTCM3Text("\n");
946 o = 12;
947 j = Parser->Data.numsats - 12;
948 while(j > 0)
949 {
950 RTCM3Text(" ");
951 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
952 {
953 if(Parser->Data.satellites[i] <= PRN_GPS_END)
954 RTCM3Text("G%02d", Parser->Data.satellites[i]);
955 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
956 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
957 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
958 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
959 && Parser->Data.satellites[i] <= PRN_WAAS_END)
960 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
961 else
962 RTCM3Text("%3d", Parser->Data.satellites[i]);
963 }
964 RTCM3Text("\n");
965 j -= 12;
966 o += 12;
967 }
968 for(i = 0; i < Parser->Data.numsats; ++i)
969 {
970 for(j = 0; j < Parser->numdatatypes; ++j)
971 {
972 int v = 0;
973 int df = Parser->dataflag[j];
974 int pos = Parser->datapos[j];
975 if((Parser->Data.dataflags[i] & df)
976 && !isnan(Parser->Data.measdata[i][pos])
977 && !isinf(Parser->Data.measdata[i][pos]))
978 {
979 v = 1;
980 }
981 else
982 {
983 df = Parser->dataflag2[j];
984 pos = Parser->datapos2[j];
985
986 if((Parser->Data.dataflags[i] & df)
987 && !isnan(Parser->Data.measdata[i][pos])
988 && !isinf(Parser->Data.measdata[i][pos]))
989 {
990 v = 1;
991 }
992 }
993
994 if(!v)
995 { /* no or illegal data */
996 RTCM3Text(" ");
997 }
998 else
999 {
1000 char lli = ' ';
1001 char snr = ' ';
1002 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1003 {
1004 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1005 lli = '1';
1006 snr = '0'+Parser->Data.snrL1[i];
1007 }
1008 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1009 {
1010 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1011 lli = '1';
1012 snr = '0'+Parser->Data.snrL2[i];
1013 }
1014 RTCM3Text("%14.3f%c%c",
1015 Parser->Data.measdata[i][pos],lli,snr);
1016 }
1017 if(j%5 == 4 || j == Parser->numdatatypes-1)
1018 RTCM3Text("\n");
1019 }
1020 }
1021 }
1022 }
1023}
1024
1025#ifndef NO_RTCM3_MAIN
1026static char datestr[] = "$Date: 2007/08/14 10:14:37 $";
1027
1028/* The string, which is send as agent in HTTP request */
1029#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
1030
1031#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
1032
1033static const char encodingTable [64] = {
1034 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1035 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1036 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1037 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1038};
1039
1040/* does not buffer overrun, but breaks directly after an error */
1041/* returns the number of required bytes */
1042static int encode(char *buf, int size, const char *user, const char *pwd)
1043{
1044 unsigned char inbuf[3];
1045 char *out = buf;
1046 int i, sep = 0, fill = 0, bytes = 0;
1047
1048 while(*user || *pwd)
1049 {
1050 i = 0;
1051 while(i < 3 && *user) inbuf[i++] = *(user++);
1052 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
1053 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
1054 while(i < 3) {inbuf[i++] = 0; ++fill; }
1055 if(out-buf < size-1)
1056 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
1057 if(out-buf < size-1)
1058 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
1059 | ((inbuf [1] & 0xF0) >> 4)];
1060 if(out-buf < size-1)
1061 {
1062 if(fill == 2)
1063 *(out++) = '=';
1064 else
1065 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
1066 | ((inbuf [2] & 0xC0) >> 6)];
1067 }
1068 if(out-buf < size-1)
1069 {
1070 if(fill >= 1)
1071 *(out++) = '=';
1072 else
1073 *(out++) = encodingTable[inbuf [2] & 0x3F];
1074 }
1075 bytes += 4;
1076 }
1077 if(out-buf < size)
1078 *out = 0;
1079 return bytes;
1080}
1081
1082static int stop = 0;
1083
1084struct Args
1085{
1086 const char *server;
1087 int port;
1088 int timeout;
1089 const char *user;
1090 const char *password;
1091 const char *data;
1092 const char *headerfile;
1093};
1094
1095/* option parsing */
1096#ifdef NO_LONG_OPTS
1097#define LONG_OPT(a)
1098#else
1099#define LONG_OPT(a) a
1100static struct option opts[] = {
1101{ "data", required_argument, 0, 'd'},
1102{ "server", required_argument, 0, 's'},
1103{ "password", required_argument, 0, 'p'},
1104{ "port", required_argument, 0, 'r'},
1105{ "timeout", required_argument, 0, 't'},
1106{ "header", required_argument, 0, 'f'},
1107{ "user", required_argument, 0, 'u'},
1108{ "help", no_argument, 0, 'h'},
1109{0,0,0,0}};
1110#endif
1111#define ARGOPT "-d:s:p:r:t:f:u:h"
1112
1113static const char *geturl(const char *url, struct Args *args)
1114{
1115 static char buf[1000];
1116 static char *Buffer = buf;
1117 static char *Bufend = buf+sizeof(buf);
1118
1119 if(strncmp("ntrip:", url, 6))
1120 return "URL must start with 'ntrip:'.";
1121 url += 6; /* skip ntrip: */
1122
1123 if(*url != '@' && *url != '/')
1124 {
1125 /* scan for mountpoint */
1126 args->data = Buffer;
1127 while(*url && *url != '@' && *url != '/' && Buffer != Bufend)
1128 *(Buffer++) = *(url++);
1129 if(Buffer == args->data)
1130 return "Mountpoint required.";
1131 else if(Buffer >= Bufend-1)
1132 return "Parsing buffer too short.";
1133 *(Buffer++) = 0;
1134 }
1135
1136 if(*url == '/') /* username and password */
1137 {
1138 ++url;
1139 args->user = Buffer;
1140 while(*url && *url != '@' && *url != ':' && Buffer != Bufend)
1141 *(Buffer++) = *(url++);
1142 if(Buffer == args->user)
1143 return "Username cannot be empty.";
1144 else if(Buffer >= Bufend-1)
1145 return "Parsing buffer too short.";
1146 *(Buffer++) = 0;
1147
1148 if(*url == ':') ++url;
1149
1150 args->password = Buffer;
1151 while(*url && *url != '@' && Buffer != Bufend)
1152 *(Buffer++) = *(url++);
1153 if(Buffer == args->password)
1154 return "Password cannot be empty.";
1155 else if(Buffer >= Bufend-1)
1156 return "Parsing buffer too short.";
1157 *(Buffer++) = 0;
1158 }
1159
1160 if(*url == '@') /* server */
1161 {
1162 ++url;
1163 args->server = Buffer;
1164 while(*url && *url != ':' && Buffer != Bufend)
1165 *(Buffer++) = *(url++);
1166 if(Buffer == args->server)
1167 return "Servername cannot be empty.";
1168 else if(Buffer >= Bufend-1)
1169 return "Parsing buffer too short.";
1170 *(Buffer++) = 0;
1171
1172 if(*url == ':')
1173 {
1174 char *s2 = 0;
1175 args->port = strtol(++url, &s2, 10);
1176 if(*s2 || args->port <= 0 || args->port > 0xFFFF)
1177 return "Illegal port number.";
1178 url = s2;
1179 }
1180 }
1181
1182 return *url ? "Garbage at end of server string." : 0;
1183}
1184
1185static int getargs(int argc, char **argv, struct Args *args)
1186{
1187 int res = 1;
1188 int getoptr;
1189 int help = 0;
1190 char *t;
1191
1192 args->server = "www.euref-ip.net";
1193 args->port = 2101;
1194 args->timeout = 60;
1195 args->user = "";
1196 args->password = "";
1197 args->data = 0;
1198 args->headerfile = 0;
1199 help = 0;
1200
1201 do
1202 {
1203
1204#ifdef NO_LONG_OPTS
1205 switch((getoptr = getopt(argc, argv, ARGOPT)))
1206#else
1207 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
1208#endif
1209 {
1210 case 's': args->server = optarg; break;
1211 case 'u': args->user = optarg; break;
1212 case 'p': args->password = optarg; break;
1213 case 'd': args->data = optarg; break;
1214 case 'f': args->headerfile = optarg; break;
1215 case 'h': help=1; break;
1216 case 'r':
1217 args->port = strtoul(optarg, &t, 10);
1218 if((t && *t) || args->port < 1 || args->port > 65535)
1219 res = 0;
1220 break;
1221 case 't':
1222 args->timeout = strtoul(optarg, &t, 10);
1223 if((t && *t) || args->timeout < 0)
1224 res = 0;
1225 break;
1226
1227 case 1:
1228 {
1229 const char *err;
1230 if((err = geturl(optarg, args)))
1231 {
1232 RTCM3Error("%s\n\n", err);
1233 res = 0;
1234 }
1235 }
1236 break;
1237 case -1: break;
1238 }
1239 } while(getoptr != -1 || !res);
1240
1241 datestr[0] = datestr[7];
1242 datestr[1] = datestr[8];
1243 datestr[2] = datestr[9];
1244 datestr[3] = datestr[10];
1245 datestr[5] = datestr[12];
1246 datestr[6] = datestr[13];
1247 datestr[8] = datestr[15];
1248 datestr[9] = datestr[16];
1249 datestr[4] = datestr[7] = '-';
1250 datestr[10] = 0;
1251
1252 if(!res || help)
1253 {
1254 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
1255 "\nUsage: %s -s server -u user ...\n"
1256 " -d " LONG_OPT("--data ") "the requested data set\n"
1257 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
1258 " -s " LONG_OPT("--server ") "the server name or address\n"
1259 " -p " LONG_OPT("--password ") "the login password\n"
1260 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
1261 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
1262 " -u " LONG_OPT("--user ") "the user name\n"
1263 "or using an URL:\n%s ntrip:mountpoint[/username[:password]][@server[:port]]\n"
1264 , revisionstr, datestr, argv[0], argv[0]);
1265 exit(1);
1266 }
1267 return res;
1268}
1269
1270/* let the output complete a block if necessary */
1271static void signalhandler(int sig)
1272{
1273 if(!stop)
1274 {
1275 RTCM3Error("Stop signal number %d received. "
1276 "Trying to terminate gentle.\n", sig);
1277 stop = 1;
1278 alarm(1);
1279 }
1280}
1281
1282/* for some reason we had to abort hard (maybe waiting for data */
1283#ifdef __GNUC__
1284static __attribute__ ((noreturn)) void signalhandler_alarm(
1285int sig __attribute__((__unused__)))
1286#else /* __GNUC__ */
1287static void signalhandler_alarm(int sig)
1288#endif /* __GNUC__ */
1289{
1290 RTCM3Error("Programm forcefully terminated.\n");
1291 exit(1);
1292}
1293
1294int main(int argc, char **argv)
1295{
1296 struct Args args;
1297 struct RTCM3ParserData Parser;
1298
1299 struct timeval tv;
1300
1301 setbuf(stdout, 0);
1302 setbuf(stdin, 0);
1303 setbuf(stderr, 0);
1304
1305 {
1306 char *a;
1307 int i=0;
1308 for(a = revisionstr+11; *a && *a != ' '; ++a)
1309 revisionstr[i++] = *a;
1310 revisionstr[i] = 0;
1311 }
1312
1313 signal(SIGINT, signalhandler);
1314 signal(SIGALRM,signalhandler_alarm);
1315 signal(SIGQUIT,signalhandler);
1316 signal(SIGTERM,signalhandler);
1317 signal(SIGPIPE,signalhandler);
1318 memset(&Parser, 0, sizeof(Parser));
1319 {
1320 time_t tim;
1321 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
1322 Parser.GPSWeek = tim/(7*24*60*60);
1323 Parser.GPSTOW = tim%(7*24*60*60);
1324 }
1325
1326 if(getargs(argc, argv, &args))
1327 {
1328 int i, sockfd, numbytes;
1329 char buf[MAXDATASIZE];
1330 struct hostent *he;
1331 struct sockaddr_in their_addr; /* connector's address information */
1332
1333 Parser.headerfile = args.headerfile;
1334
1335 if(!(he=gethostbyname(args.server)))
1336 {
1337 RTCM3Error("Function gethostbyname: %s\n", strerror(errno));
1338 exit(1);
1339 }
1340 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1341 {
1342 RTCM3Error("Function socket: %s\n", strerror(errno));
1343 exit(1);
1344 }
1345
1346 tv.tv_sec = args.timeout;
1347 tv.tv_usec = 0;
1348 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
1349 {
1350 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
1351 exit(1);
1352 }
1353
1354 their_addr.sin_family = AF_INET; /* host byte order */
1355 their_addr.sin_port = htons(args.port); /* short, network byte order */
1356 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
1357 memset(&(their_addr.sin_zero), '\0', 8);
1358 if(connect(sockfd, (struct sockaddr *)&their_addr,
1359 sizeof(struct sockaddr)) == -1)
1360 {
1361 RTCM3Error("Function connect: %s\n", strerror(errno));
1362 exit(1);
1363 }
1364
1365 if(!args.data)
1366 {
1367 i = snprintf(buf, MAXDATASIZE,
1368 "GET / HTTP/1.0\r\n"
1369 "User-Agent: %s/%s\r\n"
1370#ifdef UNUSED
1371 "Accept: */*\r\n"
1372 "Connection: close\r\n"
1373#endif
1374 "\r\n"
1375 , AGENTSTRING, revisionstr);
1376 }
1377 else
1378 {
1379 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
1380 "GET /%s HTTP/1.0\r\n"
1381 "User-Agent: %s/%s\r\n"
1382#ifdef UNUSED
1383 "Accept: */*\r\n"
1384 "Connection: close\r\n"
1385#endif
1386 "Authorization: Basic "
1387 , args.data, AGENTSTRING, revisionstr);
1388 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
1389 {
1390 RTCM3Error("Requested data too long\n");
1391 exit(1);
1392 }
1393 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
1394 if(i > MAXDATASIZE-4)
1395 {
1396 RTCM3Error("Username and/or password too long\n");
1397 exit(1);
1398 }
1399 buf[i++] = '\r';
1400 buf[i++] = '\n';
1401 buf[i++] = '\r';
1402 buf[i++] = '\n';
1403 }
1404 if(send(sockfd, buf, (size_t)i, 0) != i)
1405 {
1406 RTCM3Error("Function send: %s\n", strerror(errno));
1407 exit(1);
1408 }
1409 if(args.data)
1410 {
1411 int k = 0;
1412 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
1413 {
1414 if(!k)
1415 {
1416 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
1417 {
1418 RTCM3Error("Could not get the requested data: ");
1419 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
1420 {
1421 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
1422 }
1423 RTCM3Error("\n");
1424 exit(1);
1425 }
1426 ++k;
1427 }
1428 else
1429 {
1430 int z;
1431 for(z = 0; z < numbytes && !stop; ++z)
1432 HandleByte(&Parser, (unsigned int) buf[z]);
1433 }
1434 }
1435 }
1436 else
1437 {
1438 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
1439 {
1440 fwrite(buf, (size_t)numbytes, 1, stdout);
1441 }
1442 }
1443
1444 close(sockfd);
1445 }
1446 return 0;
1447}
1448#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.