diff --git a/server/core/buffer.c b/server/core/buffer.c index 4d28793fc..d3278a505 100644 --- a/server/core/buffer.c +++ b/server/core/buffer.c @@ -32,7 +32,6 @@ * 11/07/13 Mark Riddoch Add reference count mechanism * 16/07/2013 Massimiliano Pinto Added command type to gwbuf struct * 24/06/2014 Mark Riddoch Addition of gwbuf_trim - * 15/07/2014 Mark Riddoch Addition of properties * * @endverbatim */ @@ -78,13 +77,11 @@ SHARED_BUF *sbuf; free(sbuf); return NULL; } - spinlock_init(&rval->lock); rval->start = sbuf->data; rval->end = rval->start + size; sbuf->refcount = 1; rval->sbuf = sbuf; rval->next = NULL; - rval->properties = NULL; rval->gwbuf_type = GWBUF_TYPE_UNDEFINED; rval->command = 0; CHK_GWBUF(rval); @@ -99,22 +96,12 @@ SHARED_BUF *sbuf; void gwbuf_free(GWBUF *buf) { -BUF_PROPERTY *prop; - CHK_GWBUF(buf); if (atomic_add(&buf->sbuf->refcount, -1) == 1) { free(buf->sbuf->data); free(buf->sbuf); } - while (buf->properties) - { - prop = buf->properties; - buf->properties = prop->next; - free(prop->name); - free(prop->value); - free(prop); - } free(buf); } @@ -350,79 +337,4 @@ void gwbuf_set_type( } -/** - * Add a property to a buffer. - * - * @param buf The buffer to add the property to - * @param name The property name - * @param value The property value - * @return Non-zero on success - */ -int -gwbuf_add_property(GWBUF *buf, char *name, char *value) -{ -BUF_PROPERTY *prop; - if ((prop = malloc(sizeof(BUF_PROPERTY))) == NULL) - return 0; - - prop->name = strdup(name); - prop->value = strdup(value); - spinlock_acquire(&buf->lock); - prop->next = buf->properties; - buf->properties = prop; - spinlock_release(&buf->lock); - return 1; -} - -/** - * Return the value of a buffer property - * @param buf The buffer itself - * @param name The name of the property to return - * @return The property value or NULL if the property was not found. - */ -char * -gwbuf_get_property(GWBUF *buf, char *name) -{ -BUF_PROPERTY *prop; - - spinlock_acquire(&buf->lock); - prop = buf->properties; - while (prop && strcmp(prop->name, name) != 0) - prop = prop->next; - spinlock_release(&buf->lock); - if (prop) - return prop->value; - return NULL; -} - - -/** - * Convert a chain of GWBUF structures into a single GWBUF structure - * - * @param orig The chain to convert - * @return The contiguous buffer - */ -GWBUF * -gwbuf_make_contiguous(GWBUF *orig) -{ -GWBUF *newbuf; -char *ptr; -int len; - - if (orig->next == NULL) - return orig; - - if ((newbuf = gwbuf_alloc(gwbuf_length(orig))) != NULL) - { - ptr = GWBUF_DATA(newbuf); - while (orig) - { - len = GWBUF_LENGTH(orig); - memcpy(ptr, GWBUF_DATA(orig), len); - ptr += len; - orig = gwbuf_consume(orig, len); - } - } - return newbuf; -} diff --git a/server/core/monitor.c b/server/core/monitor.c index 8bb62bc2d..d7b53f5b7 100644 --- a/server/core/monitor.c +++ b/server/core/monitor.c @@ -312,28 +312,3 @@ monitorSetReplicationHeartbeat(MONITOR *mon, int replication_heartbeat) mon->module->replicationHeartbeat(mon->handle, replication_heartbeat); } } - -/** - * Iterate over the monitors, calling a function per call - * - * @param fcn The function to call - * @param data The data to pass to each call - */ -void -monitorIterate(void (*fcn)(MONITOR *, void *), void *data) -{ -MONITOR *monitor, *next; - - spinlock_acquire(&monLock); - monitor = allMonitors; - while (monitor) - { - next = monitor->next; - spinlock_release(&monLock); - (*fcn)(monitor, data); - spinlock_acquire(&monLock); - monitor = next; - } - spinlock_release(&monLock); - -} diff --git a/server/core/server.c b/server/core/server.c index cb3090679..bfe5e4d04 100644 --- a/server/core/server.c +++ b/server/core/server.c @@ -561,28 +561,3 @@ SERVER_PARAM *param = server->parameters; } return NULL; } - -/** - * Iterate over the servers, calling a function per call - * - * @param fcn The function to call - * @param data The data to pass to each call - */ -void -serverIterate(void (*fcn)(SERVER *, void *), void *data) -{ -SERVER *server, *next; - - spinlock_acquire(&server_spin); - server = allServers; - while (server) - { - next = server->next; - spinlock_release(&server_spin); - (*fcn)(server, data); - spinlock_acquire(&server_spin); - server = next; - } - spinlock_release(&server_spin); - -} diff --git a/server/core/service.c b/server/core/service.c index 592d90321..1102dabb4 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -1171,28 +1171,3 @@ serviceGetWeightingParameter(SERVICE *service) { return service->weightby; } - -/** - * Iterate over the services, calling a function per call - * - * @param fcn The function to call - * @param data The data to pass to each call - */ -void -serviceIterate(void (*fcn)(SERVICE *, void *), void *data) -{ -SERVICE *service, *next; - - spinlock_acquire(&service_spin); - service = allServices; - while (service) - { - next = service->next; - spinlock_release(&service_spin); - (*fcn)(service, data); - spinlock_acquire(&service_spin); - service = next; - } - spinlock_release(&service_spin); - -} diff --git a/server/core/session.c b/server/core/session.c index 9f1a55615..80767f9ff 100644 --- a/server/core/session.c +++ b/server/core/session.c @@ -756,28 +756,3 @@ session_getUser(SESSION *session) { return (session && session->client) ? session->client->user : NULL; } - -/** - * Iterate over the sessions, calling a function per call - * - * @param fcn The function to call - * @param data The data to pass to each call - */ -void -sessionIterate(void (*fcn)(SESSION *, void *), void *data) -{ -SESSION *session, *next; - - spinlock_acquire(&session_spin); - session = allSessions; - while (session) - { - next = session->next; - spinlock_release(&session_spin); - (*fcn)(session, data); - spinlock_acquire(&session_spin); - session = next; - } - spinlock_release(&session_spin); - -} diff --git a/server/include/buffer.h b/server/include/buffer.h index cf2f9e8dd..9729c538c 100644 --- a/server/include/buffer.h +++ b/server/include/buffer.h @@ -38,25 +38,12 @@ * 10/06/2013 Mark Riddoch Initial implementation * 11/07/2013 Mark Riddoch Addition of reference count in the gwbuf * 16/07/2013 Massimiliano Pinto Added command type for the queue - * 15/07/2014 Mark Riddoch Added buffer properties * * @endverbatim */ -#include #include -/** - * Buffer properties - used to store properties related to the buffer - * contents. This may be added at any point during the processing of the - * data, especially in the protocol stage of the processing. - */ -typedef struct buf_property { - char *name; - char *value; - struct buf_property *next; -} BUF_PROPERTY; - typedef enum { GWBUF_TYPE_UNDEFINED = 0x00, @@ -65,8 +52,7 @@ typedef enum GWBUF_TYPE_SINGLE_STMT = 0x04, GWBUF_TYPE_SESCMD_RESPONSE = 0x08, GWBUF_TYPE_RESPONSE_END = 0x10, - GWBUF_TYPE_SESCMD = 0x20, - GWBUF_TYPE_HTTP = 0x40 + GWBUF_TYPE_SESCMD = 0x20 } gwbuf_type_t; #define GWBUF_IS_TYPE_UNDEFINED(b) (b->gwbuf_type == 0) @@ -102,8 +88,6 @@ typedef struct gwbuf { SHARED_BUF *sbuf; /*< The shared buffer with the real data */ int command;/*< The command type for the queue */ gwbuf_type_t gwbuf_type; /*< buffer's data type information */ - SPINLOCK lock; - BUF_PROPERTY *properties; /*< Buffer properties */ } GWBUF; /*< @@ -137,7 +121,4 @@ extern unsigned int gwbuf_length(GWBUF *head); extern GWBUF *gwbuf_clone_portion(GWBUF *head, size_t offset, size_t len); extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type); extern void gwbuf_set_type(GWBUF *head, gwbuf_type_t type); -extern int gwbuf_add_property(GWBUF *buf, char *name, char *value); -extern char *gwbuf_get_property(GWBUF *buf, char *name); -extern GWBUF *gwbuf_make_contiguous(GWBUF *); #endif diff --git a/server/include/monitor.h b/server/include/monitor.h index 4dee5f49c..d65fd075f 100644 --- a/server/include/monitor.h +++ b/server/include/monitor.h @@ -110,5 +110,4 @@ extern void monitorList(DCB *); extern void monitorSetId(MONITOR *, unsigned long); extern void monitorSetInterval (MONITOR *, unsigned long); extern void monitorSetReplicationHeartbeat(MONITOR *, int); -extern void monitorIterate(void (*fcn)(MONITOR *, void *), void *data); #endif diff --git a/server/include/server.h b/server/include/server.h index f622b5765..fdcc32e80 100644 --- a/server/include/server.h +++ b/server/include/server.h @@ -161,5 +161,4 @@ extern void serverAddParameter(SERVER *, char *, char *); extern char *serverGetParameter(SERVER *, char *); extern void server_update(SERVER *, char *, char *, char *); extern void server_set_unique_name(SERVER *, char *); -extern void serverIterate(void (*fcn)(SERVER *, void *), void *data); #endif diff --git a/server/include/service.h b/server/include/service.h index 0d8d32cda..cd13d411b 100644 --- a/server/include/service.h +++ b/server/include/service.h @@ -161,7 +161,6 @@ extern void serviceSetFilters(SERVICE *, char *); extern int serviceEnableRootUser(SERVICE *, int ); extern void serviceWeightBy(SERVICE *, char *); extern char *serviceGetWeightingParameter(SERVICE *); -extern void serviceIterate(void (*fcn)(SERVICE *, void *), void *data); extern void service_update(SERVICE *, char *, char *, char *); extern int service_refresh_users(SERVICE *); extern void printService(SERVICE *); diff --git a/server/include/session.h b/server/include/session.h index 0386a5eb6..cbd43fe40 100644 --- a/server/include/session.h +++ b/server/include/session.h @@ -157,7 +157,6 @@ void dprintAllSessions(struct dcb *); void dprintSession(struct dcb *, SESSION *); void dListSessions(struct dcb *); char *session_state(int); -void sessionIterate(void (*fcn)(SESSION *, void *), void *data); bool session_link_dcb(SESSION *, struct dcb *); SESSION* get_session_by_router_ses(void* rses); #endif diff --git a/server/modules/include/httpd.h b/server/modules/include/httpd.h index 920e65b2d..0d5e65604 100644 --- a/server/modules/include/httpd.h +++ b/server/modules/include/httpd.h @@ -48,20 +48,18 @@ #define HTTPD_FIELD_MAXLEN 8192 #define HTTPD_REQUESTLINE_MAXLEN 8192 -typedef enum { - METHOD_UNKNOWN = 0, - METHOD_POST, - METHOD_PUT, - METHOD_GET, - METHOD_HEAD -} HTTP_METHOD; /** * HTTPD session specific data * */ typedef struct httpd_session { - HTTP_METHOD method; - GWBUF *saved; - int request_len; - char *url; + char user[HTTPD_USER_MAXLEN]; /*< username for authentication*/ + char *cookies; /*< all input cookies */ + char hostname[HTTPD_HOSTNAME_MAXLEN]; /*< The hostname */ + char useragent[HTTPD_USERAGENT_MAXLEN]; /*< The useragent */ + char method[HTTPD_METHOD_MAXLEN]; /*< The HTTPD Method */ + char *url; /*< the URL in the request */ + char *path_info; /*< the Pathinfo, starts with /, is the extra path segments after the document name */ + char *query_string; /*< the Query string, starts with ?, after path_info and document name */ + int headers_received; /*< All the headers has been received, if 1 */ } HTTPD_session; diff --git a/server/modules/protocol/httpd.c b/server/modules/protocol/httpd.c index bdb06e560..7db1366ad 100644 --- a/server/modules/protocol/httpd.c +++ b/server/modules/protocol/httpd.c @@ -33,8 +33,6 @@ * Date Who Description * 08/07/2013 Massimiliano Pinto Initial version * 09/07/2013 Massimiliano Pinto Added /show?dcb|session for all dcbs|sessions - * 11/07/2014 Mark Riddoch Recoded as more generic protocol module - * removing hardcoded example * * @endverbatim */ @@ -42,10 +40,6 @@ #include #include #include -#include -#include - -extern int lm_enabled_logfiles_bitmask; MODULE_INFO info = { MODULE_API_PROTOCOL, @@ -54,6 +48,7 @@ MODULE_INFO info = { "An experimental HTTPD implementation for use in admnistration" }; +#define ISspace(x) isspace((int)(x)) #define HTTP_SERVER_STRING "Gateway(c) v.1.0.0" static char *version_str = "V1.0.1"; @@ -65,8 +60,8 @@ static int httpd_hangup(DCB *dcb); static int httpd_accept(DCB *dcb); static int httpd_close(DCB *dcb); static int httpd_listen(DCB *dcb, char *config); -static char *httpd_nextline(GWBUF *buf, char *ptr); -static void httpd_process_header(GWBUF *buf, char *sol, HTTPD_session *client_data); +static int httpd_get_line(int sock, char *buf, int size); +static void httpd_send_headers(DCB *dcb, int final); /** * The "module object" for the httpd protocol module. @@ -126,99 +121,132 @@ GetModuleObject() * @return */ static int -httpd_read_event(DCB *dcb) +httpd_read_event(DCB* dcb) { -SESSION *session = dcb->session; -GWBUF *buf = NULL; -char *ptr, *sol; -HTTPD_session *client_data = NULL; -int n; +//SESSION *session = dcb->session; +//ROUTER_OBJECT *router = session->service->router; +//ROUTER *router_instance = session->service->router_instance; +//void *rsession = session->router_session; - // Read all the available data - if ((n = dcb_read(dcb, &buf)) != -1) - { - client_data = dcb->data; +int numchars = 1; +char buf[HTTPD_REQUESTLINE_MAXLEN-1] = ""; +char *query_string = NULL; +char method[HTTPD_METHOD_MAXLEN-1] = ""; +char url[HTTPD_SMALL_BUFFER] = ""; +int cgi = 0; +size_t i, j; +int headers_read = 0; +HTTPD_session *client_data = NULL; - if (client_data->saved) - { - buf = gwbuf_append(client_data->saved, buf); - client_data->saved = NULL; - } - buf = gwbuf_make_contiguous(buf); - - ptr = GWBUF_DATA(buf); - - if (strncasecmp(ptr, "POST", 4)) - { - client_data->method = METHOD_POST; - gwbuf_add_property(buf, "Method", "POST"); - ptr = ptr + 4; - } - else if (strncasecmp(ptr, "PUT", 3)) - { - client_data->method = METHOD_PUT; - gwbuf_add_property(buf, "Method", "PUT"); - ptr = ptr + 3; - } - else if (strncasecmp(ptr, "GET", 3)) - { - client_data->method = METHOD_GET; - gwbuf_add_property(buf, "Method", "GET"); - ptr = ptr + 3; - } - else if (strncasecmp(ptr, "HEAD", 4)) - { - client_data->method = METHOD_HEAD; - gwbuf_add_property(buf, "Method", "HEAD"); - ptr = ptr + 4; - } - while (ptr < (char *)(buf->end) && isspace(*ptr)) - ptr++; - sol = ptr; - while (ptr < (char *)(buf->end) && isspace(*ptr) == 0) - ptr++; - client_data->url = strndup(sol, ptr - sol); - gwbuf_add_property(buf, "URL", client_data->url); - while ((sol = httpd_nextline(buf, ptr)) != NULL && - *sol != '\n' && *sol != '\r') - { - httpd_process_header(buf, sol, client_data); - ptr = sol; - } - - /* - * We have read all the headers, or run out of data to - * examine. - */ - if (sol == NULL) - { - client_data->saved = buf; - return 0; - } - else - { - if (((char *)(buf->end) - sol) - < client_data->request_len) - { - client_data->saved = buf; - } - else - { - LOGIF(LT, (skygw_log_write( - LOGFILE_TRACE, - "HTTPD: request %s.\n", client_data->url))); - SESSION_ROUTE_QUERY(session, buf); - if (client_data->url) - { - free(client_data->url); - client_data->url = NULL; - } - } - } + client_data = dcb->data; + /** + * get the request line + * METHOD URL HTTP_VER\r\n + */ + numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); + i = 0; j = 0; + while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { + method[i] = buf[j]; + i++; j++; } + method[i] = '\0'; + + strcpy(client_data->method, method); + + /* check allowed http methods */ + if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { + //httpd_unimplemented(dcb->fd); + return 0; + } + + if (strcasecmp(method, "POST") == 0) + cgi = 1; + + i = 0; + + while (ISspace(buf[j]) && (j < sizeof(buf))) { + j++; + } + + while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { + url[i] = buf[j]; + i++; j++; + } + + url[i] = '\0'; + + /** + * Get the query string if availble + */ + + if (strcasecmp(method, "GET") == 0) { + query_string = url; + while ((*query_string != '?') && (*query_string != '\0')) + query_string++; + if (*query_string == '?') { + cgi = 1; + *query_string = '\0'; + query_string++; + } + } + + /** + * Get the request headers + */ + + while ((numchars > 0) && strcmp("\n", buf)) { + char *value = NULL; + char *end = NULL; + numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); + if ( (value = strchr(buf, ':'))) { + *value = '\0'; + value++; + end = &value[strlen(value) -1]; + *end = '\0'; + + if (strncasecmp(buf, "Hostname", 6) == 0) { + strcpy(client_data->hostname, value); + } + if (strncasecmp(buf, "useragent", 9) == 0) { + strcpy(client_data->useragent, value); + } + } + } + + if (numchars) { + headers_read = 1; + memcpy(&client_data->headers_received, &headers_read, sizeof(int)); + } + + /** + * Now begins the server reply + */ + + /* send all the basic headers and close with \r\n */ + httpd_send_headers(dcb, 1); + + /** + * ToDO: launch proper content handling based on the requested URI, later REST interface + * + */ + + dcb_printf(dcb, "Welcome to HTTPD Gateway (c) %s\n\n", version_str); + + if (strcmp(url, "/show") == 0) { + if (strlen(query_string)) { + if (strcmp(query_string, "dcb") == 0) + dprintAllDCBs(dcb); + if (strcmp(query_string, "session") == 0) + dprintAllSessions(dcb); + } + } + + /* force the client connecton close */ + dcb_close(dcb); + return 0; } @@ -259,18 +287,6 @@ httpd_write(DCB *dcb, GWBUF *queue) static int httpd_error(DCB *dcb) { -HTTPD_session *client_data = NULL; - if (dcb->data) - { - client_data = dcb->data; - if (client_data->url) - { - free(client_data->url); - client_data->url = NULL; - } - free(dcb->data); - dcb->data = NULL; - } dcb_close(dcb); return 0; } @@ -302,7 +318,7 @@ int n_connect = 0; { int so = -1; struct sockaddr_in addr; - socklen_t addrlen = 0; + socklen_t addrlen; DCB *client = NULL; HTTPD_session *client_data = NULL; @@ -317,11 +333,10 @@ int n_connect = 0; memcpy(&client->func, &MyObject, sizeof(GWPROTOCOL)); /* we don't need the session */ - client->session = session_alloc(dcb->session->service, client); + client->session = NULL; /* create the session data for HTTPD */ client_data = (HTTPD_session *)calloc(1, sizeof(HTTPD_session)); - memset(client_data, 0, sizeof(HTTPD_session)); client->data = client_data; if (poll_add_dcb(client) == -1) @@ -410,84 +425,51 @@ int rc; } /** - * Return the start of the next line int the buffer. - * - * @param buf The GWBUF chain - * @param ptr Start point within the buffer - * - * @return the start of the next line or NULL if there are no more lines + * HTTPD get line from client */ -static char * -httpd_nextline(GWBUF *buf, char *ptr) -{ - while (ptr < (char *)(buf->end) && *ptr != '\n' && *ptr != '\r') - ptr++; - if (ptr >= (char *)(buf->end)) - return NULL; +static int httpd_get_line(int sock, char *buf, int size) { + int i = 0; + char c = '\0'; + int n; - /* Skip prcisely one CR/LF */ - if (*ptr == '\r') - ptr++; - if (*ptr == '\n') - ptr++; - return ptr; -} - -/** - * The headers to extract from the HTTP request and add as properties to the - * GWBUF structure. - */ -static char *headers[] = { - "Content-Type", - "User-Agent", - "From", - "Date", - NULL -}; - -/** - * Process a single header line - * - * @param buf The GWBUF that contains the request - * @param sol The current start of line - * @param client_data The client data structure for this request - */ -static void -httpd_process_header(GWBUF *buf, char *sol, HTTPD_session *client_data) -{ -char *ptr = sol; -char cbuf[300]; -int len, i; - - /* Find the end of the line */ - while (ptr < (char *)(buf->end) && *ptr != '\n' && *ptr != '\r') - ptr++; - - if (strncmp(sol, "Content-Length:", strlen("Content-Length:")) == 0) - { - char *p1 = sol + strlen("Content-Length:"); - while (isspace(*p1)) - p1++; - len = ptr - p1; - strncpy(cbuf, p1, len); - cbuf[len] = 0; - client_data->request_len = atoi(cbuf); - gwbuf_add_property(buf, "Content-Length", cbuf); - } - else - { - for (i = 0; headers[i]; i++) - { - if (strncmp(sol, headers[i], strlen(headers[i])) == 0) - { - char *p1 = sol + strlen(headers[i]) + 1; - while (isspace(*p1)) - p1++; - len = ptr - p1; - strncpy(cbuf, p1, len); - cbuf[len] = 0; - gwbuf_add_property(buf, headers[i], cbuf); + while ((i < size - 1) && (c != '\n')) { + n = recv(sock, &c, 1, 0); + /* DEBUG printf("%02X\n", c); */ + if (n > 0) { + if (c == '\r') { + n = recv(sock, &c, 1, MSG_PEEK); + /* DEBUG printf("%02X\n", c); */ + if ((n > 0) && (c == '\n')) + recv(sock, &c, 1, 0); + else + c = '\n'; } - } + buf[i] = c; + i++; + } else + c = '\n'; + } + + buf[i] = '\0'; + + return i; +} + +/** + * HTTPD send basic headers with 200 OK + */ +static void httpd_send_headers(DCB *dcb, int final) +{ + char date[64] = ""; + const char *fmt = "%a, %d %b %Y %H:%M:%S GMT"; + time_t httpd_current_time = time(NULL); + + strftime(date, sizeof(date), fmt, localtime(&httpd_current_time)); + + dcb_printf(dcb, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s\r\nConnection: close\r\nContent-Type: text/plain\r\n", date, HTTP_SERVER_STRING); + + /* close the headers */ + if (final) { + dcb_printf(dcb, "\r\n"); } } diff --git a/server/modules/routing/Makefile b/server/modules/routing/Makefile index a1095304c..4feac68fb 100644 --- a/server/modules/routing/Makefile +++ b/server/modules/routing/Makefile @@ -44,13 +44,10 @@ DEBUGCLISRCS=debugcli.c debugcmd.c DEBUGCLIOBJ=$(DEBUGCLISRCS:.c=.o) CLISRCS=cli.c debugcmd.c CLIOBJ=$(CLISRCS:.c=.o) -WEBSRCS=webserver.o -WEBOBJ=$(WEBSRCS:.c=.o) SRCS=$(TESTSRCS) $(READCONSRCS) $(DEBUGCLISRCS) cli.c OBJ=$(SRCS:.c=.o) LIBS=$(UTILSPATH)/skygw_utils.o -lssl -llog_manager -MODULES= libdebugcli.so libreadconnroute.so libtestroute.so libcli.so \ - libwebserver.so +MODULES= libdebugcli.so libreadconnroute.so libtestroute.so libcli.so all: $(MODULES) @@ -67,9 +64,6 @@ libdebugcli.so: $(DEBUGCLIOBJ) libcli.so: $(CLIOBJ) $(CC) $(LDFLAGS) $(CLIOBJ) $(LIBS) -o $@ -libwebserver.so: $(WEBOBJ) - $(CC) $(LDFLAGS) $(WEBOBJ) $(LIBS) -o $@ - libreadwritesplit.so: # (cd readwritesplit; touch depend.mk ; make; cp $@ ..) diff --git a/server/modules/routing/webserver.c b/server/modules/routing/webserver.c deleted file mode 100644 index ee8516108..000000000 --- a/server/modules/routing/webserver.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * This file is distributed as part of MaxScale. It is free - * software: you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation, - * version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright SkySQL Ab 2014 - */ -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - SERVICE *service; -} WEB_INSTANCE; - -typedef struct { - SESSION *session; -} WEB_SESSION; - -static char *version_str = "V1.0.0"; - -MODULE_INFO info = { - MODULE_API_ROUTER, - MODULE_IN_DEVELOPMENT, - ROUTER_VERSION, - "A test router - not for use in real systems" -}; - -static ROUTER *createInstance(SERVICE *service, char **options); -static void *newSession(ROUTER *instance, SESSION *session); -static void closeSession(ROUTER *instance, void *session); -static void freeSession(ROUTER *instance, void *session); -static int routeQuery(ROUTER *instance, void *session, GWBUF *queue); -static void diagnostic(ROUTER *instance, DCB *dcb); -static uint8_t getCapabilities (ROUTER* inst, void* router_session); - - -static ROUTER_OBJECT MyObject = { - createInstance, - newSession, - closeSession, - freeSession, - routeQuery, - diagnostic, - NULL, - NULL, - getCapabilities -}; - - -static void send_index(WEB_SESSION *); -static void send_css(WEB_SESSION *); -static void send_menu(WEB_SESSION *); -static void send_blank(WEB_SESSION *); -static void send_title(WEB_SESSION *); -static void send_frame1(WEB_SESSION *); -static void send_services(WEB_SESSION *); -static void send_sessions(WEB_SESSION *); -static void send_servers(WEB_SESSION *); -static void send_monitors(WEB_SESSION *); -static void respond_error(WEB_SESSION *, int, char *); - -static struct { - char *page; - void (*fcn)(WEB_SESSION *); -} pages[] = { - { "index.html", send_index }, - { "services.html", send_services }, - { "menu.html", send_menu }, - { "sessions.html", send_sessions }, - { "blank.html", send_blank }, - { "title.html", send_title }, - { "frame1.html", send_frame1 }, - { "servers.html", send_servers }, - { "monitors.html", send_monitors }, - { "styles.css", send_css }, - { NULL, NULL } -}; - -/** - * Implementation of the mandatory version entry point - * - * @return version string of the module - */ -char * -version() -{ - return version_str; -} - -/** - * The module initialisation routine, called when the module - * is first loaded. - */ -void -ModuleInit() -{ - -} - -/** - * The module entry point routine. It is this routine that - * must populate the structure that is referred to as the - * "module object", this is a structure with the set of - * external entry points for this module. - * - * @return The module object - */ -ROUTER_OBJECT * -GetModuleObject() -{ - return &MyObject; -} - -/** - * Create an instance of the router for a particular service - * within the gateway. - * - * @param service The service this router is being create for - * @param options The options for this query router - * - * @return The instance data for this new instance - */ -static ROUTER * -createInstance(SERVICE *service, char **options) -{ -WEB_INSTANCE *inst; - - if ((inst = (WEB_INSTANCE *)malloc(sizeof(WEB_INSTANCE))) == NULL) - return NULL; - - inst->service = service; - return (ROUTER *)inst; -} - -/** - * Associate a new session with this instance of the router. - * - * @param instance The router instance data - * @param session The session itself - * @return Session specific data for this session - */ -static void * -newSession(ROUTER *instance, SESSION *session) -{ -WEB_SESSION *wsession; - - if ((wsession = (WEB_SESSION *)malloc(sizeof(WEB_SESSION))) == NULL) - return NULL; - - wsession->session = session; - return wsession; -} - -/** - * Close a session with the router, this is the mechanism - * by which a router may cleanup data structure etc. - * - * @param instance The router instance data - * @param session The session being closed - */ -static void -closeSession(ROUTER *instance, void *session) -{ - free(session); -} - -static void freeSession( - ROUTER* router_instance, - void* router_client_session) -{ - return; -} - -static int -routeQuery(ROUTER *instance, void *session, GWBUF *queue) -{ -WEB_SESSION *wsession = (WEB_SESSION *)session; -char *ptr; -int i, found = 0; -char *url; - - if ((url = gwbuf_get_property(queue, "URL")) == NULL) - { - respond_error(wsession, 404, "No URL available"); - } - - ptr = strrchr(url, '/'); - if (ptr) - ptr++; - else - ptr = url; - for (i = 0; pages[i].page; i++) - { - if (!strcmp(ptr, pages[i].page)) - { - (pages[i].fcn)(wsession); - found = 1; - } - } - if (!found) - respond_error(wsession, 404, "Unrecognised URL received"); - gwbuf_free(queue); - return 0; -} - -/** - * Diagnostics routine - * - * @param instance The router instance - * @param dcb The DCB for diagnostic output - */ -static void -diagnostic(ROUTER *instance, DCB *dcb) -{ -} - -/** - * Return the router capabilities bitmask - * - * @param inst The router instance - * @param router_session The router session - * @return Router capabilities bitmask - */ -static uint8_t -getCapabilities(ROUTER *inst, void *router_session) -{ - return 0; -} - -static char *index_page = -"" -"" -"MaxScale" -"" -"" -"" -"" -"" -""; - -static char *title_page = -"" -"" -"MaxScale" -"" -"

