source: ntrip/trunk/rtcm3torinex/lib/rtcm3torinex.c @ 3581

Last change on this file since 3581 was 3581, checked in by stoecker, 9 years ago

update MSM data format to current layout

  • Property svn:keywords set to Id Revision Date
File size: 110.7 KB
Line 
1/*
2  Converter for RTCM3 data to RINEX.
3  $Id: rtcm3torinex.c 3581 2012-01-09 16:18:58Z stoecker $
4  Copyright (C) 2005-2008 by Dirk Stöcker <stoecker@alberding.eu>
5
6  This software is a complete NTRIP-RTCM3 to RINEX converter as well as
7  a module of the BNC tool for multiformat conversion. Contact Dirk
8  Stöcker for suggestions and bug reports related to the RTCM3 to RINEX
9  conversion problems and the author of BNC for all the other problems.
10
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  GNU General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  or read http://www.gnu.org/licenses/gpl.txt
25*/
26
27#include <ctype.h>
28#include <errno.h>
29#include <math.h>
30#include <signal.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/types.h>
36#include <time.h>
37#include <unistd.h>
38
39#ifndef NO_RTCM3_MAIN
40#include <getopt.h>
41#include <netdb.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44#endif
45
46#ifndef sparc
47#include <stdint.h>
48#endif
49
50#ifndef isinf
51#define isinf(x) 0
52#endif
53
54#include "rtcm3torinex.h"
55
56/* CVS revision and version */
57static char revisionstr[] = "$Revision: 3581 $";
58
59#ifndef COMPILEDATE
60#define COMPILEDATE " built " __DATE__
61#endif
62
63static uint32_t CRC24(long size, const unsigned char *buf)
64{
65  uint32_t crc = 0;
66  int i;
67
68  while(size--)
69  {
70    crc ^= (*buf++) << (16);
71    for(i = 0; i < 8; i++)
72    {
73      crc <<= 1;
74      if(crc & 0x1000000)
75        crc ^= 0x01864cfb;
76    }
77  }
78  return crc;
79}
80
81static int GetMessage(struct RTCM3ParserData *handle)
82{
83  unsigned char *m, *e;
84  int i;
85
86  m = handle->Message+handle->SkipBytes;
87  e = handle->Message+handle->MessageSize;
88  handle->NeedBytes = handle->SkipBytes = 0;
89  while(e-m >= 3)
90  {
91    if(m[0] == 0xD3)
92    {
93      handle->size = ((m[1]&3)<<8)|m[2];
94      if(e-m >= handle->size+6)
95      {
96        if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8)
97        |(m[3+handle->size+2])) == CRC24(handle->size+3, m))
98        {
99          handle->SkipBytes = handle->size;
100          break;
101        }
102        else
103          ++m;
104      }
105      else
106      {
107        handle->NeedBytes = handle->size+6;
108        break;
109      }
110    }
111    else
112      ++m;
113  }
114  if(e-m < 3)
115    handle->NeedBytes = 3;
116
117  /* copy buffer to front */
118  i = m - handle->Message;
119  if(i && m < e)
120    memmove(handle->Message, m, (size_t)(handle->MessageSize-i));
121  handle->MessageSize -= i;
122
123  return !handle->NeedBytes;
124}
125
126#define LOADBITS(a) \
127{ \
128  while((a) > numbits) \
129  { \
130    if(!size--) break; \
131    bitfield = (bitfield<<8)|*(data++); \
132    numbits += 8; \
133  } \
134}
135
136/* extract bits from data stream
137   b = variable to store result, a = number of bits */
138#define GETBITS64(b, a) \
139{ \
140  if(((a) > 56) && ((a)-56) > numbits) \
141  { \
142    uint64_t x; \
143    GETBITS(x, 56) \
144    LOADBITS((a)-56) \
145    b = ((x<<((a)-56)) | (bitfield<<(sizeof(bitfield)*8-numbits)) \
146    >>(sizeof(bitfield)*8-((a)-56))); \
147    numbits -= ((a)-56); \
148  } \
149  else \
150  { \
151    GETBITS(b, a) \
152  } \
153}
154
155/* extract bits from data stream
156   b = variable to store result, a = number of bits */
157#define GETBITS(b, a) \
158{ \
159  LOADBITS(a) \
160  b = (bitfield<<(64-numbits))>>(64-(a)); \
161  numbits -= (a); \
162}
163
164/* extract bits from data stream
165   b = variable to store result, a = number of bits */
166#define GETBITSFACTOR(b, a, c) \
167{ \
168  LOADBITS(a) \
169  b = ((bitfield<<(sizeof(bitfield)*8-numbits))>>(sizeof(bitfield)*8-(a)))*(c); \
170  numbits -= (a); \
171}
172
173/* extract floating value from data stream
174   b = variable to store result, a = number of bits */
175#define GETFLOAT(b, a, c) \
176{ \
177  LOADBITS(a) \
178  b = ((double)((bitfield<<(64-numbits))>>(64-(a))))*(c); \
179  numbits -= (a); \
180}
181
182/* extract signed floating value from data stream
183   b = variable to store result, a = number of bits */
184#define GETFLOATSIGN(b, a, c) \
185{ \
186  LOADBITS(a) \
187  b = ((double)(((int64_t)(bitfield<<(64-numbits)))>>(64-(a))))*(c); \
188  numbits -= (a); \
189}
190
191/* extract bits from data stream
192   b = variable to store result, a = number of bits */
193#define GETBITSSIGN(b, a) \
194{ \
195  LOADBITS(a) \
196  b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
197  numbits -= (a); \
198}
199
200#define GETFLOATSIGNM(b, a, c) \
201{ int l; \
202  LOADBITS(a) \
203  l = (bitfield<<(64-numbits))>>(64-1); \
204  b = ((double)(((bitfield<<(64-(numbits-1))))>>(64-(a-1))))*(c); \
205  numbits -= (a); \
206  if(l) b *= -1.0; \
207}
208
209#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
210
211/* extract byte-aligned byte from data stream,
212   b = variable to store size, s = variable to store string pointer */
213#define GETSTRING(b, s) \
214{ \
215  b = *(data++); \
216  s = (char *) data; \
217  data += b; \
218  size -= b+1; \
219}
220
221struct leapseconds { /* specify the day of leap second */
222  int day;        /* this is the day, where 23:59:59 exists 2 times */
223  int month;      /* not the next day! */
224  int year;
225  int taicount;
226};
227static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
228static const struct leapseconds leap[] = {
229/*{31, 12, 1971, 11},*/
230/*{31, 12, 1972, 12},*/
231/*{31, 12, 1973, 13},*/
232/*{31, 12, 1974, 14},*/
233/*{31, 12, 1975, 15},*/
234/*{31, 12, 1976, 16},*/
235/*{31, 12, 1977, 17},*/
236/*{31, 12, 1978, 18},*/
237/*{31, 12, 1979, 19},*/
238{30, 06, 1981,20},
239{30, 06, 1982,21},
240{30, 06, 1983,22},
241{30, 06, 1985,23},
242{31, 12, 1987,24},
243{31, 12, 1989,25},
244{31, 12, 1990,26},
245{30, 06, 1992,27},
246{30, 06, 1993,28},
247{30, 06, 1994,29},
248{31, 12, 1995,30},
249{30, 06, 1997,31},
250{31, 12, 1998,32},
251{31, 12, 2005,33},
252{31, 12, 2008,34},
253{0,0,0,0} /* end marker */
254};
255#define LEAPSECONDS     15 /* only needed for approx. time */
256#define GPSLEAPSTART    19 /* 19 leap seconds existed at 6.1.1980 */
257
258static int longyear(int year, int month)
259{
260  if(!(year % 4) && (!(year % 400) || (year % 100)))
261  {
262    if(!month || month == 2)
263      return 1;
264  }
265  return 0;
266}
267
268int gnumleap(int year, int month, int day)
269{
270  int ls = 0;
271  const struct leapseconds *l;
272
273  for(l = leap; l->taicount && year >= l->year; ++l)
274  {
275    if(year > l->year || month > l->month || (month == l->month && day > l->day))
276       ls = l->taicount - GPSLEAPSTART;
277  }
278  return ls;
279}
280
281/* Convert Moscow time into UTC (fixnumleap == 1) or GPS (fixnumleap == 0) */
282void updatetime(int *week, int *secOfWeek, int mSecOfWeek, int fixnumleap)
283{
284  int y,m,d,k,l, nul;
285  unsigned int j = *week*(7*24*60*60) + *secOfWeek + 5*24*60*60+3*60*60;
286  int glo_daynumber = 0, glo_timeofday;
287  for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
288  + gnumleap(y+1,1,1); ++y)
289  {
290    j -= k; glo_daynumber += l;
291  }
292  for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
293  + gnumleap(y, m+1, 1); ++m)
294  {
295    j -= k; glo_daynumber += l;
296  }
297  for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
298    j -= 24*60*60;
299  glo_daynumber -= 16*365+4-d;
300  nul = gnumleap(y, m, d);
301  glo_timeofday = j-nul;
302
303  // original version
304  // if(mSecOfWeek < 5*60*1000 && glo_timeofday > 23*60*60)
305  //   *secOfWeek += 24*60*60;
306  // else if(glo_timeofday < 5*60 && mSecOfWeek > 23*60*60*1000)
307  //   *secOfWeek -= 24*60*60;
308
309  // new version
310  if(mSecOfWeek < 4*60*60*1000 && glo_timeofday > 20*60*60)
311    *secOfWeek += 24*60*60;
312  else if(glo_timeofday < 4*60*60 && mSecOfWeek > 20*60*60*1000)
313    *secOfWeek -= 24*60*60;
314
315  *secOfWeek += mSecOfWeek/1000-glo_timeofday;
316  if(fixnumleap)
317    *secOfWeek -= nul;
318  if(*secOfWeek < 0) {*secOfWeek += 24*60*60*7; --*week; }
319  if(*secOfWeek >= 24*60*60*7) {*secOfWeek -= 24*60*60*7; ++*week; }
320}
321
322int RTCM3Parser(struct RTCM3ParserData *handle)
323{
324  int ret=0;
325
326#ifdef NO_RTCM3_MAIN
327  if(GetMessage(handle)) /* don't repeat */
328#else
329  while(!ret && GetMessage(handle))
330#endif /* NO_RTCM3_MAIN */
331  {
332    /* using 64 bit integer types, as it is much easier than handling
333    the long datatypes in 32 bit */
334    uint64_t numbits = 0, bitfield = 0;
335    int size = handle->size, type;
336    int syncf, old = 0;
337    unsigned char *data = handle->Message+3;
338
339    GETBITS(type,12)
340#ifdef NO_RTCM3_MAIN
341    handle->blocktype = type;
342#endif /* NO_RTCM3_MAIN */
343    switch(type)
344    {
345#ifdef NO_RTCM3_MAIN
346    default:
347      ret = type;
348      break;
349    case 1005: case 1006:
350      {
351        SKIPBITS(22)
352        GETBITSSIGN(handle->antX, 38)
353        SKIPBITS(2)
354        GETBITSSIGN(handle->antY, 38)
355        SKIPBITS(2)
356        GETBITSSIGN(handle->antZ, 38)
357        if(type == 1006)
358          GETBITS(handle->antH, 16)
359        ret = type;
360      }
361      break;
362    case 1007: case 1008: case 1033:
363      {
364        char *antenna;
365        int antnum;
366
367        SKIPBITS(12)
368        GETSTRING(antnum,antenna)
369        memcpy(handle->antenna, antenna, antnum);
370        handle->antenna[antnum] = 0;
371        ret = type;
372      }
373      break;
374    case 1013:
375      {
376        SKIPBITS(12);
377        GETBITS(handle->modjulday, 16);
378        GETBITS(handle->secofday, 17);
379        SKIPBITS(5);
380        GETBITS(handle->leapsec, 8);
381        ret = 1013;
382      }
383      break;
384#endif /* NO_RTCM3_MAIN */
385    case 1019:
386      {
387        struct gpsephemeris *ge;
388        int sv, i;
389
390        ge = &handle->ephemerisGPS;
391        memset(ge, 0, sizeof(*ge));
392
393        GETBITS(sv, 6)
394        ge->satellite = (sv < 40 ? sv : sv+80);
395        GETBITS(ge->GPSweek, 10)
396        ge->GPSweek += 1024;
397        GETBITS(ge->URAindex, 4)
398        GETBITS(sv, 2)
399        if(sv & 1)
400          ge->flags |= GPSEPHF_L2PCODE;
401        if(sv & 2)
402          ge->flags |= GPSEPHF_L2CACODE;
403        GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
404        GETBITS(ge->IODE, 8)
405        GETBITS(ge->TOC, 16)
406        ge->TOC <<= 4;
407        GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
408        GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
409        GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
410        GETBITS(ge->IODC, 10)
411        GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
412        GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
413        GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
414        GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
415        GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
416        GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
417        GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
418        GETBITS(ge->TOE, 16)
419        ge->TOE <<= 4;
420
421        GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
422        GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
423        GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
424        GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
425        GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
426        GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
427        GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
428        GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
429        GETBITS(ge->SVhealth, 6)
430        GETBITS(sv, 1)
431        if(sv)
432          ge->flags |= GPSEPHF_L2PCODEDATA;
433
434        i = ((int)ge->GPSweek - (int)handle->GPSWeek)*7*24*60*60
435        + ((int)ge->TOE - (int)handle->GPSTOW) - 2*60*60;
436        if(i > 5*60*60 && i < 8*60*60)
437        {
438          handle->GPSTOW = ge->TOE;
439          handle->GPSWeek = ge->GPSweek;
440        }
441        ge->TOW = 0.9999E9;
442        ret = 1019;
443      }
444      break;
445    case 1045:
446      {
447        struct galileoephemeris *ge;
448        int sv;
449
450        ge = &handle->ephemerisGALILEO;
451        memset(ge, 0, sizeof(*ge));
452
453        GETBITS(sv, 6)
454        ge->satellite = sv;
455        GETBITS(ge->Week, 12)
456        GETBITS(ge->IODnav, 10)
457        GETBITS(ge->SISA, 8)
458        GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
459        GETBITSFACTOR(ge->TOC, 14, 60)
460        GETFLOATSIGN(ge->clock_driftrate, 6, 1.0/(double)(1<<30)/(double)(1<<29))
461        GETFLOATSIGN(ge->clock_drift, 21, 1.0/(double)(1<<30)/(double)(1<<16))
462        GETFLOATSIGN(ge->clock_bias, 31, 1.0/(double)(1<<30)/(double)(1<<4))
463        GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
464        GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
465        GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
466        GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
467        GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
468        GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
469        GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
470        GETBITSFACTOR(ge->TOE, 14, 60)
471        GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
472        GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
473        GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
474        GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
475        GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
476        GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
477        GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
478        GETFLOATSIGN(ge->BGD_1_5A, 10, 1.0/(double)(1<<30)/(double)(1<<2))
479        GETFLOATSIGN(ge->BGD_1_5B, 10, 1.0/(double)(1<<30)/(double)(1<<2))
480        GETBITS(ge->E5aHS, 2)
481        GETBITS(sv, 1)
482        if(sv)
483          ge->flags |= GALEPHF_E5ADINVALID;
484        ret = 1045;
485      }
486      break;
487    case 1020:
488      {
489        struct glonassephemeris *ge;
490        int i;
491
492        ge = &handle->ephemerisGLONASS;
493        memset(ge, 0, sizeof(*ge));
494
495        ge->flags |= GLOEPHF_PAVAILABLE;
496        GETBITS(ge->almanac_number, 6)
497        GETBITS(i, 5)
498        ge->frequency_number = i-7;
499        if(ge->almanac_number >= 1 && ge->almanac_number <= PRN_GLONASS_NUM)
500          handle->GLOFreq[ge->almanac_number-1] = 100+ge->frequency_number;
501        GETBITS(i, 1)
502        if(i)
503          ge->flags |= GLOEPHF_ALMANACHEALTHY;
504        GETBITS(i, 1)
505        if(i)
506          ge->flags |= GLOEPHF_ALMANACHEALTHOK;
507        GETBITS(i, 2)
508        if(i & 1)
509          ge->flags |= GLOEPHF_P10TRUE;
510        if(i & 2)
511          ge->flags |= GLOEPHF_P11TRUE;
512        GETBITS(i, 5)
513        ge->tk = i*60*60;
514        GETBITS(i, 6)
515        ge->tk += i*60;
516        GETBITS(i, 1)
517        ge->tk += i*30;
518        GETBITS(i, 1)
519        if(i)
520          ge->flags |= GLOEPHF_UNHEALTHY;
521        GETBITS(i, 1)
522        if(i)
523          ge->flags |= GLOEPHF_P2TRUE;
524        GETBITS(i, 7)
525        ge->tb = i*15*60;
526        GETFLOATSIGNM(ge->x_velocity, 24, 1.0/(double)(1<<20))
527        GETFLOATSIGNM(ge->x_pos, 27, 1.0/(double)(1<<11))
528        GETFLOATSIGNM(ge->x_acceleration, 5, 1.0/(double)(1<<30))
529        GETFLOATSIGNM(ge->y_velocity, 24, 1.0/(double)(1<<20))
530        GETFLOATSIGNM(ge->y_pos, 27, 1.0/(double)(1<<11))
531        GETFLOATSIGNM(ge->y_acceleration, 5, 1.0/(double)(1<<30))
532        GETFLOATSIGNM(ge->z_velocity, 24, 1.0/(double)(1<<20))
533        GETFLOATSIGNM(ge->z_pos, 27, 1.0/(double)(1<<11))
534        GETFLOATSIGNM(ge->z_acceleration, 5, 1.0/(double)(1<<30))
535        GETBITS(i, 1)
536        if(i)
537          ge->flags |= GLOEPHF_P3TRUE;
538        GETFLOATSIGNM(ge->gamma, 11, 1.0/(double)(1<<30)/(double)(1<<10))
539        SKIPBITS(3) /* GLONASS-M P, GLONASS-M ln (third string) */
540        GETFLOATSIGNM(ge->tau, 22, 1.0/(double)(1<<30)) /* GLONASS tau n(tb) */
541        SKIPBITS(5) /* GLONASS-M delta tau n(tb) */
542        GETBITS(ge->E, 5)
543        /* GETBITS(b, 1) / * GLONASS-M P4 */
544        /* GETBITS(b, 4) / * GLONASS-M Ft */
545        /* GETBITS(b, 11) / * GLONASS-M Nt */
546        /* GETBITS(b, 2) / * GLONASS-M M */
547        /* GETBITS(b, 1) / * GLONASS-M The Availability of Additional Data */
548        /* GETBITS(b, 11) / * GLONASS-M Na */
549        /* GETFLOATSIGNM(b, 32, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS tau c */
550        /* GETBITS(b, 5) / * GLONASS-M N4 */
551        /* GETFLOATSIGNM(b, 22, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS-M tau GPS */
552        /* GETBITS(b, 1) / * GLONASS-M ln (fifth string) */
553        ge->GPSWeek = handle->GPSWeek;
554        ge->GPSTOW = handle->GPSTOW;
555        ret = 1020;
556      }
557      break;
558    case 1001: case 1002: case 1003: case 1004:
559      if(handle->GPSWeek)
560      {
561        int lastlockl1[64];
562        int lastlockl2[64];
563        struct gnssdata *gnss;
564        int i, numsats, wasamb=0;
565
566        for(i = 0; i < 64; ++i)
567          lastlockl1[i] = lastlockl2[i] = 0;
568
569        gnss = &handle->DataNew;
570
571        SKIPBITS(12) /* id */
572        GETBITS(i,30)
573        if(i/1000 < (int)handle->GPSTOW - 86400)
574          ++handle->GPSWeek;
575        handle->GPSTOW = i/1000;
576        if(gnss->week && (gnss->timeofweek != i || gnss->week
577        != handle->GPSWeek))
578        {
579          handle->Data = *gnss;
580          memset(gnss, 0, sizeof(*gnss));
581          old = 1;
582        }
583        gnss->timeofweek = i;
584        gnss->week = handle->GPSWeek;
585
586        GETBITS(syncf,1) /* sync */
587        GETBITS(numsats,5)
588        SKIPBITS(4) /* smind, smint */
589
590        while(numsats-- && gnss->numsats < GNSS_MAXSATS)
591        {
592          int sv, code, l1range, c,l,s,ce,le,se,amb=0;
593          int fullsat, num;
594
595          GETBITS(sv, 6)
596          fullsat = sv < 40 ? sv : sv+80;
597          for(num = 0; num < gnss->numsats
598          && fullsat != gnss->satellites[num]; ++num)
599            ;
600
601          if(num == gnss->numsats)
602            gnss->satellites[gnss->numsats++] = fullsat;
603
604          /* L1 */
605          GETBITS(code, 1);
606          if(code)
607          {
608            c = GNSSDF_P1DATA;  ce = GNSSENTRY_P1DATA;
609            l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
610            s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
611          }
612          else
613          {
614            c = GNSSDF_C1DATA;  ce = GNSSENTRY_C1DATA;
615            l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
616            s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
617          }
618          GETBITS(l1range, 24);
619          GETBITSSIGN(i, 20);
620          if((i&((1<<20)-1)) != 0x80000)
621          {
622            gnss->dataflags[num] |= (c|l);
623            gnss->measdata[num][ce] = l1range*0.02;
624            gnss->measdata[num][le] = l1range*0.02+i*0.0005;
625          }
626          GETBITS(i, 7);
627          lastlockl1[sv] = i;
628          if(handle->lastlockGPSl1[sv] > i || i == 0)
629            gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
630          if(type == 1002 || type == 1004)
631          {
632            GETBITS(amb,8);
633            if(amb && (gnss->dataflags[num] & c))
634            {
635              gnss->measdata[num][ce] += amb*299792.458;
636              gnss->measdata[num][le] += amb*299792.458;
637              ++wasamb;
638            }
639            GETBITS(i, 8);
640            if(i)
641            {
642              gnss->dataflags[num] |= s;
643              gnss->measdata[num][se] = i*0.25;
644              i /= 4*4;
645              if(i > 9) i = 9;
646              else if(i < 1) i = 1;
647              gnss->snrL1[num] = i;
648            }
649          }
650          gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
651          if(type == 1003 || type == 1004)
652          {
653            /* L2 */
654            GETBITS(code,2);
655            if(code)
656            {
657              c = GNSSDF_P2DATA;  ce = GNSSENTRY_P2DATA;
658              l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
659              s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
660              if(code >= 2)
661                gnss->dataflags2[num] |= GNSSDF2_XCORRL2;
662            }
663            else
664            {
665              c = GNSSDF_C2DATA;  ce = GNSSENTRY_C2DATA;
666              l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
667              s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
668            }
669            GETBITSSIGN(i,14);
670            if((i&((1<<14)-1)) != 0x2000)
671            {
672              gnss->dataflags[num] |= c;
673              gnss->measdata[num][ce] = l1range*0.02+i*0.02
674              +amb*299792.458;
675            }
676            GETBITSSIGN(i,20);
677            if((i&((1<<20)-1)) != 0x80000)
678            {
679              gnss->dataflags[num] |= l;
680              gnss->measdata[num][le] = l1range*0.02+i*0.0005
681              +amb*299792.458;
682            }
683            GETBITS(i,7);
684            lastlockl2[sv] = i;
685            if(handle->lastlockGPSl2[sv] > i || i == 0)
686              gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
687            if(type == 1004)
688            {
689              GETBITS(i, 8);
690              if(i)
691              {
692                gnss->dataflags[num] |= s;
693                gnss->measdata[num][se] = i*0.25;
694                i /= 4*4;
695                if(i > 9) i = 9;
696                else if(i < 1) i = 1;
697                gnss->snrL2[num] = i;
698              }
699            }
700            gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
701          }
702        }
703        for(i = 0; i < 64; ++i)
704        {
705          handle->lastlockGPSl1[i] = lastlockl1[i];
706          handle->lastlockGPSl2[i] = lastlockl2[i];
707        }
708        if(!syncf && !old)
709        {
710          handle->Data = *gnss;
711          memset(gnss, 0, sizeof(*gnss));
712        }
713        if(!syncf || old)
714        {
715          if(wasamb) /* not RINEX compatible without */
716            ret = 1;
717          else
718            ret = 2;
719        }
720#ifdef NO_RTCM3_MAIN
721        else
722          ret = type;
723#endif /* NO_RTCM3_MAIN */
724      }
725      break;
726    case 1009: case 1010: case 1011: case 1012:
727      {
728        int lastlockl1[64];
729        int lastlockl2[64];
730        struct gnssdata *gnss;
731        int i, numsats;
732        int wasamb=0;
733
734        for(i = 0; i < 64; ++i)
735          lastlockl1[i] = lastlockl2[i] = 0;
736
737        gnss = &handle->DataNew;
738
739        SKIPBITS(12) /* id */;
740        GETBITS(i,27) /* tk */
741
742        updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
743        i = handle->GPSTOW*1000;
744        if(gnss->week && (gnss->timeofweek != i || gnss->week
745        != handle->GPSWeek))
746        {
747          handle->Data = *gnss;
748          memset(gnss, 0, sizeof(*gnss));
749          old = 1;
750        }
751
752        gnss->timeofweek = i;
753        gnss->week = handle->GPSWeek;
754
755        GETBITS(syncf,1) /* sync */
756        GETBITS(numsats,5)
757
758        SKIPBITS(4) /* smind, smint */
759
760        while(numsats-- && gnss->numsats < GNSS_MAXSATS)
761        {
762          int sv, code, l1range, c,l,s,ce,le,se,amb=0;
763          int freq;
764          int fullsat, num;
765
766          GETBITS(sv, 6)
767          fullsat = sv-1 + PRN_GLONASS_START;
768          for(num = 0; num < gnss->numsats
769          && fullsat != gnss->satellites[num]; ++num)
770            ;
771
772          if(num == gnss->numsats)
773            gnss->satellites[gnss->numsats++] = fullsat;
774
775          /* L1 */
776          GETBITS(code, 1)
777          GETBITS(freq, 5)
778
779          if(sv >= 1 && sv <= PRN_GLONASS_NUM)
780            handle->GLOFreq[sv-1] = 100+freq-7;
781
782          if(code)
783          {
784            c = GNSSDF_P1DATA;  ce = GNSSENTRY_P1DATA;
785            l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
786            s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
787          }
788          else
789          {
790            c = GNSSDF_C1DATA;  ce = GNSSENTRY_C1DATA;
791            l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
792            s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
793          }
794          GETBITS(l1range, 25)
795          GETBITSSIGN(i, 20)
796          if((i&((1<<20)-1)) != 0x80000)
797          {
798            /* Handle this like GPS. Actually for GLONASS L1 range is always
799               valid. To be on the save side, we handle it as invalid like we
800               do for GPS and also remove range in case of 0x80000. */
801            gnss->dataflags[num] |= (c|l);
802            gnss->measdata[num][ce] = l1range*0.02;
803            gnss->measdata[num][le] = l1range*0.02+i*0.0005;
804          }
805          GETBITS(i, 7)
806          lastlockl1[sv] = i;
807          if(handle->lastlockGLOl1[sv] > i || i == 0)
808            gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
809          if(type == 1010 || type == 1012)
810          {
811            GETBITS(amb,7)
812            if(amb && (gnss->dataflags[num] & c))
813            {
814              gnss->measdata[num][ce] += amb*599584.916;
815              gnss->measdata[num][le] += amb*599584.916;
816              ++wasamb;
817            }
818            GETBITS(i, 8)
819            if(i)
820            {
821              gnss->dataflags[num] |= s;
822              gnss->measdata[num][se] = i*0.25;
823              i /= 4*4;
824              if(i > 9) i = 9;
825              else if(i < 1) i = 1;
826              gnss->snrL1[num] = i;
827            }
828          }
829          gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
830          if(type == 1011 || type == 1012)
831          {
832            /* L2 */
833            GETBITS(code,2)
834            if(code)
835            {
836              c = GNSSDF_P2DATA;  ce = GNSSENTRY_P2DATA;
837              l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
838              s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
839            }
840            else
841            {
842              c = GNSSDF_C2DATA;  ce = GNSSENTRY_C2DATA;
843              l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
844              s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
845            }
846            GETBITSSIGN(i,14)
847            if((i&((1<<14)-1)) != 0x2000)
848            {
849              gnss->dataflags[num] |= c;
850              gnss->measdata[num][ce] = l1range*0.02+i*0.02
851              +amb*599584.916;
852            }
853            GETBITSSIGN(i,20)
854            if((i&((1<<20)-1)) != 0x80000)
855            {
856              gnss->dataflags[num] |= l;
857              gnss->measdata[num][le] = l1range*0.02+i*0.0005
858              +amb*599584.916;
859            }
860            GETBITS(i,7)
861            lastlockl2[sv] = i;
862            if(handle->lastlockGLOl2[sv] > i || i == 0)
863              gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
864            if(type == 1012)
865            {
866              GETBITS(i, 8)
867              if(i)
868              {
869                gnss->dataflags[num] |= s;
870                gnss->measdata[num][se] = i*0.25;
871                i /= 4*4;
872                if(i > 9) i = 9;
873                else if(i < 1) i = 1;
874                gnss->snrL2[num] = i;
875              }
876            }
877            gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
878          }
879          if(!sv || sv > 24) /* illegal, remove it again */
880            --gnss->numsats;
881        }
882        for(i = 0; i < 64; ++i)
883        {
884          handle->lastlockGLOl1[i] = lastlockl1[i];
885          handle->lastlockGLOl2[i] = lastlockl2[i];
886        }
887        if(!syncf && !old)
888        {
889          handle->Data = *gnss;
890          memset(gnss, 0, sizeof(*gnss));
891        }
892        if(!syncf || old)
893        {
894          if(wasamb) /* not RINEX compatible without */
895            ret = 1;
896          else
897            ret = 2;
898        }
899#ifdef NO_RTCM3_MAIN
900        else
901          ret = type;
902#endif /* NO_RTCM3_MAIN */
903      }
904      break;
905    case 1071: case 1081: case 1091:
906    case 1072: case 1082: case 1092:
907    case 1073: case 1083: case 1093:
908    case 1074: case 1084: case 1094:
909    case 1075: case 1085: case 1095:
910    case 1076: case 1086: case 1096:
911    case 1077: case 1087: case 1097:
912      if(handle->GPSWeek)
913      {
914        struct CodeData {
915          int typeR;
916          int typeP;
917          int typeD;
918          int typeS;
919          int lock;
920          double wl;
921          const char *code; /* currently unused */
922        };
923        struct CodeData gps[RTCM3_MSM_NUMSIG] =
924        {
925          {0,0,0,0,0,0,0},
926          {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
927          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1C"},
928          {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
929          GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1P"},
930          {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
931          GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1W"},
932          {0,0,0,0,0,0,0}/*{GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
933          GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1Y"}*/,
934          {0,0,0,0,0,0,0},
935          {0,0,0,0,0,0,0},
936          {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
937          GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2C"},
938          {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
939          GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2P"},
940          {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
941          GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2W"},
942          {0,0,0,0,0,0,0}/*{GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
943          GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2Y"}*/,
944          {0,0,0,0,0,0,0},
945          {0,0,0,0,0,0,0},
946          {0,0,0,0,0,0,0},
947          {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
948          GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2S"},
949          {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
950          GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2L"},
951          {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
952          GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2X"},
953          {0,0,0,0,0,0,0},
954          {0,0,0,0,0,0,0},
955          {0,0,0,0,0,0,0},
956          {0,0,0,0,0,0,0},
957          {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
958          GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5I"},
959          {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
960          GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5Q"},
961          {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
962          GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5X"},
963          {0,0,0,0,0,0,0},
964          {0,0,0,0,0,0,0},
965          {0,0,0,0,0,0,0},
966          {0,0,0,0,0,0,0},
967          {0,0,0,0,0,0,0},
968          {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
969          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1S"},
970          {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
971          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1L"},
972          {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
973          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1X"}
974        };
975        /* NOTE: Uses 0.0, 1.0 for wavelength as sat index dependence is done later! */
976        struct CodeData glo[RTCM3_MSM_NUMSIG] =
977        {
978          {0,0,0,0,0,0,0},
979          {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
980          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1C"},
981          {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
982          GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,0.0,"1P"},
983          {0,0,0,0,0,0,0},
984          {0,0,0,0,0,0,0},
985          {0,0,0,0,0,0,0},
986          {0,0,0,0,0,0,0},
987          {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
988          GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,1.0,"2C"},
989          {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
990          GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,1.0,"2P"},
991          {0,0,0,0,0,0,0},
992          {0,0,0,0,0,0,0},
993          {0,0,0,0,0,0,0},
994          {0,0,0,0,0,0,0},
995          {0,0,0,0,0,0,0},
996          {0,0,0,0,0,0,0},
997          {0,0,0,0,0,0,0},
998          {0,0,0,0,0,0,0},
999          {0,0,0,0,0,0,0},
1000          {0,0,0,0,0,0,0},
1001          {0,0,0,0,0,0,0},
1002          {0,0,0,0,0,0,0},
1003          {0,0,0,0,0,0,0},
1004          {0,0,0,0,0,0,0},
1005          {0,0,0,0,0,0,0},
1006          {0,0,0,0,0,0,0},
1007          {0,0,0,0,0,0,0},
1008          {0,0,0,0,0,0,0},
1009          {0,0,0,0,0,0,0},
1010          {0,0,0,0,0,0,0},
1011          {0,0,0,0,0,0,0},
1012          {0,0,0,0,0,0,0},
1013          {0,0,0,0,0,0,0}
1014        };
1015        struct CodeData gal[RTCM3_MSM_NUMSIG] =
1016        {
1017          {0,0,0,0,0,0,0},
1018          {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1019          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1C"},
1020          {0,0,0,0,0,0,0}/*{GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1021          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1A"}*/,
1022          {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1023          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1B"},
1024          {0,0,0,0,0,0,0}/*{GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1025          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1X"}*/,
1026          {0,0,0,0,0,0,0}/*{GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1027          GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1Z"}*/,
1028          {0,0,0,0,0,0,0},
1029          {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1030          GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6C"},
1031          {0,0,0,0,0,0,0}/*{GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1032          GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6A"}*/,
1033          {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1034          GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6B"},
1035          {0,0,0,0,0,0,0}/*{GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1036          GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6X"}*/,
1037          {0,0,0,0,0,0,0}/*{GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1038          GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6Z"}*/,
1039          {0,0,0,0,0,0,0},
1040          {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1041          GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7I"},
1042          {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1043          GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7Q"},
1044          {0,0,0,0,0,0,0}/*{GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1045          GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7X"}*/,
1046          {0,0,0,0,0,0,0},
1047          {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1048          GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8I"},
1049          {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1050          GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8Q"},
1051          {0,0,0,0,0,0,0}/*{GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1052          GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8X"}*/,
1053          {0,0,0,0,0,0,0},
1054          {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1055          GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5I"},
1056          {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1057          GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5Q"},
1058          {0,0,0,0,0,0,0}/*{GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1059          GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5X"}*/,
1060          {0,0,0,0,0,0,0},
1061          {0,0,0,0,0,0,0},
1062          {0,0,0,0,0,0,0},
1063          {0,0,0,0,0,0,0},
1064          {0,0,0,0,0,0,0},
1065          {0,0,0,0,0,0,0},
1066          {0,0,0,0,0,0,0},
1067          {0,0,0,0,0,0,0},
1068        };
1069
1070        int sys = RTCM3_MSM_GPS, i=0, count, j, old = 0, wasnoamb = 0;
1071        int syncf, sigmask, numsat = 0, numsig = 0, numcells;
1072        uint64_t satmask, cellmask, ui;
1073        double rrmod[RTCM3_MSM_NUMSAT];
1074        int rrint[RTCM3_MSM_NUMSAT], rdop[RTCM3_MSM_NUMSAT],
1075        extsat[RTCM3_MSM_NUMSAT];
1076        int ll[RTCM3_MSM_NUMCELLS];
1077        double cnr[RTCM3_MSM_NUMCELLS];
1078        double cp[RTCM3_MSM_NUMCELLS], psr[RTCM3_MSM_NUMCELLS],
1079        dop[RTCM3_MSM_NUMCELLS];
1080        struct gnssdata *gnss = &handle->DataNew;
1081
1082        SKIPBITS(12)
1083        if(type >= 1091)
1084          sys = RTCM3_MSM_GALILEO;
1085        else if(type >= 1081)
1086          sys = RTCM3_MSM_GLONASS;
1087
1088        switch(sys)
1089        {
1090        case RTCM3_MSM_GALILEO: /* use DF004 instead of DF248 */
1091        case RTCM3_MSM_GPS:
1092          GETBITS(i,30)
1093          if(i/1000 < (int)handle->GPSTOW - 86400)
1094            ++handle->GPSWeek;
1095          handle->GPSTOW = i/1000;
1096          break;
1097        case RTCM3_MSM_GLONASS:
1098          SKIPBITS(3)
1099          GETBITS(i,27) /* tk */
1100
1101          updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
1102          i = handle->GPSTOW*1000;
1103          break;
1104        }
1105
1106        if(gnss->week && (gnss->timeofweek != i || gnss->week
1107        != handle->GPSWeek))
1108        {
1109          handle->Data = *gnss;
1110          memset(gnss, 0, sizeof(*gnss));
1111          old = 1;
1112        }
1113        gnss->timeofweek = i;
1114        gnss->week = handle->GPSWeek;
1115
1116        GETBITS(syncf, 1)
1117        SKIPBITS(3+7+2+2+1+3)
1118        GETBITS64(satmask, RTCM3_MSM_NUMSAT)
1119
1120        /* http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/ */
1121        for(ui = satmask; ui; ui &= (ui - 1) /* remove rightmost bit */)
1122          ++numsat;
1123        GETBITS(sigmask, RTCM3_MSM_NUMSIG)
1124        for(i = sigmask; i; i &= (i - 1) /* remove rightmost bit */)
1125          ++numsig;
1126        i = numsat*numsig;
1127        GETBITS64(cellmask, (unsigned)i)
1128
1129        switch(type % 10)
1130        {
1131        case 1: case 2: case 3:
1132          ++wasnoamb;
1133          for(j = numsat; j--;)
1134            GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1135          break;
1136        case 4: case 6:
1137          for(j = numsat; j--;)
1138            GETBITS(rrint[j], 8)
1139          for(j = numsat; j--;)
1140            GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1141          break;
1142        case 5: case 7:
1143          for(j = numsat; j--;)
1144            GETBITS(rrint[j], 8)
1145          for(j = numsat; j--;)
1146            GETBITS(extsat[j], 4)
1147          for(j = numsat; j--;)
1148            GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1149          for(j = numsat; j--;)
1150            GETBITSSIGN(rdop[j], 14)
1151          break;
1152        }
1153
1154        numcells = numsat*numsig;
1155        if(numcells <= RTCM3_MSM_NUMCELLS)
1156        {
1157          switch(type % 10)
1158          {
1159          case 1:
1160            for(count = numcells; count--;)
1161              if(cellmask & (UINT64(1)<<count))
1162                GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1163            break;
1164          case 2:
1165            for(count = numcells; count--;)
1166              if(cellmask & (UINT64(1)<<count))
1167                GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1168            for(count = numcells; count--;)
1169              if(cellmask & (UINT64(1)<<count))
1170                GETBITS(ll[count], 4)
1171            break;
1172          case 3:
1173            for(count = numcells; count--;)
1174              if(cellmask & (UINT64(1)<<count))
1175                GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1176            for(count = numcells; count--;)
1177              if(cellmask & (UINT64(1)<<count))
1178                GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1179            for(count = numcells; count--;)
1180              if(cellmask & (UINT64(1)<<count))
1181                GETBITS(ll[count], 4)
1182            break;
1183          case 4:
1184            for(count = numcells; count--;)
1185              if(cellmask & (UINT64(1)<<count))
1186                GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1187            for(count = numcells; count--;)
1188              if(cellmask & (UINT64(1)<<count))
1189                GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1190            for(count = numcells; count--;)
1191              if(cellmask & (UINT64(1)<<count))
1192                GETBITS(ll[count], 4)
1193            for(count = numcells; count--;)
1194              if(cellmask & (UINT64(1)<<count))
1195                GETBITS(cnr[count], 6)
1196            break;
1197          case 5:
1198            for(count = numcells; count--;)
1199              if(cellmask & (UINT64(1)<<count))
1200                GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1201            for(count = numcells; count--;)
1202              if(cellmask & (UINT64(1)<<count))
1203                GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1204            for(count = numcells; count--;)
1205              if(cellmask & (UINT64(1)<<count))
1206                GETBITS(ll[count], 4)
1207            for(count = numcells; count--;)
1208              if(cellmask & (UINT64(1)<<count))
1209                GETFLOAT(cnr[count], 6, 1.0)
1210            for(count = numcells; count--;)
1211              if(cellmask & (UINT64(1)<<count))
1212                GETFLOATSIGN(dop[count], 15, 0.0001)
1213            break;
1214          case 6:
1215            for(count = numcells; count--;)
1216              if(cellmask & (UINT64(1)<<count))
1217                GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1218            for(count = numcells; count--;)
1219              if(cellmask & (UINT64(1)<<count))
1220                GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1221            for(count = numcells; count--;)
1222              if(cellmask & (UINT64(1)<<count))
1223                GETBITS(ll[count], 10)
1224            for(count = numcells; count--;)
1225              if(cellmask & (UINT64(1)<<count))
1226                GETFLOAT(cnr[count], 10, 0.1)
1227            break;
1228          case 7:
1229            for(count = numcells; count--;)
1230              if(cellmask & (UINT64(1)<<count))
1231                GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1232            for(count = numcells; count--;)
1233              if(cellmask & (UINT64(1)<<count))
1234                GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1235            for(count = numcells; count--;)
1236              if(cellmask & (UINT64(1)<<count))
1237                GETBITS(ll[count], 10)
1238            for(count = numcells; count--;)
1239              if(cellmask & (UINT64(1)<<count))
1240                GETFLOAT(cnr[count], 10, 0.1)
1241            for(count = numcells; count--;)
1242              if(cellmask & (UINT64(1)<<count))
1243                GETFLOATSIGN(dop[count], 15, 0.0001)
1244            break;
1245          }
1246          i = RTCM3_MSM_NUMSAT;
1247          j = -1;
1248          for(count = numcells; count--;)
1249          {
1250            while(j >= 0 && !(sigmask&(1<<--j)))
1251              ;
1252            if(j < 0)
1253            {
1254              while(!(satmask&(UINT64(1)<<(--i)))) /* next satellite */
1255                ;
1256              j = RTCM3_MSM_NUMSIG;
1257              while(!(sigmask&(1<<--j)))
1258                ;
1259              --numsat;
1260            }
1261            if(cellmask & (UINT64(1)<<count))
1262            {
1263              struct CodeData cd = {0,0,0,0,0,0,0};
1264              double wl = 0.0;
1265              switch(sys)
1266              {
1267              case RTCM3_MSM_GPS: cd = gps[RTCM3_MSM_NUMSIG-j-1];
1268                wl = cd.wl;
1269                break;
1270              case RTCM3_MSM_GLONASS: cd = glo[RTCM3_MSM_NUMSIG-j-1];
1271                {
1272                  int k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1];
1273                  if(k)
1274                  {
1275                    if(cd.wl == 0.0)
1276                      wl = GLO_WAVELENGTH_L1(k-100);
1277                    else if(cd.wl == 1.0)
1278                      wl = GLO_WAVELENGTH_L2(k-100);
1279                  }
1280                }
1281                break;
1282              case RTCM3_MSM_GALILEO: cd = gal[RTCM3_MSM_NUMSIG-j-1];
1283                wl = cd.wl;
1284                break;
1285              }
1286              if(cd.lock && wl) /* lock cannot have a valid zero value */
1287              {
1288                int fullsat = RTCM3_MSM_NUMSAT-i-1, num;
1289
1290                if(sys == RTCM3_MSM_GALILEO && fullsat >= 50 && fullsat <= 51)
1291                  fullsat += PRN_GIOVE_START-50;
1292                else
1293                  fullsat += sys;
1294
1295                for(num = 0; num < gnss->numsats
1296                && fullsat != gnss->satellites[num]; ++num)
1297                  ;
1298
1299                if(num == gnss->numsats)
1300                  gnss->satellites[gnss->numsats++] = fullsat;
1301
1302                switch(type % 10)
1303                {
1304                case 1:
1305                  if(psr[count] > -1.0/(1<<10))
1306                  {
1307                    gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1308                    +(rrmod[numsat])*LIGHTSPEED/1000.0;
1309                    gnss->dataflags[num] |= (1<<cd.typeR);
1310                  }
1311                  break;
1312                case 2:
1313                  if(wl && cp[count] > -1.0/(1<<8))
1314                  {
1315                    gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1316                    +(rrmod[numsat])*LIGHTSPEED/1000.0/wl;
1317                    if(handle->lastlockmsm[j][i] != ll[count])
1318                    {
1319                      gnss->dataflags2[num] |= cd.lock;
1320                      handle->lastlockmsm[j][i] = ll[count];
1321                    }
1322                    gnss->dataflags[num] |= (1<<cd.typeP);
1323                  }
1324                  break;
1325                case 3:
1326                  if(psr[count] > -1.0/(1<<10))
1327                  {
1328                    gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1329                    +(rrmod[numsat])*LIGHTSPEED/1000.0;
1330                    gnss->dataflags[num] |= (1<<cd.typeR);
1331                  }
1332
1333                  if(wl && cp[count] > -1.0/(1<<8))
1334                  {
1335                    gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1336                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1337                    if(handle->lastlockmsm[j][i] != ll[count])
1338                    {
1339                      gnss->dataflags2[num] |= cd.lock;
1340                      handle->lastlockmsm[j][i] = ll[count];
1341                    }
1342                    gnss->dataflags[num] |= (1<<cd.typeP);
1343                  }
1344                  break;
1345                case 4:
1346                  if(psr[count] > -1.0/(1<<10))
1347                  {
1348                    gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1349                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1350                    gnss->dataflags[num] |= (1<<cd.typeR);
1351                  }
1352
1353                  if(wl && cp[count] > -1.0/(1<<8))
1354                  {
1355                    gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1356                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1357                    if(handle->lastlockmsm[j][i] != ll[count])
1358                    {
1359                      gnss->dataflags2[num] |= cd.lock;
1360                      handle->lastlockmsm[j][i] = ll[count];
1361                    }
1362                    gnss->dataflags[num] |= (1<<cd.typeP);
1363                  }
1364
1365                  gnss->measdata[num][cd.typeS] = cnr[count];
1366                    gnss->dataflags[num] |= (1<<cd.typeS);
1367                  break;
1368                case 5:
1369                  if(psr[count] > -1.0/(1<<10))
1370                  {
1371                    gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1372                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1373                    gnss->dataflags[num] |= (1<<cd.typeR);
1374                  }
1375
1376                  if(wl && cp[count] > -1.0/(1<<8))
1377                  {
1378                    gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1379                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1380                    if(handle->lastlockmsm[j][i] != ll[count])
1381                    {
1382                      gnss->dataflags2[num] |= cd.lock;
1383                      handle->lastlockmsm[j][i] = ll[count];
1384                    }
1385                    gnss->dataflags[num] |= (1<<cd.typeP);
1386                  }
1387
1388                  gnss->measdata[num][cd.typeS] = cnr[count];
1389                    gnss->dataflags[num] |= (1<<cd.typeS);
1390
1391                  if(dop[count] > -1.6384)
1392                  {
1393                    gnss->measdata[num][cd.typeD] = -(dop[count]
1394                    +rdop[numsat])/wl;
1395                    gnss->dataflags[num] |= (1<<cd.typeD);
1396                  }
1397                  break;
1398                case 6:
1399                  if(psr[count] > -1.0/(1<<10))
1400                  {
1401                    gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1402                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1403                    gnss->dataflags[num] |= (1<<cd.typeR);
1404                  }
1405
1406                  if(wl && cp[count] > -1.0/(1<<8))
1407                  {
1408                    gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1409                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1410                    if(handle->lastlockmsm[j][i] != ll[count])
1411                    {
1412                      gnss->dataflags2[num] |= cd.lock;
1413                      handle->lastlockmsm[j][i] = ll[count];
1414                    }
1415                    gnss->dataflags[num] |= (1<<cd.typeP);
1416                  }
1417
1418                  gnss->measdata[num][cd.typeS] = cnr[count];
1419                    gnss->dataflags[num] |= (1<<cd.typeS);
1420                  break;
1421                case 7:
1422                  if(psr[count] > -1.0/(1<<10))
1423                  {
1424                    gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1425                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1426                    gnss->dataflags[num] |= (1<<cd.typeR);
1427                  }
1428
1429                  if(wl && cp[count] > -1.0/(1<<8))
1430                  {
1431                    gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0
1432                    +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1433                    if(handle->lastlockmsm[j][i] != ll[count])
1434                    {
1435                      gnss->dataflags2[num] |= cd.lock;
1436                      handle->lastlockmsm[j][i] = ll[count];
1437                    }
1438                    gnss->dataflags[num] |= (1<<cd.typeP);
1439                  }
1440
1441                  gnss->measdata[num][cd.typeS] = cnr[count];
1442                    gnss->dataflags[num] |= (1<<cd.typeS);
1443
1444                  if(dop[count] > -1.6384)
1445                  {
1446                    gnss->measdata[num][cd.typeD] = -(dop[count]
1447                    +rdop[numsat])/wl;
1448                    gnss->dataflags[num] |= (1<<cd.typeD);
1449                  }
1450                  break;
1451                }
1452              }
1453            }
1454          }
1455        }
1456        if(!syncf && !old)
1457        {
1458          handle->Data = *gnss;
1459          memset(gnss, 0, sizeof(*gnss));
1460        }
1461        if(!syncf || old)
1462        {
1463          if(!wasnoamb) /* not RINEX compatible without */
1464            ret = 1;
1465          else
1466            ret = 2;
1467        }
1468#ifdef NO_RTCM3_MAIN
1469        else
1470          ret = type;
1471#endif /* NO_RTCM3_MAIN */
1472      }
1473      break;
1474    }
1475  }
1476  return ret;
1477}
1478
1479struct Header
1480{
1481  const char *version;
1482  const char *pgm;
1483  const char *marker;
1484  const char *markertype;
1485  const char *observer;
1486  const char *receiver;
1487  const char *antenna;
1488  const char *position;
1489  const char *antennaposition;
1490  const char *wavelength;
1491  const char *typesofobs; /* should not be modified outside */
1492  const char *typesofobsG; /* should not be modified outside */
1493  const char *typesofobsR; /* should not be modified outside */
1494  const char *typesofobsS; /* should not be modified outside */
1495  const char *typesofobsE; /* should not be modified outside */
1496  const char *timeoffirstobs; /* should not be modified outside */
1497};
1498
1499#define MAXHEADERLINES 50
1500#define MAXHEADERBUFFERSIZE 4096
1501struct HeaderData
1502{
1503  union
1504  {
1505    struct Header named;
1506    const char *unnamed[MAXHEADERLINES];
1507  } data;
1508  int  numheaders;
1509};
1510
1511void converttime(struct converttimeinfo *c, int week, int tow)
1512{
1513  int i, k, doy, j; /* temporary variables */
1514  j = week*(7*24*60*60) + tow + 5*24*60*60;
1515  for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
1516    j -= k;
1517  c->year = i;
1518  doy = 1+ (j / (24*60*60));
1519  j %= (24*60*60);
1520  c->hour = j / (60*60);
1521  j %= (60*60);
1522  c->minute = j / 60;
1523  c->second = j % 60;
1524  j = 0;
1525  for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
1526    j += k;
1527  c->month = i;
1528  c->day = doy - j;
1529}
1530
1531#ifndef NO_RTCM3_MAIN
1532void RTCM3Error(const char *fmt, ...)
1533{
1534  va_list v;
1535  va_start(v, fmt);
1536  vfprintf(stderr, fmt, v);
1537  va_end(v);
1538}
1539#endif
1540
1541void RTCM3Text(const char *fmt, ...)
1542{
1543  va_list v;
1544  va_start(v, fmt);
1545  vprintf(fmt, v);
1546  va_end(v);
1547}
1548
1549static void fixrevision(void)
1550{
1551  if(revisionstr[0] == '$')
1552  {
1553    char *a;
1554    int i=sizeof(RTCM3TORINEX_VERSION); /* set version to 1.<revision> */
1555    strcpy(revisionstr, RTCM3TORINEX_VERSION ".");
1556    for(a = revisionstr+11; *a && *a != ' '; ++a)
1557      revisionstr[i++] = *a;
1558    revisionstr[i] = 0;
1559  }
1560}
1561
1562static int HandleRunBy(char *buffer, int buffersize, const char **u,
1563int rinex3)
1564{
1565  const char *user;
1566  time_t t;
1567  struct tm * t2;
1568
1569#ifdef NO_RTCM3_MAIN
1570  fixrevision();
1571#endif
1572
1573  user= getenv("USER");
1574  if(!user) user = "";
1575  t = time(&t);
1576  t2 = gmtime(&t);
1577  if(u) *u = user;
1578  return 1+snprintf(buffer, buffersize,
1579  rinex3 ?
1580  "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
1581  "PGM / RUN BY / DATE" :
1582  "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d    "
1583  "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1584  t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
1585}
1586
1587#ifdef NO_RTCM3_MAIN
1588#define NUMSTARTSKIP 1
1589#else
1590#define NUMSTARTSKIP 3
1591#endif
1592
1593void HandleHeader(struct RTCM3ParserData *Parser)
1594{
1595#ifdef NO_RTCM3_MAIN
1596  int i;
1597  if(Parser->allflags == 0)
1598    Parser->allflags = ~0;
1599  if(Parser->rinex3)
1600  {
1601#define CHECKFLAGSNEW(a, b, c) \
1602    if(Parser->allflags & GNSSDF_##b##DATA) \
1603    { \
1604      Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1605      Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1606      ++Parser->numdatatypes##a; \
1607    }
1608
1609    CHECKFLAGSNEW(GPS, C1,  C1C)
1610    CHECKFLAGSNEW(GPS, L1C, L1C)
1611    CHECKFLAGSNEW(GPS, D1C, D1C)
1612    CHECKFLAGSNEW(GPS, S1C, S1C)
1613    CHECKFLAGSNEW(GPS, P1,  C1P)
1614    CHECKFLAGSNEW(GPS, L1P, L1P)
1615    CHECKFLAGSNEW(GPS, D1P, D1P)
1616    CHECKFLAGSNEW(GPS, S1P, S1P)
1617    CHECKFLAGSNEW(GPS, P2,  C2P)
1618    CHECKFLAGSNEW(GPS, L2P, L2P)
1619    CHECKFLAGSNEW(GPS, D2P, D2P)
1620    CHECKFLAGSNEW(GPS, S2P, S2P)
1621    CHECKFLAGSNEW(GPS, C2,  C2X)
1622    CHECKFLAGSNEW(GPS, L2C, L2X)
1623    CHECKFLAGSNEW(GPS, D2C, D2X)
1624    CHECKFLAGSNEW(GPS, S2C, S2X)
1625    CHECKFLAGSNEW(GLO, C1,  C1C)
1626    CHECKFLAGSNEW(GLO, L1C, L1C)
1627    CHECKFLAGSNEW(GLO, D1C, D1C)
1628    CHECKFLAGSNEW(GLO, S1C, S1C)
1629    CHECKFLAGSNEW(GLO, P1,  C1P)
1630    CHECKFLAGSNEW(GLO, L1P, L1P)
1631    CHECKFLAGSNEW(GLO, D1P, D1P)
1632    CHECKFLAGSNEW(GLO, S1P, S1P)
1633    CHECKFLAGSNEW(GLO, P2,  C2P)
1634    CHECKFLAGSNEW(GLO, L2P, L2P)
1635    CHECKFLAGSNEW(GLO, D2P, D2P)
1636    CHECKFLAGSNEW(GLO, S2P, S2P)
1637    CHECKFLAGSNEW(GLO, C2,  C2C)
1638    CHECKFLAGSNEW(GLO, L2C, L2C)
1639    CHECKFLAGSNEW(GLO, D2C, D2C)
1640    CHECKFLAGSNEW(GLO, S2C, S2C)
1641  }
1642  else
1643  {
1644#define CHECKFLAGS(a, b) \
1645    if(Parser->allflags & GNSSDF_##a##DATA) \
1646    { \
1647      if(data[RINEXENTRY_##b##DATA]) \
1648      { \
1649        Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1650        Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1651      } \
1652      else \
1653      { \
1654        Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1655        Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1656        data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1657      } \
1658    }
1659
1660    int data[RINEXENTRY_NUMBER];
1661    for(i = 0; i < RINEXENTRY_NUMBER; ++i) data[i] = 0;
1662
1663    CHECKFLAGS(C1,C1)
1664    CHECKFLAGS(C2,C2)
1665    CHECKFLAGS(P1,P1)
1666    CHECKFLAGS(P2,P2)
1667    CHECKFLAGS(L1C,L1)
1668    CHECKFLAGS(L1P,L1)
1669    CHECKFLAGS(L2C,L2)
1670    CHECKFLAGS(L2P,L2)
1671    CHECKFLAGS(D1C,D1)
1672    CHECKFLAGS(D1P,D1)
1673    CHECKFLAGS(D2C,D2)
1674    CHECKFLAGS(D2P,D2)
1675    CHECKFLAGS(S1C,S1)
1676    CHECKFLAGS(S1P,S1)
1677    CHECKFLAGS(S2C,S2)
1678    CHECKFLAGS(S2P,S2)
1679    CHECKFLAGS(C5,C5)
1680    CHECKFLAGS(L5,L5)
1681    CHECKFLAGS(D5,D5)
1682    CHECKFLAGS(S5,S5)
1683    CHECKFLAGS(C5AB,C5AB)
1684    CHECKFLAGS(L5AB,L5AB)
1685    CHECKFLAGS(D5AB,D5AB)
1686    CHECKFLAGS(S5AB,S5AB)
1687    CHECKFLAGS(C5B,C5B)
1688    CHECKFLAGS(L5B,L5B)
1689    CHECKFLAGS(D5B,D5B)
1690    CHECKFLAGS(S5B,S5B)
1691    CHECKFLAGS(C6,C6)
1692    CHECKFLAGS(L6,L6)
1693    CHECKFLAGS(D6,D6)
1694    CHECKFLAGS(S6,S6)
1695  }
1696#else /* NO_RTCM3_MAIN */
1697  struct HeaderData hdata;
1698  char thebuffer[MAXHEADERBUFFERSIZE];
1699  char *buffer = thebuffer;
1700  size_t buffersize = sizeof(thebuffer);
1701  int i;
1702
1703  memset(&hdata, 0, sizeof(hdata));
1704
1705  hdata.data.named.version = buffer;
1706  i = 1+snprintf(buffer, buffersize,
1707  "%9.2f           OBSERVATION DATA    M (Mixed)"
1708  "           RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
1709  buffer += i; buffersize -= i;
1710
1711  {
1712    const char *str;
1713    hdata.data.named.pgm = buffer;
1714    i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
1715    buffer += i; buffersize -= i;
1716    hdata.data.named.observer = buffer;
1717    i = 1+snprintf(buffer, buffersize,
1718    "%-20.20s                                        "
1719    "OBSERVER / AGENCY", str);
1720    buffer += i; buffersize -= i;
1721  }
1722
1723  hdata.data.named.marker =
1724  "RTCM3TORINEX                                                "
1725  "MARKER NAME";
1726
1727  hdata.data.named.markertype =  !Parser->rinex3 ? 0 :
1728  "GEODETIC                                                    "
1729  "MARKER TYPE";
1730
1731  hdata.data.named.receiver =
1732  "                                                            "
1733  "REC # / TYPE / VERS";
1734
1735  hdata.data.named.antenna =
1736  "                                                            "
1737  "ANT # / TYPE";
1738
1739  hdata.data.named.position =
1740  "         .0000         .0000         .0000                  "
1741  "APPROX POSITION XYZ";
1742
1743  hdata.data.named.antennaposition =
1744  "         .0000         .0000         .0000                  "
1745  "ANTENNA: DELTA H/E/N";
1746
1747  hdata.data.named.wavelength = Parser->rinex3 ? 0 :
1748  "     1     1                                                "
1749  "WAVELENGTH FACT L1/2";
1750
1751  if(Parser->rinex3)
1752  {
1753#define CHECKFLAGSNEW(a, b, c) \
1754    if(flags & GNSSDF_##b##DATA) \
1755    { \
1756      Parser->dataflag##a[Parser->numdatatypes##a] = GNSSDF_##b##DATA; \
1757      Parser->datapos##a[Parser->numdatatypes##a] = GNSSENTRY_##b##DATA; \
1758      ++Parser->numdatatypes##a; \
1759      snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " %-3s", #c); \
1760      tbufferpos += 4; \
1761    }
1762
1763    int flags = Parser->startflags;
1764    char tbuffer[6*RINEXENTRY_NUMBER+1];
1765    int tbufferpos = 0;
1766    for(i = 0; i < Parser->Data.numsats; ++i)
1767      flags |= Parser->Data.dataflags[i];
1768
1769    CHECKFLAGSNEW(GPS, C1,  C1C)
1770    CHECKFLAGSNEW(GPS, L1C, L1C)
1771    CHECKFLAGSNEW(GPS, D1C, D1C)
1772    CHECKFLAGSNEW(GPS, S1C, S1C)
1773    CHECKFLAGSNEW(GPS, P1,  C1W)
1774    CHECKFLAGSNEW(GPS, L1P, L1W)
1775    CHECKFLAGSNEW(GPS, D1P, D1W)
1776    CHECKFLAGSNEW(GPS, S1P, S1W)
1777
1778    hdata.data.named.typesofobsS = buffer;
1779    i = 1+snprintf(buffer, buffersize,
1780    "S  %3d%-52.52s  SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1781    buffer += i; buffersize -= i;
1782
1783    CHECKFLAGSNEW(GPS, P2,  C2P)
1784    CHECKFLAGSNEW(GPS, L2P, L2P)
1785    CHECKFLAGSNEW(GPS, D2P, D2P)
1786    CHECKFLAGSNEW(GPS, S2P, S2P)
1787    CHECKFLAGSNEW(GPS, C2,  C2X)
1788    CHECKFLAGSNEW(GPS, L2C, L2X)
1789    CHECKFLAGSNEW(GPS, D2C, D2X)
1790    CHECKFLAGSNEW(GPS, S2C, S2X)
1791    CHECKFLAGSNEW(GPS, C5,  C5)
1792    CHECKFLAGSNEW(GPS, L5,  L5)
1793    CHECKFLAGSNEW(GPS, D5,  D5)
1794    CHECKFLAGSNEW(GPS, S5,  S5)
1795
1796    hdata.data.named.typesofobsG = buffer;
1797    i = 1+snprintf(buffer, buffersize,
1798    "G  %3d%-52.52s  SYS / # / OBS TYPES", Parser->numdatatypesGPS, tbuffer);
1799    if(Parser->numdatatypesGPS>13)
1800    {
1801      i += snprintf(buffer+i-1, buffersize,
1802      "\n      %-52.52s  SYS / # / OBS TYPES", tbuffer+13*4);
1803    }
1804    buffer += i; buffersize -= i;
1805
1806    tbufferpos = 0;
1807
1808    CHECKFLAGSNEW(GLO, C1,  C1C)
1809    CHECKFLAGSNEW(GLO, L1C, L1C)
1810    CHECKFLAGSNEW(GLO, D1C, D1C)
1811    CHECKFLAGSNEW(GLO, S1C, S1C)
1812    CHECKFLAGSNEW(GLO, P1,  C1P)
1813    CHECKFLAGSNEW(GLO, L1P, L1P)
1814    CHECKFLAGSNEW(GLO, D1P, D1P)
1815    CHECKFLAGSNEW(GLO, S1P, S1P)
1816    CHECKFLAGSNEW(GLO, P2,  C2P)
1817    CHECKFLAGSNEW(GLO, L2P, L2P)
1818    CHECKFLAGSNEW(GLO, D2P, D2P)
1819    CHECKFLAGSNEW(GLO, S2P, S2P)
1820    CHECKFLAGSNEW(GLO, C2,  C2C)
1821    CHECKFLAGSNEW(GLO, L2C, L2C)
1822    CHECKFLAGSNEW(GLO, D2C, D2C)
1823    CHECKFLAGSNEW(GLO, S2C, S2C)
1824
1825    hdata.data.named.typesofobsR = buffer;
1826    i = 1+snprintf(buffer, buffersize,
1827    "R  %3d%-52.52s  SYS / # / OBS TYPES", Parser->numdatatypesGLO, tbuffer);
1828    if(Parser->numdatatypesGLO>13)
1829    {
1830      i += snprintf(buffer+i-1, buffersize,
1831      "\n      %-52.52s  SYS / # / OBS TYPES", tbuffer+13*4);
1832    }
1833    buffer += i; buffersize -= i;
1834
1835    tbufferpos = 0;
1836
1837    CHECKFLAGSNEW(GAL, C1,   C1)
1838    CHECKFLAGSNEW(GAL, L1C,  L1)
1839    CHECKFLAGSNEW(GAL, D1C,  D1)
1840    CHECKFLAGSNEW(GAL, S1C,  S1)
1841    CHECKFLAGSNEW(GAL, C6,   C6)
1842    CHECKFLAGSNEW(GAL, L6,   L6)
1843    CHECKFLAGSNEW(GAL, D6,   D6)
1844    CHECKFLAGSNEW(GAL, S6,   S6)
1845    CHECKFLAGSNEW(GAL, C5,   C5)
1846    CHECKFLAGSNEW(GAL, L5,   L5)
1847    CHECKFLAGSNEW(GAL, D5,   D5)
1848    CHECKFLAGSNEW(GAL, S5,   S5)
1849    CHECKFLAGSNEW(GAL, C5B,  C7)
1850    CHECKFLAGSNEW(GAL, L5B,  L7)
1851    CHECKFLAGSNEW(GAL, D5B,  D7)
1852    CHECKFLAGSNEW(GAL, S5B,  S7)
1853    CHECKFLAGSNEW(GAL, C5AB, C8)
1854    CHECKFLAGSNEW(GAL, L5AB, L8)
1855    CHECKFLAGSNEW(GAL, D5AB, D8)
1856    CHECKFLAGSNEW(GAL, S5AB, S8)
1857
1858    hdata.data.named.typesofobsE = buffer;
1859    i = 1+snprintf(buffer, buffersize,
1860    "E  %3d%-52.52s  SYS / # / OBS TYPES", Parser->numdatatypesGAL, tbuffer);
1861    if(Parser->numdatatypesGAL>13)
1862    {
1863      i += snprintf(buffer+i-1, buffersize,
1864      "\n      %-52.52s  SYS / # / OBS TYPES", tbuffer+13*4);
1865    }
1866    buffer += i; buffersize -= i;
1867  }
1868  else
1869  {
1870#define CHECKFLAGS(a, b) \
1871    if(flags & GNSSDF_##a##DATA) \
1872    { \
1873      if(data[RINEXENTRY_##b##DATA]) \
1874      { \
1875        Parser->dataflagGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1876        Parser->dataposGPS[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1877      } \
1878      else \
1879      { \
1880        Parser->dataflag[Parser->numdatatypesGPS] = GNSSDF_##a##DATA; \
1881        Parser->datapos[Parser->numdatatypesGPS] = GNSSENTRY_##a##DATA; \
1882        data[RINEXENTRY_##b##DATA] = ++Parser->numdatatypesGPS; \
1883        snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, "    "#b); \
1884        tbufferpos += 6; \
1885      } \
1886    }
1887
1888    int flags = Parser->startflags;
1889    int data[RINEXENTRY_NUMBER];
1890    char tbuffer[6*RINEXENTRY_NUMBER+1];
1891    int tbufferpos = 0;
1892    for(i = 0; i < RINEXENTRY_NUMBER; ++i)
1893      data[i] = 0;
1894    for(i = 0; i < Parser->Data.numsats; ++i)
1895      flags |= Parser->Data.dataflags[i];
1896
1897    CHECKFLAGS(C1,C1)
1898    CHECKFLAGS(C2,C2)
1899    CHECKFLAGS(P1,P1)
1900    CHECKFLAGS(P2,P2)
1901    CHECKFLAGS(L1C,L1)
1902    CHECKFLAGS(L1P,L1)
1903    CHECKFLAGS(L2C,L2)
1904    CHECKFLAGS(L2P,L2)
1905    CHECKFLAGS(D1C,D1)
1906    CHECKFLAGS(D1P,D1)
1907    CHECKFLAGS(D2C,D2)
1908    CHECKFLAGS(D2P,D2)
1909    CHECKFLAGS(S1C,S1)
1910    CHECKFLAGS(S1P,S1)
1911    CHECKFLAGS(S2C,S2)
1912    CHECKFLAGS(S2P,S2)
1913    CHECKFLAGS(C5,C5)
1914    CHECKFLAGS(L5,L5)
1915    CHECKFLAGS(D5,D5)
1916    CHECKFLAGS(S5,S5)
1917    CHECKFLAGS(C5AB,C5AB)
1918    CHECKFLAGS(L5AB,L5AB)
1919    CHECKFLAGS(D5AB,D5AB)
1920    CHECKFLAGS(S5AB,S5AB)
1921    CHECKFLAGS(C5B,C5B)
1922    CHECKFLAGS(L5B,L5B)
1923    CHECKFLAGS(D5B,D5B)
1924    CHECKFLAGS(S5B,S5B)
1925    CHECKFLAGS(C6,C6)
1926    CHECKFLAGS(L6,L6)
1927    CHECKFLAGS(D6,D6)
1928    CHECKFLAGS(S6,S6)
1929
1930    hdata.data.named.typesofobs = buffer;
1931    i = 1+snprintf(buffer, buffersize,
1932    "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer);
1933    if(Parser->numdatatypesGPS>9)
1934    {
1935      i += snprintf(buffer+i-1, buffersize,
1936      "\n      %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
1937    }
1938    buffer += i; buffersize -= i;
1939  }
1940
1941  {
1942    struct converttimeinfo cti;
1943    converttime(&cti, Parser->Data.week,
1944    (int)floor(Parser->Data.timeofweek/1000.0));
1945    hdata.data.named.timeoffirstobs = buffer;
1946    i = 1+snprintf(buffer, buffersize,
1947    "  %4d    %2d    %2d    %2d    %2d   %10.7f     GPS         "
1948    "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
1949    cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
1950
1951    buffer += i; buffersize -= i;
1952  }
1953
1954  hdata.numheaders = 15;
1955
1956  if(Parser->headerfile)
1957  {
1958    FILE *fh;
1959    if((fh = fopen(Parser->headerfile, "r")))
1960    {
1961      size_t siz;
1962      char *lastblockstart;
1963      if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
1964      {
1965        buffer[siz] = '\n';
1966        if(siz == buffersize)
1967        {
1968          RTCM3Error("Header file is too large. Only %d bytes read.",
1969          (int)siz);
1970        }
1971        /* scan the file line by line and enter the entries in the list */
1972        /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
1973        /* overwrites entries, except for comments */
1974        lastblockstart = buffer;
1975        for(i = 0; i < (int)siz; ++i)
1976        {
1977          if(buffer[i] == '\n')
1978          { /* we found a line */
1979            char *end;
1980            while(buffer[i+1] == '\r')
1981              ++i; /* skip \r in case there are any */
1982            end = buffer+i;
1983            while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
1984              *(end--) = 0;
1985            if(end-lastblockstart < 60+5) /* short line */
1986              RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
1987            else
1988            {
1989              int pos;
1990              if(!strcmp("COMMENT", lastblockstart+60))
1991                pos = hdata.numheaders;
1992              else
1993              {
1994                for(pos = 0; pos < hdata.numheaders; ++pos)
1995                {
1996                  if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
1997                    break;
1998                }
1999                if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
2000                || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
2001                {
2002                  RTCM3Error("Overwriting header '%s' is dangerous.\n",
2003                  lastblockstart+60);
2004                }
2005              }
2006              if(pos >= MAXHEADERLINES)
2007              {
2008                RTCM3Error("Maximum number of header lines of %d reached.\n",
2009                MAXHEADERLINES);
2010              }
2011              else if(!strcmp("END OF HEADER", lastblockstart+60))
2012              {
2013                RTCM3Error("End of header ignored.\n");
2014              }
2015              else
2016              {
2017                hdata.data.unnamed[pos] = lastblockstart;
2018                if(pos == hdata.numheaders)
2019                  ++hdata.numheaders;
2020              }
2021            }
2022            lastblockstart = buffer+i+1;
2023          }
2024        }
2025      }
2026      else
2027      {
2028        RTCM3Error("Could not read data from headerfile '%s'.\n",
2029        Parser->headerfile);
2030      }
2031      fclose(fh);
2032    }
2033    else
2034    {
2035      RTCM3Error("Could not open header datafile '%s'.\n",
2036      Parser->headerfile);
2037    }
2038  }
2039
2040  for(i = 0; i < hdata.numheaders; ++i)
2041  {
2042    if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
2043      RTCM3Text("%s\n", hdata.data.unnamed[i]);
2044  }
2045  RTCM3Text("                                                            "
2046  "END OF HEADER\n");
2047#endif
2048}
2049
2050static void ConvLine(FILE *file, const char *fmt, ...)
2051{
2052  char buffer[100], *b;
2053  va_list v;
2054  va_start(v, fmt);
2055  vsnprintf(buffer, sizeof(buffer), fmt, v);
2056  for(b = buffer; *b; ++b)
2057  {
2058    if(*b == 'e') *b = 'D';
2059  }
2060  fprintf(file, "%s", buffer);
2061  va_end(v);
2062}
2063
2064void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
2065{
2066  Parser->Message[Parser->MessageSize++] = byte;
2067  if(Parser->MessageSize >= Parser->NeedBytes)
2068  {
2069    int r;
2070    while((r = RTCM3Parser(Parser)))
2071    {
2072      if(r == 1020 || r == 1019)
2073      {
2074        FILE *file = 0;
2075
2076        if(Parser->rinex3 && !(file = Parser->gpsfile))
2077        {
2078          const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
2079          if(n)
2080          {
2081            if(!(Parser->gpsfile = fopen(n, "w")))
2082            {
2083              RTCM3Error("Could not open ephemeris output file.\n");
2084            }
2085            else
2086            {
2087              char buffer[100];
2088              fprintf(Parser->gpsfile,
2089              "%9.2f%11sN: GNSS NAV DATA    M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
2090              HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2091              fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2092            }
2093            Parser->gpsephemeris = 0;
2094            Parser->glonassephemeris = 0;
2095            file = Parser->gpsfile;
2096          }
2097        }
2098        else
2099        {
2100          if(r == 1020)
2101          {
2102            if(Parser->glonassephemeris)
2103            {
2104              if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
2105              {
2106                RTCM3Error("Could not open GLONASS ephemeris output file.\n");
2107              }
2108              else
2109              {
2110                char buffer[100];
2111                fprintf(Parser->glonassfile,
2112                "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
2113                HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2114                fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2115              }
2116              Parser->glonassephemeris = 0;
2117            }
2118            file = Parser->glonassfile;
2119          }
2120          else if(r == 1019)
2121          {
2122            if(Parser->gpsephemeris)
2123            {
2124              if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2125              {
2126                RTCM3Error("Could not open GPS ephemeris output file.\n");
2127              }
2128              else
2129              {
2130                char buffer[100];
2131                fprintf(Parser->gpsfile,
2132                "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
2133                HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2134                fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2135              }
2136              Parser->gpsephemeris = 0;
2137            }
2138            file = Parser->gpsfile;
2139          }
2140        }
2141        if(file)
2142        {
2143          if(r == 1020)
2144          {
2145            struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2146            int w = e->GPSWeek, tow = e->GPSTOW, i;
2147            struct converttimeinfo cti;
2148
2149            updatetime(&w, &tow, e->tb*1000, 1);  /* Moscow - > UTC */
2150            converttime(&cti, w, tow);
2151
2152            i = e->tk-3*60*60; if(i < 0) i += 86400;
2153
2154            if(Parser->rinex3)
2155              ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2156              e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2157              cti.second, -e->tau, e->gamma, (double) i);
2158            else
2159              ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2160              e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2161              (double) cti.second, -e->tau, e->gamma, (double) i);
2162            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
2163            e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2164            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
2165            e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2166            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
2167            e->z_velocity, e->z_acceleration, (double) e->E);
2168          }
2169          else /* if(r == 1019) */
2170          {
2171            struct gpsephemeris *e = &Parser->ephemerisGPS;
2172            double d;                 /* temporary variable */
2173            unsigned long int i;       /* temporary variable */
2174            struct converttimeinfo cti;
2175            converttime(&cti, e->GPSweek, e->TOC);
2176
2177            if(Parser->rinex3)
2178              ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2179              e->satellite, cti.year, cti.month, cti.day, cti.hour,
2180              cti.minute, cti.second, e->clock_bias, e->clock_drift,
2181              e->clock_driftrate);
2182            else
2183              ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2184              e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
2185              cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2186              e->clock_driftrate);
2187            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
2188            e->Crs, e->Delta_n, e->M0);
2189            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
2190            e->e, e->Cus, e->sqrt_A);
2191            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n",
2192            (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2193            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n", e->i0,
2194            e->Crc, e->omega, e->OMEGADOT);
2195            d = 0;
2196            i = e->flags;
2197            if(i & GPSEPHF_L2CACODE)
2198              d += 2.0;
2199            if(i & GPSEPHF_L2PCODE)
2200              d += 1.0;
2201            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
2202            (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2203            if(e->URAindex <= 6) /* URA index */
2204              d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2205            else
2206              d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2207            /* 15 indicates not to use satellite. We can't handle this special
2208               case, so we create a high "non"-accuracy value. */
2209            ConvLine(file, "   %19.12e%19.12e%19.12e%19.12e\n", d,
2210            ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2211
2212            ConvLine(file, "   %19.12e%19.12e\n", ((double)e->TOW), 0.0);
2213            /* TOW */
2214          }
2215        }
2216      }
2217      else if (r == 1 || r == 2)
2218      {
2219        int i, j, o;
2220        struct converttimeinfo cti;
2221
2222        if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
2223        {
2224          ++Parser->init;
2225
2226          if(Parser->init == NUMSTARTSKIP)
2227            HandleHeader(Parser);
2228          else
2229          {
2230            for(i = 0; i < Parser->Data.numsats; ++i)
2231              Parser->startflags |= Parser->Data.dataflags[i];
2232            continue;
2233          }
2234        }
2235        if(r == 2 && !Parser->validwarning)
2236        {
2237          RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2238          "           COMMENT\n");
2239          Parser->validwarning = 1;
2240        }
2241
2242        converttime(&cti, Parser->Data.week,
2243        (int)floor(Parser->Data.timeofweek/1000.0));
2244        if(Parser->rinex3)
2245        {
2246          RTCM3Text("> %04d %02d %02d %02d %02d%11.7f  0%3d\n",
2247          cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2248          + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2249          for(i = 0; i < Parser->Data.numsats; ++i)
2250          {
2251            int glo = 0, gal = 0;
2252            if(Parser->Data.satellites[i] <= PRN_GPS_END)
2253              RTCM3Text("G%02d", Parser->Data.satellites[i]);
2254            else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2255            && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2256            {
2257              RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
2258              glo = 1;
2259            }
2260            else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2261            && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2262            {
2263              RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
2264              gal = 1;
2265            }
2266            else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2267            && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2268            {
2269              RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2270              gal = 1;
2271            }
2272            else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2273            && Parser->Data.satellites[i] <= PRN_WAAS_END)
2274              RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_WAAS_START+20);
2275            else
2276              RTCM3Text("%3d", Parser->Data.satellites[i]);
2277
2278            if(glo)
2279            {
2280              for(j = 0; j < Parser->numdatatypesGLO; ++j)
2281              {
2282                int df = Parser->dataflagGLO[j];
2283                int pos = Parser->dataposGLO[j];
2284                if((Parser->Data.dataflags[i] & df)
2285                && !isnan(Parser->Data.measdata[i][pos])
2286                && !isinf(Parser->Data.measdata[i][pos]))
2287                {
2288                  char lli = ' ';
2289                  char snr = ' ';
2290                  if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2291                  {
2292                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2293                      lli = '1';
2294                    snr = '0'+Parser->Data.snrL1[i];
2295                  }
2296                  if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2297                  {
2298                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2299                      lli = '1';
2300                    snr = '0'+Parser->Data.snrL2[i];
2301                  }
2302                  RTCM3Text("%14.3f%c%c",
2303                  Parser->Data.measdata[i][pos],lli,snr);
2304                }
2305                else
2306                { /* no or illegal data */
2307                  RTCM3Text("                ");
2308                }
2309              }
2310            }
2311            else if(gal)
2312            {
2313              for(j = 0; j < Parser->numdatatypesGAL; ++j)
2314              {
2315                int df = Parser->dataflagGAL[j];
2316                int pos = Parser->dataposGAL[j];
2317                if((Parser->Data.dataflags[i] & df)
2318                && !isnan(Parser->Data.measdata[i][pos])
2319                && !isinf(Parser->Data.measdata[i][pos]))
2320                {
2321                  char lli = ' ';
2322                  char snr = ' ';
2323                  if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2324                  {
2325                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2326                      lli = '1';
2327                    snr = '0'+Parser->Data.snrL1[i];
2328                  }
2329                  if(df & GNSSDF_L6DATA)
2330                  {
2331                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
2332                      lli = '1';
2333                    snr = ' ';
2334                  }
2335                  if(df & GNSSDF_L5DATA)
2336                  {
2337                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2338                      lli = '1';
2339                    snr = ' ';
2340                  }
2341                  if(df & GNSSDF_L5BDATA)
2342                  {
2343                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
2344                      lli = '1';
2345                    snr = ' ';
2346                  }
2347                  if(df & GNSSDF_L5ABDATA)
2348                  {
2349                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
2350                      lli = '1';
2351                    snr = ' ';
2352                  }
2353                  RTCM3Text("%14.3f%c%c",
2354                  Parser->Data.measdata[i][pos],lli,snr);
2355                }
2356                else
2357                { /* no or illegal data */
2358                  RTCM3Text("                ");
2359                }
2360              }
2361            }
2362            else
2363            {
2364              for(j = 0; j < Parser->numdatatypesGPS; ++j)
2365              {
2366                int df = Parser->dataflagGPS[j];
2367                int pos = Parser->dataposGPS[j];
2368                if((Parser->Data.dataflags[i] & df)
2369                && !isnan(Parser->Data.measdata[i][pos])
2370                && !isinf(Parser->Data.measdata[i][pos]))
2371                {
2372                  char lli = ' ';
2373                  char snr = ' ';
2374                  if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2375                  {
2376                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2377                      lli = '1';
2378                    snr = '0'+Parser->Data.snrL1[i];
2379                  }
2380                  if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2381                  {
2382                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2383                      lli = '1';
2384                    snr = '0'+Parser->Data.snrL2[i];
2385                  }
2386                  if(df & GNSSDF_L5DATA)
2387                  {
2388                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2389                      lli = '1';
2390                    snr = ' ';
2391                  }
2392                  RTCM3Text("%14.3f%c%c",
2393                  Parser->Data.measdata[i][pos],lli,snr);
2394                }
2395                else
2396                { /* no or illegal data */
2397                  RTCM3Text("                ");
2398                }
2399              }
2400            }
2401            RTCM3Text("\n");
2402          }
2403        }
2404        else
2405        {
2406          RTCM3Text(" %02d %2d %2d %2d %2d %10.7f  0%3d",
2407          cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
2408          + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2409          for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
2410          {
2411            if(Parser->Data.satellites[i] <= PRN_GPS_END)
2412              RTCM3Text("G%02d", Parser->Data.satellites[i]);
2413            else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2414            && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2415              RTCM3Text("R%02d", Parser->Data.satellites[i]
2416              - (PRN_GLONASS_START-1));
2417            else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2418            && Parser->Data.satellites[i] <= PRN_WAAS_END)
2419              RTCM3Text("S%02d", Parser->Data.satellites[i]
2420              - PRN_WAAS_START+20);
2421            else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2422            && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2423              RTCM3Text("E%02d", Parser->Data.satellites[i]
2424              - (PRN_GALILEO_START-1));
2425            else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2426            && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2427              RTCM3Text("E%02d", Parser->Data.satellites[i]
2428              - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2429            else
2430              RTCM3Text("%3d", Parser->Data.satellites[i]);
2431          }
2432          RTCM3Text("\n");
2433          o = 12;
2434          j = Parser->Data.numsats - 12;
2435          while(j > 0)
2436          {
2437            RTCM3Text("                                ");
2438            for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
2439            {
2440              if(Parser->Data.satellites[i] <= PRN_GPS_END)
2441                RTCM3Text("G%02d", Parser->Data.satellites[i]);
2442              else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2443              && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2444                RTCM3Text("R%02d", Parser->Data.satellites[i]
2445                - (PRN_GLONASS_START-1));
2446              else if(Parser->Data.satellites[i] >= PRN_WAAS_START
2447              && Parser->Data.satellites[i] <= PRN_WAAS_END)
2448                RTCM3Text("S%02d", Parser->Data.satellites[i]
2449                - PRN_WAAS_START+20);
2450              else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2451              && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2452                RTCM3Text("E%02d", Parser->Data.satellites[i]
2453                - (PRN_GALILEO_START-1));
2454              else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2455              && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2456                RTCM3Text("E%02d", Parser->Data.satellites[i]
2457                - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2458              else
2459                RTCM3Text("%3d", Parser->Data.satellites[i]);
2460            }
2461            RTCM3Text("\n");
2462            j -= 12;
2463            o += 12;
2464          }
2465          for(i = 0; i < Parser->Data.numsats; ++i)
2466          {
2467            for(j = 0; j < Parser->numdatatypesGPS; ++j)
2468            {
2469              int v = 0;
2470              int df = Parser->dataflag[j];
2471              int pos = Parser->datapos[j];
2472              if((Parser->Data.dataflags[i] & df)
2473              && !isnan(Parser->Data.measdata[i][pos])
2474              && !isinf(Parser->Data.measdata[i][pos]))
2475              {
2476                v = 1;
2477              }
2478              else
2479              {
2480                df = Parser->dataflagGPS[j];
2481                pos = Parser->dataposGPS[j];
2482
2483                if((Parser->Data.dataflags[i] & df)
2484                && !isnan(Parser->Data.measdata[i][pos])
2485                && !isinf(Parser->Data.measdata[i][pos]))
2486                {
2487                  v = 1;
2488                }
2489              }
2490
2491              if(!v)
2492              { /* no or illegal data */
2493                RTCM3Text("                ");
2494              }
2495              else
2496              {
2497                char lli = ' ';
2498                char snr = ' ';
2499                if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2500                {
2501                  if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2502                    lli = '1';
2503                  snr = '0'+Parser->Data.snrL1[i];
2504                }
2505                if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2506                {
2507                  if(Parser->Data.dataflags2[i]
2508                  & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
2509                  {
2510                    lli = '0';
2511                    if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2512                      lli += 1;
2513                    if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
2514                      lli += 4;
2515                  }
2516                  snr = '0'+Parser->Data.snrL2[i];
2517                }
2518                if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
2519                & GNSSDF2_XCORRL2))
2520                  lli = '4';
2521                RTCM3Text("%14.3f%c%c",
2522                Parser->Data.measdata[i][pos],lli,snr);
2523              }
2524              if(j%5 == 4 || j == Parser->numdatatypesGPS-1)
2525                RTCM3Text("\n");
2526            }
2527          }
2528        }
2529      }
2530    }
2531  }
2532}
2533
2534#ifndef NO_RTCM3_MAIN
2535static char datestr[]     = "$Date: 2012-01-09 16:18:58 +0000 (Mon, 09 Jan 2012) $";
2536
2537/* The string, which is send as agent in HTTP request */
2538#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
2539
2540#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
2541
2542static const char encodingTable [64] = {
2543  'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
2544  'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
2545  'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
2546  'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
2547};
2548
2549/* does not buffer overrun, but breaks directly after an error */
2550/* returns the number of required bytes */
2551static int encode(char *buf, int size, const char *user, const char *pwd)
2552{
2553  unsigned char inbuf[3];
2554  char *out = buf;
2555  int i, sep = 0, fill = 0, bytes = 0;
2556
2557  while(*user || *pwd)
2558  {
2559    i = 0;
2560    while(i < 3 && *user) inbuf[i++] = *(user++);
2561    if(i < 3 && !sep)    {inbuf[i++] = ':'; ++sep; }
2562    while(i < 3 && *pwd)  inbuf[i++] = *(pwd++);
2563    while(i < 3)         {inbuf[i++] = 0; ++fill; }
2564    if(out-buf < size-1)
2565      *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
2566    if(out-buf < size-1)
2567      *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
2568               | ((inbuf [1] & 0xF0) >> 4)];
2569    if(out-buf < size-1)
2570    {
2571      if(fill == 2)
2572        *(out++) = '=';
2573      else
2574        *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
2575                 | ((inbuf [2] & 0xC0) >> 6)];
2576    }
2577    if(out-buf < size-1)
2578    {
2579      if(fill >= 1)
2580        *(out++) = '=';
2581      else
2582        *(out++) = encodingTable[inbuf [2] & 0x3F];
2583    }
2584    bytes += 4;
2585  }
2586  if(out-buf < size)
2587    *out = 0;
2588  return bytes;
2589}
2590
2591static int stop = 0;
2592
2593struct Args
2594{
2595  const char *server;
2596  const char *port;
2597  int         mode;
2598  int         timeout;
2599  int         rinex3;
2600  const char *user;
2601  const char *password;
2602  const char *proxyhost;
2603  const char *proxyport;
2604  const char *nmea;
2605  const char *data;
2606  const char *headerfile;
2607  const char *gpsephemeris;
2608  const char *glonassephemeris;
2609};
2610
2611/* option parsing */
2612#ifdef NO_LONG_OPTS
2613#define LONG_OPT(a)
2614#else
2615#define LONG_OPT(a) a
2616static struct option opts[] = {
2617{ "data",             required_argument, 0, 'd'},
2618{ "server",           required_argument, 0, 's'},
2619{ "password",         required_argument, 0, 'p'},
2620{ "port",             required_argument, 0, 'r'},
2621{ "timeout",          required_argument, 0, 't'},
2622{ "header",           required_argument, 0, 'f'},
2623{ "user",             required_argument, 0, 'u'},
2624{ "gpsephemeris",     required_argument, 0, 'E'},
2625{ "glonassephemeris", required_argument, 0, 'G'},
2626{ "rinex3",           no_argument,       0, '3'},
2627{ "proxyport",        required_argument, 0, 'R'},
2628{ "proxyhost",        required_argument, 0, 'S'},
2629{ "nmea",             required_argument, 0, 'n'},
2630{ "mode",             required_argument, 0, 'M'},
2631{ "help",             no_argument,       0, 'h'},
2632{0,0,0,0}};
2633#endif
2634#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
2635
2636enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
2637
2638static const char *geturl(const char *url, struct Args *args)
2639{
2640  static char buf[1000];
2641  static char *Buffer = buf;
2642  static char *Bufend = buf+sizeof(buf);
2643
2644  if(strncmp("ntrip:", url, 6))
2645    return "URL must start with 'ntrip:'.";
2646  url += 6; /* skip ntrip: */
2647
2648  if(*url != '@' && *url != '/')
2649  {
2650    /* scan for mountpoint */
2651    args->data = Buffer;
2652    while(*url && *url != '@' &&  *url != ';' &&*url != '/' && Buffer != Bufend)
2653      *(Buffer++) = *(url++);
2654    if(Buffer == args->data)
2655      return "Mountpoint required.";
2656    else if(Buffer >= Bufend-1)
2657      return "Parsing buffer too short.";
2658    *(Buffer++) = 0;
2659  }
2660
2661  if(*url == '/') /* username and password */
2662  {
2663    ++url;
2664    args->user = Buffer;
2665    while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
2666      *(Buffer++) = *(url++);
2667    if(Buffer == args->user)
2668      return "Username cannot be empty.";
2669    else if(Buffer >= Bufend-1)
2670      return "Parsing buffer too short.";
2671    *(Buffer++) = 0;
2672
2673    if(*url == ':') ++url;
2674
2675    args->password = Buffer;
2676    while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2677      *(Buffer++) = *(url++);
2678    if(Buffer == args->password)
2679      return "Password cannot be empty.";
2680    else if(Buffer >= Bufend-1)
2681      return "Parsing buffer too short.";
2682    *(Buffer++) = 0;
2683  }
2684
2685  if(*url == '@') /* server */
2686  {
2687    ++url;
2688    if(*url != '@' && *url != ':')
2689    {
2690      args->server = Buffer;
2691      while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
2692        *(Buffer++) = *(url++);
2693      if(Buffer == args->server)
2694        return "Servername cannot be empty.";
2695      else if(Buffer >= Bufend-1)
2696        return "Parsing buffer too short.";
2697      *(Buffer++) = 0;
2698    }
2699
2700    if(*url == ':')
2701    {
2702      ++url;
2703      args->port = Buffer;
2704      while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2705        *(Buffer++) = *(url++);
2706      if(Buffer == args->port)
2707        return "Port cannot be empty.";
2708      else if(Buffer >= Bufend-1)
2709        return "Parsing buffer too short.";
2710      *(Buffer++) = 0;
2711    }
2712
2713    if(*url == '@') /* proxy */
2714    {
2715      ++url;
2716      args->proxyhost = Buffer;
2717      while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
2718        *(Buffer++) = *(url++);
2719      if(Buffer == args->proxyhost)
2720        return "Proxy servername cannot be empty.";
2721      else if(Buffer >= Bufend-1)
2722        return "Parsing buffer too short.";
2723      *(Buffer++) = 0;
2724
2725      if(*url == ':')
2726      {
2727        ++url;
2728        args->proxyport = Buffer;
2729        while(*url && *url != ';' && Buffer != Bufend)
2730          *(Buffer++) = *(url++);
2731        if(Buffer == args->proxyport)
2732          return "Proxy port cannot be empty.";
2733        else if(Buffer >= Bufend-1)
2734          return "Parsing buffer too short.";
2735        *(Buffer++) = 0;
2736      }
2737    }
2738  }
2739  if(*url == ';') /* NMEA */
2740  {
2741    args->nmea = ++url;
2742    while(*url)
2743      ++url;
2744  }
2745
2746  return *url ? "Garbage at end of server string." : 0;
2747}
2748
2749static int getargs(int argc, char **argv, struct Args *args)
2750{
2751  int res = 1;
2752  int getoptr;
2753  int help = 0;
2754  char *t;
2755
2756  args->server = "www.euref-ip.net";
2757  args->port = "2101";
2758  args->timeout = 60;
2759  args->user = "";
2760  args->password = "";
2761  args->data = 0;
2762  args->headerfile = 0;
2763  args->gpsephemeris = 0;
2764  args->glonassephemeris = 0;
2765  args->rinex3 = 0;
2766  args->nmea = 0;
2767  args->proxyhost = 0;
2768  args->proxyport = "2101";
2769  args->mode = AUTO;
2770  help = 0;
2771
2772  do
2773  {
2774
2775#ifdef NO_LONG_OPTS
2776    switch((getoptr = getopt(argc, argv, ARGOPT)))
2777#else
2778    switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
2779#endif
2780    {
2781    case 's': args->server = optarg; break;
2782    case 'u': args->user = optarg; break;
2783    case 'p': args->password = optarg; break;
2784    case 'd': args->data = optarg; break;
2785    case 'f': args->headerfile = optarg; break;
2786    case 'E': args->gpsephemeris = optarg; break;
2787    case 'G': args->glonassephemeris = optarg; break;
2788    case 'r': args->port = optarg; break;
2789    case '3': args->rinex3 = 1; break;
2790    case 'S': args->proxyhost = optarg; break;
2791    case 'n': args->nmea = optarg; break;
2792    case 'R': args->proxyport = optarg; break;
2793    case 'h': help=1; break;
2794    case 'M':
2795      args->mode = 0;
2796      if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
2797        args->mode = NTRIP1;
2798      else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
2799        args->mode = HTTP;
2800      else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
2801        args->mode = RTSP;
2802      else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
2803        args->mode = AUTO;
2804      else args->mode = atoi(optarg);
2805      if((args->mode == 0) || (args->mode >= END))
2806      {
2807        fprintf(stderr, "Mode %s unknown\n", optarg);
2808        res = 0;
2809      }
2810      break;
2811    case 't':
2812      args->timeout = strtoul(optarg, &t, 10);
2813      if((t && *t) || args->timeout < 0)
2814        res = 0;
2815      break;
2816
2817    case 1:
2818      {
2819        const char *err;
2820        if((err = geturl(optarg, args)))
2821        {
2822          RTCM3Error("%s\n\n", err);
2823          res = 0;
2824        }
2825      }
2826      break;
2827    case -1: break;
2828    }
2829  } while(getoptr != -1 || !res);
2830
2831  datestr[0] = datestr[7];
2832  datestr[1] = datestr[8];
2833  datestr[2] = datestr[9];
2834  datestr[3] = datestr[10];
2835  datestr[5] = datestr[12];
2836  datestr[6] = datestr[13];
2837  datestr[8] = datestr[15];
2838  datestr[9] = datestr[16];
2839  datestr[4] = datestr[7] = '-';
2840  datestr[10] = 0;
2841
2842  if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
2843  {
2844    RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
2845    "Please specify only one navigation file.\n");
2846    res = 0;
2847  }
2848  else if(!res || help)
2849  {
2850    RTCM3Error("Version %s (%s) GPL" COMPILEDATE
2851    "\nUsage: %s -s server -u user ...\n"
2852    " -d " LONG_OPT("--data             ") "the requested data set\n"
2853    " -f " LONG_OPT("--headerfile       ") "file for RINEX header information\n"
2854    " -s " LONG_OPT("--server           ") "the server name or address\n"
2855    " -p " LONG_OPT("--password         ") "the login password\n"
2856    " -r " LONG_OPT("--port             ") "the server port number (default 2101)\n"
2857    " -t " LONG_OPT("--timeout          ") "timeout in seconds (default 60)\n"
2858    " -u " LONG_OPT("--user             ") "the user name\n"
2859    " -E " LONG_OPT("--gpsephemeris     ") "output file for GPS ephemeris data\n"
2860    " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
2861    " -3 " LONG_OPT("--rinex3           ") "output RINEX type 3 data\n"
2862    " -S " LONG_OPT("--proxyhost        ") "proxy name or address\n"
2863    " -R " LONG_OPT("--proxyport        ") "proxy port, optional (default 2101)\n"
2864    " -n " LONG_OPT("--nmea             ") "NMEA string for sending to server\n"
2865    " -M " LONG_OPT("--mode             ") "mode for data request\n"
2866    "     Valid modes are:\n"
2867    "     1, h, http     NTRIP Version 2.0 Caster in TCP/IP mode\n"
2868    "     2, r, rtsp     NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
2869    "     3, n, ntrip1   NTRIP Version 1.0 Caster\n"
2870    "     4, a, auto     automatic detection (default)\n"
2871    "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
2872    , revisionstr, datestr, argv[0], argv[0]);
2873    exit(1);
2874  }
2875  return res;
2876}
2877
2878/* let the output complete a block if necessary */
2879static void signalhandler(int sig)
2880{
2881  if(!stop)
2882  {
2883    RTCM3Error("Stop signal number %d received. "
2884    "Trying to terminate gentle.\n", sig);
2885    stop = 1;
2886    alarm(1);
2887  }
2888}
2889
2890#ifndef WINDOWSVERSION
2891static void WaitMicro(int mic)
2892{
2893  struct timeval tv;
2894  tv.tv_sec = mic/1000000;
2895  tv.tv_usec = mic%1000000;
2896#ifdef DEBUG
2897  fprintf(stderr, "Waiting %d micro seconds\n", mic);
2898#endif
2899  select(0, 0, 0, 0, &tv);
2900}
2901#else /* WINDOWSVERSION */
2902void WaitMicro(int mic)
2903{
2904   Sleep(mic/1000);
2905}
2906#endif /* WINDOWSVERSION */
2907
2908#define ALARMTIME   (2*60)
2909
2910/* for some reason we had to abort hard (maybe waiting for data */
2911#ifdef __GNUC__
2912static __attribute__ ((noreturn)) void signalhandler_alarm(
2913int sig __attribute__((__unused__)))
2914#else /* __GNUC__ */
2915static void signalhandler_alarm(int sig)
2916#endif /* __GNUC__ */
2917{
2918  RTCM3Error("Programm forcefully terminated.\n");
2919  exit(1);
2920}
2921
2922int main(int argc, char **argv)
2923{
2924  struct Args args;
2925  struct RTCM3ParserData Parser;
2926
2927  setbuf(stdout, 0);
2928  setbuf(stdin, 0);
2929  setbuf(stderr, 0);
2930
2931  fixrevision();
2932
2933  signal(SIGINT, signalhandler);
2934  signal(SIGALRM,signalhandler_alarm);
2935  signal(SIGQUIT,signalhandler);
2936  signal(SIGTERM,signalhandler);
2937  signal(SIGPIPE,signalhandler);
2938  memset(&Parser, 0, sizeof(Parser));
2939  {
2940    time_t tim;
2941    tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
2942    Parser.GPSWeek = tim/(7*24*60*60);
2943    Parser.GPSTOW = tim%(7*24*60*60);
2944  }
2945
2946  if(getargs(argc, argv, &args))
2947  {
2948    int sockfd, numbytes;
2949    char buf[MAXDATASIZE];
2950    struct sockaddr_in their_addr; /* connector's address information */
2951    struct hostent *he;
2952    struct servent *se;
2953    const char *server, *port, *proxyserver = 0;
2954    char proxyport[6];
2955    char *b;
2956    long i;
2957    struct timeval tv;
2958
2959    alarm(ALARMTIME);
2960
2961    Parser.headerfile = args.headerfile;
2962    Parser.glonassephemeris = args.glonassephemeris;
2963    Parser.gpsephemeris = args.gpsephemeris;
2964    Parser.rinex3 = args.rinex3;
2965
2966    if(args.proxyhost)
2967    {
2968      int p;
2969      if((i = strtol(args.port, &b, 10)) && (!b || !*b))
2970        p = i;
2971      else if(!(se = getservbyname(args.port, 0)))
2972      {
2973        RTCM3Error("Can't resolve port %s.", args.port);
2974        exit(1);
2975      }
2976      else
2977      {
2978        p = ntohs(se->s_port);
2979      }
2980      snprintf(proxyport, sizeof(proxyport), "%d", p);
2981      port = args.proxyport;
2982      proxyserver = args.server;
2983      server = args.proxyhost;
2984    }
2985    else
2986    {
2987      server = args.server;
2988      port = args.port;
2989    }
2990
2991    memset(&their_addr, 0, sizeof(struct sockaddr_in));
2992    if((i = strtol(port, &b, 10)) && (!b || !*b))
2993      their_addr.sin_port = htons(i);
2994    else if(!(se = getservbyname(port, 0)))
2995    {
2996      RTCM3Error("Can't resolve port %s.", port);
2997      exit(1);
2998    }
2999    else
3000    {
3001      their_addr.sin_port = se->s_port;
3002    }
3003    if(!(he=gethostbyname(server)))
3004    {
3005      RTCM3Error("Server name lookup failed for '%s'.\n", server);
3006      exit(1);
3007    }
3008    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
3009    {
3010      perror("socket");
3011      exit(1);
3012    }
3013
3014    tv.tv_sec  = args.timeout;
3015    tv.tv_usec = 0;
3016    if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
3017    {
3018      RTCM3Error("Function setsockopt: %s\n", strerror(errno));
3019      exit(1);
3020    }
3021
3022    their_addr.sin_family = AF_INET;
3023    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3024
3025    if(args.data && args.mode == RTSP)
3026    {
3027      struct sockaddr_in local;
3028      int sockudp, localport;
3029      int cseq = 1;
3030      socklen_t len;
3031
3032      if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3033      {
3034        perror("socket");
3035        exit(1);
3036      }
3037      /* fill structure with local address information for UDP */
3038      memset(&local, 0, sizeof(local));
3039      local.sin_family = AF_INET;
3040      local.sin_port = htons(0);
3041      local.sin_addr.s_addr = htonl(INADDR_ANY);
3042      len = sizeof(local);
3043      /* bind() in order to get a random RTP client_port */
3044      if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
3045      {
3046        perror("bind");
3047        exit(1);
3048      }
3049      if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
3050      {
3051        localport = ntohs(local.sin_port);
3052      }
3053      else
3054      {
3055        perror("local access failed");
3056        exit(1);
3057      }
3058      if(connect(sockfd, (struct sockaddr *)&their_addr,
3059      sizeof(struct sockaddr)) == -1)
3060      {
3061        perror("connect");
3062        exit(1);
3063      }
3064      i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3065      "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
3066      "CSeq: %d\r\n"
3067      "Ntrip-Version: Ntrip/2.0\r\n"
3068      "Ntrip-Component: Ntripclient\r\n"
3069      "User-Agent: %s/%s\r\n"
3070      "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
3071      "Authorization: Basic ",
3072      args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3073      args.data, cseq++, AGENTSTRING, revisionstr, localport);
3074      if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3075      {
3076        RTCM3Error("Requested data too long\n");
3077        exit(1);
3078      }
3079      i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3080      if(i > MAXDATASIZE-4)
3081      {
3082        RTCM3Error("Username and/or password too long\n");
3083        exit(1);
3084      }
3085      buf[i++] = '\r';
3086      buf[i++] = '\n';
3087      buf[i++] = '\r';
3088      buf[i++] = '\n';
3089      if(args.nmea)
3090      {
3091        int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3092        if(j >= 0 && j < MAXDATASIZE-i)
3093          i += j;
3094        else
3095        {
3096          RTCM3Error("NMEA string too long\n");
3097          exit(1);
3098        }
3099      }
3100      if(send(sockfd, buf, (size_t)i, 0) != i)
3101      {
3102        perror("send");
3103        exit(1);
3104      }
3105      if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3106      {
3107        if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3108        {
3109          int serverport = 0, session = 0;
3110          const char *portcheck = "server_port=";
3111          const char *sessioncheck = "session: ";
3112          int l = strlen(portcheck)-1;
3113          int j=0;
3114          for(i = 0; j != l && i < numbytes-l; ++i)
3115          {
3116            for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
3117              ;
3118          }
3119          if(i == numbytes-l)
3120          {
3121            RTCM3Error("No server port number found\n");
3122            exit(1);
3123          }
3124          else
3125          {
3126            i+=l;
3127            while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3128              serverport = serverport * 10 + buf[i++]-'0';
3129            if(buf[i] != '\r' && buf[i] != ';')
3130            {
3131              RTCM3Error("Could not extract server port\n");
3132              exit(1);
3133            }
3134          }
3135          l = strlen(sessioncheck)-1;
3136          j=0;
3137          for(i = 0; j != l && i < numbytes-l; ++i)
3138          {
3139            for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
3140              ;
3141          }
3142          if(i == numbytes-l)
3143          {
3144            RTCM3Error("No session number found\n");
3145            exit(1);
3146          }
3147          else
3148          {
3149            i+=l;
3150            while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3151              session = session * 10 + buf[i++]-'0';
3152            if(buf[i] != '\r')
3153            {
3154              RTCM3Error("Could not extract session number\n");
3155              exit(1);
3156            }
3157          }
3158
3159          i = snprintf(buf, MAXDATASIZE,
3160          "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
3161          "CSeq: %d\r\n"
3162          "Session: %d\r\n"
3163          "\r\n",
3164          args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3165          args.data, cseq++, session);
3166
3167          if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3168          {
3169            RTCM3Error("Requested data too long\n");
3170            exit(1);
3171          }
3172          if(send(sockfd, buf, (size_t)i, 0) != i)
3173          {
3174            perror("send");
3175            exit(1);
3176          }
3177          if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3178          {
3179            if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3180            {
3181              struct sockaddr_in addrRTP;
3182              /* fill structure with caster address information for UDP */
3183              memset(&addrRTP, 0, sizeof(addrRTP));
3184              addrRTP.sin_family = AF_INET;
3185              addrRTP.sin_port   = htons(serverport);
3186              their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3187              len = sizeof(addrRTP);
3188              int ts = 0;
3189              int sn = 0;
3190              int ssrc = 0;
3191              int init = 0;
3192              int u, v, w;
3193              while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
3194              (struct sockaddr*) &addrRTP, &len)) > 0)
3195              {
3196                alarm(ALARMTIME);
3197                if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
3198                {
3199                  u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
3200                  v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
3201                  +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
3202                  w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
3203                  +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
3204
3205                  if(init)
3206                  {
3207                    int z;
3208                    if(u < -30000 && sn > 30000) sn -= 0xFFFF;
3209                    if(ssrc != w || ts > v)
3210                    {
3211                      RTCM3Error("Illegal UDP data received.\n");
3212                      exit(1);
3213                    }
3214                    if(u > sn) /* don't show out-of-order packets */
3215                    for(z = 12; z < i && !stop; ++z)
3216                      HandleByte(&Parser, (unsigned int) buf[z]);
3217                  }
3218                  sn = u; ts = v; ssrc = w; init = 1;
3219                }
3220                else
3221                {
3222                  RTCM3Error("Illegal UDP header.\n");
3223                  exit(1);
3224                }
3225              }
3226            }
3227            i = snprintf(buf, MAXDATASIZE,
3228            "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
3229            "CSeq: %d\r\n"
3230            "Session: %d\r\n"
3231            "\r\n",
3232            args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3233            args.data, cseq++, session);
3234
3235            if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3236            {
3237              RTCM3Error("Requested data too long\n");
3238              exit(1);
3239            }
3240            if(send(sockfd, buf, (size_t)i, 0) != i)
3241            {
3242              perror("send");
3243              exit(1);
3244            }
3245          }
3246          else
3247          {
3248            RTCM3Error("Could not start data stream.\n");
3249            exit(1);
3250          }
3251        }
3252        else
3253        {
3254          RTCM3Error("Could not setup initial control connection.\n");
3255          exit(1);
3256        }
3257      }
3258      else
3259      {
3260        perror("recv");
3261        exit(1);
3262      }
3263    }
3264    else
3265    {
3266      if(connect(sockfd, (struct sockaddr *)&their_addr,
3267      sizeof(struct sockaddr)) == -1)
3268      {
3269        perror("connect");
3270        exit(1);
3271      }
3272      if(!args.data)
3273      {
3274        i = snprintf(buf, MAXDATASIZE,
3275        "GET %s%s%s%s/ HTTP/1.0\r\n"
3276        "Host: %s\r\n%s"
3277        "User-Agent: %s/%s\r\n"
3278        "Connection: close\r\n"
3279        "\r\n"
3280        , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3281        proxyserver ? ":" : "", proxyserver ? proxyport : "",
3282        args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3283        AGENTSTRING, revisionstr);
3284      }
3285      else
3286      {
3287        i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3288        "GET %s%s%s%s/%s HTTP/1.0\r\n"
3289        "Host: %s\r\n%s"
3290        "User-Agent: %s/%s\r\n"
3291        "Connection: close\r\n"
3292        "Authorization: Basic "
3293        , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3294        proxyserver ? ":" : "", proxyserver ? proxyport : "",
3295        args.data, args.server,
3296        args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3297        AGENTSTRING, revisionstr);
3298        if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3299        {
3300          RTCM3Error("Requested data too long\n");
3301          exit(1);
3302        }
3303        i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3304        if(i > MAXDATASIZE-4)
3305        {
3306          RTCM3Error("Username and/or password too long\n");
3307          exit(1);
3308        }
3309        buf[i++] = '\r';
3310        buf[i++] = '\n';
3311        buf[i++] = '\r';
3312        buf[i++] = '\n';
3313        if(args.nmea)
3314        {
3315          int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3316          if(j >= 0 && j < MAXDATASIZE-i)
3317            i += j;
3318          else
3319          {
3320            RTCM3Error("NMEA string too long\n");
3321            exit(1);
3322          }
3323        }
3324      }
3325      if(send(sockfd, buf, (size_t)i, 0) != i)
3326      {
3327        perror("send");
3328        exit(1);
3329      }
3330      if(args.data)
3331      {
3332        int k = 0;
3333        int chunkymode = 0;
3334        int starttime = time(0);
3335        int lastout = starttime;
3336        int totalbytes = 0;
3337        int chunksize = 0;
3338
3339        while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3340        {
3341          if(numbytes > 0)
3342            alarm(ALARMTIME);
3343          else
3344          {
3345            WaitMicro(100);
3346            continue;
3347          }
3348          if(!k)
3349          {
3350            if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
3351            || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
3352            {
3353              const char *datacheck = "Content-Type: gnss/data\r\n";
3354              const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
3355              int l = strlen(datacheck)-1;
3356              int j=0;
3357              for(i = 0; j != l && i < numbytes-l; ++i)
3358              {
3359                for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
3360                  ;
3361              }
3362              if(i == numbytes-l)
3363              {
3364                RTCM3Error("No 'Content-Type: gnss/data' found\n");
3365                exit(1);
3366              }
3367              l = strlen(chunkycheck)-1;
3368              j=0;
3369              for(i = 0; j != l && i < numbytes-l; ++i)
3370              {
3371                for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
3372                  ;
3373              }
3374              if(i < numbytes-l)
3375                chunkymode = 1;
3376            }
3377            else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
3378            {
3379              RTCM3Error("Could not get the requested data: ");
3380              for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
3381              {
3382                RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
3383              }
3384              RTCM3Error("\n");
3385              exit(1);
3386            }
3387            else if(args.mode != NTRIP1)
3388            {
3389              if(args.mode != AUTO)
3390              {
3391                RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
3392                args.mode == AUTO ? ", falling back to NTRIP1" : "");
3393              }
3394              if(args.mode == HTTP)
3395                exit(1);
3396            }
3397            ++k;
3398          }
3399          else
3400          {
3401            if(chunkymode)
3402            {
3403              int stop = 0;
3404              int pos = 0;
3405              while(!stop && pos < numbytes)
3406              {
3407                switch(chunkymode)
3408                {
3409                case 1: /* reading number starts */
3410                  chunksize = 0;
3411                  ++chunkymode; /* no break */
3412                case 2: /* during reading number */
3413                  i = buf[pos++];
3414                  if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
3415                  else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
3416                  else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
3417                  else if(i == '\r') ++chunkymode;
3418                  else if(i == ';') chunkymode = 5;
3419                  else stop = 1;
3420                  break;
3421                case 3: /* scanning for return */
3422                  if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
3423                  else stop = 1;
3424                  break;
3425                case 4: /* output data */
3426                  i = numbytes-pos;
3427                  if(i > chunksize) i = chunksize;
3428                  {
3429                    int z;
3430                    for(z = 0; z < i && !stop; ++z)
3431                      HandleByte(&Parser, (unsigned int) buf[pos+z]);
3432                  }
3433                  totalbytes += i;
3434                  chunksize -= i;
3435                  pos += i;
3436                  if(!chunksize)
3437                    chunkymode = 1;
3438                  break;
3439                case 5:
3440                  if(i == '\r') chunkymode = 3;
3441                  break;
3442                }
3443              }
3444              if(stop)
3445              {
3446                RTCM3Error("Error in chunky transfer encoding\n");
3447                break;
3448              }
3449            }
3450            else
3451            {
3452              totalbytes += numbytes;
3453              {
3454                int z;
3455                for(z = 0; z < numbytes && !stop; ++z)
3456                  HandleByte(&Parser, (unsigned int) buf[z]);
3457              }
3458            }
3459            if(totalbytes < 0) /* overflow */
3460            {
3461              totalbytes = 0;
3462              starttime = time(0);
3463              lastout = starttime;
3464            }
3465          }
3466        }
3467      }
3468      else
3469      {
3470        while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
3471        {
3472          alarm(ALARMTIME);
3473          fwrite(buf, (size_t)numbytes, 1, stdout);
3474        }
3475      }
3476      close(sockfd);
3477    }
3478  }
3479  return 0;
3480}
3481#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.