buggy code (3)
[webserver.git] / server.c
CommitLineData
00afbb65
LM
1/* depend: */
2/* cflags: */
3/* linker: color.o debug.o */
4
5#include <assert.h>
6#include <stdio.h>
7#include <stdlib.h>
89f0e084 8#include <string.h>
00afbb65
LM
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>
89f0e084 20#include <sys/select.h>
00afbb65
LM
21#endif
22
23#include "debug.h"
24
25#include "server.h"
26
89f0e084 27/* compat */
00afbb65
LM
28
29#ifdef _WIN32 /* Windows */
00afbb65
LM
30#define PF_INET AF_INET
31#define ERRNO (WSAGetLastError ())
32#else /* Posix */
00afbb65
LM
33#define closesocket close
34#define ERRNO errno
00afbb65
LM
35#define SOCKET_ERROR -1
36#endif
37
89f0e084
LM
38/* types */
39
00afbb65
LM
40/* constants */
41
04a2223d 42#define BACKLOG 5
00afbb65 43#define BUFFER_SIZE 4096
04a2223d 44#define TIMEOUT 100000
00afbb65
LM
45
46/* macros */
47
48/* gobal variables */
49
89f0e084 50/* init network context */
00afbb65 51
89f0e084 52void init_network_context (void)
00afbb65
LM
53{
54#ifdef _WIN32 /* Windows */
55 WSADATA WSAData;
56 WSAStartup (MAKEWORD(2,0), &WSAData);
57 assert (INVALID_SOCKET == (socket_t)-1);
9ff99d58 58 assert (SOCKET_ERROR == -1);
00afbb65 59#endif
89f0e084
LM
60}
61
62/* terminate network context */
63
64void terminate_network_context (void)
65{
66#ifdef _WIN32 /* Windows */
67 WSACleanup ();
68#endif
69}
00afbb65 70
89f0e084
LM
71/* open listening socket */
72
73socket_t open_listening_socket (int port)
74{
1e0cfbd7
LM
75 int val = 1;
76
00afbb65 77 VERBOSE (DEBUG, fprintf (stdout, "Opening socket\n"));
1e0cfbd7
LM
78 //socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
79 socket_t sock = socket (AF_INET, SOCK_STREAM, 0);
9ff99d58 80 if (sock == INVALID_SOCKET) {
00afbb65 81 return -1;
9ff99d58 82 }
00afbb65
LM
83
84 struct sockaddr_in addr = {0};
1e0cfbd7
LM
85 bzero (&addr, sizeof (addr));
86 //addr.sin_family = PF_INET;
87 addr.sin_family = AF_INET;
00afbb65
LM
88 addr.sin_port = htons (port);
89 addr.sin_addr.s_addr = htonl (INADDR_ANY);
90
91 VERBOSE (DEBUG, fprintf (stdout, "Binding socket\n"));
1e0cfbd7 92 //setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val));
00afbb65 93 int rc = bind (sock, (struct sockaddr *)&addr, sizeof (addr));
9ff99d58 94 if (rc == SOCKET_ERROR) {
04a2223d 95 VERBOSE (ERROR, fprintf (stderr, "error: bind %d\n", ERRNO));
00afbb65 96 rc = closesocket (sock);
9ff99d58 97 if (rc == SOCKET_ERROR) {
04a2223d 98 VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO));
00afbb65
LM
99 }
100 return -1;
101 }
102
103 VERBOSE (DEBUG, fprintf (stdout, "Configuring socket\n"));
9ff99d58 104#ifndef _WIN32 /* Posix */
00afbb65
LM
105 fcntl (sock, F_SETFL, O_NONBLOCK);
106#endif
00afbb65
LM
107 rc = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
108 if (rc < 0) {
04a2223d 109 VERBOSE (ERROR, fprintf (stderr, "error: %s\n", "setsockopt/TCP_NODELAY"));
00afbb65 110 closesocket (sock);
9ff99d58 111 if (rc == SOCKET_ERROR) {
04a2223d
LM
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));
9ff99d58 123 }
00afbb65
LM
124 return -1;
125 }
126
127 return sock;
128}
129
04a2223d
LM
130/* accept incomming connection */
131
89f0e084 132socket_t accept_incoming_connection (socket_t sock)
04a2223d 133{
89f0e084 134 socket_t connection = accept (sock, NULL, 0);
04a2223d 135 if (connection < 0) {
89f0e084 136 return INVALID_SOCKET;
04a2223d
LM
137 }
138
139#ifndef _WIN32 /* POSIX */
140 fcntl (connection, F_SETFL, O_NONBLOCK);
141#endif
142 int val = 1;
89f0e084 143 int rc = setsockopt (connection, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
04a2223d
LM
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 }
89f0e084 150 return INVALID_SOCKET;
04a2223d
LM
151 }
152
153 return connection;
154}
155
89f0e084
LM
156/* close listening socket */
157
158void close_socket (socket_t sock)
04a2223d 159{
89f0e084
LM
160 int rc = closesocket (sock);
161 if (rc == SOCKET_ERROR) {
162 VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO));
163 }
164}
04a2223d 165
89f0e084 166/* receive data from socket */
04a2223d 167
89f0e084
LM
168int 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;
04a2223d 173
89f0e084 174 while (1) {
04a2223d 175
89f0e084
LM
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 }
04a2223d 186
89f0e084
LM
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 }
04a2223d 212
89f0e084
LM
213 if (pdata != NULL) {
214 *pdata = data;
215 }
216 return len;
04a2223d
LM
217}
218
89f0e084
LM
219/* send data onto socket */
220
221int 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}
06ec8057
LM
241
242/* vim: set ts=4 sw=4 et: */