• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

Connection.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /**************************************************************************
00025   Connections
00026 
00027   Commonality across all platforms -- move out as required.
00028 
00029 **************************************************************************/
00030 #include "libts.h"
00031 
00032 #include "P_Net.h"
00033 
00034 #define SET_TCP_NO_DELAY
00035 #define SET_NO_LINGER
00036 // set in the OS
00037 // #define RECV_BUF_SIZE            (1024*64)
00038 // #define SEND_BUF_SIZE            (1024*64)
00039 #define FIRST_RANDOM_PORT        16000
00040 #define LAST_RANDOM_PORT         32000
00041 
00042 #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
00043 
00044 #ifndef FD_CLOEXEC
00045 #define FD_CLOEXEC 1
00046 #endif
00047 
00048 int
00049 get_listen_backlog(void)
00050 {
00051   int listen_backlog = 1024;
00052 
00053   REC_ReadConfigInteger(listen_backlog, "proxy.config.net.listen_backlog");
00054   return listen_backlog;
00055 }
00056 
00057 
00058 //
00059 // Functions
00060 //
00061 char const*
00062 NetVCOptions::toString(addr_bind_style s) {
00063   return ANY_ADDR == s ? "any"
00064     : INTF_ADDR == s ? "interface"
00065     : "foreign"
00066     ;
00067 }
00068 
00069 Connection::Connection()
00070   : fd(NO_FD)
00071   , is_bound(false)
00072   , is_connected(false)
00073   , sock_type(0)
00074 {
00075   memset(&addr, 0, sizeof(addr));
00076 }
00077 
00078 
00079 Connection::~Connection()
00080 {
00081   close();
00082 }
00083 
00084 
00085 int
00086 Server::accept(Connection * c)
00087 {
00088   int res = 0;
00089   socklen_t sz = sizeof(c->addr);
00090 
00091   res = socketManager.accept(fd, &c->addr.sa, &sz);
00092   if (res < 0)
00093     return res;
00094   c->fd = res;
00095   if (is_debug_tag_set("iocore_net_server")) {
00096     ip_port_text_buffer ipb1, ipb2;
00097       Debug("iocore_net_server", "Connection accepted [Server]. %s -> %s\n"
00098         , ats_ip_nptop(&c->addr, ipb2, sizeof(ipb2))
00099         , ats_ip_nptop(&addr, ipb1, sizeof(ipb1))
00100       );
00101   }
00102 
00103 #ifdef SET_CLOSE_ON_EXEC
00104   if ((res = safe_fcntl(fd, F_SETFD, FD_CLOEXEC)) < 0)
00105     goto Lerror;
00106 #endif
00107   if ((res = safe_nonblocking(c->fd)) < 0)
00108     goto Lerror;
00109 #ifdef SEND_BUF_SIZE
00110   socketManager.set_sndbuf_size(c->fd, SEND_BUF_SIZE);
00111 #endif
00112 #ifdef SET_SO_KEEPALIVE
00113   // enables 2 hour inactivity probes, also may fix IRIX FIN_WAIT_2 leak
00114   if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_ON, sizeof(int))) < 0)
00115     goto Lerror;
00116 #endif
00117 
00118   return 0;
00119 
00120 Lerror:
00121   c->close();
00122   return res;
00123 }
00124 
00125 
00126 int
00127 Connection::close()
00128 {
00129   is_connected = false;
00130   is_bound = false;
00131   // don't close any of the standards
00132   if (fd >= 2) {
00133     int fd_save = fd;
00134     fd = NO_FD;
00135     return socketManager.close(fd_save);
00136   } else {
00137     fd = NO_FD;
00138     return -EBADF;
00139   }
00140 }
00141 
00142 static int
00143 add_http_filter(int fd ATS_UNUSED)
00144 {
00145   int err = -1;
00146 #if defined(SOL_FILTER) && defined(FIL_ATTACH)
00147   err = setsockopt(fd, SOL_FILTER, FIL_ATTACH, "httpfilt", 9);
00148 #endif
00149   return err;
00150 }
00151 
00152 int
00153 Server::setup_fd_for_listen(
00154   bool non_blocking,
00155   int recv_bufsize,
00156   int send_bufsize,
00157   bool transparent)
00158 {
00159   int res = 0;
00160 
00161   ink_assert(fd != NO_FD);
00162 
00163   if (http_accept_filter) {
00164     add_http_filter(fd);
00165   }
00166 
00167 #ifdef SEND_BUF_SIZE
00168   {
00169     int send_buf_size = SEND_BUF_SIZE;
00170     if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &send_buf_size, sizeof(int)) < 0)) {
00171       goto Lerror;
00172     }
00173   }
00174 #endif
00175 
00176 #ifdef RECV_BUF_SIZE
00177   {
00178     int recv_buf_size = RECV_BUF_SIZE;
00179     if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &recv_buf_size, sizeof(int))) < 0) {
00180       goto Lerror;
00181     }
00182   }
00183 #endif
00184 
00185   if (recv_bufsize) {
00186     if (socketManager.set_rcvbuf_size(fd, recv_bufsize)) {
00187       // Round down until success
00188       int rbufsz = ROUNDUP(recv_bufsize, 1024);
00189       while (rbufsz) {
00190         if (socketManager.set_rcvbuf_size(fd, rbufsz)) {
00191           rbufsz -= 1024;
00192         } else {
00193           break;
00194         }
00195       }
00196     }
00197   }
00198 
00199   if (send_bufsize) {
00200     if (socketManager.set_sndbuf_size(fd, send_bufsize)) {
00201       // Round down until success
00202       int sbufsz = ROUNDUP(send_bufsize, 1024);
00203       while (sbufsz) {
00204         if (socketManager.set_sndbuf_size(fd, sbufsz)) {
00205           sbufsz -= 1024;
00206         } else {
00207           break;
00208         }
00209       }
00210     }
00211   }
00212 
00213 #ifdef SET_CLOSE_ON_EXEC
00214   if ((res = safe_fcntl(fd, F_SETFD, FD_CLOEXEC)) < 0) {
00215     goto Lerror;
00216   }
00217 #endif
00218 
00219 #ifdef SET_NO_LINGER
00220   {
00221     struct linger l;
00222     l.l_onoff = 0;
00223     l.l_linger = 0;
00224     if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l))) < 0) {
00225       goto Lerror;
00226     }
00227   }
00228 #endif
00229 
00230   if (ats_is_ip6(&addr) && (res = safe_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, SOCKOPT_ON, sizeof(int))) < 0) {
00231     goto Lerror;
00232   }
00233 
00234   if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, SOCKOPT_ON, sizeof(int))) < 0) {
00235     goto Lerror;
00236   }
00237 
00238 #ifdef SET_TCP_NO_DELAY
00239   if ((res = safe_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, SOCKOPT_ON, sizeof(int))) < 0) {
00240     goto Lerror;
00241   }
00242 #endif
00243 
00244 #ifdef SET_SO_KEEPALIVE
00245   // enables 2 hour inactivity probes, also may fix IRIX FIN_WAIT_2 leak
00246   if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_ON, sizeof(int))) < 0) {
00247     goto Lerror;
00248   }
00249 #endif
00250 
00251   if (transparent) {
00252 #if TS_USE_TPROXY
00253     Debug("http_tproxy", "Listen port inbound transparency enabled.\n");
00254     if (safe_setsockopt(fd, SOL_IP, TS_IP_TRANSPARENT, SOCKOPT_ON, sizeof(int)) < 0) {
00255       Error("[Server::listen] Unable to set transparent socket option [%d] %s\n", errno, strerror(errno));
00256       _exit(1);
00257     }
00258 #else
00259     Error("[Server::listen] Transparency requested but TPROXY not configured\n");
00260 #endif
00261   }
00262 
00263 #if defined(TCP_MAXSEG)
00264   if (NetProcessor::accept_mss > 0) {
00265     if ((res = safe_setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, (char *) &NetProcessor::accept_mss, sizeof(int))) < 0) {
00266       goto Lerror;
00267     }
00268   }
00269 #endif
00270 
00271   if (non_blocking) {
00272     if ((res = safe_nonblocking(fd)) < 0) {
00273       goto Lerror;
00274     }
00275   }
00276 
00277   return 0;
00278 
00279 Lerror:
00280   res = -errno;
00281 
00282   // coverity[check_after_sink]
00283   if (fd != NO_FD) {
00284     close();
00285     fd = NO_FD;
00286   }
00287 
00288   return res;
00289 }
00290 
00291 
00292 int
00293 Server::listen(bool non_blocking, int recv_bufsize, int send_bufsize, bool transparent)
00294 {
00295   ink_assert(fd == NO_FD);
00296   int res = 0;
00297   int namelen;
00298 
00299   if (!ats_is_ip(&accept_addr)) {
00300     ats_ip4_set(&addr, INADDR_ANY, 0);
00301   } else {
00302     ats_ip_copy(&addr, &accept_addr);
00303   }
00304 
00305   fd = res = socketManager.socket(addr.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
00306   if (res < 0) {
00307     goto Lerror;
00308   }
00309 
00310   res = setup_fd_for_listen(non_blocking, recv_bufsize, send_bufsize, transparent);
00311   if (res < 0) {
00312     goto Lerror;
00313   }
00314 
00315   if ((res = socketManager.ink_bind(fd, &addr.sa, ats_ip_size(&addr.sa), IPPROTO_TCP)) < 0) {
00316     goto Lerror;
00317   }
00318 
00319   if ((res = safe_listen(fd, get_listen_backlog())) < 0) {
00320     goto Lerror;
00321   }
00322 
00323   // Original just did this on port == 0.
00324   namelen = sizeof(addr);
00325   if ((res = safe_getsockname(fd, &addr.sa, &namelen))) {
00326       goto Lerror;
00327   }
00328 
00329   return 0;
00330 
00331 Lerror:
00332   if (fd != NO_FD) {
00333     close();
00334     fd = NO_FD;
00335   }
00336 
00337   Error("Could not bind or listen to port %d (error: %d)", ats_ip_port_host_order(&addr), res);
00338   return res;
00339 }

Generated by  doxygen 1.7.1