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

Last change on this file since 268 was 268, checked in by stoecker, 18 years ago

updated to support BNC

File size: 26.7 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c,v 1.5 2006/08/29 15:42:36 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 <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <sys/types.h>
35#include <time.h>
36#include <unistd.h>
37
38#ifndef NO_RTCM3_MAIN
39#include <getopt.h>
40#include <netdb.h>
41#include <netinet/in.h>
42#include <sys/socket.h>
43#endif
44
45#include "rtcm3torinex.h"
46
47/* CVS revision and version */
48static char revisionstr[] = "$Revision: 1.5 $";
49static char datestr[] = "$Date: 2006/08/29 15:42:36 $";
50
51static const char encodingTable [64] = {
52 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
53 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
54 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
55 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
56};
57
58/* does not buffer overrun, but breaks directly after an error */
59/* returns the number of required bytes */
60static int encode(char *buf, int size, const char *user, const char *pwd)
61{
62 unsigned char inbuf[3];
63 char *out = buf;
64 int i, sep = 0, fill = 0, bytes = 0;
65
66 while(*user || *pwd)
67 {
68 i = 0;
69 while(i < 3 && *user) inbuf[i++] = *(user++);
70 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
71 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
72 while(i < 3) {inbuf[i++] = 0; ++fill; }
73 if(out-buf < size-1)
74 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
75 if(out-buf < size-1)
76 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
77 | ((inbuf [1] & 0xF0) >> 4)];
78 if(out-buf < size-1)
79 {
80 if(fill == 2)
81 *(out++) = '=';
82 else
83 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
84 | ((inbuf [2] & 0xC0) >> 6)];
85 }
86 if(out-buf < size-1)
87 {
88 if(fill >= 1)
89 *(out++) = '=';
90 else
91 *(out++) = encodingTable[inbuf [2] & 0x3F];
92 }
93 bytes += 4;
94 }
95 if(out-buf < size)
96 *out = 0;
97 return bytes;
98}
99
100static uint32_t CRC24(long size, const unsigned char *buf)
101{
102 uint32_t crc = 0;
103 int i;
104
105 while(size--)
106 {
107 crc ^= (*buf++) << (16);
108 for(i = 0; i < 8; i++)
109 {
110 crc <<= 1;
111 if(crc & 0x1000000)
112 crc ^= 0x01864cfb;
113 }
114 }
115 return crc;
116}
117
118static int GetMessage(struct RTCM3ParserData *handle)
119{
120 unsigned char *m, *e;
121 int i;
122
123 m = handle->Message+handle->SkipBytes;
124 e = handle->Message+handle->MessageSize;
125 handle->NeedBytes = handle->SkipBytes = 0;
126 while(e-m >= 3)
127 {
128 if(m[0] == 0xD3)
129 {
130 handle->size = ((m[1]&3)<<8)|m[2];
131 if(e-m >= handle->size+6)
132 {
133 if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8)
134 |(m[3+handle->size+2])) == CRC24(handle->size+3, m))
135 {
136 handle->SkipBytes = handle->size;
137 break;
138 }
139 else
140 ++m;
141 }
142 else
143 {
144 handle->NeedBytes = handle->size+6;
145 break;
146 }
147 }
148 else
149 ++m;
150 }
151 if(e-m < 3)
152 handle->NeedBytes = 3;
153
154 /* copy buffer to front */
155 i = m - handle->Message;
156 if(i && m < e)
157 memmove(handle->Message, m, handle->MessageSize-i);
158 handle->MessageSize -= i;
159
160 return !handle->NeedBytes;
161}
162
163#define LOADBITS(a) \
164{ \
165 while((a) > numbits) \
166 { \
167 if(!size--) break; \
168 bitfield = (bitfield<<8)|*(data++); \
169 numbits += 8; \
170 } \
171}
172
173/* extract bits from data stream
174 b = variable to store result, a = number of bits */
175#define GETBITS(b, a) \
176{ \
177 LOADBITS(a) \
178 b = (bitfield<<(64-numbits))>>(64-(a)); \
179 numbits -= (a); \
180}
181
182/* extract bits from data stream
183 b = variable to store result, a = number of bits */
184#define GETBITSSIGN(b, a) \
185{ \
186 LOADBITS(a) \
187 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
188 numbits -= (a); \
189}
190
191#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
192
193int RTCM3Parser(struct RTCM3ParserData *handle)
194{
195 int ret=0;
196
197 while(!ret && GetMessage(handle))
198 {
199 /* using 64 bit integer types, as it is much easier than handling
200 the long datatypes in 32 bit */
201 uint64_t numbits = 0, bitfield = 0;
202 int size = handle->size, type;
203 unsigned char *data = handle->Message+3;
204
205 GETBITS(type,12)
206 switch(type)
207 {
208 case 1001: case 1002: case 1003: case 1004:
209 if(handle->GPSWeek)
210 {
211 int lastlockl1[64];
212 int lastlockl2[64];
213 struct gnssdata *gnss;
214 int i, num, wasamb=0;
215
216 for(i = 0; i < 64; ++i)
217 lastlockl1[i] = lastlockl2[i] = 0;
218
219 gnss = &handle->Data;
220 memset(gnss, 0, sizeof(*gnss));
221
222 SKIPBITS(12) /* id */
223 GETBITS(i,30)
224 if(i/1000 < (int)handle->GPSTOW - 86400)
225 ++handle->GPSWeek;
226 handle->GPSTOW = i/1000;
227 gnss->timeofweek = i;
228 gnss->week = handle->GPSWeek;
229
230 SKIPBITS(1) /* sync */
231 GETBITS(i,5)
232 gnss->numsats = i;
233 SKIPBITS(4) /* smind, smint */
234
235 for(num = 0; num < gnss->numsats; ++num)
236 {
237 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
238
239 GETBITS(sv, 6);
240 gnss->satellites[num] = (sv < 40 ? sv : sv+80);
241 /* L1 */
242 GETBITS(code, 1);
243 if(code)
244 {
245 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
246 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
247 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
248 }
249 else
250 {
251 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
252 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
253 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
254 }
255 GETBITS(l1range, 24);
256 if(l1range != 0x80000)
257 {
258 gnss->dataflags[num] |= c;
259 gnss->measdata[num][ce] = l1range*0.02;
260 }
261 GETBITSSIGN(i, 20);
262 if(i != 0x80000)
263 {
264 gnss->dataflags[num] |= l;
265 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
266 }
267 GETBITS(i, 7);
268 lastlockl1[sv] = i;
269 if(handle->lastlockl1[sv] > i)
270 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL1;
271 if(type == 1002 || type == 1004)
272 {
273 GETBITS(amb,8);
274 if(amb && (gnss->dataflags[num] & c))
275 {
276 gnss->measdata[num][ce] += amb*299792.458;
277 gnss->measdata[num][le] += amb*299792.458;
278 ++wasamb;
279 }
280 GETBITS(i, 8);
281 if(i)
282 {
283 gnss->dataflags[num] |= s;
284 gnss->measdata[num][se] = i*0.25;
285 i /= 4*4;
286 if(i > 9) i = 9;
287 else if(i < 1) i = 1;
288 gnss->snrL1[num] = i;
289 }
290 }
291 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
292 if(type == 1003 || type == 1004)
293 {
294 /* L2 */
295 GETBITS(code,2);
296 if(code)
297 {
298 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
299 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
300 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
301 }
302 else
303 {
304 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
305 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
306 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
307 }
308 GETBITSSIGN(i,14);
309 if(i != 0x2000)
310 {
311 gnss->dataflags[num] |= c;
312 gnss->measdata[num][ce] = l1range*0.02+i*0.02
313 +amb*299792.458;
314 }
315 GETBITSSIGN(i,20);
316 if(i != 0x80000)
317 {
318 gnss->dataflags[num] |= l;
319 gnss->measdata[num][le] = l1range*0.02+i*0.0005
320 +amb*299792.458;
321 }
322 GETBITS(i,7);
323 lastlockl2[sv] = i;
324 if(handle->lastlockl2[sv] > i)
325 gnss->dataflags[num] |= GNSSDF_LOCKLOSSL2;
326 if(type == 1004)
327 {
328 GETBITS(i, 8);
329 if(i)
330 {
331 gnss->dataflags[num] |= s;
332 gnss->measdata[num][se] = i*0.25;
333 i /= 4*4;
334 if(i > 9) i = 9;
335 else if(i < 1) i = 1;
336 gnss->snrL2[num] = i;
337 }
338 }
339 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
340 }
341 }
342 for(i = 0; i < 64; ++i)
343 {
344 handle->lastlockl1[i] = lastlockl1[i];
345 handle->lastlockl2[i] = lastlockl2[i];
346 }
347 if(wasamb) /* not RINEX compatible without */
348 ret = 1;
349 else
350 ret = 2;
351 }
352 break;
353 }
354 }
355 return ret;
356}
357
358static int longyear(int year, int month)
359{
360 if(!(year % 4) && (!(year % 400) || (year % 100)))
361 {
362 if(!month || month == 2)
363 return 1;
364 }
365 return 0;
366}
367
368void converttime(struct converttimeinfo *c, int week, int tow)
369{
370 /* static variables */
371 static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
372
373 int i, k, doy, j; /* temporary variables */
374 j = week*(7*24*60*60) + tow + 5*24*60*60;
375 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
376 j -= k;
377 c->year = i;
378 doy = 1+ (j / (24*60*60));
379 j %= (24*60*60);
380 c->hour = j / (60*60);
381 j %= (60*60);
382 c->minute = j / 60;
383 c->second = j % 60;
384 j = 0;
385 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
386 j += k;
387 c->month = i;
388 c->day = doy - j;
389}
390
391struct Header
392{
393 const char *version;
394 const char *pgm;
395 const char *marker;
396 const char *observer;
397 const char *receiver;
398 const char *antenna;
399 const char *position;
400 const char *antennaposition;
401 const char *wavelength;
402 const char *typesofobs; /* should not be modified outside */
403 const char *timeoffirstobs; /* should not be modified outside */
404};
405
406#define MAXHEADERLINES 50
407#define MAXHEADERBUFFERSIZE 4096
408struct HeaderData
409{
410 union
411 {
412 struct Header named;
413 const char *unnamed[MAXHEADERLINES];
414 } data;
415 int numheaders;
416};
417
418void HandleHeader(struct RTCM3ParserData *Parser)
419{
420 struct HeaderData hdata;
421 char thebuffer[MAXHEADERBUFFERSIZE];
422 char *buffer = thebuffer;
423 int buffersize = sizeof(thebuffer);
424 int i;
425
426 hdata.data.named.version =
427 " 2.11 OBSERVATION DATA M (Mixed)"
428 " RINEX VERSION / TYPE";
429
430 {
431 const char *str;
432 time_t t;
433 struct tm * t2;
434
435 str = getenv("USER");
436 if(!str) str = "";
437 t = time(&t);
438 t2 = gmtime(&t);
439 hdata.data.named.pgm = buffer;
440 i = 1+snprintf(buffer, buffersize,
441 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
442 "PGM / RUN BY / DATE",
443 revisionstr, str, 1900+t2->tm_year, t2->tm_mon+1, t2->tm_mday, t2->tm_hour,
444 t2->tm_min);
445 buffer += i; buffersize -= i;
446
447 hdata.data.named.observer = buffer;
448 i = 1+snprintf(buffer, buffersize,
449 "%-20.20s "
450 "OBSERVER / AGENCY", str);
451 buffer += i; buffersize -= i;
452 }
453
454 hdata.data.named.marker =
455 "RTCM3TORINEX "
456 "MARKER NAME";
457
458 hdata.data.named.receiver =
459 " "
460 "REC # / TYPE / VERS";
461
462 hdata.data.named.antenna =
463 " "
464 "ANT # / TYPE";
465
466 hdata.data.named.position =
467 " .0000 .0000 .0000 "
468 "APPROX POSITION XYZ";
469
470 hdata.data.named.antennaposition =
471 " .0000 .0000 .0000 "
472 "ANTENNA: DELTA H/E/N";
473
474 hdata.data.named.wavelength =
475 " 1 1 "
476 "WAVELENGTH FACT L1/2";
477
478 {
479#define CHECKFLAGS(a, b) \
480 if(flags & GNSSDF_##a##DATA \
481 && !data[RINEXENTRY_##b##DATA]) \
482 { \
483 Parser->dataflag[Parser->numdatatypes] = GNSSDF_##a##DATA; \
484 Parser->datapos[Parser->numdatatypes++] = data[RINEXENTRY_##b##DATA] \
485 = GNSSENTRY_##a##DATA; \
486 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
487 tbufferpos += 6; \
488 }
489
490 int flags = 0;
491 int data[RINEXENTRY_NUMBER];
492 char tbuffer[6*RINEXENTRY_NUMBER+1];
493 int tbufferpos = 0;
494 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
495 data[i] = 0;
496 for(i = 0; i < Parser->Data.numsats; ++i)
497 flags |= Parser->Data.dataflags[i];
498
499 CHECKFLAGS(C1,C1)
500 CHECKFLAGS(C2,C2)
501 CHECKFLAGS(P1,P1)
502 CHECKFLAGS(P2,P2)
503 CHECKFLAGS(L1C,L1)
504 CHECKFLAGS(L1P,L1)
505 CHECKFLAGS(L2C,L2)
506 CHECKFLAGS(L2P,L2)
507 CHECKFLAGS(D1C,D1)
508 CHECKFLAGS(D1P,D1)
509 CHECKFLAGS(D2C,D2)
510 CHECKFLAGS(D2P,D2)
511 CHECKFLAGS(S1C,S1)
512 CHECKFLAGS(S1P,S1)
513 CHECKFLAGS(S2C,S2)
514 CHECKFLAGS(S2P,S2)
515
516 hdata.data.named.typesofobs = buffer;
517 i = 1+snprintf(buffer, buffersize,
518 "%6i%-54.54s# / TYPES OF OBSERV", Parser->numdatatypes, tbuffer);
519 if(Parser->numdatatypes>9)
520 {
521 i += snprintf(buffer+i-1, buffersize,
522 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
523 }
524 buffer += i; buffersize -= i;
525 }
526
527 {
528 struct converttimeinfo cti;
529 converttime(&cti, Parser->Data.week,
530 (int)floor(Parser->Data.timeofweek/1000.0));
531 hdata.data.named.timeoffirstobs = buffer;
532 i = 1+snprintf(buffer, buffersize,
533 " %4d %2d %2d %2d %2d %10.7f GPS "
534 "TIME OF FIRST OBS", cti.year%100, cti.month, cti.day, cti.hour,
535 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
536
537 buffer += i; buffersize -= i;
538 }
539
540 hdata.numheaders = 11;
541
542 if(Parser->headerfile)
543 {
544 FILE *fh;
545 if((fh = fopen(Parser->headerfile, "r")))
546 {
547 int siz;
548 char *lastblockstart;
549 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
550 {
551 buffer[siz] = '\n';
552 if(siz == buffersize)
553 {
554 fprintf(stderr, "Header file is too large. Only %d bytes read.",
555 siz);
556 }
557 /* scan the file line by line and enter the entries in the list */
558 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
559 /* overwrites entries, except for comments */
560 lastblockstart = buffer;
561 for(i = 0; i < siz; ++i)
562 {
563 if(buffer[i] == '\n')
564 { /* we found a line */
565 char *end;
566 while(buffer[i+1] == '\r')
567 ++i; /* skip \r in case there are any */
568 end = buffer+i;
569 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
570 *(end--) = 0;
571 if(end-lastblockstart < 60+5) /* short line */
572 fprintf(stderr, "Short Header line '%s' ignored.\n", lastblockstart);
573 else
574 {
575 int pos;
576 if(!strcmp("COMMENT", lastblockstart+60))
577 pos = hdata.numheaders;
578 else
579 {
580 for(pos = 0; pos < hdata.numheaders; ++pos)
581 {
582 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
583 break;
584 }
585 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
586 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
587 {
588 fprintf(stderr, "Overwriting header '%s' is dangerous.\n",
589 lastblockstart+60);
590 }
591 }
592 if(pos >= MAXHEADERLINES)
593 {
594 fprintf(stderr,
595 "Maximum number of header lines of %d reached.\n",
596 MAXHEADERLINES);
597 }
598 else if(!strcmp("END OF HEADER", lastblockstart+60))
599 {
600 fprintf(stderr, "End of header ignored.\n");
601 }
602 else
603 {
604 hdata.data.unnamed[pos] = lastblockstart;
605 if(pos == hdata.numheaders)
606 ++hdata.numheaders;
607 }
608 }
609 lastblockstart = buffer+i+1;
610 }
611 }
612 }
613 else
614 {
615 fprintf(stderr, "Could not read data from headerfile '%s'.\n",
616 Parser->headerfile);
617 }
618 fclose(fh);
619 }
620 else
621 {
622 fprintf(stderr, "Could not open header datafile '%s'.\n",
623 Parser->headerfile);
624 }
625 }
626
627 for(i = 0; i < hdata.numheaders; ++i)
628 printf("%s\n", hdata.data.unnamed[i]);
629 printf(" "
630 "END OF HEADER\n");
631}
632
633void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
634{
635 Parser->Message[Parser->MessageSize++] = byte;
636 if(Parser->MessageSize >= Parser->NeedBytes)
637 {
638 int r;
639 while((r = RTCM3Parser(Parser)))
640 {
641 int i, j, o;
642 struct converttimeinfo cti;
643
644 if(!Parser->init)
645 {
646 HandleHeader(Parser);
647 Parser->init = 1;
648 }
649 if(r == 2 && !Parser->validwarning)
650 {
651 printf("No valid RINEX! All values are modulo 299792.458!"
652 " COMMENT\n");
653 Parser->validwarning = 1;
654 }
655
656 converttime(&cti, Parser->Data.week,
657 floor(Parser->Data.timeofweek/1000.0));
658 printf(" %02d %2d %2d %2d %2d %10.7f 0%3d",
659 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
660 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
661 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
662 {
663 if(Parser->Data.satellites[i] <= PRN_GPS_END)
664 printf("G%02d", Parser->Data.satellites[i]);
665 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
666 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
667 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
668 else
669 printf("%3d", Parser->Data.satellites[i]);
670 }
671 printf("\n");
672 o = 12;
673 j = Parser->Data.numsats - 12;
674 while(j > 0)
675 {
676 printf(" ");
677 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
678 {
679 if(Parser->Data.satellites[i] <= PRN_GPS_END)
680 printf("G%02d", Parser->Data.satellites[i]);
681 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
682 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
683 printf("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
684 else
685 printf("%3d", Parser->Data.satellites[i]);
686 }
687 printf("\n");
688 j -= 12;
689 o += 12;
690 }
691 for(i = 0; i < Parser->Data.numsats; ++i)
692 {
693 for(j = 0; j < Parser->numdatatypes; ++j)
694 {
695 if(!(Parser->Data.dataflags[i] & Parser->dataflag[j])
696 || isnan(Parser->Data.measdata[i][Parser->datapos[j]])
697 || isinf(Parser->Data.measdata[i][Parser->datapos[j]]))
698 { /* no or illegal data */
699 printf(" ");
700 }
701 else
702 {
703 char lli = ' ';
704 char snr = ' ';
705 if(Parser->dataflag[j] & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
706 {
707 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL1)
708 lli = '1';
709 snr = '0'+Parser->Data.snrL1[i];
710 }
711 if(Parser->dataflag[j] & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
712 {
713 if(Parser->Data.dataflags[i] & GNSSDF_LOCKLOSSL2)
714 lli = '1';
715 snr = '0'+Parser->Data.snrL2[i];
716 }
717 printf("%14.3f%c%c",
718 Parser->Data.measdata[i][Parser->datapos[j]],lli,snr);
719 }
720 if(j%5 == 4 || j == Parser->numdatatypes-1)
721 printf("\n");
722 }
723 }
724 }
725 }
726}
727
728#ifndef NO_RTCM3_MAIN
729/* The string, which is send as agent in HTTP request */
730#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
731
732#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
733
734static int stop = 0;
735
736struct Args
737{
738 const char *server;
739 int port;
740 const char *user;
741 const char *password;
742 const char *data;
743 const char *headerfile;
744};
745
746/* option parsing */
747#ifdef NO_LONG_OPTS
748#define LONG_OPT(a)
749#else
750#define LONG_OPT(a) a
751static struct option opts[] = {
752{ "data", required_argument, 0, 'd'},
753{ "server", required_argument, 0, 's'},
754{ "password", required_argument, 0, 'p'},
755{ "port", required_argument, 0, 'r'},
756{ "header", required_argument, 0, 'f'},
757{ "user", required_argument, 0, 'u'},
758{ "help", no_argument, 0, 'h'},
759{0,0,0,0}};
760#endif
761#define ARGOPT "d:hp:r:s:u:f:"
762
763static int getargs(int argc, char **argv, struct Args *args)
764{
765 int res = 1;
766 int getoptr;
767 int help = 0;
768 char *t;
769
770 args->server = "www.euref-ip.net";
771 args->port = 80;
772 args->user = "";
773 args->password = "";
774 args->data = 0;
775 args->headerfile = 0;
776 help = 0;
777
778 do
779 {
780#ifdef NO_LONG_OPTS
781 switch((getoptr = getopt(argc, argv, ARGOPT)))
782#else
783 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
784#endif
785 {
786 case 's': args->server = optarg; break;
787 case 'u': args->user = optarg; break;
788 case 'p': args->password = optarg; break;
789 case 'd': args->data = optarg; break;
790 case 'f': args->headerfile = optarg; break;
791 case 'h': help=1; break;
792 case 'r':
793 args->port = strtoul(optarg, &t, 10);
794 if((t && *t) || args->port < 1 || args->port > 65535)
795 res = 0;
796 break;
797 case -1: break;
798 }
799 } while(getoptr != -1 || !res);
800
801 datestr[0] = datestr[7];
802 datestr[1] = datestr[8];
803 datestr[2] = datestr[9];
804 datestr[3] = datestr[10];
805 datestr[5] = datestr[12];
806 datestr[6] = datestr[13];
807 datestr[8] = datestr[15];
808 datestr[9] = datestr[16];
809 datestr[4] = datestr[7] = '-';
810 datestr[10] = 0;
811
812 if(!res || help)
813 {
814 fprintf(stderr, "Version %s (%s) GPL\nUsage: %s -s server -u user ...\n"
815 " -d " LONG_OPT("--data ") "the requested data set\n"
816 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
817 " -s " LONG_OPT("--server ") "the server name or address\n"
818 " -p " LONG_OPT("--password ") "the login password\n"
819 " -r " LONG_OPT("--port ") "the server port number (default 80)\n"
820 " -u " LONG_OPT("--user ") "the user name\n"
821 , revisionstr, datestr, argv[0]);
822 exit(1);
823 }
824 return res;
825}
826
827/* let the output complete a block if necessary */
828static void signalhandler(int sig)
829{
830 if(!stop)
831 {
832 fprintf(stderr, "Stop signal number %d received. "
833 "Trying to terminate gentle.\n", sig);
834 stop = 1;
835 alarm(1);
836 }
837}
838
839/* for some reason we had to abort hard (maybe waiting for data */
840#ifdef __GNUC__
841static __attribute__ ((noreturn)) void signalhandler_alarm(
842int sig __attribute__((__unused__)))
843#else /* __GNUC__ */
844static void signalhandler_alarm(int sig)
845#endif /* __GNUC__ */
846{
847 fprintf(stderr, "Programm forcefully terminated.\n");
848 exit(1);
849}
850
851int main(int argc, char **argv)
852{
853 struct Args args;
854 struct RTCM3ParserData Parser;
855
856 setbuf(stdout, 0);
857 setbuf(stdin, 0);
858 setbuf(stderr, 0);
859
860 {
861 char *a;
862 int i=0;
863 for(a = revisionstr+11; *a && *a != ' '; ++a)
864 revisionstr[i++] = *a;
865 revisionstr[i] = 0;
866 }
867
868 signal(SIGINT, signalhandler);
869 signal(SIGALRM,signalhandler_alarm);
870 signal(SIGQUIT,signalhandler);
871 signal(SIGTERM,signalhandler);
872 signal(SIGPIPE,signalhandler);
873 memset(&Parser, 0, sizeof(Parser));
874 {
875 time_t tim;
876 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
877 Parser.GPSWeek = tim/(7*24*60*60);
878 Parser.GPSTOW = tim%(7*24*60*60);
879 }
880
881 if(getargs(argc, argv, &args))
882 {
883 int i, sockfd, numbytes;
884 char buf[MAXDATASIZE];
885 struct hostent *he;
886 struct sockaddr_in their_addr; /* connector's address information */
887
888 Parser.headerfile = args.headerfile;
889
890 if(!(he=gethostbyname(args.server)))
891 {
892 perror("gethostbyname");
893 exit(1);
894 }
895 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
896 {
897 perror("socket");
898 exit(1);
899 }
900 their_addr.sin_family = AF_INET; /* host byte order */
901 their_addr.sin_port = htons(args.port); /* short, network byte order */
902 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
903 memset(&(their_addr.sin_zero), '\0', 8);
904 if(connect(sockfd, (struct sockaddr *)&their_addr,
905 sizeof(struct sockaddr)) == -1)
906 {
907 perror("connect");
908 exit(1);
909 }
910
911 if(!args.data)
912 {
913 i = snprintf(buf, MAXDATASIZE,
914 "GET / HTTP/1.0\r\n"
915 "User-Agent: %s/%s\r\n"
916#ifdef UNUSED
917 "Accept: */*\r\n"
918 "Connection: close\r\n"
919#endif
920 "\r\n"
921 , AGENTSTRING, revisionstr);
922 }
923 else
924 {
925 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
926 "GET /%s HTTP/1.0\r\n"
927 "User-Agent: %s/%s\r\n"
928#ifdef UNUSED
929 "Accept: */*\r\n"
930 "Connection: close\r\n"
931#endif
932 "Authorization: Basic "
933 , args.data, AGENTSTRING, revisionstr);
934 if(i > MAXDATASIZE-40 && i < 0) /* second check for old glibc */
935 {
936 fprintf(stderr, "Requested data too long\n");
937 exit(1);
938 }
939 i += encode(buf+i, MAXDATASIZE-i-5, args.user, args.password);
940 if(i > MAXDATASIZE-5)
941 {
942 fprintf(stderr, "Username and/or password too long\n");
943 exit(1);
944 }
945 snprintf(buf+i, 5, "\r\n\r\n");
946 i += 5;
947 }
948 if(send(sockfd, buf, (size_t)i, 0) != i)
949 {
950 perror("send");
951 exit(1);
952 }
953 if(args.data)
954 {
955 int k = 0;
956 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
957 {
958 if(!k)
959 {
960 if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
961 {
962 fprintf(stderr, "Could not get the requested data: ");
963 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
964 {
965 fprintf(stderr, "%c", isprint(buf[k]) ? buf[k] : '.');
966 }
967 fprintf(stderr, "\n");
968 exit(1);
969 }
970 ++k;
971 }
972 else
973 {
974 int z;
975 for(z = 0; z < numbytes && !stop; ++z)
976 HandleByte(&Parser, buf[z]);
977 }
978 }
979 }
980 else
981 {
982 while((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
983 {
984 fwrite(buf, (size_t)numbytes, 1, stdout);
985 }
986 }
987
988 close(sockfd);
989 }
990 return 0;
991}
992#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.