diff options
author | Benny Prijono <bennylp@teluu.com> | 2007-12-03 14:38:25 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2007-12-03 14:38:25 +0000 |
commit | 24e131e2488d5da39ee191413742ed57a3f8394d (patch) | |
tree | 526af62367a4a26370f1162c4006ab0023d6707c /pjmedia | |
parent | b1ab3152928f1c17596bf169ca0692044da105c3 (diff) |
Ticket #420: updated pjmedia SDP and media UDP transport to support IPv6
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1615 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r-- | pjmedia/include/pjmedia/stream.h | 4 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/transport_udp.h | 26 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/types.h | 4 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/endpoint.c | 61 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/session.c | 90 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/transport_udp.c | 149 |
6 files changed, 236 insertions, 98 deletions
diff --git a/pjmedia/include/pjmedia/stream.h b/pjmedia/include/pjmedia/stream.h index e951b0de..4967c380 100644 --- a/pjmedia/include/pjmedia/stream.h +++ b/pjmedia/include/pjmedia/stream.h @@ -90,8 +90,8 @@ struct pjmedia_stream_info { pjmedia_type type; /**< Media type (audio, video) */ pjmedia_dir dir; /**< Media direction. */ - pj_sockaddr_in rem_addr; /**< Remote RTP address */ - pj_sockaddr_in rem_rtcp; /**< Optional remote RTCP address. If + pj_sockaddr rem_addr; /**< Remote RTP address */ + pj_sockaddr rem_rtcp; /**< Optional remote RTCP address. If sin_family is zero, the RTP address will be calculated from RTP. */ pjmedia_codec_info fmt; /**< Incoming codec format info. */ diff --git a/pjmedia/include/pjmedia/transport_udp.h b/pjmedia/include/pjmedia/transport_udp.h index 745df46b..12f819d1 100644 --- a/pjmedia/include/pjmedia/transport_udp.h +++ b/pjmedia/include/pjmedia/transport_udp.h @@ -112,6 +112,32 @@ PJ_DECL(pj_status_t) pjmedia_transport_udp_create2(pjmedia_endpt *endpt, pjmedia_transport **p_tp); /** + * Another variant of #pjmedia_transport_udp_create() which allows + * the creation of IPv6 transport. + * + * @param endpt The media endpoint instance. + * @param af Address family, which can be pj_AF_INET() for IPv4 or + * pj_AF_INET6() for IPv6. + * @param name Optional name to be assigned to the transport. + * @param addr Optional local address to bind the sockets to. If this + * argument is NULL or empty, the sockets will be bound + * to all interface. + * @param port UDP port number for the RTP socket. The RTCP port number + * will be set to one above RTP port. + * @param options Options, bitmask of #pjmedia_transport_udp_options. + * @param p_tp Pointer to receive the transport instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_transport_udp_create3(pjmedia_endpt *endpt, + int af, + const char *name, + const pj_str_t *addr, + int port, + unsigned options, + pjmedia_transport **p_tp); + +/** * Get media socket info from the specified UDP transport. * * @param tp The UDP transport interface. diff --git a/pjmedia/include/pjmedia/types.h b/pjmedia/include/pjmedia/types.h index 8ff8fe60..ed080d27 100644 --- a/pjmedia/include/pjmedia/types.h +++ b/pjmedia/include/pjmedia/types.h @@ -141,7 +141,7 @@ typedef struct pjmedia_sock_info * address (for example, this address can be the address resolved * with STUN). */ - pj_sockaddr_in rtp_addr_name; + pj_sockaddr rtp_addr_name; /** The RTCP socket handle. */ pj_sock_t rtcp_sock; @@ -151,7 +151,7 @@ typedef struct pjmedia_sock_info * address (for example, this address can be the address resolved * with STUN). */ - pj_sockaddr_in rtcp_addr_name; + pj_sockaddr rtcp_addr_name; } pjmedia_sock_info; diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c index dbeefe7f..b0c1d4dc 100644 --- a/pjmedia/src/pjmedia/endpoint.c +++ b/pjmedia/src/pjmedia/endpoint.c @@ -34,6 +34,7 @@ static const pj_str_t STR_AUDIO = { "audio", 5}; static const pj_str_t STR_VIDEO = { "video", 5}; static const pj_str_t STR_IN = { "IN", 2 }; static const pj_str_t STR_IP4 = { "IP4", 3}; +static const pj_str_t STR_IP6 = { "IP6", 3}; static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 }; static const pj_str_t STR_SDP_NAME = { "pjmedia", 7 }; static const pj_str_t STR_SENDRECV = { "sendrecv", 8 }; @@ -289,6 +290,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, { pj_time_val tv; unsigned i; + const pj_sockaddr *addr0; pjmedia_sdp_session *sdp; pjmedia_sdp_media *m; pjmedia_sdp_attr *attr; @@ -303,23 +305,38 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, /* Create and initialize basic SDP session */ sdp = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session); + addr0 = &sock_info[0].rtp_addr_name; + pj_gettimeofday(&tv); sdp->origin.user = pj_str("-"); sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL; sdp->origin.net_type = STR_IN; - sdp->origin.addr_type = STR_IP4; - pj_strdup2(pool, &sdp->origin.addr, - pj_inet_ntoa(sock_info[0].rtp_addr_name.sin_addr)); + + if (addr0->addr.sa_family == pj_AF_INET()) { + sdp->origin.addr_type = STR_IP4; + pj_strdup2(pool, &sdp->origin.addr, + pj_inet_ntoa(addr0->ipv4.sin_addr)); + } else if (addr0->addr.sa_family == pj_AF_INET6()) { + char tmp_addr[PJ_INET6_ADDRSTRLEN]; + + sdp->origin.addr_type = STR_IP6; + pj_strdup2(pool, &sdp->origin.addr, + pj_sockaddr_print(addr0, tmp_addr, sizeof(tmp_addr), 0)); + + } else { + pj_assert(!"Invalid address family"); + return PJ_EAFNOTSUP; + } + sdp->name = STR_SDP_NAME; /* Since we only support one media stream at present, put the * SDP connection line in the session level. */ sdp->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn); - sdp->conn->net_type = STR_IN; - sdp->conn->addr_type = STR_IP4; - pj_strdup2(pool, &sdp->conn->addr, - pj_inet_ntoa(sock_info[0].rtp_addr_name.sin_addr)); + sdp->conn->net_type = sdp->origin.net_type; + sdp->conn->addr_type = sdp->origin.addr_type; + sdp->conn->addr = sdp->origin.addr; /* SDP time and attributes. */ @@ -334,7 +351,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, /* Standard media info: */ pj_strdup(pool, &m->desc.media, &STR_AUDIO); - m->desc.port = pj_ntohs(sock_info[0].rtp_addr_name.sin_port); + m->desc.port = pj_sockaddr_get_port(addr0); m->desc.port_count = 1; pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP); @@ -344,15 +361,31 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, /* Add "rtcp" attribute */ #if defined(PJMEDIA_HAS_RTCP_IN_SDP) && PJMEDIA_HAS_RTCP_IN_SDP!=0 - if (sock_info->rtcp_addr_name.sin_family != 0) { + if (sock_info->rtcp_addr_name.addr.sa_family != 0) { + const pj_sockaddr *rtcp_addr = &sock_info->rtcp_addr_name; + attr = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_attr); attr->name = pj_str("rtcp"); attr->value.ptr = (char*) pj_pool_alloc(pool, 80); - attr->value.slen = - pj_ansi_snprintf(attr->value.ptr, 80, - "%u IN IP4 %s", - pj_ntohs(sock_info[0].rtcp_addr_name.sin_port), - pj_inet_ntoa(sock_info[0].rtcp_addr_name.sin_addr)); + if (rtcp_addr->addr.sa_family == pj_AF_INET()) { + attr->value.slen = + pj_ansi_snprintf(attr->value.ptr, 80, + "%u IN IP4 %s", + pj_ntohs(rtcp_addr->ipv4.sin_port), + pj_inet_ntoa(rtcp_addr->ipv4.sin_addr)); + } else if (rtcp_addr->addr.sa_family == pj_AF_INET6()) { + char tmp_addr[PJ_INET6_ADDRSTRLEN]; + attr->value.slen = + pj_ansi_snprintf(attr->value.ptr, 80, + "%u IN IP6 %s", + pj_sockaddr_get_port(rtcp_addr), + pj_sockaddr_print(rtcp_addr, tmp_addr, + sizeof(tmp_addr), 0)); + + } else { + pj_assert(!"Unsupported address family"); + return PJ_EAFNOTSUP; + } pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr); } #endif diff --git a/pjmedia/src/pjmedia/session.c b/pjmedia/src/pjmedia/session.c index c2c4be92..d0784a69 100644 --- a/pjmedia/src/pjmedia/session.c +++ b/pjmedia/src/pjmedia/session.c @@ -52,8 +52,9 @@ static const pj_str_t ID_AUDIO = { "audio", 5}; static const pj_str_t ID_VIDEO = { "video", 5}; static const pj_str_t ID_IN = { "IN", 2 }; static const pj_str_t ID_IP4 = { "IP4", 3}; -static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; -static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; +static const pj_str_t ID_IP6 = { "IP6", 3}; +/*static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };*/ +/*static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 };*/ static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; static const pj_str_t ID_TELEPHONE_EVENT = { "telephone-event", 15 }; @@ -129,6 +130,8 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( const pjmedia_sdp_media *rem_m; const pjmedia_sdp_conn *local_conn; const pjmedia_sdp_conn *rem_conn; + int rem_af, local_af; + pj_sockaddr local_addr; pjmedia_sdp_rtpmap *rtpmap; int local_fmtp_mode = 0, rem_fmtp_mode = 0; unsigned i, pt, fmti; @@ -185,11 +188,61 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( return PJMEDIA_SDPNEG_EINVANSTP; } + /* Check address family in remote SDP */ + rem_af = pj_AF_UNSPEC(); + if (pj_stricmp(&rem_conn->net_type, &ID_IN)==0) { + if (pj_stricmp(&rem_conn->addr_type, &ID_IP4)==0) { + rem_af = pj_AF_INET(); + } else if (pj_stricmp(&rem_conn->addr_type, &ID_IP6)==0) { + rem_af = pj_AF_UNSPEC(); + } + } + + if (rem_af==pj_AF_UNSPEC()) { + /* Unsupported address family */ + return PJ_EAFNOTSUP; + } + + /* Set remote address: */ + status = pj_sockaddr_init(rem_af, &si->rem_addr, &rem_conn->addr, + rem_m->desc.port); + if (status != PJ_SUCCESS) { + /* Invalid IP address. */ + return PJMEDIA_EINVALIDIP; + } + + /* Check address family of local info */ + local_af = pj_AF_UNSPEC(); + if (pj_stricmp(&local_conn->net_type, &ID_IN)==0) { + if (pj_stricmp(&local_conn->addr_type, &ID_IP4)==0) { + local_af = pj_AF_INET(); + } else if (pj_stricmp(&local_conn->addr_type, &ID_IP6)==0) { + local_af = pj_AF_UNSPEC(); + } + } + + if (local_af==pj_AF_UNSPEC()) { + /* Unsupported address family */ + return PJ_EAFNOTSUP; + } + + /* Set remote address: */ + status = pj_sockaddr_init(local_af, &local_addr, &local_conn->addr, + local_m->desc.port); + if (status != PJ_SUCCESS) { + /* Invalid IP address. */ + return PJMEDIA_EINVALIDIP; + } + + /* Local and remote address family must match */ + if (local_af != rem_af) + return PJ_EAFNOTSUP; + /* Media direction: */ if (local_m->desc.port == 0 || - pj_inet_addr(&local_conn->addr).s_addr==0 || - pj_inet_addr(&rem_conn->addr).s_addr==0 || + pj_sockaddr_has_addr(&local_addr)==PJ_FALSE || + pj_sockaddr_has_addr(&si->rem_addr)==PJ_FALSE || pjmedia_sdp_media_find_attr(local_m, &STR_INACTIVE, NULL)!=NULL) { /* Inactive stream. */ @@ -216,15 +269,6 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( } - - /* Set remote address: */ - status = pj_sockaddr_in_init(&si->rem_addr, &rem_conn->addr, - rem_m->desc.port); - if (status != PJ_SUCCESS) { - /* Invalid IP address. */ - return PJMEDIA_EINVALIDIP; - } - /* If "rtcp" attribute is present in the SDP, set the RTCP address * from that attribute. Otherwise, calculate from RTP address. */ @@ -235,22 +279,24 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( status = pjmedia_sdp_attr_get_rtcp(attr, &rtcp); if (status == PJ_SUCCESS) { if (rtcp.addr.slen) { - status = pj_sockaddr_in_init(&si->rem_rtcp, &rtcp.addr, - (pj_uint16_t)rtcp.port); + status = pj_sockaddr_init(rem_af, &si->rem_rtcp, &rtcp.addr, + (pj_uint16_t)rtcp.port); } else { - pj_sockaddr_in_init(&si->rem_rtcp, NULL, - (pj_uint16_t)rtcp.port); - si->rem_rtcp.sin_addr.s_addr = si->rem_addr.sin_addr.s_addr; + pj_sockaddr_init(rem_af, &si->rem_rtcp, NULL, + (pj_uint16_t)rtcp.port); + pj_memcpy(pj_sockaddr_get_addr(&si->rem_rtcp), + pj_sockaddr_get_addr(&si->rem_addr), + pj_sockaddr_get_addr_len(&si->rem_addr)); } } } - if (si->rem_rtcp.sin_addr.s_addr == 0) { + if (!pj_sockaddr_has_addr(&si->rem_rtcp) == 0) { int rtcp_port; - pj_memcpy(&si->rem_rtcp, &si->rem_addr, sizeof(pj_sockaddr_in)); - rtcp_port = pj_ntohs(si->rem_addr.sin_port) + 1; - si->rem_rtcp.sin_port = pj_htons((pj_uint16_t)rtcp_port); + pj_memcpy(&si->rem_rtcp, &si->rem_addr, sizeof(pj_sockaddr)); + rtcp_port = pj_sockaddr_get_port(&si->rem_addr) + 1; + pj_sockaddr_set_port(&si->rem_rtcp, (pj_uint16_t)rtcp_port); } diff --git a/pjmedia/src/pjmedia/transport_udp.c b/pjmedia/src/pjmedia/transport_udp.c index 4eca8763..05a2a816 100644 --- a/pjmedia/src/pjmedia/transport_udp.c +++ b/pjmedia/src/pjmedia/transport_udp.c @@ -51,8 +51,9 @@ struct transport_udp unsigned options; /**< Transport options. */ void *user_data; /**< Only valid when attached */ pj_bool_t attached; /**< Has attachment? */ - pj_sockaddr_in rem_rtp_addr; /**< Remote RTP address */ - pj_sockaddr_in rem_rtcp_addr; /**< Remote RTCP address */ + pj_sockaddr rem_rtp_addr; /**< Remote RTP address */ + pj_sockaddr rem_rtcp_addr; /**< Remote RTCP address */ + int addr_len; /**< Length of addresses. */ void (*rtp_cb)( void*, /**< To report incoming RTP. */ const void*, pj_ssize_t); @@ -64,19 +65,19 @@ struct transport_udp unsigned rx_drop_pct; /**< Percent of rx pkts to drop. */ pj_sock_t rtp_sock; /**< RTP socket */ - pj_sockaddr_in rtp_addr_name; /**< Published RTP address. */ + pj_sockaddr rtp_addr_name; /**< Published RTP address. */ pj_ioqueue_key_t *rtp_key; /**< RTP socket key in ioqueue */ pj_ioqueue_op_key_t rtp_read_op; /**< Pending read operation */ unsigned rtp_write_op_id;/**< Next write_op to use */ pending_write rtp_pending_write[MAX_PENDING]; /**< Pending write */ - pj_sockaddr_in rtp_src_addr; /**< Actual packet src addr. */ + pj_sockaddr rtp_src_addr; /**< Actual packet src addr. */ unsigned rtp_src_cnt; /**< How many pkt from this addr. */ int rtp_addrlen; /**< Address length. */ char rtp_pkt[RTP_LEN];/**< Incoming RTP packet buffer */ pj_sock_t rtcp_sock; /**< RTCP socket */ - pj_sockaddr_in rtcp_addr_name; /**< Published RTCP address. */ - pj_sockaddr_in rtcp_src_addr; /**< Actual source RTCP address. */ + pj_sockaddr rtcp_addr_name; /**< Published RTCP address. */ + pj_sockaddr rtcp_src_addr; /**< Actual source RTCP address. */ int rtcp_addr_len; /**< Length of RTCP src address. */ pj_ioqueue_key_t *rtcp_key; /**< RTCP socket key in ioqueue */ pj_ioqueue_op_key_t rtcp_read_op; /**< Pending read operation */ @@ -150,6 +151,21 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_create2(pjmedia_endpt *endpt, unsigned options, pjmedia_transport **p_tp) { + return pjmedia_transport_udp_create3(endpt, pj_AF_INET(), name, + addr, port, options, p_tp); +} + +/** + * Create UDP stream transport. + */ +PJ_DEF(pj_status_t) pjmedia_transport_udp_create3(pjmedia_endpt *endpt, + int af, + const char *name, + const pj_str_t *addr, + int port, + unsigned options, + pjmedia_transport **p_tp) +{ pjmedia_sock_info si; pj_status_t status; @@ -162,12 +178,15 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_create2(pjmedia_endpt *endpt, si.rtp_sock = si.rtcp_sock = PJ_INVALID_SOCKET; /* Create RTP socket */ - status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &si.rtp_sock); + status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &si.rtp_sock); if (status != PJ_SUCCESS) goto on_error; /* Bind RTP socket */ - pj_sockaddr_in_init(&si.rtp_addr_name, addr, (pj_uint16_t)port); + status = pj_sockaddr_init(af, &si.rtp_addr_name, addr, (pj_uint16_t)port); + if (status != PJ_SUCCESS) + goto on_error; + status = pj_sock_bind(si.rtp_sock, &si.rtp_addr_name, sizeof(si.rtp_addr_name)); if (status != PJ_SUCCESS) @@ -175,12 +194,16 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_create2(pjmedia_endpt *endpt, /* Create RTCP socket */ - status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &si.rtcp_sock); + status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &si.rtcp_sock); if (status != PJ_SUCCESS) goto on_error; /* Bind RTCP socket */ - pj_sockaddr_in_init(&si.rtcp_addr_name, addr, (pj_uint16_t)(port+1)); + status = pj_sockaddr_init(af, &si.rtcp_addr_name, addr, + (pj_uint16_t)(port+1)); + if (status != PJ_SUCCESS) + goto on_error; + status = pj_sock_bind(si.rtcp_sock, &si.rtcp_addr_name, sizeof(si.rtcp_addr_name)); if (status != PJ_SUCCESS) @@ -221,23 +244,21 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_attach( pjmedia_endpt *endpt, /* Sanity check */ PJ_ASSERT_RETURN(endpt && si && p_tp, PJ_EINVAL); - /* Check name */ - if (!name) - name = "udpmedia"; - /* Get ioqueue instance */ ioqueue = pjmedia_endpt_get_ioqueue(endpt); - /* Create transport structure */ pool = pjmedia_endpt_create_pool(endpt, name, 512, 512); if (!pool) return PJ_ENOMEM; + if (!name) + name = pool->obj_name; + tp = PJ_POOL_ZALLOC_T(pool, struct transport_udp); tp->pool = pool; tp->options = options; - pj_ansi_strcpy(tp->base.name, name); + pj_ansi_strncpy(tp->base.name, name, PJ_MAX_OBJ_NAME-1); tp->base.op = &transport_udp_op; tp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP; @@ -248,19 +269,23 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_attach( pjmedia_endpt *endpt, tp->rtcp_addr_name = si->rtcp_addr_name; /* If address is 0.0.0.0, use host's IP address */ - if (tp->rtp_addr_name.sin_addr.s_addr == 0) { + if (!pj_sockaddr_has_addr(&tp->rtp_addr_name)) { pj_sockaddr hostip; - status = pj_gethostip(pj_AF_INET(), &hostip); + status = pj_gethostip(tp->rtp_addr_name.addr.sa_family, &hostip); if (status != PJ_SUCCESS) goto on_error; - tp->rtp_addr_name.sin_addr.s_addr = hostip.ipv4.sin_addr.s_addr; + pj_memcpy(pj_sockaddr_get_addr(&tp->rtp_addr_name), + pj_sockaddr_get_addr(&hostip), + pj_sockaddr_get_addr_len(&hostip)); } /* Same with RTCP */ - if (tp->rtcp_addr_name.sin_addr.s_addr == 0) { - tp->rtcp_addr_name.sin_addr.s_addr = tp->rtp_addr_name.sin_addr.s_addr; + if (!pj_sockaddr_has_addr(&tp->rtcp_addr_name)) { + pj_memcpy(pj_sockaddr_get_addr(&tp->rtcp_addr_name), + pj_sockaddr_get_addr(&tp->rtp_addr_name), + pj_sockaddr_get_addr_len(&tp->rtp_addr_name)); } /* Setup RTP socket with the ioqueue */ @@ -348,6 +373,7 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_close(pjmedia_transport *tp) if (udp->rtp_key) { pj_ioqueue_unregister(udp->rtp_key); udp->rtp_key = NULL; + udp->rtp_sock = PJ_INVALID_SOCKET; } else if (udp->rtp_sock != PJ_INVALID_SOCKET) { pj_sock_close(udp->rtp_sock); udp->rtp_sock = PJ_INVALID_SOCKET; @@ -356,6 +382,7 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_close(pjmedia_transport *tp) if (udp->rtcp_key) { pj_ioqueue_unregister(udp->rtcp_key); udp->rtcp_key = NULL; + udp->rtcp_sock = PJ_INVALID_SOCKET; } else if (udp->rtcp_sock != PJ_INVALID_SOCKET) { pj_sock_close(udp->rtcp_sock); udp->rtcp_sock = PJ_INVALID_SOCKET; @@ -408,45 +435,48 @@ static void on_rx_rtp( pj_ioqueue_key_t *key, if (bytes_read>0 && (udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0) { - if ((udp->rem_rtp_addr.sin_addr.s_addr != - udp->rtp_src_addr.sin_addr.s_addr) || - (udp->rem_rtp_addr.sin_port != - udp->rtp_src_addr.sin_port)) - { + if (pj_sockaddr_cmp(&udp->rem_rtp_addr, &udp->rtp_src_addr) != 0) { + udp->rtp_src_cnt++; if (udp->rtp_src_cnt >= PJMEDIA_RTP_NAT_PROBATION_CNT) { + char addr_text[80]; + /* Set remote RTP address to source address */ - udp->rem_rtp_addr = udp->rtp_src_addr; + pj_memcpy(&udp->rem_rtp_addr, &udp->rtp_src_addr, + sizeof(pj_sockaddr)); /* Reset counter */ udp->rtp_src_cnt = 0; PJ_LOG(4,(udp->base.name, - "Remote RTP address switched to %s:%d", - pj_inet_ntoa(udp->rtp_src_addr.sin_addr), - pj_ntohs(udp->rtp_src_addr.sin_port))); + "Remote RTP address switched to %s", + pj_sockaddr_print(&udp->rtp_src_addr, addr_text, + sizeof(addr_text), 3))); /* Also update remote RTCP address if actual RTCP source * address is not heard yet. */ - if (udp->rtcp_src_addr.sin_addr.s_addr == 0) { + if (!pj_sockaddr_has_addr(&udp->rtcp_src_addr)) { pj_uint16_t port; pj_memcpy(&udp->rem_rtcp_addr, &udp->rem_rtp_addr, - sizeof(pj_sockaddr_in)); + sizeof(pj_sockaddr)); + pj_sockaddr_copy_addr(&udp->rem_rtcp_addr, + &udp->rem_rtp_addr); port = (pj_uint16_t) - (pj_ntohs(udp->rem_rtp_addr.sin_port)+1); - udp->rem_rtcp_addr.sin_port = pj_htons(port); + (pj_sockaddr_get_port(&udp->rem_rtp_addr)+1); + pj_sockaddr_set_port(&udp->rem_rtcp_addr, port); pj_memcpy(&udp->rtcp_src_addr, &udp->rem_rtcp_addr, - sizeof(pj_sockaddr_in)); + sizeof(pj_sockaddr)); PJ_LOG(4,(udp->base.name, - "Remote RTCP address switched to %s:%d", - pj_inet_ntoa(udp->rtcp_src_addr.sin_addr), - pj_ntohs(udp->rtcp_src_addr.sin_port))); + "Remote RTCP address switched to %s", + pj_sockaddr_print(&udp->rtcp_src_addr, + addr_text, + sizeof(addr_text), 3))); } } @@ -455,7 +485,7 @@ static void on_rx_rtp( pj_ioqueue_key_t *key, read_next_packet: bytes_read = sizeof(udp->rtp_pkt); - udp->rtp_addrlen = sizeof(pj_sockaddr_in); + udp->rtp_addrlen = sizeof(udp->rtp_src_addr); status = pj_ioqueue_recvfrom(udp->rtp_key, &udp->rtp_read_op, udp->rtp_pkt, &bytes_read, 0, &udp->rtp_src_addr, @@ -496,17 +526,17 @@ static void on_rx_rtcp(pj_ioqueue_key_t *key, */ if (bytes_read>0 && (udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0 && - ((udp->rem_rtcp_addr.sin_addr.s_addr != - udp->rtcp_src_addr.sin_addr.s_addr) || - (udp->rem_rtcp_addr.sin_port != - udp->rtcp_src_addr.sin_port))) + pj_sockaddr_cmp(&udp->rem_rtcp_addr, &udp->rtcp_src_addr) != 0) { + char addr_text[80]; + pj_memcpy(&udp->rem_rtcp_addr, &udp->rtcp_src_addr, - sizeof(pj_sockaddr_in)); + sizeof(pj_sockaddr)); + PJ_LOG(4,(udp->base.name, - "Remote RTCP address switched to %s:%d", - pj_inet_ntoa(udp->rtcp_src_addr.sin_addr), - pj_ntohs(udp->rtcp_src_addr.sin_port))); + "Remote RTCP address switched to %s", + pj_sockaddr_print(&udp->rtcp_src_addr, addr_text, + sizeof(addr_text), 3))); } bytes_read = sizeof(udp->rtcp_pkt); @@ -552,7 +582,7 @@ static pj_status_t transport_attach( pjmedia_transport *tp, pj_ssize_t)) { struct transport_udp *udp = (struct transport_udp*) tp; - const pj_sockaddr_in *rtcp_addr; + const pj_sockaddr *rtcp_addr; /* Validate arguments */ PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL); @@ -563,20 +593,20 @@ static pj_status_t transport_attach( pjmedia_transport *tp, /* "Attach" the application: */ /* Copy remote RTP address */ - pj_memcpy(&udp->rem_rtp_addr, rem_addr, sizeof(pj_sockaddr_in)); + pj_memcpy(&udp->rem_rtp_addr, rem_addr, addr_len); /* Copy remote RTP address, if one is specified. */ - rtcp_addr = (const pj_sockaddr_in*) rem_rtcp; - if (rtcp_addr && rtcp_addr->sin_addr.s_addr != 0) { - pj_memcpy(&udp->rem_rtcp_addr, rem_rtcp, sizeof(pj_sockaddr_in)); + rtcp_addr = (const pj_sockaddr*) rem_rtcp; + if (rtcp_addr && pj_sockaddr_has_addr(rtcp_addr)) { + pj_memcpy(&udp->rem_rtcp_addr, rem_rtcp, addr_len); } else { - int rtcp_port; + unsigned rtcp_port; /* Otherwise guess the RTCP address from the RTP address */ - pj_memcpy(&udp->rem_rtcp_addr, rem_addr, sizeof(pj_sockaddr_in)); - rtcp_port = pj_ntohs(udp->rem_rtp_addr.sin_port) + 1; - udp->rem_rtcp_addr.sin_port = pj_htons((pj_uint16_t)rtcp_port); + pj_memcpy(&udp->rem_rtcp_addr, rem_addr, addr_len); + rtcp_port = pj_sockaddr_get_port(&udp->rem_rtp_addr) + 1; + pj_sockaddr_set_port(&udp->rem_rtcp_addr, (pj_uint16_t)rtcp_port); } /* Save the callbacks */ @@ -584,6 +614,9 @@ static pj_status_t transport_attach( pjmedia_transport *tp, udp->rtcp_cb = rtcp_cb; udp->user_data = user_data; + /* Save address length */ + udp->addr_len = addr_len; + /* Last, mark transport as attached */ udp->attached = PJ_TRUE; @@ -659,7 +692,7 @@ static pj_status_t transport_send_rtp( pjmedia_transport *tp, &udp->rtp_pending_write[id].op_key, pw->buffer, &sent, 0, &udp->rem_rtp_addr, - sizeof(pj_sockaddr_in)); + udp->addr_len); udp->rtp_write_op_id = (udp->rtp_write_op_id + 1) % PJ_ARRAY_SIZE(udp->rtp_pending_write); @@ -684,7 +717,7 @@ static pj_status_t transport_send_rtcp(pjmedia_transport *tp, sent = size; status = pj_ioqueue_sendto( udp->rtcp_key, &udp->rtcp_write_op, pkt, &sent, 0, - &udp->rem_rtcp_addr, sizeof(pj_sockaddr_in)); + &udp->rem_rtcp_addr, udp->addr_len); if (status==PJ_SUCCESS || status==PJ_EPENDING) return PJ_SUCCESS; |