コード例 #1
0
ファイル: sip_timer.c プロジェクト: Archipov/android-client
/* Start Session Timers */
static void start_timer(pjsip_inv_session *inv)
{
    const pj_str_t UPDATE = { "UPDATE", 6 };
    pjsip_timer *timer = inv->timer;
    pj_time_val delay = {0};

    pj_assert(inv->timer->active == PJ_TRUE);

    stop_timer(inv);

    inv->timer->use_update =
	    (pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL,
				      &UPDATE) == PJSIP_DIALOG_CAP_SUPPORTED);
    if (!inv->timer->use_update) {
	/* INVITE always needs SDP */
	inv->timer->with_sdp = PJ_TRUE;
    }

    pj_timer_entry_init(&timer->timer,
			1,		    /* id */
			inv,		    /* user data */
			timer_cb);	    /* callback */
    
    /* Set delay based on role, refresher or refreshee */
    if ((timer->refresher == TR_UAC && inv->timer->role == PJSIP_ROLE_UAC) ||
	(timer->refresher == TR_UAS && inv->timer->role == PJSIP_ROLE_UAS))
    {
	/* Add refresher expire timer */
	pj_timer_entry_init(&timer->expire_timer,
			    REFRESHER_EXPIRE_TIMER_ID,	    /* id */
			    inv,			    /* user data */
			    timer_cb);			    /* callback */

	delay.sec = timer->setting.sess_expires;
	/* Schedule the timer */
	pjsip_endpt_schedule_timer(inv->dlg->endpt, &timer->expire_timer, 
				   &delay);

	/* Next refresh, the delay is half of session expire */
	delay.sec = timer->setting.sess_expires / 2;
    } else {
	/* Send BYE if no refresh received until this timer fired, delay
	 * is the minimum of 32 seconds and one third of the session interval
	 * before session expiration.
	 */
	delay.sec = timer->setting.sess_expires - 
		    timer->setting.sess_expires/3;
	delay.sec = PJ_MAX((long)timer->setting.sess_expires-32, delay.sec);
    }

    /* Schedule the timer */
    pjsip_endpt_schedule_timer(inv->dlg->endpt, &timer->timer, &delay);

    /* Update last refresh time */
    pj_gettimeofday(&timer->last_refresh);
}
コード例 #2
0
ファイル: transport_zrtp.c プロジェクト: Agostin/csipsimple
static int32_t zrtp_activateTimer(ZrtpContext* ctx, int32_t time)
{
    pj_time_val timeout;
    struct tp_zrtp *zrtp = (struct tp_zrtp*)ctx->userData;

    timeout.sec = time / 1000;
    timeout.msec = time % 1000;

    pj_timer_entry_init(&zrtp->timeoutEntry, 0, zrtp, &timer_callback);
    timer_add_entry(&zrtp->timeoutEntry, &timeout);

    return 1;
}
コード例 #3
0
ファイル: transport_zrtp.c プロジェクト: jresende/ZRTP4PJ
static int32_t zrtp_activateTimer(ZrtpContext* ctx, int32_t time)
{
    pj_time_val timeout;
    struct tp_zrtp *zrtp = (struct tp_zrtp*)ctx->userData;

    timeout.sec = time / 1000;
    timeout.msec = time % 1000;

    pj_timer_entry_init(&zrtp->timeoutEntry, 0, zrtp, &timer_callback);
#ifndef DYNAMIC_TIMER
    timer_add_entry(&zrtp->timeoutEntry, &timeout);
#else
    if(zrtp->timer_heap != NULL){
    	pj_timer_heap_schedule(zrtp->timer_heap, &zrtp->timeoutEntry, &timeout);
    }
#endif

    return 1;
}
コード例 #4
0
ファイル: flowtable.cpp プロジェクト: JimBunch/sprout
Flow::Flow(FlowTable* flow_table, pjsip_transport* transport, const pj_sockaddr* remote_addr) :
  _flow_table(flow_table),
  _transport(transport),
  _tp_state_listener_key(NULL),
  _remote_addr(*remote_addr),
  _token(),
  _authorized_ids(),
  _default_id(),
  _refs(1),
  _dialogs(0)
{
  // Create the lock for protecting the authorized_ids and default_id.
  pthread_mutex_init(&_flow_lock, NULL);

  // Create a random base64 encoded token for the flow.
  Utils::create_random_token(Flow::TOKEN_LENGTH, _token);

  if (PJSIP_TRANSPORT_IS_RELIABLE(_transport))
  {
    // We're adding a new reliable transport, so make sure it stays around
    // until we remove it from the map.
    pjsip_transport_add_ref(_transport);

    // Add a state listener so we find out when the flow is destroyed.
    pjsip_transport_add_state_listener(_transport,
                                       &on_transport_state_changed,
                                       this,
                                       &_tp_state_listener_key);
    LOG_DEBUG("Added transport listener for flow %p", this);
  }

  // Initialize the timer.
  pj_timer_entry_init(&_timer, PJ_FALSE, (void*)this, &on_timer_expiry);
  _timer.id = 0;

  // Start the timer as an idle timer.
  restart_timer(IDLE_TIMER, IDLE_TIMEOUT);
}
コード例 #5
0
ファイル: sip_timer.c プロジェクト: max3903/SFLphone
/* Start Session Timers */
static void start_timer(pjsip_inv_session *inv)
{
    pjsip_timer *timer = inv->timer;
    pj_time_val delay = {0};

    pj_assert(inv->timer->active == PJ_TRUE);

    stop_timer(inv);

    pj_timer_entry_init(&timer->timer,
			1,		    /* id */
			inv,		    /* user data */
			timer_cb);	    /* callback */
    
    /* Set delay based on role, refresher or refreshee */
    if ((timer->refresher == TR_UAC && inv->timer->role == PJSIP_ROLE_UAC) ||
	(timer->refresher == TR_UAS && inv->timer->role == PJSIP_ROLE_UAS))
    {
	/* Next refresh, the delay is half of session expire */
	delay.sec = timer->setting.sess_expires / 2;
    } else {
	/* Send BYE if no refresh received until this timer fired, delay
	 * is the minimum of 32 seconds and one third of the session interval
	 * before session expiration.
	 */
	delay.sec = timer->setting.sess_expires - 
		    timer->setting.sess_expires/3;
	delay.sec = PJ_MAX((long)timer->setting.sess_expires-32, delay.sec);
    }

    /* Schedule the timer */
    pjsip_endpt_schedule_timer(inv->dlg->endpt, &timer->timer, &delay);

    /* Update last refresh time */
    pj_gettimeofday(&timer->last_refresh);
}
コード例 #6
0
ファイル: allocation.c プロジェクト: RyanLee27/pjproject
/*
 * Create relay.
 */
