Remove begin_transmission API
[ebb.git] / src / ebb.c
blobfdc934d0e7f39517e04dc0c49e5fdca901755398
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 #include <pthread.h>
21 #include <glib.h>
23 #define EV_STANDALONE 1
24 #include <ev.c>
26 #include "parser.h"
27 #include "ebb.h"
29 #define min(a,b) (a < b ? a : b)
30 #define ramp(a) (a > 0 ? a : 0)
32 static int server_socket_unix(const char *path, int access_mask);
34 void env_add(ebb_client *client, const char *field, int flen, const char *value, int vlen)
36 if(client->env_size >= EBB_MAX_ENV) {
37 client->parser.overflow_error = TRUE;
38 return;
40 client->env[client->env_size].type = EBB_FIELD_VALUE_PAIR;
41 client->env[client->env_size].field = field;
42 client->env[client->env_size].field_length = flen;
43 client->env[client->env_size].value = value;
44 client->env[client->env_size].value_length = vlen;
45 client->env_size += 1;
49 void env_add_const(ebb_client *client, int type, const char *value, int vlen)
51 if(client->env_size >= EBB_MAX_ENV) {
52 client->parser.overflow_error = TRUE;
53 return;
55 client->env[client->env_size].type = type;
56 client->env[client->env_size].field = NULL;
57 client->env[client->env_size].field_length = -1;
58 client->env[client->env_size].value = value;
59 client->env[client->env_size].value_length = vlen;
60 client->env_size += 1;
64 void http_field_cb(void *data, const char *field, size_t flen, const char *value, size_t vlen)
66 ebb_client *client = (ebb_client*)(data);
67 assert(field != NULL);
68 assert(value != NULL);
69 env_add(client, field, flen, value, vlen);
73 void request_method_cb(void *data, const char *at, size_t length)
75 ebb_client *client = (ebb_client*)(data);
76 env_add_const(client, EBB_REQUEST_METHOD, at, length);
80 void request_uri_cb(void *data, const char *at, size_t length)
82 ebb_client *client = (ebb_client*)(data);
83 env_add_const(client, EBB_REQUEST_URI, at, length);
87 void fragment_cb(void *data, const char *at, size_t length)
89 ebb_client *client = (ebb_client*)(data);
90 env_add_const(client, EBB_FRAGMENT, at, length);
94 void request_path_cb(void *data, const char *at, size_t length)
96 ebb_client *client = (ebb_client*)(data);
97 env_add_const(client, EBB_REQUEST_PATH, at, length);
101 void query_string_cb(void *data, const char *at, size_t length)
103 ebb_client *client = (ebb_client*)(data);
104 env_add_const(client, EBB_QUERY_STRING, at, length);
108 void http_version_cb(void *data, const char *at, size_t length)
110 ebb_client *client = (ebb_client*)(data);
111 env_add_const(client, EBB_HTTP_VERSION, at, length);
115 void content_length_cb(void *data, const char *at, size_t length)
117 ebb_client *client = (ebb_client*)(data);
118 env_add_const(client, EBB_CONTENT_LENGTH, at, length);
119 /* atoi_length - why isn't this in the statndard library? i hate c */
120 assert(client->content_length == 0);
121 int i, mult;
122 for(mult=1, i=length-1; i>=0; i--, mult*=10)
123 client->content_length += (at[i] - '0') * mult;
127 static void dispatch(ebb_client *client)
129 ebb_server *server = client->server;
131 if(client->open == FALSE)
132 return;
134 /* Set the env variables */
135 if(server->port) {
136 env_add_const(client, EBB_SERVER_PORT
137 , server->port
138 , strlen(server->port)
141 client->in_use = TRUE;
142 server->request_cb(client, server->request_cb_data);
146 static void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
148 ebb_client *client = (ebb_client*)(watcher->data);
150 assert(client->server->loop == loop);
151 assert(&(client->timeout_watcher) == watcher);
153 ebb_client_close(client);
154 #ifdef DEBUG
155 g_message("peer timed out");
156 #endif
159 #define client_finished_parsing http_parser_is_finished(&client->parser)
160 #define total_request_size (client->content_length + client->parser.nread)
162 static void* read_body_into_file(void *_client)
164 ebb_client *client = (ebb_client*)_client;
165 static unsigned int id;
166 FILE *tmpfile;
168 assert(client->open);
169 assert(client->server->open);
170 assert(client->content_length > 0);
171 assert(client_finished_parsing);
173 /* set blocking socket */
174 int flags = fcntl(client->fd, F_GETFL, 0);
175 assert(0 <= fcntl(client->fd, F_SETFL, flags & ~O_NONBLOCK));
177 sprintf(client->upload_file_filename, "/tmp/ebb_upload_%010d", id++);
178 tmpfile = fopen(client->upload_file_filename, "w+");
179 if(tmpfile == NULL) g_message("Cannot open tmpfile %s", client->upload_file_filename);
180 client->upload_file = tmpfile;
182 size_t body_head_length = client->read - client->parser.nread;
183 size_t written = 0, r;
184 while(written < body_head_length) {
185 r = fwrite( client->request_buffer + sizeof(char)*(client->parser.nread + written)
186 , sizeof(char)
187 , body_head_length - written
188 , tmpfile
190 if(r <= 0) {
191 ebb_client_close(client);
192 return NULL;
194 written += r;
197 int bufsize = 5*1024;
198 char buffer[bufsize];
199 size_t received;
200 while(written < client->content_length) {
201 received = recv(client->fd
202 , buffer
203 , min(client->content_length - written, bufsize)
206 if(received < 0) goto error;
207 client->read += received;
209 ssize_t w = 0;
210 int rv;
211 while(w < received) {
212 rv = fwrite( buffer + w*sizeof(char)
213 , sizeof(char)
214 , received - w
215 , tmpfile
217 if(rv <= 0) goto error;
218 w += rv;
220 written += received;
222 rewind(tmpfile);
223 // g_debug("%d bytes written to file %s", written, client->upload_file_filename);
224 dispatch(client);
225 return NULL;
226 error:
227 ebb_client_close(client);
228 return NULL;
232 static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents)
234 ebb_client *client = (ebb_client*)(watcher->data);
236 assert(client->in_use == FALSE);
237 assert(client->open);
238 assert(client->server->open);
239 assert(client->server->loop == loop);
240 assert(&client->read_watcher == watcher);
242 ssize_t read = recv( client->fd
243 , client->request_buffer + client->read
244 , EBB_BUFFERSIZE - client->read
247 if(read < 0) goto error;
248 if(read == 0) goto error; /* XXX is this the right action to take for read==0 ? */
249 client->read += read;
250 ev_timer_again(loop, &client->timeout_watcher);
252 if(client->read == EBB_BUFFERSIZE) goto error;
254 if(FALSE == client_finished_parsing) {
255 http_parser_execute( &client->parser
256 , client->request_buffer
257 , client->read
258 , client->parser.nread
260 if(http_parser_has_error(&client->parser)) goto error;
263 if(client_finished_parsing) {
264 if(total_request_size == client->read) {
265 ev_io_stop(loop, watcher);
266 client->nread_from_body = 0;
267 dispatch(client);
268 return;
270 if(total_request_size > EBB_BUFFERSIZE ) {
271 /* read body into file - in a thread */
272 ev_io_stop(loop, watcher);
273 pthread_t thread;
274 assert(0 <= pthread_create(&thread, NULL, read_body_into_file, client));
275 pthread_detach(thread);
276 return;
279 return;
280 error:
281 if(read < 0) g_message("Error recving data: %s", strerror(errno));
282 ebb_client_close(client);
286 static void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
288 ebb_client *client = (ebb_client*)(watcher->data);
289 ssize_t sent;
291 if(client->status_written == FALSE || client->headers_written == FALSE) {
292 g_message("no status or headers - closing connection.");
293 goto error;
296 if(EV_ERROR & revents) {
297 g_message("on_client_writable() got error event, closing peer");
298 goto error;
301 //if(client->written != 0)
302 // g_debug("total written: %d", (int)(client->written));
304 sent = send( client->fd
305 , client->response_buffer->str + sizeof(gchar)*(client->written)
306 , client->response_buffer->len - client->written
309 if(sent < 0) {
310 #ifdef DEBUG
311 g_message("Error writing: %s", strerror(errno));
312 #endif
313 goto error;
314 } else if(sent == 0) {
315 /* is this the wrong thing to do? */
316 g_message("Sent zero bytes? Closing connection");
317 goto error;
319 client->written += sent;
321 assert(client->written <= client->response_buffer->len);
322 //g_message("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
324 ev_timer_again(loop, &(client->timeout_watcher));
326 if(client->written == client->response_buffer->len) {
327 ev_io_stop(loop, watcher);
328 if(client->body_written)
329 ebb_client_close(client);
331 return;
332 error:
333 ebb_client_close(client);
337 static client_init(ebb_server *server, ebb_client *client)
339 assert(client->in_use == FALSE);
340 #ifdef DEBUG
341 /* does ragel fuck up if request buffer isn't null? */
342 for(i=0; i< EBB_BUFFERSIZE; i++)
343 client->request_buffer[i] = 'A';
344 #endif
346 client->open = TRUE;
347 client->server = server;
349 /* DO SOCKET STUFF */
350 socklen_t len;
351 client->fd = accept(server->fd, (struct sockaddr*)&(server->sockaddr), &len);
352 if(client->fd < 0) {
353 perror("accept()");
354 client->open = FALSE;
355 return;
358 int flags = fcntl(client->fd, F_GETFL, 0);
359 assert(0 <= fcntl(client->fd, F_SETFL, flags | O_NONBLOCK));
361 /* INITIALIZE http_parser */
362 http_parser_init(&(client->parser));
363 client->parser.data = client;
364 client->parser.http_field = http_field_cb;
365 client->parser.request_method = request_method_cb;
366 client->parser.request_uri = request_uri_cb;
367 client->parser.fragment = fragment_cb;
368 client->parser.request_path = request_path_cb;
369 client->parser.query_string = query_string_cb;
370 client->parser.http_version = http_version_cb;
371 client->parser.content_length = content_length_cb;
373 /* OTHER */
374 client->env_size = 0;
375 client->read = client->nread_from_body = 0;
376 client->response_buffer->len = 0; /* see note in ebb_client_close */
377 client->content_length = 0;
378 if(client->request_buffer == NULL) {
379 client->request_buffer = (char*)malloc(EBB_BUFFERSIZE);
382 client->status_written = FALSE;
383 client->headers_written = FALSE;
384 client->body_written = FALSE;
385 client->written = 0;
387 /* SETUP READ AND TIMEOUT WATCHERS */
388 client->write_watcher.data = client;
389 ev_init (&client->write_watcher, on_client_writable);
390 ev_io_set (&client->write_watcher, client->fd, EV_WRITE | EV_ERROR);
391 /* Note, do not start write_watcher until there is something to be written.
392 * See ebb_client_write_body() */
394 client->read_watcher.data = client;
395 ev_init(&client->read_watcher, on_client_readable);
396 ev_io_set(&client->read_watcher, client->fd, EV_READ | EV_ERROR);
397 ev_io_start(server->loop, &client->read_watcher);
399 client->timeout_watcher.data = client;
400 ev_timer_init(&client->timeout_watcher, on_timeout, EBB_TIMEOUT, EBB_TIMEOUT);
401 ev_timer_start(server->loop, &client->timeout_watcher);
404 static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
406 ebb_server *server = (ebb_server*)(watcher->data);
407 assert(server->open);
408 assert(server->loop == loop);
409 assert(&server->request_watcher == watcher);
411 if(EV_ERROR & revents) {
412 g_message("on_request() got error event, closing server.");
413 ebb_server_unlisten(server);
414 return;
416 /* Now we're going to initialize the client
417 * and set up her callbacks for read and write
418 * the client won't get passed back to the user, however,
419 * until the request is complete and parsed.
421 int i;
422 ebb_client *client;
423 /* Get next availible peer */
424 for(i=0; i < EBB_MAX_CLIENTS; i++)
425 if(!server->clients[i].in_use && !server->clients[i].open) {
426 client = &(server->clients[i]);
427 break;
429 if(client == NULL) {
430 g_message("Too many peers. Refusing connections.");
431 return;
434 #ifdef DEBUG
435 int count = 0;
436 for(i = 0; i < EBB_MAX_CLIENTS; i++)
437 if(server->clients[i].open) count += 1;
438 g_debug("%d open connections", count);
439 #endif
441 client_init(server, client);
445 ebb_server* ebb_server_alloc()
447 ebb_server *server = g_new0(ebb_server, 1);
448 return server;
452 void ebb_server_init( ebb_server *server
453 , struct ev_loop *loop
454 , ebb_request_cb request_cb
455 , void *request_cb_data
458 int i;
459 for(i=0; i < EBB_MAX_CLIENTS; i++) {
460 server->clients[i].request_buffer = NULL;
461 server->clients[i].response_buffer = g_string_new("");
462 server->clients[i].open = FALSE;
463 server->clients[i].in_use = FALSE;
466 server->request_cb = request_cb;
467 server->request_cb_data = request_cb_data;
468 server->loop = loop;
469 server->open = FALSE;
470 server->fd = -1;
471 return;
472 error:
473 ebb_server_free(server);
474 return;
478 void ebb_server_free(ebb_server *server)
480 ebb_server_unlisten(server);
482 int i;
483 for(i=0; i < EBB_MAX_CLIENTS; i++)
484 g_string_free(server->clients[i].response_buffer, TRUE);
485 if(server->port)
486 free(server->port);
487 if(server->socketpath)
488 free(server->socketpath);
489 free(server);
493 void ebb_server_unlisten(ebb_server *server)
495 if(server->open) {
496 int i;
497 ebb_client *client;
498 ev_io_stop(server->loop, &server->request_watcher);
499 close(server->fd);
500 if(server->socketpath)
501 unlink(server->socketpath);
502 server->open = FALSE;
506 int ebb_server_listen_on_port(ebb_server *server, const int port)
508 int sfd = -1;
509 struct linger ling = {0, 0};
510 struct sockaddr_in addr;
511 int flags = 1;
513 if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
514 perror("socket()");
515 goto error;
518 flags = fcntl(sfd, F_GETFL, 0);
519 if(fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
520 perror("setting O_NONBLOCK");
521 goto error;
524 flags = 1;
525 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
526 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
527 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
528 setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
531 * the memset call clears nonstandard fields in some impementations
532 * that otherwise mess things up.
534 memset(&addr, 0, sizeof(addr));
536 addr.sin_family = AF_INET;
537 addr.sin_port = htons(port);
538 addr.sin_addr.s_addr = htonl(INADDR_ANY);
540 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
541 perror("bind()");
542 goto error;
544 if (listen(sfd, EBB_MAX_CLIENTS) < 0) {
545 perror("listen()");
546 goto error;
548 server->fd = sfd;
549 server->port = malloc(sizeof(char)*8); /* for easy access to the port */
550 sprintf(server->port, "%d", port);
551 assert(server->open == FALSE);
552 server->open = TRUE;
554 server->request_watcher.data = server;
555 ev_init (&server->request_watcher, on_request);
556 ev_io_set (&server->request_watcher, server->fd, EV_READ | EV_ERROR);
557 ev_io_start (server->loop, &server->request_watcher);
559 return server->fd;
560 error:
561 if(sfd > 0) close(sfd);
562 return -1;
566 int ebb_server_listen_on_socket(ebb_server *server, const char *socketpath)
568 // int fd = server_socket_unix(socketpath, 0755);
569 // if(fd < 0) return 0;
570 // server->socketpath = strdup(socketpath);
571 // server->fd = fd;
572 // server_listen(server);
573 // return fd;
577 void ebb_client_release(ebb_client *client)
579 assert(client->in_use);
580 client->in_use = FALSE;
581 client->body_written = TRUE;
582 if(client->written == client->response_buffer->len)
583 ebb_client_close(client);
587 void ebb_client_close(ebb_client *client)
589 if(client->open) {
590 ev_io_stop(client->server->loop, &client->read_watcher);
591 ev_io_stop(client->server->loop, &client->write_watcher);
592 ev_timer_stop(client->server->loop, &client->timeout_watcher);
594 if(client->upload_file) {
595 fclose(client->upload_file);
596 unlink(client->upload_file_filename);
599 /* here we do not free the already allocated GString client->response_buffer
600 * that we're holding the response in. we reuse it again -
601 * presumably because the backend is going to keep sending such long
602 * requests.
604 client->response_buffer->len = 0;
606 close(client->fd);
607 client->open = FALSE;
612 void ebb_client_write_status(ebb_client *client, int status, const char *human_status)
614 assert(client->in_use);
615 if(!client->open) return;
616 assert(client->status_written == FALSE);
617 g_string_append_printf( client->response_buffer
618 , "HTTP/1.1 %d %s\r\n"
619 , status
620 , human_status
622 client->status_written = TRUE;
625 void ebb_client_write_header(ebb_client *client, const char *field, const char *value)
627 assert(client->in_use);
628 if(!client->open) return;
629 assert(client->status_written == TRUE);
630 assert(client->headers_written == FALSE);
631 g_string_append_printf( client->response_buffer
632 , "%s: %s\r\n"
633 , field
634 , value
639 void ebb_client_write_body(ebb_client *client, const char *data, int length)
641 assert(client->in_use);
642 if(!client->open) return;
644 if(client->headers_written == FALSE) {
645 g_string_append(client->response_buffer, "\r\n");
648 g_string_append_len(client->response_buffer, data, length);
650 /* If the write_watcher isn't yet active, then start it. It could be that
651 * we're streaming and the watcher has been stopped. In that case we
652 * start it again since we have more to write. */
653 if(ev_is_active(&client->write_watcher) == FALSE) {
654 /* assure the socket is still in non-blocking mode */
655 int flags = fcntl(client->fd, F_GETFL, 0);
656 if(0 > fcntl(client->fd, F_SETFL, flags | O_NONBLOCK))
657 perror("fcntl() setting non-block");
658 client->headers_written = TRUE;
659 ev_io_start(client->server->loop, &client->write_watcher);
664 /* pass an allocated buffer and the length to read. this function will try to
665 * fill the buffer with that length of data read from the body of the request.
666 * the return value says how much was actually written.
668 int ebb_client_read(ebb_client *client, char *buffer, int length)
670 size_t read;
672 assert(client->in_use);
673 if(!client->open) return -1;
674 assert(client_finished_parsing);
676 if(client->upload_file) {
677 read = fread(buffer, 1, length, client->upload_file);
678 /* TODO error checking! */
679 return read;
680 } else {
681 char* request_body = client->request_buffer + client->parser.nread;
683 read = ramp(min(length, client->content_length - client->nread_from_body));
684 memcpy( buffer
685 , request_body + client->nread_from_body
686 , read
688 client->nread_from_body += read;
689 return read;
693 /* The following socket creation routines are modified and stolen from memcached */
696 static int server_socket_unix(const char *path, int access_mask) {
697 int sfd;
698 struct linger ling = {0, 0};
699 struct sockaddr_un addr;
700 struct stat tstat;
701 int flags =1;
702 int old_umask;
704 if (!path) {
705 return -1;
708 if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
709 perror("socket()");
710 return -1;
713 if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
714 fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
715 perror("setting O_NONBLOCK");
716 close(sfd);
717 return -1;
721 * Clean up a previous socket file if we left it around
723 if (lstat(path, &tstat) == 0) {
724 if (S_ISSOCK(tstat.st_mode))
725 unlink(path);
728 flags = 1;
729 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
730 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
731 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
734 * the memset call clears nonstandard fields in some impementations
735 * that otherwise mess things up.
737 memset(&addr, 0, sizeof(addr));
739 addr.sun_family = AF_UNIX;
740 strcpy(addr.sun_path, path);
741 old_umask=umask( ~(access_mask&0777));
742 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
743 perror("bind()");
744 close(sfd);
745 umask(old_umask);
746 return -1;
748 umask(old_umask);
749 if (listen(sfd, EBB_MAX_CLIENTS) == -1) {
750 perror("listen()");
751 close(sfd);
752 return -1;
754 return sfd;