diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 6bcbeabb..b8c990e0 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -138,6 +138,11 @@ static struct http_request* parse_http_request_1(struct http_request* ret, char* ret->headers->uri_headers = kv; } } + + const char *path = evhttp_uri_get_path(uri); + if(path) + ret->path = strdup(path); + evhttp_uri_free(uri); if(parse_post) { @@ -174,6 +179,12 @@ struct http_request* parse_http_request(char* request) { } else if(strstr(request,"POST ") == request) { ret->rtype = HRT_POST; ret = parse_http_request_1(ret,request+5,1); + } else if(strstr(request,"PUT ") == request) { + ret->rtype = HRT_PUT; + ret = parse_http_request_1(ret,request+4,1); + } else if(strstr(request,"DELETE ") == request) { + ret->rtype = HRT_DELETE; + ret = parse_http_request_1(ret,request+7,1); } else { free(ret); ret = NULL; @@ -241,6 +252,10 @@ const char *get_http_header_value(const struct http_request *request, const char void free_http_request(struct http_request *request) { if(request) { + if(request->path) { + free(request->path); + request->path = NULL; + } if(request->headers) { if(request->headers->uri_headers) { evhttp_clear_headers(request->headers->uri_headers); @@ -258,4 +273,66 @@ void free_http_request(struct http_request *request) { } } +//////////////////////////////////////////// + +struct str_buffer { + size_t capacity; + size_t sz; + char* buffer; +}; + +struct str_buffer* str_buffer_new(void) +{ + struct str_buffer* ret = (struct str_buffer*)malloc(sizeof(struct str_buffer)); + ns_bzero(ret,sizeof(struct str_buffer)); + ret->buffer = (char*)malloc(1); + ret->buffer[0] = 0; + ret->capacity = 1; + return ret; +} + +void str_buffer_append(struct str_buffer* sb, const char* str) +{ + if(sb && str && str[0]) { + size_t len = strlen(str); + while(sb->sz + len + 1 > sb->capacity) { + sb->capacity += len + 1024; + sb->buffer = (char*)realloc(sb->buffer,sb->capacity); + } + ns_bcopy(str,sb->buffer+sb->sz,len+1); + sb->sz += len; + } +} + +void str_buffer_append_sz(struct str_buffer* sb, size_t sz) +{ + char ssz[129]; + snprintf(ssz,sizeof(ssz)-1,"%lu",(unsigned long)sz); + str_buffer_append(sb,ssz); +} + +const char* str_buffer_get_str(const struct str_buffer *sb) +{ + if(sb) { + return sb->buffer; + } + return NULL; +} + +size_t str_buffer_get_str_len(const struct str_buffer *sb) +{ + if(sb) { + return sb->sz; + } + return 0; +} + +void str_buffer_free(struct str_buffer *sb) +{ + if(sb) { + free(sb->buffer); + free(sb); + } +} + /////////////////////////////////////////////// diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index 20aeba19..ef400326 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -47,7 +47,9 @@ extern "C" { enum _HTTP_REQUEST_TYPE { HRT_UNKNOWN=0, HRT_GET, - HRT_POST + HRT_POST, + HRT_PUT, + HRT_DELETE }; typedef enum _HTTP_REQUEST_TYPE HTTP_REQUEST_TYPE; @@ -56,6 +58,7 @@ struct http_headers; struct http_request { HTTP_REQUEST_TYPE rtype; + char *path; struct http_headers *headers; }; @@ -65,6 +68,17 @@ void free_http_request(struct http_request *request); //////////////////////////////////////////// +struct str_buffer; + +struct str_buffer* str_buffer_new(void); +void str_buffer_append(struct str_buffer* sb, const char* str); +void str_buffer_append_sz(struct str_buffer* sb, size_t sz); +const char* str_buffer_get_str(const struct str_buffer *sb); +size_t str_buffer_get_str_len(const struct str_buffer *sb); +void str_buffer_free(struct str_buffer *sb); + +//////////////////////////////////////////// + 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 bbf5279f..233306a8 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -3191,6 +3191,51 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, return ret; } +int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t sz) +{ + int ret = -1; + + if(s && data) { + + if (s->done || (s->fd == -1) || ioa_socket_tobeclosed(s) || !(s->e)) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_INFO, + "!!! %s: (1) Trying to send data from bad socket: 0x%lx (1): done=%d, fd=%d, st=%d, sat=%d\n", + __FUNCTION__, (long) s, (int) s->done, + (int) s->fd, s->st, s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + + } else if (s->connected && s->bev) { + if (s->st == TLS_SOCKET) { +#if TLS_SUPPORTED + SSL *ctx = bufferevent_openssl_get_ssl(s->bev); + if (!ctx || SSL_get_shutdown(ctx)) { + s->tobeclosed = 1; + ret = 0; + } +#endif + } + + if (!(s->tobeclosed)) { + + ret = (int)sz; + + s->in_write = 1; + if (bufferevent_write(s->bev, data, sz) < 0) { + ret = -1; + perror("bufev send"); + log_socket_event(s, "socket write failed, to be closed", 1); + s->tobeclosed = 1; + s->broken = 1; + } + s->in_write = 0; + } + } + } + + return ret; +} + int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, int event_type, ioa_net_event_handler cb, void* ctx, int clean_preexisting) { if(s) { diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 277724df..4bc505e4 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -66,6 +66,8 @@ extern "C" { #define MAX_BUFFER_QUEUE_SIZE_PER_ENGINE (64) #define MAX_SOCKET_BUFFER_BACKLOG (16) +#define ADMIN_USER_MAX_LENGTH (32) + #define BUFFEREVENT_HIGH_WATERMARK (128<<10) #define BUFFEREVENT_MAX_UDP_TO_TCP_WRITE (64<<9) #define BUFFEREVENT_MAX_TCP_TO_TCP_WRITE (192<<10) @@ -225,7 +227,7 @@ struct _ioa_socket /* <<== RFC 6062 */ //Admin server: int as_ok; - char as_login[17]; + char as_login[ADMIN_USER_MAX_LENGTH + 1]; char as_realm[STUN_MAX_REALM_SIZE + 1]; }; @@ -301,6 +303,8 @@ int set_socket_options(ioa_socket_handle s); int send_session_cancellation_to_relay(turnsession_id sid); +int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t sz); + ///////////////////////// SUPER MEMORY //////// #define allocate_super_memory_engine(e,size) allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 7976994f..c8c7a336 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1249,7 +1249,7 @@ void setup_cli_thread(void) cliserver.https_in_buf = pair[0]; cliserver.https_out_buf = pair[1]; - bufferevent_setcb(cliserver.https_in_buf, https_cli_server_receive_message, NULL, NULL, &cliserver); + bufferevent_setcb(cliserver.https_in_buf, https_admin_server_receive_message, NULL, NULL, &cliserver); bufferevent_enable(cliserver.https_in_buf, EV_READ); } @@ -1360,19 +1360,35 @@ int send_turn_session_info(struct turn_session_info* tsi) static void write_https_logon_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { - //TODO - ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); - size_t len_http = ioa_network_buffer_get_size(nbh_http); - u08bits *data = ioa_network_buffer_data(nbh_http); - char data_http[1025]; - char content_http[1025]; - const char* title = "HTTPS TURN Server"; - snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\r\n",title,title); - snprintf(data_http,sizeof(data_http)-1,"HTTP/1.1 200 OK\r\nServer: %s\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: %d\r\n\r\n%s",TURN_SOFTWARE,(int)strlen(content_http),content_http); - len_http = strlen(data_http); - ns_bcopy(data_http,data,len_http); - ioa_network_buffer_set_size(nbh_http,len_http); - send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + + struct str_buffer* sb = str_buffer_new(); + + const char* title = "TURN Server (https admin connection)"; + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Admin user information: user name:

password:


\r\n"); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n \r\n\r\n"); + + struct str_buffer* sb_http = str_buffer_new(); + + str_buffer_append(sb_http,"HTTP/1.1 200 OK\r\nServer: "); + str_buffer_append(sb_http,TURN_SOFTWARE); + str_buffer_append(sb_http,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + str_buffer_append_sz(sb_http,str_buffer_get_str_len(sb)); + str_buffer_append(sb_http,"\r\n\r\n"); + str_buffer_append(sb_http,str_buffer_get_str(sb)); + + str_buffer_free(sb); + + send_data_from_ioa_socket_tcp(s, str_buffer_get_str(sb_http), str_buffer_get_str_len(sb_http)); + + str_buffer_free(sb_http); } } @@ -1393,6 +1409,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); } else { //TODO + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS request, path %s\n", __FUNCTION__,hr->path); write_https_logon_page(s); s->as_ok = 1; free_http_request(hr); @@ -1400,6 +1417,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { } } else { write_https_logon_page(s); + s->as_ok = 1; } } @@ -1416,7 +1434,7 @@ static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_dat data->nbh = NULL; } -void https_cli_server_receive_message(struct bufferevent *bev, void *ptr) +void https_admin_server_receive_message(struct bufferevent *bev, void *ptr) { UNUSED_ARG(ptr); diff --git a/src/apps/relay/turn_admin_server.h b/src/apps/relay/turn_admin_server.h index 05c8d262..37c63298 100644 --- a/src/apps/relay/turn_admin_server.h +++ b/src/apps/relay/turn_admin_server.h @@ -89,7 +89,7 @@ extern int cli_max_output_sessions; void setup_cli_thread(void); void cli_server_receive_message(struct bufferevent *bev, void *ptr); -void https_cli_server_receive_message(struct bufferevent *bev, void *ptr); +void https_admin_server_receive_message(struct bufferevent *bev, void *ptr); int send_turn_session_info(struct turn_session_info* tsi); void send_https_socket(ioa_socket_handle s); diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 02b2f442..1f2c1be4 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -611,17 +611,22 @@ int stun_is_channel_message_str(const u08bits *buf, size_t *blen, u16bits* chnum ////////// STUN message /////////////////////////////// -static inline int sheadof(const char *head, const char* full) +static inline int sheadof(const char *head, const char* full, int ignore_case) { while(*head) { - if(*head != *full) - return 0; + if(*head != *full) { + if(ignore_case && (tolower(*head)==tolower(*full))) { + //OK + } else { + return 0; + } + } ++head;++full; } return 1; } -static inline const char* findstr(const char *hay, size_t slen, const char *needle) +static inline const char* findstr(const char *hay, size_t slen, const char *needle, int ignore_case) { const char *ret = NULL; @@ -632,7 +637,7 @@ static inline const char* findstr(const char *hay, size_t slen, const char *need size_t i; const char *sp = hay; for(i=0;i=12) { - if((s[0]=='G')&&(s[1]=='E')&&(s[2]=='T')&&(s[3]==' ')) { - const char *sp=findstr(s+4,blen-4," HTTP/"); + if((strstr(s,"GET ")==s) ||(strstr(s,"POST ")==s) || (strstr(s,"DELETE ")==s) || (strstr(s,"PUT ")==s)) { + const char *sp=findstr(s+4,blen-4," HTTP/",0); if(sp) { sp += 6; size_t diff_blen = sp-s; if(diff_blen+4 <= blen) { - sp=findstr(sp,blen-diff_blen,"\r\n\r\n"); + sp=findstr(sp,blen-diff_blen,"\r\n\r\n",0); if(sp) { - return (int)(sp-s+4); + int ret_len = (int)(sp-s+4); + const char* clheader = "content-length: "; + const char* cl = findstr(s,sp-s,clheader,1); + if(cl) { + unsigned long clen = strtoul(cl+strlen(clheader),NULL,10); + if(clen>0 && clen<(0x0FFFFFFF)) { + ret_len += (int)clen; + } + } + return ret_len; } } } - } } return 0; } -int is_http_get(const char *s, size_t blen) { - return is_http_get_inline(s, blen); +int is_http(const char *s, size_t blen) { + return is_http_inline(s, blen); } int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app_len) { @@ -690,7 +703,7 @@ int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app //HTTP request ? { - int http_len = is_http_get_inline(((char*)buf), blen); + int http_len = is_http_inline(((char*)buf), blen); if((http_len>0) && ((size_t)http_len<=blen)) { *app_len = (size_t)http_len; return http_len; diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 52bdfadd..88d2e3d2 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -207,7 +207,7 @@ int stun_attr_get_padding_len_str(stun_attr_ref attr); int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len); /* HTTP */ -int is_http_get(const char *s, size_t blen); +int is_http(const char *s, size_t blen); /* OAUTH */ int convert_oauth_key_data(const oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 3e75e8cf..cf660f59 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4538,7 +4538,7 @@ static int read_client_connection(turn_turnserver *server, } else { SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); if((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)) { - if(is_http_get((char*)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) { + if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) { const char *proto = "HTTP"; if(st==TLS_SOCKET) { proto = "HTTPS";