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.

310 lines
16 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  1. <?php
  2. class SDPtoJingle {
  3. private $sdp;
  4. private $arr;
  5. private $jingle;
  6. private $content = null;
  7. private $transport = null;
  8. private $action;
  9. // Move the global fingerprint into each medias
  10. private $global_fingerprint = array();
  11. private $regex = array(
  12. '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) (network) (\d) (id) ([a-zA-Z0-9]{1,45}))?/i", //à partir de generation les attr sont spécifiques à XMPP..autant l'enlever de la REGEX et les traiter à part? En théorie ils peuvent être dans n'importe quel ordre.
  13. 'sess_id' => "/^o=(\S+) (\d+)/i",
  14. 'rtpmap' => "/^a=rtpmap:(\d+) (([^\s\/]+)(\/(\d+)(\/([^\s\/]+))?)?)?/i",
  15. 'fmtp' => "/^a=fmtp:(\d+) (.+)/i",
  16. 'rtcp_fb' => "/^a=rtcp-fb:(\S+) (\S+)( (\S+))?/i",
  17. 'rtcp_fb_trr_int' => "/^a=rtcp-fb:(\d+) trr-int (\d+)/i",
  18. 'pwd' => "/^a=ice-pwd:(\S+)/i",
  19. 'ufrag' => "/^a=ice-ufrag:(\S+)/i",
  20. 'ptime' => "/^a=ptime:(\d+)/i",
  21. 'maxptime' => "/^a=maxptime:(\d+)/i",
  22. 'ssrc' => "/^a=ssrc:(\d+) (\w+)(:(\S+))?( (\w+))?/i",
  23. 'rtcp_mux' => "/^a=rtcp-mux/i",
  24. 'crypto' => "/^a=crypto:(\d{1,9}) (\w+) (\S+)( (\S+))?/i",
  25. 'zrtp_hash' => "/^a=zrtp-hash:(\S+) (\w+)/i",
  26. 'fingerprint' => "/^a=fingerprint:(\S+) (\S+)/i",
  27. 'setup' => "/^a=setup:(\S+)/i",
  28. 'extmap' => "/^a=extmap:([^\s\/]+)(\/([^\s\/]+))? (\S+)/i",
  29. 'sctpmap' => "/^a=sctpmap:(\d+) (\S+) (\d+)/i",
  30. 'bandwidth' => "/^b=(\w+):(\d+)/i",
  31. 'media' => "/^m=(audio|video|application|data)/i"
  32. );
  33. function __construct($sdp, $initiator, $responder, $action) {
  34. $this->sdp = $sdp;
  35. $this->arr = explode("\n", $this->sdp);
  36. $this->jingle = new SimpleXMLElement('<jingle></jingle>');
  37. $this->jingle->addAttribute('xmlns', 'urn:xmpp:jingle:1');
  38. $this->jingle->addAttribute('action',$action);
  39. $this->jingle->addAttribute('initiator',$initiator);
  40. $this->jingle->addAttribute('responder',$responder);
  41. $this->action = $action;
  42. }
  43. function getSessionId(){
  44. $s = Session::start('movim');
  45. if($sid = $s->get('jingleSid')){
  46. return $sid;
  47. }
  48. else{
  49. $o = $this->arr[1];
  50. $sid = explode(" ", $o);
  51. return substr(base_convert($sid[1], 30, 10), 0, 6);
  52. }
  53. }
  54. function generate() {
  55. foreach($this->arr as $l) {
  56. foreach($this->regex as $key => $r) {
  57. if(preg_match($r, $l, $matches)) {
  58. switch($key) {
  59. case 'sess_id':
  60. $this->jingle->addAttribute('sid', $this->getSessionId());
  61. break;
  62. case 'media':
  63. $this->content = $this->jingle->addChild('content');
  64. $this->transport = $this->content->addChild('transport');
  65. $this->transport->addAttribute('xmlns', "urn:xmpp:jingle:transports:ice-udp:1");
  66. $this->content->addAttribute('creator', 'initiator'); // TODO à fixer !
  67. $this->content->addAttribute('name', $matches[1]);
  68. // The description node
  69. if($this->action != 'transport-info') {
  70. $description = $this->content->addChild('description');
  71. $description->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:1");
  72. $description->addAttribute('media', $matches[1]);
  73. }
  74. if(!empty($this->global_fingerprint)) {
  75. $fingerprint = $this->transport->addChild('fingerprint', $this->global_fingerprint['fingerprint']);
  76. $this->transport->addAttribute('pwd', $this->global_fingerprint['pwd']);
  77. $this->transport->addAttribute('ufrag', $this->global_fingerprint['ufrag']);
  78. $fingerprint->addAttribute('xmlns', "urn:xmpp:jingle:apps:dtls:0");
  79. $fingerprint->addAttribute('hash', $this->global_fingerprint['hash']);
  80. }
  81. break;
  82. case 'bandwidth':
  83. $bandwidth = $description->addChild('bandwidth');
  84. $bandwidth->addAttribute('type', $matches[1]);
  85. $bandwidth->addAttribute('value', $matches[2]);
  86. break;
  87. case 'rtpmap':
  88. $payloadtype = $description->addChild('payload-type');
  89. $payloadtype->addAttribute('id', $matches[1]);
  90. $payloadtype->addAttribute('name', $matches[3]);
  91. if(isset($matches[4]))
  92. $payloadtype->addAttribute('clockrate', $matches[5]);
  93. if(isset($matches[7]))
  94. $payloadtype->addAttribute('channels', $matches[7]);
  95. break;
  96. // http://xmpp.org/extensions/xep-0167.html#format
  97. case 'fmtp':
  98. // This work only if fmtp is added just after
  99. // the correspondant rtpmap
  100. if($matches[1] == $payloadtype->attributes()->id) {
  101. $params = explode(';', $matches[2]);
  102. foreach($params as $value) {
  103. $p = explode('=', trim($value));
  104. $parameter = $payloadtype->addChild('parameter');
  105. if(count($p) == 1) {
  106. $parameter->addAttribute('value', $p[0]);
  107. } else {
  108. $parameter->addAttribute('name', $p[0]);
  109. $parameter->addAttribute('value', $p[1]);
  110. }
  111. }
  112. }
  113. break;
  114. case 'rtcp_fb':
  115. if($matches[1] == '*') {
  116. $rtcpfp = $description->addChild('rtcp-fb');
  117. } else {
  118. $rtcpfp = $payloadtype->addChild('rtcp-fb');
  119. }
  120. $rtcpfp->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:rtcp-fb:0");
  121. $rtcpfp->addAttribute('id', $matches[1]);
  122. $rtcpfp->addAttribute('type', $matches[2]);
  123. if(isset($matches[4]))
  124. $rtcpfp->addAttribute('subtype', $matches[4]);
  125. break;
  126. case 'rtcp_fb_trr_int':
  127. $rtcpfp = $payloadtype->addChild('rtcp-fb-trr-int');
  128. $rtcpfp->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:rtcp-fb:0");
  129. $rtcpfp->addAttribute('id', $matches[1]);
  130. $rtcpfp->addAttribute('value', $matches[2]);
  131. break;
  132. // http://xmpp.org/extensions/xep-0167.html#srtp
  133. case 'crypto':
  134. $encryption = $description->addChild('encryption');
  135. $crypto = $encryption->addChild('crypto');
  136. $crypto->addAttribute('crypto-suite', $matches[2]);
  137. $crypto->addAttribute('key-params', $matches[3]);
  138. $crypto->addAttribute('tag', $matches[1]);
  139. if(isset($matches[5]))
  140. $crypto->addAttribute('session-params', $matches[5]);
  141. break;
  142. // http://xmpp.org/extensions/xep-0262.html
  143. case 'zrtp-hash':
  144. $zrtphash = $encryption->addChild('zrtp-hash', $matches[2]);
  145. $zrtphash->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:zrtp:1");
  146. $zrtphash->addAttribute('version', $matches[1]);
  147. break;
  148. case 'rtcp_mux':
  149. $description->addChild('rtcp-mux');
  150. break;
  151. // http://xmpp.org/extensions/xep-0294.html
  152. case 'extmap':
  153. $rtphdrext = $description->addChild('rtp-hdrext');
  154. $rtphdrext->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0");
  155. $rtphdrext->addAttribute('id', $matches[1]);
  156. $rtphdrext->addAttribute('uri', $matches[4]);
  157. if(isset($matches[3]) && $matches[3] != '')
  158. $rtphdrext->addAttribute('senders', $matches[3]);
  159. break;
  160. // http://xmpp.org/extensions/inbox/jingle-source.html
  161. case 'ssrc':
  162. if(!$description->source) {
  163. $ssrc = $description->addChild('source');
  164. $ssrc->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:ssma:0");
  165. $ssrc->addAttribute('id', $matches[1]);
  166. }
  167. $param = $ssrc->addChild('parameter');
  168. $param->addAttribute('name', $matches[2]);
  169. $param->addAttribute('value', $matches[4]);
  170. break;
  171. case 'ptime':
  172. $description->addAttribute('ptime', $matches[1]);
  173. break;
  174. case 'maxptime':
  175. $description->addAttribute('maxptime', $matches[1]);
  176. break;
  177. // http://xmpp.org/extensions/xep-0320.html
  178. case 'fingerprint':
  179. if($this->content == null) {
  180. $this->global_fingerprint['fingerprint'] = $matches[2];
  181. $this->global_fingerprint['hash'] = $matches[1];
  182. } else {
  183. $fingerprint = $this->transport->addChild('fingerprint', $matches[2]);
  184. $fingerprint->addAttribute('xmlns', "urn:xmpp:jingle:apps:dtls:0");
  185. $fingerprint->addAttribute('hash', $matches[1]);
  186. }
  187. break;
  188. // http://xmpp.org/extensions/inbox/jingle-dtls.html
  189. case 'sctpmap':
  190. $sctpmap = $this->transport->addChild('sctpmap');
  191. $sctpmap->addAttribute('xmlns', "urn:xmpp:jingle:transports:dtls-sctp:1");
  192. $sctpmap->addAttribute('number', $matches[1]);
  193. $sctpmap->addAttribute('protocol', $matches[2]);
  194. $sctpmap->addAttribute('streams', $matches[3]);
  195. break;
  196. case 'setup':
  197. if($this->content != null) {
  198. $fingerprint->addAttribute('setup', $matches[1]);
  199. }
  200. break;
  201. case 'pwd':
  202. if($this->content == null) {
  203. $this->global_fingerprint['pwd'] = $matches[1];
  204. } else {
  205. $this->transport->addAttribute('pwd', $matches[1]);
  206. }
  207. break;
  208. case 'ufrag':
  209. if($this->content == null) {
  210. $this->global_fingerprint['ufrag'] = $matches[1];
  211. } else {
  212. $this->transport->addAttribute('ufrag', $matches[1]);
  213. }
  214. break;
  215. case 'candidate':
  216. $generation = "0";
  217. $network = "0";
  218. $id = generateKey(10);
  219. if($key = array_search("generation", $matches))
  220. $generation = $matches[($key+1)];
  221. if($key = array_search("network", $matches))
  222. $network = $matches[($key+1)];
  223. if($key = array_search("id", $matches))
  224. $id = $matches[($key+1)];
  225. if(isset($matches[11]) && isset($matches[13])) {
  226. $reladdr = $matches[11];
  227. $relport = $matches[13];
  228. } else {
  229. $reladdr = $relport = null;
  230. }
  231. $candidate = $this->transport->addChild('candidate');
  232. $candidate->addAttribute('component' , $matches[2]);
  233. $candidate->addAttribute('foundation', $matches[1]);
  234. $candidate->addAttribute('generation', $generation);
  235. $candidate->addAttribute('id' , $id);
  236. $candidate->addAttribute('ip' , $matches[5]);
  237. $candidate->addAttribute('network' , $network);
  238. $candidate->addAttribute('port' , $matches[6]);
  239. $candidate->addAttribute('priority' , $matches[4]);
  240. $candidate->addAttribute('protocol' , $matches[3]);
  241. $candidate->addAttribute('type' , $matches[8]);
  242. if($reladdr) {
  243. $candidate->addAttribute('rel-addr' , $reladdr);
  244. $candidate->addAttribute('rel-port' , $relport);
  245. }
  246. break;
  247. }
  248. }
  249. }
  250. }
  251. //$this->jingle->addChild('sdp', $this->sdp);
  252. // We reindent properly the Jingle package
  253. $xml = $this->jingle->asXML();
  254. $doc = new \DOMDocument();
  255. $doc->loadXML($xml);
  256. $doc->formatOutput = true;
  257. return substr($doc->saveXML() , strpos($doc->saveXML(), "\n")+1 );
  258. }
  259. }