Browse Source

- Rewrite JingletoSDP and fix little issues in SDPtoJingle

pull/16/head
Jaussoin Timothée 12 years ago
parent
commit
0de25071ce
  1. 275
      lib/JingletoSDP.php
  2. 85
      lib/SDPtoJingle.php

275
lib/JingletoSDP.php

@ -1,129 +1,198 @@
<?php
class JingletoSDP {
private $sdp;
private $sdp = '';
private $jingle;
private $jid;
private $iceufrag = false;
private $icepwd = false;
private $icefingerprint = false;
private $icefingerprinthash = false;
private $valid = false;
private $values = array(
'session_id' => 1,
'session_version' => 0,
'nettype' => 'IN',
'addrtype' => 'IP4',
'unicast_address' => '0.0.0.0'
);
function __construct($jingle) {
$this->jingle = $jingle;
}
function generate() {
$username = substr($this->jingle['initiator'], 0, strpos($this->jingle['initiator'], '@'));
$sessid = $this->jingle['sid'];
$username = current(explode('@', $this->jingle->attributes()->initiator));
$sessid = $this->jingle->attributes()->sid;
$this->values['session_id'] = substr(base_convert($sessid, 30, 10), 0, 6);
//if($this->jingle->sdp)
// return $this->jingle->sdp;
foreach($this->jingle->children() as $content) {
$this->icepwd = $content->transport->attributes()->pwd;
$this->iceufrag = $content->transport->attributes()->ufrag;
$sdp_version =
'v=0';
if($content->transport->fingerprint) {
$this->icefingerprint = $content->transport->fingerprint;
$this->icefingerprinthash = $content->transport->fingerprint->attributes()->hash;
}
$sdp_origin =
'o='.
$username.' '.
$this->values['session_id'].' '.
$this->values['session_version'].' '.
$this->values['nettype'].' '.
$this->values['addrtype'].' '.
$this->values['unicast_address'];
$sdp_session_name =
's=SIP Call'; // Use the sessid ?
$sdp_timing =
't=0 0';
//payload and candidate
$p = $c = '';
$priority = '';
$port = false;
$ip = false;
$sdp_media = '';
//$proto = "RTP/AVP ";
$proto = "RTP/SAVPF ";
foreach($this->jingle->children() as $content) {
$sdp_media .=
"\nm=".$content->description->attributes()->media.
"\nc=IN IP4 0.0.0.0".
"\na=rtcp:1 IN IP4 0.0.0.0";
if(isset($content->transport->attributes()->ufrag))
$sdp_media .= "\na=ice-ufrag:".$content->transport->attributes()->ufrag;
if(isset($content->transport->attributes()->pwd))
$sdp_media .= "\na=ice-pwd:".$content->transport->attributes()->pwd;
foreach($content->description->children() as $payload) {
//payloads without clockrate are striped out
if($payload->attributes()->clockrate){
$p .=
"\na=rtpmap".
':'.$payload->attributes()->id.
' '.$payload->attributes()->name.
'/'.$payload->attributes()->clockrate;
switch($payload->getName()) {
case 'rtp-hdrext':
$sdp_media .=
"\na=extmap:".
$payload->attributes()->id;
if(isset($payload->attributes()->senders))
$sdp_media .= ' '.$payload->attributes()->senders;
$sdp_media .= ' '.$payload->attributes()->uri;
break;
$priority .= ' '.$payload->attributes()->id;
//if (!$priority) $priority = $payload->attributes()->id;
}
//elseif($payload->attributes()->required){ //this is an encryption request, not a payload
// $proto = "RTP/SAVP ";
//}
}
foreach($content->transport->children() as $candidate) {
if($candidate->getName() == 'candidate'){
$c .= //http://tools.ietf.org/html/rfc5245#section-15
"\na=candidate:".$candidate->attributes()->foundation.
' '.$candidate->attributes()->component.
' '.strtoupper($candidate->attributes()->protocol).
' '.$candidate->attributes()->priority.
' '.$candidate->attributes()->ip.
' '.$candidate->attributes()->port.
' typ '.$candidate->attributes()->type;
if($port == false)
$port = $candidate->attributes()->port;
case 'rtcp-mux':
$sdp_media .=
"\na=rtcp-mux";
if($ip == false)
$ip = $candidate->attributes()->ip;
if($candidate->attributes()->type == 'srflx') {
$c .=
' raddr '.$candidate->attributes()->{'rel-addr'}.
' rport '.$candidate->attributes()->{'rel-port'};
}
$c .= ' generation '.$candidate->attributes()->generation;
$this->valid = true;
case 'encryption':
if(isset($payload->crypto)) {
$sdp_media .=
"\na=crypto:".
$payload->crypto->attributes()->tag.' '.
$payload->crypto->attributes()->{'crypto-suite'}.' '.
$payload->crypto->attributes()->{'key-params'};
// TODO session params ?
}
break;
case 'payload-type':
$sdp_media .=
"\na=rtpmap:".
$payload->attributes()->id;
if(isset($payload->attributes()->name)) {
$sdp_media .= ' '.$payload->attributes()->name;
if(isset($payload->attributes()->clockrate)) {
$sdp_media .= '/'.$payload->attributes()->clockrate;
if(isset($payload->attributes()->channels)) {
$sdp_media .= '/'.$payload->attributes()->channels;
}
}
}
foreach($payload->children() as $rtcpfb) {
if($rtcpfb->getName() == 'rtcp-fb') {
$sdp_media .=
"\na=rtcp-fb:".
$rtcpfb->attributes()->id.' '.
$rtcpfb->attributes()->type;
if(isset($rtcpfb->attributes()->subtype)) {
$sdp_media .= ' '.$rtcpfb->attributes()->subtype;
}
}
// TODO rtcp_fb_trr_int ?
}
break;
case 'fmtp':
// TODO
break;
case 'source':
foreach($payload->children() as $s) {
$sdp_media .=
"\na=ssrc:".$payload->attributes()->id.' '.
$s->attributes()->name.':'.
$s->attributes()->value;
}
break;
}
// TODO sendrecv ?
}
if(isset($content->description->attributes()->ptime)) {
$sdp_media .=
"\na=ptime:".$content->description->attributes()->ptime;
}
$this->sdp .= //http://tools.ietf.org/html/rfc4566#page-22
"\nm=".$content->description->attributes()->media.
' '.$port.
' '.$proto.
$priority.
"\nc=IN IP4 ".$ip."\n".
$p.
//'a=setup:actpass'."\n".
$c;
//'a=rtcp-mux'."\n";
if(isset($content->description->attributes()->maxptime)) {
$sdp_media .=
"\na=maxptime:".$content->description->attributes()->maxptime;
}
foreach($content->transport->children() as $payload) {
switch($payload->getName()) {
case 'fingerprint':
if(isset($content->transport->fingerprint->attributes()->hash)) {
$sdp_media .=
"\na=fingerprint:".
$content->transport->fingerprint->attributes()->hash.
' '.
$content->transport->fingerprint;
}
if(isset($content->transport->fingerprint->attributes()->setup)) {
$sdp_media .=
"\na=setup:".
$content->transport->fingerprint->attributes()->setup;
}
break;
case 'candidate':
$sdp_media .=
"\na=candidate:".
$payload->attributes()->foundation.' '.
$payload->attributes()->component.' '.
$payload->attributes()->protocol.' '.
$payload->attributes()->priority.' '.
$payload->attributes()->ip.' '.
$payload->attributes()->port.' '.
'typ '.$payload->attributes()->type;
if(isset($payload->attributes()->{'rel-addr'})
&& isset($payload->attributes()->{'rel-port'})) {
$sdp_media .=
' raddr '.$payload->attributes()->{'rel-addr'}.
' rport '.$payload->attributes()->{'rel-port'};
}
if(isset($payload->attributes()->generation)) {
$sdp_media .=
' generation '.$payload->attributes()->generation;
}
break;
}
}
}
if($this->iceufrag && $this->icepwd) {
$ice =
"\na=ice-ufrag:".$this->iceufrag.
"\na=ice-pwd:".$this->icepwd;
if($this->icefingerprint && $this->icefingerprinthash)
$ice .=
"\na=fingerprint:".
$this->icefingerprinthash.
' '.
$this->icefingerprint;
} else {
$ice = '';
}
$this->sdp .= $sdp_version;
$this->sdp .= "\n".$sdp_origin;
$this->sdp .= "\n".$sdp_session_name;
$this->sdp .= "\n".$sdp_timing;
$this->sdp .= $sdp_media;
$this->sdp =
'v=0'.
"\no=".$username.' '.substr(base_convert($sessid, 30, 10), 0, 6).' 0 IN IP4 0.0.0.0'.
"\ns=TestCall".
"\nt=0 0".
$ice.
$this->sdp;
if($this->valid)
return $this->sdp;
else
return false;
return $this->sdp;
}
}

85
lib/SDPtoJingle.php

@ -3,6 +3,9 @@ class SDPtoJingle {
private $sdp;
private $jingle;
private $first_content = true;
private $current_transport = null;
private $regex = array(
'candidate' => "/^a=candidate:(\w{1,32}) (\d{1,5}) (udp|tcp) (\d{1,10}) ([a-zA-Z0-9:\.]{1,45}) (\d{1,5}) (typ) (host|srflx|prflx|relay)( (raddr) ([a-zA-Z0-9:\.]{1,45}) (rport) (\d{1,5}))?( (generation) (\d))?/i",
'rtpmap' => "/^a=rtpmap:(\d+) (([^\s\/]+)\/(\d+)(\/([^\s\/]+))?)?/i",
@ -34,46 +37,46 @@ class SDPtoJingle {
$this->jingle->addAttribute('sid', generateKey(10));
}
function createContent() {
if(!$this->jingle->content)
return $this->jingle->addChild('content');
else
return $this->jingle->content;
}
function createTransport() {
$content = $this->createContent();
if(!$content->transport) {
$transport = $content->addChild('transport');
$transport->addAttribute('xmlns', "urn:xmpp:jingle:transports:ice-udp:1");
return $transport;
}
else
return $content->transport;
}
/*
function createContent($new = false) {
if($this->current_content == null || $new) {
$this->current_content = $this->jingle->addChild('content');
$this->current_transport = $this->current_content->addChild('transport');
$this->current_transport->addAttribute('xmlns', "urn:xmpp:jingle:transports:ice-udp:1");
return $this->current_content;
} else
return $this->current_content;
}*/
//$this->current_content = $this->jingle->addChild('content');
function generate() {
$arr = explode("\n", $this->sdp);
$content = $this->jingle->addChild('content');
$this->current_transport = $content->addChild('transport');
foreach($arr as $l) {
foreach($this->regex as $key => $r) {
if(preg_match($r, $l, $matches)) {
switch($key) {
case 'media':
$media = array(
'media' => $matches[1]
);
//$content = $this->createContent(true);
if(!$this->first_content) {
$content = $this->jingle->addChild('content');
$this->current_transport = $content->addChild('transport');
}
$content = $this->jingle->addChild('content');
$content->addAttribute('creator', 'initiator'); // TODO à fixer !
$content->addAttribute('name', $media['media']);
$content->addAttribute('name', $matches[1]);
// The description node
$description = $content->addChild('description');
$description->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:1");
$description->addAttribute('media', $media['media']);
$description->addAttribute('media', $matches[1]);
// The transport node
$transport = $this->createTransport();
$this->first_content = false;
break;
case 'bandwidth':
@ -98,15 +101,15 @@ class SDPtoJingle {
$payloadtype->addAttribute('clockrate', $matches[4]);
if($channel)
$payloadtype->addAttribute('channel', $channel);
$payloadtype->addAttribute('channels', $matches[6]);
break;
case 'rtcp_fb':
if($matches[1] == '*') {
$rtcpfp = $description->addChild('rtcp-fp');
$rtcpfp = $description->addChild('rtcp-fb');
} else {
$rtcpfp = $payloadtype->addChild('rtcp-fp');
$rtcpfp = $payloadtype->addChild('rtcp-fb');
}
$rtcpfp->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:rtcp-fb:0");
$rtcpfp->addAttribute('id', $matches[1]);
@ -152,7 +155,7 @@ class SDPtoJingle {
$rtphdrext->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0");
$rtphdrext->addAttribute('id', $matches[1]);
$rtphdrext->addAttribute('uri', $matches[4]);
$rtphdrext->addAttribute('senders', $matches[4]);
$rtphdrext->addAttribute('senders', $matches[3]);
break;
// http://xmpp.org/extensions/inbox/jingle-source.html
@ -178,36 +181,33 @@ class SDPtoJingle {
// À appeler à la fin
case 'fingerprint':
$transport = $this->createTransport();
if(!$transport->fingerprint) {
$fingerprint = $transport->addChild('fingerprint', $matches[2]);
if(!$this->current_transport->fingerprint) {
$fingerprint = $this->current_transport->addChild('fingerprint', $matches[2]);
$fingerprint->addAttribute('xmlns', "urn:xmpp:jingle:apps:dtls:0");
$fingerprint->addAttribute('hash', $matches[1]);
}
break;
case 'setup':
if(!$fingerprint->attributes()->setup)
if(isset($fingerprint) && !$fingerprint->attributes()->setup)
$fingerprint->addAttribute('setup', $matches[1]);
break;
case 'pwd':
$transport = $this->createTransport();
if(!$transport->attributes()->pwd)
$transport->addAttribute('pwd', $matches[1]);
if(!$this->current_transport->attributes()->pwd) {
$this->current_transport->addAttribute('xmlns', "urn:xmpp:jingle:transports:ice-udp:1");
$this->current_transport->addAttribute('pwd', $matches[1]);
}
break;
case 'ufrag':
$transport = $this->createTransport();
if(!$transport->attributes()->ufrag)
$transport->addAttribute('ufrag', $matches[1]);
if(!$this->current_transport->attributes()->ufrag)
$this->current_transport->addAttribute('ufrag', $matches[1]);
break;
case 'candidate':
if(isset($match[16]))
$generation = $matches[16];
else
$generation = 0;
if(isset($matches[11]) && isset($matches[13])) {
$reladdr = $matches[11];
@ -216,11 +216,12 @@ class SDPtoJingle {
$reladdr = $relport = null;
}
$candidate = $transport->addChild('candidate');
$candidate = $this->current_transport->addChild('candidate');
$candidate->addAttribute('component' , $matches[2]);
$candidate->addAttribute('foundation', $matches[1]);
$candidate->addAttribute('generation', $generation); //|| JSJAC_JINGLE_GENERATION;
if(isset($match[16]))
$candidate->addAttribute('generation', $match[16]); //|| JSJAC_JINGLE_GENERATION;
$candidate->addAttribute('id' , generateKey(10)); //$self.util_generate_id();
$candidate->addAttribute('ip' , $matches[5]);
$candidate->addAttribute('network' , 0);

Loading…
Cancel
Save