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