working on SCTP

This commit is contained in:
mom040267 2015-03-16 06:10:10 +00:00
parent 7d5ab2472a
commit b824384faa
5 changed files with 194 additions and 31 deletions

View File

@ -121,8 +121,12 @@ static int is_socket_writeable(ioa_socket_handle s, size_t sz, const char *msg,
switch (s->st){
case SCTP_SOCKET:
case TLS_SCTP_SOCKET:
case TCP_SOCKET:
case TLS_SOCKET:
if (s->bev) {
struct evbuffer *evb = bufferevent_get_output(s->bev);
@ -877,7 +881,7 @@ int set_socket_options(ioa_socket_handle s)
if(!s || (s->parent_s))
return 0;
set_socket_options_fd(s->fd,((s->st == TCP_SOCKET) || (s->st == TLS_SOCKET) || (s->st == TENTATIVE_TCP_SOCKET)),s->family);
set_socket_options_fd(s->fd,is_stream_socket(s->st),s->family);
s->default_ttl = get_raw_socket_ttl(s->fd, s->family);
s->current_ttl = s->default_ttl;
@ -888,6 +892,21 @@ int set_socket_options(ioa_socket_handle s)
return 0;
}
int is_stream_socket(int st) {
switch(st) {
case TCP_SOCKET:
case TLS_SOCKET:
case TENTATIVE_TCP_SOCKET:
case SCTP_SOCKET:
case TLS_SCTP_SOCKET:
case TENTATIVE_SCTP_SOCKET:
return 1;
default:
;
}
return 0;
}
/* <<== Socket options helpers */
ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat)
@ -1282,7 +1301,7 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, io
* Section 5.2 of RFC 6062 will not work correctly
* for those OSes (for example, Linux pre-3.9 kernel).
*/
s->fd = socket(s->family, SOCK_STREAM, 0);
s->fd = socket(s->family, RELAY_STREAM_SOCKET_TYPE, RELAY_STREAM_SOCKET_PROTOCOL);
if (s->fd < 0) {
perror("TCP socket");
if(ret) {
@ -2209,7 +2228,7 @@ static int socket_input_worker(ioa_socket_handle s)
}
}
if(s->st == TLS_SOCKET) {
if((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) {
#if TLS_SUPPORTED
SSL *ctx = bufferevent_openssl_get_ssl(s->bev);
if(!ctx || SSL_get_shutdown(ctx)) {
@ -2295,6 +2314,74 @@ static int socket_input_worker(ioa_socket_handle s)
bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */
}
} else if(s->st == TENTATIVE_SCTP_SOCKET) {
EVENT_DEL(s->read_event);
#if TLS_SUPPORTED
TURN_TLS_TYPE tls_type = check_tentative_tls(s->fd);
if(tls_type) {
s->st = TLS_SCTP_SOCKET;
if(s->ssl) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d: ssl already exist\n", __FUNCTION__,(long)s, s->st, s->sat);
}
if(s->bev) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d: bev already exist\n", __FUNCTION__,(long)s, s->st, s->sat);
}
switch(tls_type) {
#if TLSv1_2_SUPPORTED
case TURN_TLS_v1_2:
if(s->e->tls_ctx_v1_2) {
set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_2));
}
break;
#endif
#if TLSv1_1_SUPPORTED
case TURN_TLS_v1_1:
if(s->e->tls_ctx_v1_1) {
set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_1));
}
break;
#endif
case TURN_TLS_v1_0:
if(s->e->tls_ctx_v1_0) {
set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_0));
}
break;
default:
if(s->e->tls_ctx_ssl23) {
set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_ssl23));
} else {
s->tobeclosed = 1;
return 0;
}
};
if(s->ssl) {
s->bev = bufferevent_openssl_socket_new(s->e->event_base,
s->fd,
s->ssl,
BUFFEREVENT_SSL_ACCEPTING,
TURN_BUFFEREVENTS_OPTIONS);
debug_ptr_add(s->bev);
bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
eventcb_bev, s);
bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */
}
} else
#endif //TLS_SUPPORTED
{
s->st = SCTP_SOCKET;
if(s->bev) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d: bev already exist\n", __FUNCTION__,(long)s, s->st, s->sat);
}
s->bev = bufferevent_socket_new(s->e->event_base,
s->fd,
TURN_BUFFEREVENTS_OPTIONS);
debug_ptr_add(s->bev);
bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
eventcb_bev, s);
bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */
}
}
try_start:
@ -2308,7 +2395,7 @@ static int socket_input_worker(ioa_socket_handle s)
stun_buffer_list_elem *buf_elem = new_blist_elem(s->e);
len = -1;
if(s->bev) { /* TCP & TLS */
if(s->bev) { /* TCP & TLS & SCTP & SCTP/TLS */
struct evbuffer *inbuf = bufferevent_get_input(s->bev);
if(inbuf) {
ev_ssize_t blen = evbuffer_copyout(inbuf, buf_elem->buf.buf, STUN_BUFFER_SIZE);
@ -2318,7 +2405,7 @@ static int socket_input_worker(ioa_socket_handle s)
if(blen>(ev_ssize_t)STUN_BUFFER_SIZE)
blen=(ev_ssize_t)STUN_BUFFER_SIZE;
if(((s->st == TCP_SOCKET)||(s->st == TLS_SOCKET)) && ((s->sat == TCP_CLIENT_DATA_SOCKET)||(s->sat==TCP_RELAY_DATA_SOCKET))) {
if(is_stream_socket(s->st) && ((s->sat == TCP_CLIENT_DATA_SOCKET)||(s->sat==TCP_RELAY_DATA_SOCKET))) {
mlen = blen;
} else {
mlen = stun_get_message_len_str(buf_elem->buf.buf, blen, 1, &app_msg_len);
@ -2331,7 +2418,7 @@ static int socket_input_worker(ioa_socket_handle s)
s->tobeclosed = 1;
s->broken = 1;
log_socket_event(s, "socket read failed, to be closed",1);
} else if(s->st == TLS_SOCKET) {
} else if((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) {
#if TLS_SUPPORTED
SSL *ctx = bufferevent_openssl_get_ssl(s->bev);
if(!ctx || SSL_get_shutdown(ctx)) {
@ -2650,7 +2737,7 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg)
if (arg) {
ioa_socket_handle s = (ioa_socket_handle) arg;
if((s->st != TCP_SOCKET)&&(s->st != TLS_SOCKET)&&(s->st != TENTATIVE_TCP_SOCKET)) {
if(!is_stream_socket(s->st)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: socket type is wrong on the socket: 0x%lx, st=%d, sat=%d\n",__FUNCTION__,(long)s,s->st,s->sat);
return;
}
@ -2710,24 +2797,24 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg)
addr_to_string(&(s->remote_addr),(u08bits*)sraddr);
if (events & BEV_EVENT_EOF) {
if(server->verbose)
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP (or SCTP) socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: stream (TCP or SCTP) socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr);
if(s == ss->client_socket) {
shutdown_client_connection(server, ss, 0, "TCP connection closed by client (callback)");
shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by client (callback)");
} else if(s == ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s) {
shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (ipv4 callback)");
shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by peer (ipv4 callback)");
} else if(s == ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s) {
shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (ipv6 callback)");
shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by peer (ipv6 callback)");
} else {
shutdown_client_connection(server, ss, 0, "TCP connection closed by remote party (callback)");
shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by remote party (callback)");
}
} else if (events & BEV_EVENT_ERROR) {
if(EVUTIL_SOCKET_ERROR()) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"session %018llu: TCP (or SCTP) socket error: %s %s\n",(unsigned long long)(ss->id),
evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), sraddr);
} else if(server->verbose) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP (or SCTP) socket disconnected: %s\n",(unsigned long long)(ss->id),sraddr);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: stream (TCP or SCTP) socket disconnected: %s\n",(unsigned long long)(ss->id),sraddr);
}
shutdown_client_connection(server, ss, 0, "TCP (or SCTP) socket buffer operation error (callback)");
shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) socket buffer operation error (callback)");
}
}
}
@ -3003,7 +3090,7 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr,
set_socket_tos(s, tos);
if (s->connected && s->bev) {
if (s->st == TLS_SOCKET) {
if ((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) {
#if TLS_SUPPORTED
SSL *ctx = bufferevent_openssl_get_ssl(s->bev);
if (!ctx || SSL_get_shutdown(ctx)) {
@ -3107,7 +3194,7 @@ int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t
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 ((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) {
#if TLS_SUPPORTED
SSL *ctx = bufferevent_openssl_get_ssl(s->bev);
if (!ctx || SSL_get_shutdown(ctx)) {
@ -3180,6 +3267,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
}
break;
case TENTATIVE_TCP_SOCKET:
case TENTATIVE_SCTP_SOCKET:
if(s->bev) {
if(!clean_preexisting) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
@ -3197,6 +3285,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
event_add(s->read_event,NULL);
}
break;
case SCTP_SOCKET:
case TCP_SOCKET:
if(s->bev) {
if(!clean_preexisting) {
@ -3220,6 +3309,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
}
}
break;
case TLS_SCTP_SOCKET:
case TLS_SOCKET:
if(s->bev) {
if(!clean_preexisting) {

View File

@ -127,6 +127,69 @@ static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd,
FUNCEND ;
}
static void sctp_server_input_handler(struct evconnlistener *l, evutil_socket_t fd,
struct sockaddr *sa, int socklen, void *arg)
{
UNUSED_ARG(l);
tls_listener_relay_server_type * server = (tls_listener_relay_server_type*) arg;
if(!(server->connect_cb)) {
socket_closesocket(fd);
return;
}
FUNCSTART;
if (!server)
return;
ns_bcopy(sa,&(server->sm.m.sm.nd.src_addr),socklen);
addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr),"tcp or tls connected to");
SOCKET_TYPE st = TENTATIVE_SCTP_SOCKET;
if(turn_params.no_tls)
st = SCTP_SOCKET;
else if(turn_params.no_tcp)
st = TLS_SCTP_SOCKET;
ioa_socket_handle ioas =
create_ioa_socket_from_fd(
server->e,
fd,
NULL,
st,
CLIENT_SOCKET,
&(server->sm.m.sm.nd.src_addr),
&(server->addr));
if (ioas) {
server->sm.m.sm.nd.recv_ttl = TTL_IGNORE;
server->sm.m.sm.nd.recv_tos = TOS_IGNORE;
server->sm.m.sm.nd.nbh = NULL;
server->sm.m.sm.s = ioas;
server->sm.m.sm.can_resume = 1;
server->sm.relay_server = server->relay_server;
int rc = server->connect_cb(server->e, &(server->sm));
if (rc < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
"Cannot create sctp or tls/sctp session\n");
}
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
"Cannot create ioa_socket from FD\n");
socket_closesocket(fd);
}
FUNCEND ;
}
///////////////////// operations //////////////////////////
static int create_server_listener(tls_listener_relay_server_type* server) {
@ -246,7 +309,7 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) {
}
server->sctp_l = evconnlistener_new(server->e->event_base,
server_input_handler, server,
sctp_server_input_handler, server,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
1024, tls_listen_fd);

View File

@ -419,14 +419,20 @@ static const char* pname(SOCKET_TYPE st)
switch(st) {
case TCP_SOCKET:
return "TCP";
case SCTP_SOCKET:
return "SCTP";
case UDP_SOCKET:
return "UDP";
case TLS_SOCKET:
return "TLS";
return "TLS/TCP";
case TLS_SCTP_SOCKET:
return "TLS/SCTP";
case DTLS_SOCKET:
return "DTLS";
case TENTATIVE_TCP_SOCKET:
return "TCP/TLS";
return "TLS/TCP ?";
case TENTATIVE_SCTP_SOCKET:
return "TLS/SCTP ?";
default:
;
};
@ -451,13 +457,13 @@ static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg
const char *pn=csarg->pname;
if(pn[0]) {
if(!strcmp(pn,"TLS") || !strcmp(pn,"tls") || !strcmp(pn,"Tls")) {
if(tsi->client_protocol != TLS_SOCKET)
if((tsi->client_protocol != TLS_SOCKET)||(tsi->client_protocol != TLS_SCTP_SOCKET))
return 0;
} else if(!strcmp(pn,"DTLS") || !strcmp(pn,"dtls") || !strcmp(pn,"Dtls")) {
if(tsi->client_protocol != DTLS_SOCKET)
return 0;
} else if(!strcmp(pn,"TCP") || !strcmp(pn,"tcp") || !strcmp(pn,"Tcp")) {
if(tsi->client_protocol != TCP_SOCKET)
if((tsi->client_protocol != TCP_SOCKET)||(tsi->client_protocol != SCTP_SOCKET))
return 0;
} else if(!strcmp(pn,"UDP") || !strcmp(pn,"udp") || !strcmp(pn,"Udp")) {
if(tsi->client_protocol != UDP_SOCKET)
@ -2195,13 +2201,13 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi
const char *pn=csarg->client_protocol;
if(pn[0]) {
if(!strcmp(pn,"TLS") || !strcmp(pn,"tls") || !strcmp(pn,"Tls")) {
if(tsi->client_protocol != TLS_SOCKET)
if((tsi->client_protocol != TLS_SOCKET)||(tsi->client_protocol != TLS_SCTP_SOCKET))
return 0;
} else if(!strcmp(pn,"DTLS") || !strcmp(pn,"dtls") || !strcmp(pn,"Dtls")) {
if(tsi->client_protocol != DTLS_SOCKET)
return 0;
} else if(!strcmp(pn,"TCP") || !strcmp(pn,"tcp") || !strcmp(pn,"Tcp")) {
if(tsi->client_protocol != TCP_SOCKET)
if((tsi->client_protocol != TCP_SOCKET)||(tsi->client_protocol != SCTP_SOCKET))
return 0;
} else if(!strcmp(pn,"UDP") || !strcmp(pn,"udp") || !strcmp(pn,"Udp")) {
if(tsi->client_protocol != UDP_SOCKET)

View File

@ -87,7 +87,10 @@ enum _SOCKET_TYPE {
TCP_SOCKET=6,
UDP_SOCKET=17,
TLS_SOCKET=56,
SCTP_SOCKET=132,
TLS_SCTP_SOCKET=133,
DTLS_SOCKET=250,
TENTATIVE_SCTP_SOCKET=254,
TENTATIVE_TCP_SOCKET=255
};
@ -227,6 +230,7 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, i
int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s, u08bits *realm);
int get_ioa_socket_address_family(ioa_socket_handle s);
int is_stream_socket(int st);
const char* get_ioa_socket_cipher(ioa_socket_handle s);
const char* get_ioa_socket_ssl_method(ioa_socket_handle s);
SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s);

View File

@ -1057,8 +1057,7 @@ static int handle_turn_allocate(turn_turnserver *server,
*reason = (const u08bits *)"UDP Transport is not allowed by the TURN Server configuration";
} else if(ss->client_socket) {
SOCKET_TYPE cst = get_ioa_socket_type(ss->client_socket);
if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) &&
(cst!=TCP_SOCKET) && (cst!=TLS_SOCKET)) {
if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && !is_stream_socket(cst)) {
*err_code = 400;
*reason = (const u08bits *)"Wrong Transport Data";
} else {
@ -2304,7 +2303,7 @@ static int handle_turn_connection_bind(turn_turnserver *server,
*err_code = 400;
*reason = (const u08bits *)"Bad request: CONNECTION_BIND cannot be issued after allocation";
} else if((get_ioa_socket_type(ss->client_socket)!=TCP_SOCKET) && (get_ioa_socket_type(ss->client_socket)!=TLS_SOCKET)) {
} else if(!is_stream_socket(get_ioa_socket_type(ss->client_socket))) {
*err_code = 400;
*reason = (const u08bits *)"Bad request: CONNECTION_BIND only possible with TCP/TLS";
@ -2666,7 +2665,8 @@ static int handle_turn_channel_bind(turn_turnserver *server,
if(!(ss->is_mobile)) {
if(get_ioa_socket_type(ss->client_socket) == UDP_SOCKET ||
get_ioa_socket_type(ss->client_socket) == TCP_SOCKET) {
get_ioa_socket_type(ss->client_socket) == TCP_SOCKET ||
get_ioa_socket_type(ss->client_socket) == SCTP_SOCKET) {
if(get_ioa_socket_type(get_relay_socket(&(ss->alloc),peer_addr.ss.sa_family)) == UDP_SOCKET) {
chn->kernel_channel = CREATE_TURN_CHANNEL_KERNEL(chn->chnum,
get_ioa_socket_address_family(ss->client_socket),
@ -3605,7 +3605,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss,
if(((cst == UDP_SOCKET)||(cst == DTLS_SOCKET)) && server->self_udp_balance &&
server->aux_servers_list && server->aux_servers_list->size) {
asl = server->aux_servers_list;
} else if(((cst == TLS_SOCKET) || (cst == DTLS_SOCKET)) &&
} else if(((cst == TLS_SOCKET) || (cst == DTLS_SOCKET) ||(cst == TLS_SCTP_SOCKET)) &&
server->tls_alternate_servers_list && server->tls_alternate_servers_list->size) {
asl = server->tls_alternate_servers_list;
}
@ -4490,7 +4490,7 @@ static int read_client_connection(turn_turnserver *server,
size_t orig_blen = blen;
SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket);
SOCKET_APP_TYPE sat = get_ioa_socket_app_type(ss->client_socket);
int is_padding_mandatory = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET));
int is_padding_mandatory = is_stream_socket(st);
if(sat == HTTP_CLIENT_SOCKET) {
@ -4590,7 +4590,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_stream_socket(st)) {
if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) {
const char *proto = "HTTP";
ioa_network_buffer_data(in_buffer->nbh)[ioa_network_buffer_get_size(in_buffer->nbh)] = 0;
@ -4761,7 +4761,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type,
ioa_network_buffer_header_init(nbh);
SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket);
int do_padding = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET));
int do_padding = is_stream_socket(st);
stun_init_channel_message_str(chnum, ioa_network_buffer_data(nbh), &len, len, do_padding);
ioa_network_buffer_set_size(nbh,len);