Changeset 467 in ntrip for trunk/ntripserver


Ignore:
Timestamp:
Jun 6, 2007, 2:16:08 PM (17 years ago)
Author:
stoecker
Message:

updated to Version 2.0 (may not work yet)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ntripserver/NtripLinuxServer.c

    r466 r467  
    11/*
    2  * $Id: NtripLinuxClient.c,v 1.27 2007/05/16 14:16:21 stoecker Exp $
     2 * $Id: NtripLinuxServer.c,v 1.28 2007/06/06 09:44:27 stoecker Exp $
    33 *
    44 * Copyright (c) 2003...2007
     
    1111 *
    1212 * The BKG disclaims any liability nor responsibility to any person or
    13  * entity with respect to any loss or damage caused, or alleged to be 
    14  * caused, directly or indirectly by the use and application of the NTRIP 
     13 * entity with respect to any loss or damage caused, or alleged to be
     14 * caused, directly or indirectly by the use and application of the NTRIP
    1515 * technology.
    1616 *
    1717 * For latest information and updates, access:
    18  * http://igs.ifag.de/index_ntrip.htm
     18 * http://igs.bkg.bund.de/index_ntrip_down.htm
    1919 *
    20  * Georg Weber
    21  * BKG, Frankfurt, Germany, June 2003-06-13
     20 * BKG, Frankfurt, Germany, February 2007
    2221 * E-mail: euref-ip@bkg.bund.de
    23  *
    24  * Based on the GNU General Public License published nmead
    2522 *
    2623 * This program is free software; you can redistribute it and/or
     
    3633 * You should have received a copy of the GNU General Public License
    3734 * along with this program; if not, write to the Free Software
    38  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
    39  * USA.
     35 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    4036 */
    4137
    4238/* CVS revision and version */
    43 static char revisionstr[] = "$Revision: 1.27 $";
    44 static char datestr[]     = "$Date: 2007/05/16 14:16:21 $";
     39static char revisionstr[] = "$Revision: 1.28 $";
     40static char datestr[]     = "$Date: 2007/06/06 09:44:27 $";
    4541
    4642#include <ctype.h>
     
    5955#include <sys/termios.h>
    6056#include <sys/types.h>
     57#include <sys/time.h>
    6158
    6259#ifndef COMPILEDATE
     
    7269
    7370enum MODE { SERIAL = 1, TCPSOCKET = 2, INFILE = 3, SISNET = 4, UDPSOCKET = 5,
    74 CASTER = 6, LAST};
     71CASTER = 6, LAST };
     72
     73enum OUTMODE { NTRIPV1, HTTP, RTSP, END };
    7574
    7675#define AGENTSTRING     "NTRIP NtripServerLinux"
    7776#define BUFSZ           1024
     77#define SZ              64
    7878
    7979/* default socket source */
     
    9191#define ALARMTIME       60
    9292
     93#define RTP_VERSION     2
     94#define TIME_RESOLUTION 125
     95
    9396static int ttybaud             = 19200;
    9497static const char *ttyport     = "/dev/gps";
    9598static const char *filepath    = "/dev/stdin";
    96 static enum MODE mode          = INFILE;
     99static enum MODE inputmode     = INFILE;
    97100static int sisnet              = 31;
    98101static int gpsfd               = -1;
     102static int sigint_received     = 0;
    99103
    100104/* Forward references */
    101 static int openserial(const char * tty, int blocksz, int baud);
    102 static void send_receive_loop(int sock, int fd);
    103 static void usage(int, char*);
    104 static int encode(char *buf, int size, const char *user, const char *pwd);
     105static int  openserial(const char * tty, int blocksz, int baud);
     106static void send_receive_loop(int sock, int fd, int outmode,
     107  struct sockaddr * pcasterRTP, socklen_t length);
     108static void usage(int, char *);
     109static int  encode(char *buf, int size, const char *user, const char *pwd);
     110static int  send_to_caster(char *input, int socket, int input_size);
     111static void close_session(int sock_udp, int sock_tcp,
     112  const char *caster_addr, const char *mountpoint, int cseq,
     113  int session, char *rtsp_ext, int in_fd);
     114
     115/* Signal Handling */
     116static void handle_sigint(int sig);
     117static void setup_signal_handler(int sig, void (*handler)(int));
     118static int  signal_was_caught(void);
    105119
    106120#ifdef __GNUC__
     
    135149int main(int argc, char **argv)
    136150{
    137   int c;
    138   int size = 2048;              /* for setting send buffer size */
    139 
    140   const char *inhost = 0;
    141   const char *outhost = 0;
    142   unsigned int outport = 0;
    143   unsigned int inport = 0;
    144   const char *mountpoint = NULL;
    145   const char *password = "";
    146   const char *sisnetpassword = "";
    147   const char *sisnetuser = "";
    148  
    149   const char *stream_name=0;
    150   const char *stream_user=0;
    151   const char *stream_password=0;
    152  
    153   const char *initfile = NULL;
    154  
    155   const char *recvrid=0;
    156   const char *recvrpwd=0;
    157  
    158   int bindmode = 0;
    159   int sock_id;
    160   char szSendBuffer[BUFSZ];
    161   int nBufferBytes;
    162   struct hostent *he;
    163   struct sockaddr_in addr;
     151  int                c;
     152  int                size = 2048; /* for setting send buffer size */
     153  struct             sockaddr_in caster;
     154  const char *       proxyhost = "";
     155  unsigned int       proxyport = 0;
     156  /*** INPUT ***/
     157  const char *       casterinhost = 0;
     158  unsigned int       casterinport = 0;
     159  const char *       inhost = 0;
     160  unsigned int       inport = 0;
     161
     162  char               get_extension[SZ] = "";
     163
     164  struct hostent *   he;
     165  const char *       mountpoint = NULL;
     166
     167  const char *       sisnetpassword = "";
     168  const char *       sisnetuser = "";
     169
     170  const char *       stream_name = 0;
     171  const char *       stream_user = 0;
     172  const char *       stream_password = 0;
     173
     174  const char *       recvrid= 0;
     175  const char *       recvrpwd = 0;
     176
     177  const char *       initfile = NULL;
     178
     179  int                bindmode = 0;
     180
     181  /*** OUTPUT ***/
     182  const char *       casterouthost = 0;
     183  unsigned int       casteroutport = 0;
     184  const char *       outhost = 0;
     185  unsigned int       outport = 0;
     186  char               post_extension[SZ] = "";
     187  char               rtsp_extension[SZ] = "";
     188
     189  const char *       ntrip_str = "";
     190
     191  const char *       user = "";
     192  const char *       password = "";
     193
     194  int                socket_tcp = 0;
     195  int                outputmode = NTRIPV1;
     196
     197  struct sockaddr_in casterRTP;
     198  struct sockaddr_in local;
     199  int                socket_udp = 0;
     200  int                client_port = 0;
     201  int                server_port = 0;
     202  int                session = 0;
     203  int                cseq = 0;
     204  socklen_t          len = 0;
     205  int                i = 0;
     206
     207  char               szSendBuffer[BUFSZ];
     208  char               authorization[SZ];
     209  int                nBufferBytes = 0;
     210  char *             dlim = " \r\n=";
     211  char *             token;
     212  char *             tok_buf[BUFSZ];
    164213
    165214  setbuf(stdout, 0);
     
    167216  setbuf(stderr, 0);
    168217
     218  {
    169219  char *a;
    170220  int i = 0;
     
    182232  datestr[4] = datestr[7] = '-';
    183233  datestr[10] = 0;
    184 
     234  }
     235
     236  /* setup signal handler for timeout */
    185237  signal(SIGALRM,sighandler_alarm);
    186238  alarm(ALARMTIME);
     239
    187240  /* get and check program arguments */
    188241  if(argc <= 1)
     
    191244    exit(1);
    192245  }
    193   while((c = getopt(argc, argv, "M:i:h:b:p:s:a:m:c:H:P:f:x:y:l:u:V:D:U:W:B"))
    194   != EOF)
     246  while((c = getopt(argc, argv,
     247  "M:i:h:b:p:s:a:m:c:H:P:f:x:y:l:u:V:D:U:W:B:O:E:F:N:n:")) != EOF)
    195248  {
    196249    switch (c)
    197250    {
    198     case 'M':
    199       if(!strcmp(optarg, "serial")) mode = SERIAL;
    200       else if(!strcmp(optarg, "tcpsocket")) mode = TCPSOCKET;
    201       else if(!strcmp(optarg, "file")) mode = INFILE;
    202       else if(!strcmp(optarg, "sisnet")) mode = SISNET;
    203       else if(!strcmp(optarg, "udpsocket")) mode = UDPSOCKET;
    204       else if(!strcmp(optarg, "caster")) mode = CASTER;
    205       else mode = atoi(optarg);
    206       if((mode == 0) || (mode >= LAST))
    207       {
    208         fprintf(stderr, "ERROR: can't convert %s to a valid mode\n", optarg);
     251    case 'M': /*** InputMode ***/
     252      if(!strcmp(optarg, "serial"))         inputmode = SERIAL;
     253      else if(!strcmp(optarg, "tcpsocket")) inputmode = TCPSOCKET;
     254      else if(!strcmp(optarg, "file"))      inputmode = INFILE;
     255      else if(!strcmp(optarg, "sisnet"))    inputmode = SISNET;
     256      else if(!strcmp(optarg, "udpsocket")) inputmode = UDPSOCKET;
     257      else if(!strcmp(optarg, "caster"))    inputmode = CASTER;
     258      else inputmode = atoi(optarg);
     259      if((inputmode == 0) || (inputmode >= LAST))
     260      {
     261        fprintf(stderr, "ERROR: can't convert <%s> to a valid InputMode\n",
     262        optarg);
    209263        usage(-1, argv[0]);
    210264      }
    211265      break;
    212     case 'i':                  /* gps serial ttyport */
     266    case 'i': /* serial input device */
    213267      ttyport = optarg;
    214268      break;
    215     case 'B':
     269    case 'B': /* bind to incoming UDP stream */
    216270      bindmode = 1;
    217271      break;
    218     case 'V':
    219       if(!strcmp("3.0", optarg)) sisnet = 30;
     272    case 'V': /* Sisnet data server version number */
     273      if(!strcmp("3.0", optarg))      sisnet = 30;
    220274      else if(!strcmp("3.1", optarg)) sisnet = 31;
    221275      else if(!strcmp("2.1", optarg)) sisnet = 21;
    222276      else
    223277      {
    224         fprintf(stderr, "ERROR: unknown SISNeT version %s\n", optarg);
     278        fprintf(stderr, "ERROR: unknown SISNeT version <%s>\n", optarg);
    225279        usage(-2, argv[0]);
    226280      }
    227281      break;
    228     case 'b':                  /* serial ttyin speed */
     282    case 'b': /* serial input baud rate */
    229283      ttybaud = atoi(optarg);
    230284      if(ttybaud <= 1)
    231285      {
    232         fprintf(stderr, "ERROR: can't convert %s to valid serial speed\n",
     286        fprintf(stderr, "ERROR: can't convert <%s> to valid serial baud rate\n",
    233287          optarg);
    234288        usage(1, argv[0]);
    235289      }
    236290      break;
    237     case 'a':                  /* http server IP address A.B.C.D */
    238       outhost = optarg;
    239       break;
    240     case 'p':                  /* http server port */
    241       outport = atoi(optarg);
    242       if(outport <= 1 || outport > 65535)
     291    case 'a': /* Destination caster address */
     292      casterouthost = optarg;
     293      break;
     294    case 'p': /* Destination caster port */
     295      casteroutport = atoi(optarg);
     296      if(casteroutport <= 1 || casteroutport > 65535)
    243297      {
    244298        fprintf(stderr,
    245           "ERROR: can't convert %s to a valid HTTP server port\n", optarg);
     299          "ERROR: can't convert <%s> to a valid HTTP server port\n", optarg);
    246300        usage(1, argv[0]);
    247301      }
    248302      break;
    249     case 'm':                  /* http server mountpoint */
     303    case 'm': /* Destination caster mountpoint for stream upload */
    250304      mountpoint = optarg;
    251305      break;
    252     case 's':                  /* datastream from file */
     306    case 's': /* File name for input data simulation from file */
    253307      filepath = optarg;
    254308      break;
    255     case 'f':
     309    case 'f': /* name of an initialization file */
    256310      initfile = optarg;
    257311      break;
    258     case 'x':
    259       recvrid = optarg; 
    260       break;     
    261     case 'y':
    262       recvrpwd = optarg; 
    263       break;           
    264     case 'u':
     312    case 'x': /* user ID to access incoming stream */
     313      recvrid = optarg;
     314      break;
     315    case 'y': /* password to access incoming stream */
     316      recvrpwd = optarg;
     317      break;
     318    case 'u': /* Sisnet data server user ID */
    265319      sisnetuser = optarg;
    266320      break;
    267     case 'l':
     321    case 'l': /* Sisnet data server password */
    268322      sisnetpassword = optarg;
    269323      break;
    270     case 'c':                  /* DestinationCasterPassword */
     324    case 'c': /* DestinationCaster password for stream upload to mountpoint */
    271325      password = optarg;
    272326      break;
    273     case 'H':                  /* SourceCasterHost */
    274       inhost = optarg;
    275       break;
    276     case 'P':                  /* SourceCasterPort */
    277       inport = atoi(optarg);
    278       if(inport <= 1 || inport > 65535)
    279       {
    280         fprintf(stderr, "ERROR: can't convert %s to a valid port number\n",
     327    case 'H': /* Input host address*/
     328      casterinhost = optarg;
     329      break;
     330    case 'P': /* Input port */
     331      casterinport = atoi(optarg);
     332      if(casterinport <= 1 || casterinport > 65535)
     333      {
     334        fprintf(stderr, "ERROR: can't convert <%s> to a valid port number\n",
    281335          optarg);
    282336        usage(1, argv[0]);
    283337      }
    284338      break;
    285     case 'D':
    286      stream_name=optarg;        /* desired stream from SourceCaster */
    287      break;
    288     case 'U':
    289      stream_user=optarg;        /* username for desired stream */
     339    case 'D': /* Source caster mountpoint for stream input */
     340     stream_name = optarg;
    290341     break;
    291     case 'W':
    292      stream_password=optarg;    /* passwd for desired stream */
     342    case 'U': /* Source caster user ID for input stream access */
     343     stream_user = optarg;
    293344     break;
    294     case 'h':                  /* help */
     345    case 'W': /* Source caster password for input stream access */
     346     stream_password = optarg;
     347     break;
     348    case 'E': /* Proxy Server */
     349      proxyhost = optarg;
     350      break;
     351    case 'F': /* Proxy port */
     352      proxyport = atoi(optarg);
     353      break;
     354    case 'O': /* OutputMode - default: Ntrip-Version 2.0 TCP/IP */
     355      if     (!strcmp(optarg,"f")) outputmode = NTRIPV1;
     356      else if(!strcmp(optarg,"r")) outputmode = RTSP;
     357      break;
     358    case 'n': /* Destination caster user ID for stream upload to mountpoint */
     359      user = optarg;
     360      break;
     361    case 'N': /* Ntrip-STR, optional for Ntrip Version 2.0 */
     362      ntrip_str = optarg;
     363      break;
     364    case 'h': /* print help screen */
    295365    case '?':
    296366      usage(0, argv[0]);
     
    305375  argv += optind;
    306376
     377  /*** argument analysis ***/
    307378  if(argc > 0)
    308379  {
     
    316387  }
    317388
    318   if(mountpoint == NULL)
    319   {
    320     fprintf(stderr, "ERROR: Missing mountpoint argument\n");
     389  if(*ntrip_str && (outputmode == NTRIPV1))
     390  {
     391     fprintf(stderr, "WARNING: OutputMode is Ntrip version 1.0"
     392     " - Ntrip-STR will not be considered\n");
     393  }
     394
     395  if(!mountpoint)
     396  {
     397    fprintf(stderr, "ERROR: Missing mountpoint argument for stream upload\n");
    321398    exit(1);
    322399  }
     400
    323401  if(!password[0])
    324402  {
    325     fprintf(stderr,
    326       "WARNING: Missing password argument - are you really sure?\n");
     403    fprintf(stderr, "WARNING: Missing password argument for stream upload - "
     404    "are you really sure?\n");
     405  }
     406  else
     407  {
     408    nBufferBytes += encode(authorization, sizeof(authorization), user,
     409    password);
     410    if(nBufferBytes > (int)sizeof(authorization))
     411    {
     412      fprintf(stderr, "ERROR: user ID and/or password too long: %d (%d)\n"
     413      "       user ID: %s \npassword: <%s>\n",
     414      nBufferBytes, (int)sizeof(authorization), user, password);
     415      exit(1);
     416    }
    327417  }
    328418
    329419  if(stream_name && stream_user && !stream_password)
    330420  {
    331     fprintf(stderr, "WARNING: Missing password argument for download"
     421    fprintf(stderr, "WARNING: Missing password argument for stream download"
    332422      " - are you really sure?\n");
    333423  }
    334424
    335   if(!outhost) outhost = NTRIP_CASTER;
    336   if(!outport) outport = NTRIP_PORT;
    337 
    338   switch(mode)
     425  /*** proxy server handling ***/
     426  if(*proxyhost)
     427  {
     428    outhost = inhost = proxyhost;
     429    outport = inport = proxyport;
     430    i = snprintf(szSendBuffer, sizeof(szSendBuffer),"http://%s:%d",
     431    casterouthost, casteroutport);
     432    if((i > SZ) || (i < 0))
     433    {
     434      fprintf(stderr, "ERROR: Destination caster name/port to long - "
     435      "length = %d (max: %d)\n", i, SZ);
     436      exit(0);
     437    }
     438    else
     439    {
     440      strncpy(post_extension, szSendBuffer, (size_t)i);
     441      strcpy(szSendBuffer, "");
     442      i = snprintf(szSendBuffer, sizeof(szSendBuffer),":%d", casteroutport);
     443      strncpy(rtsp_extension, szSendBuffer, SZ);
     444      strcpy(szSendBuffer,""); i = 0;
     445    }
     446    i = snprintf(szSendBuffer, sizeof(szSendBuffer),"http://%s:%d", casterinhost, casterinport);
     447    if((i > SZ) || (i < 0))
     448    {
     449      fprintf(stderr, "ERROR: Destination caster name/port to long - length = %d (max: %d)\n", i, SZ);
     450      exit(0);
     451    }
     452    else
     453    {
     454      strncpy(get_extension, szSendBuffer, (size_t)i);
     455      strcpy(szSendBuffer, "");
     456      i = 0;
     457    }
     458  }
     459  else
     460  {
     461    outhost   = casterouthost; outport = casteroutport;
     462    inhost    = casterinhost;  inport  = casterinport;
     463  }
     464
     465  /*** InputMode handling ***/
     466  switch(inputmode)
    339467  {
    340468  case INFILE:
     
    345473        exit(1);
    346474      }
    347       /* set blocking mode in case it was not set
     475      /* set blocking inputmode in case it was not set
    348476        (seems to be sometimes for fifo's) */
    349477      fcntl(gpsfd, F_SETFL, 0);
     
    351479    }
    352480    break;
    353   case SERIAL:                 /* open serial port */
     481  case SERIAL: /* open serial port */
    354482    {
    355483      gpsfd = openserial(ttyport, 1, ttybaud);
     
    363491  case TCPSOCKET: case UDPSOCKET: case SISNET: case CASTER:
    364492    {
    365       if(mode == SISNET)
     493      if(inputmode == SISNET)
    366494      {
    367495        if(!inhost) inhost = SISNET_SERVER;
    368496        if(!inport) inport = SISNET_PORT;
    369497      }
    370       else if(mode == CASTER)
     498      else if(inputmode == CASTER)
    371499      {
    372500        if(!inport) inport = NTRIP_PORT;
    373501        if(!inhost) inhost = NTRIP_CASTER;
    374502      }
    375       else if((mode == TCPSOCKET) || (mode == UDPSOCKET))
     503      else if((inputmode == TCPSOCKET) || (inputmode == UDPSOCKET))
    376504      {
    377505        if(!inport) inport = SERV_TCP_PORT;
    378506        if(!inhost) inhost = "127.0.0.1";
    379       }     
     507      }
    380508
    381509      if(!(he = gethostbyname(inhost)))
    382510      {
    383         fprintf(stderr, "ERROR: host %s unknown\n", inhost);
     511        fprintf(stderr, "ERROR: Input host <%s> unknown\n", inhost);
    384512        usage(-2, argv[0]);
    385513      }
    386514
    387       if((gpsfd = socket(AF_INET, mode == UDPSOCKET
     515      if((gpsfd = socket(AF_INET, inputmode == UDPSOCKET
    388516      ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
    389517      {
    390         fprintf(stderr, "ERROR: can't create socket\n");
     518        fprintf(stderr,
     519        "ERROR: can't create socket for incoming data stream\n");
    391520        exit(1);
    392521      }
    393522
    394       memset((char *) &addr, 0x00, sizeof(addr));
     523      memset((char *) &caster, 0x00, sizeof(caster));
    395524      if(!bindmode)
    396         memcpy(&addr.sin_addr, he->h_addr, (size_t)he->h_length);
    397       addr.sin_family = AF_INET;
    398       addr.sin_port = htons(inport);
    399 
    400       printf("%s input: host = %s, port = %d, %s%s%s%s%s\n",
    401       mode == CASTER ? "caster" : mode == SISNET ? "sisnet" :
    402       mode == TCPSOCKET ? "tcp socket" : "udp socket",
    403       bindmode ? "127.0.0.1" : inet_ntoa(addr.sin_addr),
     525        memcpy(&caster.sin_addr, he->h_addr, (size_t)he->h_length);
     526      caster.sin_family = AF_INET;
     527      caster.sin_port = htons(inport);
     528
     529      fprintf(stderr, "%s input: host = %s, port = %d, %s%s%s%s%s\n",
     530      inputmode == CASTER ? "caster" : inputmode == SISNET ? "sisnet" :
     531      inputmode == TCPSOCKET ? "tcp socket" : "udp socket",
     532      bindmode ? "127.0.0.1" : inet_ntoa(caster.sin_addr),
    404533      inport, stream_name ? "stream = " : "", stream_name ? stream_name : "",
    405534      initfile ? ", initfile = " : "", initfile ? initfile : "",
     
    408537      if(bindmode)
    409538      {
    410         if(bind(gpsfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
     539        if(bind(gpsfd, (struct sockaddr *) &caster, sizeof(caster)) < 0)
    411540        {
    412541          fprintf(stderr, "ERROR: can't bind input to port %d\n", inport);
    413542          exit(1);
    414543        }
    415       }
    416       else if(connect(gpsfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
     544      } /* connect to input-caster or proxy server*/
     545      else if(connect(gpsfd, (struct sockaddr *)&caster, sizeof(caster)) < 0)
    417546      {
    418547        fprintf(stderr, "ERROR: can't connect input to %s at port %d\n",
    419           inet_ntoa(addr.sin_addr), inport);
     548        inet_ntoa(caster.sin_addr), inport);
    420549        exit(1);
    421550      }
    422            
    423       if(stream_name) /* data stream from caster */
     551
     552      if(stream_name) /* input from Ntrip Version 1.0 caster*/
    424553      {
    425554        int init = 0;
     
    432561          /* leave some space for login */
    433562          nBufferBytes=snprintf(szSendBuffer, sizeof(szSendBuffer)-40,
    434           "GET /%s HTTP/1.0\r\n"
     563          "GET %s/%s HTTP/1.0\r\n"
    435564          "User-Agent: %s/%s\r\n"
    436           "Authorization: Basic ", stream_name, AGENTSTRING, revisionstr);
     565          "Authorization: Basic ", get_extension, stream_name,
     566          AGENTSTRING, revisionstr);
    437567          /* second check for old glibc */
    438568          if(nBufferBytes > (int)sizeof(szSendBuffer)-40 || nBufferBytes < 0)
    439569          {
    440             fprintf(stderr, "Requested data too long\n");
     570            fprintf(stderr, "ERROR: Source caster request too long\n");
    441571            exit(1);
    442572          }
     
    445575          if(nBufferBytes > (int)sizeof(szSendBuffer)-4)
    446576          {
    447             fprintf(stderr, "Username and/or password too long\n");
     577            fprintf(stderr,
     578            "ERROR: Source caster user ID and/or password too long\n");
    448579            exit(1);
    449580          }
     
    456587        {
    457588          nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
    458           "GET /%s HTTP/1.0\r\n"
     589          "GET %s/%s HTTP/1.0\r\n"
    459590          "User-Agent: %s/%s\r\n"
    460           "\r\n", stream_name, AGENTSTRING, revisionstr);
     591          "\r\n", get_extension, stream_name, AGENTSTRING, revisionstr);
    461592        }
    462593        if((send(gpsfd, szSendBuffer, (size_t)nBufferBytes, 0))
    463594        != nBufferBytes)
    464595        {
    465           fprintf(stderr, "ERROR: could not send to caster\n");
     596          fprintf(stderr, "ERROR: could not send Source caster request\n");
    466597          exit(1);
    467598        }
    468599        nBufferBytes = 0;
    469         /* check caster's response */
     600        /* check Source caster's response */
    470601        while(!init && nBufferBytes < (int)sizeof(szSendBuffer)
    471602        && (nBufferBytes += recv(gpsfd, szSendBuffer,
     
    479610            {
    480611              int k;
    481               fprintf(stderr, "Could not get the requested data: ");
     612              fprintf(stderr,
     613              "ERROR: could not get requested data from Source caster: ");
    482614              for(k = 0; k < nBufferBytes && szSendBuffer[k] != '\n'
    483615              && szSendBuffer[k] != '\r'; ++k)
     
    493625        if(!init)
    494626        {
    495           fprintf(stderr, "Could not init caster download.");
     627          fprintf(stderr, "ERROR: could not init Source caster download\n");
    496628          exit(1);
    497629        }
    498       } /* end data stream from caster */
    499 
    500       if(initfile && mode != SISNET)
     630      } /* end input from Ntrip Version 1.0 caster */
     631
     632      if(initfile && inputmode != SISNET)
    501633      {
    502634        char buffer[1024];
     
    523655        else
    524656        {
    525           fprintf(stderr, "ERROR: can't read init file %s\n", initfile);
     657          fprintf(stderr, "ERROR: can't read init file <%s>\n", initfile);
    526658          exit(1);
    527659        }
    528660      }
    529661    }
    530     if(mode == SISNET)
     662    if(inputmode == SISNET)
    531663    {
    532664      int i, j;
     
    537669      if((send(gpsfd, buffer, (size_t)i, 0)) != i)
    538670      {
    539         perror("ERROR: sending authentication");
     671        perror("ERROR: sending authentication for SISNeT data server");
    540672        exit(1);
    541673      }
     
    558690        if((send(gpsfd, "START\r\n", 7, 0)) != i)
    559691        {
    560           perror("ERROR: sending start command");
     692          perror("ERROR: sending Sisnet start command");
    561693          exit(1);
    562694        }
    563695      }
    564696    }
    565 
    566     if (recvrid && recvrpwd && ((mode == TCPSOCKET) || (mode == UDPSOCKET)))
    567     {
    568       if (strlen(recvrid) > (BUFSZ-3)){
    569         fprintf(stderr, "Receiver ID too long\n"); exit(0);
    570       }else{
     697    /*** receiver authentication  ***/
     698    if (recvrid && recvrpwd && ((inputmode == TCPSOCKET)
     699    || (inputmode == UDPSOCKET)))
     700    {
     701      if (strlen(recvrid) > (BUFSZ-3))
     702      {
     703        fprintf(stderr, "ERROR: Receiver ID too long\n");
     704        exit(0);
     705      }
     706      else
     707      {
    571708        fprintf(stderr, "Sending user ID for receiver...\n");
    572         nBufferBytes = read(gpsfd, szSendBuffer, BUFSZ);     
     709        nBufferBytes = read(gpsfd, szSendBuffer, BUFSZ);
    573710        strcpy(szSendBuffer, recvrid);
    574711        strcat(szSendBuffer,"\r\n");
    575712        send(gpsfd,szSendBuffer, strlen(szSendBuffer), MSG_DONTWAIT);
    576713      }
    577      
    578       if (strlen(recvrpwd) > (BUFSZ-3)){
    579         fprintf(stderr, "Receiver password too long\n"); exit(0);
    580       }else{
     714
     715      if (strlen(recvrpwd) > (BUFSZ-3))
     716      {
     717        fprintf(stderr, "ERROR: Receiver password too long\n");
     718        exit(0);
     719      }
     720      else
     721      {
    581722        fprintf(stderr, "Sending user password for receiver...\n");
    582723        nBufferBytes = read(gpsfd, szSendBuffer, BUFSZ);
    583724        strcpy(szSendBuffer, recvrpwd);
    584725        strcat(szSendBuffer,"\r\n");
    585         send(gpsfd, szSendBuffer, strlen(szSendBuffer), MSG_DONTWAIT);   
    586       }
    587     }     
     726        send(gpsfd, szSendBuffer, strlen(szSendBuffer), MSG_DONTWAIT);
     727      }
     728    }
    588729    break;
    589730  default:
     
    593734
    594735  /* ----- main part ----- */
    595   for(;;)
    596   {
     736  /* setup signal handler for CTRL+C */
     737  setup_signal_handler(SIGINT,  handle_sigint);
     738
     739  while(outputmode != END)
     740  {
     741    if(signal_was_caught())
     742    {
     743      fprintf(stderr, "NtripLinuxServer terminates\n");
     744      break;
     745    }
     746
    597747    if(!(he = gethostbyname(outhost)))
    598748    {
    599       fprintf(stderr, "ERROR: host %s unknown\n", outhost);
     749      fprintf(stderr, "ERROR: Destination caster or proxy host <%s> unknown\n",
     750      outhost);
    600751      usage(-2, argv[0]);
    601752    }
    602753
    603754    /* create socket */
    604     if((sock_id = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    605     {
    606       fprintf(stderr, "ERROR: could not create socket\n");
     755    if((socket_tcp = socket(AF_INET, SOCK_STREAM, 0)) < 0)
     756    {
     757      perror("ERROR: tcp socket");
    607758      exit(2);
    608759    }
    609760
    610     memset((char *) &addr, 0x00, sizeof(addr));
    611     memcpy(&addr.sin_addr, he->h_addr, (size_t)he->h_length);
    612     addr.sin_family = AF_INET;
    613     addr.sin_port = htons(outport);
    614 
    615     /* connect to caster */
     761    memset((char *) &caster, 0x00, sizeof(caster));
     762    memcpy(&caster.sin_addr, he->h_addr, (size_t)he->h_length);
     763    caster.sin_family = AF_INET;
     764    caster.sin_port = htons(outport);
     765
     766    /* connect to Destination caster or Proxy server*/
    616767    fprintf(stderr, "caster output: host = %s, port = %d, mountpoint = %s\n",
    617       inet_ntoa(addr.sin_addr), outport, mountpoint);
    618     if(connect(sock_id, (struct sockaddr *) &addr, sizeof(addr)) < 0)
     768    inet_ntoa(caster.sin_addr), outport, mountpoint);
     769
     770    if(connect(socket_tcp, (struct sockaddr *) &caster, sizeof(caster)) < 0)
    619771    {
    620772      fprintf(stderr, "ERROR: can't connect output to %s at port %d\n",
    621         inet_ntoa(addr.sin_addr), outport);
    622       close(sock_id);
     773        inet_ntoa(caster.sin_addr), outport);
     774      if(close(socket_tcp)==-1) perror("ERROR: close tcp socket");
    623775      exit(3);
    624776    }
    625777
    626     /* set socket buffer size */
    627     setsockopt(sock_id, SOL_SOCKET, SO_SNDBUF, (const char *) &size,
    628       sizeof(const char *));
    629     /* send message to caster */
    630     nBufferBytes = sprintf(szSendBuffer, "SOURCE %s /%s\r\nSource-Agent: "
    631     "%s/%s\r\n\r\n", password, mountpoint, AGENTSTRING, revisionstr);
    632     if((send(sock_id, szSendBuffer, (size_t)nBufferBytes, 0)) != nBufferBytes)
    633     {
    634       fprintf(stderr, "ERROR: could not send to caster\n");
    635       break;
    636     }
    637     /* check caster's response */
    638     nBufferBytes = recv(sock_id, szSendBuffer, sizeof(szSendBuffer), 0);
    639     szSendBuffer[nBufferBytes] = '\0';
    640     if(!strstr(szSendBuffer, "OK"))
    641     {
    642       char *a;
    643       fprintf(stderr, "ERROR: caster's reply is not OK : ");
    644       for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
    645       {
    646         fprintf(stderr, "%.1s", isprint(*a) ? a : ".");
    647       }
    648       fprintf(stderr, "\n");
    649       break;
    650     }
    651     printf("connection successfull\n");
    652     send_receive_loop(sock_id, gpsfd);
    653   }
    654   close(sock_id);
    655   sleep(5);
     778    /*** OutputMode handling ***/
     779    switch(outputmode){
     780      case NTRIPV1: /*** OutputMode Ntrip Version 1.0 ***/
     781        nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
     782          "SOURCE %s %s/%s\r\n"
     783          "Source-Agent: %s\r\n\r\n",
     784          password, post_extension, mountpoint, AGENTSTRING);
     785        if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
     786        {
     787          fprintf(stderr, "ERROR: Destination caster request to long\n");
     788          outputmode = END;
     789          break;
     790        }
     791        if(!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
     792        {
     793          outputmode = END;
     794          break;
     795        }
     796        /* check Destination caster's response */
     797        nBufferBytes = recv(socket_tcp, szSendBuffer, sizeof(szSendBuffer), 0);
     798        szSendBuffer[nBufferBytes] = '\0';
     799        if(!strstr(szSendBuffer, "OK"))
     800        {
     801          char *a;
     802          fprintf(stderr,
     803          "ERROR: Destination caster's or Proxy's reply is not OK: ");
     804          for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
     805          {
     806            fprintf(stderr, "%.1s", isprint(*a) ? a : ".");
     807          }
     808          fprintf(stderr, "\n");
     809          outputmode = END;
     810          break;
     811        }
     812        else
     813        {
     814          fprintf(stderr,
     815          "Destination caster response:\n%s\nconnection successfull\n",
     816          szSendBuffer);
     817        }
     818        send_receive_loop(socket_tcp, gpsfd, outputmode, NULL, 0);
     819        break;
     820      case HTTP: /*** Ntrip-Version 2.0 HTTP/1.1 ***/
     821        nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
     822          "POST %s/%s HTTP/1.1\r\n"
     823          "Host: %s\r\n"
     824          "Ntrip-Version: Ntrip/2.0\r\n"
     825          "User-Agent: NTRIP %s\r\n"
     826          "Authorization: Basic %s\r\n"
     827          "Ntrip-STR: %s\r\n"
     828          "Transfer-Encoding: chunked\r\n\r\n",
     829          post_extension, mountpoint, casterouthost, AGENTSTRING,
     830          authorization, ntrip_str);
     831        if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
     832        {
     833          fprintf(stderr, "ERROR: Destination caster request to long\n");
     834          outputmode = END;
     835          break;
     836        }
     837        if (!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
     838        {
     839          outputmode = END;
     840          break;
     841        }
     842        /* check Destination caster's response */
     843        nBufferBytes = recv(socket_tcp, szSendBuffer, sizeof(szSendBuffer), 0);
     844        szSendBuffer[nBufferBytes] = '\0';
     845        if(!strstr(szSendBuffer, "HTTP/1.1 200 OK"))
     846        {
     847          char *a;
     848          fprintf(stderr,
     849          "ERROR: Destination caster's or Proxy's reply is not OK: ");
     850          for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
     851          {
     852            fprintf(stderr, "%.1s", isprint(*a) ? a : ".");
     853          }
     854          fprintf(stderr, "\n");
     855          /* fallback if necessary */
     856          if(!strstr(szSendBuffer,"Ntrip-Version: Ntrip/2.0\r\n"))
     857          {
     858            fprintf(stderr,
     859            " - Ntrip Version 2.0 not implemented at Destination caster"
     860            " <%s> or Proxy <%s> or\n"
     861            " - HTTP/1.1 not implemented at Proxy or\n"
     862            " - RTSP/1.0 not implemented at Destination caster or Proxy\n\n"
     863            "caster fallback: Fallback to Ntrip Version 1.0\n\n",
     864            casterouthost, proxyhost);
     865            outputmode = NTRIPV1;
     866            break;
     867          }
     868          outputmode = END;
     869          break;
     870        }
     871        else
     872        {
     873          fprintf(stderr, "Destination caster response:\n%s\n"
     874          "connection successfull\n",szSendBuffer);
     875        }
     876        send_receive_loop(socket_tcp, gpsfd, outputmode, NULL, 0);
     877        break;
     878      case RTSP: /*** Ntrip-Version 2.0 RTSP / RTP ***/
     879        if((socket_udp = socket(AF_INET, SOCK_DGRAM,0)) < 0)
     880        {
     881          perror("ERROR: udp socket");
     882          exit(4);
     883        }
     884        /* fill structure with local address information for UDP */
     885        memset(&local, 0, sizeof(local));
     886        local.sin_family = AF_INET;
     887        local.sin_port = htons(0);
     888        local.sin_addr.s_addr = htonl(INADDR_ANY);
     889        len = (socklen_t)sizeof(local);
     890        /* bind() in order to get a random RTP client_port */
     891        if((bind(socket_udp,(struct sockaddr *)&local, len)) < 0)
     892        {
     893          perror("ERROR: udp bind");
     894          if(close(socket_udp)==-1) perror("ERROR: close udp socket");
     895          if(close(socket_tcp)==-1) perror("ERROR: close tcp socket");
     896          exit(4);
     897        }
     898        if((getsockname(socket_udp, (struct sockaddr*)&local, &len)) != -1)
     899        {
     900          client_port = (unsigned int)ntohs(local.sin_port);
     901        }else{
     902          perror("ERROR: getsockname(localhost)");
     903          if(close(socket_udp)==-1) perror("ERROR: close udp socket");
     904          if(close(socket_tcp)==-1) perror("ERROR: close tcp socket");
     905          exit(4);
     906        }
     907        nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
     908          "SETUP rtsp://%s%s/%s RTSP/1.0\r\n"
     909          "CSeq: 1\r\n"
     910          "Ntrip-Version: Ntrip/2.0\r\n"
     911          "Ntrip-Component: Ntripserver\r\n"
     912          "User-Agent: NTRIP %s \r\n"
     913          "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
     914          "Authorization: Basic %s\r\n"
     915          "Ntrip-STR: %s\r\n\r\n",
     916          casterouthost, rtsp_extension, mountpoint, AGENTSTRING, client_port,
     917          authorization, ntrip_str);
     918        if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
     919        {
     920          fprintf(stderr, "ERROR: Destination caster request to long\n");
     921          outputmode = END;
     922          break;
     923        }
     924        if (!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
     925        {
     926          outputmode = END;
     927          break;
     928        }
     929        while((nBufferBytes = recv(socket_tcp, szSendBuffer,
     930        sizeof(szSendBuffer), 0)) > 0)
     931        {
     932          /* check Destination caster's response */
     933          szSendBuffer[nBufferBytes] = '\0';
     934          if(!strstr(szSendBuffer, "RTSP/1.0 200 OK"))
     935          {
     936            char *a;
     937            fprintf(stderr,
     938            "ERROR: Destination caster's or Proxy's reply is not OK: ");
     939            for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
     940            {
     941              fprintf(stderr, "%c", isprint(*a) ? *a : '.');
     942            }
     943            fprintf(stderr, "\n");
     944            /* fallback if necessary */
     945            if(strncmp(szSendBuffer, "RTSP",4) != 0)
     946            {
     947              if(strstr(szSendBuffer,"Ntrip-Version: Ntrip/2.0\r\n"))
     948              {
     949                fprintf(stderr,
     950                " - RTSP not implemented at Destination caster <%s> or"
     951                " Proxy <%s>\n\n"
     952                "caster fallback: Fallback to Ntrip Version 2.0 in TCP/IP"
     953                " mode\n\n", casterouthost, proxyhost);
     954                outputmode = HTTP;
     955                break;
     956              }
     957              else
     958              {
     959                fprintf(stderr,
     960                " - Ntrip-Version 2.0 not implemented at Destination caster"
     961                "<%s> or Proxy <%s> or\n"
     962                " - HTTP/1.1 not implemented at Proxy or\n"
     963                " - RTSP/1.0 not implemented at Destination caster or Proxy\n\n"
     964                "caster fallback: Fallback to Ntrip Version 1.0\n\n",
     965                casterouthost, proxyhost);
     966                outputmode = NTRIPV1;
     967                break;
     968              }
     969            }
     970            else
     971            {
     972              outputmode = END;
     973              break;
     974            }
     975          }
     976          else
     977          {
     978            fprintf(stderr, "Destination caster response:\n%s\n",szSendBuffer);
     979          }
     980          if((strstr(szSendBuffer,"RTSP/1.0 200 OK\r\n"))
     981          && (strstr(szSendBuffer,"CSeq: 1\r\n")))
     982          {
     983            for(token = strtok(szSendBuffer, dlim); token != NULL;
     984            token = strtok(NULL, dlim))
     985            {
     986              tok_buf[i] = token; i++;
     987            }
     988            session = atoi(tok_buf[6]);
     989            server_port = atoi(tok_buf[10]);
     990            nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
     991              "POST rtsp://%s%s/%s RTSP/1.0\r\n"
     992              "CSeq: 2\r\n"
     993              "Session: %d\r\n"
     994              "\r\n",
     995              casterouthost, rtsp_extension,  mountpoint,  session);
     996            if((nBufferBytes >= (int)sizeof(szSendBuffer))
     997            || (nBufferBytes < 0))
     998            {
     999              fprintf(stderr, "ERROR: Destination caster request to long\n");
     1000              outputmode = END;
     1001              break;
     1002            }
     1003            if(!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
     1004            {
     1005               outputmode = END;
     1006               break;
     1007            }
     1008          }else if((strstr(szSendBuffer,"RTSP/1.0 200 OK\r\n")) && (strstr(szSendBuffer,"CSeq: 2\r\n"))) {
     1009            /* fill structure with caster address information for UDP */
     1010            memset(&casterRTP, 0, sizeof(casterRTP));
     1011            casterRTP.sin_family = AF_INET;
     1012            casterRTP.sin_port   = htons(((uint16_t)server_port));
     1013            if((he = gethostbyname(outhost))== NULL) {
     1014              fprintf(stderr, "ERROR: Destination caster unknown\n");
     1015              if(close(socket_udp)==-1) perror("ERROR: close udp socket");
     1016              if(close(socket_tcp)==-1) perror("ERROR: close tcp socket");
     1017              exit(4);
     1018            }else{
     1019              memcpy((char *)&casterRTP.sin_addr.s_addr,
     1020              he->h_addr_list[0], (size_t)he->h_length);
     1021            }
     1022            cseq = 2;
     1023            len = (socklen_t)sizeof(casterRTP);
     1024            send_receive_loop(socket_udp, gpsfd, outputmode, (struct sockaddr *)&casterRTP, (socklen_t)len);
     1025            break;
     1026          }else{break;}
     1027        }
     1028        break;
     1029    }
     1030  }
     1031  close_session(socket_udp, socket_tcp, casterouthost, mountpoint, cseq, session, rtsp_extension, gpsfd);
    6561032  return 0;
    6571033}
    6581034
    659 static void send_receive_loop(int sock, int fd)
     1035static void send_receive_loop(int sock, int fd, int outmode, struct sockaddr* pcasterRTP,
     1036socklen_t length)
    6601037{
    6611038  int nodata = 0;
    6621039  char buffer[BUFSZ] = { 0 };
    6631040  char sisnetbackbuffer[200];
     1041  char szSendBuffer[BUFSZ] = "";
    6641042  int nBufferBytes = 0;
     1043
     1044   /* RTSP / RTP Mode */
     1045  int    isfirstpacket = 1;
     1046  struct timeval now;
     1047  struct timeval last = {0,0};
     1048  long int sendtimediff;
     1049  int rtpseq = 0;
     1050  int rtpssrc = 0;
     1051  int rtptime = 0;
     1052
    6651053  /* data transmission */
    666   printf("transfering data ...\n");
     1054  fprintf(stderr,"transfering data ...\n");
     1055
    6671056  while(1)
    6681057  {
     1058    /* signal handling*/
     1059    if(signal_was_caught())
     1060    {
     1061      fprintf(stderr, "NtripLinuxServer exits send-receive mode\n");
     1062      break;
     1063    }
    6691064    if(!nodata) alarm(ALARMTIME);
    6701065    else nodata = 0;
     
    6721067    if(!nBufferBytes)
    6731068    {
    674       if(mode == SISNET && sisnet <= 30)
     1069      if(inputmode == SISNET && sisnet <= 30)
    6751070      {
    6761071        int i;
     
    6831078        if((send(gpsfd, "MSG\r\n", i, 0)) != i)
    6841079        {
    685           perror("ERROR: sending data request");
     1080          perror("ERROR: sending SISNeT data request");
    6861081          exit(1);
    6871082        }
    6881083      }
    689       /* receiving data */
     1084      /*** receiving data ****/
    6901085      nBufferBytes = read(fd, buffer, sizeof(buffer));
    6911086      if(!nBufferBytes)
     
    7031098      /* we can compare the whole buffer, as the additional bytes
    7041099         remain unchanged */
    705       if(mode == SISNET && sisnet <= 30 &&
     1100      if(inputmode == SISNET && sisnet <= 30 &&
    7061101      !memcmp(sisnetbackbuffer, buffer, sizeof(sisnetbackbuffer)))
    7071102      {
     
    7091104      }
    7101105    }
    711     if(nBufferBytes)
     1106    /**  send data ***/
     1107    if((nBufferBytes)  && (outmode == NTRIPV1)) /*** Ntrip-Version 1.0 ***/
    7121108    {
    7131109      int i;
    714       /* send data */
    7151110      if((i = send(sock, buffer, (size_t)nBufferBytes, MSG_DONTWAIT))
    716         != nBufferBytes)
     1111      != nBufferBytes)
    7171112      {
    7181113        if(i < 0)
     
    7201115          if(errno != EAGAIN)
    7211116          {
    722             perror("WARNING: could not send data - retry connection");
     1117            perror("WARNING: could not send data to Destination caster"
     1118            " - retry connection");
    7231119            close(sock);
    7241120            sleep(5);
     
    7311127          nBufferBytes -= i;
    7321128        }
     1129      }else
     1130      {
     1131        nBufferBytes = 0;
     1132      }
     1133    }
     1134    /*** Ntrip-Version 2.0 HTTP/1.1 ***/
     1135    else if((nBufferBytes)  && (outmode == HTTP))
     1136    {
     1137      int i, nChunkBytes, j = 1;
     1138      nChunkBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),"%x\r\n",
     1139      nBufferBytes);
     1140      send(sock, szSendBuffer, nChunkBytes, MSG_DONTWAIT);
     1141      if((i = send(sock, buffer, (size_t)nBufferBytes, MSG_DONTWAIT))
     1142      != nBufferBytes)
     1143      {
     1144        if(i < 0)
     1145        {
     1146          if(errno != EAGAIN)
     1147          {
     1148            perror("WARNING: could not send data to Destination caster"
     1149            " - retry connection");
     1150            close(sock);
     1151            sleep(5);
     1152            return;
     1153          }
     1154        }
     1155        else if(i)
     1156        {
     1157          while(j>0)
     1158          {
     1159            j = send(sock, buffer, (size_t)BUFSZ, MSG_DONTWAIT);
     1160          }
     1161        }
    7331162      }
    7341163      else
    7351164      {
     1165        send(sock, "\r\n", strlen("\r\n"), MSG_DONTWAIT);
    7361166        nBufferBytes = 0;
    7371167      }
    7381168    }
    739   }
     1169    /*** Ntrip-Version 2.0 RTSP(TCP) / RTP(UDP) ***/
     1170    else if((nBufferBytes)  && (outmode == RTSP))
     1171    {
     1172      char rtpbuffer[BUFSZ+12];
     1173      int i, j;
     1174      /* Signal Handling */
     1175      if(signal_was_caught())
     1176      {
     1177        fprintf(stderr, "NtripLinuxServer exits send-receive mode \n");
     1178        break;
     1179      }
     1180      gettimeofday(&now, NULL);
     1181      /* RTP data packet generation*/
     1182      if(isfirstpacket){
     1183        rtpseq = rand();
     1184        rtptime = rand();
     1185        rtpssrc = rand();
     1186        last = now;
     1187        isfirstpacket = 0;
     1188      }
     1189      else
     1190      {
     1191        ++rtpseq;
     1192        sendtimediff = (((now.tv_sec - last.tv_sec)*1000000)
     1193        + (now.tv_usec - last.tv_usec));
     1194        rtptime += sendtimediff/TIME_RESOLUTION;
     1195      }
     1196      rtpbuffer[0] = (RTP_VERSION<<6);
     1197      /* padding, extension, csrc are empty */
     1198      rtpbuffer[1] = 96;
     1199      /* marker is empty */
     1200      rtpbuffer[2] = rtpseq>>8;
     1201      rtpbuffer[3] = rtpseq;
     1202      rtpbuffer[4] = rtptime>>24;
     1203      rtpbuffer[5] = rtptime>>16;
     1204      rtpbuffer[6] = rtptime>>8;
     1205      rtpbuffer[7] = rtptime;
     1206      rtpbuffer[8] = rtpssrc>>24;
     1207      rtpbuffer[9] = rtpssrc>>16;
     1208      rtpbuffer[10] = rtpssrc>>8;
     1209      rtpbuffer[11] = rtpssrc;
     1210      for(j=0; j<nBufferBytes; j++) {rtpbuffer[12+j] = buffer[j];}
     1211      last.tv_sec  = now.tv_sec;
     1212      last.tv_usec = now.tv_usec;
     1213
     1214      if ((i = sendto(sock, rtpbuffer, 12 + nBufferBytes, 0, pcasterRTP,
     1215      length)) != (nBufferBytes + 12))
     1216      {
     1217        if(i < 0)
     1218        {
     1219          if(errno != EAGAIN)
     1220          {
     1221            perror("WARNING: could not send data to Destination caster - retry connection");
     1222            close(sock);
     1223            sleep(5);
     1224            return;
     1225          }
     1226        }
     1227        else if(i)
     1228        {
     1229          memmove(buffer, buffer+(i-12), (size_t)(nBufferBytes-(i-12)));
     1230          nBufferBytes -= i-12;
     1231        }
     1232      }
     1233      else
     1234      {
     1235        nBufferBytes = 0;
     1236      }
     1237    }
     1238  }
     1239  return;
    7401240}
    7411241
    742 /*
     1242
     1243/********************************************************************
    7431244 * openserial
    7441245 *
     
    7581259 * Remarks:
    7591260 *
    760  */
     1261 ********************************************************************/
    7611262
    7621263static int openserial(const char * tty, int blocksz, int baud)
     
    7891290
    7901291#if (B4800 != 4800)
    791   /*
    792    * Not every system has speed settings equal to absolute speed value.
    793    */
     1292/* Not every system has speed settings equal to absolute speed value. */
    7941293
    7951294  switch (baud)
     
    8551354  if(fcntl(fd, F_SETFL, 0) == -1)
    8561355  {
    857     perror("WARNING: setting blocking mode failed");
     1356    perror("WARNING: setting blocking inputmode failed");
    8581357  }
    8591358  return (fd);
    860 }
    861 
    862 /*
    863  * usage
    864  *
    865  * Send a usage message to standard error and quit the program.
    866  *
    867  * Parameters:
    868  *     None.
    869  *
    870  * Return Value:
    871  *     The function does not return a value.
    872  *
    873  * Remarks:
    874  *
    875  */
    876 
     1359} /* openserial */
     1360
     1361/********************************************************************
     1362* usage
     1363*
     1364* Send a usage message to standard error and quit the program.
     1365*
     1366* Parameters:
     1367*     None.
     1368*
     1369* Return Value:
     1370*     The function does not return a value.
     1371*
     1372* Remarks:
     1373*
     1374*********************************************************************/
    8771375static
    8781376#ifdef __GNUC__
     
    8811379void usage(int rc, char *name)
    8821380{
    883   fprintf(stderr, "Version %s (%s) GPL" COMPILEDATE "\nUsage:\n%s [OPTIONS]",
     1381  fprintf(stderr, "Version %s (%s) GPL" COMPILEDATE "\nUsage:\n%s [OPTIONS]\n",
    8841382    revisionstr, datestr, name);
    885   fprintf(stderr, "  Options are: [-]           \n");
    886   fprintf(stderr, "    -a DestinationCaster name or address (default: %s)\n",
    887     NTRIP_CASTER);
    888   fprintf(stderr, "    -p DestinationCaster port (default: %d)\n", NTRIP_PORT);
    889   fprintf(stderr, "    -m DestinationCaster mountpoint\n");
    890   fprintf(stderr, "    -c DestinationCaster password\n");
    891   fprintf(stderr, "    -h|? print this help screen\n");
    892   fprintf(stderr, "    -M <mode>  sets the input mode\n");
    893   fprintf(stderr, "               (1=serial, 2=tcpsocket, 3=file, 4=sisnet"
    894     ", 5=udpsocket, 6=caster)\n");
    895   fprintf(stderr, "  Mode = file:\n");
    896   fprintf(stderr, "    -s file, simulate data stream by reading log file\n");
    897   fprintf(stderr, "       default/current setting is %s\n", filepath);
    898   fprintf(stderr, "  Mode = serial:\n");
    899   fprintf(stderr, "    -b baud_rate, sets serial input baud rate\n");
    900   fprintf(stderr, "       default/current value is %d\n", ttybaud);
    901   fprintf(stderr, "    -i input_device, sets name of serial input device\n");
    902   fprintf(stderr, "       default/current value is %s\n", ttyport);
    903   fprintf(stderr, "       (normally a symbolic link to /dev/tty\?\?)\n");
    904   fprintf(stderr, "  Mode = tcpsocket or udpsocket:\n");
    905   fprintf(stderr, "    -P receiver port (default: %d)\n", SERV_TCP_PORT);
    906   fprintf(stderr, "    -H hostname of TCP server (default: %s)\n",
    907     SERV_HOST_ADDR);
    908   fprintf(stderr, "    -f initfile send to server\n");
    909   fprintf(stderr, "    -x receiver id\n");
    910   fprintf(stderr, "    -y receiver password\n"); 
    911   fprintf(stderr, "    -B bindmode: bind to incoming UDP stream\n");
    912   fprintf(stderr, "  Mode = sisnet:\n");
    913   fprintf(stderr, "    -P receiver port (default: %d)\n", SISNET_PORT);
    914   fprintf(stderr, "    -H hostname of TCP server (default: %s)\n",
    915     SISNET_SERVER);
    916   fprintf(stderr, "    -u username\n");
    917   fprintf(stderr, "    -l password\n");
    918   fprintf(stderr, "    -V version [2.1, 3.0 or 3.1] (default: 3.1)\n");
    919   fprintf(stderr, "  Mode = caster:\n");
    920   fprintf(stderr, "    -P SourceCaster port (default: %d)\n", NTRIP_PORT);
    921   fprintf(stderr, "    -H SourceCaster hostname (default: %s)\n",
    922     NTRIP_CASTER);
    923   fprintf(stderr, "    -D SourceCaster mountpoint\n");
    924   fprintf(stderr, "    -U SourceCaster mountpoint username\n");
    925   fprintf(stderr, "    -W SourceCaster mountpoint password\n"); 
    926   fprintf(stderr, "\n");
     1383  fprintf(stderr, "PURPOSE\n");
     1384  fprintf(stderr, "   The purpose of this program is to pick up a GNSS data stream (Input, Source)\n");
     1385  fprintf(stderr, "   from either\n\n");
     1386  fprintf(stderr, "     1. a Serial port, or\n");
     1387  fprintf(stderr, "     2. an IP server, or\n");
     1388  fprintf(stderr, "     3. a File, or\n");
     1389  fprintf(stderr, "     4. a SISNeT Data Server, or\n");
     1390  fprintf(stderr, "     5. a UDP server, or\n");
     1391  fprintf(stderr, "     6. an NTRIP Version 1.0 Caster\n\n");
     1392  fprintf(stderr, "   and forward that incoming stream (Output, Destination) to either\n\n");
     1393  fprintf(stderr, "     - an NTRIP Version 1.0 Caster, or\n");
     1394  fprintf(stderr, "     - an NTRIP Version 2.0 Caster via TCP/IP or RTSP/RTP.\n\n\n");
     1395  fprintf(stderr, "OPTIONS\n");
     1396  fprintf(stderr, "   -h|? print this help screen\n\n");
     1397  fprintf(stderr, "    -E <ProxyHost>       Proxy server host name or address, required i.e. when\n");
     1398  fprintf(stderr, "                         running the program in a proxy server protected LAN,\n");
     1399  fprintf(stderr, "                         optional\n");
     1400  fprintf(stderr, "    -F <ProxyPort>       Proxy server IP port, required i.e. when running\n");
     1401  fprintf(stderr, "                         the program in a proxy server protected LAN, optional\n\n");
     1402  fprintf(stderr, "    -M <InputMode> Sets the input mode (1 = Serial Port, 2 = IP server,\n");
     1403  fprintf(stderr, "       3 = File, 4 = SISNeT Data Server, 5 = UDP server, 6 = NTRIP Caster),\n");
     1404  fprintf(stderr, "       mandatory\n\n");
     1405  fprintf(stderr, "       <InputMode> = 1 (Serial Port):\n");
     1406  fprintf(stderr, "       -i <Device>       Serial input device, default: /dev/gps, mandatory if\n");
     1407  fprintf(stderr, "                         <InputMode>=1\n");
     1408  fprintf(stderr, "       -b <BaudRate>     Serial input baud rate, default: 19200 bps, mandatory\n");
     1409  fprintf(stderr, "                         if <InputMode>=1\n\n");
     1410  fprintf(stderr, "       <InputMode> = 2|5 (IP port | UDP port):\n");
     1411  fprintf(stderr, "       -H <ServerHost>   Input host name or address, default: 127.0.0.1,\n");
     1412  fprintf(stderr, "                         mandatory if <InputMode> = 2|5\n");
     1413  fprintf(stderr, "       -P <ServerPort>   Input port, default: 1025, mandatory if <InputMode>= 2|5\n");
     1414  fprintf(stderr, "       -f <ServerFile>   Name of initialization file to be send to server,\n");
     1415  fprintf(stderr, "                         optional\n");
     1416  fprintf(stderr, "       -x <ServerUser>   User ID to access incoming stream, optional\n");
     1417  fprintf(stderr, "       -y <ServerPass>   Password, to access incoming stream, optional\n");
     1418  fprintf(stderr, "       -B Bind to incoming UDP stream, optional for <InputMode> = 5\n\n");
     1419  fprintf(stderr, "       <InputMode> = 3 (File):\n");
     1420  fprintf(stderr, "       -s <File>         File name to simulate stream by reading data from (log)\n");
     1421  fprintf(stderr, "                         file, default is /dev/stdin, mandatory for <InputMode> = 3\n\n");
     1422  fprintf(stderr, "       <InputMode> = 4 (SISNeT Data Server):\n");
     1423  fprintf(stderr, "       -H <SisnetHost>   SISNeT Data Server name or address,\n");
     1424  fprintf(stderr, "                         default: 131.176.49.142, mandatory if <InputMode> = 4\n");
     1425  fprintf(stderr, "       -P <SisnetPort>   SISNeT Data Server port, default: 7777, mandatory if\n");
     1426  fprintf(stderr, "                         <InputMode> = 4\n");
     1427  fprintf(stderr, "       -u <SisnetUser>   SISNeT Data Server user ID, mandatory if <InputMode> = 4\n");
     1428  fprintf(stderr, "       -l <SisnetPass>   SISNeT Data Server password, mandatory if <InputMode> = 4\n");
     1429  fprintf(stderr, "       -V <SisnetVers>   SISNeT Data Server Version number, options are 2.1, 3.0\n");
     1430  fprintf(stderr, "                         or 3.1, default: 3.1, mandatory if <InputMode> = 4\n\n");
     1431  fprintf(stderr, "       <InputMode> = 6 (NTRIP Version 1.0 Caster):\n");
     1432  fprintf(stderr, "       -H <SourceHost>   Source caster name or address, default: 127.0.0.1,\n");
     1433  fprintf(stderr, "                         mandatory if <InputMode> = 6\n");
     1434  fprintf(stderr, "       -P <SourcePort>   Source caster port, default: 2101, mandatory if\n");
     1435  fprintf(stderr, "                         <InputMode> = 6\n");
     1436  fprintf(stderr, "       -D <SourceMount>  Source caster mountpoint for stream input, mandatory if\n");
     1437  fprintf(stderr, "                         <InputMode> = 6\n");
     1438  fprintf(stderr, "       -U <SourceUser>   Source caster user Id for input stream access, mandatory\n");
     1439  fprintf(stderr, "                         for protected streams if <InputMode> = 6\n");
     1440  fprintf(stderr, "       -W <SourcePass>   Source caster password for input stream access, mandatory\n");
     1441  fprintf(stderr, "                         for protected streams if <InputMode> = 6\n\n");
     1442  fprintf(stderr, "    -O <OutputMode> Sets the output mode for communatation with the destination\n");
     1443  fprintf(stderr, "       caster (r = NTRIP Version 2.0 Caster in RTSP/RTP mode, t = Ntrip Version 2.0\n");
     1444  fprintf(stderr, "       Caster in TCP/IP mode, f = NTRIP Version 1.0 Caster)\n\n");
     1445  fprintf(stderr, "       Defaults to NTRIP1.0, but wil change to 2.0 in future versions\n");
     1446  fprintf(stderr, "       Note that the program automatically falls back from mode r to mode t and\n");
     1447  fprintf(stderr, "       further to mode f if necessary.\n\n");
     1448  fprintf(stderr, "       -a <DestHost>     Destination caster name or address, default: 127.0.0.1,\n");
     1449  fprintf(stderr, "                         mandatory\n");
     1450  fprintf(stderr, "       -p <DestPort>     Destination caster port, default: 2101, mandatory\n");
     1451  fprintf(stderr, "       -m <DestMount>    Destination caster mountpoint for stream upload,\n");
     1452  fprintf(stderr, "                         mandatory\n");
     1453  fprintf(stderr, "       -n <DestUser>     Destination caster user ID for stream upload to\n");
     1454  fprintf(stderr, "                         mountpoint, only for NTRIP Version 2.0 destination\n");
     1455  fprintf(stderr, "                         casters, mandatory\n");
     1456  fprintf(stderr, "       -c <DestPass>     Destination caster password for stream upload to\n");
     1457  fprintf(stderr, "                         mountpoint, mandatory\n");
     1458  fprintf(stderr, "       -N <STR-record>   Sourcetable STR-record\n");
     1459  fprintf(stderr, "                         optional for Ntrip Version 2.0 in RTSP/RTP and TCP/IP mode\n\n");
    9271460  exit(rc);
    928 }
    929 
    930 static const char encodingTable [64] = {
     1461} /* usage */
     1462
     1463
     1464/********************************************************************/
     1465/* signal handling                                                  */
     1466/********************************************************************/
     1467#ifdef __GNUC__
     1468static void handle_sigint(int sig __attribute__((__unused__)))
     1469#else /* __GNUC__ */
     1470static void handle_sigint(int sig)
     1471#endif /* __GNUC__ */
     1472{sigint_received  = 1;}
     1473
     1474static void setup_signal_handler(int sig, void (*handler)(int))
     1475{
     1476#if _POSIX_VERSION > 198800L
     1477  struct sigaction action;
     1478
     1479  action.sa_handler = handler;
     1480  sigemptyset(&(action.sa_mask));
     1481  sigaddset(&(action.sa_mask), sig);
     1482  action.sa_flags = 0;
     1483  sigaction(sig, &action, 0);
     1484#else
     1485  signal(sig, handler);
     1486#endif
     1487  return;
     1488} /* setupsignal_handler */
     1489
     1490static int signal_was_caught(void)
     1491{
     1492  fflush(stdout);
     1493  if(sigint_received)
     1494    fprintf(stderr, "\nSIGINT received: ");
     1495
     1496  return (sigint_received);
     1497} /* signal_was_caught */
     1498
     1499/********************************************************************
     1500 * base64-encoding                                                  *
     1501*******************************************************************/
     1502static const char encodingTable [64] =
     1503{
    9311504  'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
    9321505  'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
     
    9751548    *out = 0;
    9761549  return bytes;
    977 }
     1550}/* base64 Encoding */
     1551
     1552
     1553/********************************************************************
     1554 * send message to caster                                           *
     1555*********************************************************************/
     1556static int send_to_caster(char *input, int socket, int input_size)
     1557{
     1558int send_error = 1;
     1559
     1560  if((send(socket, input, (size_t)input_size, 0)) != input_size)
     1561  {
     1562    fprintf(stderr, "ERROR: could not send full header to Destination caster\n");
     1563    send_error = 0;
     1564  }else{
     1565    fprintf(stderr, "\nDestination caster request:\n");
     1566    fprintf(stderr, "%s", input);
     1567  }
     1568  return send_error;
     1569}/* send_to_caster */
     1570
     1571
     1572/********************************************************************
     1573 * close session                                                    *
     1574*********************************************************************/
     1575static void close_session(int sock_udp, int sock_tcp,
     1576const char *caster_addr, const char *mountpoint, int cseq,
     1577int session, char *rtsp_ext, int in_fd)
     1578{
     1579  int  size_send_buf;
     1580  char send_buf[BUFSZ];
     1581
     1582  if(in_fd)
     1583  {
     1584    if(close(in_fd)==-1)
     1585    {
     1586      perror("ERROR: close input device ");
     1587      exit(0);
     1588    }
     1589    else
     1590    {
     1591      fprintf(stderr, "\nclose input device: successful\n");
     1592    }
     1593  }
     1594
     1595  if(sock_udp  != 0)
     1596  {
     1597    if(cseq == 2)
     1598    {
     1599      size_send_buf = snprintf(send_buf, sizeof(send_buf),
     1600        "TEARDOWN rtsp://%s%s/%s RTSP/1.0\r\n"
     1601        "CSeq: 2\r\n"
     1602        "Session: %d\r\n"
     1603        "\r\n",
     1604        caster_addr, rtsp_ext, mountpoint, session);
     1605      if((size_send_buf >= (int)sizeof(send_buf)) || (size_send_buf < 0))
     1606      {
     1607        fprintf(stderr, "ERROR: Destination caster request to long\n");
     1608        exit(0);
     1609      }
     1610      send_to_caster(send_buf, sock_tcp, size_send_buf); strcpy(send_buf,"");
     1611      size_send_buf = recv(sock_tcp, send_buf, sizeof(send_buf), 0);
     1612      send_buf[size_send_buf] = '\0';
     1613      fprintf(stderr, "Destination caster response:\n%s", send_buf);
     1614    }
     1615    if(close(sock_udp)==-1)
     1616    {
     1617      perror("ERROR: close udp socket");
     1618      exit(0);
     1619    }
     1620    else
     1621    {
     1622      fprintf(stderr, "close udp socket:   successful\n");
     1623    }
     1624  }
     1625
     1626  if(close(sock_tcp)==-1)
     1627  {
     1628    perror("ERROR: close tcp socket");
     1629    exit(0);
     1630  }
     1631  else
     1632  {
     1633    fprintf(stderr, "close tcp socket:   successful\n\n");
     1634  }
     1635} /* close_session */
Note: See TracChangeset for help on using the changeset viewer.