Exemple #1
0
static pj_status_t create_client(pj_stun_config *cfg,
				 struct stun_client **p_client,
				 pj_bool_t destroy_on_err)
{
    pj_pool_t *pool;
    struct stun_client *client;
    pj_stun_sock_cfg sock_cfg;
    pj_stun_sock_cb cb;
    pj_status_t status;

    pool = pj_pool_create(mem, "test", 512, 512, NULL);
    client = PJ_POOL_ZALLOC_T(pool, struct stun_client);
    client->pool = pool;

    pj_stun_sock_cfg_default(&sock_cfg);

    pj_bzero(&cb, sizeof(cb));
    cb.on_status = &stun_sock_on_status;
    cb.on_rx_data = &stun_sock_on_rx_data;
    status = pj_stun_sock_create(cfg, NULL, pj_AF_INET(), &cb,
				 &sock_cfg, client, &client->sock);
    if (status != PJ_SUCCESS) {
	app_perror("   pj_stun_sock_create()", status);
	pj_pool_release(pool);
	return status;
    }

    pj_stun_sock_set_user_data(client->sock, client);

    pj_ioqueue_op_key_init(&client->send_key, sizeof(client->send_key));

    client->destroy_on_err = destroy_on_err;

    *p_client = client;

    return PJ_SUCCESS;
}
static int init()
{
    int i;
    pj_status_t status;

    CHECK( pj_init() );
    CHECK( pjlib_util_init() );
    CHECK( pjnath_init() );

    /* Check that server is specified */
    if (!o.srv_addr) {
	printf("Error: server must be specified\n");
	return PJ_EINVAL;
    }

    pj_caching_pool_init(&g.cp, &pj_pool_factory_default_policy, 0);

    g.pool = pj_pool_create(&g.cp.factory, "main", 1000, 1000, NULL);

    /* Init global STUN config */
    pj_stun_config_init(&g.stun_config, &g.cp.factory, 0, NULL, NULL);

    /* Create global timer heap */
    CHECK( pj_timer_heap_create(g.pool, 1000, &g.stun_config.timer_heap) );

    /* Create global ioqueue */
    CHECK( pj_ioqueue_create(g.pool, 16, &g.stun_config.ioqueue) );

    /* 
     * Create peers
     */
    for (i=0; i<(int)PJ_ARRAY_SIZE(g.peer); ++i) {
	pj_stun_sock_cb stun_sock_cb;
	char name[] = "peer0";
	pj_uint16_t port;
	pj_stun_sock_cfg ss_cfg;
	pj_str_t server;

	pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb));
	stun_sock_cb.on_rx_data = &stun_sock_on_rx_data;
	stun_sock_cb.on_status = &stun_sock_on_status;

	g.peer[i].mapped_addr.addr.sa_family = pj_AF_INET();

	pj_stun_sock_cfg_default(&ss_cfg);
#if 1
	/* make reading the log easier */
	ss_cfg.ka_interval = 300;
#endif

	name[strlen(name)-1] = '0'+i;
	status = pj_stun_sock_create(&g.stun_config, name, pj_AF_INET(), 
				     &stun_sock_cb, &ss_cfg,
				     &g.peer[i], &g.peer[i].stun_sock);
	if (status != PJ_SUCCESS) {
	    my_perror("pj_stun_sock_create()", status);
	    return status;
	}

	if (o.stun_server) {
	    server = pj_str(o.stun_server);
	    port = PJ_STUN_PORT;
	} else {
	    server = pj_str(o.srv_addr);
	    port = (pj_uint16_t)(o.srv_port?atoi(o.srv_port):PJ_STUN_PORT);
	}
	status = pj_stun_sock_start(g.peer[i].stun_sock, &server, 
				    port,  NULL);
	if (status != PJ_SUCCESS) {
	    my_perror("pj_stun_sock_start()", status);
	    return status;
	}
    }

    /* Start the worker thread */
    CHECK( pj_thread_create(g.pool, "stun", &worker_thread, NULL, 0, 0, &g.thread) );


    return PJ_SUCCESS;
}
Exemple #3
0
/*
 * Create the STUN transport using the specified configuration.
 */
PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg,
					 const char *name,
					 int af,
					 const pj_stun_sock_cb *cb,
					 const pj_stun_sock_cfg *cfg,
					 void *user_data,
					 pj_stun_sock **p_stun_sock)
{
    pj_pool_t *pool;
    pj_stun_sock *stun_sock;
    pj_stun_sock_cfg default_cfg;
    unsigned i;
    pj_status_t status;

    PJ_ASSERT_RETURN(stun_cfg && cb && p_stun_sock, PJ_EINVAL);
    PJ_ASSERT_RETURN(af==pj_AF_INET()||af==pj_AF_INET6(), PJ_EAFNOTSUP);
    PJ_ASSERT_RETURN(!cfg || pj_stun_sock_cfg_is_valid(cfg), PJ_EINVAL);
    PJ_ASSERT_RETURN(cb->on_status, PJ_EINVAL);

    status = pj_stun_config_check_valid(stun_cfg);
    if (status != PJ_SUCCESS)
	return status;

    if (name == NULL)
	name = "stuntp%p";

    if (cfg == NULL) {
	pj_stun_sock_cfg_default(&default_cfg);
	cfg = &default_cfg;
    }


    /* Create structure */
    pool = pj_pool_create(stun_cfg->pf, name, 256, 512, NULL);
    stun_sock = PJ_POOL_ZALLOC_T(pool, pj_stun_sock);
    stun_sock->pool = pool;
    stun_sock->obj_name = pool->obj_name;
    stun_sock->user_data = user_data;
    stun_sock->af = af;
    stun_sock->sock_fd = PJ_INVALID_SOCKET;
    pj_memcpy(&stun_sock->stun_cfg, stun_cfg, sizeof(*stun_cfg));
    pj_memcpy(&stun_sock->cb, cb, sizeof(*cb));

    stun_sock->ka_interval = cfg->ka_interval;
    if (stun_sock->ka_interval == 0)
	stun_sock->ka_interval = PJ_STUN_KEEP_ALIVE_SEC;

    /* Create socket and bind socket */
    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &stun_sock->sock_fd);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Apply QoS, if specified */
    status = pj_sock_apply_qos2(stun_sock->sock_fd, cfg->qos_type,
				&cfg->qos_params, 2, stun_sock->obj_name,
				NULL);
    if (status != PJ_SUCCESS && !cfg->qos_ignore_error)
	goto on_error;

    /* Bind socket */
    if (pj_sockaddr_has_addr(&cfg->bound_addr)) {
	status = pj_sock_bind(stun_sock->sock_fd, &cfg->bound_addr,
			      pj_sockaddr_get_len(&cfg->bound_addr));
    } else {
	pj_sockaddr bound_addr;

	pj_sockaddr_init(af, &bound_addr, NULL, 0);
	status = pj_sock_bind(stun_sock->sock_fd, &bound_addr,
			      pj_sockaddr_get_len(&bound_addr));
    }

    if (status != PJ_SUCCESS)
	goto on_error;

    /* Create more useful information string about this transport */
#if 0
    {
	pj_sockaddr bound_addr;
	int addr_len = sizeof(bound_addr);

	status = pj_sock_getsockname(stun_sock->sock_fd, &bound_addr, 
				     &addr_len);
	if (status != PJ_SUCCESS)
	    goto on_error;

	stun_sock->info = pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+10);
	pj_sockaddr_print(&bound_addr, stun_sock->info, 
			  PJ_INET6_ADDRSTRLEN, 3);
    }
