From 57921286f7577dd670b905f85a4ef0271cfb2028 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Fri, 23 Mar 2007 19:09:54 +0000 Subject: ICE (work in progress): implemented server reflexive candidate git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1099 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/src/pjmedia/transport_ice.c | 86 +++++++---- pjnath/include/pjnath/errno.h | 5 + pjnath/include/pjnath/ice_stream_transport.h | 26 ++-- pjnath/src/pjnath/ice.c | 13 +- pjnath/src/pjnath/ice_stream_transport.c | 215 +++++++++++++++++++++++---- pjnath/src/pjnath/stun_session.c | 16 +- pjsip/src/pjsua-lib/pjsua_acc.c | 12 ++ pjsip/src/pjsua-lib/pjsua_core.c | 7 + pjsip/src/pjsua-lib/pjsua_media.c | 6 +- 9 files changed, 295 insertions(+), 91 deletions(-) diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c index 2023a1dc..7bb14b88 100644 --- a/pjmedia/src/pjmedia/transport_ice.c +++ b/pjmedia/src/pjmedia/transport_ice.c @@ -19,19 +19,25 @@ #include #include #include +#include struct transport_ice { pjmedia_transport base; pj_ice_st *ice_st; - void *stream; - void (*rtp_cb)(void*, - const void*, - pj_ssize_t); - void (*rtcp_cb)(void*, - const void*, - pj_ssize_t); + pj_time_val start_ice; + + void *stream; + pj_sockaddr_in remote_rtp; + pj_sockaddr_in remote_rtcp; + + void (*rtp_cb)(void*, + const void*, + pj_ssize_t); + void (*rtcp_cb)(void*, + const void*, + pj_ssize_t); }; @@ -68,12 +74,6 @@ static void ice_on_rx_data(pj_ice_st *ice_st, void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len); -static void ice_on_stun_srv_resolved(pj_ice_st *ice_st, - pj_status_t status); -static void ice_on_interface_status(pj_ice_st *ice_st, - void *notify_data, - pj_status_t status, - int itf_id); static void ice_on_ice_complete(pj_ice_st *ice_st, pj_status_t status); @@ -107,9 +107,7 @@ PJ_DEF(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt, /* Configure ICE callbacks */ pj_bzero(&ice_st_cb, sizeof(ice_st_cb)); ice_st_cb.on_ice_complete = &ice_on_ice_complete; - ice_st_cb.on_interface_status = &ice_on_interface_status; ice_st_cb.on_rx_data = &ice_on_rx_data; - ice_st_cb.on_stun_srv_resolved = &ice_on_stun_srv_resolved; /* Create ICE */ status = pj_ice_st_create(stun_cfg, name, NULL, &ice_st_cb, &ice_st); @@ -387,6 +385,9 @@ PJ_DEF(pj_status_t) pjmedia_ice_start_ice(pjmedia_transport *tp, cand_cnt++; } + /* Mark start time */ + pj_gettimeofday(&tp_ice->start_ice); + /* Start ICE */ return pj_ice_st_start_ice(tp_ice->ice_st, &uname, &pass, cand_cnt, cand); } @@ -454,9 +455,8 @@ static pj_status_t tp_attach( pjmedia_transport *tp, tp_ice->rtp_cb = rtp_cb; tp_ice->rtcp_cb = rtcp_cb; - PJ_UNUSED_ARG(rem_addr); - PJ_UNUSED_ARG(rem_rtcp); - PJ_UNUSED_ARG(addr_len); + pj_memcpy(&tp_ice->remote_rtp, rem_addr, addr_len); + pj_memcpy(&tp_ice->remote_rtcp, rem_rtcp, addr_len); return PJ_SUCCESS; } @@ -480,7 +480,13 @@ static pj_status_t tp_send_rtp(pjmedia_transport *tp, pj_size_t size) { struct transport_ice *tp_ice = (struct transport_ice*)tp; - return pj_ice_st_send_data(tp_ice->ice_st, 1, pkt, size); + if (tp_ice->ice_st->ice) { + return pj_ice_st_send_data(tp_ice->ice_st, 1, pkt, size); + } else { + return pj_ice_st_sendto(tp_ice->ice_st, 1, 0, + pkt, size, &tp_ice->remote_rtp, + sizeof(pj_sockaddr_in)); + } } @@ -520,26 +526,40 @@ static void ice_on_rx_data(pj_ice_st *ice_st, } -static void ice_on_stun_srv_resolved(pj_ice_st *ice_st, - pj_status_t status) +static void ice_on_ice_complete(pj_ice_st *ice_st, + pj_status_t status) { struct transport_ice *tp_ice = (struct transport_ice*) ice_st->user_data; -} + pj_time_val end_ice; + pj_ice_cand *lcand, *rcand; + pj_ice_check *check; + char src_addr[32]; + char dst_addr[32]; + + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(status, errmsg, sizeof(errmsg)); + PJ_LOG(1,(ice_st->obj_name, "ICE negotiation failed: %s", errmsg)); + return; + } + pj_gettimeofday(&end_ice); + PJ_TIME_VAL_SUB(end_ice, tp_ice->start_ice); -static void ice_on_interface_status(pj_ice_st *ice_st, - void *notify_data, - pj_status_t status, - int itf_id) -{ - struct transport_ice *tp_ice = (struct transport_ice*) ice_st->user_data; -} + check = &ice_st->ice->clist.checks[ice_st->ice->valid_list[0]]; + + lcand = check->lcand; + rcand = check->rcand; + pj_ansi_strcpy(src_addr, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); + pj_ansi_strcpy(dst_addr, pj_inet_ntoa(rcand->addr.ipv4.sin_addr)); -static void ice_on_ice_complete(pj_ice_st *ice_st, - pj_status_t status) -{ - struct transport_ice *tp_ice = (struct transport_ice*) ice_st->user_data; + PJ_LOG(3,(ice_st->obj_name, + "ICE negotiation completed in %d.%03ds. Sending from " + "%s:%d to %s:%d", + (int)end_ice.sec, (int)end_ice.msec, + src_addr, pj_ntohs(lcand->addr.ipv4.sin_port), + dst_addr, pj_ntohs(rcand->addr.ipv4.sin_port))); } diff --git a/pjnath/include/pjnath/errno.h b/pjnath/include/pjnath/errno.h index 9f45bc86..7fbd9837 100644 --- a/pjnath/include/pjnath/errno.h +++ b/pjnath/include/pjnath/errno.h @@ -133,6 +133,11 @@ * STUN transaction terminates with failure. */ #define PJNATH_ESTUNTSXFAILED (PJNATH_ERRNO_START+126)/* 370126 */ +/** + * @hideinitializer + * STUN mapped address attribute not found + */ +#define PJNATH_ESTUNNOMAPPEDADDR (PJNATH_ERRNO_START+127)/* 370127 */ //#define PJ_STATUS_FROM_STUN_CODE(code) (PJNATH_ERRNO_START+code) diff --git a/pjnath/include/pjnath/ice_stream_transport.h b/pjnath/include/pjnath/ice_stream_transport.h index 37ff5686..59207324 100644 --- a/pjnath/include/pjnath/ice_stream_transport.h +++ b/pjnath/include/pjnath/ice_stream_transport.h @@ -48,13 +48,6 @@ typedef struct pj_ice_st_cb void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len); - - void (*on_stun_srv_resolved)(pj_ice_st *ice_st, - pj_status_t status); - void (*on_interface_status)(pj_ice_st *ice_st, - void *notify_data, - pj_status_t status, - int itf_id); void (*on_ice_complete)(pj_ice_st *ice_st, pj_status_t status); @@ -85,6 +78,7 @@ typedef struct pj_ice_st_interface pj_ioqueue_op_key_t write_op; pj_sockaddr src_addr; int src_addr_len; + pj_stun_session *stun_sess; } pj_ice_st_interface; @@ -133,19 +127,14 @@ PJ_DECL(pj_status_t) pj_ice_st_add_host_interface(pj_ice_st *ice_st, unsigned comp_id, pj_uint16_t local_pref, const pj_sockaddr_in *addr, - unsigned *p_itf_id, - pj_bool_t notify, - void *notify_data); + unsigned *p_itf_id); PJ_DECL(pj_status_t) pj_ice_st_add_all_host_interfaces(pj_ice_st *ice_st, unsigned comp_id, - unsigned port, - pj_bool_t notify, - void *notify_data); + unsigned port); PJ_DECL(pj_status_t) pj_ice_st_add_stun_interface(pj_ice_st *ice_st, unsigned comp_id, unsigned local_port, - pj_bool_t notify, - void *notify_data); + unsigned *p_itf_id); PJ_DECL(pj_status_t) pj_ice_st_add_relay_interface(pj_ice_st *ice_st, unsigned comp_id, unsigned local_port, @@ -171,6 +160,13 @@ PJ_DECL(pj_status_t) pj_ice_st_send_data(pj_ice_st *ice_st, unsigned comp_id, const void *data, pj_size_t data_len); +PJ_DECL(pj_status_t) pj_ice_st_sendto(pj_ice_st *ice_st, + unsigned comp_id, + unsigned itf_id, + const void *data, + pj_size_t data_len, + const pj_sockaddr_t *dst_addr, + int dst_addr_len); /** diff --git a/pjnath/src/pjnath/ice.c b/pjnath/src/pjnath/ice.c index d2d2474d..9ab50262 100644 --- a/pjnath/src/pjnath/ice.c +++ b/pjnath/src/pjnath/ice.c @@ -56,11 +56,6 @@ static const char *clist_state_name[] = "Completed" }; -const pj_str_t host_foundation = {"host", 4}; -const pj_str_t mapped_foundation = {"srfx", 4}; -const pj_str_t relayed_foundation = {"rlyd", 4}; -const pj_str_t peer_mapped_foundation = {"peer", 4}; - #define CHECK_NAME_LEN 128 #define LOG(expr) PJ_LOG(4,expr) #define GET_LCAND_ID(cand) (cand - ice->lcand) @@ -1431,11 +1426,17 @@ static void on_stun_request_complete(pj_stun_session *stun_sess, if (i == ice->lcand_cnt) { unsigned cand_id; + char buf[32]; + pj_str_t foundation; + + pj_ansi_snprintf(buf, sizeof(buf), "P%x", + lcand->base_addr.ipv4.sin_addr.s_addr); + foundation = pj_str(buf); /* Add new peer reflexive candidate */ status = pj_ice_add_cand(ice, lcand->comp_id, PJ_ICE_CAND_TYPE_PRFLX, - 65535, &peer_mapped_foundation, + 65535, &foundation, &xaddr->sockaddr, &lcand->base_addr, NULL, sizeof(pj_sockaddr_in), &cand_id); if (status != PJ_SUCCESS) { diff --git a/pjnath/src/pjnath/ice_stream_transport.c b/pjnath/src/pjnath/ice_stream_transport.c index e654fcf7..1462ff25 100644 --- a/pjnath/src/pjnath/ice_stream_transport.c +++ b/pjnath/src/pjnath/ice_stream_transport.c @@ -47,6 +47,18 @@ static void on_read_complete(pj_ioqueue_key_t *key, static void destroy_ice_interface(pj_ice_st_interface *is); static void destroy_ice_st(pj_ice_st *ice_st, pj_status_t reason); +/* STUN session callback */ +static pj_status_t stun_on_send_msg(pj_stun_session *sess, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); +static void stun_on_request_complete(pj_stun_session *sess, + pj_status_t status, + pj_stun_tx_data *tdata, + const pj_stun_msg *response); + +/* Utility: print error */ static void ice_st_perror(pj_ice_st *ice_st, const char *title, pj_status_t status) { @@ -160,6 +172,7 @@ static void on_read_complete(pj_ioqueue_key_t *key, { pj_ice_st_interface *is = (pj_ice_st_interface*) pj_ioqueue_get_user_data(key); + pj_ice_st *ice_st = is->ice_st; pj_ssize_t pkt_size; pj_status_t status; @@ -168,11 +181,29 @@ static void on_read_complete(pj_ioqueue_key_t *key, /* If we have an active ICE session, hand over all incoming * packets to the ICE session. Otherwise just drop the packet. */ - if (is->ice_st->ice) { - status = pj_ice_on_rx_pkt(is->ice_st->ice, + if (ice_st->ice) { + status = pj_ice_on_rx_pkt(ice_st->ice, is->comp_id, is->cand_id, is->pkt, bytes_read, &is->src_addr, is->src_addr_len); + } else if (is->stun_sess) { + status = pj_stun_msg_check(is->pkt, bytes_read, PJ_STUN_IS_DATAGRAM); + if (status == PJ_SUCCESS) { + status = pj_stun_session_on_rx_pkt(is->stun_sess, is->pkt, + bytes_read, + PJ_STUN_IS_DATAGRAM, NULL, + &is->src_addr, + is->src_addr_len); + } else { + (*ice_st->cb.on_rx_data)(ice_st, is->comp_id, is->cand_id, + is->pkt, bytes_read, + &is->src_addr, is->src_addr_len); + + } + } else { + (*ice_st->cb.on_rx_data)(ice_st, is->comp_id, is->cand_id, + is->pkt, bytes_read, + &is->src_addr, is->src_addr_len); } } else if (bytes_read < 0) { @@ -195,6 +226,11 @@ static void on_read_complete(pj_ioqueue_key_t *key, */ static void destroy_ice_interface(pj_ice_st_interface *is) { + if (is->stun_sess) { + pj_stun_session_destroy(is->stun_sess); + is->stun_sess = NULL; + } + if (is->key) { pj_ioqueue_unregister(is->key); is->key = NULL; @@ -344,8 +380,7 @@ PJ_DEF(pj_status_t) pj_ice_st_add_comp(pj_ice_st *ice_st, /* Add interface */ static void add_interface(pj_ice_st *ice_st, pj_ice_st_interface *is, - unsigned *p_itf_id, pj_bool_t notify, - void *notify_data) + unsigned *p_itf_id) { unsigned itf_id; @@ -354,11 +389,6 @@ static void add_interface(pj_ice_st *ice_st, pj_ice_st_interface *is, if (p_itf_id) *p_itf_id = itf_id; - - if (notify && ice_st->cb.on_interface_status) { - (*ice_st->cb.on_interface_status)(ice_st, notify_data, - PJ_SUCCESS, itf_id); - } } /* @@ -368,9 +398,7 @@ PJ_DEF(pj_status_t) pj_ice_st_add_host_interface(pj_ice_st *ice_st, unsigned comp_id, pj_uint16_t local_pref, const pj_sockaddr_in *addr, - unsigned *p_itf_id, - pj_bool_t notify, - void *notify_data) + unsigned *p_itf_id) { pj_ice_st_interface *is; pj_status_t status; @@ -394,7 +422,7 @@ PJ_DEF(pj_status_t) pj_ice_st_add_host_interface(pj_ice_st *ice_st, pj_memcpy(&is->addr, &is->base_addr, sizeof(is->addr)); /* Store this interface */ - add_interface(ice_st, is, p_itf_id, notify, notify_data); + add_interface(ice_st, is, p_itf_id); /* Set interface status to SUCCESS */ is->status = PJ_SUCCESS; @@ -407,9 +435,7 @@ PJ_DEF(pj_status_t) pj_ice_st_add_host_interface(pj_ice_st *ice_st, */ PJ_DEF(pj_status_t) pj_ice_st_add_all_host_interfaces(pj_ice_st *ice_st, unsigned comp_id, - unsigned port, - pj_bool_t notify, - void *notify_data) + unsigned port) { pj_sockaddr_in addr; pj_status_t status; @@ -423,8 +449,7 @@ PJ_DEF(pj_status_t) pj_ice_st_add_all_host_interfaces(pj_ice_st *ice_st, if (status != PJ_SUCCESS) return status; - return pj_ice_st_add_host_interface(ice_st, comp_id, 65535, &addr, - NULL, notify, notify_data); + return pj_ice_st_add_host_interface(ice_st, comp_id, 65535, &addr, NULL); } /* @@ -433,16 +458,61 @@ PJ_DEF(pj_status_t) pj_ice_st_add_all_host_interfaces(pj_ice_st *ice_st, PJ_DEF(pj_status_t) pj_ice_st_add_stun_interface(pj_ice_st *ice_st, unsigned comp_id, unsigned local_port, - pj_bool_t notify, - void *notify_data) + unsigned *p_itf_id) { - /* Yeah, TODO */ - PJ_UNUSED_ARG(ice_st); - PJ_UNUSED_ARG(comp_id); - PJ_UNUSED_ARG(local_port); - PJ_UNUSED_ARG(notify); - PJ_UNUSED_ARG(notify_data); - return -1; + pj_ice_st_interface *is; + pj_sockaddr_in local_addr; + pj_stun_session_cb sess_cb; + pj_stun_tx_data *tdata; + pj_status_t status; + + PJ_ASSERT_RETURN(ice_st && comp_id, PJ_EINVAL); + + /* STUN server must have been configured */ + PJ_ASSERT_RETURN(ice_st->stun_srv.sin_family != 0, PJ_EINVALIDOP); + + + /* Create interface */ + pj_sockaddr_in_init(&local_addr, NULL, (pj_uint16_t)local_port); + status = create_ice_interface(ice_st, PJ_ICE_CAND_TYPE_SRFLX, comp_id, + 65535, &local_addr, &is); + if (status != PJ_SUCCESS) + return status; + + /* Create STUN session */ + pj_bzero(&sess_cb, sizeof(sess_cb)); + sess_cb.on_request_complete = &stun_on_request_complete; + sess_cb.on_send_msg = &stun_on_send_msg; + status = pj_stun_session_create(&ice_st->stun_cfg, ice_st->obj_name, + &sess_cb, PJ_FALSE, &is->stun_sess); + if (status != PJ_SUCCESS) + goto on_error; + + /* Associate interface with STUN session */ + pj_stun_session_set_user_data(is->stun_sess, (void*)is); + + /* Create and send STUN binding request */ + status = pj_stun_session_create_req(is->stun_sess, + PJ_STUN_BINDING_REQUEST, &tdata); + if (status != PJ_SUCCESS) + goto on_error; + + status = pj_stun_session_send_msg(is->stun_sess, PJ_FALSE, + &ice_st->stun_srv, + sizeof(pj_sockaddr_in), tdata); + if (status != PJ_SUCCESS) + goto on_error; + + /* Mark interface as pending */ + is->status = PJ_EPENDING; + + add_interface(ice_st, is, p_itf_id); + + return PJ_SUCCESS; + +on_error: + destroy_ice_interface(is); + return status; } /* @@ -623,6 +693,29 @@ PJ_DEF(pj_status_t) pj_ice_st_send_data( pj_ice_st *ice_st, return pj_ice_send_data(ice_st->ice, comp_id, data, data_len); } +/* + * Send packet using non-ICE means (e.g. when ICE was not negotiated). + */ +PJ_DEF(pj_status_t) pj_ice_st_sendto( pj_ice_st *ice_st, + unsigned comp_id, + unsigned itf_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_st_interface *is = ice_st->itfs[itf_id]; + pj_status_t status; + + pkt_size = data_len; + status = pj_ioqueue_sendto(is->key, &is->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. @@ -687,4 +780,72 @@ static void on_rx_data(pj_ice *ice, } } +/* + * 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_st_interface *is; + pj_ssize_t pkt_size; + pj_status_t status; + + is = (pj_ice_st_interface*) pj_stun_session_get_user_data(sess); + pkt_size = size; + status = pj_ioqueue_sendto(is->key, &is->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) +{ + pj_ice_st_interface *is; + pj_stun_xor_mapped_addr_attr *xa; + pj_stun_mapped_addr_attr *ma; + pj_sockaddr *mapped_addr; + + PJ_UNUSED_ARG(tdata); + + is = (pj_ice_st_interface*) pj_stun_session_get_user_data(sess); + if (status != PJ_SUCCESS) { + is->status = status; + ice_st_perror(is->ice_st, "STUN Binding request failed", is->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 { + is->status = PJNATH_ESTUNNOMAPPEDADDR; + ice_st_perror(is->ice_st, "STUN Binding request failed", is->status); + return; + } + + PJ_LOG(4,(is->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(&is->addr, mapped_addr, sizeof(pj_sockaddr_in)); + is->status = PJ_SUCCESS; + +} diff --git a/pjnath/src/pjnath/stun_session.c b/pjnath/src/pjnath/stun_session.c index 44493120..1a048f2c 100644 --- a/pjnath/src/pjnath/stun_session.c +++ b/pjnath/src/pjnath/stun_session.c @@ -280,10 +280,12 @@ static pj_status_t apply_msg_options(pj_stun_session *sess, /* Create and add USERNAME attribute */ - status = pj_stun_msg_add_string_attr(pool, msg, - PJ_STUN_ATTR_USERNAME, - &username); - PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + if (username.slen) { + status = pj_stun_msg_add_string_attr(pool, msg, + PJ_STUN_ATTR_USERNAME, + &username); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + } /* Add REALM only when long term credential is used */ if (realm.slen) { @@ -301,8 +303,10 @@ static pj_status_t apply_msg_options(pj_stun_session *sess, } /* Add MESSAGE-INTEGRITY attribute */ - status = pj_stun_msg_add_msgint_attr(pool, msg); - PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + if (username.slen) { + status = pj_stun_msg_add_msgint_attr(pool, msg); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + } /* Add FINGERPRINT attribute if necessary */ diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index b168c9ad..3e39b15f 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -943,6 +943,12 @@ PJ_DEF(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool, PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL); acc = &pjsua_var.acc[acc_id]; + /* If force_contact is configured, then use use it */ + if (acc->cfg.force_contact.slen) { + *contact = acc->cfg.force_contact; + return PJ_SUCCESS; + } + /* If route-set is configured for the account, then URI is the * first entry of the route-set. */ @@ -1037,6 +1043,12 @@ PJ_DEF(pj_status_t) pjsua_acc_create_uas_contact( pj_pool_t *pool, PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL); acc = &pjsua_var.acc[acc_id]; + /* If force_contact is configured, then use use it */ + if (acc->cfg.force_contact.slen) { + *contact = acc->cfg.force_contact; + return PJ_SUCCESS; + } + /* If Record-Route is present, then URI is the top Record-Route. */ if (rdata->msg_info.record_route) { sip_uri = (pjsip_sip_uri*) diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 116a51f5..8c6e3506 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -675,6 +675,13 @@ pj_status_t pjsua_resolve_stun_server(pj_bool_t wait) pj_sockaddr_in_init(&pjsua_var.stun_srv.ipv4, NULL, 0); pjsua_var.stun_srv.ipv4.sin_addr = *(pj_in_addr*)he.h_addr; pjsua_var.stun_srv.ipv4.sin_port = pj_htons((pj_uint16_t)3478); + + PJ_LOG(4,(THIS_FILE, + "STUN server %.*s resolved, address is %s:%d", + (int)pjsua_var.ua_cfg.stun_srv.slen, + pjsua_var.ua_cfg.stun_srv.ptr, + pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr), + (int)pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port))); } } return pjsua_var.stun_status; diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 6c81583d..b8b0f33f 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -571,8 +571,7 @@ static pj_status_t create_ice_media_transports(pjsua_transport_config *cfg) ice_st = pjmedia_ice_get_ice_st(pjsua_var.calls[i].med_tp); /* Add host candidates for RTP */ - status = pj_ice_st_add_all_host_interfaces(ice_st, 1, 0, - PJ_FALSE, NULL); + status = pj_ice_st_add_all_host_interfaces(ice_st, 1, 0); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Error adding ICE host candidates", status); @@ -592,8 +591,7 @@ static pj_status_t create_ice_media_transports(pjsua_transport_config *cfg) } /* Add STUN server reflexive candidate for RTP */ - status = pj_ice_st_add_stun_interface(ice_st, 1, 0, - PJ_FALSE, NULL); + status = pj_ice_st_add_stun_interface(ice_st, 1, 0, NULL); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Error adding ICE address", status); -- cgit v1.2.3