?? ice_strans.c
字號:
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 + -