r2748 - in trunk/libminisip: include/libminisip/mediahandler source/mediahandler

mikma at minisip.org mikma at minisip.org
Thu Sep 7 13:38:01 CEST 2006


Author: mikma
Date: 2006-09-07 13:38:00 +0200 (Thu, 07 Sep 2006)
New Revision: 2748

Modified:
   trunk/libminisip/include/libminisip/mediahandler/Session.h
   trunk/libminisip/source/mediahandler/Session.cxx
Log:
Add IPv6 and ANAT (RFC 4091) support to sdp negotiator in Session.


Modified: trunk/libminisip/include/libminisip/mediahandler/Session.h
===================================================================
--- trunk/libminisip/include/libminisip/mediahandler/Session.h	2006-09-07 11:03:50 UTC (rev 2747)
+++ trunk/libminisip/include/libminisip/mediahandler/Session.h	2006-09-07 11:38:00 UTC (rev 2748)
@@ -68,7 +68,7 @@
 		 * description
 		 * @param config security related configuration for the call
 		 */
-		Session( std::string localIp, SipDialogSecurityConfig &config );
+		Session( std::string localIp, SipDialogSecurityConfig &config, std::string localIp6 = "" );
 		
 		/**
 		 * Destructor.
@@ -93,9 +93,10 @@
 		/**
 		 * Used by the SIP stack to query the session description 
 		 * offer (SDP offer), upon session initiation.
+		 * @param anatSupported Use ANAT (RFC 4091)
 		 * @returns a reference to the SDP object
 		 */
