Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / apps / websrv / net.c
blobf6ab5d8c709db8aa605f57206bede8392ae3210c
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/socket.h>
28 #include <netdb.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include "http.h"
32 #include "client.h"
33 #include "net.h"
35 #define SUPPORT_IPV6 1
37 struct sockaddr *sockName; // "Jmeno" portu
38 struct sockaddr *clientInfo; // Klient, ktere se pripojil
40 int mainSocket; // Soket
41 socklen_t addrlen; // Velikost adresy vzdaleneho pocĂ­tace
42 char *buffer; // Buffer
43 int client_count; // Pocet pripojenych clientu
44 int proto; // Protocol
46 client_t client_list;
49 int send_to_socket (int fd, char *data, unsigned len)
51 int ret;
52 if ((ret = send (fd, data, len, 0)) == -1) {
53 printf ("ERROR -> send () = -1\n");
54 return -1;
57 return ret;
60 int client_get (client_t *c)
62 if (c->ret > 32566) {
63 c->state = CLIENT_STATE_TIMEOUT;
64 return 1;
67 memset (buffer, 0, 1024);
68 int ret = recv (c->fd, buffer, 1024, 0);
70 if (ret < 1) {
71 c->ret ++;
72 return ret;
75 buffer[ret] = '\0';
77 // printf ("DATA: %s\n", buffer);
79 if (!strncmp (buffer, "GET /", 5)) {
81 int i;
82 for (i = 4; i < ret; i ++)
83 if (buffer[i] == ' ')
84 break;
86 if ((i-5) >= 32)
87 i = 36;
89 memcpy (c->page, buffer+5, i-5);
90 c->page[i-5] = '\0';
92 c->state = CLIENT_STATE_TRANSFER;
94 return 1;
95 } else
96 printf ("ERROR -> corrupted http session ..\n");
98 c->state = CLIENT_STATE_DONE;
100 return ret;
103 client_t *client_connected (int fd)
105 client_t *c;
106 for (c = client_list.next; c != &client_list; c = c->next)
107 if (c->fd == fd)
108 return 0;
110 // alloc and init context
111 client_t *ctx = (client_t *) malloc (sizeof (client_t));
113 if (!ctx)
114 return 0;
116 ctx->fd = fd;
117 ctx->state = CLIENT_STATE_CONNECTED;
118 ctx->ret = 0;
120 ctx->next = &client_list;
121 ctx->prev = client_list.prev;
122 ctx->prev->next = ctx;
123 ctx->next->prev = ctx;
125 return ctx;
128 int client_handle (client_t *c)
130 switch (c->state) {
131 case CLIENT_STATE_CONNECTED:
132 return client_get (c);
133 case CLIENT_STATE_TRANSFER:
134 return http_transfer (c);
135 case CLIENT_STATE_DONE:
136 case CLIENT_STATE_TIMEOUT:
137 /* disconnect socket */
138 close (c->fd);
140 /* delete client_t * struct from list */
141 c->next->prev = c->prev;
142 c->prev->next = c->next;
144 free (c);
145 return 0;
148 return 0;
151 int init (int port, int flags)
153 proto = AF_INET;
155 /* switch to IPv6 */
156 if (flags & FLAG_IPV6) {
157 proto = AF_INET6;
158 printf ("> initializing IPv6\n");
159 } else
160 printf ("> initializing IPv4\n");
162 if ((mainSocket = socket (proto, SOCK_STREAM, IPPROTO_TCP)) == -1) {
163 printf ("ERROR -> socket ()\n");
164 return -1;
167 if (proto == AF_INET6) {
168 struct sockaddr_in6 *sockName6 = (struct sockaddr_in6 *) malloc (sizeof (struct sockaddr_in6));
169 clientInfo = (struct sockaddr *) malloc (sizeof (struct sockaddr_in6));
171 if (!sockName6 || !clientInfo)
172 return 0;
174 sockName6->sin6_family = proto;
175 sockName6->sin6_port = htons (port);
176 //sockName6->sin6_addr.s6_addr = INADDR6_ANY;
178 sockName = (struct sockaddr *) sockName6;
180 addrlen = sizeof (struct sockaddr_in6);
181 } else {
182 struct sockaddr_in *sockName4 = (struct sockaddr_in *) malloc (sizeof (struct sockaddr_in));
183 clientInfo = (struct sockaddr *) malloc (sizeof (struct sockaddr_in));
185 if (!sockName4 || !clientInfo)
186 return 0;
188 sockName4->sin_family = proto;
189 sockName4->sin_port = htons (port);
190 sockName4->sin_addr.s_addr = INADDR_ANY;
192 sockName = (struct sockaddr *) sockName4;
194 addrlen = sizeof (struct sockaddr_in);
197 if ((bind (mainSocket, (struct sockaddr *) sockName, addrlen)) == -1) {
198 printf ("ERROR -> bind () - %d\n", port);
199 return -1;
202 /* max 10 connecting clients */
203 if (listen (mainSocket, 10) == -1) {
204 printf ("ERROR -> listen ()\n");
205 return -1;
208 // Let's switch socket mode to non-blocking
209 int oldFlag = fcntl (mainSocket, F_GETFL, 0);
210 if (fcntl (mainSocket, F_SETFL, oldFlag | O_NONBLOCK) == -1) {
211 printf ("ERROR -> fcntl ()\n");
212 return 0;
215 printf ("> listen on port: %d\n", port);
217 buffer = (char *) malloc (sizeof (char) * 1025);
219 if (!buffer) {
220 printf ("Buffer is out of memory\n");
221 return 0;
224 client_list.next = &client_list;
225 client_list.prev = &client_list;
227 client_count = 0;
229 return http_init ();
232 int loop ()
234 int client = 0;
236 client = accept (mainSocket, (struct sockaddr *) clientInfo, &addrlen);
238 if (client > 0) {
239 char str[40];
241 if (proto == AF_INET) {
242 struct sockaddr_in *clientInfoS = (struct sockaddr_in *) clientInfo;
243 inet_ntop (proto, (void *) &clientInfoS->sin_addr, str, 40);
245 printf ("> New client (%d) -- %s:%d connected !\n", client, str, clientInfoS->sin_port);
246 } else if (proto == AF_INET6) {
247 struct sockaddr_in6 *clientInfoS = (struct sockaddr_in6 *) clientInfo;
248 inet_ntop (proto, (void *) &clientInfoS->sin6_addr, str, 40);
250 printf ("> New client (%d) -- [%s]:%d connected !\n", client, str, clientInfoS->sin6_port);
253 // Nastavime soket do neblokovaciho rezimu
254 int oldFlag = fcntl (client, F_GETFL, 0);
255 if (fcntl (client, F_SETFL, oldFlag | O_NONBLOCK) == -1) {
256 printf ("Cant set socket to nonblocking mode\n");
257 return 0;
260 client_t *c = client_connected (client);
262 if (!c)
263 close (client);
266 unsigned i = 0;
268 client_t *c;
269 for (c = client_list.next; c != &client_list; c = c->next) {
270 if (!client_handle (c))
271 break;
273 i ++;
276 if (!i)
277 usleep (64);
279 return 1;