Browse Source

working on https

mom040267 11 years ago
parent
commit
bd8c39c3b7

+ 77 - 0
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);
+	}
+}
+
 ///////////////////////////////////////////////

+ 15 - 1
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);
 
 ////////////////////////////////////////////

+ 45 - 0
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) {

+ 5 - 1
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__)

+ 33 - 15
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,"<!DOCTYPE html>\r\n<html>\r\n  <head>\r\n    <title>%s</title>\r\n  </head>\r\n  <body>\r\n    %s\r\n  </body>\r\n</html>\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,"<!DOCTYPE html>\r\n<html>\r\n  <head>\r\n    <title>");
+		str_buffer_append(sb,title);
+		str_buffer_append(sb,"</title>\r\n  </head>\r\n  <body>\r\n    ");
+		str_buffer_append(sb,title);
+		str_buffer_append(sb,"<br>\r\n");
+		str_buffer_append(sb,"<form action=\"logon\" method=\"POST\">\r\n");
+		str_buffer_append(sb,"  <fieldset><legend>Admin user information:</legend>  user name:<br><input type=\"text\" name=\"uname\" value=\"\"><br>password:<br><input type=\"password\" name=\"pwd\" value=\"\"><br><br><input type=\"submit\" value=\"Login\"></fieldset>\r\n");
+		str_buffer_append(sb,"</form>\r\n");
+		str_buffer_append(sb,"\r\n  </body>\r\n</html>\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);
 

+ 1 - 1
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);

+ 27 - 14
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<smax;++i) {
-				if(sheadof(needle,sp+i)) {
+				if(sheadof(needle,sp+i,ignore_case)) {
 					ret = sp+i;
 					break;
 				}
@@ -643,28 +648,36 @@ static inline const char* findstr(const char *hay, size_t slen, const char *need
 	return ret;
 }
 
-static inline int is_http_get_inline(const char *s, size_t blen) {
+static inline int is_http_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/");
+		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;

+ 1 - 1
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);

+ 1 - 1
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";