int acl_sane_socketpair(int domain, int type, int protocol, ACL_SOCKET result[2]) { ACL_SOCKET listener = acl_inet_listen("127.0.0.1:0", 1, ACL_BLOCKING); char addr[64]; (void) domain; result[0] = ACL_SOCKET_INVALID; result[1] = ACL_SOCKET_INVALID; if (listener == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: listen error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); return -1; } acl_tcp_set_nodelay(listener); if (acl_getsockname(listener, addr, sizeof(addr)) < 0) { acl_msg_error("%s(%d), %s: getoskname error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); acl_socket_close(listener); return -1; } result[0] = acl_inet_connect(addr, ACL_BLOCKING, 0); if (result[0] == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: connect %s error %s", __FILE__, __LINE__, __FUNCTION__, addr, acl_last_serror()); acl_socket_close(listener); return -1; } result[1] = acl_inet_accept(listener); acl_socket_close(listener); if (result[1] == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: accept error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); acl_socket_close(result[0]); result[0] = ACL_SOCKET_INVALID; return -1; } acl_tcp_set_nodelay(result[0]); acl_tcp_set_nodelay(result[1]); return 0; }
bool server_socket::close() { if (fd_ == ACL_SOCKET_INVALID) return true; bool ret = acl_socket_close(fd_) == 0 ? true : false; fd_ = ACL_SOCKET_INVALID; addr_[0] = 0; return ret; }
ACL_VSTREAM *acl_vstream_listen_ex(const char *addr, int qlen, int block_mode, int io_bufsize, int io_timeout) { const char *myname = "acl_vstream_listen_ex"; ACL_SOCKET listenfd; struct sockaddr_in local; ACL_VSTREAM *listen_stream; int len; if (addr == 0 || *addr == 0 || qlen <= 0) { acl_msg_error("%s: input invalid", myname); return NULL; } #ifdef ACL_UNIX /* this maybe unix addr, such as '/home/test/listen.sock' */ if (strchr(addr, '/') != NULL) { listenfd = acl_unix_listen(addr, qlen, 0); if (listenfd == ACL_SOCKET_INVALID) return NULL; acl_non_blocking(listenfd, block_mode); listen_stream = acl_vstream_fdopen(listenfd, ACL_VSTREAM_FLAG_RW, io_bufsize, io_timeout, ACL_VSTREAM_TYPE_LISTEN_UNIX); if (listen_stream == NULL) { acl_socket_close(listenfd); acl_msg_error("%s: open vstream error, addr(%s)", myname, addr); return NULL; } acl_vstream_set_local(listen_stream, addr); sprintf(listen_stream->errbuf, "+OK"); return (listen_stream); } #endif /* addr such as '192.168.0.1:80' */ listenfd = acl_inet_listen(addr, qlen, block_mode); if (listenfd == ACL_SOCKET_INVALID) { acl_msg_error("%s: listen addr(%s) error(%s)", myname, addr, acl_last_serror()); return NULL; } listen_stream = acl_vstream_fdopen(listenfd, ACL_VSTREAM_FLAG_RW, io_bufsize, io_timeout, ACL_VSTREAM_TYPE_LISTEN_INET); if (listen_stream == NULL) { acl_socket_close(listenfd); acl_msg_error("%s: open vstream error addr(%s)", myname, addr); return NULL; } memset(&local, 0, sizeof(local)); len = (int) sizeof(struct sockaddr); if (getsockname(listenfd, (struct sockaddr*) &local, (socklen_t *) &len) < 0) { acl_msg_warn("%s: getsockname error(%s) for sock(%d)", myname, acl_last_serror(), listenfd); acl_vstream_set_local(listen_stream, addr); } else { char ip[32], buf[64]; int port; acl_inet_ntoa(local.sin_addr, ip, sizeof(ip)); port = ntohs(local.sin_port); snprintf(buf, sizeof(buf), "%s:%d", ip, port); acl_vstream_set_local(listen_stream, buf); } sprintf(listen_stream->errbuf, "+OK"); return listen_stream; }
server_socket::~server_socket() { if (fd_ != ACL_SOCKET_INVALID) acl_socket_close(fd_); }
ACL_SOCKET acl_inet_listen(const char *addr, int backlog, int block_mode) { const char *myname = "acl_inet_listen"; ACL_SOCKET sock; int on, nport; char *buf, *host = NULL, *sport = NULL; const char *ptr; struct sockaddr_in sa; /* * Translate address information to internal form. */ buf = acl_mystrdup(addr); ptr = acl_host_port(buf, &host, "", &sport, (char *) 0); if (ptr) { acl_msg_error("%s(%d): %s, %s invalid", myname, __LINE__, addr, ptr); acl_myfree(buf); return ACL_SOCKET_INVALID; } if (host && *host == 0) host = 0; if (host == NULL) host = "0.0.0.0"; if (sport == NULL) { acl_msg_error("%s(%d): no port given from addr(%s)", myname, __LINE__, addr); acl_myfree(buf); return ACL_SOCKET_INVALID; } nport = atoi(sport); if (nport < 0) { acl_msg_error("%s: port(%d) < 0 invalid from addr(%s)", myname, nport, addr); acl_myfree(buf); return ACL_SOCKET_INVALID; } memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons((short) nport); sa.sin_addr.s_addr = inet_addr(host); acl_myfree(buf); /* Create a listener socket. */ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == ACL_SOCKET_INVALID) { acl_msg_error("%s: socket %s", myname, acl_last_serror()); return ACL_SOCKET_INVALID; } on = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0) { acl_msg_error("%s: setsockopt(SO_REUSEADDR): %s", myname, acl_last_serror()); } if (bind(sock, (struct sockaddr *) &sa, sizeof(struct sockaddr)) < 0) { acl_msg_error("%s: bind %s error %s", myname, addr, acl_last_serror()); acl_socket_close(sock); return ACL_SOCKET_INVALID; } acl_non_blocking(sock, block_mode); if (listen(sock, backlog) < 0) { acl_msg_error("%s: listen error: %s, addr(%s)", myname, acl_last_serror(), addr); acl_socket_close(sock); return ACL_SOCKET_INVALID; } return sock; }