MaxScale - Status View

" -""; - -static char *frame1_page = -"" -"" -"" -"" -"" -""; - -static char *menu_page = -"" -"" -"" -"

Options

" -"

"; - -static char *blank_page = " "; - -static char *css = -"table, td, th { border: 1px solid blue; }\n" -"th { background-color: blue; color: white; padding: 5px }\n" -"td { padding: 5px; }\n" -"table { border-collapse: collapse; }\n" -"a:link { color: #0000FF; }\n" -"a:visted { color: #0000FF; }\n" -"a:hover { color: #FF0000; }\n" -"a:active { color: #0000FF; }\n" -"h1 { color: blue; font-family: serif }\n" -"h2 { color: blue; font-family: serif }\n" -"p { font-family: serif }\n" -"li { font-family: serif }\n"; - - -static void -send_html_header(DCB *dcb) -{ -char date[64] = ""; -const char *fmt = "%a, %d %b %Y %H:%M:%S GMT"; - - time_t httpd_current_time = time(NULL); - - strftime(date, sizeof(date), fmt, localtime(&httpd_current_time)); - - dcb_printf(dcb, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s\r\nConnection: close\r\nContent-Type: text/html\r\n", date, "MaxScale"); - - dcb_printf(dcb, "\r\n"); -} - -static void -send_static_html(DCB *dcb, char *html) -{ - dcb_printf(dcb, html); -} - -static void -send_index(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - send_static_html(dcb, index_page); - dcb_close(dcb); -} - -static void -send_css(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - send_static_html(dcb, css); - dcb_close(dcb); -} - -static void -send_title(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - send_static_html(dcb, title_page); - dcb_close(dcb); -} - -static void -send_frame1(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - send_static_html(dcb, frame1_page); - dcb_close(dcb); -} - -static void -send_menu(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - send_static_html(dcb, menu_page); - dcb_close(dcb); -} - -static void -send_blank(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - send_static_html(dcb, blank_page); - dcb_close(dcb); -} - -static void -service_row(SERVICE *service, DCB *dcb) -{ - dcb_printf(dcb, "%s%s%d%d\n", - service->name, service->routerModule, - service->stats.n_current, service->stats.n_sessions); -} - -static void -send_services(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - dcb_printf(dcb, ""); - dcb_printf(dcb, ""); - dcb_printf(dcb, "

Services

"); - dcb_printf(dcb, "\n"); - serviceIterate(service_row, dcb); - dcb_printf(dcb, "
NameRouter"); - dcb_printf(dcb, "Current SessionsTotal Sessions
\n"); - dcb_close(dcb); -} - -static void -session_row(SESSION *session, DCB *dcb) -{ - dcb_printf(dcb, "%-16p%s%s%s\n", - session, ((session->client && session->client->remote) - ? session->client->remote : ""), - (session->service && session->service->name - ? session->service->name : ""), - session_state(session->state)); -} - -static void -send_sessions(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - dcb_printf(dcb, ""); - dcb_printf(dcb, ""); - dcb_printf(dcb, "

Sessions

"); - dcb_printf(dcb, "\n"); - sessionIterate(session_row, dcb); - dcb_printf(dcb, "
SessionClient"); - dcb_printf(dcb, "ServiceState
\n"); - dcb_close(dcb); -} - -static void -server_row(SERVER *server, DCB *dcb) -{ - dcb_printf(dcb, "%s%s%d%s%d\n", - server->unique_name, server->name, server->port, - server_status(server), server->stats.n_current); -} - -static void -send_servers(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - dcb_printf(dcb, ""); - dcb_printf(dcb, ""); - dcb_printf(dcb, "

Servers

"); - dcb_printf(dcb, "\n"); - serverIterate(server_row, dcb); - dcb_printf(dcb, "
ServerAddress"); - dcb_printf(dcb, "PortStateConnections
\n"); - dcb_close(dcb); -} - -static void -monitor_row(MONITOR *monitor, DCB *dcb) -{ - dcb_printf(dcb, "%s%s\n", - monitor->name, monitor->state & MONITOR_STATE_RUNNING - ? "Running" : "Stopped"); -} - -static void -send_monitors(WEB_SESSION *session) -{ -DCB *dcb = session->session->client; - - send_html_header(dcb); - dcb_printf(dcb, ""); - dcb_printf(dcb, ""); - dcb_printf(dcb, "

Monitors

"); - dcb_printf(dcb, "\n"); - monitorIterate(monitor_row, dcb); - dcb_printf(dcb, "
MonitorState
\n"); - dcb_close(dcb); -} - -static void -respond_error(WEB_SESSION *session, int err, char *msg) -{ -DCB *dcb = session->session->client; - - dcb_printf(dcb, "HTTP/1.1 %d %s\n", err, msg); - dcb_printf(dcb, "Content-Type: text/html\n"); - dcb_printf(dcb, "\n"); - dcb_printf(dcb, "\n"); - dcb_printf(dcb, "MaxScale webserver plugin unable to satisfy request.\n"); - dcb_printf(dcb, "

Code: %d, %s\n", err, msg); - dcb_printf(dcb, ""); - dcb_close(dcb); -}