📄 socket.c
字号:
int socket_set_blocking(int fd, int blocking){ int flags, newflags; flags = fcntl(fd, F_GETFL); if (flags < 0) { error(errno, "cannot get flags for fd %d", fd); return -1; } if (blocking) newflags = flags & ~O_NONBLOCK; else newflags = flags | O_NONBLOCK; if (newflags != flags) { if (fcntl(fd, F_SETFL, newflags) < 0) { error(errno, "cannot set flags for fd %d", fd); return -1; } } return 0;}int read_available(int fd, long wait_usec){ fd_set rf; struct timeval to; int ret; div_t waits; gw_assert(fd >= 0); FD_ZERO(&rf); FD_SET(fd, &rf); waits = div(wait_usec, 1000000); to.tv_sec = waits.quot; to.tv_usec = waits.rem;retry: ret = select(fd + 1, &rf, NULL, NULL, &to); if (ret > 0 && FD_ISSET(fd, &rf)) return 1; if (ret < 0) { /* In most select() implementations, to will now contain the * remaining time rather than the original time. That is exactly * what we want when retrying after an interrupt. */ switch (errno) { /*The first two entries here are OK*/ case EINTR: goto retry; case EAGAIN: return 1; /* We are now sucking mud, figure things out here * as much as possible before it gets lost under * layers of abstraction. */ case EBADF: if (!FD_ISSET(fd, &rf)) { warning(0, "Tried to select on fd %d, not in the set!\n", fd); } else { warning(0, "Tried to select on invalid fd %d!\n", fd); } break; case EINVAL: /* Solaris catchall "It didn't work" error, lets apply * some tests and see if we can catch it. */ /* First up, try invalid timeout*/ if (to.tv_sec > 10000000) warning(0, "Wait more than three years for a select?\n"); if (to.tv_usec > 1000000) warning(0, "There are only 1000000 usec in a second...\n"); break; } return -1; /* some error */ } return 0;}int udp_client_socket(void){ int s; s = socket(PF_INET, SOCK_DGRAM, 0); if (s == -1) { error(errno, "Couldn't create a UDP socket"); return -1; } return s;}int udp_bind(int port, const char *interface_name){ int s; struct sockaddr_in sa; struct hostent hostinfo; char *buff = NULL; s = socket(PF_INET, SOCK_DGRAM, 0); if (s == -1) { error(errno, "Couldn't create a UDP socket"); return -1; } sa = empty_sockaddr_in; sa.sin_family = AF_INET; sa.sin_port = htons(port); if (strcmp(interface_name, "*") == 0) sa.sin_addr.s_addr = htonl(INADDR_ANY); else { if (gw_gethostbyname(&hostinfo, interface_name, &buff) == -1) { error(errno, "gethostbyname failed"); gw_free(buff); return -1; } sa.sin_addr = *(struct in_addr *) hostinfo.h_addr; } if (bind(s, (struct sockaddr *) &sa, (int) sizeof(sa)) == -1) { error(errno, "Couldn't bind a UDP socket to port %d", port); (void) close(s); return -1; } gw_free(buff); return s;}Octstr *udp_create_address(Octstr *host_or_ip, int port){ struct sockaddr_in sa; struct hostent h; char *buff = NULL; Octstr *ret; sa = empty_sockaddr_in; sa.sin_family = AF_INET; sa.sin_port = htons(port); if (strcmp(octstr_get_cstr(host_or_ip), "*") == 0) { sa.sin_addr.s_addr = INADDR_ANY; } else { if (gw_gethostbyname(&h, octstr_get_cstr(host_or_ip), &buff) == -1) { error(0, "Couldn't find the IP number of `%s'", octstr_get_cstr(host_or_ip)); gw_free(buff); return NULL; } sa.sin_addr = *(struct in_addr *) h.h_addr; } ret = octstr_create_from_data((char *) &sa, sizeof(sa)); gw_free(buff); return ret;}int udp_get_port(Octstr *addr){ struct sockaddr_in sa; gw_assert(octstr_len(addr) == sizeof(sa)); memcpy(&sa, octstr_get_cstr(addr), sizeof(sa)); return ntohs(sa.sin_port);}Octstr *udp_get_ip(Octstr *addr){ struct sockaddr_in sa; gw_assert(octstr_len(addr) == sizeof(sa)); memcpy(&sa, octstr_get_cstr(addr), sizeof(sa)); return gw_netaddr_to_octstr(AF_INET, &sa.sin_addr);}int udp_sendto(int s, Octstr *datagram, Octstr *addr){ struct sockaddr_in sa; gw_assert(octstr_len(addr) == sizeof(sa)); memcpy(&sa, octstr_get_cstr(addr), sizeof(sa)); if (sendto(s, octstr_get_cstr(datagram), octstr_len(datagram), 0, (struct sockaddr *) &sa, (int) sizeof(sa)) == -1) { error(errno, "Couldn't send UDP packet"); return -1; } return 0;}int udp_recvfrom(int s, Octstr **datagram, Octstr **addr){ struct sockaddr_in sa; int salen; char *buf; int bytes; buf = gw_malloc(UDP_PACKET_MAX_SIZE); salen = sizeof(sa); bytes = recvfrom(s, buf, UDP_PACKET_MAX_SIZE, 0, (struct sockaddr *) &sa, &salen); if (bytes == -1) { if (errno != EAGAIN) error(errno, "Couldn't receive UDP packet"); gw_free(buf); return -1; } *datagram = octstr_create_from_data(buf, bytes); *addr = octstr_create_from_data((char *) &sa, salen); gw_free(buf); return 0;}Octstr *host_ip(struct sockaddr_in addr){ return gw_netaddr_to_octstr(AF_INET, &addr.sin_addr);}Octstr *get_official_name(void){ gw_assert(official_name != NULL); return official_name;}Octstr *get_official_ip(void){ gw_assert(official_ip != NULL); return official_ip;}static void setup_official_name(void){ struct utsname u; struct hostent h; char *buff = NULL; gw_assert(official_name == NULL); if (uname(&u) == -1) panic(0, "uname failed - can't happen, unless " GW_NAME " is buggy."); if (gw_gethostbyname(&h, u.nodename, &buff) == -1) { error(0, "Can't find out official hostname for this host, " "using `%s' instead.", u.nodename); official_name = octstr_create(u.nodename); official_ip = octstr_create("127.0.0.1"); } else { official_name = octstr_create(h.h_name); official_ip = gw_netaddr_to_octstr(AF_INET, h.h_addr); } gw_free(buff);}void socket_init(void){ setup_official_name();}void socket_shutdown(void){ octstr_destroy(official_name); official_name = NULL; octstr_destroy(official_ip); official_ip = NULL;}static Octstr *gw_netaddr_to_octstr4(unsigned char *src){ return octstr_format("%d.%d.%d.%d", src[0], src[1], src[2], src[3]);}#ifdef AF_INET6static Octstr *gw_netaddr_to_octstr6(unsigned char *src){ return octstr_format( "%x:%x:%x:%x:" "%x:%x:%x:%x:" "%x:%x:%x:%x:" "%x:%x:%x:%x", src[0], src[1], src[2], src[3], src[4], src[5], src[6], src[7], src[8], src[9], src[10], src[11], src[12], src[13], src[14], src[15]);}#endifOctstr *gw_netaddr_to_octstr(int af, void *src){ switch (af) { case AF_INET: return gw_netaddr_to_octstr4(src);#ifdef AF_INET6 case AF_INET6: return gw_netaddr_to_octstr6(src);#endif default: return NULL; } }int gw_accept(int fd, Octstr **client_addr){ struct sockaddr_in addr; int addrlen; int new_fd; if (gwthread_pollfd(fd, POLLIN, -1.0) != POLLIN) { debug("gwlib.socket", 0, "gwthread_pollfd interrupted or failed"); return -1; } addrlen = sizeof(addr); new_fd = accept(fd, (struct sockaddr *) &addr, &addrlen); if (new_fd == -1) { error(errno, "accept system call failed."); return -1; } *client_addr = host_ip(addr); debug("test_smsc", 0, "accept() succeeded, client from %s", octstr_get_cstr(*client_addr)); return new_fd;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -