1 2 #include "pipe/p_compiler.h" 3 #include "util/u_network.h" 4 #include "util/u_debug.h" 5 #include "util/u_string.h" 6 7 #include <stdio.h> 8 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER) 9 # include <winsock2.h> 10 # include <windows.h> 11 # include <ws2tcpip.h> 12 #elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || \ 13 defined(PIPE_OS_APPLE) || defined(PIPE_OS_CYGWIN) || defined(PIPE_OS_SOLARIS) 14 # include <sys/socket.h> 15 # include <netinet/in.h> 16 # include <unistd.h> 17 # include <fcntl.h> 18 # include <netdb.h> 19 #else 20 # warning "No socket implementation" 21 #endif 22 23 boolean 24 u_socket_init() 25 { 26 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER) 27 WORD wVersionRequested; 28 WSADATA wsaData; 29 int err; 30 31 /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ 32 wVersionRequested = MAKEWORD(1, 1); 33 34 err = WSAStartup(wVersionRequested, &wsaData); 35 if (err != 0) { 36 debug_printf("WSAStartup failed with error: %d\n", err); 37 return FALSE; 38 } 39 return TRUE; 40 #elif defined(PIPE_HAVE_SOCKETS) 41 return TRUE; 42 #else 43 return FALSE; 44 #endif 45 } 46 47 void 48 u_socket_stop() 49 { 50 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER) 51 WSACleanup(); 52 #endif 53 } 54 55 void 56 u_socket_close(int s) 57 { 58 if (s < 0) 59 return; 60 61 #if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \ 62 || defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS) 63 shutdown(s, SHUT_RDWR); 64 close(s); 65 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) 66 shutdown(s, SD_BOTH); 67 closesocket(s); 68 #else 69 assert(0); 70 #endif 71 } 72 73 int u_socket_accept(int s) 74 { 75 #if defined(PIPE_HAVE_SOCKETS) 76 return accept(s, NULL, NULL); 77 #else 78 return -1; 79 #endif 80 } 81 82 int 83 u_socket_send(int s, void *data, size_t size) 84 { 85 #if defined(PIPE_HAVE_SOCKETS) 86 return send(s, data, size, 0); 87 #else 88 return -1; 89 #endif 90 } 91 92 int 93 u_socket_peek(int s, void *data, size_t size) 94 { 95 #if defined(PIPE_HAVE_SOCKETS) 96 return recv(s, data, size, MSG_PEEK); 97 #else 98 return -1; 99 #endif 100 } 101 102 int 103 u_socket_recv(int s, void *data, size_t size) 104 { 105 #if defined(PIPE_HAVE_SOCKETS) 106 return recv(s, data, size, 0); 107 #else 108 return -1; 109 #endif 110 } 111 112 int 113 u_socket_connect(const char *hostname, uint16_t port) 114 { 115 #if defined(PIPE_HAVE_SOCKETS) 116 int s, r; 117 struct addrinfo hints, *addr; 118 char portString[20]; 119 120 memset(&hints, 0, sizeof hints); 121 hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version 122 hints.ai_socktype = SOCK_STREAM; 123 124 util_snprintf(portString, sizeof(portString), "%d", port); 125 126 r = getaddrinfo(hostname, portString, NULL, &addr); 127 if (r != 0) { 128 return -1; 129 } 130 131 s = socket(addr->ai_family, SOCK_STREAM, IPPROTO_TCP); 132 if (s < 0) { 133 freeaddrinfo(addr); 134 return -1; 135 } 136 137 if (connect(s, addr->ai_addr, (int) addr->ai_addrlen)) { 138 u_socket_close(s); 139 freeaddrinfo(addr); 140 return -1; 141 } 142 143 freeaddrinfo(addr); 144 145 return s; 146 #else 147 assert(0); 148 return -1; 149 #endif 150 } 151 152 int 153 u_socket_listen_on_port(uint16_t portnum) 154 { 155 #if defined(PIPE_HAVE_SOCKETS) 156 int s; 157 struct sockaddr_in sa; 158 memset(&sa, 0, sizeof(struct sockaddr_in)); 159 160 sa.sin_family = AF_INET; 161 sa.sin_port = htons(portnum); 162 163 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 164 if (s < 0) 165 return -1; 166 167 if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1) { 168 u_socket_close(s); 169 return -1; 170 } 171 172 listen(s, 0); 173 174 return s; 175 #else 176 assert(0); 177 return -1; 178 #endif 179 } 180 181 void 182 u_socket_block(int s, boolean block) 183 { 184 #if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \ 185 || defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS) 186 int old = fcntl(s, F_GETFL, 0); 187 if (old == -1) 188 return; 189 190 /* TODO obey block */ 191 if (block) 192 fcntl(s, F_SETFL, old & ~O_NONBLOCK); 193 else 194 fcntl(s, F_SETFL, old | O_NONBLOCK); 195 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) 196 u_long iMode = block ? 0 : 1; 197 ioctlsocket(s, FIONBIO, &iMode); 198 #else 199 assert(0); 200 #endif 201 } 202