static pj_status_t create_relay(pj_turn_srv *srv,
				pj_turn_allocation *alloc,
				const pj_stun_msg *msg,
				const alloc_request *req,
				pj_turn_relay_res *relay)
{
    enum { RETRY = 40 };
    pj_pool_t *pool = alloc->pool;
    int retry, retry_max, sock_type;
    pj_ioqueue_callback icb;
    int af, namelen;
    pj_stun_string_attr *sa;
    pj_status_t status;

    pj_bzero(relay, sizeof(*relay));

    relay->allocation = alloc;
    relay->tp.sock = PJ_INVALID_SOCKET;

    /* TODO: get the requested address family from somewhere */
    af = alloc->transport->listener->addr.addr.sa_family;

    /* Save realm */
    sa = (pj_stun_string_attr*)
	 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REALM, 0);
    PJ_ASSERT_RETURN(sa, PJ_EINVALIDOP);
    pj_strdup(pool, &relay->realm, &sa->value);

    /* Save username */
    sa = (pj_stun_string_attr*)
	 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USERNAME, 0);
    PJ_ASSERT_RETURN(sa, PJ_EINVALIDOP);
    pj_strdup(pool, &relay->user, &sa->value);

    /* Lifetime and timeout */
    relay->lifetime = req->lifetime;
    pj_timer_entry_init(&relay->timer, TIMER_ID_NONE, relay,
			&relay_timeout_cb);
    resched_timeout(alloc);

    /* Transport type */
    relay->hkey.tp_type = req->tp_type;

    /* Create the socket */
    if (req->tp_type == PJ_TURN_TP_UDP) {
	sock_type = pj_SOCK_DGRAM();
    } else if (req->tp_type == PJ_TURN_TP_TCP) {
	sock_type = pj_SOCK_STREAM();
    } else {
	pj_assert(!"Unknown transport");
	return PJ_EINVALIDOP;
    }

    status = pj_sock_socket(af, sock_type, 0, &relay->tp.sock);
    if (status != PJ_SUCCESS) {
	pj_bzero(relay, sizeof(*relay));
	return status;
    }

    /* Find suitable port for this allocation */
    if (req->rpp_port) {
	retry_max = 1;
    } else {
	retry_max = RETRY;
    }

    for (retry=0; retry<retry_max; ++retry) {
	pj_uint16_t port;
	pj_sockaddr bound_addr;

	pj_lock_acquire(srv->core.lock);

	if (req->rpp_port) {
	    port = (pj_uint16_t) req->rpp_port;
	} else if (req->tp_type == PJ_TURN_TP_UDP) {
	    port = (pj_uint16_t) srv->ports.next_udp++;
	    if (srv->ports.next_udp > srv->ports.max_udp)
		srv->ports.next_udp = srv->ports.min_udp;
	} else if (req->tp_type == PJ_TURN_TP_TCP) {
	    port = (pj_uint16_t) srv->ports.next_tcp++;
	    if (srv->ports.next_tcp > srv->ports.max_tcp)
		srv->ports.next_tcp = srv->ports.min_tcp;
	} else {
	    pj_assert(!"Invalid transport");
	    port = 0;
	}

	pj_lock_release(srv->core.lock);

	pj_sockaddr_init(af, &bound_addr, NULL, port);

	status = pj_sock_bind(relay->tp.sock, &bound_addr,
			      pj_sockaddr_get_len(&bound_addr));
	if (status == PJ_SUCCESS)
	    break;
    }

    if (status != PJ_SUCCESS) {
	/* Unable to allocate port */
	PJ_LOG(4,(THIS_FILE, "Unable to allocate relay, giving up: err %d",
		  status));
	pj_sock_close(relay->tp.sock);
	relay->tp.sock = PJ_INVALID_SOCKET;
	return status;
    }

    /* Init relay key */
    namelen = sizeof(relay->hkey.addr);
    status = pj_sock_getsockname(relay->tp.sock, &relay->hkey.addr, &namelen);
    if (status != PJ_SUCCESS) {
	PJ_LOG(4,(THIS_FILE, "pj_sock_getsockname() failed: err %d",
		  status));
	pj_sock_close(relay->tp.sock);
	relay->tp.sock = PJ_INVALID_SOCKET;
	return status;
    }
    if (!pj_sockaddr_has_addr(&relay->hkey.addr)) {
	pj_sockaddr_copy_addr(&relay->hkey.addr,
			      &alloc->transport->listener->addr);
    }
    if (!pj_sockaddr_has_addr(&relay->hkey.addr)) {
	pj_sockaddr tmp_addr;
	pj_gethostip(af, &tmp_addr);
	pj_sockaddr_copy_addr(&relay->hkey.addr, &tmp_addr);
    }

    /* Init ioqueue */
    pj_bzero(&icb, sizeof(icb));
    icb.on_read_complete = &on_rx_from_peer;

    status = pj_ioqueue_register_sock(pool, srv->core.ioqueue, relay->tp.sock,
				      relay, &icb, &relay->tp.key);
    if (status != PJ_SUCCESS) {
	PJ_LOG(4,(THIS_FILE, "pj_ioqueue_register_sock() failed: err %d",
		  status));
	pj_sock_close(relay->tp.sock);
	relay->tp.sock = PJ_INVALID_SOCKET;
	return status;
    }

    /* Kick off pending read operation */
    pj_ioqueue_op_key_init(&relay->tp.read_key, sizeof(relay->tp.read_key));
    on_rx_from_peer(relay->tp.key, &relay->tp.read_key, 0);

    /* Done */
    return PJ_SUCCESS;
}
コード例 #7
0
ファイル: turn_sock.c プロジェクト: 0x0B501E7E/pjproject
/*
 * Create.
 */
