Changeset 1569 in ntrip


Ignore:
Timestamp:
Feb 10, 2009, 1:18:23 PM (15 years ago)
Author:
stoecker
Message:

added Plain UDP mode

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ntripclient/ntripclient.c

    r1183 r1569  
    11/*
    22  NTRIP client for POSIX.
    3   $Id: ntripclient.c,v 1.45 2008/05/15 16:51:04 stoecker Exp $
     3  $Id: ntripclient.c,v 1.46 2008/11/04 15:35:03 stoecker Exp $
    44  Copyright (C) 2003-2008 by Dirk Stöcker <soft@dstoecker.de>
    55
     
    3535  typedef u_long in_addr_t;
    3636  typedef size_t socklen_t;
     37  void myperror(char *s)
     38  {
     39    fprintf(stderr, "%s: %d\n", s, WSAGetLastError());
     40  }
    3741#else
    3842  typedef int sockettype;
     
    4751  #define closesocket(sock)       close(sock)
    4852  #define ALARMTIME   (2*60)
     53  #define myperror perror
    4954#endif
    5055
     
    5560/* The string, which is send as agent in HTTP request */
    5661#define AGENTSTRING "NTRIP NtripClientPOSIX"
     62#define TIME_RESOLUTION 125
    5763
    5864#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
    5965
    6066/* CVS revision and version */
    61 static char revisionstr[] = "$Revision: 1.45 $";
    62 static char datestr[]     = "$Date: 2008/05/15 16:51:04 $";
    63 
    64 enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
     67static char revisionstr[] = "$Revision: 1.46 $";
     68static char datestr[]     = "$Date: 2008/11/04 15:35:03 $";
     69
     70enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, UDP = 5, END };
    6571
    6672struct Args
     
    434440      else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
    435441        args->mode = RTSP;
     442      else if(!strcmp(optarg,"u") || !strcmp(optarg,"udp"))
     443        args->mode = UDP;
    436444      else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
    437445        args->mode = AUTO;
     
    485493    "     3, n, ntrip1   NTRIP Version 1.0 Caster\n"
    486494    "     4, a, auto     automatic detection (default)\n"
     495    "     5, u, udp      NTRIP Version 2.0 Caster in UDP mode\n"
    487496    "or using an URL:\n%s ntrip:mountpoint[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
    488497    "\nExpert options:\n"
     
    680689            error = 1;
    681690          }
    682           else if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
     691          else if((sockfd = socket(AF_INET, (args.mode == UDP ? SOCK_DGRAM :
     692          SOCK_STREAM), 0)) == -1)
    683693          {
    684             perror("socket");
     694            myperror("socket");
    685695            error = 1;
    686696          }
     
    694704      if(!stop && !error)
    695705      {
    696         if(args.data && *args.data != '%' && args.mode == RTSP)
     706        if(args.mode == UDP)
     707        {
     708          int session, tim, seq, init;
     709          char rtpbuf[1526];
     710          int i=12, j;
     711
     712          init = time(0);
     713          srand(init);
     714          session = rand();
     715          tim = rand();
     716          seq = rand();
     717
     718          rtpbuf[0] = (2<<6);
     719          /* padding, extension, csrc are empty */
     720          rtpbuf[1] = 97;
     721          /* marker is empty */
     722          rtpbuf[2] = (seq>>8)&0xFF;
     723          rtpbuf[3] = (seq)&0xFF;
     724          rtpbuf[4] = (tim>>24)&0xFF;
     725          rtpbuf[5] = (tim>>16)&0xFF;
     726          rtpbuf[6] = (tim>>8)&0xFF;
     727          rtpbuf[7] = (tim)&0xFF;
     728          /* sequence and timestamp are empty */
     729          rtpbuf[8] = (session>>24)&0xFF;
     730          rtpbuf[9] = (session>>16)&0xFF;
     731          rtpbuf[10] = (session>>8)&0xFF;
     732          rtpbuf[11] = (session)&0xFF;
     733          ++seq;
     734
     735          j = snprintf(rtpbuf+i, sizeof(rtpbuf)-i-40, /* leave some space for login */
     736          "GET /%s HTTP/1.1\r\n"
     737          "Host: %s\r\n"
     738          "Ntrip-Version: Ntrip/2.0\r\n"
     739          "User-Agent: %s/%s\r\n"
     740          "%s%s%s"
     741          "Connection: close%s",
     742          args.data ? args.data : "", args.server, AGENTSTRING, revisionstr,
     743          args.nmea ? "Ntrip-GGA: " : "", args.nmea ? args.nmea : "",
     744          args.nmea ? "\r\n" : "",
     745          (*args.user || *args.password) ? "\r\nAuthorization: Basic " : "");
     746          i += j;
     747          if(i > (int)sizeof(rtpbuf)-40 || j < 0) /* second check for old glibc */
     748          {
     749            fprintf(stderr, "Requested data too long\n");
     750            stop = 1;
     751          }
     752          else
     753          {
     754            i += encode(rtpbuf+i, sizeof(rtpbuf)-i-4, args.user, args.password);
     755            if(i > (int)sizeof(rtpbuf)-4)
     756            {
     757              fprintf(stderr, "Username and/or password too long\n");
     758              stop = 1;
     759            }
     760            else
     761            {
     762              struct sockaddr_in local;
     763              socklen_t len;
     764
     765              rtpbuf[i++] = '\r';
     766              rtpbuf[i++] = '\n';
     767              rtpbuf[i++] = '\r';
     768              rtpbuf[i++] = '\n';
     769
     770
     771              /* fill structure with local address information for UDP */
     772              memset(&local, 0, sizeof(local));
     773              local.sin_family = AF_INET;
     774              local.sin_port = htons(args.udpport);
     775              local.sin_addr.s_addr = htonl(INADDR_ANY);
     776              len = sizeof(local);
     777
     778              /* bind() in order to get a random RTP client_port */
     779              if((bind(sockfd, (struct sockaddr *)&local, len)) < 0)
     780              {
     781                myperror("bind");
     782                error = 1;
     783              }
     784              else if(connect(sockfd, (struct sockaddr *)&their_addr,
     785              sizeof(struct sockaddr)) == -1)
     786              {
     787                myperror("connect");
     788                error = 1;
     789              }
     790              else if(send(sockfd, rtpbuf, i, 0) != i)
     791              {
     792                myperror("Could not send UDP packet");
     793                stop = 1;
     794              }
     795              else
     796              {
     797                if((numbytes=recv(sockfd, rtpbuf, sizeof(rtpbuf)-1, 0)) > 0)
     798                {
     799                  int sn = 0x10000, ts=0;
     800                  /* we don't expect message longer than 1513, so we cut the last
     801                    byte for security reasons to prevent buffer overrun */
     802                  rtpbuf[numbytes] = 0;
     803                  if(numbytes > 17+12 &&
     804                  (!strncmp(rtpbuf+12, "HTTP/1.1 200 OK\r\n", 17) ||
     805                  !strncmp(rtpbuf+12, "HTTP/1.0 200 OK\r\n", 17)))
     806                  {
     807                    const char *sessioncheck = "session: ";
     808                    const char *datacheck = "Content-Type: gnss/data\r\n";
     809                    int l = strlen(datacheck)-1;
     810                    int j=0;
     811                    for(i = 12; j != l && i < numbytes-l; ++i)
     812                    {
     813                      for(j = 0; j < l && rtpbuf[i+j] == datacheck[j]; ++j)
     814                        ;
     815                    }
     816                    if(i == numbytes-l)
     817                    {
     818                      fprintf(stderr, "No 'Content-Type: gnss/data' found\n");
     819                      error = 1;
     820                    }
     821                    /* check for Session */
     822                    l = strlen(sessioncheck)-1;
     823                    j=0;
     824                    for(i = 12; j != l && i < numbytes-l; ++i)
     825                    {
     826                      for(j = 0; j < l && tolower(rtpbuf[i+j]) == sessioncheck[j]; ++j)
     827                        ;
     828                    }
     829                    if(i != numbytes-l) /* found a session number */
     830                    {
     831                      i+=l;
     832                      session = 0;
     833                      while(i < numbytes && rtpbuf[i] >= '0' && rtpbuf[i] <= '9')
     834                        session = session * 10 + rtpbuf[i++]-'0';
     835                      if(rtpbuf[i] != '\r')
     836                      {
     837                        fprintf(stderr, "Could not extract session number\n");
     838                        stop = 1;
     839                      }
     840                    }
     841                  }
     842                  else
     843                  {
     844                    int k;
     845                    fprintf(stderr, "Could not get the requested data: ");
     846                    for(k = 12; k < numbytes && rtpbuf[k] != '\n' && rtpbuf[k] != '\r'; ++k)
     847                    {
     848                      fprintf(stderr, "%c", isprint(rtpbuf[k]) ? rtpbuf[k] : '.');
     849                    }
     850                    fprintf(stderr, "\n");
     851                    error = 1;
     852                  }
     853                  while(!stop && !error)
     854                  {
     855                    struct timeval tv = {1,0};
     856                    fd_set fdr;
     857                    fd_set fde;
     858
     859                    FD_ZERO(&fdr);
     860                    FD_ZERO(&fde);
     861                    FD_SET(sockfd, &fdr);
     862                    FD_SET(sockfd, &fde);
     863                    if(select(sockfd+1,&fdr,0,&fde,&tv) < 0)
     864                    {
     865                      fprintf(stderr, "Select problem.\n");
     866                      error = 1;
     867                      continue;
     868                    }
     869                    i = recv(sockfd, rtpbuf, sizeof(rtpbuf), 0);
     870#ifndef WINDOWSVERSION
     871                    alarm(ALARMTIME);
     872#endif
     873                    if(i >= 12+1 && (unsigned char)rtpbuf[0] == (2 << 6)
     874                    && rtpbuf[1] >= 96 && rtpbuf[1] <= 98)
     875                    {
     876                      time_t ct;
     877                      int u,v,w;
     878                      u = ((unsigned char)rtpbuf[2]<<8)+(unsigned char)rtpbuf[3];
     879                      v = ((unsigned char)rtpbuf[4]<<24)+((unsigned char)rtpbuf[5]<<16)
     880                      +((unsigned char)rtpbuf[6]<<8)+(unsigned char)rtpbuf[7];
     881                      w = ((unsigned char)rtpbuf[8]<<24)+((unsigned char)rtpbuf[9]<<16)
     882                      +((unsigned char)rtpbuf[10]<<8)+(unsigned char)rtpbuf[11];
     883
     884                      if(sn == 0x10000) {sn = u-1;ts=v-1;}
     885                      else if(u < -30000 && sn > 30000) sn -= 0xFFFF;
     886                      if(session != w || ts > v)
     887                      {
     888                        fprintf(stderr, "Illegal UDP data received.\n");
     889                        continue;
     890                      }
     891                      else if(u > sn) /* don't show out-of-order packets */
     892                      {
     893                        if(rtpbuf[1] == 98)
     894                        {
     895                          fprintf(stderr, "Connection closed.\n");
     896                          error = 1;
     897                          continue;
     898                        }
     899                        else if(rtpbuf[1] == 96)
     900                        {
     901                          fwrite(rtpbuf+12, (size_t)i-12, 1, stdout);
     902                        }
     903                      }
     904                      sn = u; ts = v;
     905 
     906                      /* Keep Alive */
     907                      ct = time(0);
     908                      if(ct-init > 15)
     909                      {
     910                        tim += (ct-init)*1000000/TIME_RESOLUTION;
     911                        rtpbuf[0] = (2<<6);
     912                        /* padding, extension, csrc are empty */
     913                        rtpbuf[1] = 96;
     914                        /* marker is empty */
     915                        rtpbuf[2] = (seq>>8)&0xFF;
     916                        rtpbuf[3] = (seq)&0xFF;
     917                        rtpbuf[4] = (tim>>24)&0xFF;
     918                        rtpbuf[5] = (tim>>16)&0xFF;
     919                        rtpbuf[6] = (tim>>8)&0xFF;
     920                        rtpbuf[7] = (tim)&0xFF;
     921                        /* sequence and timestamp are empty */
     922                        rtpbuf[8] = (session>>24)&0xFF;
     923                        rtpbuf[9] = (session>>16)&0xFF;
     924                        rtpbuf[10] = (session>>8)&0xFF;
     925                        rtpbuf[11] = (session)&0xFF;
     926                        ++seq;
     927                        init = ct;
     928
     929                        if(send(sockfd, rtpbuf, 12, 0) != 12)
     930                        {
     931                          myperror("send");
     932                          error = 1;
     933                        }
     934                      }
     935                    }
     936                    else if(i >= 0)
     937                    {
     938                      fprintf(stderr, "Illegal UDP header.\n");
     939                      continue;
     940                    }
     941                  }
     942                }
     943                /* send connection close always to allow nice session closing */
     944                tim += (time(0)-init)*1000000/TIME_RESOLUTION;
     945                rtpbuf[0] = (2<<6);
     946                /* padding, extension, csrc are empty */
     947                rtpbuf[1] = 98;
     948                /* marker is empty */
     949                rtpbuf[2] = (seq>>8)&0xFF;
     950                rtpbuf[3] = (seq)&0xFF;
     951                rtpbuf[4] = (tim>>24)&0xFF;
     952                rtpbuf[5] = (tim>>16)&0xFF;
     953                rtpbuf[6] = (tim>>8)&0xFF;
     954                rtpbuf[7] = (tim)&0xFF;
     955                /* sequence and timestamp are empty */
     956                rtpbuf[8] = (session>>24)&0xFF;
     957                rtpbuf[9] = (session>>16)&0xFF;
     958                rtpbuf[10] = (session>>8)&0xFF;
     959                rtpbuf[11] = (session)&0xFF;
     960
     961                send(sockfd, rtpbuf, 12, 0); /* cleanup */
     962              }
     963            }
     964          }
     965        }
     966        else if(args.data && *args.data != '%' && args.mode == RTSP)
    697967        {
    698968          struct sockaddr_in local;
     
    704974          if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    705975          {
    706             perror("socket");
     976            myperror("socket");
    707977            error = 1;
    708978          }
     
    718988            if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
    719989            {
    720               perror("bind");
     990              myperror("bind");
    721991              error = 1;
    722992            }
    723993            else if((getsockname(sockudp, (struct sockaddr*)&local, &len)) == -1)
    724994            {
    725               perror("local access failed");
     995              myperror("local access failed");
    726996              error = 1;
    727997            }
     
    729999            sizeof(struct sockaddr)) == -1)
    7301000            {
    731               perror("connect");
     1001              myperror("connect");
    7321002              error = 1;
    7331003            }
     
    7421012            "Ntrip-Component: Ntripclient\r\n"
    7431013            "User-Agent: %s/%s\r\n"
    744             "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
    745             "Authorization: Basic ",
     1014            "Transport: RTP/GNSS;unicast;client_port=%u%s",
    7461015            args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
    747             args.data, cseq++, AGENTSTRING, revisionstr, localport);
     1016            args.data, cseq++, AGENTSTRING, revisionstr, localport,
     1017            (*args.user || *args.password) ? "\r\nAuthorization: Basic " : "");
    7481018            if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
    7491019            {
     
    7771047            if(send(sockfd, buf, (size_t)i, 0) != i)
    7781048            {
    779               perror("send");
     1049              myperror("send");
    7801050              error = 1;
    7811051            }
    7821052            else if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1)
    7831053            {
    784               perror("recv");
     1054              myperror("recv");
    7851055              error = 1;
    7861056            }
     
    8681138                if((i = sendto(sockudp, rtpbuffer, 12, 0,
    8691139                (struct sockaddr *) &casterRTP, sizeof(casterRTP))) != 12)
    870                   perror("WARNING: could not send initial UDP packet");
     1140                  myperror("WARNING: could not send initial UDP packet");
    8711141              }
    8721142              if(!stop && !error)
     
    8871157                else if(send(sockfd, buf, (size_t)i, 0) != i)
    8881158                {
    889                   perror("send");
     1159                  myperror("send");
    8901160                  error = 1;
    8911161                }
     
    9191189                    while(!stop && !error)
    9201190                    {
     1191                      char rtpbuffer[1526];
    9211192                      struct timeval tv = {1,0};
    9221193                      fd_set fdr;
     
    9371208                        continue;
    9381209                      }
    939                       i = recvfrom(sockudp, buf, 1526, 0,
     1210                      i = recvfrom(sockudp, rtpbuffer, sizeof(rtpbuffer), 0,
    9401211                      (struct sockaddr*) &addrRTP, &len);
    9411212#ifndef WINDOWSVERSION
    9421213                      alarm(ALARMTIME);
    9431214#endif
    944                       if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
     1215                      if(i >= 12+1 && (unsigned char)rtpbuffer[0] == (2 << 6) && rtpbuffer[1] == 0x60)
    9451216                      {
    9461217                        int u,v,w;
    947                         u = ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
    948                         v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
    949                         +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
    950                         w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
    951                         +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
     1218                        u = ((unsigned char)rtpbuffer[2]<<8)+(unsigned char)rtpbuffer[3];
     1219                        v = ((unsigned char)rtpbuffer[4]<<24)+((unsigned char)rtpbuffer[5]<<16)
     1220                        +((unsigned char)rtpbuffer[6]<<8)+(unsigned char)rtpbuffer[7];
     1221                        w = ((unsigned char)rtpbuffer[8]<<24)+((unsigned char)rtpbuffer[9]<<16)
     1222                        +((unsigned char)rtpbuffer[10]<<8)+(unsigned char)rtpbuffer[11];
    9521223
    9531224                        if(init)
     
    9611232                          }
    9621233                          else if(u > sn) /* don't show out-of-order packets */
    963                             fwrite(buf+12, (size_t)i-12, 1, stdout);
     1234                            fwrite(rtpbuffer+12, (size_t)i-12, 1, stdout);
    9641235                          ct = time(0);
    9651236                          if(ct-init > 15)
     
    9791250                            else if(send(sockfd, buf, (size_t)i, 0) != i)
    9801251                            {
    981                               perror("send");
     1252                              myperror("send");
    9821253                              error = 1;
    9831254                            }
     
    10311302                  else if(send(sockfd, buf, (size_t)i, 0) != i)
    10321303                  {
    1033                     perror("send");
     1304                    myperror("send");
    10341305                    error = 1;
    10351306                  }
     
    10561327          sizeof(struct sockaddr)) == -1)
    10571328          {
    1058             perror("connect");
     1329            myperror("connect");
    10591330            error = 1;
    10601331          }
     
    10641335            {
    10651336              i = snprintf(buf, MAXDATASIZE,
    1066               "GET %s%s%s%s/ HTTP/1.0\r\n"
     1337              "GET %s%s%s%s/ HTTP/1.1\r\n"
    10671338              "Host: %s\r\n%s"
    10681339              "User-Agent: %s/%s\r\n"
     
    10771348            {
    10781349              i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
    1079               "GET %s%s%s%s/%s HTTP/1.0\r\n"
     1350              "GET %s%s%s%s/%s HTTP/1.1\r\n"
    10801351              "Host: %s\r\n%s"
    10811352              "User-Agent: %s/%s\r\n"
    1082               "Connection: close\r\n"
    1083               "Authorization: Basic "
     1353              "Connection: close%s"
    10841354              , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
    10851355              proxyserver ? ":" : "", proxyserver ? proxyport : "",
    10861356              args.data, args.server,
    10871357              args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
    1088               AGENTSTRING, revisionstr);
     1358              AGENTSTRING, revisionstr,
     1359              (*args.user || *args.password) ? "\r\nAuthorization: Basic " : "");
    10891360              if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
    10901361              {
     
    11251396            if(send(sockfd, buf, (size_t)i, 0) != i)
    11261397            {
    1127               perror("send");
     1398              myperror("send");
    11281399              error = 1;
    11291400            }
Note: See TracChangeset for help on using the changeset viewer.