4 #include <netinet/ip.h>
5 #include <netinet/tcp.h>
7 int socket_bind(string host_port_str) {
8 const char *cs(strrchr(host_port_str.c_str(),':'));
9 const string node(!cs?"":host_port_str.substr(0,cs-host_port_str.c_str()));
10 const string service(!cs?host_port_str:cs+1);
11 struct addrinfo hints={}; // designated initializer: error: missing initializer for member ... [-Werror=missing-field-initializers]
12 hints.ai_family=AF_UNSPEC; /* Allow IPv4 or IPv6 */
13 hints.ai_socktype=SOCK_STREAM;
14 hints.ai_flags=AI_PASSIVE|AI_ADDRCONFIG; /* For wildcard IP address */
15 struct addrinfo *result;
16 int err(getaddrinfo(node.empty()?NULL:node.c_str(),service.c_str(),&hints,&result));
18 fatal("<%s>:<%s>: %s",node.c_str(),service.c_str(),gai_strerror(err));
21 for (rp=result;rp;rp=rp->ai_next) {
22 fd=socket(rp->ai_family,rp->ai_socktype,rp->ai_protocol);
25 static const int int1(1);
26 err=setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&int1,sizeof(int1));
28 if (bind(fd,rp->ai_addr,rp->ai_addrlen)==0)
34 fatal("Cannot bind(): <%s>:<%s>: %m",node.c_str(),service.c_str());
37 err=listen(fd,SOMAXCONN);
42 string sockaddr_string(const struct sockaddr *sockaddrp,socklen_t socklen) {
43 char hostname[NI_MAXHOST];
44 char servname[NI_MAXSERV];
45 const int err=getnameinfo(sockaddrp,socklen,hostname,sizeof(hostname),servname,sizeof(servname),NI_NUMERICSERV/*flags*/);
47 return stringf("%s:%s",hostname,servname);
50 string socket_name(int socket_fd) {
51 struct sockaddr sockaddr;
52 socklen_t socklen(sizeof(sockaddr));
53 const int err(getsockname(socket_fd,&sockaddr,&socklen));
55 return sockaddr_string(&sockaddr,socklen);
58 static void socket_setopt(int fd) {
59 static const int int1(1);
61 err=setsockopt(fd,SOL_SOCKET,SO_KEEPALIVE,&int1,sizeof(int1));
63 static const uint8_t tos(IPTOS_LOWDELAY);
64 err=setsockopt(fd,IPPROTO_IP,IP_TOS,&tos,sizeof(tos));
66 err=setsockopt(fd,IPPROTO_IP,TCP_NODELAY,&int1,sizeof(int1));
70 int socket_accept(int listen_fd,function<void(int client_fd,string addr)> msgfunc) {
71 struct sockaddr sockaddr;
72 socklen_t socklen(sizeof(sockaddr));
73 const int client_fd(accept(listen_fd,&sockaddr,&socklen));
75 msgfunc(client_fd,sockaddr_string(&sockaddr,socklen));
76 socket_setopt(client_fd);
80 int socket_connect(const string &host_port_str,unsigned retries) {
81 const char *cs(strrchr(host_port_str.c_str(),':'));
83 fatal("Error parsing <host>:<port>: %s",host_port_str.c_str());
84 const string node(host_port_str.substr(0,cs-host_port_str.c_str()));
85 const string service(cs+1);
86 struct addrinfo hints={}; // designated initializer: error: missing initializer for member ... [-Werror=missing-field-initializers]
87 hints.ai_family=AF_UNSPEC; /* Allow IPv4 or IPv6 */
88 hints.ai_socktype=SOCK_STREAM;
89 struct addrinfo *result;
90 int err=getaddrinfo(node.c_str(),service.c_str(),&hints,&result);
92 fatal("Error parsing node+service: <%s>:<%s>: %s",node.c_str(),service.c_str(),gai_strerror(err));
95 for (unsigned retryno=0;retryno<1+retries;++retryno) {
97 warning("Sleeping 1 second for connect retry #%u/%u",retryno,retries);
101 for (rp=result;rp;rp=rp->ai_next) {
102 fd=socket(rp->ai_family,rp->ai_socktype,rp->ai_protocol);
105 if (connect(fd,rp->ai_addr,rp->ai_addrlen)==0)
111 warning("Could not connect(): <%s>:<%s>: %m",node.c_str(),service.c_str());
115 freeaddrinfo(result);
117 fatal("Could not connect(), giving up");