Fix for windows
[webserver.git] / server.c
1 #include <assert.h>
2 #include <signal.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #ifdef _WIN32 /* Windows */
7 #include <winsock2.h>
8 #include <ws2tcpip.h>
9 #else /* Posix */
10 #include <errno.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <netinet/ip.h>
14 #include <netinet/tcp.h>
15 #include <sys/select.h>
16 #endif
17 #include <unistd.h>
18
19 #include "debug.h"
20
21 #include "server.h"
22
23 /* types */
24
25 #ifdef _WIN32 /* Windows */
26 typedef SOCKET socket_t;
27 #else /* Posix */
28 typedef int socket_t;
29 #endif
30
31 /* constants */
32
33 #define BACKLOG 5
34 #define BUFFER_SIZE 4096
35 #define TIMEOUT 100000
36
37 /* macros */
38
39 #ifdef _WIN32 /* Windows */
40 #define PF_INET AF_INET
41 #define ERRNO (WSAGetLastError ())
42 #else /* Posix */
43 #define closesocket close
44 #define ERRNO errno
45 #define SOCKET_ERROR -1
46 #define INVALID_SOCKET -1
47 #endif
48
49 /* gobal variables */
50
51 socket_t sock = INVALID_SOCKET;
52 socket_t conn = INVALID_SOCKET;
53
54 /* stop server */
55
56 void stop_server (int sig)
57 {
58 VERBOSE (INFO, PRINT ("Signal: %d\n", sig));
59 terminate_network_context ();
60 exit (0);
61 }
62
63 /* init network context */
64
65 void init_network_context (void)
66 {
67 #ifdef _WIN32 /* Windows */
68 WSADATA WSAData;
69 WSAStartup (MAKEWORD(2,0), &WSAData);
70
71 assert (INVALID_SOCKET == (socket_t)-1);
72 assert (SOCKET_ERROR == -1);
73 #endif
74
75 #ifndef _WIN32 /* Posix */
76 signal (SIGINT, &stop_server);
77 #endif
78 signal (SIGABRT, &stop_server);
79 signal (SIGSEGV, &stop_server);
80 signal (SIGTERM, &stop_server);
81 }
82
83 /* terminate network context */
84
85 void terminate_network_context (void)
86 {
87 closesocket (sock);
88 closesocket (conn);
89 #ifdef _WIN32 /* Windows */
90 WSACleanup ();
91 #endif
92 }
93
94 /* open listening socket */
95
96 int open_listening_socket (int port)
97 {
98 int val = 1;
99
100 VERBOSE (DEBUG, PRINT ("Opening socket\n"));
101 //socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
102 if (sock != INVALID_SOCKET) {
103 int rc = closesocket (sock);
104 if (rc == SOCKET_ERROR) {
105 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
106 }
107 sock = INVALID_SOCKET;
108 }
109 sock = socket (AF_INET, SOCK_STREAM, 0);
110 if (sock == INVALID_SOCKET) {
111 return 0;
112 }
113
114 struct sockaddr_in addr = {0};
115 //bzero (&addr, sizeof (addr));
116 //addr.sin_family = PF_INET;
117 addr.sin_family = AF_INET;
118 addr.sin_port = htons (port);
119 addr.sin_addr.s_addr = htonl (INADDR_ANY);
120
121 VERBOSE (DEBUG, PRINT ("Binding socket\n"));
122 //setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val));
123 int rc = bind (sock, (struct sockaddr *)&addr, sizeof (addr));
124 if (rc == SOCKET_ERROR) {
125 VERBOSE (ERROR, PERROR ("error: bind %d\n", ERRNO));
126 rc = closesocket (sock);
127 if (rc == SOCKET_ERROR) {
128 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
129 }
130 sock = INVALID_SOCKET;
131 return 0;
132 }
133
134 VERBOSE (DEBUG, PRINT ("Configuring socket\n"));
135 #ifndef _WIN32 /* Posix */
136 fcntl (sock, F_SETFL, O_NONBLOCK);
137 #endif
138 rc = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
139 if (rc < 0) {
140 VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY"));
141 closesocket (sock);
142 if (rc == SOCKET_ERROR) {
143 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
144 }
145 sock = INVALID_SOCKET;
146 return 0;
147 }
148
149 rc = listen (sock, BACKLOG);
150 if (rc < 0) {
151 VERBOSE (ERROR, PERROR ("error: %s\n", "listen"));
152 closesocket (sock);
153 if (rc == SOCKET_ERROR) {
154 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
155 }
156 sock = INVALID_SOCKET;
157 return 0;
158 }
159
160 return 1;
161 }
162
163 /* accept incomming connection */
164
165 int accept_incoming_connection (void)
166 {
167 if (sock == INVALID_SOCKET) {
168 VERBOSE (ERROR, PERROR ("Can't accept connection from closed socket\n"));
169 return 0;
170 }
171
172 if (conn != INVALID_SOCKET) {
173 int rc = closesocket (conn);
174 if (rc == SOCKET_ERROR) {
175 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
176 }
177 conn = INVALID_SOCKET;
178 }
179 conn = accept (sock, NULL, 0);
180 if (conn == INVALID_SOCKET) {
181 return 0;
182 }
183
184 #ifndef _WIN32 /* POSIX */
185 fcntl (conn, F_SETFL, O_NONBLOCK);
186 #endif
187 int val = 1;
188 int rc = setsockopt (conn, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
189 if (rc < 0) {
190 VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY"));
191 closesocket (conn);
192 if (rc == SOCKET_ERROR) {
193 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
194 }
195 conn = INVALID_SOCKET;
196 return 0;
197 }
198
199 return 1;
200 }
201
202 /* close connection socket */
203
204 void close_connection (void)
205 {
206 int rc = closesocket (conn);
207 if (rc == SOCKET_ERROR) {
208 VERBOSE (ERROR, PERROR ("error: %d\n", ERRNO));
209 }
210 conn = INVALID_SOCKET;
211 }
212
213 /* receive data from socket */
214
215 int receive_data (char **pdata)
216 {
217 char buffer[BUFFER_SIZE] = {0};
218 char *data = NULL;
219 int len = 0;
220
221 if (conn == INVALID_SOCKET) {
222 VERBOSE (ERROR, PERROR ("Can't read data from closed socket\n"));
223 return 0;
224 }
225
226 while (1) {
227
228 /* timeout management */
229 fd_set rfds;
230 struct timeval tv = { 0, TIMEOUT };
231 FD_ZERO (&rfds);
232 FD_SET (conn, &rfds);
233
234 int retval = select (conn + 1, &rfds, NULL, NULL, &tv);
235 if (retval != 1) { /* 0 or SOCKET_ERROR */
236 break;
237 }
238
239 /* read from socket */
240 int rc = recv (conn, buffer, BUFFER_SIZE, 0);
241 VERBOSE (DEBUG, PRINT ("rc: %d\nerrno: %d\n", rc, ERRNO));
242
243 if (rc == 0) { /* sock closed */
244 if (data) {
245 free (data);
246 data = NULL;
247 len = 0;
248 }
249 break;
250
251 } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
252 if (data) {
253 free (data);
254 data = NULL;
255 }
256 len = -1;
257 break;
258
259 } else if (rc > 0) {
260 data = realloc (data, len + rc);
261 memcpy (data + len, buffer, rc);
262 len += rc;
263 }
264 }
265
266 if (pdata != NULL) {
267 *pdata = data;
268 }
269 return len;
270 }
271
272 /* send data onto socket */
273
274 int send_data (char *data, int len)
275 {
276 int index = 0;
277
278 if (conn == INVALID_SOCKET) {
279 VERBOSE (ERROR, PERROR ("Can't read data from closed socket\n"));
280 return 0;
281 }
282
283 while (index < len) {
284 int rc = write (conn, data + index, len - index);
285
286 if (rc == 0) { /* sock closed */
287 index = 0;
288 break;
289 } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
290 index = -1;
291 break;
292 } else if (rc > 0) {
293 index += rc;
294 }
295 }
296
297 return index;
298 }
299
300 /* vim: set ts=4 sw=4 et: */