#endif

    /* Init active socket configuration */
    {
	pj_activesock_cfg activesock_cfg;
	pj_activesock_cb activesock_cb;

	pj_activesock_cfg_default(&activesock_cfg);
	activesock_cfg.async_cnt = cfg->async_cnt;
	activesock_cfg.concurrency = 0;

	/* Create the active socket */
	pj_bzero(&activesock_cb, sizeof(activesock_cb));
	activesock_cb.on_data_recvfrom = &on_data_recvfrom;
	activesock_cb.on_data_sent = &on_data_sent;
	status = pj_activesock_create(pool, stun_sock->sock_fd, 
				      pj_SOCK_DGRAM(), 
				      &activesock_cfg, stun_cfg->ioqueue,
				      &activesock_cb, stun_sock,
				      &stun_sock->active_sock);
	if (status != PJ_SUCCESS)
	    goto on_error;

	/* Start asynchronous read operations */
	status = pj_activesock_start_recvfrom(stun_sock->active_sock, pool,
					      cfg->max_pkt_size, 0);
	if (status != PJ_SUCCESS)
	    goto on_error;

	/* Init send keys */
	pj_ioqueue_op_key_init(&stun_sock->send_key, 
			       sizeof(stun_sock->send_key));
	pj_ioqueue_op_key_init(&stun_sock->int_send_key,
			       sizeof(stun_sock->int_send_key));
    }

    /* Create STUN session */
    {
	pj_stun_session_cb sess_cb;

	pj_bzero(&sess_cb, sizeof(sess_cb));
	sess_cb.on_request_complete = &sess_on_request_complete;
	sess_cb.on_send_msg = &sess_on_send_msg;
	status = pj_stun_session_create(&stun_sock->stun_cfg, 
					stun_sock->obj_name,
					&sess_cb, PJ_FALSE, 
					&stun_sock->stun_sess);
	if (status != PJ_SUCCESS)
	    goto on_error;
    }

    /* Associate us with the STUN session */
    pj_stun_session_set_user_data(stun_sock->stun_sess, stun_sock);

    /* Initialize random numbers to be used as STUN transaction ID for
     * outgoing Binding request. We use the 80bit number to distinguish
     * STUN messages we sent with STUN messages that the application sends.
     * The last 16bit value in the array is a counter.
     */
    for (i=0; i<PJ_ARRAY_SIZE(stun_sock->tsx_id); ++i) {
	stun_sock->tsx_id[i] = (pj_uint16_t) pj_rand();
    }
    stun_sock->tsx_id[5] = 0;


    /* Init timer entry */
    stun_sock->ka_timer.cb = &ka_timer_cb;
    stun_sock->ka_timer.user_data = stun_sock;

    /* Done */
    *p_stun_sock = stun_sock;
    return PJ_SUCCESS;

on_error:
    pj_stun_sock_destroy(stun_sock);
    return status;
}
Exemple #4
0
/*
 * Create the STUN transport using the specified configuration.
 */
PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg,
					 const char *name,
					 int af,
					 const pj_stun_sock_cb *cb,
					 const pj_stun_sock_cfg *cfg,
					 void *user_data,
					 pj_stun_sock **p_stun_sock)
{
    pj_pool_t *pool;
    pj_stun_sock *stun_sock;
    pj_stun_sock_cfg default_cfg;
    pj_sockaddr bound_addr;
    unsigned i;
    pj_uint16_t max_bind_retry;
    pj_status_t status;

    PJ_ASSERT_RETURN(stun_cfg && cb && p_stun_sock, PJ_EINVAL);
    PJ_ASSERT_RETURN(af==pj_AF_INET()||af==pj_AF_INET6(), PJ_EAFNOTSUP);
    PJ_ASSERT_RETURN(!cfg || pj_stun_sock_cfg_is_valid(cfg), PJ_EINVAL);
    PJ_ASSERT_RETURN(cb->on_status, PJ_EINVAL);

    status = pj_stun_config_check_valid(stun_cfg);
    if (status != PJ_SUCCESS)
	return status;

    if (name == NULL)
	name = "stuntp%p";

    if (cfg == NULL) {
	pj_stun_sock_cfg_default(&default_cfg);
	cfg = &default_cfg;
    }


    /* Create structure */
    pool = pj_pool_create(stun_cfg->pf, name, 256, 512, NULL);
    stun_sock = PJ_POOL_ZALLOC_T(pool, pj_stun_sock);
    stun_sock->pool = pool;
    stun_sock->obj_name = pool->obj_name;
    stun_sock->user_data = user_data;
    stun_sock->af = af;
    stun_sock->sock_fd = PJ_INVALID_SOCKET;
    pj_memcpy(&stun_sock->stun_cfg, stun_cfg, sizeof(*stun_cfg));
    pj_memcpy(&stun_sock->cb, cb, sizeof(*cb));

    stun_sock->ka_interval = cfg->ka_interval;
    		stun_sock->timerstat = cfg->timerstat;
    if (stun_sock->ka_interval == 0)
	stun_sock->ka_interval = PJ_STUN_KEEP_ALIVE_SEC;
    printf(": cfg->stunProtocol=%d\n", cfg->stunProtocol);
    printf("%s", cfg->timerstat ? "SBR keepalive enabled\n": "SBR keepalive disabled\n");

    if (cfg->grp_lock) {
	stun_sock->grp_lock = cfg->grp_lock;
    } else {
	status = pj_grp_lock_create(pool, NULL, &stun_sock->grp_lock);
	if (status != PJ_SUCCESS) {
	    pj_pool_release(pool);
	    return status;
	}
    }

    pj_grp_lock_add_ref(stun_sock->grp_lock);
    pj_grp_lock_add_handler(stun_sock->grp_lock, pool, stun_sock,
			    &stun_sock_destructor);

    /* Create socket and bind socket */
//    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &stun_sock->sock_fd);
    if(cfg->stunProtocol == 1)
    status = pj_sock_socket(af, PJ_SOCK_STREAM, 0, &stun_sock->sock_fd);
    else
    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &stun_sock->sock_fd);
    if (status != PJ_SUCCESS)
	goto on_error;
	
    /* Apply QoS, if specified */
    status = pj_sock_apply_qos2(stun_sock->sock_fd, cfg->qos_type,
				&cfg->qos_params, 2, stun_sock->obj_name,
				NULL);
    if (status != PJ_SUCCESS && !cfg->qos_ignore_error)
	goto on_error;

    /* Apply socket buffer size */
    if (cfg->so_rcvbuf_size > 0) {
	unsigned sobuf_size = cfg->so_rcvbuf_size;
	status = pj_sock_setsockopt_sobuf(stun_sock->sock_fd, pj_SO_RCVBUF(),
					  PJ_TRUE, &sobuf_size);
	if (status != PJ_SUCCESS) {
	    pj_perror(3, stun_sock->obj_name, status,
		      "Failed setting SO_RCVBUF");
	} else {
	    if (sobuf_size < cfg->so_rcvbuf_size) {
		PJ_LOG(4, (stun_sock->obj_name, 
			   "Warning! Cannot set SO_RCVBUF as configured, "
			   "now=%d, configured=%d",
			   sobuf_size, cfg->so_rcvbuf_size));
	    } else {
		PJ_LOG(5, (stun_sock->obj_name, "SO_RCVBUF set to %d",
			   sobuf_size));
	    }
	}
    }
    if (cfg->so_sndbuf_size > 0) {
	unsigned sobuf_size = cfg->so_sndbuf_size;
	status = pj_sock_setsockopt_sobuf(stun_sock->sock_fd, pj_SO_SNDBUF(),
					  PJ_TRUE, &sobuf_size);
	if (status != PJ_SUCCESS) {
	    pj_perror(3, stun_sock->obj_name, status,
		      "Failed setting SO_SNDBUF");
	} else {
	    if (sobuf_size < cfg->so_sndbuf_size) {
		PJ_LOG(4, (stun_sock->obj_name, 
			   "Warning! Cannot set SO_SNDBUF as configured, "
			   "now=%d, configured=%d",
			   sobuf_size, cfg->so_sndbuf_size));
	    } else {
		PJ_LOG(5, (stun_sock->obj_name, "SO_SNDBUF set to %d",
			   sobuf_size));
	    }
	}
    }

#if 1
    /* Bind socket */
    max_bind_retry = MAX_BIND_RETRY;
    if (cfg->port_range && cfg->port_range < max_bind_retry)
	max_bind_retry = cfg->port_range;
    pj_sockaddr_init(af, &bound_addr, NULL, 0);
    if (cfg->bound_addr.addr.sa_family == pj_AF_INET() || 
	cfg->bound_addr.addr.sa_family == pj_AF_INET6())
    {
	pj_sockaddr_cp(&bound_addr, &cfg->bound_addr);
    }
    status = pj_sock_bind_random(stun_sock->sock_fd, &bound_addr,
				 cfg->port_range, max_bind_retry);
    if (status != PJ_SUCCESS)
	goto on_error;
#endif

    /* Create more useful information string about this transport */
#if 0
    {
	pj_sockaddr bound_addr;
	int addr_len = sizeof(bound_addr);

	status = pj_sock_getsockname(stun_sock->sock_fd, &bound_addr, 
				     &addr_len);
	if (status != PJ_SUCCESS)
	    goto on_error;

	stun_sock->info = pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+10);
	pj_sockaddr_print(&bound_addr, stun_sock->info, 
			  PJ_INET6_ADDRSTRLEN, 3);
    }
