Ensure request is sent even if ebb_client_body_write isn't called
[ebb.git] / src / ebb.c
bloba18648b34c18986ac1bc845b199db9c7eb74bfcb
1 /* The Ebb Web Server
2 * Copyright (c) 2008 Ry Dahl. This software is released under the MIT
3 * License. See README file for details.
4 */
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/types.h>
8 #include <arpa/inet.h>
9 #include <netinet/tcp.h>
10 #include <sys/un.h>
11 #include <netdb.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include <assert.h>
20 #define EV_STANDALONE 1
21 #include <ev.c>
22 #include <glib.h>
24 #include "parser.h"
25 #include "ebb.h"
27 #define min(a,b) (a < b ? a : b)
28 #define ramp(a) (a > 0 ? a : 0)
30 static void client_init(ebb_client *client);
32 static void set_nonblock(int fd)
34 int flags = fcntl(fd, F_GETFL, 0);
35 assert(0 <= fcntl(fd, F_SETFL, flags | O_NONBLOCK) && "Setting socket non-block failed!");
39 void env_add(ebb_client *client, const char *field, int flen, const char *value, int vlen)
41 if(client->env_size >= EBB_MAX_ENV) {
42 client->parser.overflow_error = TRUE;
43 return;
45 client->env[client->env_size].type = -1;
46 client->env[client->env_size].field = field;
47 client->env[client->env_size].field_length = flen;
48 client->env[client->env_size].value = value;
49 client->env[client->env_size].value_length = vlen;
50 client->env_size += 1;
54 void env_add_const(ebb_client *client, int type, const char *value, int vlen)
56 if(client->env_size >= EBB_MAX_ENV) {
57 client->parser.overflow_error = TRUE;
58 return;
60 client->env[client->env_size].type = type;
61 client->env[client->env_size].field = NULL;
62 client->env[client->env_size].field_length = -1;
63 client->env[client->env_size].value = value;
64 client->env[client->env_size].value_length = vlen;
65 client->env_size += 1;
69 void http_field_cb(void *data, const char *field, size_t flen, const char *value, size_t vlen)
71 ebb_client *client = (ebb_client*)(data);
72 assert(field != NULL);
73 assert(value != NULL);
74 env_add(client, field, flen, value, vlen);
78 void on_element(void *data, int type, const char *at, size_t length)
80 ebb_client *client = (ebb_client*)(data);
81 env_add_const(client, type, at, length);
85 static void dispatch(ebb_client *client)
87 ebb_server *server = client->server;
88 if(client->open == FALSE)
89 return;
90 client->in_use = TRUE;
92 /* XXX decide if to use keep-alive or not? */
94 server->request_cb(client, server->request_cb_data);
98 static void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
100 ebb_client *client = (ebb_client*)(watcher->data);
102 assert(client->server->loop == loop);
103 assert(&(client->timeout_watcher) == watcher);
105 ebb_client_close(client);
106 #ifdef DEBUG
107 g_message("peer timed out");
108 #endif
111 #define client_finished_parsing http_parser_is_finished(&client->parser)
112 #define total_request_size (client->parser.content_length + client->parser.nread)
114 static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents)
116 ebb_client *client = (ebb_client*)(watcher->data);
118 assert(client->in_use == FALSE);
119 assert(client->open);
120 assert(client->server->open);
121 assert(client->server->loop == loop);
122 assert(&client->read_watcher == watcher);
124 ssize_t read = recv( client->fd
125 , client->request_buffer + client->read
126 , EBB_BUFFERSIZE - client->read
129 if(read < 0) goto error;
130 if(read == 0) goto error; /* XXX is this the right action to take for read==0 ? */
131 client->read += read;
132 ev_timer_again(loop, &client->timeout_watcher);
134 // if(client->read == EBB_BUFFERSIZE) goto error;
136 if(FALSE == client_finished_parsing) {
137 http_parser_execute( &client->parser
138 , client->request_buffer
139 , client->read
140 , client->parser.nread
142 if(http_parser_has_error(&client->parser)) goto error;
145 if(client_finished_parsing) {
146 assert(client->read <= total_request_size);
147 if(total_request_size == client->read || total_request_size > EBB_BUFFERSIZE) {
148 client->body_head = client->request_buffer + client->parser.nread;
149 client->body_head_len = client->read - client->parser.nread;
150 ev_io_stop(loop, watcher);
151 dispatch(client);
152 return;
155 return;
156 error:
157 #ifdef DEBUG
158 if(read < 0) g_message("Error recving data: %s", strerror(errno));
159 #endif
160 ebb_client_close(client);
164 static void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
166 ebb_client *client = (ebb_client*)(watcher->data);
167 ssize_t sent;
169 if(client->status_written == FALSE || client->headers_written == FALSE) {
170 g_message("no status or headers - closing connection.");
171 goto error;
174 if(EV_ERROR & revents) {
175 g_message("on_client_writable() got error event, closing peer");
176 goto error;
179 //if(client->written != 0)
180 // g_debug("total written: %d", (int)(client->written));
182 sent = send( client->fd
183 , client->response_buffer->str + sizeof(gchar)*(client->written)
184 , client->response_buffer->len - client->written
187 if(sent < 0) {
188 #ifdef DEBUG
189 g_message("Error writing: %s", strerror(errno));
190 #endif
191 goto error;
192 } else if(sent == 0) {
193 /* is this the wrong thing to do? */
194 g_message("Sent zero bytes? Closing connection");
195 goto error;
197 client->written += sent;
199 assert(client->written <= client->response_buffer->len);
200 //g_message("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
202 ev_timer_again(loop, &client->timeout_watcher);
204 if(client->written == client->response_buffer->len) {
205 /* stop the write watcher. to be restarted by the next call to ebb_client_write_body
206 * or if client->body_written is set (by using ebb_client_release) then
207 * we close the connection
209 ev_io_stop(loop, watcher);
210 if(client->body_written) {
211 client->keep_alive ? client_init(client) : ebb_client_close(client);
214 return;
215 error:
216 ebb_client_close(client);
220 static void client_init(ebb_client *client)
222 assert(client->in_use == FALSE);
224 /* If the client is already open, reuse the fd, just reset all the parameters
225 * this would happen in the case of a keep_alive request
227 if(!client->open) {
228 /* DO SOCKET STUFF */
229 socklen_t len;
230 int fd = accept(client->server->fd, (struct sockaddr*)&(client->sockaddr), &len);
231 if(fd < 0) {
232 perror("accept()");
233 return;
235 client->open = TRUE;
236 client->fd = fd;
239 set_nonblock(client->fd);
241 /* IP Address */
242 if(client->server->port)
243 client->ip = inet_ntoa(client->sockaddr.sin_addr);
245 /* INITIALIZE http_parser */
246 http_parser_init(&client->parser);
247 client->parser.data = client;
248 client->parser.http_field = http_field_cb;
249 client->parser.on_element = on_element;
251 /* OTHER */
252 client->env_size = 0;
253 client->read = 0;
254 if(client->request_buffer == NULL) {
255 /* Only allocate the request_buffer once */
256 client->request_buffer = (char*)malloc(EBB_BUFFERSIZE);
258 client->keep_alive = FALSE;
259 client->status_written = client->headers_written = client->body_written = FALSE;
260 client->written = 0;
262 if(client->response_buffer != NULL)
263 g_string_free(client->response_buffer, TRUE);
264 client->response_buffer = g_string_new("");
266 /* SETUP READ AND TIMEOUT WATCHERS */
267 client->write_watcher.data = client;
268 ev_init (&client->write_watcher, on_client_writable);
269 ev_io_set (&client->write_watcher, client->fd, EV_WRITE | EV_ERROR);
270 /* Note, do not start write_watcher until there is something to be written.
271 * See ebb_client_write_body() */
273 client->read_watcher.data = client;
274 ev_init(&client->read_watcher, on_client_readable);
275 ev_io_set(&client->read_watcher, client->fd, EV_READ | EV_ERROR);
276 ev_io_start(client->server->loop, &client->read_watcher);
278 client->timeout_watcher.data = client;
279 ev_timer_init(&client->timeout_watcher, on_timeout, EBB_TIMEOUT, EBB_TIMEOUT);
280 ev_timer_start(client->server->loop, &client->timeout_watcher);
284 static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
286 ebb_server *server = (ebb_server*)(watcher->data);
287 assert(server->open);
288 assert(server->loop == loop);
289 assert(&server->request_watcher == watcher);
291 if(EV_ERROR & revents) {
292 g_message("on_request() got error event, closing server.");
293 ebb_server_unlisten(server);
294 return;
296 /* Now we're going to initialize the client
297 * and set up her callbacks for read and write
298 * the client won't get passed back to the user, however,
299 * until the request is complete and parsed.
301 int i;
302 ebb_client *client;
303 /* Get next availible peer */
304 for(i=0; i < EBB_MAX_CLIENTS; i++)
305 if(!server->clients[i].in_use && !server->clients[i].open) {
306 client = &(server->clients[i]);
307 break;
309 if(client == NULL) {
310 g_message("Too many peers. Refusing connections.");
311 return;
314 #ifdef DEBUG
315 int count = 0;
316 for(i = 0; i < EBB_MAX_CLIENTS; i++)
317 if(server->clients[i].open) count += 1;
318 g_debug("%d open connections", count);
319 #endif
321 client_init(client);
325 ebb_server* ebb_server_alloc()
327 ebb_server *server = g_new0(ebb_server, 1);
328 return server;
332 void ebb_server_init( ebb_server *server
333 , struct ev_loop *loop
334 , ebb_request_cb request_cb
335 , void *request_cb_data
338 int i;
339 for(i=0; i < EBB_MAX_CLIENTS; i++) {
340 server->clients[i].request_buffer = NULL;
341 server->clients[i].response_buffer = NULL;
342 server->clients[i].open = FALSE;
343 server->clients[i].in_use = FALSE;
344 server->clients[i].server = server;
347 server->request_cb = request_cb;
348 server->request_cb_data = request_cb_data;
349 server->loop = loop;
350 server->open = FALSE;
351 server->fd = -1;
352 return;
353 error:
354 ebb_server_free(server);
355 return;
359 void ebb_server_free(ebb_server *server)
361 ebb_server_unlisten(server);
363 if(server->port)
364 free(server->port);
365 if(server->socketpath)
366 free(server->socketpath);
367 free(server);
371 void ebb_server_unlisten(ebb_server *server)
373 if(server->open) {
374 int i;
375 ebb_client *client;
376 ev_io_stop(server->loop, &server->request_watcher);
377 close(server->fd);
378 if(server->socketpath) {
379 unlink(server->socketpath);
380 server->socketpath = NULL;
382 if(server->port) {
383 free(server->port);
384 server->port = NULL;
386 server->open = FALSE;
391 int ebb_server_listen_on_fd(ebb_server *server, const int sfd)
393 if (listen(sfd, EBB_MAX_CLIENTS) < 0) {
394 perror("listen()");
395 return -1;
398 set_nonblock(sfd); /* XXX: superfluous? */
400 server->fd = sfd;
401 assert(server->port == NULL);
402 assert(server->socketpath == NULL);
403 assert(server->open == FALSE);
404 server->open = TRUE;
406 server->request_watcher.data = server;
407 ev_init (&server->request_watcher, on_request);
408 ev_io_set (&server->request_watcher, server->fd, EV_READ | EV_ERROR);
409 ev_io_start (server->loop, &server->request_watcher);
411 return server->fd;
415 int ebb_server_listen_on_port(ebb_server *server, const int port)
417 int sfd = -1;
418 struct linger ling = {0, 0};
419 struct sockaddr_in addr;
420 int flags = 1;
422 if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
423 perror("socket()");
424 goto error;
427 flags = 1;
428 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
429 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
430 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
431 setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
434 * the memset call clears nonstandard fields in some impementations
435 * that otherwise mess things up.
437 memset(&addr, 0, sizeof(addr));
439 addr.sin_family = AF_INET;
440 addr.sin_port = htons(port);
441 addr.sin_addr.s_addr = htonl(INADDR_ANY);
443 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
444 perror("bind()");
445 goto error;
448 int ret = ebb_server_listen_on_fd(server, sfd);
449 if (ret >= 0) {
450 assert(server->port == NULL);
451 server->port = malloc(sizeof(char)*8); /* for easy access to the port */
452 sprintf(server->port, "%d", port);
454 return ret;
455 error:
456 if(sfd > 0) close(sfd);
457 return -1;
461 int ebb_server_listen_on_unix_socket(ebb_server *server, const char *socketpath)
463 int sfd = -1;
464 struct linger ling = {0, 0};
465 struct sockaddr_un addr;
466 struct stat tstat;
467 int flags =1;
468 int old_umask = -1;
469 int access_mask = 0777;
471 if(( sfd = socket(AF_UNIX, SOCK_STREAM, 0) ) == -1) {
472 perror("socket()");
473 goto error;
476 /* Clean up a previous socket file if we left it around */
477 if(lstat(socketpath, &tstat) == 0 && S_ISSOCK(tstat.st_mode)) {
478 unlink(socketpath);
481 flags = 1;
482 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
483 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
484 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
487 * the memset call clears nonstandard fields in some impementations
488 * that otherwise mess things up.
490 memset(&addr, 0, sizeof(addr));
492 addr.sun_family = AF_UNIX;
493 strcpy(addr.sun_path, socketpath);
494 old_umask = umask( ~(access_mask & 0777) );
496 if(bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
497 perror("bind()");
498 goto error;
500 umask(old_umask);
502 int ret = ebb_server_listen_on_fd(server, sfd);
503 if (ret >= 0) {
504 assert(server->socketpath == NULL);
505 server->socketpath = strdup(socketpath);
507 return ret;
508 error:
509 if(sfd > 0) close(sfd);
510 return -1;
514 int ebb_server_clients_in_use_p(ebb_server *server)
516 int i;
517 for(i = 0; i < EBB_MAX_CLIENTS; i++)
518 if(server->clients[i].in_use) return TRUE;
519 return FALSE;
523 void ebb_client_release(ebb_client *client)
525 assert(client->in_use);
526 client->in_use = FALSE;
528 if(client->headers_written == FALSE) {
529 g_string_append(client->response_buffer, "\r\n");
530 client->headers_written = TRUE;
532 client->body_written = TRUE;
534 /* If the write_watcher isn't yet active, then start it. It could be that
535 * we're streaming and the watcher has been stopped. In that case we
536 * start it again since we have more to write. */
537 if(ev_is_active(&client->write_watcher) == FALSE) {
538 set_nonblock(client->fd);
539 ev_io_start(client->server->loop, &client->write_watcher);
542 if(client->written == client->response_buffer->len)
543 ebb_client_close(client);
547 void ebb_client_close(ebb_client *client)
549 if(client->open) {
550 ev_io_stop(client->server->loop, &client->read_watcher);
551 ev_io_stop(client->server->loop, &client->write_watcher);
552 ev_timer_stop(client->server->loop, &client->timeout_watcher);
554 client->ip = NULL;
556 g_string_free(client->response_buffer, TRUE);
557 client->response_buffer = NULL;
559 close(client->fd);
560 client->open = FALSE;
565 void ebb_client_write_status(ebb_client *client, int status, const char *reason_phrase)
567 assert(client->in_use);
568 if(!client->open) return;
569 assert(client->status_written == FALSE);
570 g_string_append_printf( client->response_buffer
571 , "HTTP/1.1 %d %s\r\n"
572 , status
573 , reason_phrase
575 client->status_written = TRUE;
579 void ebb_client_write_header(ebb_client *client, const char *field, const char *value)
581 assert(client->in_use);
582 if(!client->open) return;
583 assert(client->status_written == TRUE);
584 assert(client->headers_written == FALSE);
586 if(strcmp(field, "Connection") == 0 && strcmp(value, "Keep-Alive") == 0) {
587 client->keep_alive = TRUE;
589 g_string_append_printf( client->response_buffer
590 , "%s: %s\r\n"
591 , field
592 , value
597 void ebb_client_write_body(ebb_client *client, const char *data, int length)
599 assert(client->in_use);
600 if(!client->open) return;
602 if(client->headers_written == FALSE) {
603 g_string_append(client->response_buffer, "\r\n");
604 client->headers_written = TRUE;
607 g_string_append_len(client->response_buffer, data, length);
609 /* If the write_watcher isn't yet active, then start it. It could be that
610 * we're streaming and the watcher has been stopped. In that case we
611 * start it again since we have more to write. */
612 if(ev_is_active(&client->write_watcher) == FALSE) {
613 set_nonblock(client->fd);
614 ev_io_start(client->server->loop, &client->write_watcher);
618 // int ebb_client_should_keep_alive(ebb_client*)
619 // {
620 // /* TODO - return boolean */
621 // if env['HTTP_VERSION'] == 'HTTP/1.0'
622 // return true if env['HTTP_CONNECTION'] =~ /Keep-Alive/i
623 // else
624 // return true unless env['HTTP_CONNECTION'] =~ /close/i
625 // end
626 // false
627 // }