-		MRef<SdpPacket *> getSdpOffer();
+		MRef<SdpPacket *> getSdpOffer( bool anatSupported = false );
 		
 		/**
 		 * Used by the SIP stack to query the session description
@@ -270,6 +271,7 @@
 
 		MRef<KeyAgreement *> ka;
 		std::string localIpString;
+		std::string localIp6String;
 		MRef<SdpPacket *> sdpAnswer;
 		bool secured;
 

Modified: trunk/libminisip/source/mediahandler/Session.cxx
===================================================================
--- trunk/libminisip/source/mediahandler/Session.cxx	2006-09-07 11:03:50 UTC (rev 2747)
+++ trunk/libminisip/source/mediahandler/Session.cxx	2006-09-07 11:38:00 UTC (rev 2748)
@@ -35,7 +35,6 @@
 #include<libminisip/mediahandler/RtpReceiver.h>
 #include<libminisip/mediahandler/DtmfSender.h>
 #include<libminisip/codecs/Codec.h>
-#include<libminisip/ipprovider/IpProvider.h>
 #include<libminisip/sdp/SdpPacket.h>
 #include<libminisip/sdp/SdpHeaderV.h>
 #include<libminisip/sdp/SdpHeaderT.h>
@@ -66,7 +65,7 @@
 SessionRegistry * Session::registry = NULL;
 MRef<KeyAgreement *> Session::precomputedKa = NULL;
 
-Session::Session( string localIp, SipDialogSecurityConfig &securityConfig ):ka(NULL),localIpString(localIp){
+Session::Session( string localIp, SipDialogSecurityConfig &securityConfig, string localIp6 ):ka(NULL),localIpString(localIp), localIp6String(localIp6){
 	this->securityConfig = securityConfig; // hardcopy
 	this->ka = Session::precomputedKa;
 	dtmfTOProvider = new TimeoutProvider<DtmfEvent *, MRef<DtmfSender *> >;
@@ -94,6 +93,114 @@
 	dtmfTOProvider->stopThread();
 }
 
+
+static string matchAnat(string group, MRef<SdpPacket *> offer, string localIpString, string localIp6String){
+	vector<string> groups;
+
+#ifdef DEBUG_OUTPUT	
+	cerr << "Found group:" << group << endl;
+#endif
+	if( group.substr(0, 5) == "ANAT "){
+		size_t start = 5;
+		for(;;){
+			string id;
+			size_t pos = group.find(' ', start);
+
+			if( pos == string::npos )
+				id = group.substr( start );
+			else
+				id = group.substr( start, pos - start );
+			groups.push_back( id );
+#ifdef DEBUG_OUTPUT	
+			cerr << "Found id: " << id << endl;
+#endif
+			if( pos == string::npos )
+				break;
+			
+			start = pos + 1;
+		}
+	}
+
+	// Search for an ANAT group id with all valid streams.
+	vector<string>::iterator j;
+	for( j = groups.begin(); j != groups.end(); j++ ){
+		string id = *j;
+		bool idOk = false;
+		
+		unsigned int i;
+		for( i = 0; i < offer->getHeaders().size(); i++ ){
+			if( offer->getHeaders()[i]->getType() != SDP_HEADER_TYPE_M )
+				continue;
+			
+			MRef<SdpHeaderM *> offerM = (SdpHeaderM*)*offer->getHeaders()[i];
+			string curId = offerM->getAttribute("mid", 0);
+			if( id != curId ){
+#ifdef DEBUG_OUTPUT	
+				cout << "Skip id:" << curId << endl;
+#endif
+				continue;
+			}
+			
+#ifdef DEBUG_OUTPUT	
+			cout << "Header " << i << endl;
+#endif
+			MRef<SdpHeaderC *> c = offerM->getConnection();
+
+			if( !c ){
+#ifdef DEBUG_OUTPUT	
+				cout << "No connection header:" << endl;
+#endif
+				// Ignore, may be an unsupported media type 
+				continue;
+			}
+
+			if( c->getNetType() != "IN" ){
+#ifdef DEBUG_OUTPUT	
+				cout << "Unsupported net type:" << c->getNetType() << endl;
+#endif
+				idOk = false;
+				break;
+			}
+			
+			if( c->getAddrType() != "IP4" && localIp6String.empty() ){
+#ifdef DEBUG_OUTPUT	
+				cout << "Unsupported addr type:" << c->getAddrType() << endl;
+#endif
+				idOk = false;
+				break;
+			}
+			
+			if( c->getAddrType() != "IP6" && localIpString.empty() ){
+				cout << "Unsupported addr type:" << c->getAddrType() << endl;
+				idOk = false;
+				break;
+			}
+			
+			if( offerM->getPort() == 0 ){
+#ifdef DEBUG_OUTPUT	
+				cout << "Disabled port:" << endl;
+#endif
+				// Ignore, may be an unsupported media type 
+				continue;
+			}
+			
+#ifdef DEBUG_OUTPUT	
+			cerr << "Found valid group id:" << curId << endl;
+#endif
+			idOk = true;
+		}
+		
+		if( idOk ){
+#ifdef DEBUG_OUTPUT	
+			cout << "Return id:" << id << endl;
+#endif
+			return id;
+		}
+	}
+
+	return "";
+}
+
 MRef<SdpPacket *> Session::emptySdp(){
 	MRef<SdpPacket *> result;
 
@@ -102,32 +209,38 @@
 	MRef<SdpHeader*> v = new SdpHeaderV(0);
 	result->addHeader(v);
 
-	/* FIXME */
-	string addrtype = "IP4";
+	string ipString;
+	string addrtype;
 
+	if( !localIpString.empty() ){
+		ipString = localIpString;
+		addrtype = "IP4";
+	}
+	else{
+		ipString = localIp6String;
+		addrtype = "IP6";
+	}
+
 	MRef<SdpHeader*> o = new SdpHeaderO("","3344","3344","IN", 
-			addrtype, localIpString );
+			addrtype, ipString );
 	result->addHeader(o);
 
 	MRef<SdpHeader*> s = new SdpHeaderS(SESSION_LINE);
 	result->addHeader(s);
 
-	MRef<SdpHeader*> c = new SdpHeaderC("IN", addrtype, localIpString );
-	result->addHeader(c);
-
 	MRef<SdpHeader*> t = new SdpHeaderT(0,0);
 	result->addHeader(t);
 
 	return result;
 }
 