#endif

    /* Init active socket configuration */
    {
	pj_activesock_cfg activesock_cfg;
	pj_activesock_cb activesock_cb;

	pj_activesock_cfg_default(&activesock_cfg);
	activesock_cfg.grp_lock = stun_sock->grp_lock;
	activesock_cfg.async_cnt = cfg->async_cnt;
	activesock_cfg.concurrency = 0;

	/* Create the active socket */
	pj_bzero(&activesock_cb, sizeof(activesock_cb));
	activesock_cb.on_data_recvfrom = &on_data_recvfrom;
	activesock_cb.on_data_sent = &on_data_sent;
        if(cfg->stunProtocol == 1)
	{
	status = pj_activesock_create(pool, stun_sock->sock_fd, 
				      PJ_SOCK_STREAM, 
				      &activesock_cfg, stun_cfg->ioqueue,
				      &activesock_cb, stun_sock,
				      &stun_sock->active_sock);
	}
	else
	{
	    status = pj_activesock_create(pool, stun_sock->sock_fd, 
				      pj_SOCK_DGRAM(), 		//nish
				      &activesock_cfg, stun_cfg->ioqueue,
				      &activesock_cb, stun_sock,
				      &stun_sock->active_sock);
	}

	if (status != PJ_SUCCESS)
	    goto on_error;
        if(cfg->stunProtocol == 1)
	{
		stun_sock->srv_addr.addr.sa_family = AF_INET;
		stun_sock->srv_addr.ipv4.sin_port= pj_htons(cfg->sin_port);
		stun_sock->srv_addr.ipv4.sin_addr = (cfg->sin_addr);

		status=pj_activesock_start_connect(stun_sock->active_sock, 
				pool,
				&(stun_sock->srv_addr), 
				pj_sockaddr_get_len(&(stun_sock->srv_addr)));

		if (status == PJ_SUCCESS) {
			printf("actie sock connect succesful");
		}
	}

	
	/* Start asynchronous read operations */
	status = pj_activesock_start_recvfrom(stun_sock->active_sock, pool,
					      cfg->max_pkt_size, 0);
	if (status != PJ_SUCCESS)
	    goto on_error;

	/* Init send keys */
	pj_ioqueue_op_key_init(&stun_sock->send_key, 
			       sizeof(stun_sock->send_key));
	pj_ioqueue_op_key_init(&stun_sock->int_send_key,
			       sizeof(stun_sock->int_send_key));
    }

    /* Create STUN session */
    {
	pj_stun_session_cb sess_cb;

	pj_bzero(&sess_cb, sizeof(sess_cb));
	sess_cb.on_request_complete = &sess_on_request_complete;
	sess_cb.on_send_msg = &sess_on_send_msg;
//	stun_sock->stunProtocol = 1; //FIXME: cfg->stunProtocol;
//	stun_sock->stunProtocol = 0; //FIXME: cfg->stunProtocol;
	printf(" stun_sock->stunProtocol=%d\n", stun_sock->stunProtocol);
	status = pj_stun_session_create(&stun_sock->stun_cfg, 
					stun_sock->obj_name,
					&sess_cb, PJ_FALSE, 
					stun_sock->grp_lock,
					&stun_sock->stun_sess);
	if (status != PJ_SUCCESS)
	    goto on_error;
    }

    /* Associate us with the STUN session */
    pj_stun_session_set_user_data(stun_sock->stun_sess, stun_sock);

    /* Initialize random numbers to be used as STUN transaction ID for
     * outgoing Binding request. We use the 80bit number to distinguish
     * STUN messages we sent with STUN messages that the application sends.
     * The last 16bit value in the array is a counter.
     */
    for (i=0; i<PJ_ARRAY_SIZE(stun_sock->tsx_id); ++i) {
	stun_sock->tsx_id[i] = (pj_uint16_t) pj_rand();
    }
    stun_sock->tsx_id[5] = 0;


    /* Init timer entry */
    stun_sock->ka_timer.cb = &ka_timer_cb;
    stun_sock->ka_timer.user_data = stun_sock;

    /* Done */
    *p_stun_sock = stun_sock;
    return PJ_SUCCESS;

on_error:
    pj_stun_sock_destroy(stun_sock);
    return status;
}