mirror of
https://github.com/coturn/coturn.git
synced 2025-11-03 00:10:59 +01:00
working on https
This commit is contained in:
parent
385bb2fe9b
commit
bd8c39c3b7
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
@ -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);
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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__)
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user