/*! \brief Set all socket/fd options: disable nagle, tos lowdelay, * non-blocking * \return -1 on error */ int tcp_init_sock_opt(int s) { int flags; int optval; #ifdef DISABLE_NAGLE flags=1; if ( (tcp_proto_no!=-1) && (setsockopt(s, tcp_proto_no , TCP_NODELAY, &flags, sizeof(flags))<0) ){ LM_WARN("could not disable Nagle: %s\n", strerror(errno)); } #endif /* tos*/ optval = tos; if (setsockopt(s, IPPROTO_IP, IP_TOS, (void*)&optval,sizeof(optval)) ==-1){ LM_WARN("setsockopt tos: %s\n", strerror(errno)); /* continue since this is not critical */ } if (probe_max_sock_buff(s,1,MAX_SEND_BUFFER_SIZE,BUFFER_INCREMENT)) { LM_WARN("setsockopt tcp snd buff: %s\n", strerror(errno)); /* continue since this is not critical */ } init_sock_keepalive(s); /* non-blocking */ flags=fcntl(s, F_GETFL); if (flags==-1){ LM_ERR("fcntl failed: (%d) %s\n", errno, strerror(errno)); goto error; } if (fcntl(s, F_SETFL, flags|O_NONBLOCK)==-1){ LM_ERR("set non-blocking failed: (%d) %s\n", errno, strerror(errno)); goto error; } return 0; error: return -1; }
int tcp_init(struct socket_info* sock_info) { union sockaddr_union* addr; int optval; #ifdef DISABLE_NAGLE int flag; struct protoent* pe; if (tcp_proto_no==-1){ /* if not already set */ pe=getprotobyname("tcp"); if (pe==0){ LM_ERR("could not get TCP protocol number\n"); tcp_proto_no=-1; }else{ tcp_proto_no=pe->p_proto; } } #endif addr=&sock_info->su; /* sock_info->proto=PROTO_TCP; */ if (init_su(addr, &sock_info->address, sock_info->port_no)<0){ LM_ERR("could no init sockaddr_union\n"); goto error; } sock_info->socket=socket(AF2PF(addr->s.sa_family), SOCK_STREAM, 0); if (sock_info->socket==-1){ LM_ERR("socket: %s\n", strerror(errno)); goto error; } #ifdef DISABLE_NAGLE flag=1; if ( (tcp_proto_no!=-1) && (setsockopt(sock_info->socket, tcp_proto_no , TCP_NODELAY, &flag, sizeof(flag))<0) ){ LM_ERR("could not disable Nagle: %s\n", strerror(errno)); } #endif #if !defined(TCP_DONT_REUSEADDR) /* Stevens, "Network Programming", Section 7.5, "Generic Socket * Options": "...server started,..a child continues..on existing * connection..listening server is restarted...call to bind fails * ... ALL TCP servers should specify the SO_REUSEADDRE option * to allow the server to be restarted in this situation * * Indeed, without this option, the server can't restart. * -jiri */ optval=1; if (setsockopt(sock_info->socket, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval))==-1) { LM_ERR("setsockopt %s\n", strerror(errno)); goto error; } #endif /* tos */ optval = tos; if (setsockopt(sock_info->socket, IPPROTO_IP, IP_TOS, (void*)&optval, sizeof(optval)) ==-1){ LM_WARN("setsockopt tos: %s\n", strerror(errno)); /* continue since this is not critical */ } if (probe_max_sock_buff(sock_info->socket,1,MAX_SEND_BUFFER_SIZE, BUFFER_INCREMENT)) { LM_WARN("setsockopt tcp snd buff: %s\n", strerror(errno)); /* continue since this is not critical */ } if (bind(sock_info->socket, &addr->s, sockaddru_len(*addr))==-1){ LM_ERR("bind(%x, %p, %d) on %s:%d : %s\n", sock_info->socket, &addr->s, (unsigned)sockaddru_len(*addr), sock_info->address_str.s, sock_info->port_no, strerror(errno)); goto error; } if (listen(sock_info->socket, 10)==-1){ LM_ERR("listen(%x, %p, %d) on %s: %s\n", sock_info->socket, &addr->s, (unsigned)sockaddru_len(*addr), sock_info->address_str.s, strerror(errno)); goto error; } return 0; error: if (sock_info->socket!=-1){ close(sock_info->socket); sock_info->socket=-1; } return -1; }