proper ending
[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 signal (SIGINT, &stop_server);
76 signal (SIGQUIT, &stop_server);
77 signal (SIGABRT, &stop_server);
78 signal (SIGSEGV, &stop_server);
79 signal (SIGTERM, &stop_server);
80 }
81
82 /* terminate network context */
83
84 void terminate_network_context (void)
85 {
86 closesocket (sock);
87 closesocket (conn);
88 #ifdef _WIN32 /* Windows */
89 WSACleanup ();
90 #endif
91 }
92
93 /* open listening socket */
94
95 int open_listening_socket (int port)
96 {
97 int val = 1;
98
99 VERBOSE (DEBUG, PRINT ("Opening socket\n"));
100 //socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
101 if (sock != INVALID_SOCKET) {
102 int rc = closesocket (sock);
103 if (rc == SOCKET_ERROR) {
104 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
105 }
106 sock = INVALID_SOCKET;
107 }
108 sock = socket (AF_INET, SOCK_STREAM, 0);
109 if (sock == INVALID_SOCKET) {
110 return 0;
111 }
112
113 struct sockaddr_in addr = {0};
114 //bzero (&addr, sizeof (addr));
115 //addr.sin_family = PF_INET;
116 addr.sin_family = AF_INET;
117 addr.sin_port = htons (port);
118 addr.sin_addr.s_addr = htonl (INADDR_ANY);
119
120 VERBOSE (DEBUG, PRINT ("Binding socket\n"));
121 //setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val));
122 int rc = bind (sock, (struct sockaddr *)&addr, sizeof (addr));
123 if (rc == SOCKET_ERROR) {
124 VERBOSE (ERROR, PERROR ("error: bind %d\n", ERRNO));
125 rc = closesocket (sock);
126 if (rc == SOCKET_ERROR) {
127 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
128 }
129 sock = INVALID_SOCKET;
130 return 0;
131 }
132
133 VERBOSE (DEBUG, PRINT ("Configuring socket\n"));
134 #ifndef _WIN32 /* Posix */
135 fcntl (sock, F_SETFL, O_NONBLOCK);
136 #endif
137 rc = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
138 if (rc < 0) {
139 VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY"));
140 closesocket (sock);
141 if (rc == SOCKET_ERROR) {
142 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
143 }
144 sock = INVALID_SOCKET;
145 return 0;
146 }
147
148 rc = listen (sock, BACKLOG);
149 if (rc < 0) {
150 VERBOSE (ERROR, PERROR ("error: %s\n", "listen"));
151 closesocket (sock);
152 if (rc == SOCKET_ERROR) {
153 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
154 }
155 sock = INVALID_SOCKET;
156 return 0;
157 }
158
159 return 1;
160 }
161
162 /* accept incomming connection */
163
164 int accept_incoming_connection (void)
165 {
166 if (sock == INVALID_SOCKET) {
167 VERBOSE (ERROR, PERROR ("Can't accept connection from closed socket\n"));
168 return 0;
169 }
170
171 if (conn != INVALID_SOCKET) {
172 int rc = closesocket (conn);
173 if (rc == SOCKET_ERROR) {
174 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
175 }
176 conn = INVALID_SOCKET;
177 }
178 conn = accept (sock, NULL, 0);
179 if (conn == INVALID_SOCKET) {
180 return 0;
181 }
182
183 #ifndef _WIN32 /* POSIX */
184 fcntl (conn, F_SETFL, O_NONBLOCK);
185 #endif
186 int val = 1;
187 int rc = setsockopt (conn, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
188 if (rc < 0) {
189 VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY"));
190 closesocket (conn);
191 if (rc == SOCKET_ERROR) {
192 VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
193 }
194 conn = INVALID_SOCKET;
195 return 0;
196 }
197
198 return 1;
199 }
200
201 /* close connection socket */
202
203 void close_connection (void)
204 {
205 int rc = closesocket (conn);
206 if (rc == SOCKET_ERROR) {
207 VERBOSE (ERROR, PERROR ("error: %d\n", ERRNO));
208 }
209 conn = INVALID_SOCKET;
210 }
211
212 /* receive data from socket */
213
214 int receive_data (unsigned char **pdata)
215 {
216 unsigned char buffer[BUFFER_SIZE] = {0};
217 unsigned char *data = NULL;
218 int len = 0;
219
220 if (conn == INVALID_SOCKET) {
221 VERBOSE (ERROR, PERROR ("Can't read data from closed socket\n"));
222 return 0;
223 }
224
225 while (1) {
226
227 /* timeout management */
228 fd_set rfds;
229 struct timeval tv = { 0, TIMEOUT };
230 FD_ZERO (&rfds);
231 FD_SET (conn, &rfds);
232
233 int retval = select (conn + 1, &rfds, NULL, NULL, &tv);
234 if (retval != 1) { /* 0 or SOCKET_ERROR */
235 break;
236 }
237
238 /* read from socket */
239 int rc = read (conn, buffer, BUFFER_SIZE);
240
241 if (rc == 0) { /* sock closed */
242 if (data) {
243 free (data);
244 data = NULL;
245 len = 0;
246 }
247 break;
248
249 } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
250 if (data) {
251 free (data);
252 data = NULL;
253 }
254 len = -1;
255 break;
256
257 } else if (rc > 0) {
258 data = realloc (data, len + rc);
259 memcpy (data + len, buffer, rc);
260 len += rc;
261 }
262 }
263
264 if (pdata != NULL) {
265 *pdata = data;
266 }
267 return len;
268 }
269
270 /* send data onto socket */
271
272 int send_data (unsigned char *data, int len)
273 {
274 int index = 0;
275
276 if (conn == INVALID_SOCKET) {
277 VERBOSE (ERROR, PERROR ("Can't read data from closed socket\n"));
278 return 0;
279 }
280
281 while (index < len) {
282 int rc = write (conn, data + index, len - index);
283
284 if (rc == 0) { /* sock closed */
285 index = 0;
286 break;
287 } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
288 index = -1;
289 break;
290 } else if (rc > 0) {
291 index += rc;
292 }
293 }
294
295 return index;
296 }
297
298 /* vim: set ts=4 sw=4 et: */