diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 8c1316c..4e3f73f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -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) { diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 6c62aa2..85fa0c6 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -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); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index dcb58cc..f86f26c 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -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) diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 5208484..75fc3ae 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -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); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index cbf4fd9..68dc4ce 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -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);