From 0aee63f61eee251e56a1426d2721e1dac0180fab Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 4 Jan 2015 09:09:52 +0000 Subject: [PATCH] working on https --- src/apps/relay/http_server.c | 205 +++++++++++++++++++++++++ src/apps/relay/http_server.h | 27 +++- src/apps/relay/ns_ioalib_engine_impl.c | 4 +- src/apps/relay/turn_admin_server.c | 8 +- src/client/ns_turn_msg.c | 4 +- src/server/ns_turn_server.c | 4 +- 6 files changed, 242 insertions(+), 10 deletions(-) diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 8e08e4d2..6bcbeabb 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -30,6 +30,26 @@ #include "ns_ioalib_impl.h" +#include "http_server.h" + +#include +#include + +////////////////////////////////////// + +struct headers_list { + size_t n; + char **keys; + char **values; +}; + +struct http_headers { + struct evkeyvalq *uri_headers; + struct headers_list *post_headers; +}; + +////////////////////////////////////// + static void write_http_echo(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { @@ -54,3 +74,188 @@ static void write_http_echo(ioa_socket_handle s) void handle_http_echo(ioa_socket_handle s) { write_http_echo(s); } + +/////////////////////////////////////////////// + +static struct headers_list * post_parse(char *data, size_t data_len) +{ + char *post_data = calloc(data_len + 1, sizeof(char)); + memcpy(post_data, data, data_len); + char *fmarker = NULL; + char *fsplit = strtok_r(post_data, "&", &fmarker); + struct headers_list *list = (struct headers_list*)malloc(sizeof(struct headers_list)); + ns_bzero(list,sizeof(struct headers_list)); + while (fsplit != NULL) { + char *vmarker = NULL; + char *key = strtok_r(fsplit, "=", &vmarker); + char *value = strtok_r(NULL, "=", &vmarker); + value = value ? value : ""; + value = evhttp_decode_uri(value); + char *p = value; + while (*p != '\0') { + if (*p == '+') + *p = ' '; + p++; + } + list->keys = (char**)realloc(list->keys,sizeof(char*)*(list->n+1)); + list->keys[list->n] = strdup(key); + list->values = (char**)realloc(list->values,sizeof(char*)*(list->n+1)); + list->values[list->n] = value; + ++(list->n); + fsplit = strtok_r(NULL, "&", &fmarker); + } + free(post_data); + return list; +} + +static struct http_request* parse_http_request_1(struct http_request* ret, char* request, int parse_post) +{ + if(ret && request) { + + char* s = strstr(request," HTTP/"); + if(!s) { + free(ret); + ret = NULL; + } else { + *s = 0; + + struct evhttp_uri *uri = evhttp_uri_parse(request); + if(!uri) { + free(ret); + ret = NULL; + } else { + + const char *query = evhttp_uri_get_query(uri); + if(query) { + struct evkeyvalq* kv = (struct evkeyvalq*)malloc(sizeof(struct evkeyvalq)); + ns_bzero(kv,sizeof(struct evkeyvalq)); + if(evhttp_parse_query_str(query, kv)<0) { + free(ret); + ret = NULL; + } else { + ret->headers = (struct http_headers*)malloc(sizeof(struct http_headers)); + ns_bzero(ret->headers,sizeof(struct http_headers)); + ret->headers->uri_headers = kv; + } + } + evhttp_uri_free(uri); + + if(parse_post) { + char *body = strstr(s+1,"\r\n\r\n"); + if(body && body[0]) { + if(!ret->headers) { + ret->headers = (struct http_headers*)malloc(sizeof(struct http_headers)); + ns_bzero(ret->headers,sizeof(struct http_headers)); + } + ret->headers->post_headers = post_parse(body,strlen(body)); + } + } + } + + *s = ' '; + } + } + + return ret; +} + +struct http_request* parse_http_request(char* request) { + + struct http_request* ret = NULL; + + if(request) { + + ret = (struct http_request*)malloc(sizeof(struct http_request)); + ns_bzero(ret,sizeof(struct http_request)); + + if(strstr(request,"GET ") == request) { + ret->rtype = HRT_GET; + ret = parse_http_request_1(ret,request+4,0); + } else if(strstr(request,"POST ") == request) { + ret->rtype = HRT_POST; + ret = parse_http_request_1(ret,request+5,1); + } else { + free(ret); + ret = NULL; + } + } + + return ret; +} + +static const char * get_headers_list_value(struct headers_list *h, const char* key) { + const char* ret = NULL; + if(h && h->keys && h->values && key && key[0]) { + size_t i = 0; + for(i=0;in;++i) { + if(h->keys[i] && !strcmp(key,h->keys[i]) && h->values[i]) { + ret = h->values[i]; + break; + } + } + } + return ret; +} + +static void free_headers_list(struct headers_list *h) { + if(h) { + if(h->keys) { + size_t i = 0; + for(i=0;in;++i) { + if(h->keys[i]) { + free(h->keys[i]); + h->keys[i]=NULL; + } + } + free(h->keys); + h->keys = NULL; + } + if(h->values) { + size_t i = 0; + for(i=0;in;++i) { + if(h->values[i]) { + free(h->values[i]); + h->values[i]=NULL; + } + } + free(h->values); + h->values = NULL; + } + h->n = 0; + free(h); + } +} + +const char *get_http_header_value(const struct http_request *request, const char* key) { + const char *ret = NULL; + if(key && key[0] && request && request->headers) { + if(request->headers->uri_headers) { + ret = evhttp_find_header(request->headers->uri_headers,key); + } + if(!ret && request->headers->post_headers) { + ret = get_headers_list_value(request->headers->post_headers,key); + } + } + return ret; +} + +void free_http_request(struct http_request *request) { + if(request) { + if(request->headers) { + if(request->headers->uri_headers) { + evhttp_clear_headers(request->headers->uri_headers); + free(request->headers->uri_headers); + request->headers->uri_headers = NULL; + } + if(request->headers->post_headers) { + free_headers_list(request->headers->post_headers); + request->headers->post_headers = NULL; + } + free(request->headers); + request->headers = NULL; + } + free(request); + } +} + +/////////////////////////////////////////////// diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index 0bfb7714..20aeba19 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -31,17 +31,38 @@ #ifndef __TURN_HTTP_SERVER__ #define __TURN_HTTP_SERVER__ -#include -#include - #include "ns_turn_utils.h" #include "ns_turn_server.h" #include "apputils.h" +#include +#include + #ifdef __cplusplus extern "C" { #endif +///////// HTTP REQUEST ////////// + +enum _HTTP_REQUEST_TYPE { + HRT_UNKNOWN=0, + HRT_GET, + HRT_POST +}; + +typedef enum _HTTP_REQUEST_TYPE HTTP_REQUEST_TYPE; + +struct http_headers; + +struct http_request { + HTTP_REQUEST_TYPE rtype; + struct http_headers *headers; +}; + +struct http_request* parse_http_request(char* request); +const char *get_http_header_value(const struct http_request *request, const char* key); +void free_http_request(struct http_request *request); + //////////////////////////////////////////// void handle_http_echo(ioa_socket_handle s); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 1d9111ca..bbf5279f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2601,7 +2601,7 @@ void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s) if (s && ioa_socket_tobeclosed(s)) { if(!(s->session) && !(s->sub_session)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s https server socket closed: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, get_ioa_socket_type(s), get_ioa_socket_type(s)); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s https server socket closed: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, get_ioa_socket_type(s), get_ioa_socket_app_type(s)); IOA_CLOSE_SOCKET(s); return; } @@ -2782,7 +2782,7 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) if(!(s->session) && !(s->sub_session)) { char sraddr[129]="\0"; addr_to_string(&(s->remote_addr),(u08bits*)sraddr); - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s https server socket closed: 0x%lx, st=%d, sat=%d, remote addr=%s\n", __FUNCTION__,(long)s, get_ioa_socket_type(s), get_ioa_socket_type(s),sraddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s https server socket closed: 0x%lx, st=%d, sat=%d, remote addr=%s\n", __FUNCTION__,(long)s, get_ioa_socket_type(s), get_ioa_socket_app_type(s),sraddr); IOA_CLOSE_SOCKET(s); return; } diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index fb5d32a5..735d0ea5 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1390,7 +1390,13 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { handle_http_echo(s); } else { if(nbh) { - //TODO + struct http_request* hr = parse_http_request((char*)ioa_network_buffer_data(nbh)); + if(!hr) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); + } else { + //TODO + free_http_request(hr); + } } write_https_default_page(s); } diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 7f7c1172..02b2f442 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -646,9 +646,9 @@ static inline const char* findstr(const char *hay, size_t slen, const char *need static inline int is_http_get_inline(const char *s, size_t blen) { if(s && blen>=12) { if((s[0]=='G')&&(s[1]=='E')&&(s[2]=='T')&&(s[3]==' ')) { - const char *sp=findstr(s+4,blen-4,"HTTP"); + const char *sp=findstr(s+4,blen-4," HTTP/"); if(sp) { - sp += 4; + sp += 6; size_t diff_blen = sp-s; if(diff_blen+4 <= blen) { sp=findstr(sp,blen-diff_blen,"\r\n\r\n"); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 1e8316db..3e75e8cf 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4545,10 +4545,10 @@ static int read_client_connection(turn_turnserver *server, set_ioa_socket_app_type(ss->client_socket,HTTPS_CLIENT_SOCKET); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) request: %s\n", __FUNCTION__, proto, get_ioa_socket_cipher(ss->client_socket), get_ioa_socket_ssl_method(ss->client_socket), (char*)ioa_network_buffer_data(in_buffer->nbh)); if(server->send_https_socket) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s socket to be detached: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)ss->client_socket, get_ioa_socket_type(ss->client_socket), get_ioa_socket_type(ss->client_socket)); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s socket to be detached: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)ss->client_socket, get_ioa_socket_type(ss->client_socket), get_ioa_socket_app_type(ss->client_socket)); ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket); if(new_s) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s new detached socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)new_s, get_ioa_socket_type(new_s), get_ioa_socket_type(new_s)); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s new detached socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)new_s, get_ioa_socket_type(new_s), get_ioa_socket_app_type(new_s)); server->send_https_socket(new_s); } ss->to_be_closed = 1;