• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
u_socket_init()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
u_socket_stop()48 u_socket_stop()
49 {
50 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
51    WSACleanup();
52 #endif
53 }
54 
55 void
u_socket_close(int s)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 
u_socket_accept(int s)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
u_socket_send(int s,void * data,size_t size)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
u_socket_peek(int s,void * data,size_t size)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
u_socket_recv(int s,void * data,size_t size)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
u_socket_connect(const char * hostname,uint16_t port)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
u_socket_listen_on_port(uint16_t portnum)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
u_socket_block(int s,boolean block)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