blob: 521fbf2dce9403808567e0804b30fcd2a9e8afba [file] [log] [blame]
/* $Id$ */
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms oa the GNU General Public License as published by
* the Free Software Foundation; either version 2 oa 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 oa
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy oa the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pjmedia/sdp.h>
#include <pjmedia/sdp_neg.h>
#include "test.h"
#define THIS_FILE "sdp_neg_test.c"
#define START_TEST 0
enum session_type
{
REMOTE_OFFER,
LOCAL_OFFER,
};
struct offer_answer
{
enum session_type type; /* LOCAL_OFFER: REMOTE_OFFER: */
char *sdp1; /* local offer remote offer */
char *sdp2; /* remote answer initial local */
char *sdp3; /* local active media local answer */
};
struct test
{
const char *title;
unsigned offer_answer_count;
struct offer_answer offer_answer[4];
} test[] =
{
/* test 0: */
{
/*********************************************************************
* RFC 3264 examples, section 10.1 (Alice's view)
*
* Difference from the example:
* - Bob's port number of the third media stream in the first answer
* is changed (make it different than Alice's)
* - in the second offer/answer exchange, Alice can't accept the
* additional line since she didn't specify the capability
* in the initial negotiator creation.
*/
"RFC 3264 example 10.1 (Alice's view)",
2,
{
{
LOCAL_OFFER,
/* Alice sends offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
"s= \r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 51372 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* Received Bob's answer: */
"v=0\r\n"
"o=bob 2890844730 2890844730 IN IP4 host.example.com\r\n"
"s= \r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 49920 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"m=video 53002 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* Alice's SDP now: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
"s= \r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
},
{
REMOTE_OFFER,
/* Bob wants to change his local SDP
* (change local port for the first stream and add new stream)
* Received SDP from Bob:
*/
"v=0\r\n"
"o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 65422 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"m=video 53002 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
"m=audio 51434 RTP/AVP 110\r\n"
"a=rtpmap:110 telephone-events/8000\r\n"
"a=recvonly\r\n",
NULL,
/* Alice's SDP now */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
"s= \r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n" /* <-- this is not necessary */
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
"m=audio 0 RTP/AVP 110\r\n"
"a=rtpmap:110 telephone-events/8000\r\n"
"a=sendonly\r\n"
}
}
},
/* test 1: */
{
/*********************************************************************
* RFC 3264 examples, section 10.1. (Bob's view)
*
* Difference:
* - the SDP version in Bob's capability is changed to ver-1.
*/
"RFC 3264 example 10.1 (Bob's view)",
2,
{
{
REMOTE_OFFER,
/* Remote offer from Alice: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
"s= \r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 51372 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* Bob's capability: */
"v=0\r\n"
"o=bob 2890844730 2890844729 IN IP4 host.example.com\r\n"
"s= \r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 49920 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* This's how Bob's answer should look like: */
"v=0\r\n"
"o=bob 2890844730 2890844730 IN IP4 host.example.com\r\n"
"s= \r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 49920 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
},
{
LOCAL_OFFER,
/* Bob wants to change his local SDP
* (change local port for the first stream and add new stream)
*/
"v=0\r\n"
"o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 65422 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
"m=audio 51434 RTP/AVP 110\r\n"
"a=rtpmap:110 telephone-events/8000\r\n"
"a=recvonly\r\n",
/* Got answer from Alice */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
"s=-\r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
"m=audio 53122 RTP/AVP 110\r\n"
"a=rtpmap:110 telephone-events/8000\r\n"
"a=sendonly\r\n",
/* This is how Bob's SDP should look like after negotiation */
"v=0\r\n"
"o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 65422 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"m=video 53000 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
"m=audio 51434 RTP/AVP 110\r\n"
"a=rtpmap:110 telephone-events/8000\r\n"
"a=recvonly\r\n"
}
}
},
/* test 2: */
{
/*********************************************************************
* RFC 3264 examples, section 10.2.
* This is from Alice's point of view.
*/
"RFC 3264 example 10.2 (Alice's view)",
2,
{
{
LOCAL_OFFER,
/* The initial offer from Alice to Bob indicates a single audio
* stream with the three audio codecs that are available in the
* DSP. The stream is marked as inactive,
*/
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
"s=-\r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 62986 RTP/AVP 0 4 18\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=rtpmap:18 G729/8000\r\n"
"a=inactive\r\n",
/* Bob can support dynamic switching between PCMU and G.723. So,
* he sends the following answer:
*/
"v=0\r\n"
"o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 54344 RTP/AVP 0 4\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=inactive\r\n",
/* This is how Alice's media should look like after negotiation */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
"s=-\r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 62986 RTP/AVP 0 4\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=inactive\r\n",
},
{
LOCAL_OFFER,
/* Alice sends an updated offer with a sendrecv stream: */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
"s=-\r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 62986 RTP/AVP 4\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=sendrecv\r\n",
/* Bob accepts the single codec: */
"v=0\r\n"
"o=bob 2890844730 2890844732 IN IP4 host.example.com\r\n"
"s= \r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 54344 RTP/AVP 4\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=sendrecv\r\n",
/* This is how Alice's media should look like after negotiation */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
"s=-\r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 62986 RTP/AVP 4\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=sendrecv\r\n"
}
}
},
#if 0
// this test is commented, this causes error:
// No suitable codec for remote offer (PJMEDIA_SDPNEG_NOANSCODEC),
// since currently the negotiator always answer with one codec,
// PCMU in this case, while PCMU is not included in the second offer.
/* test 3: */
{
/*********************************************************************
* RFC 3264 examples, section 10.2.
* This is from Bob's point of view.
*
* Difference:
* - The SDP version number in Bob's initial capability is ver-1
*/
"RFC 3264 example 10.2 (Bob's view)",
2,
{
{
REMOTE_OFFER,
/* Bob received offer from Alice:
*/
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
"s=-\r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 62986 RTP/AVP 0 4 18\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=rtpmap:18 G729/8000\r\n"
"a=inactive\r\n",
/* Bob's capability:
*/
"v=0\r\n"
"o=bob 2890844730 2890844730 IN IP4 host.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 54344 RTP/AVP 0 4\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=inactive\r\n",
/* This is how Bob's media should look like after negotiation */
"v=0\r\n"
"o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 54344 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=inactive\r\n"
},
{
REMOTE_OFFER,
/* Received updated Alice's SDP: offer with a sendrecv stream: */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
"s=-\r\n"
"c=IN IP4 host.anywhere.com\r\n"
"t=0 0\r\n"
"m=audio 62986 RTP/AVP 4\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=sendrecv\r\n",
/* Bob accepts the single codec: */
NULL,
/* This is how Bob's media should look like after negotiation */
"v=0\r\n"
"o=bob 2890844730 2890844732 IN IP4 host.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.example.com\r\n"
"t=0 0\r\n"
"m=audio 54344 RTP/AVP 4\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=sendrecv\r\n",
}
}
},
#endif
/* test 4: */
{
/*********************************************************************
* RFC 4317 Sample 2.1: Audio and Video 1 (Alice's view)
*
* This common scenario shows a video and audio session in which
* multiple codecs are offered but only one is accepted. As a result of
* the exchange shown below, Alice and Bob may send only PCMU audio and
* MPV video. Note: Dynamic payload type 97 is used for iLBC codec
*/
"RFC 4317 section 2.1: Audio and Video 1 (Alice's view)",
1,
{
{
LOCAL_OFFER,
/* Alice's local offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0 8 97\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=video 51372 RTP/AVP 31 32\r\n"
"a=rtpmap:31 H261/90000\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* Received answer from Bob: */
"v=0\r\n"
"o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49174 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 49170 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* This is how Alice's media should look like now: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 51372 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
}
}
},
/* test 5: */
{
/*********************************************************************
* RFC 4317 Sample 2.1: Audio and Video 1 (Bob's view)
*
* This common scenario shows a video and audio session in which
* multiple codecs are offered but only one is accepted. As a result of
* the exchange shown below, Alice and Bob may send only PCMU audio and
* MPV video. Note: Dynamic payload type 97 is used for iLBC codec
*
* Difference:
* - Bob's initial capability version number
*/
"RFC 4317 section 2.1: Audio and Video 1 (Bob's view)",
1,
{
{
REMOTE_OFFER,
/* Received Alice's local offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0 8 97\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=video 51372 RTP/AVP 31 32\r\n"
"a=rtpmap:31 H261/90000\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* Bob's capability: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49174 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 49170 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* This is how Bob's media should look like now: */
"v=0\r\n"
"o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
"s=-\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49174 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 49170 RTP/AVP 32\r\n"
"a=rtpmap:32 MPV/90000\r\n"
}
}
},
/* test 6: */
{
/*********************************************************************
* RFC 4317 Sample 2.2: Audio and Video 2 (Alice's view)
*
* Difference:
* - Bob's initial capability version number
*/
"RFC 4317 section 2.2: Audio and Video 2 (Alice's view)",
2,
{
{
LOCAL_OFFER,
/* Alice sends offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0 8 97\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=video 51372 RTP/AVP 31 32\r\n"
"a=rtpmap:31 H261/90000\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49172 RTP/AVP 0 8\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n",
/* This is how Alice's media should look like now: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0 8\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
},
{
LOCAL_OFFER,
/* Alice sends updated offer: */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 51372 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n",
/* Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49172 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n",
/* This is how Alice's SDP should look like: */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 51372 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
}
}
},
/* test 7: */
{
/*********************************************************************
* RFC 4317 Sample 2.2: Audio and Video 2 (Bob's view)
*
* Difference:
* - Bob's initial capability version number
*/
"RFC 4317 section 2.2: Audio and Video 2 (Bob's view)",
2,
{
{
REMOTE_OFFER,
/* Received offer from alice: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0 8 97\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=video 51372 RTP/AVP 31 32\r\n"
"a=rtpmap:31 H261/90000\r\n"
"a=rtpmap:32 MPV/90000\r\n",
/* Bob's initial capability: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49172 RTP/AVP 0 8\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n",
/* This is how Bob's answer should look like now: */
"v=0\r\n"
"o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49172 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
},
{
REMOTE_OFFER,
/* Received updated offer from Alice: */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 51372 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n",
/* Bob's answer: */
NULL,
/* This is how Bob's answer should look like: */
"v=0\r\n"
"o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49172 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
}
}
},
/* test 8: */
{
/*********************************************************************
* RFC 4317 Sample 2.4: Audio and Telephone-Events (Alice's view)
*
*/
"RFC 4317 section 2.4: Audio and Telephone-Events (Alice's view)",
1,
{
{
LOCAL_OFFER,
/* Alice sends offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0 97\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=audio 49172 RTP/AVP 98\r\n"
"a=rtpmap:98 telephone-event/8000\r\n"
"a=sendonly\r\n",
/* Received Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49172 RTP/AVP 97\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=audio 49174 RTP/AVP 98\r\n"
"a=rtpmap:98 telephone-event/8000\r\n"
"a=recvonly\r\n",
/* Alice's SDP now: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 97\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=audio 49172 RTP/AVP 98\r\n"
"a=rtpmap:98 telephone-event/8000\r\n"
"a=sendonly\r\n"
}
}
},
/* test 9: */
{
/*********************************************************************
* RFC 4317 Sample 2.4: Audio and Telephone-Events (Bob's view)
*
* Difference:
* - Bob's initial SDP version number
* - Bob's capability are added with more formats, and the
* stream order is interchanged to test the negotiator.
*/
"RFC 4317 section 2.4: Audio and Telephone-Events (Bob's view)",
1,
{
{
REMOTE_OFFER,
/* Received Alice's offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0 97\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=audio 49172 RTP/AVP 98\r\n"
"a=rtpmap:98 telephone-event/8000\r\n"
"a=sendonly\r\n",
/* Bob's initial capability: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49174 RTP/AVP 4 98\r\n"
"a=rtpmap:98 telephone-event/8000\r\n"
"m=audio 49172 RTP/AVP 97 8 99\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"a=rtpmap:99 telephone-event/8000\r\n",
/* Bob's answer should be: */
"v=0\r\n"
"o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49172 RTP/AVP 97\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"m=audio 49174 RTP/AVP 98\r\n"
"a=rtpmap:98 telephone-event/8000\r\n"
"a=recvonly\r\n"
}
}
},
/* test 10: */
{
/*********************************************************************
* RFC 4317 Sample 2.6: Audio with Telephone-Events (Alice's view)
*
*/
"RFC 4317 section 2.6: Audio with Telephone-Events (Alice's view)",
1,
{
{
LOCAL_OFFER,
/* Alice sends offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 51372 RTP/AVP 97 101\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"a=rtpmap:101 telephone-event/8000\r\n",
/* Received bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 0 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 49170 RTP/AVP 97 101\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"a=rtpmap:101 telephone-event/8000\r\n",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 0 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 51372 RTP/AVP 97 101\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"a=rtpmap:101 telephone-event/8000\r\n"
}
}
},
/* test 11: */
{
/*********************************************************************
* RFC 4317 Sample 2.6: Audio with Telephone-Events (Bob's view)
*
* Difference:
* - Bob's SDP version number
* - Bob's initial capability are expanded with multiple m lines
* and more formats
*/
"RFC 4317 section 2.6: Audio with Telephone-Events (Bob's view)",
1,
{
{
REMOTE_OFFER,
/* Received Alice's offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 51372 RTP/AVP 97 101\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"a=rtpmap:101 telephone-event/8000\r\n",
/* Bob's initial capability also has video: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 4 97 101\r\n"
"a=rtpmap:4 G723/8000\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"a=rtpmap:101 telephone-event/8000\r\n"
"m=video 1000 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n",
/* Bob's answer should be: */
"v=0\r\n"
"o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 0 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 49170 RTP/AVP 97 101\r\n"
"a=rtpmap:97 iLBC/8000\r\n"
"a=rtpmap:101 telephone-event/8000\r\n",
}
}
},
/* test 12: */
{
/*********************************************************************
* Ticket #527: More lenient SDP negotiator.
*/
"Ticket #527 scenario #1: Partial answer",
1,
{
{
LOCAL_OFFER,
/* Alice sends offer audio and video: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 4000 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n",
/* Receive Bob's answer only audio: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
}
}
},
/* test 13: */
{
/*********************************************************************
* Ticket #527: More lenient SDP negotiator.
*/
"Ticket #527 scenario #1: Media mismatch in answer",
1,
{
{
LOCAL_OFFER,
/* Alice sends offer audio and video: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 3000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 4000 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n",
/* Receive Bob's answer two audio: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 49172 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 3000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
}
}
},
/* test 14: */
{
/*********************************************************************
* Ticket #527: More lenient SDP negotiator.
*/
"Ticket #527 scenario #2: Modify offer - partial streams",
2,
{
{
LOCAL_OFFER,
/* Alice sends offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 3000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 3100 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 3200 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Receive Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 4000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 4100 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 4200 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 3000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 3100 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 3200 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
},
{
LOCAL_OFFER,
/* Alice modifies offer with only specify one audio: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 5200 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"",
/* Receive Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 7000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 0 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 5200 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 0 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 0 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
}
}
},
/* test 15: */
{
/*********************************************************************
* Ticket #527: More lenient SDP negotiator.
*/
"Ticket #527 scenario #2: Modify offer - unordered m= lines",
2,
{
{
LOCAL_OFFER,
/* Alice sends offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 3000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 3200 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Receive Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 4000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 4200 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 3000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 3200 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
},
{
LOCAL_OFFER,
/* Alice modifies offer with unordered m= lines: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=video 5000 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"m=audio 5200 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"",
/* Receive Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 7000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 2000 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 5200 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 5000 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
}
}
},
/* test 16: */
{
/*********************************************************************
* Ticket #527: More lenient SDP negotiator.
*/
"Ticket #527 scenario #2: Modify offer - partial & unordered streams",
2,
{
{
LOCAL_OFFER,
/* Alice sends offer: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 3000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 3200 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 3400 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Receive Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 4000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 4200 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 4400 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 3000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 3200 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 3400 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
},
{
LOCAL_OFFER,
/* Alice modifies offer by specifying partial and unordered media: */
"v=0\r\n"
"o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=video 5000 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"m=audio 7000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"",
/* Receive Bob's answer: */
"v=0\r\n"
"o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
"s=bob\r\n"
"c=IN IP4 host.biloxi.example.com\r\n"
"t=0 0\r\n"
"m=audio 4000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 0 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 4400 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
/* Alice's local SDP should be: */
"v=0\r\n"
"o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
"s=alice\r\n"
"c=IN IP4 host.atlanta.example.com\r\n"
"t=0 0\r\n"
"m=audio 7000 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=audio 0 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"m=video 5000 RTP/AVP 31\r\n"
"a=rtpmap:31 H261/90000\r\n"
"",
}
}
},
};
static const char *find_diff(const char *s1, const char *s2,
int *line)
{
*line = 1;
while (*s2 && *s1) {
if (*s2 != *s1)
return s2;
if (*s2 == '\n')
++*line;
++s2, ++s1;
}
return s2;
}
static int compare_sdp_string(const char *cmp_title,
const char *title1,
const pjmedia_sdp_session *sdp1,
const char *title2,
const pjmedia_sdp_session *sdp2,
pj_status_t logical_cmp)
{
char sdpbuf1[1024], sdpbuf2[1024];
pj_ssize_t len1, len2;
len1 = pjmedia_sdp_print(sdp1, sdpbuf1, sizeof(sdpbuf1));
if (len1 < 1) {
PJ_LOG(3,(THIS_FILE," error: printing sdp1"));
return -1;
}
sdpbuf1[len1] = '\0';
len2 = pjmedia_sdp_print(sdp2, sdpbuf2, sizeof(sdpbuf2));
if (len2 < 1) {
PJ_LOG(3,(THIS_FILE," error: printing sdp2"));
return -1;
}
sdpbuf2[len2] = '\0';
if (logical_cmp != PJ_SUCCESS) {
char errbuf[80];
pjmedia_strerror(logical_cmp, errbuf, sizeof(errbuf));
PJ_LOG(3,(THIS_FILE,"%s mismatch: %s\n"
"%s:\n"
"%s\n"
"%s:\n"
"%s\n",
cmp_title,
errbuf,
title1, sdpbuf1,
title2, sdpbuf2));
return -1;
} else if (strcmp(sdpbuf1, sdpbuf2) != 0) {
int line;
const char *diff;
PJ_LOG(3,(THIS_FILE,"%s mismatch:\n"
"%s:\n"
"%s\n"
"%s:\n"
"%s\n",
cmp_title,
title1, sdpbuf1,
title2, sdpbuf2));
diff = find_diff(sdpbuf1, sdpbuf2, &line);
PJ_LOG(3,(THIS_FILE,"Difference: line %d:\n"
"%s",
line, diff));
return -1;
} else {
return 0;
}
}
static int offer_answer_test(pj_pool_t *pool, pjmedia_sdp_neg **p_neg,
struct offer_answer *oa)
{
pjmedia_sdp_session *sdp1;
pjmedia_sdp_neg *neg;
pj_status_t status;
status = pjmedia_sdp_parse(pool, oa->sdp1, pj_ansi_strlen(oa->sdp1),
&sdp1);
if (status != PJ_SUCCESS) {
app_perror(status, " error: unexpected parse status for sdp1");
return -10;
}
status = pjmedia_sdp_validate(sdp1);
if (status != PJ_SUCCESS) {
app_perror(status, " error: sdp1 validation failed");
return -15;
}
neg = *p_neg;
if (oa->type == LOCAL_OFFER) {
/*
* Local creates offer first.
*/
pjmedia_sdp_session *sdp2, *sdp3;
const pjmedia_sdp_session *active;
if (neg == NULL) {
/* Create negotiator with local offer. */
status = pjmedia_sdp_neg_create_w_local_offer(pool, sdp1, &neg);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_create_w_local_offer");
return -20;
}
*p_neg = neg;
} else {
/* Modify local offer */
status = pjmedia_sdp_neg_modify_local_offer(pool, neg, sdp1);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_modify_local_offer");
return -30;
}
}
/* Parse and validate remote answer */
status = pjmedia_sdp_parse(pool, oa->sdp2, pj_ansi_strlen(oa->sdp2),
&sdp2);
if (status != PJ_SUCCESS) {
app_perror(status, " error: parsing sdp2");
return -40;
}
status = pjmedia_sdp_validate(sdp2);
if (status != PJ_SUCCESS) {
app_perror(status, " error: sdp2 validation failed");
return -50;
}
/* Give the answer to negotiator. */
status = pjmedia_sdp_neg_set_remote_answer(pool, neg, sdp2);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_rx_remote_answer");
return -60;
}
/* Negotiate remote answer with local answer */
status = pjmedia_sdp_neg_negotiate(pool, neg, 0);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_negotiate");
return -70;
}
/* Get the local active media. */
status = pjmedia_sdp_neg_get_active_local(neg, &active);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_get_local");
return -80;
}
/* Parse and validate the correct active media. */
status = pjmedia_sdp_parse(pool, oa->sdp3, pj_ansi_strlen(oa->sdp3),
&sdp3);
if (status != PJ_SUCCESS) {
app_perror(status, " error: parsing sdp3");
return -90;
}
status = pjmedia_sdp_validate(sdp3);
if (status != PJ_SUCCESS) {
app_perror(status, " error: sdp3 validation failed");
return -100;
}
/* Compare active with sdp3 */
status = pjmedia_sdp_session_cmp(active, sdp3, 0);
if (status != PJ_SUCCESS) {
app_perror(status, " error: active local comparison mismatch");
compare_sdp_string("Logical cmp after negotiatin remote answer",
"Active local sdp from negotiator", active,
"The correct active local sdp", sdp3,
status);
return -110;
}
/* Compare the string representation oa both sdps */
status = compare_sdp_string("String cmp after negotiatin remote answer",
"Active local sdp from negotiator", active,
"The correct active local sdp", sdp3,
PJ_SUCCESS);
if (status != 0)
return -120;
} else {
/*
* Remote creates offer first.
*/
pjmedia_sdp_session *sdp2 = NULL, *sdp3;
const pjmedia_sdp_session *answer;
if (oa->sdp2) {
/* Parse and validate initial local capability */
status = pjmedia_sdp_parse(pool, oa->sdp2, pj_ansi_strlen(oa->sdp2),
&sdp2);
if (status != PJ_SUCCESS) {
app_perror(status, " error: parsing sdp2");
return -200;
}
status = pjmedia_sdp_validate(sdp2);
if (status != PJ_SUCCESS) {
app_perror(status, " error: sdp2 validation failed");
return -210;
}
} else if (neg) {
status = pjmedia_sdp_neg_get_active_local(neg, &sdp2);
if (status != PJ_SUCCESS) {
app_perror(status,
" error: pjmedia_sdp_neg_get_active_local");
return -215;
}
}
if (neg == NULL) {
/* Create negotiator with remote offer. */
status = pjmedia_sdp_neg_create_w_remote_offer(pool, sdp2, sdp1, &neg);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_create_w_remote_offer");
return -220;
}
*p_neg = neg;
} else {
/* Received subsequent offer from remote. */
status = pjmedia_sdp_neg_set_remote_offer(pool, neg, sdp1);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_rx_remote_offer");
return -230;
}
status = pjmedia_sdp_neg_set_local_answer(pool, neg, sdp2);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_set_local_answer");
return -235;
}
}
/* Negotiate. */
status = pjmedia_sdp_neg_negotiate(pool, neg, 0);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_negotiate");
return -240;
}
/* Get our answer. */
status = pjmedia_sdp_neg_get_active_local(neg, &answer);
if (status != PJ_SUCCESS) {
app_perror(status, " error: pjmedia_sdp_neg_get_local");
return -250;
}
/* Parse the correct answer. */
status = pjmedia_sdp_parse(pool, oa->sdp3, pj_ansi_strlen(oa->sdp3),
&sdp3);
if (status != PJ_SUCCESS) {
app_perror(status, " error: parsing sdp3");
return -260;
}
/* Validate the correct answer. */
status = pjmedia_sdp_validate(sdp3);
if (status != PJ_SUCCESS) {
app_perror(status, " error: sdp3 validation failed");
return -270;
}
/* Compare answer from negotiator and the correct answer */
status = pjmedia_sdp_session_cmp(sdp3, answer, 0);
if (status != PJ_SUCCESS) {
compare_sdp_string("Logical cmp after negotiating remote offer",
"Local answer from negotiator", answer,
"The correct local answer", sdp3,
status);
return -280;
}
/* Compare the string representation oa both answers */
status = compare_sdp_string("String cmp after negotiating remote offer",
"Local answer from negotiator", answer,
"The correct local answer", sdp3,
PJ_SUCCESS);
if (status != 0)
return -290;
}
return 0;
}
static int perform_test(pj_pool_t *pool, int test_index)
{
pjmedia_sdp_neg *neg = NULL;
unsigned i;
int rc;
for (i=0; i<test[test_index].offer_answer_count; ++i) {
rc = offer_answer_test(pool, &neg, &test[test_index].offer_answer[i]);
if (rc != 0) {
PJ_LOG(3,(THIS_FILE, " test %d offer answer %d failed with status %d",
test_index, i, rc));
return rc;
}
}
return 0;
}
int sdp_neg_test()
{
unsigned i;
int status;
for (i=START_TEST; i<PJ_ARRAY_SIZE(test); ++i) {
pj_pool_t *pool;
pool = pj_pool_create(mem, "sdp_neg_test", 4000, 4000, NULL);
if (!pool)
return PJ_ENOMEM;
PJ_LOG(3,(THIS_FILE," test %d: %s", i, test[i].title));
status = perform_test(pool, i);
pj_pool_release(pool);
if (status != 0) {
return status;
}
}
return 0;
}