static int OpenSocket(I2Addr addr, char* serv, int family, int options) { int fd = -1; int return_code = 0; struct addrinfo *fai = NULL; if (!(fai = I2AddrAddrInfo(addr, NULL, serv))) { return -2; } // Attempt to connect to one of the chosen addresses. struct addrinfo* ai = NULL; for (ai = fai; ai; ai = ai->ai_next) { if (ai->ai_family != family) continue; // create socket with obtained address domain, socket type and protocol fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); // socket create failed. Abandon further activities using this socket if (fd < 0) continue; // allow sockets to reuse local address while binding unless there // is an active listener. If unable to set this option, indicate failure int on = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) { return_code = -2; goto failsock; } // end trying to set socket option to reuse local address #ifdef AF_INET6 #ifdef IPV6_V6ONLY if (family == AF_INET6 && (options & OPT_IPV6_ONLY)) { on = 1; // the IPv6 version socket option setup if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) != 0) { return_code = -2; goto failsock; } } #endif #endif // try to bind to address if (bind(fd, ai->ai_addr, ai->ai_addrlen) == 0) { // successful // set values in "addr" structure if (!I2AddrSetSAddr(addr, ai->ai_addr, ai->ai_addrlen) || !I2AddrSetProtocol(addr, ai->ai_protocol) || !I2AddrSetSocktype(addr, ai->ai_socktype)) { log_println(1, "OpenSocket: Unable to set saddr in address record"); return_code = -1; goto failsock; } // set port if not already done, else return -1 if (!I2AddrPort(addr)) { struct sockaddr_storage tmp_addr; socklen_t tmp_addr_len = sizeof(tmp_addr); I2Addr tmpAddr; if (getsockname(fd, (struct sockaddr*) &tmp_addr, &tmp_addr_len)) { log_println(1, "OpenSocket: Unable to getsockname in address record"); return_code = -1; goto failsock; } tmpAddr = I2AddrBySAddr( get_errhandle(), (struct sockaddr*) &tmp_addr, tmp_addr_len, 0, 0); I2AddrSetPort(addr, I2AddrPort(tmpAddr)); I2AddrFree(tmpAddr); } // save socket file descriptor if (!I2AddrSetFD(addr, fd, True)) { log_println(1, "OpenSocket: Unable to set file descriptor in address " "record"); return_code = -1; goto failsock; } // end setting values in "addr" structure break; } // Address is indicated as being in use. Display actual socket options to // user and return if (errno == EADDRINUSE) { /* RAC debug statemement 10/11/06 */ socklen_t onSize = sizeof(on); getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, &onSize); log_println(1, "bind(%d) failed: Address already in use given as the " "reason, getsockopt() returned %d", fd, on); } else { log_println(1, "bind(%d) failed: %s", fd, strerror(errno)); } return_code = -1; goto failsock; } return fd; // If opening socket failed, print error, and try to close socket // file-descriptor. failsock: while ((close(fd) < 0) && (errno == EINTR)) { } return return_code; }
static int OpenSocket(I2Addr addr, char* serv, int options) { struct addrinfo *fai; struct addrinfo *ai; int on; socklen_t onSize; int fd=-1; if (!(fai = I2AddrAddrInfo(addr, NULL, serv))) { return -2; } for (ai = fai; ai; ai = ai->ai_next) { #ifdef AF_INET6 if (options & OPT_IPV6_ONLY) { if(ai->ai_family != AF_INET6) continue; } #endif if (options & OPT_IPV4_ONLY) { if(ai->ai_family != AF_INET) continue; } fd = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol); /* if (meta.family == 0) meta.family = ai->ai_family; */ if (fd < 0) { continue; } on=1; if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) != 0) { goto failsock; } #if defined(AF_INET6) && defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) if ((ai->ai_family == AF_INET6) && (options & OPT_IPV6_ONLY) && setsockopt(fd,IPPROTO_IPV6,IPV6_V6ONLY,&on,sizeof(on)) != 0) { goto failsock; } #endif if (bind(fd,ai->ai_addr,ai->ai_addrlen) == 0) { if (!I2AddrSetSAddr(addr,ai->ai_addr,ai->ai_addrlen) || !I2AddrSetProtocol(addr,ai->ai_protocol) || !I2AddrSetSocktype(addr,ai->ai_socktype)) { log_println(1, "OpenSocket: Unable to set saddr in address record"); return -1; } if (!I2AddrPort(addr)) { struct sockaddr_storage tmp_addr; socklen_t tmp_addr_len = sizeof(tmp_addr); I2Addr tmpAddr; if (getsockname(fd, (struct sockaddr*) &tmp_addr, &tmp_addr_len)) { return -1; } tmpAddr = I2AddrBySAddr(get_errhandle(), (struct sockaddr*) &tmp_addr, tmp_addr_len, 0, 0); I2AddrSetPort(addr, I2AddrPort(tmpAddr)); I2AddrFree(tmpAddr); } if (!I2AddrSetFD(addr,fd,True)) { log_println(1, "OpenSocket: Unable to set file descriptor in address record"); return -1; } break; } if (errno == EADDRINUSE) { /* RAC debug statemement 10/11/06 */ onSize = sizeof(on); getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, &onSize); log_println(1, "bind(%d) failed: Address already in use given as the reason, getsockopt() returned %d", fd, on); return -2; } failsock: /* RAC debug statemement 10/11/06 */ log_println(1, "failsock: Unable to set socket options for fd=%d", fd); while((close(fd) < 0) && (errno == EINTR)); } if (meta.family == 0) meta.family = ai->ai_family; return fd; }
int CreateConnectSocket(int* sockfd, I2Addr local_addr, I2Addr server_addr, int options, int buf_size) { struct addrinfo *fai = NULL; struct addrinfo *ai = NULL; struct addrinfo *lfai = NULL; struct addrinfo *lai = NULL; socklen_t optlen; int set_size; assert(sockfd); assert(server_addr); if (!server_addr) { log_println(1, "Invalid server address"); goto error; } // already connected and bound if ((*sockfd = I2AddrFD(server_addr)) > -1) { return 0; } if (!(fai = I2AddrAddrInfo(server_addr, NULL, NULL))) { log_println(1, "Failed to get address info for server address"); goto error; } int family = AF_UNSPEC; #ifdef AF_INET6 // options provided by user indicate V6 or V4 only if ((options & OPT_IPV6_ONLY) != 0) family = AF_INET6; #endif else if ((options & OPT_IPV4_ONLY) != 0) family = AF_INET; for (ai = fai; ai; ai = ai->ai_next) { if (family != AF_UNSPEC && ai->ai_family != family) { log_println(1, "Skipping family %d", family); continue; } // create socket with obtained address domain, socket type and protocol *sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (*sockfd < 0) { // socket create failed. Abandon further activities using this socket log_println(1, "Failed to create %d %d %d", ai->ai_family, ai->ai_socktype, ai->ai_protocol); continue; } // local address has been specified. Get details and bind to this adderess if (local_addr) { printf("local_addr\n"); int bindFailed = 1; if (!(lfai = I2AddrAddrInfo(local_addr, NULL, NULL))) continue; // Validate INET address family for (lai = lfai; lai; lai = lai->ai_next) { if (lai->ai_family != family) continue; // bind to local address if (bind((*sockfd), lai->ai_addr, lai->ai_addrlen) == 0) { bindFailed = 0; // bind successful break; /* success */ } } // Failed to bind. Close socket file-descriptor and move on if (bindFailed == 1) { close((*sockfd)); /* ignore this one */ continue; } } // end local address /* Set sock opt code from Marion Nakanson <[email protected] * OHSU Advanced Computing Center * email on 2/19/09 correctly notes that setsockops must be made before open() * or listen() calls are made */ optlen = sizeof(set_size); // get send buffer size for logs getsockopt(*sockfd, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); log_print(5, "\nSend buffer initialized to %d, ", set_size); // get receive buffer size for logs getsockopt(*sockfd, SOL_SOCKET, SO_RCVBUF, &set_size, &optlen); log_println(5, "Receive buffer initialized to %d", set_size); // now assign buffer sizes passed as arguments if (buf_size > 0) { setsockopt(*sockfd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)); setsockopt(*sockfd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)); // log values for reference getsockopt(*sockfd, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); log_print(5, "Changed buffer sizes: Send buffer set to %d(%d), ", set_size, buf_size); getsockopt(*sockfd, SOL_SOCKET, SO_RCVBUF, &set_size, &optlen); log_println(5, "Receive buffer set to %d(%d)", set_size, buf_size); } // Connect to target socket if (connect(*sockfd, ai->ai_addr, ai->ai_addrlen) == 0) { log_println(1, "Connected!"); // save server address values if (I2AddrSetSAddr(server_addr, ai->ai_addr, ai->ai_addrlen) && I2AddrSetSocktype(server_addr, ai->ai_socktype) && I2AddrSetProtocol(server_addr, ai->ai_protocol) && I2AddrSetFD(server_addr, *sockfd, True)) { log_println(1, "Client socket created"); return 0; } // unable to save log_println(1, "I2Addr functions failed after successful connection"); while ((close(*sockfd) < 0) && (errno == EINTR)) { } return 1; } else { log_println(0, "Failed to connect: %s", strerror(errno)); // goto error; } } log_println(0, "No sockets could be created that match requirements."); error: return -1; }
int CreateConnectSocket(int* sockfd, I2Addr local_addr, I2Addr server_addr, int options, int buf_size) { struct addrinfo *fai = NULL; struct addrinfo *ai = NULL; struct addrinfo *lfai = NULL; struct addrinfo *lai = NULL; socklen_t optlen; int set_size; assert(sockfd); assert(server_addr); if (!server_addr) { goto error; } if ((*sockfd = I2AddrFD(server_addr)) > -1) { return 0; } if (!(fai = I2AddrAddrInfo(server_addr, NULL, NULL))) { goto error; } for (ai=fai; ai; ai=ai->ai_next) { #ifdef AF_INET6 if (options & OPT_IPV6_ONLY) { if(ai->ai_family != AF_INET6) continue; } #endif if (options & OPT_IPV4_ONLY) { if(ai->ai_family != AF_INET) continue; } *sockfd = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol); if (*sockfd < 0) { continue; } if (local_addr) { int bindFailed = 1; if (!(lfai = I2AddrAddrInfo(local_addr, NULL, NULL))) { continue; } for (lai=lfai; lai; lai=lai->ai_next) { #ifdef AF_INET6 if (options & OPT_IPV6_ONLY) { if(lai->ai_family != AF_INET6) continue; } #endif if (options & OPT_IPV4_ONLY) { if(lai->ai_family != AF_INET) continue; } if (bind((*sockfd), lai->ai_addr, lai->ai_addrlen) == 0) { bindFailed = 0; break; /* success */ } } if (bindFailed == 1) { close((*sockfd)); /* ignore this one */ continue; } } /* Set sock opt code from Marion Nakanson <[email protected] * OHSU Advanced Computing Center * email on 2/19/09 correctly notes that setsockops must be made before open() * or listen() calls are made */ optlen = sizeof(set_size); getsockopt(*sockfd, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); log_print(5, "\nSend buffer initialized to %d, ", set_size); getsockopt(*sockfd, SOL_SOCKET, SO_RCVBUF, &set_size, &optlen); log_println(5, "Receive buffer initialized to %d", set_size); if (buf_size > 0) { setsockopt(*sockfd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)); setsockopt(*sockfd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)); getsockopt(*sockfd, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); log_print(5, "Changed buffer sizes: Send buffer set to %d(%d), ", set_size, buf_size); getsockopt(*sockfd, SOL_SOCKET, SO_RCVBUF, &set_size, &optlen); log_println(5, "Receive buffer set to %d(%d)", set_size, buf_size); } if (connect(*sockfd,ai->ai_addr,ai->ai_addrlen) == 0) { if(I2AddrSetSAddr(server_addr,ai->ai_addr,ai->ai_addrlen) && I2AddrSetSocktype(server_addr,ai->ai_socktype) && I2AddrSetProtocol(server_addr,ai->ai_protocol) && I2AddrSetFD(server_addr,*sockfd,True)){ return 0; } log_println(1, "I2Addr functions failed after successful connection"); while((close(*sockfd) < 0) && (errno == EINTR)); return 1; } } error: log_println(1, "Unable to create connect socket."); return -1; }