Changeset 487 in ntrip


Ignore:
Timestamp:
Aug 30, 2007, 4:52:43 PM (17 years ago)
Author:
stuerze
Message:

reconnect mechanism added

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ntripserver/ntripserver.c

    r485 r487  
    11/*
    2  * $Id: NtripLinuxServer.c,v 1.32 2007/06/07 07:47:24 stoecker Exp $
     2 * $Id: ntripserver.c,v 1.33 2007/08/30 07:45:36 stoecker Exp $
    33 *
    44 * Copyright (c) 2003...2007
     
    3737
    3838/* CVS revision and version */
    39 static char revisionstr[] = "$Revision: 1.32 $";
    40 static char datestr[]     = "$Date: 2007/06/07 07:47:24 $";
     39static char revisionstr[] = "$Revision: 1.33 $";
     40static char datestr[]     = "$Date: 2007/08/30 07:45:36 $";
    4141
    4242#include <ctype.h>
     
    7171CASTER = 6, LAST };
    7272
    73 enum OUTMODE { HTTP = 1, RTSP = 2, NTRIPV1 = 3, END };
    74 
    75 #define AGENTSTRING     "NTRIP NtripLinuxServer"
     73enum OUTMODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, END };
     74
     75#define AGENTSTRING     "NTRIP ntripserver"
    7676#define BUFSZ           1024
    7777#define SZ              64
     
    100100static int sisnet              = 31;
    101101static int gpsfd               = -1;
     102static int socket_tcp          = -1;
     103static int socket_udp          = -1;
    102104static int sigint_received     = 0;
     105static int sigalarm_received   = 0;
     106static int sigpipe_received    = 0;
     107static int reconnect_sec       = 1;
     108
    103109
    104110/* Forward references */
     
    109115static int  encode(char *buf, int size, const char *user, const char *pwd);
    110116static int  send_to_caster(char *input, int socket, int input_size);
    111 static 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);
     117static void close_session(const char *caster_addr, const char *mountpoint,
     118  int cseq, int session, char *rtsp_ext, int fallback);
     119static int  reconnect(int rec_sec, int rec_sec_max);
    114120
    115121/* Signal Handling */
    116122static void handle_sigint(int sig);
     123static void handle_alarm(int sig);
     124static void handle_sigpipe(int sig);
    117125static void setup_signal_handler(int sig, void (*handler)(int));
    118 static int  signal_was_caught(void);
    119 
    120 #ifdef __GNUC__
    121 static __attribute__ ((noreturn)) void sighandler_alarm(
    122 int sig __attribute__((__unused__)))
    123 #else /* __GNUC__ */
    124 static void sighandler_alarm(int sig)
    125 #endif /* __GNUC__ */
    126 {
    127   fprintf(stderr, "ERROR: more than %d seconds no activity\n", ALARMTIME);
    128   exit(1);
    129 }
    130126
    131127/*
     
    192188  const char *       password = "";
    193189
    194   int                socket_tcp = 0;
    195   int                outputmode = NTRIPV1;
     190  int                outputmode = NTRIP1;
    196191
    197192  struct sockaddr_in casterRTP;
    198193  struct sockaddr_in local;
    199   int                socket_udp = 0;
    200194  int                client_port = 0;
    201195  int                server_port = 0;
     
    211205  char *             token;
    212206  char *             tok_buf[BUFSZ];
     207
     208  int                reconnect_sec_max = 0;
    213209
    214210  setbuf(stdout, 0);
     
    235231
    236232  /* setup signal handler for timeout */
    237   signal(SIGALRM,sighandler_alarm);
     233  setup_signal_handler(SIGALRM, handle_alarm);
    238234  alarm(ALARMTIME);
     235
     236  /* setup signal handler for CTRL+C */
     237  setup_signal_handler(SIGINT, handle_sigint);
     238 
     239/* setup signal handler for boken pipe */
     240  setup_signal_handler(SIGPIPE, handle_sigpipe);
    239241
    240242  /* get and check program arguments */
     
    245247  }
    246248  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)
     249  "M:i:h:b:p:s:a:m:c:H:P:f:x:y:l:u:V:D:U:W:O:E:F:R:N:n:B")) != EOF)
    248250  {
    249251    switch (c)
     
    352354      proxyport = atoi(optarg);
    353355      break;
     356    case 'R':  /* maximum delay between reconnect attempts in seconds */
     357       reconnect_sec_max = atoi(optarg);
     358       break;
    354359    case 'O': /* OutputMode */
    355360      outputmode = 0;
    356361      if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
    357         outputmode = NTRIPV1;
     362        outputmode = NTRIP1;
    358363      else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
    359364        outputmode = HTTP;
     
    399404  }
    400405
    401   if(*ntrip_str && (outputmode == NTRIPV1))
     406  if(outputmode != NTRIP1)
     407  {
     408     fprintf(stderr, "\nWARNING: *** NTRIP VERSION 2 PROTOCOL IS STILL"
     409      " BETA AND MAY BE CHANGED ***\n\n");
     410  }
     411 
     412  if(*ntrip_str && (outputmode == NTRIP1))
    402413  {
    403414     fprintf(stderr, "WARNING: OutputMode is Ntrip version 1.0"
    404415     " - Ntrip-STR will not be considered\n");
     416  }
     417
     418  if((reconnect_sec_max > 0) && (reconnect_sec_max < 256))
     419  {
     420    fprintf(stderr,
     421    "WARNING: maximum delay between reconnect attemts changed from %d to 256 seconds\n"
     422    , reconnect_sec_max);
     423    reconnect_sec_max = 256;
    405424  }
    406425
     
    459478    if((i > SZ) || (i < 0))
    460479    {
    461       fprintf(stderr, "ERROR: Destination caster name/port to long - length = %d (max: %d)\n", i, SZ);
     480      fprintf(stderr,"ERROR: Destination caster name/port to long - length = %d (max: %d)\n", i, SZ);
    462481      exit(0);
    463482    }
     
    475494  }
    476495
    477   /*** InputMode handling ***/
    478   switch(inputmode)
    479   {
    480   case INFILE:
    481     {
    482       if((gpsfd = open(filepath, O_RDONLY)) < 0)
    483       {
    484         perror("ERROR: opening input file");
    485         exit(1);
    486       }
    487       /* set blocking inputmode in case it was not set
    488         (seems to be sometimes for fifo's) */
    489       fcntl(gpsfd, F_SETFL, 0);
    490       printf("file input: file = %s\n", filepath);
    491     }
    492     break;
    493   case SERIAL: /* open serial port */
    494     {
    495       gpsfd = openserial(ttyport, 1, ttybaud);
    496       if(gpsfd < 0)
    497       {
    498         exit(1);
    499       }
    500       printf("serial input: device = %s, speed = %d\n", ttyport, ttybaud);
    501     }
    502     break;
    503   case TCPSOCKET: case UDPSOCKET: case SISNET: case CASTER:
    504     {
     496  while(inputmode != LAST)
     497  {
     498    int input_init = 1;
     499    /*** InputMode handling ***/
     500    switch(inputmode)
     501    {
     502    case INFILE:
     503      {
     504        if((gpsfd = open(filepath, O_RDONLY)) < 0)
     505        {
     506          perror("ERROR: opening input file");
     507          exit(1);
     508        }
     509        /* set blocking inputmode in case it was not set
     510          (seems to be sometimes for fifo's) */
     511        fcntl(gpsfd, F_SETFL, 0);
     512        printf("file input: file = %s\n", filepath);
     513      }
     514      break;
     515    case SERIAL: /* open serial port */
     516      {
     517        gpsfd = openserial(ttyport, 1, ttybaud);
     518        if(gpsfd < 0)
     519        {
     520          exit(1);
     521        }
     522        printf("serial input: device = %s, speed = %d\n", ttyport, ttybaud);
     523      }
     524      break;
     525    case TCPSOCKET: case UDPSOCKET: case SISNET: case CASTER:
     526      {
     527        if(inputmode == SISNET)
     528        {
     529          if(!inhost) inhost = SISNET_SERVER;
     530          if(!inport) inport = SISNET_PORT;
     531        }
     532        else if(inputmode == CASTER)
     533        {
     534          if(!inport) inport = NTRIP_PORT;
     535          if(!inhost) inhost = NTRIP_CASTER;
     536        }
     537        else if((inputmode == TCPSOCKET) || (inputmode == UDPSOCKET))
     538        {
     539          if(!inport) inport = SERV_TCP_PORT;
     540          if(!inhost) inhost = SERV_HOST_ADDR;
     541        }
     542
     543        if(!(he = gethostbyname(inhost)))
     544        {
     545          fprintf(stderr, "ERROR: Input host <%s> unknown\n", inhost);
     546          usage(-2, argv[0]);
     547        }
     548
     549        if((gpsfd = socket(AF_INET, inputmode == UDPSOCKET
     550        ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
     551        {
     552          fprintf(stderr,
     553          "ERROR: can't create socket for incoming data stream\n");
     554          exit(1);
     555        }
     556
     557        memset((char *) &caster, 0x00, sizeof(caster));
     558        if(!bindmode)
     559          memcpy(&caster.sin_addr, he->h_addr, (size_t)he->h_length);
     560        caster.sin_family = AF_INET;
     561        caster.sin_port = htons(inport);
     562
     563        fprintf(stderr, "%s input: host = %s, port = %d, %s%s%s%s%s\n",
     564        inputmode == CASTER ? "caster" : inputmode == SISNET ? "sisnet" :
     565        inputmode == TCPSOCKET ? "tcp socket" : "udp socket",
     566        bindmode ? "127.0.0.1" : inet_ntoa(caster.sin_addr),
     567        inport, stream_name ? "stream = " : "", stream_name ? stream_name : "",
     568        initfile ? ", initfile = " : "", initfile ? initfile : "",
     569        bindmode ? "binding mode" : "");
     570
     571        if(bindmode)
     572        {
     573          if(bind(gpsfd, (struct sockaddr *) &caster, sizeof(caster)) < 0)
     574          {
     575            fprintf(stderr, "ERROR: can't bind input to port %d\n", inport);
     576            reconnect_sec_max = 0;
     577            input_init = 0;
     578            break;
     579          }
     580        } /* connect to input-caster or proxy server*/
     581        else if(connect(gpsfd, (struct sockaddr *)&caster, sizeof(caster)) < 0)
     582        {
     583          fprintf(stderr, "WARNING: can't connect input to %s at port %d\n",
     584          inet_ntoa(caster.sin_addr), inport);
     585          input_init = 0;
     586          break;
     587        }
     588
     589        if(stream_name) /* input from Ntrip Version 1.0 caster*/
     590        {
     591          int init = 0;
     592
     593          /* set socket buffer size */
     594          setsockopt(gpsfd, SOL_SOCKET, SO_SNDBUF, (const char *) &size,
     595            sizeof(const char *));
     596          if(stream_user && stream_password)
     597          {
     598            /* leave some space for login */
     599            nBufferBytes=snprintf(szSendBuffer, sizeof(szSendBuffer)-40,
     600            "GET %s/%s HTTP/1.0\r\n"
     601            "User-Agent: %s/%s\r\n"
     602            "Authorization: Basic ", get_extension, stream_name,
     603            AGENTSTRING, revisionstr);
     604            /* second check for old glibc */
     605            if(nBufferBytes > (int)sizeof(szSendBuffer)-40 || nBufferBytes < 0)
     606            {
     607              fprintf(stderr, "ERROR: Source caster request too long\n");
     608              input_init = 0;
     609              reconnect_sec_max =0;
     610              break;
     611            }
     612            nBufferBytes += encode(szSendBuffer+nBufferBytes,
     613              sizeof(szSendBuffer)-nBufferBytes-4, stream_user, stream_password);
     614            if(nBufferBytes > (int)sizeof(szSendBuffer)-4)
     615            {
     616              fprintf(stderr,
     617              "ERROR: Source caster user ID and/or password too long\n");
     618              input_init = 0;
     619              reconnect_sec_max =0;
     620              break;
     621            }             
     622            szSendBuffer[nBufferBytes++] = '\r';
     623            szSendBuffer[nBufferBytes++] = '\n';
     624            szSendBuffer[nBufferBytes++] = '\r';
     625            szSendBuffer[nBufferBytes++] = '\n';
     626          }
     627          else
     628          {
     629            nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
     630            "GET %s/%s HTTP/1.0\r\n"
     631            "User-Agent: %s/%s\r\n"
     632            "\r\n", get_extension, stream_name, AGENTSTRING, revisionstr);
     633          }
     634          if((send(gpsfd, szSendBuffer, (size_t)nBufferBytes, 0))
     635          != nBufferBytes)
     636          {
     637            fprintf(stderr, "WARNING: could not send Source caster request\n");
     638            input_init = 0;
     639            break;
     640          }
     641          nBufferBytes = 0;
     642          /* check Source caster's response */
     643          while(!init && nBufferBytes < (int)sizeof(szSendBuffer)
     644          && (nBufferBytes += recv(gpsfd, szSendBuffer,
     645          sizeof(szSendBuffer)-nBufferBytes, 0)) > 0)
     646          {
     647            if(strstr(szSendBuffer, "\r\n"))
     648            {             
     649              if(strncmp(szSendBuffer, "ICY 200 OK", 10))
     650              {
     651                int k;
     652                fprintf(stderr,
     653                "ERROR: could not get requested data from Source caster: ");
     654                for(k = 0; k < nBufferBytes && szSendBuffer[k] != '\n'
     655                  && szSendBuffer[k] != '\r'; ++k)
     656                {
     657                  fprintf(stderr, "%c", isprint(szSendBuffer[k])
     658                  ? szSendBuffer[k] : '.');
     659                }
     660                fprintf(stderr, "\n");
     661                if(strncmp(szSendBuffer, "SOURCETABLE 200 OK",18))
     662                {
     663                  reconnect_sec_max =0;
     664                }
     665                input_init = 0;
     666                break;
     667              }
     668              else init = 1;
     669            }
     670          }
     671        } /* end input from Ntrip Version 1.0 caster */
     672
     673        if(initfile && inputmode != SISNET)
     674        {
     675          char buffer[1024];
     676          FILE *fh;
     677          int i;
     678
     679          if((fh = fopen(initfile, "r")))
     680          {
     681            while((i = fread(buffer, 1, sizeof(buffer), fh)) > 0)
     682            {
     683              if((send(gpsfd, buffer, (size_t)i, 0)) != i)
     684              {
     685                perror("WARNING: sending init file");
     686                input_init = 0;
     687                break;
     688              }
     689            }
     690            if(i < 0)
     691            {
     692              perror("ERROR: reading init file");
     693              reconnect_sec_max = 0;
     694              input_init = 0;
     695              break;
     696            }
     697            fclose(fh);
     698          }
     699          else
     700          {
     701            fprintf(stderr, "ERROR: can't read init file <%s>\n", initfile);
     702            reconnect_sec_max = 0;
     703            input_init = 0;
     704            break;
     705          }
     706        }
     707      }
    505708      if(inputmode == SISNET)
    506709      {
    507         if(!inhost) inhost = SISNET_SERVER;
    508         if(!inport) inport = SISNET_PORT;
    509       }
    510       else if(inputmode == CASTER)
    511       {
    512         if(!inport) inport = NTRIP_PORT;
    513         if(!inhost) inhost = NTRIP_CASTER;
    514       }
    515       else if((inputmode == TCPSOCKET) || (inputmode == UDPSOCKET))
    516       {
    517         if(!inport) inport = SERV_TCP_PORT;
    518         if(!inhost) inhost = SERV_HOST_ADDR;
    519       }
    520 
    521       if(!(he = gethostbyname(inhost)))
    522       {
    523         fprintf(stderr, "ERROR: Input host <%s> unknown\n", inhost);
    524         usage(-2, argv[0]);
    525       }
    526 
    527       if((gpsfd = socket(AF_INET, inputmode == UDPSOCKET
    528       ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
    529       {
    530         fprintf(stderr,
    531         "ERROR: can't create socket for incoming data stream\n");
    532         exit(1);
     710        int i, j;
     711        char buffer[1024];
     712
     713        i = snprintf(buffer, sizeof(buffer), sisnet >= 30 ? "AUTH,%s,%s\r\n"
     714          : "AUTH,%s,%s", sisnetuser, sisnetpassword);
     715        if((send(gpsfd, buffer, (size_t)i, 0)) != i)
     716        {
     717          perror("WARNING: sending authentication for SISNeT data server");
     718          input_init = 0;
     719          break;
     720        }
     721        i = sisnet >= 30 ? 7 : 5;
     722        if((j = recv(gpsfd, buffer, i, 0)) != i && strncmp("*AUTH", buffer, 5))
     723        {
     724          fprintf(stderr, "WARNING: SISNeT connect failed:");
     725          for(i = 0; i < j; ++i)
     726          {
     727            if(buffer[i] != '\r' && buffer[i] != '\n')
     728            {
     729              fprintf(stderr, "%c", isprint(buffer[i]) ? buffer[i] : '.');
     730            }
     731          }
     732          fprintf(stderr, "\n");
     733          input_init = 0;
     734          break;
     735        }
     736        if(sisnet >= 31)
     737        {
     738          if((send(gpsfd, "START\r\n", 7, 0)) != i)
     739          {
     740            perror("WARNING: sending Sisnet start command");
     741            input_init = 0;
     742            break;
     743          }
     744        }
     745      }
     746      /*** receiver authentication  ***/
     747      if (recvrid && recvrpwd && ((inputmode == TCPSOCKET)
     748      || (inputmode == UDPSOCKET)))
     749      {
     750        if (strlen(recvrid) > (BUFSZ-3))
     751        {
     752          fprintf(stderr, "ERROR: Receiver ID too long\n");
     753          reconnect_sec_max = 0;
     754          input_init = 0;
     755          break;
     756        }
     757        else
     758        {
     759          fprintf(stderr, "Sending user ID for receiver...\n");
     760          nBufferBytes = read(gpsfd, szSendBuffer, BUFSZ);
     761          strcpy(szSendBuffer, recvrid);
     762          strcat(szSendBuffer,"\r\n");
     763          if(send(gpsfd,szSendBuffer, strlen(szSendBuffer), MSG_DONTWAIT) < 0)
     764          {
     765            perror("WARNING: sending user ID for receiver");
     766            input_init = 0;
     767            break;
     768          }
     769        }
     770
     771        if (strlen(recvrpwd) > (BUFSZ-3))
     772        {
     773          fprintf(stderr, "ERROR: Receiver password too long\n");
     774          reconnect_sec_max = 0;
     775          input_init = 0;
     776          break;
     777        }
     778        else
     779        {
     780          fprintf(stderr, "Sending user password for receiver...\n");
     781          nBufferBytes = read(gpsfd, szSendBuffer, BUFSZ);
     782          strcpy(szSendBuffer, recvrpwd);
     783          strcat(szSendBuffer,"\r\n");
     784          if(send(gpsfd, szSendBuffer, strlen(szSendBuffer), MSG_DONTWAIT) < 0)
     785          {
     786            perror("WARNING: sending user password for receiver");
     787            input_init = 0;
     788            break;
     789          }
     790        }
     791      }
     792      break;
     793    default:
     794      usage(-1, argv[0]);
     795      break;
     796    }
     797   
     798    /* ----- main part ----- */
     799    int output_init = 1;
     800
     801    while((input_init) && (output_init))
     802    {
     803      if((sigint_received) || (sigalarm_received) || (sigpipe_received)) break;
     804
     805      if(!(he = gethostbyname(outhost)))
     806      {
     807        fprintf(stderr, "ERROR: Destination caster or proxy host <%s> unknown\n",
     808        outhost);
     809        close_session(casterouthost, mountpoint, cseq, session, rtsp_extension, 0);
     810        usage(-2, argv[0]);
     811      }
     812
     813      /* create socket */
     814      if((socket_tcp = socket(AF_INET, SOCK_STREAM, 0)) < 0)
     815      {
     816        perror("ERROR: tcp socket");
     817        reconnect_sec_max = 0;
     818        break;
    533819      }
    534820
    535821      memset((char *) &caster, 0x00, sizeof(caster));
    536       if(!bindmode)
    537         memcpy(&caster.sin_addr, he->h_addr, (size_t)he->h_length);
     822      memcpy(&caster.sin_addr, he->h_addr, (size_t)he->h_length);
    538823      caster.sin_family = AF_INET;
    539       caster.sin_port = htons(inport);
    540 
    541       fprintf(stderr, "%s input: host = %s, port = %d, %s%s%s%s%s\n",
    542       inputmode == CASTER ? "caster" : inputmode == SISNET ? "sisnet" :
    543       inputmode == TCPSOCKET ? "tcp socket" : "udp socket",
    544       bindmode ? "127.0.0.1" : inet_ntoa(caster.sin_addr),
    545       inport, stream_name ? "stream = " : "", stream_name ? stream_name : "",
    546       initfile ? ", initfile = " : "", initfile ? initfile : "",
    547       bindmode ? "binding mode" : "");
    548 
    549       if(bindmode)
    550       {
    551         if(bind(gpsfd, (struct sockaddr *) &caster, sizeof(caster)) < 0)
    552         {
    553           fprintf(stderr, "ERROR: can't bind input to port %d\n", inport);
    554           exit(1);
    555         }
    556       } /* connect to input-caster or proxy server*/
    557       else if(connect(gpsfd, (struct sockaddr *)&caster, sizeof(caster)) < 0)
    558       {
    559         fprintf(stderr, "ERROR: can't connect input to %s at port %d\n",
    560         inet_ntoa(caster.sin_addr), inport);
    561         exit(1);
    562       }
    563 
    564       if(stream_name) /* input from Ntrip Version 1.0 caster*/
    565       {
    566         int init = 0;
    567 
    568         /* set socket buffer size */
    569         setsockopt(gpsfd, SOL_SOCKET, SO_SNDBUF, (const char *) &size,
    570           sizeof(const char *));
    571         if(stream_user && stream_password)
    572         {
    573           /* leave some space for login */
    574           nBufferBytes=snprintf(szSendBuffer, sizeof(szSendBuffer)-40,
    575           "GET %s/%s HTTP/1.0\r\n"
    576           "User-Agent: %s/%s\r\n"
    577           "Authorization: Basic ", get_extension, stream_name,
    578           AGENTSTRING, revisionstr);
    579           /* second check for old glibc */
    580           if(nBufferBytes > (int)sizeof(szSendBuffer)-40 || nBufferBytes < 0)
    581           {
    582             fprintf(stderr, "ERROR: Source caster request too long\n");
    583             exit(1);
    584           }
    585           nBufferBytes += encode(szSendBuffer+nBufferBytes,
    586             sizeof(szSendBuffer)-nBufferBytes-4, stream_user, stream_password);
    587           if(nBufferBytes > (int)sizeof(szSendBuffer)-4)
    588           {
     824      caster.sin_port = htons(outport);
     825
     826      /* connect to Destination caster or Proxy server*/
     827      fprintf(stderr, "caster output: host = %s, port = %d, mountpoint = %s"
     828      ", mode = %s\n\n", inet_ntoa(caster.sin_addr), outport, mountpoint,
     829      outputmode == NTRIP1 ? "ntrip1" : outputmode == HTTP ? "http" : "rtsp");
     830
     831      if(connect(socket_tcp, (struct sockaddr *) &caster, sizeof(caster)) < 0)
     832      {
     833        fprintf(stderr, "WARNING: can't connect output to %s at port %d\n",
     834          inet_ntoa(caster.sin_addr), outport);
     835        break;
     836      }
     837
     838      /*** OutputMode handling ***/
     839      switch(outputmode)
     840      {
     841        case NTRIP1: /*** OutputMode Ntrip Version 1.0 ***/
     842          nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
     843            "SOURCE %s %s/%s\r\n"
     844            "Source-Agent: %s/%s\r\n\r\n",
     845            password, post_extension, mountpoint, AGENTSTRING, revisionstr);
     846          if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
     847          {
     848            fprintf(stderr, "ERROR: Destination caster request to long\n");
     849            reconnect_sec_max = 0;
     850            output_init = 0;
     851            break;
     852          }
     853          if(!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
     854          {
     855            output_init = 0;
     856            break;
     857          }
     858          /* check Destination caster's response */
     859          nBufferBytes = recv(socket_tcp, szSendBuffer, sizeof(szSendBuffer), 0);
     860          szSendBuffer[nBufferBytes] = '\0';
     861          if(!strstr(szSendBuffer, "OK"))
     862          {
     863            char *a;
    589864            fprintf(stderr,
    590             "ERROR: Source caster user ID and/or password too long\n");
    591             exit(1);
    592           }
    593           szSendBuffer[nBufferBytes++] = '\r';
    594           szSendBuffer[nBufferBytes++] = '\n';
    595           szSendBuffer[nBufferBytes++] = '\r';
    596           szSendBuffer[nBufferBytes++] = '\n';
    597         }
    598         else
    599         {
     865            "ERROR: Destination caster's or Proxy's reply is not OK: ");
     866            for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
     867            {
     868              fprintf(stderr, "%.1s", isprint(*a) ? a : ".");
     869            }
     870            fprintf(stderr, "\n");
     871            if((strstr(szSendBuffer,"ERROR - Bad Password"))
     872            || (strstr(szSendBuffer,"400 Bad Request")))           
     873            reconnect_sec_max = 0;
     874            output_init = 0;
     875            break;
     876          }
     877#ifndef NDEBUG
     878          else
     879          {
     880            fprintf(stderr, "Destination caster response:\n%s\n",
     881            szSendBuffer);
     882          }
     883#endif
     884          send_receive_loop(socket_tcp, gpsfd, outputmode, NULL, 0);
     885          break;
     886        case HTTP: /*** Ntrip-Version 2.0 HTTP/1.1 ***/
    600887          nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
    601           "GET %s/%s HTTP/1.0\r\n"
    602           "User-Agent: %s/%s\r\n"
    603           "\r\n", get_extension, stream_name, AGENTSTRING, revisionstr);
    604         }
    605         if((send(gpsfd, szSendBuffer, (size_t)nBufferBytes, 0))
    606         != nBufferBytes)
    607         {
    608           fprintf(stderr, "ERROR: could not send Source caster request\n");
    609           exit(1);
    610         }
    611         nBufferBytes = 0;
    612         /* check Source caster's response */
    613         while(!init && nBufferBytes < (int)sizeof(szSendBuffer)
    614         && (nBufferBytes += recv(gpsfd, szSendBuffer,
    615         sizeof(szSendBuffer)-nBufferBytes, 0)) > 0)
    616         {
    617           if(strstr(szSendBuffer, "\r\n"))
    618           {
    619             if(!strncmp(szSendBuffer, "ICY 200 OK\r\n", 10))
    620               init = 1;
    621             else
    622             {
    623               int k;
    624               fprintf(stderr,
    625               "ERROR: could not get requested data from Source caster: ");
    626               for(k = 0; k < nBufferBytes && szSendBuffer[k] != '\n'
    627               && szSendBuffer[k] != '\r'; ++k)
    628               {
    629                 fprintf(stderr, "%c", isprint(szSendBuffer[k])
    630                 ? szSendBuffer[k] : '.');
    631               }
    632               fprintf(stderr, "\n");
    633               exit(1);
    634             }
    635           }
    636         }
    637         if(!init)
    638         {
    639           fprintf(stderr, "ERROR: could not init Source caster download\n");
    640           exit(1);
    641         }
    642       } /* end input from Ntrip Version 1.0 caster */
    643 
    644       if(initfile && inputmode != SISNET)
    645       {
    646         char buffer[1024];
    647         FILE *fh;
    648         int i;
    649 
    650         if((fh = fopen(initfile, "r")))
    651         {
    652           while((i = fread(buffer, 1, sizeof(buffer), fh)) > 0)
    653           {
    654             if((send(gpsfd, buffer, (size_t)i, 0)) != i)
    655             {
    656               perror("ERROR: sending init file");
    657               exit(1);
    658             }
    659           }
    660           if(i < 0)
    661           {
    662             perror("ERROR: reading init file");
    663             exit(1);
    664           }
    665           fclose(fh);
    666         }
    667         else
    668         {
    669           fprintf(stderr, "ERROR: can't read init file <%s>\n", initfile);
    670           exit(1);
    671         }
    672       }
    673     }
    674     if(inputmode == SISNET)
    675     {
    676       int i, j;
    677       char buffer[1024];
    678 
    679       i = snprintf(buffer, sizeof(buffer), sisnet >= 30 ? "AUTH,%s,%s\r\n"
    680         : "AUTH,%s,%s", sisnetuser, sisnetpassword);
    681       if((send(gpsfd, buffer, (size_t)i, 0)) != i)
    682       {
    683         perror("ERROR: sending authentication for SISNeT data server");
    684         exit(1);
    685       }
    686       i = sisnet >= 30 ? 7 : 5;
    687       if((j = recv(gpsfd, buffer, i, 0)) != i && strncmp("*AUTH", buffer, 5))
    688       {
    689         fprintf(stderr, "ERROR: SISNeT connect failed:");
    690         for(i = 0; i < j; ++i)
    691         {
    692           if(buffer[i] != '\r' && buffer[i] != '\n')
    693           {
    694             fprintf(stderr, "%c", isprint(buffer[i]) ? buffer[i] : '.');
    695           }
    696         }
    697         fprintf(stderr, "\n");
    698         exit(1);
    699       }
    700       if(sisnet >= 31)
    701       {
    702         if((send(gpsfd, "START\r\n", 7, 0)) != i)
    703         {
    704           perror("ERROR: sending Sisnet start command");
    705           exit(1);
    706         }
    707       }
    708     }
    709     /*** receiver authentication  ***/
    710     if (recvrid && recvrpwd && ((inputmode == TCPSOCKET)
    711     || (inputmode == UDPSOCKET)))
    712     {
    713       if (strlen(recvrid) > (BUFSZ-3))
    714       {
    715         fprintf(stderr, "ERROR: Receiver ID too long\n");
    716         exit(0);
    717       }
    718       else
    719       {
    720         fprintf(stderr, "Sending user ID for receiver...\n");
    721         nBufferBytes = read(gpsfd, szSendBuffer, BUFSZ);
    722         strcpy(szSendBuffer, recvrid);
    723         strcat(szSendBuffer,"\r\n");
    724         send(gpsfd,szSendBuffer, strlen(szSendBuffer), MSG_DONTWAIT);
    725       }
    726 
    727       if (strlen(recvrpwd) > (BUFSZ-3))
    728       {
    729         fprintf(stderr, "ERROR: Receiver password too long\n");
    730         exit(0);
    731       }
    732       else
    733       {
    734         fprintf(stderr, "Sending user password for receiver...\n");
    735         nBufferBytes = read(gpsfd, szSendBuffer, BUFSZ);
    736         strcpy(szSendBuffer, recvrpwd);
    737         strcat(szSendBuffer,"\r\n");
    738         send(gpsfd, szSendBuffer, strlen(szSendBuffer), MSG_DONTWAIT);
    739       }
    740     }
    741     break;
    742   default:
    743     usage(-1, argv[0]);
    744     break;
    745   }
    746 
    747   /* ----- main part ----- */
    748   /* setup signal handler for CTRL+C */
    749   setup_signal_handler(SIGINT,  handle_sigint);
    750 
    751   while(outputmode != END)
    752   {
    753     if(signal_was_caught())
    754     {
    755       fprintf(stderr, "NtripLinuxServer terminates\n");
    756       break;
    757     }
    758 
    759     if(!(he = gethostbyname(outhost)))
    760     {
    761       fprintf(stderr, "ERROR: Destination caster or proxy host <%s> unknown\n",
    762       outhost);
    763       usage(-2, argv[0]);
    764     }
    765 
    766     /* create socket */
    767     if((socket_tcp = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    768     {
    769       perror("ERROR: tcp socket");
    770       exit(2);
    771     }
    772 
    773     memset((char *) &caster, 0x00, sizeof(caster));
    774     memcpy(&caster.sin_addr, he->h_addr, (size_t)he->h_length);
    775     caster.sin_family = AF_INET;
    776     caster.sin_port = htons(outport);
    777 
    778     /* connect to Destination caster or Proxy server*/
    779     fprintf(stderr, "caster output: host = %s, port = %d, mountpoint = %s"
    780     ", mode = %s\n", inet_ntoa(caster.sin_addr), outport, mountpoint,
    781     outputmode == NTRIPV1 ? "ntrip1" : outputmode == HTTP ? "http" : "rtsp");
    782 
    783     if(connect(socket_tcp, (struct sockaddr *) &caster, sizeof(caster)) < 0)
    784     {
    785       fprintf(stderr, "ERROR: can't connect output to %s at port %d\n",
    786         inet_ntoa(caster.sin_addr), outport);
    787       if(close(socket_tcp)==-1) perror("ERROR: close tcp socket");
    788       exit(3);
    789     }
    790 
    791     /*** OutputMode handling ***/
    792     switch(outputmode){
    793       case NTRIPV1: /*** OutputMode Ntrip Version 1.0 ***/
    794         nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
    795           "SOURCE %s %s/%s\r\n"
    796           "Source-Agent: %s\r\n\r\n",
    797           password, post_extension, mountpoint, AGENTSTRING);
    798         if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
    799         {
    800           fprintf(stderr, "ERROR: Destination caster request to long\n");
    801           outputmode = END;
    802           break;
    803         }
    804         if(!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
    805         {
    806           outputmode = END;
    807           break;
    808         }
    809         /* check Destination caster's response */
    810         nBufferBytes = recv(socket_tcp, szSendBuffer, sizeof(szSendBuffer), 0);
    811         szSendBuffer[nBufferBytes] = '\0';
    812         if(!strstr(szSendBuffer, "OK"))
    813         {
    814           char *a;
    815           fprintf(stderr,
    816           "ERROR: Destination caster's or Proxy's reply is not OK: ");
    817           for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
    818           {
    819             fprintf(stderr, "%.1s", isprint(*a) ? a : ".");
    820           }
    821           fprintf(stderr, "\n");
    822           outputmode = END;
    823           break;
    824         }
    825 #ifndef NDEBUG
    826         else
    827         {
    828           fprintf(stderr,
    829           "Destination caster response:\n%s\nconnection successfull\n",
    830           szSendBuffer);
    831         }
    832 #endif
    833         send_receive_loop(socket_tcp, gpsfd, outputmode, NULL, 0);
    834         break;
    835       case HTTP: /*** Ntrip-Version 2.0 HTTP/1.1 ***/
    836         nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
    837           "POST %s/%s HTTP/1.1\r\n"
    838           "Host: %s\r\n"
    839           "Ntrip-Version: Ntrip/2.0\r\n"
    840           "User-Agent: %s/%s\r\n"
    841           "Authorization: Basic %s\r\n"
    842           "Ntrip-STR: %s\r\n"
    843           "Transfer-Encoding: chunked\r\n\r\n",
    844           post_extension, mountpoint, casterouthost, AGENTSTRING,
    845           revisionstr, authorization, ntrip_str);
    846         if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
    847         {
    848           fprintf(stderr, "ERROR: Destination caster request to long\n");
    849           outputmode = END;
    850           break;
    851         }
    852         if (!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
    853         {
    854           outputmode = END;
    855           break;
    856         }
    857         /* check Destination caster's response */
    858         nBufferBytes = recv(socket_tcp, szSendBuffer, sizeof(szSendBuffer), 0);
    859         szSendBuffer[nBufferBytes] = '\0';
    860         if(!strstr(szSendBuffer, "HTTP/1.1 200 OK"))
    861         {
    862           char *a;
    863           fprintf(stderr,
    864           "ERROR: Destination caster's%s reply is not OK: ",
    865           *proxyhost ? " or Proxy's" : "");
    866           for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
    867           {
    868             fprintf(stderr, "%.1s", isprint(*a) ? a : ".");
    869           }
    870           fprintf(stderr, "\n");
    871           /* fallback if necessary */
    872           if(!strstr(szSendBuffer,"Ntrip-Version: Ntrip/2.0\r\n"))
    873           {
    874             fprintf(stderr,
    875             " Ntrip Version 2.0 not implemented at Destination caster"
    876             " <%s>%s%s%s\n%s\n"
    877             "caster fallback: Fallback to Ntrip Version 1.0\n",
    878             casterouthost,
    879             *proxyhost ? " or Proxy <" : "", proxyhost, *proxyhost ? ">" : "",
    880             *proxyhost ? " or HTTP/1.1 not implemented at Proxy\n" : "");
    881             outputmode = NTRIPV1;
     888            "POST %s/%s HTTP/1.1\r\n"
     889            "Host: %s\r\n"
     890            "Ntrip-Version: Ntrip/2.0\r\n"
     891            "User-Agent: %s/%s\r\n"
     892            "Authorization: Basic %s\r\n"
     893            "Ntrip-STR: %s\r\n"
     894            "Transfer-Encoding: chunked\r\n\r\n",
     895            post_extension, mountpoint, casterouthost, AGENTSTRING,
     896            revisionstr, authorization, ntrip_str);
     897          if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
     898          {
     899            fprintf(stderr, "ERROR: Destination caster request to long\n");
     900            reconnect_sec_max = 0;
     901            output_init = 0;
    882902            break;
    883903          }
    884           outputmode = END;
    885           break;
    886         }
    887 #ifndef NDEBUG
    888         else
    889         {
    890           fprintf(stderr, "Destination caster response:\n%s\n"
    891           "connection successfull\n",szSendBuffer);
    892         }
    893 #endif
    894         send_receive_loop(socket_tcp, gpsfd, outputmode, NULL, 0);
    895         break;
    896       case RTSP: /*** Ntrip-Version 2.0 RTSP / RTP ***/
    897         if((socket_udp = socket(AF_INET, SOCK_DGRAM,0)) < 0)
    898         {
    899           perror("ERROR: udp socket");
    900           exit(4);
    901         }
    902         /* fill structure with local address information for UDP */
    903         memset(&local, 0, sizeof(local));
    904         local.sin_family = AF_INET;
    905         local.sin_port = htons(0);
    906         local.sin_addr.s_addr = htonl(INADDR_ANY);
    907         len = (socklen_t)sizeof(local);
    908         /* bind() in order to get a random RTP client_port */
    909         if((bind(socket_udp,(struct sockaddr *)&local, len)) < 0)
    910         {
    911           perror("ERROR: udp bind");
    912           if(close(socket_udp)==-1) perror("ERROR: close udp socket");
    913           if(close(socket_tcp)==-1) perror("ERROR: close tcp socket");
    914           exit(4);
    915         }
    916         if((getsockname(socket_udp, (struct sockaddr*)&local, &len)) != -1)
    917         {
    918           client_port = (unsigned int)ntohs(local.sin_port);
    919         }else{
    920           perror("ERROR: getsockname(localhost)");
    921           if(close(socket_udp)==-1) perror("ERROR: close udp socket");
    922           if(close(socket_tcp)==-1) perror("ERROR: close tcp socket");
    923           exit(4);
    924         }
    925         nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
    926           "SETUP rtsp://%s%s/%s RTSP/1.0\r\n"
    927           "CSeq: 1\r\n"
    928           "Ntrip-Version: Ntrip/2.0\r\n"
    929           "Ntrip-Component: Ntripserver\r\n"
    930           "User-Agent: %s/%s\r\n"
    931           "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
    932           "Authorization: Basic %s\r\n"
    933           "Ntrip-STR: %s\r\n\r\n",
    934           casterouthost, rtsp_extension, mountpoint, AGENTSTRING, revisionstr,
    935           client_port, authorization, ntrip_str);
    936         if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
    937         {
    938           fprintf(stderr, "ERROR: Destination caster request to long\n");
    939           outputmode = END;
    940           break;
    941         }
    942         if (!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
    943         {
    944           outputmode = END;
    945           break;
    946         }
    947         while((nBufferBytes = recv(socket_tcp, szSendBuffer,
    948         sizeof(szSendBuffer), 0)) > 0)
    949         {
     904          if(!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
     905          {
     906            output_init = 0;
     907            break;
     908          }
    950909          /* check Destination caster's response */
     910          nBufferBytes = recv(socket_tcp, szSendBuffer, sizeof(szSendBuffer), 0);
    951911          szSendBuffer[nBufferBytes] = '\0';
    952           if(!strstr(szSendBuffer, "RTSP/1.0 200 OK"))
     912          if(!strstr(szSendBuffer, "HTTP/1.1 200 OK"))
    953913          {
    954914            char *a;
     
    958918            for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
    959919            {
    960               fprintf(stderr, "%c", isprint(*a) ? *a : '.');
     920              fprintf(stderr, "%.1s", isprint(*a) ? a : ".");
    961921            }
    962922            fprintf(stderr, "\n");
    963923            /* fallback if necessary */
    964             if(strncmp(szSendBuffer, "RTSP",4) != 0)
     924            if(!strstr(szSendBuffer,"Ntrip-Version: Ntrip/2.0\r\n"))
    965925            {
    966               if(strstr(szSendBuffer,"Ntrip-Version: Ntrip/2.0\r\n"))
     926              fprintf(stderr,
     927              "       Ntrip Version 2.0 not implemented at Destination caster"
     928              " <%s>%s%s%s\n%s\n"
     929              "ntripserver falls back to Ntrip Version 1.0\n\n",
     930              casterouthost,
     931              *proxyhost ? " or Proxy <" : "", proxyhost, *proxyhost ? ">" : "",
     932              *proxyhost ? "       or HTTP/1.1 not implemented at Proxy\n" : "");
     933              close_session(casterouthost, mountpoint, cseq, session, rtsp_extension, 1);
     934              outputmode = NTRIP1;
     935              break;
     936            }
     937            else if((strstr(szSendBuffer,"HTTP/1.1 401 Unauthorized"))
     938            || (strstr(szSendBuffer,"501 Not Implemented")))
     939            {
     940               reconnect_sec_max = 0;
     941            }
     942            output_init = 0;
     943            break;
     944          }
     945#ifndef NDEBUG
     946          else
     947          {
     948            fprintf(stderr, "Destination caster response:\n%s\n",szSendBuffer);
     949          }
     950#endif
     951          send_receive_loop(socket_tcp, gpsfd, outputmode, NULL, 0);
     952          break;
     953        case RTSP: /*** Ntrip-Version 2.0 RTSP / RTP ***/
     954          if((socket_udp = socket(AF_INET, SOCK_DGRAM,0)) < 0)
     955          {
     956            perror("ERROR: udp socket");
     957            exit(4);
     958          }
     959          /* fill structure with local address information for UDP */
     960          memset(&local, 0, sizeof(local));
     961          local.sin_family = AF_INET;
     962          local.sin_port = htons(0);
     963          local.sin_addr.s_addr = htonl(INADDR_ANY);
     964          len = (socklen_t)sizeof(local);
     965          /* bind() in order to get a random RTP client_port */
     966          if((bind(socket_udp,(struct sockaddr *)&local, len)) < 0)
     967          {
     968            perror("ERROR: udp bind");
     969            reconnect_sec_max = 0;
     970            output_init = 0;
     971            break;
     972          }
     973          if((getsockname(socket_udp, (struct sockaddr*)&local, &len)) != -1)
     974          {
     975            client_port = (unsigned int)ntohs(local.sin_port);
     976          }
     977          else
     978          {
     979            perror("ERROR: getsockname(localhost)");
     980            reconnect_sec_max = 0;
     981            output_init = 0;
     982            break;
     983          }
     984          nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
     985            "SETUP rtsp://%s%s/%s RTSP/1.0\r\n"
     986            "CSeq: 1\r\n"
     987            "Ntrip-Version: Ntrip/2.0\r\n"
     988            "Ntrip-Component: Ntripserver\r\n"
     989            "User-Agent: %s/%s\r\n"
     990            "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
     991            "Authorization: Basic %s\r\n"
     992            "Ntrip-STR: %s\r\n\r\n",
     993            casterouthost, rtsp_extension, mountpoint, AGENTSTRING, revisionstr,
     994            client_port, authorization, ntrip_str);
     995          if((nBufferBytes > (int)sizeof(szSendBuffer)) || (nBufferBytes < 0))
     996          {
     997            fprintf(stderr, "ERROR: Destination caster request to long\n");
     998            reconnect_sec_max = 0;
     999            output_init = 0;
     1000            break;
     1001          }
     1002          if(!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
     1003          {
     1004            output_init = 0;
     1005            break;
     1006          }
     1007          while((nBufferBytes = recv(socket_tcp, szSendBuffer,
     1008          sizeof(szSendBuffer), 0)) > 0)
     1009          {
     1010            /* check Destination caster's response */
     1011            szSendBuffer[nBufferBytes] = '\0';
     1012            if(!strstr(szSendBuffer, "RTSP/1.0 200 OK"))
     1013            {
     1014              char *a;
     1015              fprintf(stderr,
     1016              "ERROR: Destination caster's%s reply is not OK: ",
     1017              *proxyhost ? " or Proxy's" : "");
     1018              for(a = szSendBuffer; *a && *a != '\n' && *a != '\r'; ++a)
    9671019              {
    968                 fprintf(stderr,
    969                 " - RTSP not implemented at Destination caster <%s>%s%s%s\n\n"
    970                 "caster fallback: Fallback to Ntrip Version 2.0 in TCP/IP"
    971                 " mode\n\n", casterouthost,
    972                 *proxyhost ? " or Proxy <" :"", proxyhost, *proxyhost ? ">":"");
    973                 outputmode = HTTP;
     1020                fprintf(stderr, "%c", isprint(*a) ? *a : '.');
     1021              }
     1022              fprintf(stderr, "\n");
     1023              /* fallback if necessary */
     1024              if(strncmp(szSendBuffer, "RTSP",4) != 0)
     1025              {
     1026                if(strstr(szSendBuffer,"Ntrip-Version: Ntrip/2.0\r\n"))
     1027                {
     1028                  fprintf(stderr,
     1029                  "       RTSP not implemented at Destination caster <%s>%s%s%s\n\n"
     1030                  "ntripserver falls back to Ntrip Version 2.0 in TCP/IP"
     1031                  " mode\n\n", casterouthost,
     1032                  *proxyhost ? " or Proxy <" :"", proxyhost, *proxyhost ? ">":"");
     1033                  close_session(casterouthost, mountpoint, cseq, session, rtsp_extension, 1);
     1034                  outputmode = HTTP;
     1035                  break;
     1036                }
     1037                else
     1038                {
     1039                  fprintf(stderr,
     1040                  "       Ntrip-Version 2.0 not implemented at Destination caster"
     1041                  "<%s>%s%s%s\n%s"
     1042                  "       or RTSP/1.0 not implemented at Destination caster%s\n\n"
     1043                  "ntripserver falls back to Ntrip Version 1.0\n\n",
     1044                  casterouthost, *proxyhost ? " or Proxy <" :"", proxyhost,
     1045                  *proxyhost ? ">":"",
     1046                  *proxyhost ? " or HTTP/1.1 not implemented at Proxy\n" : "",
     1047                  *proxyhost ? " or Proxy" :"");
     1048                  close_session(casterouthost, mountpoint, cseq, session, rtsp_extension, 1);
     1049                  outputmode = NTRIP1;
     1050                  break;
     1051                }
     1052              }
     1053              else if((strstr(szSendBuffer, "RTSP/1.0 401 Unauthorized"))
     1054              || (strstr(szSendBuffer, "RTSP/1.0 501 Not Implemented")))
     1055              {
     1056                reconnect_sec_max = 0;
     1057              }
     1058              output_init = 0;
     1059              break;
     1060            }
     1061#ifndef NDEBUG
     1062            else
     1063            {
     1064              fprintf(stderr, "Destination caster response:\n%s\n",szSendBuffer);
     1065            }
     1066#endif
     1067            if((strstr(szSendBuffer,"RTSP/1.0 200 OK\r\n"))
     1068            && (strstr(szSendBuffer,"CSeq: 1\r\n")))
     1069            {
     1070              for(token = strtok(szSendBuffer, dlim); token != NULL;
     1071              token = strtok(NULL, dlim))
     1072              {
     1073                tok_buf[i] = token; i++;
     1074              }
     1075              session = atoi(tok_buf[6]);
     1076              server_port = atoi(tok_buf[10]);
     1077              nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
     1078                "POST rtsp://%s%s/%s RTSP/1.0\r\n"
     1079                "CSeq: 2\r\n"
     1080                "Session: %d\r\n"
     1081                "\r\n",
     1082                casterouthost, rtsp_extension,  mountpoint,  session);
     1083              if((nBufferBytes >= (int)sizeof(szSendBuffer))
     1084              || (nBufferBytes < 0))
     1085              {
     1086                fprintf(stderr, "ERROR: Destination caster request to long\n");
     1087                reconnect_sec_max = 0;
     1088                output_init = 0;
     1089                break;
     1090              }
     1091              if(!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
     1092              {
     1093                 output_init = 0;
     1094                 break;
     1095              }
     1096            }
     1097            else if((strstr(szSendBuffer,"RTSP/1.0 200 OK\r\n")) && (strstr(szSendBuffer,
     1098            "CSeq: 2\r\n")))
     1099            {
     1100              /* fill structure with caster address information for UDP */
     1101              memset(&casterRTP, 0, sizeof(casterRTP));
     1102              casterRTP.sin_family = AF_INET;
     1103              casterRTP.sin_port   = htons(((uint16_t)server_port));
     1104              if((he = gethostbyname(outhost))== NULL)
     1105              {
     1106                fprintf(stderr, "ERROR: Destination caster unknown\n");
     1107                reconnect_sec_max = 0;
     1108                output_init = 0;
    9741109                break;
    9751110              }
    9761111              else
    9771112              {
    978                 fprintf(stderr,
    979                 " Ntrip-Version 2.0 not implemented at Destination caster"
    980                 "<%s>%s%s%s\n%s"
    981                 " or RTSP/1.0 not implemented at Destination caster%s\n\n"
    982                 "caster fallback: Fallback to Ntrip Version 1.0\n",
    983                 casterouthost, *proxyhost ? " or Proxy <" :"", proxyhost,
    984                 *proxyhost ? ">":"",
    985                 *proxyhost ? " or HTTP/1.1 not implemented at Proxy\n" : "",
    986                 *proxyhost ? " or Proxy" :"");
    987                 outputmode = NTRIPV1;
    988                 break;
     1113                memcpy((char *)&casterRTP.sin_addr.s_addr,
     1114                he->h_addr_list[0], (size_t)he->h_length);
    9891115              }
    990             }
    991             else
    992             {
    993               outputmode = END;
     1116              cseq = 2;
     1117              len = (socklen_t)sizeof(casterRTP);
     1118              send_receive_loop(socket_udp, gpsfd, outputmode, (struct sockaddr *)&casterRTP,
     1119              (socklen_t)len);
    9941120              break;
    9951121            }
    996           }
    997 #ifndef NDEBUG
    998           else
    999           {
    1000             fprintf(stderr, "Destination caster response:\n%s\n",szSendBuffer);
    1001           }
    1002 #endif
    1003           if((strstr(szSendBuffer,"RTSP/1.0 200 OK\r\n"))
    1004           && (strstr(szSendBuffer,"CSeq: 1\r\n")))
    1005           {
    1006             for(token = strtok(szSendBuffer, dlim); token != NULL;
    1007             token = strtok(NULL, dlim))
    1008             {
    1009               tok_buf[i] = token; i++;
    1010             }
    1011             session = atoi(tok_buf[6]);
    1012             server_port = atoi(tok_buf[10]);
    1013             nBufferBytes = snprintf(szSendBuffer, sizeof(szSendBuffer),
    1014               "POST rtsp://%s%s/%s RTSP/1.0\r\n"
    1015               "CSeq: 2\r\n"
    1016               "Session: %d\r\n"
    1017               "\r\n",
    1018               casterouthost, rtsp_extension,  mountpoint,  session);
    1019             if((nBufferBytes >= (int)sizeof(szSendBuffer))
    1020             || (nBufferBytes < 0))
    1021             {
    1022               fprintf(stderr, "ERROR: Destination caster request to long\n");
    1023               outputmode = END;
    1024               break;
    1025             }
    1026             if(!send_to_caster(szSendBuffer, socket_tcp, nBufferBytes))
    1027             {
    1028                outputmode = END;
    1029                break;
    1030             }
    1031           }else if((strstr(szSendBuffer,"RTSP/1.0 200 OK\r\n")) && (strstr(szSendBuffer,"CSeq: 2\r\n"))) {
    1032             /* fill structure with caster address information for UDP */
    1033             memset(&casterRTP, 0, sizeof(casterRTP));
    1034             casterRTP.sin_family = AF_INET;
    1035             casterRTP.sin_port   = htons(((uint16_t)server_port));
    1036             if((he = gethostbyname(outhost))== NULL) {
    1037               fprintf(stderr, "ERROR: Destination caster unknown\n");
    1038               if(close(socket_udp)==-1) perror("ERROR: close udp socket");
    1039               if(close(socket_tcp)==-1) perror("ERROR: close tcp socket");
    1040               exit(4);
    1041             }else{
    1042               memcpy((char *)&casterRTP.sin_addr.s_addr,
    1043               he->h_addr_list[0], (size_t)he->h_length);
    1044             }
    1045             cseq = 2;
    1046             len = (socklen_t)sizeof(casterRTP);
    1047             send_receive_loop(socket_udp, gpsfd, outputmode, (struct sockaddr *)&casterRTP, (socklen_t)len);
    1048             break;
    1049           }else{break;}
    1050         }
    1051         break;
    1052     }
    1053   }
    1054   close_session(socket_udp, socket_tcp, casterouthost, mountpoint, cseq, session, rtsp_extension, gpsfd);
     1122            else{break;}
     1123          }
     1124          break;
     1125      }     
     1126    }
     1127    close_session(casterouthost, mountpoint, cseq, session, rtsp_extension, 0);
     1128    if((!sigint_received) && (reconnect_sec_max))
     1129    {
     1130       reconnect_sec = reconnect(reconnect_sec, reconnect_sec_max);
     1131    }
     1132    else inputmode = LAST;
     1133  }
    10551134  return 0;
    10561135}
     
    10761155  /* data transmission */
    10771156  fprintf(stderr,"transfering data ...\n");
    1078 
     1157  int send_recv_success = 0;
    10791158  while(1)
    10801159  {
     1160    if(send_recv_success < 3) send_recv_success++; 
     1161    if(!nodata) alarm(ALARMTIME);
     1162    else nodata = 0;
     1163
    10811164    /* signal handling*/
    1082     if(signal_was_caught())
    1083     {
    1084       fprintf(stderr, "NtripLinuxServer exits send-receive mode\n");
    1085       break;
    1086     }
    1087     if(!nodata) alarm(ALARMTIME);
    1088     else nodata = 0;
    1089 
     1165    if((sigint_received) || (sigpipe_received) || (sigalarm_received)) break;
     1166   
    10901167    if(!nBufferBytes)
    10911168    {
     
    11011178        if((send(gpsfd, "MSG\r\n", i, 0)) != i)
    11021179        {
    1103           perror("ERROR: sending SISNeT data request");
    1104           exit(1);
     1180          perror("WARNING: sending SISNeT data request failed");
     1181          return;
    11051182        }
    11061183      }
     
    11141191        continue;
    11151192      }
    1116       else if(nBufferBytes < 0)
    1117       {
    1118         perror("ERROR: reading input failed");
    1119         exit(1);
     1193      else if((nBufferBytes < 0) && (!sigint_received))
     1194      {
     1195        perror("WARNING: reading input failed");
     1196        return;
    11201197      }
    11211198      /* we can compare the whole buffer, as the additional bytes
     
    11281205    }
    11291206    /**  send data ***/
    1130     if((nBufferBytes)  && (outmode == NTRIPV1)) /*** Ntrip-Version 1.0 ***/
     1207    if((nBufferBytes)  && (outmode == NTRIP1)) /*** Ntrip-Version 1.0 ***/
    11311208    {
    11321209      int i;
     
    11381215          if(errno != EAGAIN)
    11391216          {
    1140             perror("WARNING: could not send data to Destination caster"
    1141             " - retry connection");
    1142             close(sock);
    1143             sleep(5);
     1217            perror("WARNING: could not send data to Destination caster");
    11441218            return;
    11451219          }
     
    11691243          if(errno != EAGAIN)
    11701244          {
    1171             perror("WARNING: could not send data to Destination caster"
    1172             " - retry connection");
    1173             close(sock);
    1174             sleep(5);
     1245            perror("WARNING: could not send data to Destination caster");
    11751246            return;
    11761247          }
     
    11951266      char rtpbuffer[BUFSZ+12];
    11961267      int i, j;
    1197       /* Signal Handling */
    1198       if(signal_was_caught())
    1199       {
    1200         fprintf(stderr, "NtripLinuxServer exits send-receive mode\n");
    1201         break;
    1202       }
    12031268      gettimeofday(&now, NULL);
    12041269      /* RTP data packet generation*/
     
    12421307          if(errno != EAGAIN)
    12431308          {
    1244             perror("WARNING: could not send data to Destination caster - retry connection");
    1245             close(sock);
    1246             sleep(5);
     1309            perror("WARNING: could not send data to Destination caster");
    12471310            return;
    12481311          }
     
    12591322      }
    12601323    }
     1324    if(send_recv_success == 3) reconnect_sec = 1;
    12611325  }
    12621326  return;
     
    14221486  fprintf(stderr, "                         optional\n");
    14231487  fprintf(stderr, "    -F <ProxyPort>       Proxy server IP port, required i.e. when running\n");
    1424   fprintf(stderr, "                         the program in a proxy server protected LAN, optional\n\n");
     1488  fprintf(stderr, "                         the program in a proxy server protected LAN, optional\n");
     1489  fprintf(stderr, "    -R <maxDelay>        Reconnect mechanism with maximum delay between reconnect\n");
     1490  fprintf(stderr, "                         attemts in seconds, default: no reconnect activated,\n");
     1491  fprintf(stderr, "                         optional\n\n");
    14251492  fprintf(stderr, "    -M <InputMode> Sets the input mode (1 = Serial Port, 2 = IP server,\n");
    14261493  fprintf(stderr, "       3 = File, 4 = SISNeT Data Server, 5 = UDP server, 6 = NTRIP Caster),\n");
     
    14641531  fprintf(stderr, "                         for protected streams if <InputMode> = 6\n\n");
    14651532  fprintf(stderr, "    -O <OutputMode> Sets output mode for communatation with destination caster\n");
    1466   fprintf(stderr, "       0 = h = http: Ntrip Version 2.0 Caster in TCP/IP mode\n");
    1467   fprintf(stderr, "       1 = r = rtsp: NTRIP Version 2.0 Caster in RTSP/RTP mode\n");
    1468   fprintf(stderr, "       2 = n = ntrip1: NTRIP Version 1.0 Caster\n\n");
    1469   fprintf(stderr, "       Defaults to NTRIP1.0, but wil change to 2.0 in future versions\n");
    1470   fprintf(stderr, "       Note that the program automatically falls back from mode r to mode t and\n");
    1471   fprintf(stderr, "       further to mode f if necessary.\n\n");
     1533  fprintf(stderr, "       1 = http: NTRIP Version 2.0 Caster in TCP/IP mode\n");
     1534  fprintf(stderr, "       2 = rtsp: NTRIP Version 2.0 Caster in RTSP/RTP mode\n");
     1535  fprintf(stderr, "       3 = ntrip1: NTRIP Version 1.0 Caster\n");
     1536  fprintf(stderr, "       optional\n\n");
     1537  fprintf(stderr, "       Defaults to NTRIP1.0, but will change to 2.0 in future versions\n");
     1538  fprintf(stderr, "       Note that the program automatically falls back from mode rtsp to mode http and\n");
     1539  fprintf(stderr, "       further to mode ntrip1 if necessary.\n\n");
    14721540  fprintf(stderr, "       -a <DestHost>     Destination caster name or address, default: 127.0.0.1,\n");
    14731541  fprintf(stderr, "                         mandatory\n");
     
    14811549  fprintf(stderr, "                         mountpoint, mandatory\n");
    14821550  fprintf(stderr, "       -N <STR-record>   Sourcetable STR-record\n");
    1483   fprintf(stderr, "                         optional for Ntrip Version 2.0 in RTSP/RTP and TCP/IP mode\n\n");
     1551  fprintf(stderr, "                         optional for NTRIP Version 2.0 in RTSP/RTP and TCP/IP mode\n\n");
    14841552  exit(rc);
    14851553} /* usage */
     
    14941562static void handle_sigint(int sig)
    14951563#endif /* __GNUC__ */
    1496 {sigint_received  = 1;}
     1564{
     1565  sigint_received  = 1;
     1566  fprintf(stderr, "WARNING: SIGINT received - ntripserver terminates\n");
     1567}
     1568
     1569#ifdef __GNUC__
     1570static void handle_alarm(int sig __attribute__((__unused__)))
     1571#else /* __GNUC__ */
     1572static void handle_alarm(int sig)
     1573#endif /* __GNUC__ */
     1574{
     1575  sigalarm_received = 1;
     1576  fprintf(stderr, "ERROR: more than %d seconds no activity\n", ALARMTIME);
     1577}
     1578
     1579#ifdef __GNUC__
     1580static void handle_sigpipe(int sig __attribute__((__unused__)))
     1581#else /* __GNUC__ */
     1582static void handle_sigpipe(int sig)
     1583#endif /* __GNUC__ */
     1584{sigpipe_received = 1;}
    14971585
    14981586static void setup_signal_handler(int sig, void (*handler)(int))
     
    15111599  return;
    15121600} /* setupsignal_handler */
    1513 
    1514 static int signal_was_caught(void)
    1515 {
    1516   fflush(stdout);
    1517   if(sigint_received)
    1518     fprintf(stderr, "SIGINT received: ");
    1519 
    1520   return (sigint_received);
    1521 } /* signal_was_caught */
    15221601
    15231602/********************************************************************
     
    15841663  if((send(socket, input, (size_t)input_size, 0)) != input_size)
    15851664  {
    1586     fprintf(stderr, "ERROR: could not send full header to Destination caster\n");
     1665    fprintf(stderr, "WARNING: could not send full header to Destination caster\n");
    15871666    send_error = 0;
    15881667  }
     
    15991678
    16001679/********************************************************************
     1680 * reconnect                                                        *
     1681*********************************************************************/
     1682int reconnect(int rec_sec, int rec_sec_max)
     1683{
     1684  fprintf(stderr,"reconnect in <%d> seconds\n\n", rec_sec);
     1685  rec_sec *= 2;
     1686  if (rec_sec > rec_sec_max) rec_sec = rec_sec_max;
     1687  sleep(rec_sec);
     1688  sigalarm_received = 0;
     1689  sigpipe_received = 0;
     1690  return rec_sec;
     1691} /* reconnect */
     1692
     1693
     1694/********************************************************************
    16011695 * close session                                                    *
    16021696*********************************************************************/
    1603 static void close_session(int sock_udp, int sock_tcp,
    1604 const char *caster_addr, const char *mountpoint, int cseq,
    1605 int session, char *rtsp_ext, int in_fd)
     1697static void close_session(const char *caster_addr, const char *mountpoint,
     1698int cseq, int session, char *rtsp_ext, int fallback)
    16061699{
    16071700  int  size_send_buf;
    16081701  char send_buf[BUFSZ];
    16091702
    1610   if(in_fd)
    1611   {
    1612     if(close(in_fd)==-1)
     1703  if((gpsfd != -1) && (!fallback))
     1704  {
     1705    if(close(gpsfd) == -1)
    16131706    {
    16141707      perror("ERROR: close input device ");
    16151708      exit(0);
    16161709    }
    1617 #ifndef NDEBUG
    16181710    else
    16191711    {
    1620       fprintf(stderr, "\nclose input device: successful\n");
    1621     }
     1712      gpsfd = -1;
     1713#ifndef NDEBUG 
     1714    fprintf(stderr, "close input device: successful\n");
    16221715#endif
    1623   }
    1624 
    1625   if(sock_udp  != 0)
     1716    }
     1717  }
     1718
     1719  if(socket_udp  != -1)
    16261720  {
    16271721    if(cseq == 2)
     
    16381732        exit(0);
    16391733      }
    1640       send_to_caster(send_buf, sock_tcp, size_send_buf); strcpy(send_buf,"");
    1641       size_send_buf = recv(sock_tcp, send_buf, sizeof(send_buf), 0);
     1734      send_to_caster(send_buf, socket_tcp, size_send_buf); strcpy(send_buf,"");
     1735      size_send_buf = recv(socket_tcp, send_buf, sizeof(send_buf), 0);
    16421736      send_buf[size_send_buf] = '\0';
    16431737#ifndef NDEBUG
     
    16451739#endif
    16461740    }
    1647     if(close(sock_udp)==-1)
     1741    if(close(socket_udp)==-1)
    16481742    {
    16491743      perror("ERROR: close udp socket");
    16501744      exit(0);
    16511745    }
     1746    else
     1747    {
     1748      socket_udp = -1;
    16521749#ifndef NDEBUG
     1750      fprintf(stderr, "close udp socket: successful\n");
     1751#endif
     1752    }
     1753  }
     1754
     1755  if(socket_tcp != -1)
     1756  {
     1757    if(close(socket_tcp) == -1)
     1758    {
     1759      perror("ERROR: close tcp socket");
     1760      exit(0);
     1761    }
    16531762    else
    16541763    {
    1655       fprintf(stderr, "close udp socket:   successful\n");
    1656     }
     1764      socket_tcp = -1;
     1765#ifndef NDEBUG
     1766      fprintf(stderr, "close tcp socket: successful\n");
    16571767#endif
    1658   }
    1659 
    1660   if(close(sock_tcp)==-1)
    1661   {
    1662     perror("ERROR: close tcp socket");
    1663     exit(0);
    1664   }
    1665 #ifndef NDEBUG
    1666   else
    1667   {
    1668     fprintf(stderr, "close tcp socket:   successful\n\n");
    1669   }
    1670 #endif
     1768    }
     1769  }
    16711770} /* close_session */
Note: See TracChangeset for help on using the changeset viewer.