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;
}
示例#4
0
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;
}
示例#6
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;
}
示例#7
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));
}
示例#8
0
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.";
    }
}
示例#9
0
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*) &lt, 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;
}
示例#10
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;
}
示例#11
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");
	}
}
示例#12
0
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	;
}