mirror of https://github.com/movim/movim
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
16 KiB
417 lines
16 KiB
<?php
|
|
|
|
use Movim\Session;
|
|
|
|
class JingletoSDP
|
|
{
|
|
private $sdp = '';
|
|
private $jingle;
|
|
|
|
private $action;
|
|
|
|
// Only used for ICE Candidate (Jingle transport-info)
|
|
public $media;
|
|
public $name = null;
|
|
|
|
// Non standard
|
|
public $mid;
|
|
public $mlineindex;
|
|
|
|
private $values = [
|
|
'session_sdp_id' => 1,
|
|
'session_version' => 0,
|
|
'nettype' => 'IN',
|
|
'addrtype' => 'IP4',
|
|
'unicast_address' => '0.0.0.0'
|
|
];
|
|
|
|
public function __construct($jingle)
|
|
{
|
|
$this->jingle = $jingle;
|
|
|
|
if (isset($this->jingle->attributes()->sid)) {
|
|
$sid = (string)$this->jingle->attributes()->sid;
|
|
$s = Session::start();
|
|
$s->set('jingleSid', $sid);
|
|
}
|
|
|
|
$this->action = (string)$this->jingle->attributes()->action;
|
|
}
|
|
|
|
public function getSessionId()
|
|
{
|
|
$s = Session::start();
|
|
return substr(base_convert($s->get('jingleSid'), 30, 10), 0, 6);
|
|
}
|
|
|
|
public function generate()
|
|
{
|
|
if ($this->jingle->attributes()->initiator) {
|
|
$username = explode('@', (string)$this->jingle->attributes()->initiator);
|
|
$username = $username[0];
|
|
} else {
|
|
$username = '-';
|
|
}
|
|
|
|
$this->values['session_sdp_id'] = $this->getSessionId();
|
|
|
|
$sdp_version =
|
|
'v=0';
|
|
|
|
$sdp_origin =
|
|
'o='.
|
|
$username.' '.
|
|
$this->values['session_sdp_id'].' '.
|
|
$this->values['session_version'].' '.
|
|
$this->values['nettype'].' '.
|
|
$this->values['addrtype'].' '.
|
|
$this->values['unicast_address'];
|
|
|
|
$sdp_session_name =
|
|
's=-'; // Use the sessid ?
|
|
|
|
$sdp_timing =
|
|
't=0 0';
|
|
|
|
$sdp_medias = '';
|
|
|
|
foreach ($this->jingle->children() as $content) {
|
|
$media_header_ids = [];
|
|
$media_header_first_port = null;
|
|
$media_header_last_ip = null;
|
|
|
|
$sdp_media = '';
|
|
|
|
// http://xmpp.org/extensions/xep-0338.html
|
|
if ((string)$content->getName() == 'group') {
|
|
$sdp_medias .=
|
|
"\r\na=group:".
|
|
(string)$content->attributes()->semantics;
|
|
foreach ($content->children() as $content) {
|
|
$sdp_medias .= " ".(string)$content->attributes()->name;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if ($content->getName() != 'content') {
|
|
break;
|
|
}
|
|
|
|
$this->name = (string)$content->attributes()->name;
|
|
|
|
if (isset($content->transport->attributes()->pwd)) {
|
|
$sdp_media .= "\r\na=ice-pwd:".$content->transport->attributes()->pwd;
|
|
}
|
|
|
|
// ufrag can be alone without a password for candidates
|
|
if (isset($content->transport->attributes()->ufrag)
|
|
&& isset($content->transport->attributes()->pwd)) {
|
|
$sdp_media .= "\r\na=ice-ufrag:".$content->transport->attributes()->ufrag;
|
|
}
|
|
|
|
if (isset($content->description)) {
|
|
foreach ($content->description->children() as $payload) {
|
|
switch ($payload->getName()) {
|
|
case 'rtp-hdrext':
|
|
$sdp_media .=
|
|
"\r\na=extmap:".
|
|
$payload->attributes()->id;
|
|
|
|
if (isset($payload->attributes()->senders)) {
|
|
$sdp_media .= ' '.$payload->attributes()->senders;
|
|
}
|
|
|
|
$sdp_media .= ' '.$payload->attributes()->uri;
|
|
break;
|
|
|
|
// https://xmpp.org/extensions/xep-0293.html
|
|
case 'rtcp-fb':
|
|
$sdp_media .=
|
|
"\r\na=rtcp-fb:".
|
|
'* '.
|
|
$payload->attributes()->type;
|
|
|
|
if (isset($payload->attributes()->subtype)) {
|
|
$sdp_media .= ' '.$payload->attributes()->subtype;
|
|
}
|
|
break;
|
|
|
|
case 'rtcp-mux':
|
|
$sdp_media .=
|
|
"\r\na=rtcp-mux";
|
|
|
|
// no break
|
|
case 'encryption':
|
|
if (isset($payload->crypto)) {
|
|
$sdp_media .=
|
|
"\r\na=crypto:".
|
|
$payload->crypto->attributes()->tag.' '.
|
|
$payload->crypto->attributes()->{'crypto-suite'}.' '.
|
|
$payload->crypto->attributes()->{'key-params'};
|
|
|
|
// TODO session params ?
|
|
}
|
|
|
|
if (isset($payload->{'zrtp-hash'})) {
|
|
$sdp_media .=
|
|
"\r\na=zrtp-hash:".
|
|
$payload->{'zrtp-hash'}->attributes()->version.' '.
|
|
(string)$payload->{'zrtp-hash'};
|
|
}
|
|
break;
|
|
|
|
case 'payload-type':
|
|
$payload_id = $payload->attributes()->id;
|
|
$sdp_media .=
|
|
"\r\na=rtpmap:".
|
|
$payload_id;
|
|
|
|
array_push($media_header_ids, $payload_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;
|
|
}
|
|
}
|
|
}
|
|
|
|
$first_fmtp = true;
|
|
|
|
foreach ($payload->children() as $param) {
|
|
switch ($param->getName()) {
|
|
case 'rtcp-fb':
|
|
$sdp_media .=
|
|
"\r\na=rtcp-fb:".
|
|
$payload_id.' '.
|
|
$param->attributes()->type;
|
|
|
|
if (isset($param->attributes()->subtype)) {
|
|
$sdp_media .= ' '.$param->attributes()->subtype;
|
|
}
|
|
|
|
break;
|
|
// http://xmpp.org/extensions/xep-0167.html#format
|
|
case 'parameter':
|
|
if ($first_fmtp) {
|
|
$sdp_media .=
|
|
"\r\na=fmtp:".
|
|
$payload_id.
|
|
' ';
|
|
} else {
|
|
$sdp_media .= ';';
|
|
}
|
|
|
|
if (isset($param->attributes()->name)) {
|
|
$sdp_media .=
|
|
$param->attributes()->name.
|
|
'=';
|
|
}
|
|
|
|
$sdp_media .=
|
|
$param->attributes()->value;
|
|
|
|
$first_fmtp = false;
|
|
|
|
break;
|
|
}
|
|
|
|
// TODO rtcp_fb_trr_int ?
|
|
}
|
|
|
|
break;
|
|
|
|
case 'source':
|
|
foreach ($payload->children() as $s) {
|
|
$sdp_media .=
|
|
"\r\na=ssrc:".$payload->attributes()->ssrc.' '.
|
|
$s->attributes()->name.':'.
|
|
$s->attributes()->value;
|
|
}
|
|
break;
|
|
}
|
|
// TODO sendrecv ?
|
|
}
|
|
}
|
|
|
|
if (isset($content->description)
|
|
&& isset($content->description->attributes()->ptime)) {
|
|
$sdp_media .=
|
|
"\r\na=ptime:".$content->description->attributes()->ptime;
|
|
}
|
|
|
|
if (isset($content->description)
|
|
&& isset($content->description->attributes()->maxptime)) {
|
|
$sdp_media .=
|
|
"\r\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 .=
|
|
"\r\na=fingerprint:".
|
|
$content->transport->fingerprint->attributes()->hash.
|
|
' '.
|
|
$content->transport->fingerprint;
|
|
}
|
|
|
|
if (isset($content->transport->fingerprint->attributes()->setup)) {
|
|
$sdp_media .=
|
|
"\r\na=setup:".
|
|
$content->transport->fingerprint->attributes()->setup;
|
|
}
|
|
break;
|
|
|
|
// https://xmpp.org/extensions/xep-0343.html
|
|
case 'sctpmap':
|
|
$sdp_media .=
|
|
"\r\na=sctpmap:".
|
|
$payload->attributes()->number.' '.
|
|
$payload->attributes()->protocol.' '.
|
|
$payload->attributes()->streams.' '
|
|
;
|
|
|
|
|
|
array_push($media_header_ids, $payload->attributes()->number);
|
|
|
|
break;
|
|
|
|
case 'candidate':
|
|
$sdp_media .=
|
|
"\r\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 ($media_header_first_port == null) {
|
|
$media_header_first_port = $payload->attributes()->port;
|
|
}
|
|
}
|
|
|
|
if (isset($payload->attributes()->tcptype)) {
|
|
$sdp_media .=
|
|
' tcptype '.$payload->attributes()->tcptype;
|
|
}
|
|
|
|
if (isset($payload->attributes()->generation)) {
|
|
$sdp_media .=
|
|
' generation '.$payload->attributes()->generation;
|
|
}
|
|
|
|
// ufrag in candidate transport
|
|
if (isset($content->transport->attributes()->ufrag)) {
|
|
$sdp_media .=
|
|
' ufrag '.$content->transport->attributes()->ufrag;
|
|
}
|
|
|
|
if (isset($payload->attributes()->network)) {
|
|
$sdp_media .=
|
|
' network '.$payload->attributes()->network;
|
|
}
|
|
|
|
if (isset($payload->attributes()->id)) {
|
|
$sdp_media .=
|
|
' id '.$payload->attributes()->id;
|
|
}
|
|
|
|
if (isset($payload->attributes()->{'network-id'})) {
|
|
$sdp_media .=
|
|
' network-id '.$payload->attributes()->{'network-id'};
|
|
}
|
|
|
|
if (isset($payload->attributes()->{'network-cost'})) {
|
|
$sdp_media .=
|
|
' network-id '.$payload->attributes()->{'network-cost'};
|
|
}
|
|
|
|
// mid, mlineindex
|
|
if (isset($payload->attributes()->mid)) {
|
|
$this->mid = (int)$payload->attributes()->mid;
|
|
}
|
|
|
|
if (isset($payload->attributes()->mlineindex)) {
|
|
$this->mlineindex = (int)$payload->attributes()->mlineindex;
|
|
}
|
|
|
|
$media_header_last_ip = $payload->attributes()->ip;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($media_header_first_port == null) {
|
|
$media_header_first_port = 1;
|
|
}
|
|
|
|
if ($media_header_last_ip == null) {
|
|
$media_header_last_ip = '0.0.0.0';
|
|
}
|
|
|
|
if (isset($content->description)) {
|
|
$this->media = (string)$content->description->attributes()->media;
|
|
$this->mlineindex = ($this->media == 'audio') ? 0 : 1;
|
|
}
|
|
|
|
if ($this->action != 'transport-info') {
|
|
$sdp_media_header =
|
|
"\r\nm=".$this->media.
|
|
' '.$media_header_first_port.' ';
|
|
|
|
if (isset($content->transport->sctpmap)) {
|
|
$sdp_media_header .= 'DTLS/SCTP';
|
|
} elseif (isset($content->description->crypto)
|
|
|| isset($content->transport->fingerprint)) {
|
|
$sdp_media_header .= 'UDP/TLS/RTP/SAVPF';
|
|
} else {
|
|
$sdp_media_header .= 'UDP/TLS/RTP/AVP';
|
|
}
|
|
|
|
$sdp_media_header = $sdp_media_header.' '.implode(' ', $media_header_ids);
|
|
|
|
$ipVersion = filter_var($media_header_last_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)
|
|
? 'IP6'
|
|
: 'IP4';
|
|
|
|
$sdp_medias .=
|
|
$sdp_media_header.
|
|
"\r\nc=IN ".$ipVersion." ".$media_header_last_ip.
|
|
$sdp_media;
|
|
//"\r\na=sendrecv";
|
|
|
|
if ($this->name !== null) {
|
|
$sdp_medias .= "\r\na=mid:".$this->name;
|
|
}
|
|
} else {
|
|
$sdp_medias = $sdp_media;
|
|
}
|
|
}
|
|
|
|
if ($this->action != 'transport-info') {
|
|
$this->sdp .= /*"\r\n".*/$sdp_version;
|
|
$this->sdp .= "\r\n".$sdp_origin;
|
|
$this->sdp .= "\r\n".$sdp_session_name;
|
|
$this->sdp .= "\r\n".$sdp_timing;
|
|
}
|
|
|
|
$this->sdp .= $sdp_medias;
|
|
|
|
return trim($this->sdp."\r\n");
|
|
}
|
|
}
|