buggy code
[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>
8#ifdef _WIN32 /* Windows */
9#include <winsock2.h>
10#include <ws2tcpip.h>
11#else /* Posix */
12#include <errno.h>
13#include <unistd.h>
14#include <fcntl.h>
15#include <netinet/ip.h>
16#include <netinet/tcp.h>
17//#include <sys/types.h>
18//#include <sys/socket.h>
19#endif
20
21#include "debug.h"
22
23#include "server.h"
24
25/* types */
26
27#ifdef _WIN32 /* Windows */
28typedef SOCKET socket_t;
29#define PF_INET AF_INET
30#define ERRNO (WSAGetLastError ())
31#else /* Posix */
32typedef int socket_t;
33#define closesocket close
34#define ERRNO errno
00afbb65
LM
35#define SOCKET_ERROR -1
36#endif
37
38/* constants */
39
04a2223d 40#define BACKLOG 5
00afbb65 41#define BUFFER_SIZE 4096
04a2223d 42#define TIMEOUT 100000
00afbb65
LM
43
44/* macros */
45
46/* gobal variables */
47
48/* open listening socket */
49
50socket_t open_listening_socket (int port)
51{
52#ifdef _WIN32 /* Windows */
53 WSADATA WSAData;
54 WSAStartup (MAKEWORD(2,0), &WSAData);
55 assert (INVALID_SOCKET == (socket_t)-1);
9ff99d58 56 assert (SOCKET_ERROR == -1);
00afbb65
LM
57#endif
58
59 VERBOSE (DEBUG, fprintf (stdout, "Opening socket\n"));
60 socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
9ff99d58 61 if (sock == INVALID_SOCKET) {
00afbb65 62 return -1;
9ff99d58 63 }
00afbb65
LM
64
65 struct sockaddr_in addr = {0};
66 addr.sin_family = PF_INET;
67 addr.sin_port = htons (port);
68 addr.sin_addr.s_addr = htonl (INADDR_ANY);
69
70 VERBOSE (DEBUG, fprintf (stdout, "Binding socket\n"));
71 int rc = bind (sock, (struct sockaddr *)&addr, sizeof (addr));
9ff99d58 72 if (rc == SOCKET_ERROR) {
04a2223d 73 VERBOSE (ERROR, fprintf (stderr, "error: bind %d\n", ERRNO));
00afbb65 74 rc = closesocket (sock);
9ff99d58 75 if (rc == SOCKET_ERROR) {
04a2223d 76 VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO));
00afbb65
LM
77 }
78 return -1;
79 }
80
81 VERBOSE (DEBUG, fprintf (stdout, "Configuring socket\n"));
9ff99d58 82#ifndef _WIN32 /* Posix */
00afbb65
LM
83 fcntl (sock, F_SETFL, O_NONBLOCK);
84#endif
85 int val = 1;
86 rc = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
87 if (rc < 0) {
04a2223d 88 VERBOSE (ERROR, fprintf (stderr, "error: %s\n", "setsockopt/TCP_NODELAY"));
00afbb65 89 closesocket (sock);
9ff99d58 90 if (rc == SOCKET_ERROR) {
04a2223d
LM
91 VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO));
92 }
93 return -1;
94 }
95
96 rc = listen (sock, BACKLOG);
97 if (rc < 0) {
98 VERBOSE (ERROR, fprintf (stderr, "error: %s\n", "listen"));
99 closesocket (sock);
100 if (rc == SOCKET_ERROR) {
101 VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO));
9ff99d58 102 }
00afbb65
LM
103 return -1;
104 }
105
106 return sock;
107}
108
109/* close listening socket */
110void close_listening_socket (socket_t sock)
111{
9ff99d58
LM
112 int rc = closesocket (sock);
113 if (rc == SOCKET_ERROR) {
114 VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO));
115 }
00afbb65
LM
116#ifdef _WIN32 /* Windows */
117 WSACleanup ();
118#endif
119}
120
04a2223d
LM
121/* accept incomming connection */
122
123int accept_incoming_connection (socket_t sock)
124{
125 int connection = accept (sock, NULL, 0);
126 if (connection < 0) {
127 return connection;
128 }
129
130#ifndef _WIN32 /* POSIX */
131 fcntl (connection, F_SETFL, O_NONBLOCK);
132#endif
133 int val = 1;
134 rc = setsockopt (connection, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
135 if (rc < 0) {
136 VERBOSE (ERROR, fprintf (stderr, "error: %s\n", "setsockopt/TCP_NODELAY"));
137 closesocket (connection);
138 if (rc == SOCKET_ERROR) {
139 VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO));
140 }
141 return -1;
142 }
143
144 return connection;
145}
146
147/* receive data */
148int receive_data (socket_t sock, unsigned char data, int maxlen)
149{
150
151 /* timeout management */
152 fd_set rfds;
153 struct timeval tv = { 0, TIMEOUT };
154 FD_ZERO (&rfds);
155 FD_SET (sock, &rfds);
156
157 int retval = select (sock + 1, &rfds, NULL, NULL, &tv);
158 if (retval != 1)
159 return retval; /* 0 or SOCKET_ERROR */
160
161 /* read from socket */
162 int len = read (sock, data, maxlen);
163
164 if (rc = 0) { /* sock closed */
165 return 0;
166 } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
167 return -1;
168 } else if (rc > 0) {
169 return len;
170 }
171
172 /* do we retry ? */
173
174 return -2;
175}
176
06ec8057
LM
177
178/* vim: set ts=4 sw=4 et: */