-MRef<SdpPacket *> Session::getSdpOffer(){ // used by the initiator when creating the first message
+MRef<SdpPacket *> Session::getSdpOffer( bool anatSupported ){ // used by the initiator when creating the first message
 	MRef<SdpPacket *> result;
 	list< MRef<MediaStreamReceiver *> >::iterator i;
 	std::list<std::string>::iterator iAttribute;
 	std::list<std::string> attributes;
 	string type;
-	uint16_t localPort;	
+	uint16_t localPort = 0;
 	MRef<SdpHeaderM *> m;
 	string keyMgmtMessage;
 	std::list<MRef<Codec *> > codecs;
@@ -135,6 +248,7 @@
 	uint8_t payloadType;
 	string rtpmap;
 	const char *transport = NULL;
+	bool anat = false;
 
 // 	cerr << "Session::getSdpOffer" << endl;
 	result = emptySdp();
@@ -152,11 +266,15 @@
 		transport = "RTP/AVP";
 	}
 
+	if( anatSupported && !localIpString.empty() && !localIp6String.empty() ){
+		anat = true;
+		result->setSessionLevelAttribute( "group", "ANAT 1 2" );
+	}
+
 	for( i = mediaStreamReceivers.begin(); i != mediaStreamReceivers.end(); i++ ){
 		codecs = (*i)->getAvailableCodecs();
 
 		type = (*i)->getSdpMediaType();
-		localPort = (*i)->getPort();
 		m = new SdpHeaderM( type, localPort, 1, transport );
 		
 		for( iC = codecs.begin(); iC != codecs.end(); iC ++ ){
@@ -192,6 +310,53 @@
 			a->setAttributes( *iAttribute );
 			m->addAttribute( *a );
 		}
+
+		if( anat ){
+			MRef<SdpHeaderM*> m4 = m;
+			MRef<SdpHeaderM*> m6 = new SdpHeaderM( **m );
+
+			// IPv4
+			m4->setPort( (*i)->getPort("IP4") );
+
+			MRef<SdpHeaderA*> mid2 = new SdpHeaderA( "a=mid:2" );
+
+			m4->addAttribute( mid2 );
+
+			MRef<SdpHeaderC*> conn4 = new SdpHeaderC( "IN", "IP4", localIpString );
+			conn4->set_priority( m4->getPriority() );
+			m4->setConnection( *conn4 );
+
+			// IPv6
+			m6->setPort( (*i)->getPort("IP6") );
+
+			MRef<SdpHeaderA*> mid1 = new SdpHeaderA( "a=mid:1" );
+			m6->addAttribute( mid1 );
+
+
+			MRef<SdpHeaderC*> conn6 = new SdpHeaderC( "IN", "IP6", localIp6String );
+			conn6->set_priority( m6->getPriority() );
+			m6->setConnection( *conn6 );
+
+			result->addHeader( *m6 );
+		}
+		else{
+			string ipString;
+			string addrtype;
+
+			if( !localIpString.empty() ){
+				ipString = localIpString;
+				addrtype = "IP4";
+			}
+			else{
+				ipString = localIp6String;
+				addrtype = "IP6";
+			}
+
+			MRef<SdpHeaderC*> c = new SdpHeaderC("IN", addrtype, ipString );
+			m->setConnection(c);
+			m->setPort( (*i)->getPort( addrtype ) );
+		}
+
 	}
 #ifdef DEBUG_OUTPUT	
 	cerr << "Session::getSdpOffer: " << endl << result->getString() << endl << endl;
@@ -235,6 +400,16 @@
 		}
 		*/
 	}
+
+	string group = answer->getSessionLevelAttribute("group");
+	string selectedId;
+
+	if( !group.empty() )
+		selectedId = matchAnat(group, answer, localIpString, localIp6String);
+#ifdef DEBUG_OUTPUT	
+	cout << "Selected:" << selectedId << endl;
+#endif
+
 	MRef<SdpHeaderC*> sessionConn = answer->getSessionLevelConnection();
 
 	for( i = 0; i < answer->getHeaders().size(); i++ ){
@@ -244,6 +419,22 @@
 			cerr << "Session::setSdpAnswer - trying media line " << m->getString() << endl;
 #endif
 			
+			if( !group.empty() ){
+#ifdef DEBUG_OUTPUT
+				cout << "Media " << i << endl;
+#endif
+				const string &id = m->getAttribute("mid", 0);
+#ifdef DEBUG_OUTPUT
+				cout << "id: " << id << endl;
+#endif
+				if( id != selectedId ){
+#ifdef DEBUG_OUTPUT
+					cerr << "Skip unselected id:" << id << endl;
+#endif
+					continue;
+				}
+			}
+
 			MRef<IPAddress *> remoteAddress;
 			MRef<SdpHeaderC *> c = m->getConnection();
 			if( !c )
@@ -263,8 +454,10 @@
 					continue;
 #ifdef DEBUG_OUTPUT
 				cerr << "Session::setSdpAnswer - Found receiver at " << remoteAddress->getString() << endl;
+				cerr << "Receiver found: " << !!receiver << endl;
 #endif
-				if( m->getPort() == 0 ){
+
+				if( receiver && m->getPort() == 0 ){
 					/* This offer was rejected */
 					receiver->disabled = true;
 				}
@@ -307,6 +500,10 @@
 					);
 			}
 #endif
