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

Last change on this file since 477 was 477, checked in by stoecker, 17 years ago

added timeout patch supplied by Kirill Palamartchouk

File size: 38.8 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.18 2007/04/11 09:08:39 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.18 $";
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
940 RTCM3Text("%3d", Parser->Data.satellites[i]);
941 }
942 RTCM3Text("\n");
943 o = 12;
944 j = Parser->Data.numsats - 12;
945 while(j > 0)
946 {
947 RTCM3Text(" ");
948 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
949 {
950 if(Parser->Data.satellites[i] <= PRN_GPS_END)
951 RTCM3Text("G%02d", Parser->Data.satellites[i]);
952 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
953 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
954 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
955 else if(Parser->Data.satellites[i] >= PRN_WAAS_START
956 && Parser->Data.satellites[i] <= PRN_WAAS_END)
957 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START);
958 else
959 RTCM3Text("%3d", Parser->Data.satellites[i]);
960 }
961 RTCM3Text("\n");
962 j -= 12;
963 o += 12;
964 }
965 for(i = 0; i < Parser->Data.numsats; ++i)
966 {
967 for(j = 0; j < Parser->numdatatypes; ++j)
968 {
969 int v = 0;
970 int df = Parser->dataflag[j];
971 int pos = Parser->datapos[j];
972 if((Parser->Data.dataflags[i] & df)
973 && !isnan(Parser->Data.measdata[i][pos])
974 && !isinf(Parser->Data.measdata[i][pos]))
975 {
976 v = 1;
977 }
978 else
979 {
980 df = Parser->dataflag2[j];
981 pos = Parser->datapos2[j];
982
983 if((Parser->Data.dataflags[i] & df)
984 && !isnan(Parser->Data.measdata[i][pos])
985 && !isinf(Parser->Data.measdata[i][pos]))
986 {
987 v = 1;
988 }
989 }
990
991 if(!v)
992 { /* no or illegal data */
993 RTCM3Text(" ");
994 }
995 else
996 {
997 char lli = ' ';
998 char snr = ' ';
999 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
1000 {
1001 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
1002 lli = '1';
1003 snr = '0'+Parser->Data.snrL1[i];
1004 }
1005 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
1006 {
1007 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
1008 lli = '1';
1009 snr = '0'+Parser->Data.snrL2[i];
1010 }
1011 RTCM3Text("%14.3f%c%c",
1012 Parser->Data.measdata[i][pos],lli,snr);
1013 }
1014 if(j%5 == 4 || j == Parser->numdatatypes-1)
1015 RTCM3Text("\n");
1016 }
1017 }
1018 }
1019 }
1020}
1021
1022#ifndef NO_RTCM3_MAIN
1023static char datestr[] = "$Date: 2007/04/11 09:08:39 $";
1024
1025/* The string, which is send as agent in HTTP request */
1026#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
1027
1028#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
1029
1030static const char encodingTable [64] = {
1031 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1032 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1033 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1034 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1035};
1036
1037/* does not buffer overrun, but breaks directly after an error */
1038/* returns the number of required bytes */
1039static int encode(char *buf, int size, const char *user, const char *pwd)
1040{
1041 unsigned char inbuf[3];
1042 char *out = buf;
1043 int i, sep = 0, fill = 0, bytes = 0;
1044
1045 while(*user || *pwd)
1046 {
1047 i = 0;
1048 while(i < 3 && *user) inbuf[i++] = *(user++);
1049 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
1050 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
1051 while(i < 3) {inbuf[i++] = 0; ++fill; }
1052 if(out-buf < size-1)
1053 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
1054 if(out-buf < size-1)
1055 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
1056 | ((inbuf [1] & 0xF0) >> 4)];
1057 if(out-buf < size-1)
1058 {
1059 if(fill == 2)
1060 *(out++) = '=';
1061 else
1062 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
1063 | ((inbuf [2] & 0xC0) >> 6)];
1064 }
1065 if(out-buf < size-1)
1066 {
1067 if(fill >= 1)
1068 *(out++) = '=';
1069 else
1070 *(out++) = encodingTable[inbuf [2] & 0x3F];
1071 }
1072 bytes += 4;
1073 }
1074 if(out-buf < size)
1075 *out = 0;
1076 return bytes;
1077}
1078
1079static int stop = 0;
1080
1081struct Args
1082{
1083 const char *server;
1084 int port;
1085 int timeout;
1086 const char *user;
1087 const char *password;
1088 const char *data;
1089 const char *headerfile;
1090};
1091
1092/* option parsing */
1093#ifdef NO_LONG_OPTS
1094#define LONG_OPT(a)
1095#else
1096#define LONG_OPT(a) a
1097static struct option opts[] = {
1098{ "data", required_argument, 0, 'd'},
1099{ "server", required_argument, 0, 's'},
1100{ "password", required_argument, 0, 'p'},
1101{ "port", required_argument, 0, 'r'},
1102{ "timeout", required_argument, 0, 't'},
1103{ "header", required_argument, 0, 'f'},
1104{ "user", required_argument, 0, 'u'},
1105{ "help", no_argument, 0, 'h'},
1106{0,0,0,0}};
1107#endif
1108#define ARGOPT "-d:s:p:r:t:f:u:h"
1109
1110static const char *geturl(const char *url, struct Args *args)
1111{
1112 static char buf[1000];
1113 static char *Buffer = buf;
1114 static char *Bufend = buf+sizeof(buf);
1115
1116 if(strncmp("ntrip:", url, 6))
1117 return "URL must start with 'ntrip:'.";
1118 url += 6; /* skip ntrip: */
1119
1120 if(*url != '@' && *url != '/')
1121 {
1122 /* scan for mountpoint */
1123 args->data = Buffer;
1124 while(*url && *url != '@' && *url != '/' && Buffer != Bufend)
1125 *(Buffer++) = *(url++);
1126 if(Buffer == args->data)
1127 return "Mountpoint required.";
1128 else if(Buffer >= Bufend-1)
1129 return "Parsing buffer too short.";
1130 *(Buffer++) = 0;
1131 }
1132
1133 if(*url == '/') /* username and password */
1134 {
1135 ++url;
1136 args->user = Buffer;
1137 while(*url && *url != '@' && *url != ':' && Buffer != Bufend)
1138 *(Buffer++) = *(url++);
1139 if(Buffer == args->user)
1140 return "Username cannot be empty.";
1141 else if(Buffer >= Bufend-1)
1142 return "Parsing buffer too short.";
1143 *(Buffer++) = 0;
1144
1145 if(*url == ':') ++url;
1146
1147 args->password = Buffer;
1148 while(*url && *url != '@' && Buffer != Bufend)
1149 *(Buffer++) = *(url++);
1150 if(Buffer == args->password)
1151 return "Password cannot be empty.";
1152 else if(Buffer >= Bufend-1)
1153 return "Parsing buffer too short.";
1154 *(Buffer++) = 0;
1155 }
1156
1157 if(*url == '@') /* server */
1158 {
1159 ++url;
1160 args->server = Buffer;
1161 while(*url && *url != ':' && Buffer != Bufend)
1162 *(Buffer++) = *(url++);
1163 if(Buffer == args->server)
1164 return "Servername cannot be empty.";
1165 else if(Buffer >= Bufend-1)
1166 return "Parsing buffer too short.";
1167 *(Buffer++) = 0;
1168
1169 if(*url == ':')
1170 {
1171 char *s2 = 0;
1172 args->port = strtol(++url, &s2, 10);
1173 if(*s2 || args->port <= 0 || args->port > 0xFFFF)
1174 return "Illegal port number.";
1175 url = s2;
1176 }
1177 }
1178
1179 return *url ? "Garbage at end of server string." : 0;
1180}
1181
1182static int getargs(int argc, char **argv, struct Args *args)
1183{
1184 int res = 1;
1185 int getoptr;
1186 int help = 0;
1187 char *t;
1188
1189 args->server = "www.euref-ip.net";
1190 args->port = 2101;
1191 args->timeout = 60;
1192 args->user = "";
1193 args->password = "";
1194 args->data = 0;
1195 args->headerfile = 0;
1196 help = 0;
1197
1198 do
1199 {
1200
1201#ifdef NO_LONG_OPTS
1202 switch((getoptr = getopt(argc, argv, ARGOPT)))
1203#else
1204 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
1205#endif
1206 {
1207 case 's': args->server = optarg; break;
1208 case 'u': args->user = optarg; break;
1209 case 'p': args->password = optarg; break;
1210 case 'd': args->data = optarg; break;
1211 case 'f': args->headerfile = optarg; break;
1212 case 'h': help=1; break;
1213 case 'r':
1214 args->port = strtoul(optarg, &t, 10);
1215 if((t && *t) || args->port < 1 || args->port > 65535)
1216 res = 0;
1217 break;
1218 case 't':
1219 args->timeout = strtoul(optarg, &t, 10);
1220 if((t && *t) || args->timeout < 0)
1221 res = 0;
1222 break;
1223
1224 case 1:
1225 {
1226 const char *err;
1227 if((err = geturl(optarg, args)))
1228 {
1229 RTCM3Error("%s\n\n", err);
1230 res = 0;
1231 }
1232 }
1233 break;
1234 case -1: break;
1235 }
1236 } while(getoptr != -1 || !res);
1237
1238 datestr[0] = datestr[7];
1239 datestr[1] = datestr[8];
1240 datestr[2] = datestr[9];
1241 datestr[3] = datestr[10];
1242 datestr[5] = datestr[12];
1243 datestr[6] = datestr[13];
1244 datestr[8] = datestr[15];
1245 datestr[9] = datestr[16];
1246 datestr[4] = datestr[7] = '-';
1247 datestr[10] = 0;
1248
1249 if(!res || help)
1250 {
1251 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
1252 "\nUsage: %s -s server -u user ...\n"
1253 " -d " LONG_OPT("--data ") "the requested data set\n"
1254 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
1255 " -s " LONG_OPT("--server ") "the server name or address\n"
1256 " -p " LONG_OPT("--password ") "the login password\n"
1257 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
1258 " -t " LONG_OPT("--timeout ") "timeout in seconds\n"
1259 " -u " LONG_OPT("--user ") "the user name\n"
1260 "or using an URL:\n%s ntrip:mountpoint[/username[:password]][@server[:port]]\n"
1261 , revisionstr, datestr, argv[0], argv[0]);
1262 exit(1);
1263 }
1264 return res;
1265}
1266
1267/* let the output complete a block if necessary */
1268static void signalhandler(int sig)
1269{
1270 if(!stop)
1271 {
1272 RTCM3Error("Stop signal number %d received. "
1273 "Trying to terminate gentle.\n", sig);
1274 stop = 1;
1275 alarm(1);
1276 }
1277}
1278
1279/* for some reason we had to abort hard (maybe waiting for data */
1280#ifdef __GNUC__
1281static __attribute__ ((noreturn)) void signalhandler_alarm(
1282int sig __attribute__((__unused__)))
1283#else /* __GNUC__ */
1284static void signalhandler_alarm(int sig)
1285#endif /* __GNUC__ */
1286{
1287 RTCM3Error("Programm forcefully terminated.\n");
1288 exit(1);
1289}
1290
1291int main(int argc, char **argv)
1292{
1293 struct Args args;
1294 struct RTCM3ParserData Parser;
1295
1296 struct timeval tv;
1297
1298 setbuf(stdout, 0);
1299 setbuf(stdin, 0);
1300 setbuf(stderr, 0);
1301
1302 {
1303 char *a;
1304 int i=0;
1305 for(a = revisionstr+11; *a && *a != ' '; ++a)
1306 revisionstr[i++] = *a;
1307 revisionstr[i] = 0;
1308 }
1309
1310 signal(SIGINT, signalhandler);
1311 signal(SIGALRM,signalhandler_alarm);
1312 signal(SIGQUIT,signalhandler);
1313 signal(SIGTERM,signalhandler);
1314 signal(SIGPIPE,signalhandler);
1315 memset(&Parser, 0, sizeof(Parser));
1316 {
1317 time_t tim;
1318 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
1319 Parser.GPSWeek = tim/(7*24*60*60);
1320 Parser.GPSTOW = tim%(7*24*60*60);
1321 }
1322
1323 if(getargs(argc, argv, &args))
1324 {
1325 int i, sockfd, numbytes;
1326 char buf[MAXDATASIZE];
1327 struct hostent *he;
1328 struct sockaddr_in their_addr; /* connector's address information */
1329
1330 Parser.headerfile = args.headerfile;
1331
1332 if(!(he=gethostbyname(args.server)))
1333 {
1334 RTCM3Error("Function gethostbyname: %s\n", strerror(errno));
1335 exit(1);
1336 }
1337 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1338 {
1339 RTCM3Error("Function socket: %s\n", strerror(errno));
1340 exit(1);
1341 }
1342
1343 tv.tv_sec = args.timeout;
1344 tv.tv_usec = 0;
1345 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
1346 {
1347 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
1348 exit(1);
1349 }
1350
1351 their_addr.sin_family = AF_INET; /* host byte order */
1352 their_addr.sin_port = htons(args.port); /* short, network byte order */
1353 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
1354 memset(&(their_addr.sin_zero), '\0', 8);
1355 if(connect(sockfd, (struct sockaddr *)&their_addr,
1356 sizeof(struct sockaddr)) == -1)
1357 {
1358 RTCM3Error("Function connect: %s\n", strerror(errno));
1359 exit(1);
1360 }
1361
1362 if(!args.data)
1363 {
1364 i = snprintf(buf, MAXDATASIZE,
1365 "GET / HTTP/1.0\r\n"
1366 "User-Agent: %s/%s\r\n"
1367#ifdef UNUSED
1368 "Accept: */*\r\n"
1369 "Connection: close\r\n"
1370#endif
1371 "\r\n"
1372 , AGENTSTRING, revisionstr);
1373 }
1374 else
1375 {
1376 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
1377 "GET /%s HTTP/1.0\r\n"
1378 "User-Agent: %s/%s\r\n"
1379#ifdef UNUSED
1380 "Accept: */*\r\n"
1381 "Connection: close\r\n"
1382#endif
1383 "Authorization: Basic "
1384 , args.data, AGENTSTRING, revisionstr);
1385 if(i > MAXDATASIZE-40 && i < 0) /* second check for old glibc */
1386 {
1387 RTCM3Error("Requested data too long\n");
1388 exit(1);
1389 }
1390 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
1391 if(i > MAXDATASIZE-4)
1392 {
1393 RTCM3Error("Username and/or password too long\n");
1394 exit(1);
1395 }
1396 buf[i++] = '\r';
1397 buf[i++] = '\n';
1398 buf[i++] = '\r';
1399 buf[i++] = '\n';
1400 }
1401 if(send(sockfd, buf, (size_t)i, 0) != i)
1402 {
1403 RTCM3Error("Function send: %s\n", strerror(errno));
1404 exit(1);
1405 }
1406 if(args.data)
1407 {
1408 int k = 0;
1409 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
1410 {
1411 if(!k)
1412 {
1413 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
1414 {
1415 RTCM3Error("Could not get the requested data: ");
1416 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
1417 {
1418 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
1419 }
1420 RTCM3Error("\n");
1421 exit(1);
1422 }
1423 ++k;
1424 }
1425 else
1426 {
1427 int z;
1428 for(z = 0; z < numbytes && !stop; ++z)
1429 HandleByte(&Parser, (unsigned int) buf[z]);
1430 }
1431 }
1432 }
1433 else
1434 {
1435 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
1436 {
1437 fwrite(buf, (size_t)numbytes, 1, stdout);
1438 }
1439 }
1440
1441 close(sockfd);
1442 }
1443 return 0;
1444}
1445#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.