"Fossies" - the Fresh Open Source Software Archive

Member "HTTPing-2.9/tcp.c" (29 Oct 2022, 5148 Bytes) of package /linux/www/HTTPing-2.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tcp.c" see the Fossies "Dox" file reference documentation.

    1 /* Released under AGPL v3 with exception for the OpenSSL library. See license.txt */
    2 
    3 #include <sys/types.h>
    4 #include <sys/time.h>
    5 #include <sys/socket.h>
    6 #include <netinet/in.h>
    7 #include <netinet/tcp.h>
    8 #include <arpa/inet.h>
    9 #include <libintl.h>
   10 #include <netdb.h>
   11 #include <errno.h>
   12 #include <stdio.h>
   13 #include <string.h>
   14 #include <unistd.h>
   15 
   16 #include "error.h"
   17 #include "gen.h"
   18 #include "io.h"
   19 #include "main.h"
   20 #include "tcp.h"
   21 
   22 void failure_close(int fd)
   23 {
   24     struct linger sl;
   25 
   26     sl.l_onoff = 1;
   27     sl.l_linger = 0;
   28 
   29     if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &sl, sizeof sl) == -1)
   30         set_error(gettext("could not set TCP_NODELAY on socket (%s)"), strerror(errno));
   31 
   32     close(fd);
   33 }
   34 
   35 int set_no_delay(int fd)
   36 {
   37     int flag = 1;
   38 
   39     if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) == -1)
   40     {
   41         set_error(gettext("could not set TCP_NODELAY on socket (%s)"), strerror(errno));
   42         return -1;
   43     }
   44 
   45     return 0;
   46 }
   47 
   48 int create_socket(struct sockaddr *bind_to, struct addrinfo *ai, int recv_buffer_size, int tx_buffer_size, int max_mtu, char use_no_delay, int priority, int tos)
   49 {
   50     int fd = -1;
   51 
   52     /* create socket */
   53     fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
   54     if (fd == -1)
   55     {
   56         set_error(gettext("problem creating socket (%s)"), strerror(errno));
   57         return RC_INVAL;
   58     }
   59 
   60     /* go through a specific interface? */
   61     if (bind_to)
   62     {
   63         int set = 1;
   64 
   65         /* set reuse flags */
   66         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &set, sizeof set) == -1)
   67         {
   68             set_error(gettext("error setting sockopt to interface (%s)"), strerror(errno));
   69             close(fd);
   70             return RC_INVAL;
   71         }
   72 
   73         if (bind(fd, bind_to, sizeof *bind_to) == -1)
   74         {
   75             set_error(gettext("error binding to interface (%s)"), strerror(errno));
   76             close(fd);
   77             return RC_INVAL;
   78         }
   79     }
   80 
   81     if (max_mtu >= 0)
   82     {
   83         if (setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &max_mtu, sizeof max_mtu) == -1)
   84         {
   85             set_error(gettext("error setting MTU size (%s)"), strerror(errno));
   86             close(fd);
   87             return RC_INVAL;
   88         }
   89     }
   90 
   91     if (use_no_delay)
   92     {
   93         int rc = -1;
   94 
   95         if ((rc = set_no_delay(fd)) != 0)
   96             return rc;
   97     }
   98 
   99     if (tx_buffer_size > 0)
  100         {
  101         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&tx_buffer_size, sizeof tx_buffer_size) == -1)
  102         {
  103             set_error(gettext("error setting transmit buffer size (%s)"), strerror(errno));
  104             close(fd);
  105             return RC_INVAL;
  106         }
  107     }
  108 
  109     if (recv_buffer_size > 0)
  110         {
  111         if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buffer_size, sizeof recv_buffer_size) == -1)
  112         {
  113             set_error(gettext("error setting receive buffer size (%s)"), strerror(errno));
  114             close(fd);
  115             return RC_INVAL;
  116         }
  117     }
  118 
  119 #ifdef linux
  120     if (priority >= 0)
  121     {
  122         if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (char *)&priority, sizeof priority) == -1)
  123         {
  124             set_error(gettext("error setting priority (%s)"), strerror(errno));
  125             close(fd);
  126             return RC_INVAL;
  127         }
  128     }
  129 #endif
  130 
  131     if (tos >= 0)
  132     {
  133         if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof tos) == -1)
  134         {
  135             set_error(gettext("failed to set TOS info"));
  136             close(fd);
  137             return RC_INVAL;
  138         }
  139     }
  140 
  141     return fd;
  142 }
  143 
  144 int connect_to(int fd, struct addrinfo *ai, double timeout, char *tfo, char *msg, int msg_len, char *msg_accepted)
  145 {
  146     int rc = -1;
  147     struct timeval to;
  148     fd_set wfds;
  149 
  150     /* make fd nonblocking */
  151     if (set_fd_nonblocking(fd) == -1)
  152         return RC_INVAL;
  153 
  154     /* wait for connection */
  155     FD_ZERO(&wfds);
  156     FD_SET(fd, &wfds);
  157 
  158     to.tv_sec  = (long)(timeout / 1000.0);
  159     to.tv_usec = (long)(timeout * 1000.0) % 1000000;
  160 
  161     /* connect to peer */
  162 #ifdef TCP_TFO
  163     if (tfo && *tfo)
  164     {
  165         rc = sendto(fd, msg, msg_len, MSG_FASTOPEN, ai -> ai_addr, ai -> ai_addrlen);
  166         
  167         if(rc == msg_len)
  168             *msg_accepted = 1;
  169         if(errno == 0)
  170             return RC_OK;
  171         if(errno == ENOTSUP)
  172         {
  173             printf(gettext("TCP TFO Not Supported. Please check if \"/proc/sys/net/ipv4/tcp_fastopen\" is 1. Disabling TFO for now.\n"));
  174             *tfo = 0;
  175             goto old_connect;
  176         }
  177     }
  178             
  179     else
  180 #else
  181     (void)tfo;
  182     (void)msg;
  183     (void)msg_len;
  184     (void)msg_accepted;
  185 #endif
  186     {
  187         int rc = -1;
  188 
  189 old_connect:
  190         rc = connect(fd, ai -> ai_addr, ai -> ai_addrlen);
  191 
  192         if (rc == 0)
  193         {
  194             /* connection made, return */
  195             return RC_OK;
  196         }
  197 
  198         if (rc == -1)
  199         {
  200             /* problem connecting */
  201             if (errno != EINPROGRESS)
  202             {
  203                 set_error(gettext("problem connecting to host: %s"), strerror(errno));
  204                 return RC_INVAL;
  205             }
  206         }
  207     }
  208 
  209     if (stop)
  210         return RC_CTRLC;
  211 
  212     /* wait for connection */
  213     rc = select(fd + 1, NULL, &wfds, NULL, &to);
  214     if (rc == 0)
  215     {
  216         set_error(gettext("connect time out"));
  217         return RC_TIMEOUT;  /* timeout */
  218     }
  219     else if (rc == -1)
  220     {
  221         if (errno == EINTR)
  222             return RC_CTRLC;/* ^C pressed */
  223 
  224         set_error(gettext("select() failed: %s"), strerror(errno));
  225 
  226         return RC_INVAL;    /* error */
  227     }
  228     else
  229     {
  230         int optval=0;
  231         socklen_t optvallen = sizeof optval;
  232 
  233         /* see if the connect succeeded or failed */
  234         if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optvallen) == -1)
  235         {
  236             set_error(gettext("getsockopt failed (%s)"), strerror(errno));
  237             return RC_INVAL;
  238         }
  239 
  240         /* no error? */
  241         if (optval == 0)
  242             return RC_OK;
  243 
  244         /* don't ask */
  245         errno = optval;
  246     }
  247 
  248     set_error(gettext("could not connect (%s)"), strerror(errno));
  249 
  250     return RC_INVAL;
  251 }