PJ_DEF(pj_status_t) pj_turn_sock_create(pj_stun_config *cfg,
					int af,
					pj_turn_tp_type conn_type,
					const pj_turn_sock_cb *cb,
					const pj_turn_sock_cfg *setting,
					void *user_data,
					pj_turn_sock **p_turn_sock)
{
    pj_turn_sock *turn_sock;
    pj_turn_session_cb sess_cb;
    pj_turn_sock_cfg default_setting;
    pj_pool_t *pool;
    const char *name_tmpl;
    pj_status_t status;

    PJ_ASSERT_RETURN(cfg && p_turn_sock, PJ_EINVAL);
    PJ_ASSERT_RETURN(af==pj_AF_INET() || af==pj_AF_INET6(), PJ_EINVAL);
    PJ_ASSERT_RETURN(conn_type!=PJ_TURN_TP_TCP || PJ_HAS_TCP, PJ_EINVAL);

    if (!setting) {
	pj_turn_sock_cfg_default(&default_setting);
	setting = &default_setting;
    }

    switch (conn_type) {
    case PJ_TURN_TP_UDP:
	name_tmpl = "udprel%p";
	break;
    case PJ_TURN_TP_TCP:
	name_tmpl = "tcprel%p";
	break;
    default:
	PJ_ASSERT_RETURN(!"Invalid TURN conn_type", PJ_EINVAL);
	name_tmpl = "tcprel%p";
	break;
    }

    /* Create and init basic data structure */
    pool = pj_pool_create(cfg->pf, name_tmpl, PJNATH_POOL_LEN_TURN_SOCK,
			  PJNATH_POOL_INC_TURN_SOCK, NULL);
    turn_sock = PJ_POOL_ZALLOC_T(pool, pj_turn_sock);
    turn_sock->pool = pool;
    turn_sock->obj_name = pool->obj_name;
    turn_sock->user_data = user_data;
    turn_sock->af = af;
    turn_sock->conn_type = conn_type;

    /* Copy STUN config (this contains ioqueue, timer heap, etc.) */
    pj_memcpy(&turn_sock->cfg, cfg, sizeof(*cfg));

    /* Copy setting (QoS parameters etc */
    pj_memcpy(&turn_sock->setting, setting, sizeof(*setting));

    /* Set callback */
    if (cb) {
	pj_memcpy(&turn_sock->cb, cb, sizeof(*cb));
    }

    /* Session lock */
    if (setting && setting->grp_lock) {
	turn_sock->grp_lock = setting->grp_lock;
    } else {
	status = pj_grp_lock_create(pool, NULL, &turn_sock->grp_lock);
	if (status != PJ_SUCCESS) {
	    pj_pool_release(pool);
	    return status;
	}
    }

    pj_grp_lock_add_ref(turn_sock->grp_lock);
    pj_grp_lock_add_handler(turn_sock->grp_lock, pool, turn_sock,
                            &turn_sock_on_destroy);

    /* Init timer */
    pj_timer_entry_init(&turn_sock->timer, TIMER_NONE, turn_sock, &timer_cb);

    /* Init TURN session */
    pj_bzero(&sess_cb, sizeof(sess_cb));
    sess_cb.on_send_pkt = &turn_on_send_pkt;
    sess_cb.on_channel_bound = &turn_on_channel_bound;
    sess_cb.on_rx_data = &turn_on_rx_data;
    sess_cb.on_state = &turn_on_state;
    status = pj_turn_session_create(cfg, pool->obj_name, af, conn_type,
                                    turn_sock->grp_lock, &sess_cb, 0,
                                    turn_sock, &turn_sock->sess);
    if (status != PJ_SUCCESS) {
	destroy(turn_sock);
	return status;
    }

    /* Note: socket and ioqueue will be created later once the TURN server
     * has been resolved.
     */

    *p_turn_sock = turn_sock;
    return PJ_SUCCESS;
}
コード例 #8
0
ファイル: tcp_session.c プロジェクト: themiron/asuswrt-merlin
/*
 * Create TCP client session.
 */
