/* Create complete answer for remote's offer. */ static pj_status_t create_answer( pj_pool_t *pool, pj_bool_t prefer_remote_codec_order, const pjmedia_sdp_session *initial, const pjmedia_sdp_session *offer, pjmedia_sdp_session **p_answer) { pj_status_t status = PJMEDIA_SDPNEG_ENOMEDIA; pj_bool_t has_active = PJ_FALSE; pjmedia_sdp_session *answer; char media_used[PJMEDIA_MAX_SDP_MEDIA]; unsigned i; /* Validate remote offer. * This should have been validated before. */ PJ_ASSERT_RETURN((status=pjmedia_sdp_validate(offer))==PJ_SUCCESS, status); /* Create initial answer by duplicating initial SDP, * but clear all media lines. The media lines will be filled up later. */ answer = pjmedia_sdp_session_clone(pool, initial); PJ_ASSERT_RETURN(answer != NULL, PJ_ENOMEM); answer->media_count = 0; pj_bzero(media_used, sizeof(media_used)); /* For each media line, create our answer based on our initial * capability. */ for (i=0; i<offer->media_count; ++i) { const pjmedia_sdp_media *om; /* offer */ const pjmedia_sdp_media *im; /* initial media */ pjmedia_sdp_media *am = NULL; /* answer/result */ unsigned j; om = offer->media[i]; /* Find media description in our initial capability that matches * the media type and transport type of offer's media, has * matching codec, and has not been used to answer other offer. */ for (im=NULL, j=0; j<initial->media_count; ++j) { im = initial->media[j]; if (pj_strcmp(&om->desc.media, &im->desc.media)==0 && pj_strcmp(&om->desc.transport, &im->desc.transport)==0 && media_used[j] == 0) { /* See if it has matching codec. */ if (prefer_remote_codec_order) { status = match_offer(pool, om, im, im, &am); } else { status = match_offer(pool, im, om, im, &am); } if (status == PJ_SUCCESS) { /* Mark media as used. */ media_used[j] = 1; break; } } } if (j==initial->media_count) { /* No matching media. * Reject the offer by setting the port to zero in the answer. */ //pjmedia_sdp_attr *a; /* For simplicity in the construction of the answer, we'll * just clone the media from the offer. Anyway receiver will * ignore anything in the media once it sees that the port * number is zero. */ am = pjmedia_sdp_media_clone(pool, om); am->desc.port = 0; // Just set port zero to disable stream without set it to inactive. /* Remove direction attribute, and replace with inactive */ remove_all_media_directions(am); //a = pjmedia_sdp_attr_create(pool, "inactive", NULL); //pjmedia_sdp_media_add_attr(am, a); /* Then update direction */ update_media_direction(pool, om, am); } else { /* The answer is in am */ pj_assert(am != NULL); } /* Add the media answer */ answer->media[answer->media_count++] = am; /* Check if this media is active.*/ if (am->desc.port != 0) has_active = PJ_TRUE; } *p_answer = answer; return has_active ? PJ_SUCCESS : status; }
int tdav_session_msrp_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m) { tdav_session_msrp_t* msrp; const tsdp_header_A_t* A; tsk_bool_t answer; TSK_DEBUG_INFO("tdav_session_msrp_set_ro"); if(!self || !m){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } msrp = (tdav_session_msrp_t*)self; // answer or initial offer? answer = (self->M.lo != tsk_null); /* update remote offer */ TSK_OBJECT_SAFE_FREE(self->M.ro); self->M.ro = tsk_object_ref((void*)m); if(self->M.lo){ if((match_offer(msrp, m))){ } else{ TSK_DEBUG_ERROR("MSRP offer doesn't match"); return -1; } /* QoS */ if(self->qos){ tmedia_qos_tline_t* ro_tline; if(self->M.ro && (ro_tline = tmedia_qos_tline_from_sdp(self->M.ro))){ tmedia_qos_tline_set_ro(self->qos, ro_tline); TSK_OBJECT_SAFE_FREE(ro_tline); } } } /* To-Path */ if((A = tsdp_header_M_findA(m, "path"))){ tmsrp_uri_t* uri; if((uri = tmsrp_uri_parse(A->value, tsk_strlen(A->value)))){ TSK_OBJECT_SAFE_FREE(msrp->config->To_Path); msrp->config->To_Path = tmsrp_header_To_Path_create(uri); TSK_OBJECT_SAFE_FREE(uri); } } // OMA-TS-SIMPLE_IM-V1_0-20080903-C - 5.8.1 Negotiate direction of the MSRP connection setup if((A = tsdp_header_M_findA(m, "setup"))){ tdav_msrp_setup_t setup = setup_from_string(A->value); switch(setup){ case msrp_setup_actpass: case msrp_setup_passive: msrp->setup = msrp_setup_active; break; case msrp_setup_active: msrp->setup = msrp_setup_passive; break; } } /* Neg parameters */ init_neg_types(msrp, m); /* [OMA-TS-SIMPLE_IM-V1_0-20100322-C] - 5.8.2 Support of Application Level Gateway */ /* get connection associated to this media line * If the connnection is global, then the manager will call tdav_session_audio_set() */ if(m->C && m->C->addr && !msrp->remote_ip){ tsk_strupdate(&msrp->remote_ip, m->C->addr); msrp->useIPv6 = tsk_striequals(m->C->addrtype, "IP6"); } /* set remote port */ msrp->remote_port = m->port; return 0; }