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 
22 boolean
u_socket_init(void)23 u_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 
46 void
u_socket_stop(void)47 u_socket_stop(void)
48 {
49 #if defined(PIPE_OS_WINDOWS)
50    WSACleanup();
51 #endif
52 }
53 
54 void
u_socket_close(int s)55 u_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 
u_socket_accept(int s)71 int 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 
80 int
u_socket_send(int s,void * data,size_t size)81 u_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 
90 int
u_socket_peek(int s,void * data,size_t size)91 u_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 
100 int
u_socket_recv(int s,void * data,size_t size)101 u_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 
110 int
u_socket_connect(const char * hostname,uint16_t port)111 u_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 
150 int
u_socket_listen_on_port(uint16_t portnum)151 u_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 
179 void
u_socket_block(int s,boolean block)180 u_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