/* Connect to socket with ip address */ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; if (my_ip != NULL && ip->family != my_ip->family) { g_warning("net_connect_ip(): ip->family != my_ip->family"); my_ip = NULL; } /* create the socket */ memset(&so, 0, sizeof(so)); so.sin.sin_family = ip->family; handle = socket(ip->family, SOCK_STREAM, 0); if (handle == -1) return NULL; /* set socket options */ #ifndef WIN32 fcntl(handle, F_SETFL, O_NONBLOCK); #endif setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)); setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt)); /* set our own address */ if (my_ip != NULL) { sin_set_ip(&so, my_ip); if (bind(handle, &so.sa, SIZEOF_SOCKADDR(so)) == -1) { /* failed, set it back to INADDR_ANY */ sin_set_ip(&so, NULL); bind(handle, &so.sa, SIZEOF_SOCKADDR(so)); } } /* connect */ sin_set_ip(&so, ip); sin_set_port(&so, port); ret = connect(handle, &so.sa, SIZEOF_SOCKADDR(so)); #ifndef WIN32 if (ret < 0 && errno != EINPROGRESS) #else if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) #endif { int old_errno = errno; close(handle); errno = old_errno; return NULL; } return g_io_channel_new(handle); }
/* Get name for host, *name should be g_free()'d unless it's NULL. Return values are the same as with net_gethostbyname() */ int net_gethostbyaddr(IPADDR *ip, char **name) { #ifdef HAVE_IPV6 union sockaddr_union so; int host_error; char hostname[NI_MAXHOST]; #else struct hostent *hp; #endif g_return_val_if_fail(ip != NULL, -1); g_return_val_if_fail(name != NULL, -1); *name = NULL; #ifdef HAVE_IPV6 memset(&so, 0, sizeof(so)); sin_set_ip(&so, ip); /* save error to host_error for later use */ host_error = getnameinfo((struct sockaddr *) &so, sizeof(so), hostname, sizeof(hostname), NULL, 0, 0); if (host_error != 0) return host_error; *name = g_strdup(hostname); #else if (ip->family != AF_INET) return -1; hp = gethostbyaddr((const char *) &ip->ip, 4, AF_INET); if (hp == NULL) return -1; *name = g_strdup(hp->h_name); #endif return 0; }
/* Listen for connections on a socket. if `my_ip' is NULL, listen in any address. */ GIOChannel *net_listen(IPADDR *my_ip, int *port) { union sockaddr_union so; int ret, handle, opt = 1; socklen_t len; g_return_val_if_fail(port != NULL, NULL); memset(&so, 0, sizeof(so)); sin_set_port(&so, *port); sin_set_ip(&so, my_ip); /* create the socket */ handle = socket(so.sin.sin_family, SOCK_STREAM, 0); #ifdef HAVE_IPV6 if (handle == -1 && (errno == EINVAL || errno == EAFNOSUPPORT)) { /* IPv6 is not supported by OS */ so.sin.sin_family = AF_INET; so.sin.sin_addr.s_addr = INADDR_ANY; handle = socket(AF_INET, SOCK_STREAM, 0); } #endif if (handle == -1) return NULL; /* set socket options */ #ifndef WIN32 fcntl(handle, F_SETFL, O_NONBLOCK); #endif setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)); setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt)); /* specify the address/port we want to listen in */ ret = bind(handle, &so.sa, SIZEOF_SOCKADDR(so)); if (ret >= 0) { /* get the actual port we started listen */ len = SIZEOF_SOCKADDR(so); ret = getsockname(handle, &so.sa, &len); if (ret >= 0) { *port = sin_get_port(&so); /* start listening */ if (listen(handle, 1) >= 0) return g_io_channel_new(handle); } } /* error */ close(handle); return NULL; }
/* Connect to socket with ip address */ int net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; /* create the socket */ memset(&so, 0, sizeof(so)); so.sin.sin_family = ip->family; handle = socket(ip->family, SOCK_STREAM, 0); if (handle == -1) return -1; /* set socket options */ fcntl(handle, F_SETFL, O_NONBLOCK); setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)); setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt)); /* set our own address, ignore if bind() fails */ if (my_ip != NULL) { sin_set_ip(&so, my_ip); bind(handle, &so.sa, sizeof(so)); } /* connect */ sin_set_ip(&so, ip); sin_set_port(&so, port); ret = connect(handle, &so.sa, sizeof(so)); if (ret < 0 && errno != EINPROGRESS) { close(handle); return -1; } return handle; }
/* Listen for connections on a socket. if `my_ip' is NULL, listen in any address. */ int net_listen(IPADDR *my_ip, int *port) { union sockaddr_union so; int ret, handle, opt = 1; socklen_t len = sizeof(so); g_return_val_if_fail(port != NULL, -1); memset(&so, 0, sizeof(so)); sin_set_port(&so, *port); sin_set_ip(&so, my_ip); /* create the socket */ handle = socket(so.sin.sin_family, SOCK_STREAM, 0); if (handle == -1) return -1; /* set socket options */ fcntl(handle, F_SETFL, O_NONBLOCK); setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)); setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt)); /* specify the address/port we want to listen in */ ret = bind(handle, &so.sa, sizeof(so)); if (ret < 0) { close(handle); return -1; } /* get the actual port we started listen */ ret = getsockname(handle, &so.sa, &len); if (ret < 0) { close(handle); return -1; } *port = sin_get_port(&so); /* start listening */ if (listen(handle, 1) < 0) { close(handle); return -1; } return handle; }