@ -4038,7 +4038,9 @@ void media_subscriptions_clear(subscription_q *q) {
i_queue_clear_full ( q , media_subscription_free ) ;
}
static void __unsubscribe_media_link ( struct call_media * which , struct media_subscription * ms )
__attribute__ ( ( nonnull ( 1 , 2 ) ) )
static inline void __unsubscribe_media_link_store ( struct call_media * which , struct media_subscription * ms ,
subscription_store_ht ht )
{
struct media_subscription * rev_ms = ms - > reverse ;
struct call_media * from = ms - > media ;
@ -4055,11 +4057,23 @@ static void __unsubscribe_media_link(struct call_media *which, struct media_subs
t_hash_table_remove ( from - > media_subscribers_ht , rev_ms - > media ) ;
g_free ( ms ) ;
g_free ( rev_ms ) ;
if ( t_hash_table_is_set ( ht ) )
t_hash_table_insert ( ht , from , rev_ms ) ;
else
g_free ( rev_ms ) ;
}
__attribute__ ( ( nonnull ( 1 , 2 ) ) )
static void __unsubscribe_media_link ( struct call_media * which , struct media_subscription * ms )
{
__unsubscribe_media_link_store ( which , ms , subscription_store_ht_null ( ) ) ;
}
/**
* Unsubscribe one particular media subscriber from this call media .
*/
__attribute__ ( ( nonnull ( 1 , 2 ) ) )
bool __unsubscribe_media ( struct call_media * which , struct call_media * from )
{
if ( ! t_hash_table_is_set ( which - > media_subscriptions_ht )
@ -4098,23 +4112,27 @@ static void __unsubscribe_all_offer_answer_medias(struct call_media *cm, medias_
__unsubscribe_media ( cm , other_cm ) ;
}
}
static void __unsubscribe_medias_from_all ( struct call_monologue * ml ) {
__attribute__ ( ( nonnull ( 1 ) ) )
static inline void __unsubscribe_medias_from_all ( struct call_monologue * ml , subscription_store_ht ht )
{
for ( int i = 0 ; i < ml - > medias - > len ; i + + )
{
struct call_media * media = ml - > medias - > pdata [ i ] ;
struct call_media * media = ml - > medias - > pdata [ i ] ;
if ( ! media )
continue ;
IQUEUE_FOREACH_SAFE ( & media - > media_subscriptions , subscription )
__unsubscribe_media_link ( media , subscription ) ;
__unsubscribe_media_link _store ( media , subscription , ht ) ;
}
}
/**
* Check whether this monologue medias are subscribed to a single other monologue medias .
*/
struct call_monologue * ml_medias_subscribed_to_single_ml ( struct call_monologue * ml ) {
/* detect monologues multiplicity */
struct call_monologue * return_ml = NULL ;
struct call_monologue * return_ml = NULL ;
for ( unsigned int i = 0 ; i < ml - > medias - > len ; i + + )
{
struct call_media * media = ml - > medias - > pdata [ i ] ;
@ -4129,7 +4147,7 @@ struct call_monologue *ml_medias_subscribed_to_single_ml(struct call_monologue *
}
return return_ml ;
}
struct media_subscription * __add_media_subscription ( struct call_media * which , struct call_media * to ,
struct media_subscription * __add_media_subscription ( struct call_media * which , struct call_media * to ,
const struct sink_attrs * attrs )
{
struct media_subscription * ret ;
@ -4359,9 +4377,9 @@ int monologue_publish(struct call_monologue *ml, sdp_streams_q *streams, sdp_ng_
}
/* called with call->master_lock held in W */
__attribute__ ( ( nonnull ( 1 , 2 , 3 , 4 )) )
__attribute__ ( ( nonnull ( 1 , 2 , 3 )) )
static int monologue_subscribe_request1 ( struct call_media * src_media , struct call_monologue * dst_ml ,
sdp_ng_flags * flags , unsigned int * index )
sdp_ng_flags * flags , subscription_store_ht ht )
{
unsigned int idx_diff = 0 , rev_idx_diff = 0 ;
g_auto ( str_ht ) mid_tracker_dst = str_ht_new ( ) ;
@ -4369,8 +4387,16 @@ static int monologue_subscribe_request1(struct call_media *src_media, struct cal
struct stream_params * sp = & src_media - > sp ;
struct call_media * dst_media = call_get_media ( dst_ml , & src_media - > type , src_media - > type_id ,
NULL , false , ( * index ) + + , mid_tracker_dst ) ;
// check if we have a matching existing subscription
struct call_media * dst_media = NULL ;
__auto_type ms = t_hash_table_lookup ( ht , src_media ) ;
if ( ms )
dst_media = ms - > media ;
if ( ! dst_media ) {
// new media needed
dst_media = call_get_media ( dst_ml , & src_media - > type , src_media - > type_id ,
NULL , false , dst_ml - > medias - > len + 1 , mid_tracker_dst ) ;
}
/* subscribe dst_ml (subscriber) to src_ml, don't forget to carry the egress flag, if required */
__add_media_subscription ( dst_media , src_media , & ( struct sink_attrs ) { . egress = ! ! flags - > egress } ) ;
@ -4446,12 +4472,13 @@ static int monologue_subscribe_request1(struct call_media *src_media, struct cal
return 0 ;
}
/* called with call->master_lock held in W */
__attribute__ ( ( nonnull ( 1 , 2 , 3 ) ) )
int monologue_subscribe_request ( const subscription_q * srms , struct call_monologue * dst_ml , sdp_ng_flags * flags ) {
unsigned int index = 1 ; /* running counter for output/dst medias */
g_auto ( subscription_store_ht ) ht = subscription_store_ht_new ( ) ;
__unsubscribe_medias_from_all ( dst_ml );
__unsubscribe_medias_from_all ( dst_ml , ht );
__call_monologue_init_from_flags ( dst_ml , NULL , flags ) ;
IQUEUE_FOREACH ( srms , ms ) {
@ -4459,7 +4486,7 @@ int monologue_subscribe_request(const subscription_q *srms, struct call_monologu
if ( ! src_media )
continue ;
int ret = monologue_subscribe_request1 ( src_media , dst_ml , flags , & index ) ;
int ret = monologue_subscribe_request1 ( src_media , dst_ml , flags , ht ) ;
if ( ret )
return - 1 ;