static int create_server_listener(tls_listener_relay_server_type* server) { FUNCSTART; if(!server) return -1; evutil_socket_t tls_listen_fd = -1; tls_listen_fd = socket(server->addr.ss.ss_family, SOCK_STREAM, 0); if (tls_listen_fd < 0) { perror("socket"); return -1; } if(sock_bind_to_device(tls_listen_fd, (unsigned char*)server->ifname)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); } if(addr_bind(tls_listen_fd,&server->addr)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind TCP/TLS listener socket to addr %s\n",saddr); socket_closesocket(tls_listen_fd); return -1; } socket_tcp_set_keepalive(tls_listen_fd); socket_set_nonblocking(tls_listen_fd); server->l = evconnlistener_new(server->e->event_base, server_input_handler, server, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 1024, tls_listen_fd); if(!(server->l)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot create TLS listener\n"); socket_closesocket(tls_listen_fd); return -1; } if(addr_get_from_sock(tls_listen_fd, &(server->addr))) { perror("Cannot get local socket addr"); socket_closesocket(tls_listen_fd); return -1; } if(!no_tcp && !no_tls) addr_debug_print(server->verbose, &server->addr,"TCP/TLS listener opened on "); else if(!no_tls) addr_debug_print(server->verbose, &server->addr,"TLS listener opened on "); else if(!no_tcp) addr_debug_print(server->verbose, &server->addr,"TCP listener opened on "); FUNCEND; return 0; }
static int create_server_socket(dtls_listener_relay_server_type* server) { FUNCSTART; if(!server) return -1; clean_server(server); ioa_socket_raw udp_listen_fd = -1; udp_listen_fd = socket(server->addr.ss.ss_family, SOCK_DGRAM, 0); if (udp_listen_fd < 0) { perror("socket"); return -1; } server->udp_listen_s = create_ioa_socket_from_fd(server->e, udp_listen_fd, NULL, UDP_SOCKET, LISTENER_SOCKET, NULL, &(server->addr)); server->udp_listen_s->listener_server = server; set_sock_buf_size(udp_listen_fd,UR_SERVER_SOCK_BUF_SIZE); if(sock_bind_to_device(udp_listen_fd, (unsigned char*)server->ifname)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); } if(addr_bind(udp_listen_fd,&server->addr)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind UDP/DTLS listener socket to addr %s\n",saddr); return -1; } server->udp_listen_ev = event_new(server->e->event_base,udp_listen_fd, EV_READ|EV_PERSIST,udp_server_input_handler,server); event_add(server->udp_listen_ev,NULL); if(addr_get_from_sock(udp_listen_fd, &(server->addr))) { perror("Cannot get local socket addr"); return -1; } if(!no_udp && !no_dtls) addr_debug_print(server->verbose, &server->addr,"UDP/DTLS listener opened on "); else if(!no_dtls) addr_debug_print(server->verbose, &server->addr,"DTLS listener opened on "); else if(!no_udp) addr_debug_print(server->verbose, &server->addr,"UDP listener opened on "); FUNCEND; return 0; }
static ioa_socket_handle dtls_accept_client_connection( dtls_listener_relay_server_type* server, SSL *ssl, ioa_addr *remote_addr, ioa_addr *local_addr, u08bits *s, int len) { FUNCSTART; if (!ssl) return NULL; int rc = ssl_read(server->udp_listen_s->fd, ssl, (s08bits*)s, ioa_network_buffer_get_capacity(), server->verbose, &len); if (rc < 0) return NULL; addr_debug_print(server->verbose, remote_addr, "Accepted connection from"); ioa_socket_handle ioas = create_ioa_socket_from_ssl(server->e, server->udp_listen_s, ssl, DTLS_SOCKET, CLIENT_SOCKET, remote_addr, local_addr); if(ioas) { ioas->listener_server = server; addr_cpy(&(server->sm.m.sm.nd.src_addr),remote_addr); server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; server->sm.m.sm.nd.recv_tos = TOS_IGNORE; server->sm.m.sm.s = ioas; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create ioa_socket from SSL\n"); } FUNCEND ; return ioas; }
static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *arg) { UNUSED_ARG(l); tcp_listener_relay_server_type * server = (tcp_listener_relay_server_type*) arg; if(!(server->e->connect_cb)) { close(fd); return; } FUNCSTART; if (!server) return; if (server->stats) ++(*(server->stats)); ioa_addr client_addr; ns_bcopy(sa,&client_addr,socklen); addr_debug_print(server->verbose, &client_addr,"tcp connected to"); ioa_socket_handle ioas = create_ioa_socket_from_fd( server->e, fd, TCP_SOCKET, CLIENT_SOCKET, &client_addr, &(server->addr)); if (ioas) { ioa_net_data nd = { &client_addr, NULL, 0, TTL_IGNORE, TOS_IGNORE }; int rc = server->e->connect_cb(server->e, ioas, &nd); if (rc < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create tcp session\n"); IOA_CLOSE_SOCKET(ioas); } } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create ioa_socket from FD\n"); close(fd); } FUNCEND ; }
static int reopen_server_socket(dtls_listener_relay_server_type* server) { if(!server) return 0; FUNCSTART; EVENT_DEL(server->udp_listen_ev); if(server->udp_listen_s->fd>=0) { socket_closesocket(server->udp_listen_s->fd); server->udp_listen_s->fd = -1; } if (!(server->udp_listen_s)) { return create_server_socket(server); } ioa_socket_raw udp_listen_fd = socket(server->addr.ss.ss_family, SOCK_DGRAM, 0); if (udp_listen_fd < 0) { perror("socket"); FUNCEND; return -1; } server->udp_listen_s->fd = udp_listen_fd; /* some UDP sessions may fail due to the race condition here */ set_socket_options(server->udp_listen_s); set_sock_buf_size(udp_listen_fd, UR_SERVER_SOCK_BUF_SIZE); if (sock_bind_to_device(udp_listen_fd, (unsigned char*) server->ifname) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind listener socket to device %s\n", server->ifname); } if(addr_bind(udp_listen_fd,&server->addr)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to addr %s\n",saddr); return -1; } server->udp_listen_ev = event_new(server->e->event_base, udp_listen_fd, EV_READ | EV_PERSIST, udp_server_input_handler, server); event_add(server->udp_listen_ev, NULL ); if (!no_udp && !no_dtls) addr_debug_print(server->verbose, &server->addr, "UDP/DTLS listener opened on "); else if (!no_dtls) addr_debug_print(server->verbose, &server->addr, "DTLS listener opened on "); else if (!no_udp) addr_debug_print(server->verbose, &server->addr, "UDP listener opened on "); FUNCEND; return 0; }
static int create_server_socket(dtls_listener_relay_server_type* server, int report_creation) { FUNCSTART; if(!server) return -1; clean_server(server); { ioa_socket_raw udp_listen_fd = -1; udp_listen_fd = socket(server->addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_listen_fd < 0) { perror("socket"); return -1; } server->udp_listen_s = create_ioa_socket_from_fd(server->e, udp_listen_fd, NULL, UDP_SOCKET, LISTENER_SOCKET, NULL, &(server->addr)); set_sock_buf_size(udp_listen_fd,UR_SERVER_SOCK_BUF_SIZE); if(sock_bind_to_device(udp_listen_fd, (unsigned char*)server->ifname)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); } set_raw_socket_ttl_options(udp_listen_fd, server->addr.ss.sa_family); set_raw_socket_tos_options(udp_listen_fd, server->addr.ss.sa_family); { const int max_binding_time = 60; int addr_bind_cycle = 0; retry_addr_bind: if(addr_bind(udp_listen_fd,&server->addr,1,1,UDP_SOCKET)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"Cannot bind DTLS/UDP listener socket to addr %s\n",saddr); if(addr_bind_cycle++<max_binding_time) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Trying to bind DTLS/UDP listener socket to addr %s, again...\n",saddr); sleep(1); goto retry_addr_bind; } TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Fatal final failure: cannot bind DTLS/UDP listener socket to addr %s\n",saddr); exit(-1); } } server->udp_listen_ev = event_new(server->e->event_base,udp_listen_fd, EV_READ|EV_PERSIST,udp_server_input_handler, server); event_add(server->udp_listen_ev,NULL); } if(report_creation) { if(!turn_params.no_udp && !turn_params.no_dtls) addr_debug_print(server->verbose, &server->addr,"DTLS/UDP listener opened on"); else if(!turn_params.no_dtls) addr_debug_print(server->verbose, &server->addr,"DTLS listener opened on"); else if(!turn_params.no_udp) addr_debug_print(server->verbose, &server->addr,"UDP listener opened on"); } FUNCEND; return 0; }
static int create_new_connected_udp_socket( dtls_listener_relay_server_type* server, ioa_socket_handle s) { evutil_socket_t udp_fd = socket(s->local_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_fd < 0) { perror("socket"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot allocate new socket\n", __FUNCTION__); return -1; } if (sock_bind_to_device(udp_fd, (unsigned char*) (s->e->relay_ifname)) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot bind udp server socket to device %s\n", (char*) (s->e->relay_ifname)); } ioa_socket_handle ret = (ioa_socket*) turn_malloc(sizeof(ioa_socket)); if (!ret) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot allocate new socket structure\n", __FUNCTION__); close(udp_fd); return -1; } ns_bzero(ret, sizeof(ioa_socket)); ret->magic = SOCKET_MAGIC; ret->fd = udp_fd; ret->family = s->family; ret->st = s->st; ret->sat = CLIENT_SOCKET; ret->local_addr_known = 1; addr_cpy(&(ret->local_addr), &(s->local_addr)); if (addr_bind(udp_fd,&(s->local_addr),1,1,UDP_SOCKET) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot bind new detached udp server socket to local addr\n"); IOA_CLOSE_SOCKET(ret); return -1; } ret->bound = 1; { int connect_err = 0; if (addr_connect(udp_fd, &(server->sm.m.sm.nd.src_addr), &connect_err) < 0) { char sl[129]; char sr[129]; addr_to_string(&(ret->local_addr),(u08bits*)sl); addr_to_string(&(server->sm.m.sm.nd.src_addr),(u08bits*)sr); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect new detached udp client socket from local addr %s to remote addr %s\n",sl,sr); IOA_CLOSE_SOCKET(ret); return -1; } } ret->connected = 1; addr_cpy(&(ret->remote_addr), &(server->sm.m.sm.nd.src_addr)); set_socket_options(ret); ret->current_ttl = s->current_ttl; ret->default_ttl = s->default_ttl; ret->current_tos = s->current_tos; ret->default_tos = s->default_tos; #if DTLS_SUPPORTED if (!turn_params.no_dtls && is_dtls_handshake_message( ioa_network_buffer_data(server->sm.m.sm.nd.nbh), (int) ioa_network_buffer_get_size( server->sm.m.sm.nd.nbh))) { SSL* connecting_ssl = NULL; BIO *wbio = NULL; struct timeval timeout; /* Create BIO */ wbio = BIO_new_dgram(ret->fd, BIO_NOCLOSE); (void) BIO_dgram_set_peer(wbio, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr)); BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &(server->sm.m.sm.nd.src_addr)); /* Set and activate timeouts */ timeout.tv_sec = DTLS_MAX_RECV_TIMEOUT; timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); #if DTLSv1_2_SUPPORTED if(get_dtls_version(ioa_network_buffer_data(server->sm.m.sm.nd.nbh), (int)ioa_network_buffer_get_size(server->sm.m.sm.nd.nbh)) == 1) { connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); } else { connecting_ssl = SSL_NEW(server->dtls_ctx); } #else { connecting_ssl = SSL_NEW(server->dtls_ctx); } #endif SSL_set_accept_state(connecting_ssl); SSL_set_bio(connecting_ssl, NULL, wbio); SSL_set_options(connecting_ssl, SSL_OP_COOKIE_EXCHANGE); SSL_set_max_cert_list(connecting_ssl, 655350); int rc = ssl_read(ret->fd, connecting_ssl, server->sm.m.sm.nd.nbh, server->verbose); if (rc < 0) { if (!(SSL_get_shutdown(connecting_ssl) & SSL_SENT_SHUTDOWN)) { SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN); SSL_shutdown(connecting_ssl); } SSL_FREE(connecting_ssl); IOA_CLOSE_SOCKET(ret); return -1; } addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr), "Accepted DTLS connection from"); ret->ssl = connecting_ssl; ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); server->sm.m.sm.nd.nbh = NULL; ret->st = DTLS_SOCKET; } #endif server->sm.m.sm.s = ret; return server->connect_cb(server->e, &(server->sm)); }
void StunClient::processResponse(QByteArray resp, QString peer_addr) { u08bits rbuf[STUN_BUFFER_SIZE]; size_t rlen = 0; stun_buffer buf; QString mapped_addr; u08bits addr_buff[STUN_BUFFER_SIZE] = {0}; rlen = resp.length(); memcpy(rbuf, resp.data(), resp.length()); buf.len = resp.length(); memcpy(buf.buf, resp.data(), resp.length()); if (!stun_is_command_message(&buf)) { qDebug()<<resp.length()<<("The response is not a STUN message")<<peer_addr; // should be a relayed raw UDP packet to peerA emit packetReceived(resp, peer_addr); return; } u16bits stun_method; u16bits stun_msg_type; stun_method = stun_get_method_str(buf.buf, buf.len); stun_msg_type = stun_get_msg_type_str(buf.buf, buf.len); qDebug()<<"method:"<<stun_method<<getMethodName(stun_method)<<",msg type:"<<stun_msg_type; if (stun_method == STUN_METHOD_BINDING) { } else { this->debugStunResponse(resp); } // channel data if (stun_is_indication(&buf)) { u16bits chan_no; size_t blen = 0; qDebug()<<"indication data:"<<buf.len; stun_attr_ref t_attr = stun_attr_get_first_by_type(&buf, STUN_ATTRIBUTE_DATA); const u08bits *t_value = stun_attr_get_value(t_attr); blen = stun_attr_get_len(t_attr); QString xor_peer_addr = getStunAddress(resp, STUN_ATTRIBUTE_XOR_PEER_ADDRESS); qDebug()<<"is chan msg:"<<stun_is_channel_message_str(t_value, &blen, &chan_no, 0); qDebug()<<"chan no:"<<chan_no<<blen<<xor_peer_addr; emit this->packetReceived(QByteArray((char*)t_value + 4, blen - 4), xor_peer_addr); return; } if (!stun_is_response(&buf)) { qDebug()<<resp.length()<<("The response is not a reponse message\n"); return; } if (!stun_is_success_response(&buf)) { int err_code = 0; u08bits err_msg[1025] = "\0"; size_t err_msg_size = sizeof(err_msg); if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) { printf("The response is an error %d (%s)\n", err_code, (char*) err_msg); } else { printf("The response is an unrecognized error\n"); } // test unauth u08bits realm[128] = {0}; u08bits nonce[256] = {0}; if (stun_is_challenge_response_str(buf.buf, buf.len, &err_code, err_msg, err_msg_size, realm, nonce)) { qDebug()<<err_code; qDebug()<<err_code<<(char*)err_msg<<(char*)realm<<(char*)nonce; m_realm = QByteArray((char*)realm); m_nonce = QByteArray((char*)nonce); if (stun_method == STUN_METHOD_ALLOCATE) { this->allocate((char*)realm, (char*)nonce); } if (stun_method == STUN_METHOD_CHANNEL_BIND) { QThread::msleep(100); this->channelBind(m_peer_addr); } } if (err_code == 437) { assert(err_code != 437); // allocate mismatch } if (err_code == 438) { assert(err_code != 438); // stale nonce } if (err_code == 486) { assert(err_code != 486); // allocate quota reached } return; } if (stun_is_binding_response(&buf)) { ioa_addr reflexive_addr; addr_set_any(&reflexive_addr); if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &reflexive_addr, NULL) >= 0) { stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS); if (sar) { // *rfc5780 = 1; printf("\n========================================\n"); // printf("RFC 5780 response %d\n",++counter); ioa_addr other_addr; stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &other_addr, NULL); sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); if (sar) { ioa_addr response_origin; stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL); addr_debug_print(1, &response_origin, "Response origin: "); } addr_debug_print(1, &other_addr, "Other addr: "); } addr_debug_print(1, &reflexive_addr, "UDP reflexive addr"); addr_to_string(&reflexive_addr, addr_buff); } else { printf("Cannot read the response\n"); } // emit got addr if (strlen((char*)addr_buff) > 0) { mapped_addr = QString((char*)addr_buff); emit this->mappedAddressRecieved(mapped_addr); } return; } // end bind resp if (stun_method == STUN_METHOD_ALLOCATE) { m_relayed_addr = this->getStunAddress(resp, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS); this->saveAllocatePuples(m_realm, m_nonce); emit this->allocateDone(m_relayed_addr); if (!m_channel_refresh_timer) { m_channel_refresh_timer = new QTimer(); QObject::connect(m_channel_refresh_timer, &QTimer::timeout, this, &StunClient::onRefreshTimeout); } if (!m_channel_refresh_timer->isActive()) { m_channel_refresh_timer->start(m_channel_refresh_timeout); } } if (stun_method == STUN_METHOD_CREATE_PERMISSION) { if (!m_permission_keepalive_timer) { emit this->createPermissionDone(); } if (!m_permission_keepalive_timer) { m_permission_keepalive_timer = new QTimer(); QObject::connect(m_permission_keepalive_timer, &QTimer::timeout, this, &StunClient::onPermKATimeout); } if (!m_permission_keepalive_timer->isActive()) { m_permission_keepalive_timer->start(m_permission_keepalive_timeout); } } if (stun_method == STUN_METHOD_CHANNEL_BIND) { emit this->channelBindDone(m_relayed_addr); } if (stun_method == STUN_METHOD_REFRESH) { qDebug()<<"refresh responsed."; } }
static int clnet_allocate(int verbose, app_ur_conn_info *clnet_info, ioa_addr *relay_addr, int af, char *turn_addr, u16bits *turn_port) { int af_cycle = 0; int reopen_socket = 0; int allocate_finished; stun_buffer request_message, response_message; beg_allocate: allocate_finished=0; while (!allocate_finished && af_cycle++ < 32) { int allocate_sent = 0; if(reopen_socket && !use_tcp) { socket_closesocket(clnet_info->fd); clnet_info->fd = -1; if (clnet_connect(addr_get_port(&(clnet_info->remote_addr)), clnet_info->rsaddr, (u08bits*)clnet_info->ifname, clnet_info->lsaddr, verbose, clnet_info) < 0) { exit(-1); } reopen_socket = 0; } int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4); int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6); uint64_t reservation_token = 0; char* rt = NULL; int ep = !no_rtcp && !dual_allocation; if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { reservation_token = ioa_ntoh64(current_reservation_token); rt = (char*) (&reservation_token); } } if(is_TCP_relay()) { ep = -1; } else if(rt) { ep = -1; } else if(!ep) { ep = (((u08bits)random()) % 2); ep = ep-1; } if(!dos) stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility, rt, ep); else stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility, rt, ep); if(bps) stun_attr_add_bandwidth_str(request_message.buf, (size_t*)(&(request_message.len)), bps); if(dont_fragment) stun_attr_add(&request_message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); add_origin(&request_message); if(add_integrity(clnet_info, &request_message)<0) return -1; stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!allocate_sent) { int len = send_buffer(clnet_info, &request_message,0,0); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate sent\n"); } allocate_sent = 1; } else { perror("send"); exit(1); } } ////////////<<==allocate send if(not_rare_event()) return 0; ////////allocate response==>> { int allocate_received = 0; while (!allocate_received) { int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate response received: \n"); } response_message.len = len; int err_code = 0; u08bits err_msg[129]; if (stun_is_success_response(&response_message)) { allocate_received = 1; allocate_finished = 1; if(clnet_info->nonce[0]) { if(check_integrity(clnet_info, &response_message)<0) return -1; } if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } { int found = 0; stun_attr_ref sar = stun_attr_get_first(&response_message); while (sar) { int attr_type = stun_attr_get_type(sar); if(attr_type == STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS) { if (stun_attr_get_addr(&response_message, sar, relay_addr, NULL) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: !!!: relay addr cannot be received (1)\n", __FUNCTION__); return -1; } else { if (verbose) { ioa_addr raddr; memcpy(&raddr, relay_addr,sizeof(ioa_addr)); addr_debug_print(verbose, &raddr,"Received relay addr"); } if(!addr_any(relay_addr)) { if(relay_addr->ss.sa_family == AF_INET) { if(default_address_family != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) { found = 1; addr_cpy(&(clnet_info->relay_addr),relay_addr); break; } } if(relay_addr->ss.sa_family == AF_INET6) { if(default_address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) { found = 1; addr_cpy(&(clnet_info->relay_addr),relay_addr); break; } } } } } sar = stun_attr_get_next(&response_message,sar); } if(!found) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: !!!: relay addr cannot be received (2)\n", __FUNCTION__); return -1; } } stun_attr_ref rt_sar = stun_attr_get_first_by_type( &response_message, STUN_ATTRIBUTE_RESERVATION_TOKEN); uint64_t rtv = stun_attr_get_reservation_token_value(rt_sar); current_reservation_token = rtv; if (verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: rtv=%llu\n", __FUNCTION__, (long long unsigned int)rtv); read_mobility_ticket(clnet_info, &response_message); } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { goto beg_allocate; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { allocate_received = 1; if(err_code == 300) { if(clnet_info->nonce[0]) { if(check_integrity(clnet_info, &response_message)<0) return -1; } ioa_addr alternate_server; if(stun_attr_get_first_addr(&response_message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) { //error } else if(turn_addr && turn_port){ addr_to_string_no_port(&alternate_server, (u08bits*)turn_addr); *turn_port = (u16bits)addr_get_port(&alternate_server); } } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n", err_code,(char*)err_msg); if (err_code != 437) { allocate_finished = 1; current_reservation_token = 0; return -1; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "trying allocate again %d...\n", err_code); sleep(1); reopen_socket = 1; } } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown allocate response\n"); /* Try again ? */ } } else { perror("recv"); exit(-1); break; } } } } ////////////<<== allocate response received if(rare_event()) return 0; if(!allocate_finished) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot complete Allocation\n"); exit(-1); } allocate_rtcp = !allocate_rtcp; if (1) { af_cycle = 0; if(clnet_info->s_mobile_id[0]) { int fd = clnet_info->fd; SSL* ssl = clnet_info->ssl; int close_now = (int)(random()%2); if(close_now) { int close_socket = (int)(random()%2); if(ssl && !close_socket) { SSL_shutdown(ssl); SSL_FREE(ssl); fd = -1; } else if(fd>=0) { close(fd); fd = -1; ssl = NULL; } } app_ur_conn_info ci; ns_bcopy(clnet_info,&ci,sizeof(ci)); ci.fd = -1; ci.ssl = NULL; clnet_info->fd = -1; clnet_info->ssl = NULL; //Reopen: if(clnet_connect(addr_get_port(&(ci.remote_addr)), ci.rsaddr, (unsigned char*)ci.ifname, ci.lsaddr, clnet_verbose, clnet_info)<0) { exit(-1); } if(ssl) { SSL_shutdown(ssl); SSL_FREE(ssl); } else if(fd>=0) { close(fd); } } beg_refresh: if(af_cycle++>32) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot complete Refresh\n"); exit(-1); } //==>>refresh request, for an example only: { int refresh_sent = 0; stun_init_request(STUN_METHOD_REFRESH, &request_message); uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME); stun_attr_add(&request_message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); if(clnet_info->s_mobile_id[0]) { stun_attr_add(&request_message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); } if(dual_allocation && !mobility) { int t = ((u08bits)random())%3; if(t) { u08bits field[4]; field[0] = (t==1) ? (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4 : (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; field[1]=0; field[2]=0; field[3]=0; stun_attr_add(&request_message, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY, (const char*) field, 4); } } add_origin(&request_message); if(add_integrity(clnet_info, &request_message)<0) return -1; stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!refresh_sent) { int len = send_buffer(clnet_info, &request_message, 0,0); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh sent\n"); } refresh_sent = 1; if(clnet_info->s_mobile_id[0]) { usleep(10000); send_buffer(clnet_info, &request_message, 0,0); } } else { perror("send"); exit(1); } } } if(not_rare_event()) return 0; ////////refresh response==>> { int refresh_received = 0; while (!refresh_received) { int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if(clnet_info->s_mobile_id[0]) { len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); } if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh response received: \n"); } response_message.len = len; int err_code = 0; u08bits err_msg[129]; if (stun_is_success_response(&response_message)) { read_mobility_ticket(clnet_info, &response_message); refresh_received = 1; if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { goto beg_refresh; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { refresh_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n", err_code,(char*)err_msg); return -1; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown refresh response\n"); /* Try again ? */ } } else { perror("recv"); exit(-1); break; } } } } return 0; }
static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, const unsigned char* ifname, const char *local_address, int verbose, app_ur_conn_info *clnet_info) { ioa_addr local_addr; evutil_socket_t clnet_fd; int connect_err; int connect_cycle = 0; ioa_addr remote_addr; start_socket: clnet_fd = -1; connect_err = 0; ns_bzero(&remote_addr, sizeof(ioa_addr)); if (make_ioa_addr((const u08bits*) remote_address, clnet_remote_port, &remote_addr) < 0) return -1; ns_bzero(&local_addr, sizeof(ioa_addr)); clnet_fd = socket(remote_addr.ss.sa_family, use_sctp ? SCTP_CLIENT_STREAM_SOCKET_TYPE : (use_tcp ? CLIENT_STREAM_SOCKET_TYPE : CLIENT_DGRAM_SOCKET_TYPE), use_sctp ? SCTP_CLIENT_STREAM_SOCKET_PROTOCOL : (use_tcp ? CLIENT_STREAM_SOCKET_PROTOCOL : CLIENT_DGRAM_SOCKET_PROTOCOL)); if (clnet_fd < 0) { perror("socket"); exit(-1); } if (sock_bind_to_device(clnet_fd, ifname) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind client socket to device %s\n", ifname); } set_sock_buf_size(clnet_fd, UR_CLIENT_SOCK_BUF_SIZE); set_raw_socket_tos(clnet_fd, remote_addr.ss.sa_family, 0x22); set_raw_socket_ttl(clnet_fd, remote_addr.ss.sa_family, 47); if(clnet_info->is_peer && (*local_address==0)) { if(remote_addr.ss.sa_family == AF_INET6) { if (make_ioa_addr((const u08bits*) "::1", 0, &local_addr) < 0) { return -1; } } else { if (make_ioa_addr((const u08bits*) "127.0.0.1", 0, &local_addr) < 0) { return -1; } } addr_bind(clnet_fd, &local_addr, 0, 1, get_socket_type()); } else if (strlen(local_address) > 0) { if (make_ioa_addr((const u08bits*) local_address, 0, &local_addr) < 0) return -1; addr_bind(clnet_fd, &local_addr,0,1,get_socket_type()); } if(clnet_info->is_peer) { ; } else if(socket_connect(clnet_fd, &remote_addr, &connect_err)>0) goto start_socket; if (clnet_info) { addr_cpy(&(clnet_info->remote_addr), &remote_addr); addr_cpy(&(clnet_info->local_addr), &local_addr); clnet_info->fd = clnet_fd; addr_get_from_sock(clnet_fd, &(clnet_info->local_addr)); STRCPY(clnet_info->lsaddr,local_address); STRCPY(clnet_info->rsaddr,remote_address); STRCPY(clnet_info->ifname,(const char*)ifname); } if (use_secure) { int try_again = 0; clnet_info->ssl = tls_connect(clnet_info->fd, &remote_addr,&try_again,connect_cycle++); if (!clnet_info->ssl) { if(try_again) { goto start_socket; } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); exit(-1); } } if(verbose && clnet_info) { addr_debug_print(verbose, &(clnet_info->local_addr), "Connected from"); addr_debug_print(verbose, &remote_addr, "Connected to"); } if(!dos) usleep(500); return 0; }
void tcp_data_connect(app_ur_session *elem, u32bits cid) { int clnet_fd; int connect_cycle = 0; again: clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, CLIENT_STREAM_SOCKET_TYPE, CLIENT_STREAM_SOCKET_PROTOCOL); if (clnet_fd < 0) { perror("socket"); exit(-1); } if (sock_bind_to_device(clnet_fd, client_ifname) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind client socket to device %s\n", client_ifname); } set_sock_buf_size(clnet_fd, (UR_CLIENT_SOCK_BUF_SIZE<<2)); ++elem->pinfo.tcp_conn_number; int i = (int)(elem->pinfo.tcp_conn_number-1); elem->pinfo.tcp_conn=(app_tcp_conn_info**)turn_realloc(elem->pinfo.tcp_conn,0,elem->pinfo.tcp_conn_number*sizeof(app_tcp_conn_info*)); elem->pinfo.tcp_conn[i]=(app_tcp_conn_info*)turn_malloc(sizeof(app_tcp_conn_info)); ns_bzero(elem->pinfo.tcp_conn[i],sizeof(app_tcp_conn_info)); elem->pinfo.tcp_conn[i]->tcp_data_fd = clnet_fd; elem->pinfo.tcp_conn[i]->cid = cid; addr_cpy(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),&(elem->pinfo.local_addr)); addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr), 1, 1, TCP_SOCKET); addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); { int cycle = 0; while(cycle++<1024) { int err = 0; if (addr_connect(clnet_fd, &(elem->pinfo.remote_addr),&err) < 0) { if(err == EADDRINUSE) { socket_closesocket(clnet_fd); clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, CLIENT_STREAM_SOCKET_TYPE, CLIENT_STREAM_SOCKET_PROTOCOL); if (clnet_fd < 0) { perror("socket"); exit(-1); } if (sock_bind_to_device(clnet_fd, client_ifname) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind client socket to device %s\n", client_ifname); } set_sock_buf_size(clnet_fd, UR_CLIENT_SOCK_BUF_SIZE<<2); elem->pinfo.tcp_conn[i]->tcp_data_fd = clnet_fd; addr_cpy(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),&(elem->pinfo.local_addr)); addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),1,1,TCP_SOCKET); addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); continue; } else { perror("connect"); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect to remote addr\n", __FUNCTION__); exit(-1); } } else { break; } } } if(use_secure) { int try_again = 0; elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr),&try_again, connect_cycle++); if(!(elem->pinfo.tcp_conn[i]->tcp_data_ssl)) { if(try_again) { --elem->pinfo.tcp_conn_number; goto again; } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); exit(-1); } } if(turn_tcp_connection_bind(clnet_verbose, &(elem->pinfo), elem->pinfo.tcp_conn[i],0)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot BIND to tcp connection\n", __FUNCTION__); } else { socket_set_nonblocking(clnet_fd); struct event* ev = event_new(client_event_base,clnet_fd, EV_READ|EV_PERSIST,client_input_handler, elem); event_add(ev,NULL); elem->input_tcp_data_ev = ev; addr_debug_print(clnet_verbose, &(elem->pinfo.remote_addr), "TCP data network connected to"); } }
static void 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_TCP_SOCKET; if(no_tls) st = TCP_SOCKET; else if(no_tcp) st = TLS_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) { ioas->listener_server = server; 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.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 tcp or tls session\n"); } } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create ioa_socket from FD\n"); socket_closesocket(fd); } FUNCEND ; }