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

Last change on this file since 4498 was 4498, checked in by stoecker, 8 years ago

switch place for L1 signal to match JAXA drafts

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