From 123f23c43846dd83ccad024635d86d27e0a24cac Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 31 May 2015 23:17:50 +0100 Subject: [PATCH] Added http daemon --- .gitignore | 1 + Makefile.am | 1 + configure.ac | 3 + runstabber.c | 13 ++--- src/client/stabber.c | 4 +- src/server/httpapi.c | 129 +++++++++++++++++++++++++++++++++++++++++++ src/server/httpapi.h | 2 + src/server/server.c | 23 +++++++- src/server/server.h | 2 +- stabber.h | 2 +- stabbertest.c | 2 +- 11 files changed, 167 insertions(+), 15 deletions(-) create mode 100644 src/server/httpapi.c create mode 100644 src/server/httpapi.h diff --git a/.gitignore b/.gitignore index 54c2f34..1b4d938 100644 --- a/.gitignore +++ b/.gitignore @@ -42,5 +42,6 @@ config.cache configure.lineno src/server/prime.lo src/server/verify.lo +src/server/httpapi.lo stabbertest diff --git a/Makefile.am b/Makefile.am index 587fe7f..70d8dea 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,7 @@ lib_LTLIBRARIES = libstabber.la sources = \ src/server/server.c src/server/server.h \ + src/server/httpapi.c src/server/httpapi.h \ src/server/xmppclient.c src/server/xmppclient.h \ src/server/parser.c src/server/parser.h \ src/server/stanza.c src/server/stanza.h \ diff --git a/configure.ac b/configure.ac index ae0a5e3..4d0ff20 100644 --- a/configure.ac +++ b/configure.ac @@ -22,6 +22,9 @@ PKG_CHECK_MODULES([expat], [expat >= 2.0.0], [], AC_CHECK_LIB([pthread], [main], [], [AC_MSG_ERROR([pthread is required])]) +AC_CHECK_LIB([microhttpd], [main], [], + [AC_MSG_ERROR([microhttpd is required])]) + AM_CFLAGS="-Wall -Wno-deprecated-declarations" AM_CFLAGS="$AM_CFLAGS -Wunused -Werror" AM_CPPFLAGS="$AM_CPPFLAGS $glib_CFLAGS $expat_CFLAGS" diff --git a/runstabber.c b/runstabber.c index 856ab45..4a7268b 100644 --- a/runstabber.c +++ b/runstabber.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -7,10 +8,12 @@ int main(int argc , char *argv[]) { int port = 0; + int httpport = 0; GOptionEntry entries[] = { { "port", 'p', 0, G_OPTION_ARG_INT, &port, "Listen port", NULL }, + { "http", 'h', 0, G_OPTION_ARG_INT, &httpport, "HTTP Listen port", NULL }, { NULL } }; @@ -29,15 +32,11 @@ main(int argc , char *argv[]) g_option_context_free(context); if (port == 0) { - port = 5230; + printf("Port must be specified with -p \n"); + return 1; } - - if (argc == 2) { - port = atoi(argv[1]); - } - - stbbr_start(port); + stbbr_start(port, httpport); pthread_exit(0); } diff --git a/src/client/stabber.c b/src/client/stabber.c index 7d0f73b..daceda9 100644 --- a/src/client/stabber.c +++ b/src/client/stabber.c @@ -11,9 +11,9 @@ typedef struct server_args_t { } StabberArgs; int -stbbr_start(int port) +stbbr_start(int port, int httpport) { - return server_run(port); + return server_run(port, httpport); } void diff --git a/src/server/httpapi.c b/src/server/httpapi.c new file mode 100644 index 0000000..544fbb2 --- /dev/null +++ b/src/server/httpapi.c @@ -0,0 +1,129 @@ +#include +#include +#include + +#include +#include + +#include "server/log.h" +#include "server/server.h" + +struct MHD_Daemon *httpdaemmon = NULL; + +#define POSTBUFFERSIZE 2048 + +typedef struct conn_info_t { + GString *body; +} ConnectionInfo; + +ConnectionInfo* +create_connection_info(void) +{ + ConnectionInfo *con_info = malloc(sizeof(ConnectionInfo)); + con_info->body = g_string_new(""); + + return con_info; +} + +void +destroy_connection_info(ConnectionInfo *con_info) +{ + if (con_info->body) { + g_string_free(con_info->body, TRUE); + con_info->body = NULL; + } + free(con_info); +} + +int +send_response(struct MHD_Connection* conn, const char* body, int status_code) +{ + struct MHD_Response* response; + if (body) { + response = MHD_create_response_from_data(strlen(body), (void*)body, MHD_NO, MHD_YES); + } else { + response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_YES); + } + + if (!response) + return MHD_NO; + + int ret = MHD_queue_response(conn, status_code, response); + MHD_destroy_response(response); + return ret; +} + +int connection_cb(void* cls, struct MHD_Connection* conn, const char* url, const char* method, + const char* version, const char* data, size_t* size, void** con_cls) +{ + if (*con_cls == NULL) { + ConnectionInfo *con_info = create_connection_info(); + + if (g_strcmp0(method, "POST") == 0 && g_strcmp0(url, "/send") == 0) { + if (*size != 0) { + g_string_append_len(con_info->body, data, *size); + *size = 0; + } + } else { + return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); + } + + *con_cls = (void*) con_info; + + return MHD_YES; + } + + ConnectionInfo *con_info = (ConnectionInfo*) *con_cls; + + if (*size != 0) { + g_string_append_len(con_info->body, data, *size); + *size = 0; + + return MHD_YES; + } else { + server_send(con_info->body->str); + + return send_response(conn, NULL, MHD_HTTP_OK); + } +} + +void request_completed(void* cls, struct MHD_Connection* conn, + void** con_cls, enum MHD_RequestTerminationCode termcode) +{ + ConnectionInfo *con_info = (ConnectionInfo*) *con_cls; + if (con_info) { + destroy_connection_info(con_info); + } + con_info = NULL; + *con_cls = NULL; +} + +int +httpapi_start(int port) +{ + httpdaemmon = MHD_start_daemon( + MHD_USE_SELECT_INTERNALLY, + port, + NULL, + NULL, + &connection_cb, + NULL, + MHD_OPTION_NOTIFY_COMPLETED, + request_completed, + NULL, MHD_OPTION_END); + + if (!httpdaemmon) { + return 0; + } + + log_println("HTTP daemon started on port: %d", port); + + return 1; +} + +void +httpapi_stop(void) +{ + MHD_stop_daemon(httpdaemmon); + log_println("HTTP daemon stopped."); +} diff --git a/src/server/httpapi.h b/src/server/httpapi.h new file mode 100644 index 0000000..cc4c289 --- /dev/null +++ b/src/server/httpapi.h @@ -0,0 +1,2 @@ +int httpapi_start(int port); +void httpapi_stop(void); diff --git a/src/server/server.c b/src/server/server.c index 77204fe..5752093 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -12,6 +12,7 @@ #include "server/stanza.h" #include "server/verify.h" #include "server/server.h" +#include "server/httpapi.h" #include "server/log.h" #define XML_START "" @@ -34,6 +35,7 @@ static void _shutdown(void); static int listen_socket; static pthread_t server_thread; static gboolean kill_recv = FALSE; +static gboolean httpapi_run = FALSE; void write_stream(const char * const stream) @@ -122,8 +124,6 @@ read_stream(void) log_println("RECV: "); log_println("--> Stream end callback fired"); write_stream(STREAM_END); - log_println(""); - log_println(""); _shutdown(); return 0; } @@ -250,7 +250,7 @@ _start_server_cb(void* userdata) } int -server_run(int port) +server_run(int port, int httpport) { pthread_mutex_lock(&send_queue_lock); send_queue = NULL; @@ -314,6 +314,16 @@ server_run(int port) return -1; } + // start http server + if (httpport > 0) { + res = httpapi_start(httpport); + if (!res) { + _shutdown(); + return -1; + } + httpapi_run = TRUE; + } + return 0; } @@ -337,6 +347,11 @@ _shutdown(void) { log_println("SHUTDOWN"); // stanza_show_all(); + + if (httpapi_run) { + httpapi_stop(); + } + xmppclient_end_session(client); client = NULL; @@ -354,5 +369,7 @@ _shutdown(void) send_queue = NULL; pthread_mutex_unlock(&send_queue_lock); + log_println(""); + log_println(""); log_close(); } diff --git a/src/server/server.h b/src/server/server.h index 72c1e60..fe06623 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -1,7 +1,7 @@ #ifndef __H_SERVER #define __H_SERVER -int server_run(int port); +int server_run(int port, int httpport); void server_stop(void); void server_wait_for(char *id); diff --git a/stabber.h b/stabber.h index bf45bf4..aaf669a 100644 --- a/stabber.h +++ b/stabber.h @@ -1,7 +1,7 @@ #ifndef __H_STABBER #define __H_STABBER -int stbbr_start(int port); +int stbbr_start(int port, int httpport); void stbbr_stop(void); void stbbr_set_timeout(int seconds); diff --git a/stabbertest.c b/stabbertest.c index 5716f74..e74020d 100644 --- a/stabbertest.c +++ b/stabbertest.c @@ -4,7 +4,7 @@ int main(void) { - stbbr_start(5230); + stbbr_start(5230, 5231); stbbr_auth_passwd("password");