From 4e1d5dc0d96e099f12ea0127434b4f7029e95b2b Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 11 Mar 2008 21:38:05 +0000 Subject: Ticket #479: allow media transport framework to return transport specific info (for example, to know whether SRTP is enabled) git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1860 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/config.h | 21 ++++++++++ pjmedia/include/pjmedia/transport.h | 70 ++++++++++++++++++++++++++++++-- pjmedia/include/pjmedia/transport_srtp.h | 24 +++++++++++ pjmedia/src/pjmedia/transport_ice.c | 17 ++++---- pjmedia/src/pjmedia/transport_srtp.c | 30 ++++++++++++-- pjmedia/src/pjmedia/transport_udp.c | 13 +++--- pjsip-apps/src/samples/simpleua.c | 9 ++-- pjsip-apps/src/samples/siprtp.c | 4 +- pjsip/src/pjsua-lib/pjsua_call.c | 38 ++++++++++++++--- pjsip/src/pjsua-lib/pjsua_core.c | 16 ++++---- pjsip/src/pjsua-lib/pjsua_media.c | 6 +-- 11 files changed, 204 insertions(+), 44 deletions(-) diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h index 0640b184..38dd872c 100644 --- a/pjmedia/include/pjmedia/config.h +++ b/pjmedia/include/pjmedia/config.h @@ -524,6 +524,27 @@ #endif +/** + * Transport info (pjmedia_transport_info) contains a socket info and list + * of transport specific info, since transports can be chained together + * (for example, SRTP transport uses UDP transport as the underlying + * transport). This constant specifies maximum number of transport specific + * infos that can be held in a transport info. + */ +#ifndef PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXCNT +# define PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXCNT 4 +#endif + + +/** + * Maximum size in bytes of storage buffer of a transport specific info. + */ +#ifndef PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXSIZE +# define PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXSIZE (12*sizeof(long)) +#endif + + + /** * @} */ diff --git a/pjmedia/include/pjmedia/transport.h b/pjmedia/include/pjmedia/transport.h index 2629cf87..fcf120da 100644 --- a/pjmedia/include/pjmedia/transport.h +++ b/pjmedia/include/pjmedia/transport.h @@ -207,11 +207,17 @@ PJ_BEGIN_DECL #include + /** * Forward declaration for media transport. */ typedef struct pjmedia_transport pjmedia_transport; +/** + * Forward declaration for media transport info. + */ +typedef struct pjmedia_transport_info pjmedia_transport_info; + /** * This enumeration specifies the general behaviour of media processing */ @@ -228,6 +234,7 @@ typedef enum pjmedia_tranport_media_option } pjmedia_tranport_media_option; + /** * This structure describes the operations for the stream transport. */ @@ -239,7 +246,7 @@ struct pjmedia_transport_op * Application should call #pjmedia_transport_get_info() instead */ pj_status_t (*get_info)(pjmedia_transport *tp, - pjmedia_sock_info *info); + pjmedia_transport_info *info); /** * This function is called by the stream when the transport is about @@ -368,7 +375,14 @@ typedef enum pjmedia_transport_type PJMEDIA_TRANSPORT_TYPE_UDP, /** Media transport using ICE */ - PJMEDIA_TRANSPORT_TYPE_ICE + PJMEDIA_TRANSPORT_TYPE_ICE, + + /** + * Media transport SRTP, this transport is actually security adapter to be + * stacked with other transport to enable encryption on the underlying + * transport. + */ + PJMEDIA_TRANSPORT_TYPE_SRTP } pjmedia_transport_type; @@ -390,6 +404,56 @@ struct pjmedia_transport pjmedia_transport_op *op; }; +/** + * This structure describes buffer storage of transport specific info. + * The actual transport specific info contents will be defined by transport + * implementation. Note that some transport implementations do not need to + * provide specific info, since the general socket info is enough. + */ +typedef struct pjmedia_transport_specific_info +{ + /** + * Specify media transport type. + */ + pjmedia_transport_type type; + + /** + * Specify storage buffer size of transport specific info. + */ + int cbsize; + + /** + * Storage buffer of transport specific info. + */ + char buffer[PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXSIZE]; + +} pjmedia_transport_specific_info; + + +/** + * This structure describes transport informations, including general + * socket information and specific information of single transport or + * stacked transports (e.g: SRTP stacked on top of UDP) + */ +struct pjmedia_transport_info +{ + /** + * General socket info. + */ + pjmedia_sock_info sock_info; + + /** + * Specifies number of transport specific info included. + */ + int specific_info_cnt; + + /** + * Buffer storage of transport specific info. + */ + pjmedia_transport_specific_info spc_info[PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXCNT]; + +}; + /** * Get media socket info from the specified transport. The socket info @@ -403,7 +467,7 @@ struct pjmedia_transport * @return PJ_SUCCESS on success. */ PJ_INLINE(pj_status_t) pjmedia_transport_get_info(pjmedia_transport *tp, - pjmedia_sock_info *info) + pjmedia_transport_info *info) { if (tp->op->get_info) return (*tp->op->get_info)(tp, info); diff --git a/pjmedia/include/pjmedia/transport_srtp.h b/pjmedia/include/pjmedia/transport_srtp.h index a04e28b6..d2b6a015 100644 --- a/pjmedia/include/pjmedia/transport_srtp.h +++ b/pjmedia/include/pjmedia/transport_srtp.h @@ -159,6 +159,30 @@ typedef struct pjmedia_srtp_setting } pjmedia_srtp_setting; +/** + * This structure specifies SRTP transport specific info. This will fit + * into \a buffer field of pjmedia_transport_specific_info. + */ +typedef struct pjmedia_srtp_info +{ + /** + * Specify whether the SRTP transport is active for SRTP session. + */ + pj_bool_t active; + + /** + * Specify the policy used by the SRTP session for receive direction. + */ + pjmedia_srtp_crypto rx_policy; + + /** + * Specify the policy used by the SRTP session for transmit direction. + */ + pjmedia_srtp_crypto tx_policy; + +} pjmedia_srtp_info; + + /** * Initialize SRTP setting with its default values. * diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c index 8a6124f3..0534ad4b 100644 --- a/pjmedia/src/pjmedia/transport_ice.c +++ b/pjmedia/src/pjmedia/transport_ice.c @@ -55,7 +55,7 @@ struct transport_ice * These are media transport operations. */ static pj_status_t transport_get_info (pjmedia_transport *tp, - pjmedia_sock_info *info); + pjmedia_transport_info *info); static pj_status_t transport_attach (pjmedia_transport *tp, void *user_data, const pj_sockaddr_t *rem_addr, @@ -673,20 +673,20 @@ static pj_status_t transport_media_stop(pjmedia_transport *tp) static pj_status_t transport_get_info(pjmedia_transport *tp, - pjmedia_sock_info *info) + pjmedia_transport_info *info) { struct transport_ice *tp_ice = (struct transport_ice*)tp; pj_ice_strans *ice_st = tp_ice->ice_st; pj_ice_strans_comp *comp; - pj_bzero(info, sizeof(*info)); - info->rtp_sock = info->rtcp_sock = PJ_INVALID_SOCKET; + pj_bzero(&info->sock_info, sizeof(info->sock_info)); + info->sock_info.rtp_sock = info->sock_info.rtcp_sock = PJ_INVALID_SOCKET; /* Retrieve address of default candidate for component 1 (RTP) */ comp = ice_st->comp[0]; pj_assert(comp->default_cand >= 0); - info->rtp_sock = comp->sock; - pj_memcpy(&info->rtp_addr_name, + info->sock_info.rtp_sock = comp->sock; + pj_memcpy(&info->sock_info.rtp_addr_name, &comp->cand_list[comp->default_cand].addr, sizeof(pj_sockaddr_in)); @@ -694,12 +694,13 @@ static pj_status_t transport_get_info(pjmedia_transport *tp, if (ice_st->comp_cnt > 1) { comp = ice_st->comp[1]; pj_assert(comp->default_cand >= 0); - info->rtp_sock = comp->sock; - pj_memcpy(&info->rtcp_addr_name, + info->sock_info.rtp_sock = comp->sock; + pj_memcpy(&info->sock_info.rtcp_addr_name, &comp->cand_list[comp->default_cand].addr, sizeof(pj_sockaddr_in)); } + info->specific_info_cnt = 0; return PJ_SUCCESS; } diff --git a/pjmedia/src/pjmedia/transport_srtp.c b/pjmedia/src/pjmedia/transport_srtp.c index 5dadb207..3bd95c88 100644 --- a/pjmedia/src/pjmedia/transport_srtp.c +++ b/pjmedia/src/pjmedia/transport_srtp.c @@ -125,7 +125,7 @@ static void srtp_rtcp_cb( void *user_data, void *pkt, pj_ssize_t size); * These are media transport operations. */ static pj_status_t transport_get_info (pjmedia_transport *tp, - pjmedia_sock_info *info); + pjmedia_transport_info *info); static pj_status_t transport_attach (pjmedia_transport *tp, void *user_data, const pj_sockaddr_t *rem_addr, @@ -551,12 +551,34 @@ PJ_DEF(pjmedia_transport *) pjmedia_transport_srtp_get_member( static pj_status_t transport_get_info(pjmedia_transport *tp, - pjmedia_sock_info *info) + pjmedia_transport_info *info) { transport_srtp *srtp = (transport_srtp*) tp; + pjmedia_srtp_info srtp_info; + int spc_info_idx; + pj_status_t status; + + PJ_ASSERT_RETURN(tp && info, PJ_EINVAL); + PJ_ASSERT_RETURN(info->specific_info_cnt < + PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXCNT, PJ_ETOOMANY); + PJ_ASSERT_RETURN(sizeof(pjmedia_srtp_info) <= + PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXSIZE, PJ_ENOMEM); + + status = pjmedia_transport_get_info(srtp->real_tp, info); + if (status != PJ_SUCCESS) + return status; + + srtp_info.active = srtp->session_inited; + srtp_info.rx_policy = srtp->rx_policy; + srtp_info.tx_policy = srtp->tx_policy; - /* put SRTP info as well? */ - return pjmedia_transport_get_info(srtp->real_tp, info); + spc_info_idx = info->specific_info_cnt++; + info->spc_info[spc_info_idx].type = PJMEDIA_TRANSPORT_TYPE_SRTP; + info->spc_info[spc_info_idx].cbsize = sizeof(srtp_info); + pj_memcpy(&info->spc_info[spc_info_idx].buffer, &srtp_info, + sizeof(srtp_info)); + + return PJ_SUCCESS; } static pj_status_t transport_attach(pjmedia_transport *tp, diff --git a/pjmedia/src/pjmedia/transport_udp.c b/pjmedia/src/pjmedia/transport_udp.c index a341d44a..f4e12cd1 100644 --- a/pjmedia/src/pjmedia/transport_udp.c +++ b/pjmedia/src/pjmedia/transport_udp.c @@ -101,7 +101,7 @@ static void on_rx_rtcp(pj_ioqueue_key_t *key, * These are media transport operations. */ static pj_status_t transport_get_info (pjmedia_transport *tp, - pjmedia_sock_info *info); + pjmedia_transport_info *info); static pj_status_t transport_attach (pjmedia_transport *tp, void *user_data, const pj_sockaddr_t *rem_addr, @@ -584,15 +584,16 @@ 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) + pjmedia_transport_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; + info->sock_info.rtp_sock = udp->rtp_sock; + info->sock_info.rtp_addr_name = udp->rtp_addr_name; + info->sock_info.rtcp_sock = udp->rtcp_sock; + info->sock_info.rtcp_addr_name = udp->rtcp_addr_name; + info->specific_info_cnt = 0; return PJ_SUCCESS; } diff --git a/pjsip-apps/src/samples/simpleua.c b/pjsip-apps/src/samples/simpleua.c index 313deee9..634bc539 100644 --- a/pjsip-apps/src/samples/simpleua.c +++ b/pjsip-apps/src/samples/simpleua.c @@ -81,7 +81,7 @@ static pjsip_endpoint *g_endpt; /* SIP endpoint. */ static pj_caching_pool cp; /* Global pool factory. */ static pjmedia_endpt *g_med_endpt; /* Media endpoint. */ -static pjmedia_sock_info g_med_skinfo; /* Socket info for media */ +static pjmedia_transport_info g_med_tpinfo; /* Socket info for media */ static pjmedia_transport *g_med_transport;/* Media stream transport */ /* Call variables: */ @@ -301,7 +301,7 @@ int main(int argc, char *argv[]) * need this info to create SDP (i.e. the address and port info in * the SDP). */ - pjmedia_transport_get_info(g_med_transport, &g_med_skinfo); + pjmedia_transport_get_info(g_med_transport, &g_med_tpinfo); /* @@ -364,7 +364,8 @@ int main(int argc, char *argv[]) status = pjmedia_endpt_create_sdp( g_med_endpt, /* the media endpt */ dlg->pool, /* pool. */ 1, /* # of streams */ - &g_med_skinfo, /* RTP sock info */ + &g_med_tpinfo.sock_info, + /* RTP sock info */ &local_sdp); /* the SDP result */ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); @@ -571,7 +572,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ) */ status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool, 1, - &g_med_skinfo, + &g_med_tpinfo.sock_info, &local_sdp); PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); diff --git a/pjsip-apps/src/samples/siprtp.c b/pjsip-apps/src/samples/siprtp.c index 5f0a3379..53abcdee 100644 --- a/pjsip-apps/src/samples/siprtp.c +++ b/pjsip-apps/src/samples/siprtp.c @@ -1005,7 +1005,7 @@ static pj_status_t create_sdp( pj_pool_t *pool, pjmedia_sdp_session *sdp; pjmedia_sdp_media *m; pjmedia_sdp_attr *attr; - pjmedia_sock_info tpinfo; + pjmedia_transport_info tpinfo; struct media_stream *audio = &call->media[0]; PJ_ASSERT_RETURN(pool && p_sdp, PJ_EINVAL); @@ -1047,7 +1047,7 @@ static pj_status_t create_sdp( pj_pool_t *pool, /* Standard media info: */ m->desc.media = pj_str("audio"); - m->desc.port = pj_ntohs(tpinfo.rtp_addr_name.ipv4.sin_port); + m->desc.port = pj_ntohs(tpinfo.sock_info.rtp_addr_name.ipv4.sin_port); m->desc.port_count = 1; m->desc.transport = pj_str("RTP/AVP"); diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index 403a473a..6329732a 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -2200,6 +2200,7 @@ PJ_DEF(pj_status_t) pjsua_call_dump( pjsua_call_id call_id, char *p, *end; pj_status_t status; int len; + pjmedia_transport_info tp_info; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); @@ -2258,6 +2259,31 @@ PJ_DEF(pj_status_t) pjsua_call_dump( pjsua_call_id call_id, *p = '\0'; } + /* Get SRTP status */ + pjmedia_transport_get_info(call->med_tp, &tp_info); + if (tp_info.specific_info_cnt > 0) { + int i; + for (i = 0; i < tp_info.specific_info_cnt; ++i) { + if (tp_info.spc_info[i].type == PJMEDIA_TRANSPORT_TYPE_SRTP) + { + pjmedia_srtp_info *srtp_info = + (pjmedia_srtp_info*) tp_info.spc_info[i].buffer; + + len = pj_ansi_snprintf(p, end-p, + "%s SRTP status: %s Crypto-suite: %s", + indent, + (srtp_info->active?"Active":"Not active"), + srtp_info->tx_policy.name.ptr); + if (len > 0 && len < end-p) { + p += len; + *p++ = '\n'; + *p = '\0'; + } + break; + } + } + } + /* Dump session statistics */ if (with_media && call->session) dump_media_session(indent, p, end-p, call->session); @@ -2442,11 +2468,11 @@ static void call_disconnect( pjsip_inv_session *inv, code==PJSIP_SC_NOT_ACCEPTABLE_HERE) { pjmedia_sdp_session *local_sdp; - pjmedia_sock_info si; + pjmedia_transport_info ti; - call->med_tp->op->get_info(call->med_tp, &si); + pjmedia_transport_get_info(call->med_tp, &ti); status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, tdata->pool, - 1, &si, &local_sdp); + 1, &ti.sock_info, &local_sdp); if (status == PJ_SUCCESS) { pjsip_create_sdp_body(tdata->pool, local_sdp, &tdata->msg->body); @@ -2551,15 +2577,15 @@ static pj_status_t create_inactive_sdp(pjsua_call *call, pj_status_t status; pjmedia_sdp_conn *conn; pjmedia_sdp_attr *attr; - pjmedia_sock_info skinfo; + pjmedia_transport_info tp_info; pjmedia_sdp_session *sdp; /* Get media socket info */ - pjmedia_transport_get_info(call->med_tp, &skinfo); + pjmedia_transport_get_info(call->med_tp, &tp_info); /* Create new offer */ status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pjsua_var.pool, 1, - &skinfo, &sdp); + &tp_info.sock_info, &sdp); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create local SDP", status); return status; diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 40471583..ef838ba8 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -260,7 +260,7 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata) { pjsip_tx_data *tdata; pjsip_response_addr res_addr; - pjmedia_sock_info skinfo; + pjmedia_transport_info tpinfo; pjmedia_sdp_session *sdp; const pjsip_hdr *cap_hdr; pj_status_t status; @@ -320,11 +320,11 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata) } /* Get media socket info */ - pjmedia_transport_get_info(pjsua_var.calls[0].med_tp, &skinfo); + pjmedia_transport_get_info(pjsua_var.calls[0].med_tp, &tpinfo); /* Add SDP body, using call0's RTP address */ status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, tdata->pool, 1, - &skinfo, &sdp); + &tpinfo.sock_info, &sdp); if (status == PJ_SUCCESS) { pjsip_create_sdp_body(tdata->pool, sdp, &tdata->msg->body); } @@ -2060,17 +2060,17 @@ PJ_DEF(void) pjsua_dump(pj_bool_t detail) PJ_LOG(3,(THIS_FILE, "Dumping media transports:")); for (i=0; imed_tp, &skinfo); + pjmedia_transport_get_info(call->med_tp, &tpinfo); PJ_LOG(3,(THIS_FILE, " %s: %s", (pjsua_var.media_cfg.enable_ice ? "ICE" : "UDP"), - pj_sockaddr_print(&skinfo.rtp_addr_name, addr_buf, + pj_sockaddr_print(&tpinfo.sock_info.rtp_addr_name, addr_buf, sizeof(addr_buf), 3))); } diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index dea8b5b7..238b1fb5 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -814,7 +814,7 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, { enum { MAX_MEDIA = 1, MEDIA_IDX = 0 }; pjmedia_sdp_session *sdp; - pjmedia_sock_info skinfo; + pjmedia_transport_info tpinfo; pjsua_call *call = &pjsua_var.calls[call_id]; pj_status_t status; @@ -826,11 +826,11 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, } /* Get media socket info */ - pjmedia_transport_get_info(call->med_tp, &skinfo); + pjmedia_transport_get_info(call->med_tp, &tpinfo); /* Create SDP */ status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pool, MAX_MEDIA, - &skinfo, &sdp); + &tpinfo.sock_info, &sdp); if (status != PJ_SUCCESS) { if (sip_status_code) *sip_status_code = 500; goto on_error; -- cgit v1.2.3