From 50f37f145651fea130fcc96ef305ab4cf18dd25e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sat, 3 Nov 2007 06:34:53 +0000 Subject: [PATCH] add callbacks for a virtual http server --- http.c | 99 +++++++++++++++++++++++++++++++++++++--------------------- http.h | 17 ++++++++++ 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/http.c b/http.c index f18ff9a6..87fe94d1 100644 --- a/http.c +++ b/http.c @@ -44,6 +44,8 @@ #include "http.h" #include "rtsp.h" +static LIST_HEAD(, http_path) http_paths; + static struct strtab HTTP_cmdtab[] = { { "GET", HTTP_CMD_GET }, { "DESCRIBE", RTSP_CMD_DESCRIBE }, @@ -64,6 +66,33 @@ static struct strtab HTTP_versiontab[] = { }; +/** + * + */ +static http_path_t * +http_resolve(http_connection_t *hc, char **remainp) +{ + http_path_t *hp; + char *v; + LIST_FOREACH(hp, &http_paths, hp_link) { + if(!strncmp(hc->hc_url, hp->hp_path, hp->hp_len)) + break; + } + + if(hp == NULL) + return NULL; + + v = hc->hc_url + hp->hp_len; + + if(*v != 0 && *v != '/') + return NULL; + + *remainp = v; + return hp; +} + + + /* * HTTP status code to string */ @@ -107,7 +136,7 @@ http_output_reply_header(http_connection_t *hc, int rc) /** * Send HTTP error back */ -static void +void http_error(http_connection_t *hc, int error) { char ret[300]; @@ -126,6 +155,9 @@ http_error(http_connection_t *hc, int error) error, errtxt); if(hc->hc_version >= HTTP_VERSION_1_0) { + if(error == HTTP_STATUS_UNAUTHORIZED) + http_printf(hc, "WWW-Authenticate: Basic realm=\"tvheadend\"\r\n"); + http_printf(hc, "Content-Type: text/html\r\n"); http_printf(hc, "Content-Length: %d\r\n", strlen(ret)); http_printf(hc, "\r\n"); @@ -133,46 +165,25 @@ http_error(http_connection_t *hc, int error) http_printf(hc, "%s", ret); } -#if 0 -/** - * Send HTTP unauthorized back, and ask for authentication - */ -static void -http_unauthorized(http_connection_t *hc) -{ - char ret[300]; - const char *errtxt = http_rc2str(HTTP_STATUS_UNAUTHORIZED); - - http_output_reply_header(hc, HTTP_STATUS_UNAUTHORIZED); - - snprintf(ret, sizeof(ret), - "\r\n" - "\r\n" - "%d %s\r\n" - "\r\n" - "

%d %s

\r\n" - "\r\n", - HTTP_STATUS_UNAUTHORIZED, errtxt, - HTTP_STATUS_UNAUTHORIZED, errtxt); - - if(hc->hc_version >= HTTP_VERSION_1_0) { - http_printf(hc, "WWW-Authenticate: Basic realm=\"tvheadend\"\r\n"); - http_printf(hc, "Content-Type: text/html\r\n"); - http_printf(hc, "Content-Length: %d\r\n", strlen(ret)); - http_printf(hc, "\r\n"); - } - http_printf(hc, "%s", ret); -} -#endif - - /** * HTTP GET */ static void http_cmd_get(http_connection_t *hc) { - http_error(hc, HTTP_STATUS_NOT_FOUND); + http_path_t *hp; + char *remain; + int err; + + hp = http_resolve(hc, &remain); + if(hp == NULL) { + http_error(hc, HTTP_STATUS_NOT_FOUND); + return; + } + + err = hp->hp_callback(hc, remain, hp->hp_opaque); + if(err) + http_error(hc, err); } @@ -469,3 +480,21 @@ http_tokenize(char *buf, char **vec, int vecsize, int delimiter) } return n; } + + +/** + * Add a callback for a given "virtual path" on our HTTP server + */ +http_path_t * +http_path_add(const char *path, void *opaque, http_callback_t *callback) +{ + http_path_t *hp = malloc(sizeof(http_path_t)); + + hp->hp_len = strlen(path); + hp->hp_path = strdup(path); + hp->hp_opaque = opaque; + hp->hp_callback = callback; + LIST_INSERT_HEAD(&http_paths, hp, hp_link); + return hp; +} + diff --git a/http.h b/http.h index add001cd..8f580e0c 100644 --- a/http.h +++ b/http.h @@ -83,4 +83,21 @@ void http_arg_set(struct http_arg_list *list, char *key, char *val); int http_tokenize(char *buf, char **vec, int vecsize, int delimiter); +void http_error(http_connection_t *hc, int error); + + +typedef int (http_callback_t)(http_connection_t *hc, const char *remain, + void *opaque); + +typedef struct http_path { + LIST_ENTRY(http_path) hp_link; + const char *hp_path; + void *hp_opaque; + http_callback_t *hp_callback; + int hp_len; +} http_path_t; + +http_path_t *http_path_add(const char *path, void *opaque, + http_callback_t *callback); + #endif /* HTTP_H_ */