⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ice_strans.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    comp = ice_st->comp[comp_id-1];
    return add_cand(ice_st, comp, comp_id, type, local_pref, addr, 
		    set_default);
}


PJ_DEF(pj_status_t) pj_ice_strans_get_comps_status(pj_ice_strans *ice_st)
{
    unsigned i;
    pj_status_t worst = PJ_SUCCESS;

    for (i=0; i<ice_st->comp_cnt; ++i) {
	pj_ice_strans_comp *comp = ice_st->comp[i];

	if (comp->last_status == PJ_SUCCESS) {
	    /* okay */
	} else if (comp->pending_cnt && worst==PJ_SUCCESS) {
	    worst = PJ_EPENDING;
	    break;
	} else if (comp->last_status != PJ_SUCCESS) {
	    worst = comp->last_status;
	    break;
	}

	if (worst != PJ_SUCCESS)
	    break;
    }

    return worst;
}

/*
 * Create ICE!
 */
PJ_DEF(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st,
					   pj_ice_sess_role role,
					   const pj_str_t *local_ufrag,
					   const pj_str_t *local_passwd)
{
    pj_status_t status;
    unsigned i;
    pj_ice_sess_cb ice_cb;
    const pj_uint8_t srflx_prio[4] = { 100, 126, 110, 0 };

    /* Check arguments */
    PJ_ASSERT_RETURN(ice_st, PJ_EINVAL);
    /* Must not have ICE */
    PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EINVALIDOP);
    /* Components must have been created */
    PJ_ASSERT_RETURN(ice_st->comp[0] != NULL, PJ_EINVALIDOP);

    /* Init callback */
    pj_bzero(&ice_cb, sizeof(ice_cb));
    ice_cb.on_ice_complete = &on_ice_complete;
    ice_cb.on_rx_data = &ice_rx_data;
    ice_cb.on_tx_pkt = &ice_tx_pkt;

    /* Create! */
    status = pj_ice_sess_create(&ice_st->stun_cfg, ice_st->obj_name, role,
			        ice_st->comp_cnt, &ice_cb, 
			        local_ufrag, local_passwd, &ice_st->ice);
    if (status != PJ_SUCCESS)
	return status;

    /* Associate user data */
    ice_st->ice->user_data = (void*)ice_st;

    /* If default candidate for components are SRFLX one, upload a custom
     * type priority to ICE session so that SRFLX candidates will get
     * checked first.
     */
    if (ice_st->comp[0]->default_cand >= 0 &&
	ice_st->comp[0]->cand_list[ice_st->comp[0]->default_cand].type 
	    == PJ_ICE_CAND_TYPE_SRFLX)
    {
	pj_ice_sess_set_prefs(ice_st->ice, srflx_prio);
    }


    /* Add candidates */
    for (i=0; i<ice_st->comp_cnt; ++i) {
	unsigned j;
	pj_ice_strans_comp *comp= ice_st->comp[i];

	for (j=0; j<comp->cand_cnt; ++j) {
	    pj_ice_strans_cand *cand = &comp->cand_list[j];

	    /* Skip if candidate is not ready */
	    if (cand->status != PJ_SUCCESS) {
		PJ_LOG(5,(ice_st->obj_name, 
			  "Candidate %d in component %d is not added",
			  j, i));
		continue;
	    }

	    status = pj_ice_sess_add_cand(ice_st->ice, comp->comp_id, 
					  cand->type, cand->local_pref, 
					  &cand->foundation, &cand->addr, 
					  &comp->local_addr, NULL, 
					  sizeof(pj_sockaddr_in), 
					  (unsigned*)&cand->ice_cand_id);
	    if (status != PJ_SUCCESS)
		goto on_error;
	}
    }

    return PJ_SUCCESS;

on_error:
    pj_ice_strans_stop_ice(ice_st);
    return status;
}

/*
 * Enum candidates
 */
PJ_DEF(pj_status_t) pj_ice_strans_enum_cands(pj_ice_strans *ice_st,
					 unsigned *count,
					 pj_ice_sess_cand cand[])
{
    unsigned i, cnt;
    pj_ice_sess_cand *pcand;

    PJ_ASSERT_RETURN(ice_st && count && cand, PJ_EINVAL);
    PJ_ASSERT_RETURN(ice_st->ice, PJ_EINVALIDOP);

    cnt = ice_st->ice->lcand_cnt;
    cnt = (cnt > *count) ? *count : cnt;
    *count = 0;

    for (i=0; i<cnt; ++i) {
	pcand = &ice_st->ice->lcand[i];
	pj_memcpy(&cand[i], pcand, sizeof(pj_ice_sess_cand));
    }

    *count = cnt;
    return PJ_SUCCESS;
}