+
+#ifdef DEBUG_OUTPUT	
+			cerr << "Set remote: " << remoteAddress->getString() << "," << m->getPort() << endl;
+#endif
 	
 			(*iSStream)->setPort( (uint16_t)m->getPort() );
 			(*iSStream)->setRemoteAddress( remoteAddress );
@@ -367,13 +564,53 @@
 
 	sdpAnswer = emptySdp();
 
+	string group = offer->getSessionLevelAttribute("group");
+	string selectedId;
+
+	if( !group.empty() ){
+		sdpAnswer->setSessionLevelAttribute("group", group);
+
+		selectedId = matchAnat(group, offer, localIpString, localIp6String);
+	}
+
+#ifdef DEBUG_OUTPUT	
+	cout << "Get remote addr " << endl;
+#endif
 	MRef<SdpHeaderC*> sessionConn = offer->getSessionLevelConnection();
 
+#ifdef DEBUG_OUTPUT	
+	cout << "Built empty sdp" << endl;
+#endif
+
 	for( i = 0; i < offer->getHeaders().size(); i++ ){
+#ifdef DEBUG_OUTPUT	
+		cout << "Header " << i << endl;
+#endif
 
 		if( offer->getHeaders()[i]->getType() == SDP_HEADER_TYPE_M ){
 			MRef<SdpHeaderM *> offerM = (SdpHeaderM*)*(offer->getHeaders()[i]);
 
+			MRef<SdpHeaderM *> answerM = new SdpHeaderM(
+					offerM->getMedia(), 0, 0,
+					offerM->getTransport() );
+
+			sdpAnswer->addHeader( *answerM );
+
+			if( !group.empty() ){
+#ifdef DEBUG_OUTPUT	
+				cout << "Media " << i << endl;
+#endif
+				const string &id = offerM->getAttribute("mid", 0);
+				if(!id.empty())
+					answerM->addAttribute(new SdpHeaderA("a=mid:" + id));
+
+#ifdef DEBUG_OUTPUT	
+				cout << "id: " << id << endl;
+#endif
+				if( id != selectedId )
+					continue;
+			}
+
 			const string &transport = offerM->getTransport();
 
 			if (transport != "RTP/AVP" &&
@@ -383,13 +620,6 @@
 				return false;
 			}
 
-
-			MRef<SdpHeaderM *> answerM = new SdpHeaderM(
-					offerM->getMedia(), 0, 0,
-					offerM->getTransport() );
-
-			sdpAnswer->addHeader( *answerM );
-
 			MRef<SdpHeaderC *> c = offerM->getConnection();
 			MRef<IPAddress *> remoteAddress;
 			string addrString;
@@ -408,8 +638,10 @@
 					continue;
 				addrString = localIpString;
 			}
-			else{
-				continue;
+			else if( c->getAddrType() == "IP6" ){
+				if( localIp6String.empty() )
+					continue;
+				addrString = localIp6String;
 			}
 
 			remoteAddress = c->getIPAdress();
@@ -420,7 +652,7 @@
 
 				if( receiver ){
 					if( answerM->getPort() == 0 ){
-						answerM->setPort( receiver->getPort() );
+						answerM->setPort( receiver->getPort( c->getAddrType() ) );
 					}
 					else{
 						/* This media has already been treated */



More information about the Minisip-devel mailing list