diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-02-02 19:16:07 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-02-02 19:16:07 +0000 |
commit | 5125fc4191998ab13529ee59706f95116fc1725a (patch) | |
tree | e1f9b4fe1c3c3a1a734e099333c7107678065df9 /pjmedia/src/test/sdp_neg_test.c | |
parent | 6cbba81e8937d6793705608e7e68e83ec950dd2a (diff) |
Added SDP negotiator and changed SDP structs (tested)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@129 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia/src/test/sdp_neg_test.c')
-rw-r--r-- | pjmedia/src/test/sdp_neg_test.c | 1209 |
1 files changed, 1209 insertions, 0 deletions
diff --git a/pjmedia/src/test/sdp_neg_test.c b/pjmedia/src/test/sdp_neg_test.c new file mode 100644 index 00000000..ff474a9a --- /dev/null +++ b/pjmedia/src/test/sdp_neg_test.c @@ -0,0 +1,1209 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2006 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" + } + } + }, + + /* 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", + } + } + }, + + /* 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" + "a=recvonly\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", + } + } + }, + +}; + +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_native_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_native_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_rx_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_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_native_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, *sdp3; + const pjmedia_sdp_session *answer; + + if (neg == NULL) { + /* Parse and validate initial local capability */ + status = pjmedia_sdp_parse(pool, oa->sdp2, pj_native_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; + } + + /* 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_rx_remote_offer(pool, neg, sdp1); + if (status != PJ_SUCCESS) { + app_perror(status, " error: pjmedia_sdp_neg_rx_remote_offer"); + return -230; + } + } + + /* 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_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_native_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; +} + |