2020-08-31 09:03:13 +00:00
/* Osmo-CC: RTP handling
*
* ( C ) 2016 by Andreas Eversberg < jolly @ eversberg . eu >
* All Rights Reserved
*
* 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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include <stdio.h>
# include <stdint.h>
# include <stdlib.h>
# include <unistd.h>
# include <fcntl.h>
# include <string.h>
# include <errno.h>
# include <arpa/inet.h>
# include "../libdebug/debug.h"
# include "../libtimer/timer.h"
2022-12-04 10:02:58 +00:00
# include "../libselect/select.h"
2020-08-31 09:03:13 +00:00
# include "endpoint.h"
# define RTP_VERSION 2
2021-07-09 18:26:07 +00:00
void osmo_cc_set_rtp_ports ( osmo_cc_session_config_t * conf , uint16_t from , uint16_t to )
2020-08-31 09:03:13 +00:00
{
2021-07-09 18:26:07 +00:00
conf - > rtp_port_next = from ;
conf - > rtp_port_from = from ;
conf - > rtp_port_to = to ;
2020-08-31 09:03:13 +00:00
}
struct rtp_hdr {
uint8_t byte0 ;
uint8_t byte1 ;
uint16_t sequence ;
uint32_t timestamp ;
uint32_t ssrc ;
} __attribute__ ( ( packed ) ) ;
struct rtp_x_hdr {
uint16_t by_profile ;
uint16_t length ;
} __attribute__ ( ( packed ) ) ;
2023-08-19 13:27:53 +00:00
static int rtp_receive ( struct sockaddr_storage * sa , socklen_t * slen , int sock , uint8_t * * payload_p , int * payload_len_p , uint8_t * marker_p , uint8_t * pt_p , uint16_t * sequence_p , uint32_t * timestamp_p , uint32_t * ssrc_p )
2020-08-31 09:03:13 +00:00
{
static uint8_t data [ 2048 ] ;
int len ;
struct rtp_hdr * rtph = ( struct rtp_hdr * ) data ;
uint8_t version , padding , extension , csrc_count , marker , payload_type ;
struct rtp_x_hdr * rtpxh ;
uint8_t * payload ;
int payload_len ;
int x_len ;
2023-08-19 13:27:53 +00:00
len = recvfrom ( sock , data , sizeof ( data ) , 0 , ( struct sockaddr * ) sa , slen ) ;
2020-08-31 09:03:13 +00:00
if ( len < 0 ) {
if ( errno = = EAGAIN )
return - EAGAIN ;
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_DEBUG , " Read errno = %d (%s) \n " , errno , strerror ( errno ) ) ;
2020-08-31 09:03:13 +00:00
return - EIO ;
}
if ( len < 12 ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Received RTP frame too short (len = %d). \n " , len ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
version = rtph - > byte0 > > 6 ;
padding = ( rtph - > byte0 > > 5 ) & 1 ;
extension = ( rtph - > byte0 > > 4 ) & 1 ;
csrc_count = rtph - > byte0 & 0x0f ;
marker = rtph - > byte1 > > 7 ;
payload_type = rtph - > byte1 & 0x7f ;
* sequence_p = ntohs ( rtph - > sequence ) ;
* timestamp_p = ntohl ( rtph - > timestamp ) ;
2021-11-07 06:28:12 +00:00
* ssrc_p = ntohl ( rtph - > ssrc ) ;
2020-08-31 09:03:13 +00:00
if ( version ! = RTP_VERSION ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Received RTP version %d not supported. \n " , version ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
payload = data + sizeof ( * rtph ) + ( csrc_count < < 2 ) ;
payload_len = len - sizeof ( * rtph ) - ( csrc_count < < 2 ) ;
if ( payload_len < 0 ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Received RTP frame too short (len = %d, csrc count = %d). \n " , len , csrc_count ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
if ( extension ) {
if ( payload_len < ( int ) sizeof ( * rtpxh ) ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Received RTP frame too short for extension header. \n " ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
rtpxh = ( struct rtp_x_hdr * ) payload ;
x_len = ntohs ( rtpxh - > length ) * 4 + sizeof ( * rtpxh ) ;
payload + = x_len ;
payload_len - = x_len ;
if ( payload_len < ( int ) sizeof ( * rtpxh ) ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Received RTP frame too short, extension header exceeds frame length. \n " ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
}
if ( padding ) {
if ( payload_len < 1 ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Received RTP frame too short for padding length. \n " ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
payload_len - = payload [ payload_len - 1 ] ;
if ( payload_len < 0 ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Received RTP frame padding is greater than payload. \n " ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
}
* payload_p = payload ;
* payload_len_p = payload_len ;
* marker_p = marker ;
* pt_p = payload_type ;
return 0 ;
}
2023-08-19 13:27:53 +00:00
static int rtcp_receive ( struct sockaddr_storage * sa , socklen_t * slen , int sock )
2022-12-04 10:02:58 +00:00
{
static uint8_t data [ 2048 ] ;
int len ;
2023-08-19 13:27:53 +00:00
len = recvfrom ( sock , data , sizeof ( data ) , 0 , ( struct sockaddr * ) sa , slen ) ;
2022-12-04 10:02:58 +00:00
if ( len < 0 ) {
if ( errno = = EAGAIN )
return - EAGAIN ;
LOGP ( DCC , LOGL_DEBUG , " Read errno = %d (%s) \n " , errno , strerror ( errno ) ) ;
return - EIO ;
}
return 0 ;
}
2023-08-19 13:27:53 +00:00
static void rtp_send ( struct sockaddr_storage * sa , socklen_t slen , int sock , uint8_t * payload , int payload_len , uint8_t marker , uint8_t pt , uint16_t sequence , uint32_t timestamp , uint32_t ssrc )
2020-08-31 09:03:13 +00:00
{
struct rtp_hdr * rtph ;
char data [ sizeof ( * rtph ) + payload_len ] ;
int len , rc ;
rtph = ( struct rtp_hdr * ) data ;
len = sizeof ( * rtph ) ;
rtph - > byte0 = RTP_VERSION < < 6 ;
2022-10-05 18:12:23 +00:00
rtph - > byte1 = pt | ( marker < < 7 ) ;
2020-08-31 09:03:13 +00:00
rtph - > sequence = htons ( sequence ) ;
rtph - > timestamp = htonl ( timestamp ) ;
rtph - > ssrc = htonl ( ssrc ) ;
len + = payload_len ;
if ( len > ( int ) sizeof ( data ) ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Buffer overflow, please fix!. \n " ) ;
2020-08-31 09:03:13 +00:00
abort ( ) ;
}
memcpy ( data + sizeof ( * rtph ) , payload , payload_len ) ;
2023-08-19 13:27:53 +00:00
rc = sendto ( sock , data , len , 0 , ( struct sockaddr * ) sa , slen ) ;
2020-08-31 09:03:13 +00:00
if ( rc < 0 )
2023-08-19 13:27:53 +00:00
LOGP ( DCC , LOGL_DEBUG , " sendto errno = %d (%s) \n " , errno , strerror ( errno ) ) ;
2020-08-31 09:03:13 +00:00
}
2022-12-04 10:02:58 +00:00
static int rtp_listen_cb ( struct osmo_fd * ofd , unsigned int when ) ;
static int rtcp_listen_cb ( struct osmo_fd * ofd , unsigned int when ) ;
2020-08-31 09:03:13 +00:00
/* open and bind RTP
* set local port to what we bound
*/
int osmo_cc_rtp_open ( osmo_cc_session_media_t * media )
{
2021-07-09 18:26:07 +00:00
osmo_cc_session_config_t * conf = media - > session - > config ;
2020-08-31 09:03:13 +00:00
int domain = 0 ; // make GCC happy
uint16_t start_port ;
struct sockaddr_storage sa ;
2023-08-19 13:27:53 +00:00
socklen_t slen = 0 ; // make GCC happy
2020-08-31 09:03:13 +00:00
struct sockaddr_in6 * sa6 ;
struct sockaddr_in * sa4 ;
uint16_t * sport ;
int flags ;
int rc ;
2021-11-07 06:28:12 +00:00
media - > tx_ssrc = rand ( ) ;
2020-08-31 09:03:13 +00:00
osmo_cc_rtp_close ( media ) ;
switch ( media - > connection_data_local . addrtype ) {
case osmo_cc_session_addrtype_ipv4 :
domain = AF_INET ;
memset ( & sa , 0 , sizeof ( sa ) ) ;
sa4 = ( struct sockaddr_in * ) & sa ;
sa4 - > sin_family = domain ;
2021-11-07 06:28:12 +00:00
rc = inet_pton ( AF_INET , media - > connection_data_local . address , & sa4 - > sin_addr ) ;
if ( rc < 1 ) {
pton_error :
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Cannot bind to address '%s'. \n " , media - > connection_data_local . address ) ;
2021-11-07 06:28:12 +00:00
return - EINVAL ;
}
2020-08-31 09:03:13 +00:00
sport = & sa4 - > sin_port ;
slen = sizeof ( * sa4 ) ;
break ;
case osmo_cc_session_addrtype_ipv6 :
domain = AF_INET6 ;
memset ( & sa , 0 , sizeof ( sa ) ) ;
sa6 = ( struct sockaddr_in6 * ) & sa ;
sa6 - > sin6_family = domain ;
2021-11-07 06:28:12 +00:00
rc = inet_pton ( AF_INET6 , media - > connection_data_local . address , & sa6 - > sin6_addr ) ;
if ( rc < 1 )
goto pton_error ;
2020-08-31 09:03:13 +00:00
sport = & sa6 - > sin6_port ;
slen = sizeof ( * sa6 ) ;
break ;
case osmo_cc_session_addrtype_unknown :
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Unsupported address type '%s'. \n " , media - > connection_data_local . addrtype_name ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
/* rtp_port_from/rtp_port_to may be changed at run time, so rtp_port_next can become out of range. */
2021-07-09 18:26:07 +00:00
if ( conf - > rtp_port_next < conf - > rtp_port_from | | conf - > rtp_port_next > conf - > rtp_port_to )
conf - > rtp_port_next = conf - > rtp_port_from ;
start_port = conf - > rtp_port_next ;
2020-08-31 09:03:13 +00:00
while ( 1 ) {
/* open sockets */
rc = socket ( domain , SOCK_DGRAM , IPPROTO_UDP ) ;
if ( rc < 0 ) {
socket_error :
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_ERROR , " Cannot create socket (domain=%d, errno=%d(%s)) \n " , domain , errno , strerror ( errno ) ) ;
2020-08-31 09:03:13 +00:00
osmo_cc_rtp_close ( media ) ;
return - EIO ;
}
2022-12-04 10:02:58 +00:00
media - > rtp_ofd . fd = rc ;
media - > rtp_ofd . cb = rtp_listen_cb ;
media - > rtp_ofd . data = media ;
media - > rtp_ofd . when = OSMO_FD_READ ;
osmo_fd_register ( & media - > rtp_ofd ) ;
2020-08-31 09:03:13 +00:00
rc = socket ( domain , SOCK_DGRAM , IPPROTO_UDP ) ;
if ( rc < 0 )
goto socket_error ;
2022-12-04 10:02:58 +00:00
media - > rtcp_ofd . fd = rc ;
media - > rtcp_ofd . cb = rtcp_listen_cb ;
media - > rtcp_ofd . data = media ;
media - > rtcp_ofd . when = OSMO_FD_READ ;
osmo_fd_register ( & media - > rtcp_ofd ) ;
2020-08-31 09:03:13 +00:00
/* bind sockets */
2021-07-09 18:26:07 +00:00
* sport = htons ( conf - > rtp_port_next ) ;
2022-12-04 10:02:58 +00:00
rc = bind ( media - > rtp_ofd . fd , ( struct sockaddr * ) & sa , slen ) ;
2020-08-31 09:03:13 +00:00
if ( rc < 0 ) {
bind_error :
osmo_cc_rtp_close ( media ) ;
2021-07-09 18:26:07 +00:00
conf - > rtp_port_next = ( conf - > rtp_port_next + 2 > conf - > rtp_port_to ) ? conf - > rtp_port_from : conf - > rtp_port_next + 2 ;
if ( conf - > rtp_port_next = = start_port ) {
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_ERROR , " Cannot bind socket (errno=%d(%s)) \n " , errno , strerror ( errno ) ) ;
2020-08-31 09:03:13 +00:00
return - EIO ;
}
continue ;
}
2021-07-09 18:26:07 +00:00
* sport = htons ( conf - > rtp_port_next + 1 ) ;
2022-12-04 10:02:58 +00:00
rc = bind ( media - > rtcp_ofd . fd , ( struct sockaddr * ) & sa , slen ) ;
2020-08-31 09:03:13 +00:00
if ( rc < 0 )
goto bind_error ;
2021-07-09 18:26:07 +00:00
media - > description . port_local = conf - > rtp_port_next ;
conf - > rtp_port_next = ( conf - > rtp_port_next + 2 > conf - > rtp_port_to ) ? conf - > rtp_port_from : conf - > rtp_port_next + 2 ;
2022-12-04 10:02:58 +00:00
/* set nonblocking io, to prevent write to block */
flags = fcntl ( media - > rtp_ofd . fd , F_GETFL ) ;
2020-08-31 09:03:13 +00:00
flags | = O_NONBLOCK ;
2022-12-04 10:02:58 +00:00
fcntl ( media - > rtp_ofd . fd , F_SETFL , flags ) ;
flags = fcntl ( media - > rtcp_ofd . fd , F_GETFL ) ;
2020-08-31 09:03:13 +00:00
flags | = O_NONBLOCK ;
2022-12-04 10:02:58 +00:00
fcntl ( media - > rtcp_ofd . fd , F_SETFL , flags ) ;
2020-08-31 09:03:13 +00:00
break ;
}
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_DEBUG , " Opening media port %d \n " , media - > description . port_local ) ;
2020-08-31 09:03:13 +00:00
return 0 ;
}
/* connect RTP
* use remote port to connect to
*/
int osmo_cc_rtp_connect ( osmo_cc_session_media_t * media )
{
struct sockaddr_in6 * sa6 ;
struct sockaddr_in * sa4 ;
int rc ;
2023-08-19 13:27:53 +00:00
LOGP ( DCC , LOGL_DEBUG , " Connecting media port %d->%d (remote %s) \n " , media - > description . port_local , media - > description . port_remote , media - > connection_data_remote . address ) ;
2020-08-31 09:03:13 +00:00
switch ( media - > connection_data_remote . addrtype ) {
case osmo_cc_session_addrtype_ipv4 :
2023-08-19 13:27:53 +00:00
memset ( & media - > rtp_sa , 0 , sizeof ( media - > rtp_sa ) ) ;
sa4 = ( struct sockaddr_in * ) & media - > rtp_sa ;
2020-08-31 09:03:13 +00:00
sa4 - > sin_family = AF_INET ;
rc = inet_pton ( AF_INET , media - > connection_data_remote . address , & sa4 - > sin_addr ) ;
if ( rc < 1 ) {
pton_error :
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Cannot connect to address '%s'. \n " , media - > connection_data_remote . address ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
2023-08-19 13:27:53 +00:00
media - > rtp_sport = & sa4 - > sin_port ;
media - > rtp_slen = sizeof ( * sa4 ) ;
memcpy ( & media - > rtcp_sa , & media - > rtp_sa , sizeof ( * sa4 ) ) ;
sa4 = ( struct sockaddr_in * ) & media - > rtcp_sa ;
media - > rtcp_sport = & sa4 - > sin_port ;
media - > rtcp_slen = sizeof ( * sa4 ) ;
2020-08-31 09:03:13 +00:00
break ;
case osmo_cc_session_addrtype_ipv6 :
2023-08-19 13:27:53 +00:00
memset ( & media - > rtp_sa , 0 , sizeof ( media - > rtp_sa ) ) ;
sa6 = ( struct sockaddr_in6 * ) & media - > rtp_sa ;
2020-08-31 09:03:13 +00:00
sa6 - > sin6_family = AF_INET6 ;
rc = inet_pton ( AF_INET6 , media - > connection_data_remote . address , & sa6 - > sin6_addr ) ;
if ( rc < 1 )
goto pton_error ;
2023-08-19 13:27:53 +00:00
media - > rtp_sport = & sa6 - > sin6_port ;
media - > rtp_slen = sizeof ( * sa6 ) ;
memcpy ( & media - > rtcp_sa , & media - > rtp_sa , sizeof ( * sa6 ) ) ;
sa6 = ( struct sockaddr_in6 * ) & media - > rtcp_sa ;
media - > rtcp_sport = & sa6 - > sin6_port ;
media - > rtcp_slen = sizeof ( * sa6 ) ;
2020-08-31 09:03:13 +00:00
break ;
case osmo_cc_session_addrtype_unknown :
2022-12-04 10:02:58 +00:00
LOGP ( DCC , LOGL_NOTICE , " Unsupported address type '%s'. \n " , media - > connection_data_local . addrtype_name ) ;
2020-08-31 09:03:13 +00:00
return - EINVAL ;
}
2023-08-19 13:27:53 +00:00
* media - > rtp_sport = htons ( media - > description . port_remote ) ;
* media - > rtcp_sport = htons ( media - > description . port_remote + 1 ) ;
2020-08-31 09:03:13 +00:00
return 0 ;
}
/* send rtp data with given codec */
2022-12-04 10:02:58 +00:00
void osmo_cc_rtp_send ( osmo_cc_session_codec_t * codec , uint8_t * data , int len , uint8_t marker , int inc_sequence , int inc_timestamp , void * priv )
2020-08-31 09:03:13 +00:00
{
uint8_t * payload = NULL ;
int payload_len = 0 ;
2022-12-04 10:02:58 +00:00
if ( ! codec | | ! codec - > media - > rtp_ofd . fd )
2020-08-31 09:03:13 +00:00
return ;
if ( codec - > encoder )
2022-12-04 10:02:58 +00:00
codec - > encoder ( data , len , & payload , & payload_len , priv ) ;
2020-08-31 09:03:13 +00:00
else {
payload = data ;
payload_len = len ;
}
2023-08-19 13:27:53 +00:00
rtp_send ( & codec - > media - > rtp_sa , codec - > media - > rtp_slen , codec - > media - > rtp_ofd . fd , payload , payload_len , marker , codec - > payload_type_remote , codec - > media - > tx_sequence , codec - > media - > tx_timestamp , codec - > media - > tx_ssrc ) ;
2020-08-31 09:03:13 +00:00
codec - > media - > tx_sequence + = inc_sequence ;
codec - > media - > tx_timestamp + = inc_timestamp ;
if ( codec - > encoder )
free ( payload ) ;
}
2023-08-19 13:27:53 +00:00
static void check_port_translation ( struct sockaddr_storage * sa , struct sockaddr_storage * media_sa , const char * what )
{
struct sockaddr_in6 * sa6 , * sa6_2 ;
struct sockaddr_in * sa4 , * sa4_2 ;
int from = 0 , to = 0 ;
if ( sa - > ss_family ! = media_sa - > ss_family )
return ;
switch ( sa - > ss_family ) {
case AF_INET :
sa4 = ( struct sockaddr_in * ) sa ;
sa4_2 = ( struct sockaddr_in * ) media_sa ;
if ( sa4 - > sin_port ! = sa4_2 - > sin_port ) {
if ( ! ! memcmp ( & sa4 - > sin_addr , & sa4_2 - > sin_addr , sizeof ( struct in_addr ) ) )
break ;
from = ntohs ( sa4_2 - > sin_port ) ;
to = ntohs ( sa4 - > sin_port ) ;
sa4_2 - > sin_port = sa4 - > sin_port ;
}
break ;
case AF_INET6 :
sa6 = ( struct sockaddr_in6 * ) sa ;
sa6_2 = ( struct sockaddr_in6 * ) media_sa ;
if ( sa6 - > sin6_port ! = sa6_2 - > sin6_port ) {
if ( ! ! memcmp ( & sa6 - > sin6_addr , & sa6_2 - > sin6_addr , sizeof ( struct in6_addr ) ) )
break ;
from = ntohs ( sa6_2 - > sin6_port ) ;
to = ntohs ( sa6 - > sin6_port ) ;
sa6_2 - > sin6_port = sa6 - > sin6_port ;
}
break ;
}
if ( from )
LOGP ( DCC , LOGL_NOTICE , " Remote sends with different %s port, changing from %d to %d! \n " , what , from , to ) ;
}
2022-12-04 10:02:58 +00:00
static int rtp_listen_cb ( struct osmo_fd * ofd , unsigned int when )
2020-08-31 09:03:13 +00:00
{
2022-12-04 10:02:58 +00:00
osmo_cc_session_media_t * media = ofd - > data ;
2020-08-31 09:03:13 +00:00
int rc ;
uint8_t * payload = NULL ;
int payload_len = 0 ;
uint8_t marker ;
uint8_t payload_type ;
osmo_cc_session_codec_t * codec ;
uint8_t * data ;
int len ;
2023-08-19 13:27:53 +00:00
struct sockaddr_storage sa ;
socklen_t slen = sizeof ( sa ) ; // must be initialized and will be overwritten
2020-08-31 09:03:13 +00:00
2022-12-04 10:02:58 +00:00
if ( when & OSMO_FD_READ ) {
2023-08-19 13:27:53 +00:00
rc = rtp_receive ( & sa , & slen , media - > rtp_ofd . fd , & payload , & payload_len , & marker , & payload_type , & media - > rx_sequence , & media - > rx_timestamp , & media - > rx_ssrc ) ;
2022-12-04 10:02:58 +00:00
if ( rc < 0 )
return rc ;
2023-08-19 13:27:53 +00:00
check_port_translation ( & sa , & media - > rtp_sa , " RTP " ) ;
2020-08-31 09:03:13 +00:00
2022-12-04 10:02:58 +00:00
/* search for codec */
for ( codec = media - > codec_list ; codec ; codec = codec - > next ) {
if ( codec - > payload_type_local = = payload_type )
break ;
}
if ( ! codec ) {
LOGP ( DCC , LOGL_NOTICE , " Received RTP frame for unknown codec (payload_type = %d). \n " , payload_type ) ;
return 0 ;
}
2020-08-31 09:03:13 +00:00
2022-12-04 10:02:58 +00:00
if ( codec - > decoder )
codec - > decoder ( payload , payload_len , & data , & len , media - > session - > priv ) ;
else {
data = payload ;
len = payload_len ;
}
2020-08-31 09:03:13 +00:00
2022-12-04 10:02:58 +00:00
if ( codec - > media - > receive )
codec - > media - > receiver ( codec , marker , media - > rx_sequence , media - > rx_timestamp , media - > rx_ssrc , data , len ) ;
if ( codec - > decoder )
free ( data ) ;
2020-08-31 09:03:13 +00:00
}
2022-12-04 10:02:58 +00:00
return 0 ;
}
static int rtcp_listen_cb ( struct osmo_fd * ofd , unsigned int when )
{
osmo_cc_session_media_t * media = ofd - > data ;
int rc ;
2023-08-19 13:27:53 +00:00
struct sockaddr_storage sa ;
socklen_t slen = sizeof ( sa ) ; // must be initialized and will be overwritten
2020-08-31 09:03:13 +00:00
2022-12-04 10:02:58 +00:00
if ( when & OSMO_FD_READ ) {
2023-08-19 13:27:53 +00:00
rc = rtcp_receive ( & sa , & slen , media - > rtcp_ofd . fd ) ;
2022-12-04 10:02:58 +00:00
if ( rc < 0 )
return rc ;
2023-08-19 13:27:53 +00:00
check_port_translation ( & sa , & media - > rtcp_sa , " RTCP " ) ;
2022-12-04 10:02:58 +00:00
}
2020-08-31 09:03:13 +00:00
return 0 ;
}
void osmo_cc_rtp_close ( osmo_cc_session_media_t * media )
{
2022-12-04 10:02:58 +00:00
if ( media - > rtp_ofd . fd ) {
osmo_fd_unregister ( & media - > rtp_ofd ) ;
close ( media - > rtp_ofd . fd ) ;
media - > rtp_ofd . fd = 0 ;
2020-08-31 09:03:13 +00:00
}
2022-12-04 10:02:58 +00:00
if ( media - > rtcp_ofd . fd ) {
osmo_fd_unregister ( & media - > rtcp_ofd ) ;
close ( media - > rtcp_ofd . fd ) ;
media - > rtcp_ofd . fd = 0 ;
2020-08-31 09:03:13 +00:00
}
}