PJ_DEF(pj_status_t) pj_tcp_session_create( const pj_stun_config *cfg,
        const char *name,
        int af,
        const pj_tcp_session_cb *cb,
        unsigned options,
        void *user_data,
        pj_stun_session *default_stun,
        pj_tcp_session **p_sess,
        int sess_idx,
        int check_idx)
{
    pj_pool_t *pool;
    pj_tcp_session *sess;
    pj_stun_session_cb stun_cb;
    pj_lock_t *null_lock;
    pj_status_t status;

    PJ_ASSERT_RETURN(cfg && cfg->pf && cb && p_sess, PJ_EINVAL);
    PJ_ASSERT_RETURN(cb->on_send_pkt, PJ_EINVAL);

    PJ_UNUSED_ARG(options);

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

    /* Allocate and create TCP session */
    pool = pj_pool_create(cfg->pf, name, PJNATH_POOL_LEN_TCP_SESS,
                          PJNATH_POOL_INC_TCP_SESS, NULL);
    sess = PJ_POOL_ZALLOC_T(pool, pj_tcp_session);
    sess->pool = pool;
    sess->obj_name = pool->obj_name;
    sess->timer_heap = cfg->timer_heap;
    sess->af = (pj_uint16_t)af;
    sess->ka_interval = PJ_TCP_KEEP_ALIVE_SEC;
    sess->user_data = user_data;
    sess->sess_idx = sess_idx;
    sess->check_idx = check_idx;

    /* Copy STUN session */
    pj_memcpy(&sess->stun_cfg, cfg, sizeof(pj_stun_config));

    /* Copy callback */
    pj_memcpy(&sess->cb, cb, sizeof(*cb));

    /* Session lock */
    status = pj_lock_create_recursive_mutex(pool, sess->obj_name,
                                            &sess->lock);
    if (status != PJ_SUCCESS) {
        do_destroy(sess);
        return status;
    }

    /* Timer */
    pj_timer_entry_init(&sess->timer, TIMER_NONE, sess, &on_timer_event);

    //DEAN
    if (default_stun) {
        sess->stun = default_stun;
    } else {
        /* Create STUN session */
        pj_bzero(&stun_cb, sizeof(stun_cb));
        stun_cb.on_send_msg = &stun_on_send_msg;
#if 0
        stun_cb.on_request_complete = &stun_on_request_complete;
#else
        stun_cb.on_request_complete = &on_stun_request_complete;
#endif
        stun_cb.on_rx_request = &on_stun_rx_request;
        stun_cb.on_rx_indication = &on_stun_rx_indication;

        status = pj_stun_session_create2(&sess->stun_cfg, sess->obj_name, &stun_cb,
                                         PJ_FALSE, NULL, &sess->stun, PJ_TRUE, sess);
        if (status != PJ_SUCCESS) {
            do_destroy(sess);
            return status;
        }
    }


    /* Attach ourself to STUN session */
    pj_stun_session_set_user_data(sess->stun, pj_tcp_sock_get_tsd(user_data));

    /* Replace mutex in STUN session with a NULL mutex, since access to
     * STUN session is serialized.
     */
    status = pj_lock_create_null_mutex(pool, name, &null_lock);
    if (status != PJ_SUCCESS) {
        do_destroy(sess);
        return status;
    }
    pj_stun_session_set_lock(sess->stun, null_lock, PJ_TRUE);

    /* Done */

    PJ_LOG(4,(sess->obj_name, "TCP client session created"));

    *p_sess = sess;
    return PJ_SUCCESS;
}