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