From 05e7998ba4cbd7fb0b02b7f82c5b328cf203fbc9 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Fri, 23 Mar 2007 00:42:47 +0000 Subject: ICE (work in progress): implemented ICE media transport git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1097 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/build/pjmedia.dsp | 12 +- pjmedia/include/pjmedia/transport.h | 13 + pjmedia/include/pjmedia/transport_ice.h | 78 +++++ pjmedia/src/pjmedia/transport_ice.c | 549 ++++++++++++++++++++++++++++++++ pjmedia/src/pjmedia/transport_udp.c | 29 +- 5 files changed, 670 insertions(+), 11 deletions(-) create mode 100644 pjmedia/include/pjmedia/transport_ice.h create mode 100644 pjmedia/src/pjmedia/transport_ice.c (limited to 'pjmedia') diff --git a/pjmedia/build/pjmedia.dsp b/pjmedia/build/pjmedia.dsp index db649fdf..2e2e9617 100644 --- a/pjmedia/build/pjmedia.dsp +++ b/pjmedia/build/pjmedia.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir ".\output\pjmedia-i386-win32-vc6-release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MD /W4 /GX /Zi /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /I "../src/pjmedia-codec" /D "NDEBUG" /D "PA_NO_ASIO" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c +# ADD CPP /nologo /MD /W4 /GX /Zi /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /I "../src/pjmedia-codec" /I "../../pjnath/include" /D "NDEBUG" /D "PA_NO_ASIO" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -65,7 +65,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir ".\output\pjmedia-i386-win32-vc6-debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /I "../src/pjmedia-codec" /D "_DEBUG" /D "PA_NO_ASIO" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c +# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /I "../src/pjmedia-codec" /I "../../pjnath/include" /D "_DEBUG" /D "PA_NO_ASIO" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -244,6 +244,10 @@ SOURCE=..\src\pjmedia\tonegen.c # End Source File # Begin Source File +SOURCE=..\src\pjmedia\transport_ice.c +# End Source File +# Begin Source File + SOURCE=..\src\pjmedia\transport_udp.c # End Source File # Begin Source File @@ -400,6 +404,10 @@ SOURCE=..\include\pjmedia\transport.h # End Source File # Begin Source File +SOURCE=..\include\pjmedia\transport_ice.h +# End Source File +# Begin Source File + SOURCE=..\include\pjmedia\transport_udp.h # End Source File # Begin Source File diff --git a/pjmedia/include/pjmedia/transport.h b/pjmedia/include/pjmedia/transport.h index ce509f03..4b2450bc 100644 --- a/pjmedia/include/pjmedia/transport.h +++ b/pjmedia/include/pjmedia/transport.h @@ -26,6 +26,7 @@ */ #include +#include /** * @defgroup PJMEDIA_TRANSPORT Media Transports @@ -177,6 +178,9 @@ typedef struct pjmedia_transport pjmedia_transport; */ struct pjmedia_transport_op { + pj_status_t (*get_info)(pjmedia_transport *tp, + pjmedia_sock_info *info); + /** * This function is called by the stream when the transport is about * to be used by the stream for the first time, and it tells the transport @@ -265,6 +269,15 @@ struct pjmedia_transport }; +PJ_INLINE(pj_status_t) pjmedia_transport_get_info(pjmedia_transport *tp, + pjmedia_sock_info *info) +{ + if (tp->op->get_info) + return (*tp->op->get_info)(tp, info); + else + return PJ_ENOTSUP; +} + /** * Attach callbacks to be called on receipt of incoming RTP/RTCP packets. diff --git a/pjmedia/include/pjmedia/transport_ice.h b/pjmedia/include/pjmedia/transport_ice.h new file mode 100644 index 00000000..fa4deebb --- /dev/null +++ b/pjmedia/include/pjmedia/transport_ice.h @@ -0,0 +1,78 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2007 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __pjmedia_ice_H__ +#define __pjmedia_ice_H__ + + +/** + * @file transport_ice.h + * @brief Stream transport with ICE. + */ + +#include +#include + + +/** + * @defgroup PJMEDIA_TRANSPORT_ICE ICE Socket Transport + * @ingroup PJMEDIA_TRANSPORT_H + * @brief Implementation of media transport with ICE. + * @{ + */ + +PJ_BEGIN_DECL + + +PJ_DECL(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt, + const char *name, + pj_stun_config *stun_cfg, + pj_dns_resolver *resolver, + pj_bool_t enable_relay, + const pj_str_t *stun_name, + pjmedia_transport **p_tp); +PJ_DECL(pj_status_t) pjmedia_ice_destroy(pjmedia_transport *tp); + + +PJ_DECL(pj_status_t) pjmedia_ice_init_ice(pjmedia_transport *tp, + pj_ice_role role, + const pj_str_t *local_ufrag, + const pj_str_t *local_passwd); +PJ_DECL(pj_status_t) pjmedia_ice_build_sdp(pjmedia_transport *tp, + pj_pool_t *pool, + pjmedia_sdp_session *sdp); +PJ_DECL(pj_status_t) pjmedia_ice_start_ice(pjmedia_transport *tp, + pj_pool_t *pool, + pjmedia_sdp_session *rem_sdp); +PJ_DECL(pj_status_t) pjmedia_ice_stop_ice(pjmedia_transport *tp); + + + + + +PJ_END_DECL + + +/** + * @} + */ + + +#endif /* __pjmedia_ice_H__ */ + + diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c new file mode 100644 index 00000000..98e89fbc --- /dev/null +++ b/pjmedia/src/pjmedia/transport_ice.c @@ -0,0 +1,549 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2007 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +struct transport_ice +{ + pjmedia_transport base; + pj_ice_st *ice_st; + + void *user_data; + void (*rtp_cb)(void*, + const void*, + pj_ssize_t); + void (*rtcp_cb)(void*, + const void*, + pj_ssize_t); +}; + + +/* + * These are media transport operations. + */ +static pj_status_t tp_get_info(pjmedia_transport *tp, + pjmedia_sock_info *info); +static pj_status_t tp_attach( pjmedia_transport *tp, + void *user_data, + const pj_sockaddr_t *rem_addr, + const pj_sockaddr_t *rem_rtcp, + unsigned addr_len, + void (*rtp_cb)(void*, + const void*, + pj_ssize_t), + void (*rtcp_cb)(void*, + const void*, + pj_ssize_t)); +static void tp_detach( pjmedia_transport *tp, + void *strm); +static pj_status_t tp_send_rtp( pjmedia_transport *tp, + const void *pkt, + pj_size_t size); +static pj_status_t tp_send_rtcp( pjmedia_transport *tp, + const void *pkt, + pj_size_t size); + +/* + * And these are ICE callbacks. + */ +static void ice_on_rx_data(pj_ice_st *ice_st, + unsigned comp_id, unsigned cand_id, + 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); + + +static pjmedia_transport_op tp_ice_op = +{ + &tp_get_info, + &tp_attach, + &tp_detach, + &tp_send_rtp, + &tp_send_rtcp, + &pjmedia_ice_destroy +}; + + + +PJ_DEF(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt, + const char *name, + pj_stun_config *stun_cfg, + pj_dns_resolver *resolver, + pj_bool_t enable_relay, + const pj_str_t *stun_name, + pjmedia_transport **p_tp) +{ + pj_ice_st *ice_st; + pj_ice_st_cb ice_st_cb; + struct transport_ice *tp_ice; + pj_status_t status; + + PJ_UNUSED_ARG(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); + if (status != PJ_SUCCESS) + return status; + + /* Add component 1 (RTP) */ + status = pj_ice_st_add_comp(ice_st, 1); + if (status != PJ_SUCCESS) + goto on_error; + + /* Add host candidates. */ + status = pj_ice_st_add_all_host_interfaces(ice_st, 1, 0, PJ_FALSE, NULL); + if (status != PJ_SUCCESS) + goto on_error; + + /* Configure STUN server for ICE */ + if (stun_name) { + status = pj_ice_st_set_stun(ice_st, resolver, enable_relay, stun_name); + if (status != PJ_SUCCESS) + goto on_error; + + /* Add STUN candidates */ + status = pj_ice_st_add_stun_interface(ice_st, 1, 0, PJ_FALSE, NULL); + } + + /* Create transport instance and attach to ICE */ + tp_ice = PJ_POOL_ZALLOC_T(ice_st->pool, struct transport_ice); + tp_ice->ice_st = ice_st; + pj_ansi_strcpy(tp_ice->base.name, ice_st->obj_name); + tp_ice->base.op = &tp_ice_op; + + ice_st->user_data = (void*)tp_ice; + + /* Done */ + if (p_tp) + *p_tp = &tp_ice->base; + + return PJ_SUCCESS; + +on_error: + pj_ice_st_destroy(ice_st); + return status; +} + + +PJ_DEF(pj_status_t) pjmedia_ice_close(pjmedia_transport *tp) +{ + struct transport_ice *tp_ice = (struct transport_ice*)tp; + + if (tp_ice->ice_st) { + pj_ice_st_destroy(tp_ice->ice_st); + tp_ice->ice_st = NULL; + } + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pjmedia_ice_init_ice(pjmedia_transport *tp, + pj_ice_role role, + const pj_str_t *local_ufrag, + const pj_str_t *local_passwd) +{ + struct transport_ice *tp_ice = (struct transport_ice*)tp; + return pj_ice_st_init_ice(tp_ice->ice_st, role, local_ufrag, local_passwd); +} + + +PJ_DEF(pj_status_t) pjmedia_ice_build_sdp(pjmedia_transport *tp, + pj_pool_t *pool, + pjmedia_sdp_session *sdp) +{ + struct transport_ice *tp_ice = (struct transport_ice*)tp; + enum { MAXLEN = 256 }; + char *buffer; + pjmedia_sdp_attr *attr; + unsigned i, cand_cnt; + + buffer = pj_pool_alloc(pool, MAXLEN); + + /* Create ice-ufrag attribute */ + attr = pjmedia_sdp_attr_create(pool, "ice-ufrag", + &tp_ice->ice_st->ice->rx_ufrag); + sdp->attr[sdp->attr_count++] = attr; + + /* Create ice-pwd attribute */ + attr = pjmedia_sdp_attr_create(pool, "ice-pwd", + &tp_ice->ice_st->ice->rx_pass); + sdp->attr[sdp->attr_count++] = attr; + + /* Add all candidates */ + cand_cnt = pj_ice_get_cand_cnt(tp_ice->ice_st->ice); + for (i=0; iice_st->ice, i, &cand); + + len = pj_ansi_snprintf( buffer, MAXLEN, + "%.*s %d UDP %u %s %d typ ", + (int)cand->foundation.slen, + cand->foundation.ptr, + cand->comp_id, + cand->prio, + pj_inet_ntoa(cand->addr.ipv4.sin_addr), + (int)pj_ntohs(cand->addr.ipv4.sin_port)); + if (len < 1 || len >= MAXLEN) + return PJ_ENAMETOOLONG; + + switch (cand->type) { + case PJ_ICE_CAND_TYPE_HOST: + len = pj_ansi_snprintf(buffer+len, MAXLEN-len, + "host"); + break; + case PJ_ICE_CAND_TYPE_SRFLX: + len = pj_ansi_snprintf(buffer+len, MAXLEN-len, + "srflx raddr %s rport %d", + pj_inet_ntoa(cand->base_addr.ipv4.sin_addr), + (int)pj_ntohs(cand->base_addr.ipv4.sin_port)); + break; + case PJ_ICE_CAND_TYPE_RELAYED: + PJ_TODO(RELATED_ADDR_FOR_RELAYED_ADDR); + len = pj_ansi_snprintf(buffer+len, MAXLEN-len, + "srflx raddr %s rport %d", + pj_inet_ntoa(cand->base_addr.ipv4.sin_addr), + (int)pj_ntohs(cand->base_addr.ipv4.sin_port)); + break; + case PJ_ICE_CAND_TYPE_PRFLX: + len = pj_ansi_snprintf(buffer+len, MAXLEN-len, + "prflx raddr %s rport %d", + pj_inet_ntoa(cand->base_addr.ipv4.sin_addr), + (int)pj_ntohs(cand->base_addr.ipv4.sin_port)); + break; + default: + pj_assert(!"Invalid candidate type"); + break; + } + if (len < 1 || len >= MAXLEN) + return PJ_ENAMETOOLONG; + + value = pj_str(buffer); + attr = pjmedia_sdp_attr_create(pool, "candidate", &value); + sdp->attr[sdp->attr_count++] = attr; + } + + /* Done */ + return PJ_SUCCESS; + +} + + +static pj_status_t parse_cand(pj_pool_t *pool, + const pj_str_t *orig_input, + pj_ice_cand *cand) +{ + pj_str_t input; + char *token, *host; + pj_str_t s; + pj_status_t status = PJ_EICEINCANDSDP; + + pj_bzero(cand, sizeof(*cand)); + pj_strdup_with_null(pool, &input, orig_input); + + /* Foundation */ + token = strtok(input.ptr, " "); + if (!token) + goto on_return; + pj_strdup2(pool, &cand->foundation, token); + + /* Component ID */ + token = strtok(NULL, " "); + if (!token) + goto on_return; + cand->comp_id = atoi(token); + + /* Transport */ + token = strtok(NULL, " "); + if (!token) + goto on_return; + if (strcmp(token, "UDP") != 0) + goto on_return; + + /* Priority */ + token = strtok(NULL, " "); + if (!token) + goto on_return; + cand->prio = atoi(token); + + /* Host */ + host = strtok(NULL, " "); + if (!host) + goto on_return; + if (pj_sockaddr_in_init(&cand->addr.ipv4, pj_cstr(&s, host), 0)) + goto on_return; + + /* Port */ + token = strtok(NULL, " "); + if (!token) + goto on_return; + cand->addr.ipv4.sin_port = pj_htons((pj_uint16_t)atoi(token)); + + /* typ */ + token = strtok(NULL, " "); + if (!token) + goto on_return; + if (strcmp(token, "typ") != 0) + goto on_return; + + /* candidate type */ + token = strtok(NULL, " "); + if (!token) + goto on_return; + + if (strcmp(token, "host") == 0) { + cand->type = PJ_ICE_CAND_TYPE_HOST; + + } else if (strcmp(token, "srflx") == 0) { + cand->type = PJ_ICE_CAND_TYPE_SRFLX; + + } else if (strcmp(token, "relay") == 0) { + cand->type = PJ_ICE_CAND_TYPE_RELAYED; + + } else if (strcmp(token, "prflx") == 0) { + cand->type = PJ_ICE_CAND_TYPE_PRFLX; + + } else { + goto on_return; + } + + + status = PJ_SUCCESS; + +on_return: + return status; +} + + +PJ_DEF(pj_status_t) pjmedia_ice_start_ice(pjmedia_transport *tp, + pj_pool_t *pool, + pjmedia_sdp_session *rem_sdp) +{ + struct transport_ice *tp_ice = (struct transport_ice*)tp; + pjmedia_sdp_attr *attr; + unsigned i, cand_cnt; + pj_ice_cand cand[PJ_ICE_MAX_CAND]; + pj_str_t uname, pass; + pj_status_t status; + + /* Find ice-ufrag attribute */ + attr = pjmedia_sdp_attr_find2(rem_sdp->attr_count, rem_sdp->attr, + "ice-ufrag", NULL); + if (attr == NULL) + return PJ_EICEMISSINGSDP; + uname = attr->value; + + /* Find ice-pwd attribute */ + attr = pjmedia_sdp_attr_find2(rem_sdp->attr_count, rem_sdp->attr, + "ice-pwd", NULL); + if (attr == NULL) + return PJ_EICEMISSINGSDP; + pass = attr->value; + + /* Get all candidates */ + cand_cnt = 0; + for (i=0; iattr_count; ++i) { + pjmedia_sdp_attr *attr; + + attr = rem_sdp->attr[i]; + if (pj_strcmp2(&attr->name, "candidate")!=0) + continue; + + status = parse_cand(pool, &attr->value, &cand[cand_cnt]); + if (status != PJ_SUCCESS) + return status; + + cand_cnt++; + } + + /* Start ICE */ + return pj_ice_st_start_ice(tp_ice->ice_st, &uname, &pass, cand_cnt, cand); +} + + +PJ_DEF(pj_status_t) pjmedia_ice_stop_ice(pjmedia_transport *tp) +{ + struct transport_ice *tp_ice = (struct transport_ice*)tp; + return pj_ice_st_stop_ice(tp_ice->ice_st); +} + + +static pj_status_t tp_get_info(pjmedia_transport *tp, + pjmedia_sock_info *info) +{ + struct transport_ice *tp_ice = (struct transport_ice*)tp; + int rel_idx = -1, srflx_idx = -1, host_idx = -1, idx = -1; + unsigned i; + + pj_bzero(info, sizeof(*info)); + info->rtp_sock = info->rtcp_sock = PJ_INVALID_SOCKET; + + for (i=0; iice_st->itf_cnt; ++i) { + pj_ice_st_interface *itf = tp_ice->ice_st->itfs[i]; + + if (itf->type == PJ_ICE_CAND_TYPE_HOST && host_idx == -1) + host_idx = i; + else if (itf->type == PJ_ICE_CAND_TYPE_RELAYED && rel_idx == -1) + rel_idx = i; + else if (itf->type == PJ_ICE_CAND_TYPE_SRFLX && srflx_idx == -1) + srflx_idx = i; + } + + if (idx == -1 && srflx_idx != -1) + idx = srflx_idx; + else if (idx == -1 && rel_idx != -1) + idx = rel_idx; + else if (idx == -1 && host_idx != -1) + idx = host_idx; + + PJ_ASSERT_RETURN(idx != -1, PJ_EBUG); + + pj_memcpy(&info->rtp_addr_name, &tp_ice->ice_st->itfs[idx]->addr, + sizeof(pj_sockaddr_in)); + + return PJ_SUCCESS; +} + + +static pj_status_t tp_attach( pjmedia_transport *tp, + void *user_data, + const pj_sockaddr_t *rem_addr, + const pj_sockaddr_t *rem_rtcp, + unsigned addr_len, + void (*rtp_cb)(void*, + const void*, + pj_ssize_t), + void (*rtcp_cb)(void*, + const void*, + pj_ssize_t)) +{ + struct transport_ice *tp_ice = (struct transport_ice*)tp; + + tp_ice->user_data = user_data; + 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); + + return PJ_SUCCESS; +} + + +static void tp_detach(pjmedia_transport *tp, + void *strm) +{ + struct transport_ice *tp_ice = (struct transport_ice*)tp; + + tp_ice->rtp_cb = NULL; + tp_ice->rtcp_cb = NULL; + tp_ice->user_data = NULL; + + PJ_UNUSED_ARG(strm); +} + + +static pj_status_t tp_send_rtp(pjmedia_transport *tp, + const void *pkt, + 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); +} + + +static pj_status_t tp_send_rtcp(pjmedia_transport *tp, + const void *pkt, + pj_size_t size) +{ +#if 0 + struct transport_ice *tp_ice = (struct transport_ice*)tp; + return pj_ice_st_send_data(tp_ice->ice_st, 1, pkt, size); +#else + PJ_TODO(SUPPORT_RTCP); + PJ_UNUSED_ARG(tp); + PJ_UNUSED_ARG(pkt); + PJ_UNUSED_ARG(size); + return PJ_SUCCESS; +#endif +} + + +static void ice_on_rx_data(pj_ice_st *ice_st, + unsigned comp_id, unsigned cand_id, + void *pkt, pj_size_t size, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + struct transport_ice *tp_ice = (struct transport_ice*) ice_st->user_data; + + if (comp_id==1 && tp_ice->rtp_cb) + (*tp_ice->rtp_cb)(tp_ice->user_data, pkt, size); + else if (comp_id==2 && tp_ice->rtcp_cb) + (*tp_ice->rtcp_cb)(tp_ice->user_data, pkt, size); + + PJ_UNUSED_ARG(cand_id); + PJ_UNUSED_ARG(src_addr); + PJ_UNUSED_ARG(src_addr_len); +} + + +static void ice_on_stun_srv_resolved(pj_ice_st *ice_st, + pj_status_t status) +{ + struct transport_ice *tp_ice = (struct transport_ice*) ice_st->user_data; +} + + +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; +} + + +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; +} + + diff --git a/pjmedia/src/pjmedia/transport_udp.c b/pjmedia/src/pjmedia/transport_udp.c index 4b131c0a..3325be0e 100644 --- a/pjmedia/src/pjmedia/transport_udp.c +++ b/pjmedia/src/pjmedia/transport_udp.c @@ -93,6 +93,8 @@ static void on_rx_rtcp(pj_ioqueue_key_t *key, pj_ioqueue_op_key_t *op_key, pj_ssize_t bytes_read); +static pj_status_t transport_get_info(pjmedia_transport *tp, + pjmedia_sock_info *info); static pj_status_t transport_attach( pjmedia_transport *tp, void *user_data, const pj_sockaddr_t *rem_addr, @@ -116,6 +118,7 @@ static pj_status_t transport_send_rtcp(pjmedia_transport *tp, static pjmedia_transport_op transport_udp_op = { + &transport_get_info, &transport_attach, &transport_detach, &transport_send_rtp, @@ -324,15 +327,7 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_get_info( pjmedia_transport *tp, pjmedia_transport_udp_info *inf) { - struct transport_udp *udp = (struct transport_udp*)tp; - PJ_ASSERT_RETURN(tp && inf, PJ_EINVAL); - - inf->skinfo.rtp_sock = udp->rtp_sock; - inf->skinfo.rtp_addr_name = udp->rtp_addr_name; - inf->skinfo.rtcp_sock = udp->rtcp_sock; - inf->skinfo.rtcp_addr_name = udp->rtcp_addr_name; - - return PJ_SUCCESS; + return transport_get_info(tp, &inf->skinfo); } @@ -527,6 +522,22 @@ static void on_rx_rtcp(pj_ioqueue_key_t *key, } +/* Called to get the transport info */ +static pj_status_t transport_get_info(pjmedia_transport *tp, + pjmedia_sock_info *info) +{ + struct transport_udp *udp = (struct transport_udp*)tp; + PJ_ASSERT_RETURN(tp && info, PJ_EINVAL); + + info->rtp_sock = udp->rtp_sock; + info->rtp_addr_name = udp->rtp_addr_name; + info->rtcp_sock = udp->rtcp_sock; + info->rtcp_addr_name = udp->rtcp_addr_name; + + return PJ_SUCCESS; +} + + /* Called by application to initialize the transport */ static pj_status_t transport_attach( pjmedia_transport *tp, void *user_data, -- cgit v1.2.3