Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
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;
}