aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Draxinger <Wolfgang.Draxinger@physik.uni-muenchen.de>2013-03-08 20:08:35 +0100
committerWolfgang Draxinger <Wolfgang.Draxinger@physik.uni-muenchen.de>2013-03-08 20:08:35 +0100
commit720a430b3d9cc87512f1625e6d78391480dfb062 (patch)
tree4928bb840034d4396d95066719ef2bdbafc8f9ec
parentdfb3c1ca13a828405503d6ec2ee3979ae825326b (diff)
downloadlitheweb-720a430b3d9cc87512f1625e6d78391480dfb062.tar.gz
litheweb-720a430b3d9cc87512f1625e6d78391480dfb062.tar.bz2
Fri Mar 8 20:08:35 CET 2013
-rw-r--r--picohttp.c529
-rw-r--r--picohttp.h29
-rw-r--r--test/bsd_socket.c45
3 files changed, 473 insertions, 130 deletions
diff --git a/picohttp.c b/picohttp.c
index 10b7d3c..feef174 100644
--- a/picohttp.c
+++ b/picohttp.c
@@ -2,47 +2,131 @@
#include <alloca.h>
#include <string.h>
+#include <stdio.h>
static void picohttpStatus400BadRequest(
struct picohttpRequest *req )
{
+ fputs("400\n", stderr);
}
static void picohttpStatus404NotFound(
struct picohttpRequest *req )
{
+ char http_header[] = "HTTP/x.x 404 Not Found\r\nServer: picoweb\r\nContent-Type: text/text\r\n\r\n";
+ http_header[5] = '0'+req->httpversion.major;
+ http_header[7] = '0'+req->httpversion.minor;
+ picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header);
+ picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header);
}
static void picohttpStatus405MethodNotAllowed(
struct picohttpRequest *req )
{
+ fputs("405\n", stderr);
}
static void picohttpStatus414RequestURITooLong(
struct picohttpRequest *req )
{
+ char http_header[] = "HTTP/x.x 414 URI Too Long\r\nServer: picoweb\r\nContent-Type: text/text\r\n\r\n";
+ http_header[5] = '0'+req->httpversion.major;
+ http_header[7] = '0'+req->httpversion.minor;
+ picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header);
+ picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header);
}
static void picohttpStatus500InternalServerError(
struct picohttpRequest *req )
{
+ fputs("500\n", stderr);
}
static void picohttpStatus501NotImplemented(
struct picohttpRequest *req )
{
+ fputs("501\n", stderr);
}
static void picohttpStatus505HTTPVersionNotSupported(
struct picohttpRequest *req )
{
+ fputs("505\n", stderr);
}
-static int16_t picohttpIoSkipSpace(
- struct picohttpIoOps const * const ioops )
+static uint8_t picohttpIsCRLF(int16_t ch)
{
- int16_t ch;
- while(' ' == (char)(ch = picohttpIoGetch(ioops)));
+ switch(ch) {
+ case '\r':
+ case '\n':
+ return 1;
+ }
+ return 0;
+}
+
+static uint8_t picohttpIsLWS(int16_t ch)
+{
+ return
+ picohttpIsCRLF(ch) ||
+ ' ' == ch || '\t' == ch;
+}
+
+static int16_t picohttpIoSkipSpace (
+ struct picohttpIoOps const * const ioops,
+ int16_t ch)
+{
+ for(;;ch = 0) {
+ if(!ch)
+ ch = picohttpIoGetch(ioops);
+ if( 0 >= ch ||
+ ( ' ' != ch && '\t' != ch ) )
+ break;
+ }
+ return ch;
+}
+
+static int16_t picohttpIoSkipOverCRLF (
+ struct picohttpIoOps const * const ioops,
+ int16_t ch)
+{
+ for(;;ch = 0) {
+ if(!ch)
+ ch = picohttpIoGetch(ioops);
+ if( ch < 0 ) {
+ return -1;
+ }
+ if( ch == '\n' ) {
+ break;
+ }
+ if( ch == '\r' ) {
+ ch = picohttpIoGetch(ioops);
+ if( ch < 0 ) {
+ return -1;
+ }
+ if( ch != '\n' ) {
+ return 0;
+ }
+ break;
+ }
+ }
+ ch = picohttpIoGetch(ioops);
+ return ch;
+}
+
+static int16_t picohttpIoB10ToU8 (
+ uint8_t *i,
+ struct picohttpIoOps const * const ioops,
+ int16_t ch )
+{
+ if( !ch )
+ ch = picohttpIoGetch(ioops);
+
+ while( ch >= '0' && ch <= '9' ) {
+ *i *= 10;
+ *i += (ch & 0x0f);
+ ch = picohttpIoGetch(ioops);
+ }
+
return ch;
}
@@ -56,10 +140,10 @@ static int16_t picohttpIoGetPercentCh(
chr |= 0x20;
if( chr >= '0' && chr <= '9' ) {
- ch = ((chr)&0x0f);
+ ch = ((chr)&0x0f)<<4;
} else if(
chr >= 'a' && chr <= 'f' ) {
- ch = (((chr)&0x0f) + 9);
+ ch = (((chr)&0x0f) + 9)<<4;
}
if( 0 > (chr = picohttpIoGetch(ioops)))
@@ -67,199 +151,402 @@ static int16_t picohttpIoGetPercentCh(
chr |= 0x20;
if( chr >= '0' && chr <= '9' ) {
- ch |= ((chr)&0x0f) << 4;
+ ch |= ((chr)&0x0f);
} else if(
chr >= 'a' && chr <= 'f' ) {
- ch |= (((chr)&0x0f) + 9) << 4;
+ ch |= (((chr)&0x0f) + 9);
}
return ch;
}
-int picohttpMatchRoute(
- struct picohttpRequest * const req,
- struct picohttpURLRoute const * const routes )
+static size_t picohttpMatchURL(
+ char const * const urlhead,
+ char const * const url )
{
-}
-
-void picohttpProcessRequest(
- struct picohttpIoOps const * const ioops,
- struct picohttpURLRoute const * const routes )
-{
- char *url, *var;
- struct picohttpRequest request = {0,};
- size_t url_max_length = 0;
- size_t var_max_length = 0;
-
- for(size_t i = 0; routes[i].urlhead; i++) {
- size_t url_length =
- strlen(routes[i].urlhead) +
- routes[i].max_urltail_len;
+ size_t len_urlhead = strlen(urlhead);
+ size_t j;
+ for(j = 0; j < len_urlhead; j++) {
+ if( '|' == urlhead[j] ) {
+ /* hard URL termination */
+ if( url[j] ) {
+ return 0;
+ }
+ break;
+ }
- if(url_length > url_max_length)
- url_max_length = url_length;
+ if( '\\' == urlhead[j] ) {
+ /* soft URL termination, i.e. URL may be terminated
+ * by an optional '/' character */
+ if( url[j] && !( url[j] == '/' && !url[j+1] ) ) {
+ return 0;
+ }
+ break;
+ }
+ if( urlhead[j] != url[j] ) {
+ return 0;
+ }
}
- url = alloca(url_max_length+1);
- memset(url, 0, url_max_length+1);
+ if( url[j] && url[j] != '/' ) {
+ return 0;
+ }
+ return j;
+}
- request.url = url;
- request.urltail = 0;
- request.ioops = ioops;
- request.method = 0;
+static int8_t picohttpMatchRoute(
+ struct picohttpRequest * const req,
+ struct picohttpURLRoute const * const routes )
+{
+ struct picohttpURLRoute const *r;
+ for(size_t i = 0; (r = routes + i)->urlhead; i++) {
+ size_t l;
+ if( (l = picohttpMatchURL(r->urlhead, req->url)) &&
+ req->method & r->allowed_methods ) {
+ req->route = r;
+ req->urltail = req->url[l] ? req->url+l : 0;
+ return 1;
+ }
+ }
+ return 0;
+}
- /* Poor mans string matching tree; trade RAM for code */
+static int16_t picohttpProcessRequestMethod (
+ struct picohttpIoOps const * const ioops )
+{
+ int16_t method = 0;
+ /* Poor man's string matching tree; trade RAM for code */
switch( picohttpIoGetch(ioops) ) {
case 'H': switch( picohttpIoGetch(ioops) ) {
case 'E': switch( picohttpIoGetch(ioops) ) {
case 'A': switch( picohttpIoGetch(ioops) ) {
case 'D':
- request.method = PICOHTTP_METHOD_HEAD;
+ method = PICOHTTP_METHOD_HEAD;
break;
- }
+ case -1:
+ method = -1;
+ break;
+ } break;
+ case -1:
+ method = -1;
+ break;
} break;
+ case -1:
+ method = -1;
+ break;
} break;
case 'G': switch( picohttpIoGetch(ioops) ) {
case 'E': switch( picohttpIoGetch(ioops) ) {
case 'T':
- request.method = PICOHTTP_METHOD_GET;
+ method = PICOHTTP_METHOD_GET;
+ break;
+ case -1:
+ method = -1;
+ break;
} break;
+ case -1:
+ method = -1;
+ break;
} break;
case 'P': switch( picohttpIoGetch(ioops) ) {
case 'O': switch( picohttpIoGetch(ioops) ) {
case 'S': switch( picohttpIoGetch(ioops) ) {
case 'T':
- request.method = PICOHTTP_METHOD_POST;
+ method = PICOHTTP_METHOD_POST;
break;
- }
+ case -1:
+ method = -1;
+ break;
+ } break;
+ case -1:
+ method = -1;
+ break;
} break;
+ case -1:
+ method = -1;
+ break;
} break;
+ case -1:
+ method = -1;
+ break;
}
- if( !request.method ) {
- picohttpStatus501NotImplemented(&request);
- return;
- }
-
- int16_t ch;
+ return method;
+}
- ch = picohttpIoSkipSpace(ioops);
- if( ch < 0 ) {
- picohttpStatus500InternalServerError(&request);
- return;
- }
-
- url[0] = (char)ch;
- /* copy url up to the first query variable; note that this is not
- * fully compliant to RFC 6874, which permits query components in each
- * path component (i.e. between '/'-es). */
- for(char *urliter = url+1 ;; urliter++) {
- if( urliter - url >= url_max_length ) {
- picohttpStatus414RequestURITooLong(&request);
- return;
- }
- ch = picohttpIoGetch(ioops);
+static int16_t picohttpProcessURL (
+ struct picohttpRequest * const req,
+ size_t const url_max_length,
+ int16_t ch )
+{
+ /* copy url up to the first query component; note that this is not
+ * fully compliant to RFC 3986, which permits query components in each
+ * path component (i.e. between '/'-es).
+ * picohttp terminates the path once it encounters the first query
+ * component.
+ */
+ /* Deliberately discarding const qualifier! */
+ for(char *urliter = (char*)req->url ;; urliter++) {
if( ch < 0 ) {
- picohttpStatus500InternalServerError(&request);
- return;
+ return -500;
}
- if( '?' == (char)ch || ' ' == (char)ch ) {
+ if( '?' == ch ||
+ picohttpIsLWS(ch) ) {
break;
}
- if( '%' == (char)ch ) {
- ch = picohttpIoGetPercentCh(ioops);
+ if( '%' == ch ) {
+ ch = picohttpIoGetPercentCh(req->ioops);
+ if( ch < 0 ) {
+ return -500;
+ }
}
- if(ch < 0) {
- picohttpStatus500InternalServerError(&request);
- return;
+ if( !ch ) {
+ return -400;
}
- *urliter = (char)ch;
- }
+ if( urliter - req->url >= url_max_length ) {
+ return -414;
+ }
+ *urliter = ch;
- if( !picohttpMatchRoute(&request, routes) ) {
- picohttpStatus404NotFound(&request);
- return;
- }
- if( !(request.route->allowed_methods & request.method) ) {
- picohttpStatus405MethodNotAllowed(&request);
- return;
+ ch = picohttpIoGetch(req->ioops);
}
+ return ch;
+}
- if(request.route->get_vars) {
- for(size_t j = 0; request.route->get_vars[j].name; j++) {
+static int16_t picohttpProcessQuery (
+ struct picohttpRequest * const req,
+ int16_t ch )
+{
+ size_t var_max_length = 0;
+ if(req->route->get_vars) {
+ for(size_t j = 0; req->route->get_vars[j].name; j++) {
size_t var_length = strlen(
- request.route->get_vars[j].name );
+ req->route->get_vars[j].name );
if( var_length > var_max_length ) {
var_max_length = var_length;
}
}
}
- var = alloca(var_max_length+1);
+ char *var = alloca(var_max_length+1);
- while('?' == (char)ch || '&' ==(char)ch) {
+ while('?' == ch || '&' == ch) {
memset(var, 0, var_max_length+1);
- ch = picohttpIoGetch(ioops);
+ ch = picohttpIoGetch(req->ioops);
if( ch < 0 ) {
- picohttpStatus500InternalServerError(&request);
- return;
+ return -500;
}
-
- if( '&' == (char)ch )
+ if( '&' == ch )
continue;
- if( '%' == (char)ch ) {
- ch = picohttpIoGetPercentCh(ioops);
- }
- if(ch < 0) {
- picohttpStatus500InternalServerError(&request);
- return;
- }
- var[0] = ch;
- for(char *variter = var+1 ;; variter++) {
+ for(char *variter = var ;; variter++) {
+ if( ch < 0 ) {
+ return -500;
+ }
+ if( '=' == ch ||
+ '#' == ch ||
+ '&' == ch ||
+ picohttpIsLWS(ch) ) {
+ break;
+ }
+ if( '%' == ch ) {
+ ch = picohttpIoGetPercentCh(req->ioops);
+ if( ch < 0 ) {
+ return -500;
+ }
+ }
+ if( !ch ) {
+ return -400;
+ }
+
if( variter - var >= var_max_length ) {
- /* variable name longer than longest accepted
- * variable name --> skip to next variable */
+/* variable name in request longer than longest
+ * variable name accepted by route --> skip to next variable */
do {
- ch = picohttpIoGetch(ioops);
+ ch = picohttpIoGetch(req->ioops);
if( ch < 0 ) {
- picohttpStatus500InternalServerError(&request);
- return;
+ return -500;
}
- } while ( '&' != ch );
+ } while(!( '&' == ch ||
+ picohttpIsLWS(ch) ));
continue;
}
+ *variter = ch;
- ch = picohttpIoGetch(ioops);
- if( ch < 0 ) {
- picohttpStatus500InternalServerError(&request);
- return;
- }
+ ch = picohttpIoGetch(req->ioops);
}
+ if( '=' == ch ) {
+ } else {
+ }
+ }
+ if( 0 > (ch = picohttpIoSkipSpace(req->ioops, ch)) ) {
+ return -500;
}
- ch = picohttpIoSkipSpace(ioops);
+ return ch;
+}
+
+static int16_t picohttpProcessHTTPVersion (
+ struct picohttpRequest * const req,
+ int16_t ch )
+{
+ if( !picohttpIsCRLF(ch) ) {
+ for(uint8_t i = 0; i < 5; i++) {
+ if("HTTP/"[i] != (char)ch ) {
+ if( ch < 0 ) {
+ return -500;
+ }
+ return -400;
+ }
+ ch = picohttpIoGetch(req->ioops);
+ }
+
+ req->httpversion.major = 0;
+ req->httpversion.minor = 0;
+ ch = picohttpIoB10ToU8(
+ &req->httpversion.major,
+ req->ioops,
+ ch );
+ if( ch < 0 ) {
+ return -500;
+ }
+ if( ch != '.' ) {
+ return -400;
+ }
+ ch = picohttpIoB10ToU8(
+ &req->httpversion.minor,
+ req->ioops,
+ 0 );
+ if( ch < 0 ) {
+ return -500;
+ }
+
+ ch = picohttpIoSkipSpace(req->ioops, ch);
+ if( ch < 0 ) {
+ return -500;
+ }
+ }
+ ch = picohttpIoSkipOverCRLF(req->ioops, ch);
if( ch < 0 ) {
- picohttpStatus500InternalServerError(&request);
- return;
+ return -500;
}
- for(uint8_t i = 0; i < 4; i++) {
- if("HTTP"[i] != (char)(ch = picohttpIoGetch(ioops)) ) {
- if( ch < 0 ) {
- picohttpStatus500InternalServerError(&request);
- } else {
- picohttpStatus400BadRequest(&request);
+ if( !ch ) {
+ return -400;
+ }
+
+ return ch;
+}
+
+static int16_t picohttpProcessHeaders (
+ struct picohttpRequest * const req,
+ int16_t ch )
+{
+#define PICOHTTP_HEADERNAME_MAX_LEN 32
+ char headername[PICOHTTP_HEADERNAME_MAX_LEN] = {0,};
+
+ /* FIXME: Add Header handling here */
+ while( !picohttpIsCRLF(ch) ) {
+ fprintf(stderr, "\n>>> 0x%02x ", (int)ch, stderr);
+
+ while( !picohttpIsCRLF( ch=picohttpIoSkipSpace(req->ioops, ch)) ){
+ fputc(ch, stderr);
+ if( 0 > ( ch=picohttpIoGetch(req->ioops) ) ) {
+ return -500;
}
- return;
}
+
+ ch = picohttpIoSkipOverCRLF(req->ioops, ch);
+ if( 0 > ch ) {
+ return -500;
+ }
+ if( !ch ) {
+ return -400;
+ }
+ }
+ fputc('\n', stderr);
+ return ch;
+}
+
+void picohttpProcessRequest (
+ struct picohttpIoOps const * const ioops,
+ struct picohttpURLRoute const * const routes )
+{
+ char *url;
+ struct picohttpRequest request = {0,};
+ size_t url_max_length = 0;
+
+ for(size_t i = 0; routes[i].urlhead; i++) {
+ size_t url_length =
+ strlen(routes[i].urlhead) +
+ routes[i].max_urltail_len;
+
+ if(url_length > url_max_length)
+ url_max_length = url_length;
+
+ }
+ url = alloca(url_max_length+1);
+ memset(url, 0, url_max_length+1);
+
+ request.url = url;
+ request.urltail = 0;
+ request.ioops = ioops;
+ request.method = 0;
+ request.httpversion.major = 1;
+ request.httpversion.minor = 0;
+
+ request.method = picohttpProcessRequestMethod(ioops);
+ if( !request.method ) {
+ picohttpStatus501NotImplemented(&request);
+ return;
+ }
+ if( 0 > request.method ) {
+ picohttpStatus500InternalServerError(&request);
+ return;
}
- if( PICOHTTP_MAJORVERSION(request.httpversion) > 1 ||
- PICOHTTP_MINORVERSION(request.httpversion) > 1 ) {
+ int16_t ch;
+ if( 0 > (ch = picohttpIoSkipSpace(ioops, 0)) ) {
+ picohttpStatus500InternalServerError(&request);
+ return;
+ }
+
+ if( 0 > (ch = picohttpProcessURL(&request, url_max_length, ch)) )
+ goto http_error;
+
+ if( !picohttpMatchRoute(&request, routes) || !request.route ) {
+ picohttpStatus404NotFound(&request);
+ return;
+ }
+ if( !(request.route->allowed_methods & request.method) ) {
+ picohttpStatus405MethodNotAllowed(&request);
+ return;
+ }
+
+ if( 0 > (ch = picohttpProcessQuery(&request, ch)) )
+ goto http_error;
+
+ if( 0 > (ch = picohttpProcessHTTPVersion (&request, ch)) )
+ goto http_error;
+
+ if( request.httpversion.major > 1 ||
+ request.httpversion.minor > 1 ) {
picohttpStatus505HTTPVersionNotSupported(&request);
return;
}
+ if( 0 > (ch = picohttpProcessHeaders(&request, ch)) )
+ goto http_error;
+
request.route->handler(&request);
+ return;
+
+http_error:
+ switch(-ch) {
+ case 400: picohttpStatus400BadRequest(&request); break;
+ case 404: picohttpStatus404NotFound(&request); break;
+ case 405: picohttpStatus405MethodNotAllowed(&request); break;
+ case 500: picohttpStatus500InternalServerError(&request); break;
+ }
}
+
diff --git a/picohttp.h b/picohttp.h
index cceee44..9df3596 100644
--- a/picohttp.h
+++ b/picohttp.h
@@ -14,7 +14,7 @@
struct picohttpIoOps {
int (*read)(size_t /*count*/, char* /*buf*/, void*);
- int (*write)(size_t /*count*/, char* /*buf*/, void*);
+ int (*write)(size_t /*count*/, char const* /*buf*/, void*);
int16_t (*getch)(void*); // returns -1 on error
int (*putch)(char, void*);
void *data;
@@ -52,24 +52,41 @@ struct picohttpVar {
struct picohttpRequest;
-typedef void (*picohttpHandler) (struct picohttpRequest *ctx);
+typedef void (*picohttpHandler)(struct picohttpRequest*);
struct picohttpURLRoute {
char const * urlhead;
struct picohttpVarSpec const * get_vars;
picohttpHandler handler;
uint16_t max_urltail_len;
- uint8_t allowed_methods;
+ int16_t allowed_methods;
};
struct picohttpRequest {
struct picohttpIoOps const * ioops;
- struct picohttpURLRoute *route;
+ struct picohttpURLRoute const * route;
struct picohttpVar *get_vars;
char const *url;
char const *urltail;
- int16_t httpversion;
- uint8_t method;
+ int16_t status;
+ int16_t method;
+ struct {
+ uint8_t major;
+ uint8_t minor;
+ } httpversion;
+ struct {
+ uint8_t encoding;
+ char const *contenttype;
+ size_t contentlength;
+ } queryheader;
+ struct {
+ uint8_t encoding;
+ char const *contenttype;
+ char const *date;
+ char const *cachecontrol;
+ char const *disposition;
+ size_t contentlength;
+ } responseheader;
};
void picohttpProcessRequest(
diff --git a/test/bsd_socket.c b/test/bsd_socket.c
index e03f882..d4bd5a2 100644
--- a/test/bsd_socket.c
+++ b/test/bsd_socket.c
@@ -5,6 +5,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
+#include <string.h>
#include <unistd.h>
@@ -40,7 +41,7 @@ int bsdsock_read(size_t count, char *buf, void *data)
return rb;
}
-int bsdsock_write(size_t count, char *buf, void *data)
+int bsdsock_write(size_t count, char const *buf, void *data)
{
int fd = *((int*)data);
@@ -92,6 +93,33 @@ void bye(void)
close(sockfd);
}
+void rhRoot(struct picohttpRequest *req)
+{
+ fprintf(stderr, "handling request /%s\n", req->urltail);
+
+ char http_header[] = "HTTP/x.x 200 OK\r\nServer: picoweb\r\nContent-Type: text/html\r\n\r\n";
+ http_header[5] = '0'+req->httpversion.major;
+ http_header[7] = '0'+req->httpversion.minor;
+ picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header);
+ char http_test[] = "<html><head><title>handling request /</title></head>\n<body><a href=\"/test\">/test</a></body></html>\n";
+
+ picohttpIoWrite(req->ioops, sizeof(http_test)-1, http_test);
+}
+
+void rhTest(struct picohttpRequest *req)
+{
+ fprintf(stderr, "handling request /test%s\n", req->urltail);
+ char http_header[] = "HTTP/x.x 200 OK\r\nServer: picoweb\r\nContent-Type: text/text\r\n\r\n";
+ http_header[5] = '0'+req->httpversion.major;
+ http_header[7] = '0'+req->httpversion.minor;
+ picohttpIoWrite(req->ioops, sizeof(http_header)-1, http_header);
+ char http_test[] = "handling request /test";
+ picohttpIoWrite(req->ioops, sizeof(http_test)-1, http_test);
+ if(req->urltail) {
+ picohttpIoWrite(req->ioops, strlen(req->urltail), req->urltail);
+ }
+}
+
int main(int argc, char *argv[])
{
sockfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -99,9 +127,11 @@ int main(int argc, char *argv[])
perror("socket");
return -1;
}
+#if 0
if( atexit(bye) ) {
return -1;
}
+#endif
struct sockaddr_in addr = {
.sin_family = AF_INET,
@@ -109,6 +139,8 @@ int main(int argc, char *argv[])
.sin_addr = 0
};
+ int const one = 1;
+ setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if( -1 == bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) ) {
perror("bind");
return -1;
@@ -141,11 +173,18 @@ int main(int argc, char *argv[])
.data = &confd
};
- char const hellostr[] = "Hello World!\n";
- write(confd, hellostr, sizeof(hellostr));
+ struct picohttpURLRoute routes[] = {
+ { "/test", 0, rhTest, 16, PICOHTTP_METHOD_GET },
+ { "/|", 0, rhRoot, 0, PICOHTTP_METHOD_GET },
+ { NULL, 0, 0, 0, 0 }
+ };
+
+ picohttpProcessRequest(&ioops, routes);
+
shutdown(confd, SHUT_RDWR);
close(confd);
}
return 0;
}
+