/*
 * Start ICE processing !
 */
PJ_DEF(pj_status_t) pj_ice_strans_start_ice( pj_ice_strans *ice_st,
					     const pj_str_t *rem_ufrag,
					     const pj_str_t *rem_passwd,
					     unsigned rem_cand_cnt,
					     const pj_ice_sess_cand rem_cand[])
{
    pj_status_t status;

    status = pj_ice_sess_create_check_list(ice_st->ice, rem_ufrag, rem_passwd,
					   rem_cand_cnt, rem_cand);
    if (status != PJ_SUCCESS)
	return status;

    status = pj_ice_sess_start_check(ice_st->ice);
    if (status != PJ_SUCCESS) {
	pj_ice_strans_stop_ice(ice_st);
    }

    return status;
}

/*
 * Stop ICE!
 */
PJ_DECL(pj_status_t) pj_ice_strans_stop_ice(pj_ice_strans *ice_st)
{
    unsigned i;

    if (ice_st->ice) {
	pj_ice_sess_destroy(ice_st->ice);
	ice_st->ice = NULL;
    }

    /* Invalidate all candidate Ids */
    for (i=0; i<ice_st->comp_cnt; ++i) {
	unsigned j;
	for (j=0; j<ice_st->comp[i]->cand_cnt; ++j) {
	    ice_st->comp[i]->cand_list[j].ice_cand_id = -1;
	}
    }

    return PJ_SUCCESS;
}

/*
 * Send packet using non-ICE means (e.g. when ICE was not negotiated).
 */
PJ_DEF(pj_status_t) pj_ice_strans_sendto( pj_ice_strans *ice_st,
					  unsigned comp_id,
					  const void *data,
					  pj_size_t data_len,
					  const pj_sockaddr_t *dst_addr,
					  int dst_addr_len)
{
    pj_ssize_t pkt_size;
    pj_ice_strans_comp *comp;
    pj_status_t status;

    PJ_ASSERT_RETURN(ice_st && comp_id && comp_id <= ice_st->comp_cnt &&
		     dst_addr && dst_addr_len, PJ_EINVAL);

    comp = ice_st->comp[comp_id-1];

    /* If ICE is available, send data with ICE */
    if (ice_st->ice) {
	return pj_ice_sess_send_data(ice_st->ice, comp_id, data, data_len);
    }

    /* Otherwise send direcly with the socket. This is for compatibility
     * with remote that doesn't support ICE.
     */
    pkt_size = data_len;
    status = pj_ioqueue_sendto(comp->key, &comp->write_op, 
			       data, &pkt_size, 0,
			       dst_addr, dst_addr_len);
    
    return (status==PJ_SUCCESS||status==PJ_EPENDING) ? PJ_SUCCESS : status;
}

/*
 * Callback called by ICE session when ICE processing is complete, either
 * successfully or with failure.
 */
static void on_ice_complete(pj_ice_sess *ice, pj_status_t status)
{
    pj_ice_strans *ice_st = (pj_ice_strans*)ice->user_data;
    if (ice_st->cb.on_ice_complete) {
	(*ice_st->cb.on_ice_complete)(ice_st, status);
    }
}

/*
 * Callback called by ICE session when it wants to send outgoing packet.
 */
static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 
			      unsigned comp_id, 
			      const void *pkt, pj_size_t size,
			      const pj_sockaddr_t *dst_addr,
			      unsigned dst_addr_len)
{
    pj_ice_strans *ice_st = (pj_ice_strans*)ice->user_data;
    pj_ice_strans_comp *comp = NULL;
    pj_ssize_t pkt_size;
    pj_status_t status;

    PJ_TODO(TX_TO_RELAY);

    PJ_ASSERT_RETURN(comp_id && comp_id <= ice_st->comp_cnt, PJ_EINVAL);
    comp = ice_st->comp[comp_id-1];

    TRACE_PKT((comp->ice_st->obj_name, 
	      "Component %d TX packet to %s:%d",
	      comp_id,
	      pj_inet_ntoa(((pj_sockaddr_in*)dst_addr)->sin_addr),
	      (int)pj_ntohs(((pj_sockaddr_in*)dst_addr)->sin_port)));

    pkt_size = size;
    status = pj_ioqueue_sendto(comp->key, &comp->write_op, 
			       pkt, &pkt_size, 0,
			       dst_addr, dst_addr_len);
    
    return (status==PJ_SUCCESS||status==PJ_EPENDING) ? PJ_SUCCESS : status;
}

