summaryrefslogtreecommitdiff
path: root/src/c/driver.c
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adamc@hcoop.net>2009-06-23 15:56:04 -0400
committerGravatar Adam Chlipala <adamc@hcoop.net>2009-06-23 15:56:04 -0400
commita4717bf85434747f0e96aa11030ce0869db2706c (patch)
tree5c08087fd98403edb3500ac4399ddece25c667ad /src/c/driver.c
parentca88628fbeb6fe8cadf9d7e12e5faccf2a7da96b (diff)
Initial implementation of protocols in Settings
Diffstat (limited to 'src/c/driver.c')
-rw-r--r--src/c/driver.c349
1 files changed, 0 insertions, 349 deletions
diff --git a/src/c/driver.c b/src/c/driver.c
deleted file mode 100644
index e8345be2..00000000
--- a/src/c/driver.c
+++ /dev/null
@@ -1,349 +0,0 @@
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include <pthread.h>
-
-#include <mhash.h>
-
-#include "urweb.h"
-#include "request.h"
-
-int uw_backlog = 10;
-
-typedef struct node {
- int fd;
- struct node *next;
-} *node;
-
-static node front = NULL, back = NULL;
-
-static int empty() {
- return front == NULL;
-}
-
-static void enqueue(int fd) {
- node n = malloc(sizeof(struct node));
-
- n->fd = fd;
- n->next = NULL;
- if (back)
- back->next = n;
- else
- front = n;
- back = n;
-}
-
-static int dequeue() {
- int ret = front->fd;
-
- front = front->next;
- if (!front)
- back = NULL;
-
- return ret;
-}
-
-static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER;
-
-static char *get_header(void *data, const char *h) {
- char *s = data;
- int len = strlen(h);
- char *p;
-
- while (p = strchr(s, ':')) {
- if (p - s == len && !strncasecmp(s, h, len)) {
- return p + 2;
- } else {
- if ((s = strchr(p, 0)) && s[1] != 0)
- s += 2;
- else
- return NULL;
- }
- }
-
- return NULL;
-}
-
-static void *worker(void *data) {
- int me = *(int *)data;
- uw_context ctx = uw_request_new_context();
- size_t buf_size = 2;
- char *buf = malloc(buf_size);
- uw_request_context rc = uw_new_request_context();
-
- while (1) {
- char *back = buf;
- int sock;
-
- pthread_mutex_lock(&queue_mutex);
- while (empty())
- pthread_cond_wait(&queue_cond, &queue_mutex);
- sock = dequeue();
- pthread_mutex_unlock(&queue_mutex);
-
- printf("Handling connection with thread #%d.\n", me);
-
- while (1) {
- int r;
- char *method, *path, *query_string, *headers, *body, *s, *s2;
-
- if (back - buf == buf_size - 1) {
- char *new_buf;
- buf_size *= 2;
- new_buf = realloc(buf, buf_size);
- back = new_buf + (back - buf);
- buf = new_buf;
- }
-
- r = recv(sock, back, buf_size - 1 - (back - buf), 0);
-
- if (r < 0) {
- fprintf(stderr, "Recv failed\n");
- break;
- }
-
- if (r == 0) {
- printf("Connection closed.\n");
- break;
- }
-
- back += r;
- *back = 0;
-
- if ((body = strstr(buf, "\r\n\r\n"))) {
- request_result rr;
-
- body[0] = body[1] = 0;
- body += 4;
-
- if ((s = strcasestr(buf, "\r\nContent-Length: ")) && s < body) {
- int clen;
-
- if (sscanf(s + 18, "%d\r\n", &clen) != 1) {
- fprintf(stderr, "Malformed Content-Length header\n");
- break;
- }
-
- while (back - body < clen) {
- if (back - buf == buf_size - 1) {
- char *new_buf;
- buf_size *= 2;
- new_buf = realloc(buf, buf_size);
-
- back = new_buf + (back - buf);
- body = new_buf + (body - buf);
- s = new_buf + (s - buf);
-
- buf = new_buf;
- }
-
- r = recv(sock, back, buf_size - 1 - (back - buf), 0);
-
- if (r < 0) {
- fprintf(stderr, "Recv failed\n");
- close(sock);
- goto done;
- }
-
- if (r == 0) {
- fprintf(stderr, "Connection closed.\n");
- close(sock);
- goto done;
- }
-
- back += r;
- *back = 0;
- }
- }
-
- if (!(s = strstr(buf, "\r\n"))) {
- fprintf(stderr, "No newline in request\n");
- close(sock);
- goto done;
- }
-
- *s = 0;
- headers = s + 2;
- method = s = buf;
-
- if (!strsep(&s, " ")) {
- fprintf(stderr, "No first space in HTTP command\n");
- close(sock);
- goto done;
- }
- path = s;
-
- if (s = strchr(path, ' '))
- *s = 0;
-
- if (s = strchr(path, '?')) {
- *s = 0;
- query_string = s+1;
- }
- else
- query_string = NULL;
-
- s = headers;
- while (s2 = strchr(s, '\r')) {
- s = s2;
-
- if (s[1] == 0)
- break;
-
- *s = 0;
- s += 2;
- }
-
- uw_set_headers(ctx, get_header, headers);
-
- rr = uw_request(rc, ctx, method, path, query_string, body, back - body, sock);
- uw_send(ctx, sock);
-
- if (rr == SERVED || rr == FAILED)
- close(sock);
- else if (rr != KEEP_OPEN)
- fprintf(stderr, "Illegal uw_request return code: %d\n", rr);
-
- break;
- }
- }
-
- done:
- uw_reset(ctx);
- }
-}
-
-static void help(char *cmd) {
- printf("Usage: %s [-p <port>] [-t <thread-count>]\n", cmd);
-}
-
-static void sigint(int signum) {
- printf("Exiting....\n");
- exit(0);
-}
-
-int main(int argc, char *argv[]) {
- // The skeleton for this function comes from Beej's sockets tutorial.
- int sockfd; // listen on sock_fd
- struct sockaddr_in my_addr;
- struct sockaddr_in their_addr; // connector's address information
- int sin_size, yes = 1;
- int uw_port = 8080, nthreads = 1, i, *names, opt;
-
- signal(SIGINT, sigint);
- signal(SIGPIPE, SIG_IGN);
-
- while ((opt = getopt(argc, argv, "hp:t:")) != -1) {
- switch (opt) {
- case '?':
- fprintf(stderr, "Unknown command-line option");
- help(argv[0]);
- return 1;
-
- case 'h':
- help(argv[0]);
- return 0;
-
- case 'p':
- uw_port = atoi(optarg);
- if (uw_port <= 0) {
- fprintf(stderr, "Invalid port number\n");
- help(argv[0]);
- return 1;
- }
- break;
-
- case 't':
- nthreads = atoi(optarg);
- if (nthreads <= 0) {
- fprintf(stderr, "Invalid thread count\n");
- help(argv[0]);
- return 1;
- }
- break;
-
- default:
- fprintf(stderr, "Unexpected getopt() behavior\n");
- return 1;
- }
- }
-
- uw_request_init();
-
- names = calloc(nthreads, sizeof(int));
-
- sockfd = socket(PF_INET, SOCK_STREAM, 0); // do some error checking!
-
- if (sockfd < 0) {
- fprintf(stderr, "Listener socket creation failed\n");
- return 1;
- }
-
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
- fprintf(stderr, "Listener socket option setting failed\n");
- return 1;
- }
-
- my_addr.sin_family = AF_INET; // host byte order
- my_addr.sin_port = htons(uw_port); // short, network byte order
- my_addr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP
- memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
-
- if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) < 0) {
- fprintf(stderr, "Listener socket bind failed\n");
- return 1;
- }
-
- if (listen(sockfd, uw_backlog) < 0) {
- fprintf(stderr, "Socket listen failed\n");
- return 1;
- }
-
- sin_size = sizeof their_addr;
-
- printf("Listening on port %d....\n", uw_port);
-
- {
- pthread_t thread;
- int name;
-
- if (pthread_create(&thread, NULL, client_pruner, &name)) {
- fprintf(stderr, "Error creating pruner thread\n");
- return 1;
- }
- }
-
- for (i = 0; i < nthreads; ++i) {
- pthread_t thread;
- names[i] = i;
- if (pthread_create(&thread, NULL, worker, &names[i])) {
- fprintf(stderr, "Error creating worker thread #%d\n", i);
- return 1;
- }
- }
-
- while (1) {
- int new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
-
- if (new_fd < 0) {
- fprintf(stderr, "Socket accept failed\n");
- return 1;
- }
-
- printf("Accepted connection.\n");
-
- pthread_mutex_lock(&queue_mutex);
- enqueue(new_fd);
- pthread_cond_broadcast(&queue_cond);
- pthread_mutex_unlock(&queue_mutex);
- }
-}