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