/*
 * Callback called by ICE session when it receives application data.
 */
static void ice_rx_data(pj_ice_sess *ice, 
		        unsigned comp_id, 
		        void *pkt, pj_size_t size,
		        const pj_sockaddr_t *src_addr,
		        unsigned src_addr_len)
{
    pj_ice_strans *ice_st = (pj_ice_strans*)ice->user_data;

    if (ice_st->cb.on_rx_data) {
	(*ice_st->cb.on_rx_data)(ice_st, comp_id, pkt, size, 
				 src_addr, src_addr_len);
    }
}

/*
 * Callback called by STUN session to send outgoing packet.
 */
static pj_status_t stun_on_send_msg(pj_stun_session *sess,
				    const void *pkt,
				    pj_size_t size,
				    const pj_sockaddr_t *dst_addr,
				    unsigned dst_addr_len)
{
    pj_ice_strans_comp *comp;
    pj_ssize_t pkt_size;
    pj_status_t status;

    comp = (pj_ice_strans_comp*) pj_stun_session_get_user_data(sess);
    pkt_size = size;
    status = pj_ioqueue_sendto(comp->key, &comp->write_op, 
			       pkt, &pkt_size, 0,
			       dst_addr, dst_addr_len);
    
    return (status==PJ_SUCCESS||status==PJ_EPENDING) ? PJ_SUCCESS : status;
}

/*
 * Callback sent by STUN session when outgoing STUN request has
 * completed.
 */
static void stun_on_request_complete(pj_stun_session *sess,
				     pj_status_t status,
				     pj_stun_tx_data *tdata,
				     const pj_stun_msg *response,
				     const pj_sockaddr_t *src_addr,
				     unsigned src_addr_len)
{
    pj_ice_strans_comp *comp;
    pj_ice_strans_cand *cand = NULL;
    pj_stun_xor_mapped_addr_attr *xa;
    pj_stun_mapped_addr_attr *ma;
    pj_sockaddr *mapped_addr;

    comp = (pj_ice_strans_comp*) pj_stun_session_get_user_data(sess);
    cand = (pj_ice_strans_cand*) tdata->user_data;

    PJ_UNUSED_ARG(src_addr);
    PJ_UNUSED_ARG(src_addr_len);

    if (cand == NULL) {
	/* This is keep-alive */
	if (status != PJ_SUCCESS) {
	    ice_st_perror(comp->ice_st, "STUN keep-alive request failed",
			  status);
	}
	return;
    }

    /* Decrement pending count for this component */
    pj_assert(comp->pending_cnt > 0);
    comp->pending_cnt--;

    if (status != PJ_SUCCESS) {
	comp->last_status = cand->status = status;
	ice_st_perror(comp->ice_st, "STUN Binding request failed", 
		      cand->status);
	return;
    }

    xa = (pj_stun_xor_mapped_addr_attr*)
	 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_XOR_MAPPED_ADDR, 0);
    ma = (pj_stun_mapped_addr_attr*)
	 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_MAPPED_ADDR, 0);

    if (xa)
	mapped_addr = &xa->sockaddr;
    else if (ma)
	mapped_addr = &ma->sockaddr;
    else {
	cand->status = PJNATH_ESTUNNOMAPPEDADDR;
	ice_st_perror(comp->ice_st, "STUN Binding request failed", 
		      cand->status);
	return;
    }

    PJ_LOG(4,(comp->ice_st->obj_name, 
	      "STUN mapped address: %s:%d",
	      pj_inet_ntoa(mapped_addr->ipv4.sin_addr),
	      (int)pj_ntohs(mapped_addr->ipv4.sin_port)));
    pj_memcpy(&cand->addr, mapped_addr, sizeof(pj_sockaddr_in));
    cand->status = PJ_SUCCESS;

    /* Set this candidate as the default candidate */
    comp->default_cand = (cand - comp->cand_list);
    comp->last_status = PJ_SUCCESS;

    /* We have STUN, so we must start the keep-alive timer */
    start_ka_timer(comp->ice_st);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -