Esempio n. 1
0
/*
 * pjsip_udp_transport_attach()
 *
 * Attach UDP socket and start transport.
 */
static pj_status_t transport_attach( pjsip_endpoint *endpt,
				     pjsip_transport_type_e type,
				     pj_sock_t sock,
				     const pjsip_host_port *a_name,
				     unsigned async_cnt,
				     pjsip_transport **p_transport)
{
    pj_pool_t *pool;
    struct udp_transport *tp;
    const char *format, *ipv6_quoteb, *ipv6_quotee;
    unsigned i;
    pj_status_t status;

    PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0,
		     PJ_EINVAL);

    /* Object name. */
    if (type & PJSIP_TRANSPORT_IPV6) {
	format = "udpv6%p";
	ipv6_quoteb = "[";
	ipv6_quotee = "]";
    } else {
	format = "udp%p";
	ipv6_quoteb = ipv6_quotee = "";
    }

    /* Create pool. */
    pool = pjsip_endpt_create_pool(endpt, format, PJSIP_POOL_LEN_TRANSPORT, 
				   PJSIP_POOL_INC_TRANSPORT);
    if (!pool)
	return PJ_ENOMEM;

    /* Create the UDP transport object. */
    tp = PJ_POOL_ZALLOC_T(pool, struct udp_transport);

    /* Save pool. */
    tp->base.pool = pool;

    pj_memcpy(tp->base.obj_name, pool->obj_name, PJ_MAX_OBJ_NAME);

    /* Init reference counter. */
    status = pj_atomic_create(pool, 0, &tp->base.ref_cnt);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Init lock. */
    status = pj_lock_create_recursive_mutex(pool, pool->obj_name, 
					    &tp->base.lock);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Set type. */
    tp->base.key.type = type;

    /* Remote address is left zero (except the family) */
    tp->base.key.rem_addr.addr.sa_family = (pj_uint16_t)
	((type & PJSIP_TRANSPORT_IPV6) ? pj_AF_INET6() : pj_AF_INET());

    /* Type name. */
    tp->base.type_name = "UDP";

    /* Transport flag */
    tp->base.flag = pjsip_transport_get_flag_from_type(type);


    /* Length of addressess. */
    tp->base.addr_len = sizeof(tp->base.local_addr);

    /* Init local address. */
    status = pj_sock_getsockname(sock, &tp->base.local_addr, 
				 &tp->base.addr_len);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Init remote name. */
    if (type == PJSIP_TRANSPORT_UDP)
	tp->base.remote_name.host = pj_str("0.0.0.0");
    else
	tp->base.remote_name.host = pj_str("::0");
    tp->base.remote_name.port = 0;

    /* Init direction */
    tp->base.dir = PJSIP_TP_DIR_NONE;

    /* Set endpoint. */
    tp->base.endpt = endpt;

    /* Transport manager and timer will be initialized by tpmgr */

    /* Attach socket and assign name. */
    udp_set_socket(tp, sock, a_name);

    /* Register to ioqueue */
    status = register_to_ioqueue(tp);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Set functions. */
    tp->base.send_msg = &udp_send_msg;
    tp->base.do_shutdown = &udp_shutdown;
    tp->base.destroy = &udp_destroy;

    /* This is a permanent transport, so we initialize the ref count
     * to one so that transport manager don't destroy this transport
     * when there's no user!
     */
    pj_atomic_inc(tp->base.ref_cnt);

    /* Register to transport manager. */
    tp->base.tpmgr = pjsip_endpt_get_tpmgr(endpt);
    status = pjsip_transport_register( tp->base.tpmgr, (pjsip_transport*)tp);
    if (status != PJ_SUCCESS)
	goto on_error;


    /* Create rdata and put it in the array. */
    tp->rdata_cnt = 0;
    tp->rdata = (pjsip_rx_data**)
    		pj_pool_calloc(tp->base.pool, async_cnt, 
			       sizeof(pjsip_rx_data*));
    for (i=0; i<async_cnt; ++i) {
	pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p", 
							PJSIP_POOL_RDATA_LEN,
							PJSIP_POOL_RDATA_INC);
	if (!rdata_pool) {
	    pj_atomic_set(tp->base.ref_cnt, 0);
	    pjsip_transport_destroy(&tp->base);
	    return PJ_ENOMEM;
	}

	init_rdata(tp, i, rdata_pool, NULL);
	tp->rdata_cnt++;
    }

    /* Start reading the ioqueue. */
    status = start_async_read(tp);
    if (status != PJ_SUCCESS) {
	pjsip_transport_destroy(&tp->base);
	return status;
    }

    /* Done. */
    if (p_transport)
	*p_transport = &tp->base;
    
    PJ_LOG(4,(tp->base.obj_name, 
	      "SIP %s started, published address is %s%.*s%s:%d",
	      pjsip_transport_get_type_desc((pjsip_transport_type_e)tp->base.key.type),
	      ipv6_quoteb,
	      (int)tp->base.local_name.host.slen,
	      tp->base.local_name.host.ptr,
	      ipv6_quotee,
	      tp->base.local_name.port));

    return PJ_SUCCESS;

on_error:
    udp_destroy((pjsip_transport*)tp);
    return status;
}
Esempio n. 2
0
    //
    // Set the value.
    //
    void set(pj_atomic_value_t val)
    {
	pj_atomic_set(var_, val);
    }