JingletoSDP.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. <?php
  2. use Movim\Session;
  3. class JingletoSDP
  4. {
  5. private $sdp = '';
  6. private $jingle;
  7. private $action;
  8. // Only used for ICE Candidate (Jingle transport-info)
  9. public $media;
  10. public $name;
  11. private $values = array(
  12. 'session_sdp_id' => 1,
  13. 'session_version' => 0,
  14. 'nettype' => 'IN',
  15. 'addrtype' => 'IP4',
  16. 'unicast_address' => '0.0.0.0'
  17. );
  18. function __construct($jingle)
  19. {
  20. $this->jingle = $jingle;
  21. if(isset($this->jingle->attributes()->sid))
  22. {
  23. $sid = (string)$this->jingle->attributes()->sid;
  24. //$sid = substr(base_convert($sid, 30, 10), 0, 6);
  25. $s = Session::start();
  26. $s->set('jingleSid', $sid);
  27. //$this->values['session_id'] = $sid;
  28. }
  29. $this->action = (string)$this->jingle->attributes()->action;
  30. }
  31. function getSessionId()
  32. {
  33. $s = Session::start();
  34. return substr(base_convert($s->get('jingleSid'), 30, 10), 0, 6);
  35. }
  36. function generate()
  37. {
  38. if($this->jingle->attributes()->initiator) {
  39. $username = explode('@', (string)$this->jingle->attributes()->initiator);
  40. $username = $username[0];
  41. } else
  42. $username = '-';
  43. $this->values['session_sdp_id'] = $this->getSessionId();
  44. $sdp_version =
  45. 'v=0';
  46. $sdp_origin =
  47. 'o='.
  48. $username.' '.
  49. $this->values['session_sdp_id'].' '.
  50. $this->values['session_version'].' '.
  51. $this->values['nettype'].' '.
  52. $this->values['addrtype'].' '.
  53. $this->values['unicast_address'];
  54. $sdp_session_name =
  55. 's=-'; // Use the sessid ?
  56. $sdp_timing =
  57. 't=0 0';
  58. $sdp_medias = '';
  59. foreach($this->jingle->children() as $content) {
  60. $media_header_ids = [];
  61. $media_header_first_port = null;
  62. $media_header_last_ip = null;
  63. $sdp_media = '';
  64. // http://xmpp.org/extensions/xep-0338.html
  65. if((string)$content->getName() == 'group') {
  66. $sdp_medias .=
  67. "\r\na=group:".
  68. (string)$content->attributes()->semantics;
  69. foreach($content->children() as $content) {
  70. $sdp_medias .= " ".(string)$content->attributes()->name;
  71. }
  72. continue;
  73. }
  74. if($content->getName() != 'content')
  75. break;
  76. $this->name = (string)$content->attributes()->name;
  77. if(isset($content->transport->attributes()->pwd))
  78. $sdp_media .= "\r\na=ice-pwd:".$content->transport->attributes()->pwd;
  79. if(isset($content->transport->attributes()->ufrag))
  80. $sdp_media .= "\r\na=ice-ufrag:".$content->transport->attributes()->ufrag;
  81. if(isset($content->description)) {
  82. foreach($content->description->children() as $payload) {
  83. switch($payload->getName()) {
  84. case 'rtp-hdrext':
  85. $sdp_media .=
  86. "\r\na=extmap:".
  87. $payload->attributes()->id;
  88. if(isset($payload->attributes()->senders))
  89. $sdp_media .= ' '.$payload->attributes()->senders;
  90. $sdp_media .= ' '.$payload->attributes()->uri;
  91. break;
  92. case 'rtcp-mux':
  93. $sdp_media .=
  94. "\r\na=rtcp-mux";
  95. case 'encryption':
  96. if(isset($payload->crypto)) {
  97. $sdp_media .=
  98. "\r\na=crypto:".
  99. $payload->crypto->attributes()->tag.' '.
  100. $payload->crypto->attributes()->{'crypto-suite'}.' '.
  101. $payload->crypto->attributes()->{'key-params'};
  102. // TODO session params ?
  103. }
  104. if(isset($payload->{'zrtp-hash'})) {
  105. $sdp_media .=
  106. "\r\na=zrtp-hash:".
  107. $payload->{'zrtp-hash'}->attributes()->version.' '.
  108. (string)$payload->{'zrtp-hash'};
  109. }
  110. break;
  111. case 'payload-type':
  112. $sdp_media .=
  113. "\r\na=rtpmap:".
  114. $payload->attributes()->id;
  115. array_push($media_header_ids, $payload->attributes()->id);
  116. if(isset($payload->attributes()->name)) {
  117. $sdp_media .= ' '.$payload->attributes()->name;
  118. if(isset($payload->attributes()->clockrate)) {
  119. $sdp_media .= '/'.$payload->attributes()->clockrate;
  120. if(isset($payload->attributes()->channels)) {
  121. $sdp_media .= '/'.$payload->attributes()->channels;
  122. }
  123. }
  124. }
  125. $first_fmtp = true;
  126. foreach($payload->children() as $param) {
  127. switch($param->getName()) {
  128. case 'rtcp-fb' :
  129. $sdp_media .=
  130. "\r\na=rtcp-fb:".
  131. $param->attributes()->id.' '.
  132. $param->attributes()->type;
  133. if(isset($param->attributes()->subtype)) {
  134. $sdp_media .= ' '.$param->attributes()->subtype;
  135. }
  136. break;
  137. // http://xmpp.org/extensions/xep-0167.html#format
  138. case 'parameter' :
  139. if($first_fmtp) {
  140. $sdp_media .=
  141. "\r\na=fmtp:".
  142. $payload->attributes()->id.
  143. ' ';
  144. } else {
  145. $sdp_media .= ';';
  146. }
  147. if(isset($param->attributes()->name)) {
  148. $sdp_media .=
  149. $param->attributes()->name.
  150. '=';
  151. }
  152. $sdp_media .=
  153. $param->attributes()->value;
  154. $first_fmtp = false;
  155. break;
  156. }
  157. // TODO rtcp_fb_trr_int ?
  158. }
  159. break;
  160. case 'source':
  161. foreach($payload->children() as $s) {
  162. $sdp_media .=
  163. "\r\na=ssrc:".$payload->attributes()->id.' '.
  164. $s->attributes()->name.':'.
  165. $s->attributes()->value;
  166. }
  167. break;
  168. }
  169. // TODO sendrecv ?
  170. }
  171. }
  172. if(isset($content->description)
  173. && isset($content->description->attributes()->ptime)) {
  174. $sdp_media .=
  175. "\r\na=ptime:".$content->description->attributes()->ptime;
  176. }
  177. if(isset($content->description)
  178. && isset($content->description->attributes()->maxptime)) {
  179. $sdp_media .=
  180. "\r\na=maxptime:".$content->description->attributes()->maxptime;
  181. }
  182. foreach($content->transport->children() as $payload) {
  183. switch($payload->getName()) {
  184. case 'fingerprint':
  185. if(isset($content->transport->fingerprint->attributes()->hash)) {
  186. $sdp_media .=
  187. "\r\na=fingerprint:".
  188. $content->transport->fingerprint->attributes()->hash.
  189. ' '.
  190. $content->transport->fingerprint;
  191. }
  192. if(isset($content->transport->fingerprint->attributes()->setup)) {
  193. $sdp_media .=
  194. "\r\na=setup:".
  195. $content->transport->fingerprint->attributes()->setup;
  196. }
  197. break;
  198. // http://xmpp.org/extensions/inbox/jingle-dtls.html
  199. case 'sctpmap':
  200. $sdp_media .=
  201. "\r\na=sctpmap:".
  202. $payload->attributes()->number.' '.
  203. $payload->attributes()->protocol.' '.
  204. $payload->attributes()->streams.' '
  205. ;
  206. array_push($media_header_ids, $payload->attributes()->number);
  207. break;
  208. case 'candidate':
  209. $sdp_media .=
  210. "\r\na=candidate:".
  211. $payload->attributes()->foundation.' '.
  212. $payload->attributes()->component.' '.
  213. $payload->attributes()->protocol.' '.
  214. $payload->attributes()->priority.' '.
  215. $payload->attributes()->ip.' '.
  216. $payload->attributes()->port.' '.
  217. 'typ '.$payload->attributes()->type;
  218. if(isset($payload->attributes()->{'rel-addr'})
  219. && isset($payload->attributes()->{'rel-port'})) {
  220. $sdp_media .=
  221. ' raddr '.$payload->attributes()->{'rel-addr'}.
  222. ' rport '.$payload->attributes()->{'rel-port'};
  223. if($media_header_first_port == null)
  224. $media_header_first_port = $payload->attributes()->port;
  225. }
  226. if(isset($payload->attributes()->generation)) {
  227. $sdp_media .=
  228. ' generation '.$payload->attributes()->generation;
  229. }
  230. if(isset($payload->attributes()->network)) {
  231. $sdp_media .=
  232. ' network '.$payload->attributes()->network;
  233. }
  234. if(isset($payload->attributes()->id)) {
  235. $sdp_media .=
  236. ' id '.$payload->attributes()->id;
  237. }
  238. if(isset($payload->attributes()->{'network-id'})) {
  239. $sdp_media .=
  240. ' network-id '.$payload->attributes()->{'network-id'};
  241. }
  242. $media_header_last_ip = $payload->attributes()->ip;
  243. break;
  244. }
  245. }
  246. if($media_header_first_port == null)
  247. $media_header_first_port = 1;
  248. if($media_header_last_ip == null)
  249. $media_header_last_ip = '0.0.0.0';
  250. if(isset($content->description)) {
  251. $this->media = (string)$content->description->attributes()->media;
  252. $this->mlineindex = ($this->media == 'audio') ? 0 : 1;
  253. }
  254. if($this->action != 'transport-info') {
  255. $sdp_media_header =
  256. "\r\nm=".$this->media.
  257. ' '.$media_header_first_port.' ';
  258. if(isset($content->transport->sctpmap)) {
  259. $sdp_media_header .= 'DTLS/SCTP';
  260. } elseif(isset($content->description->crypto)
  261. || isset($content->transport->fingerprint)) {
  262. $sdp_media_header .= 'UDP/TLS/RTP/SAVPF';
  263. } else {
  264. $sdp_media_header .= 'UDP/TLS/RTP/AVP';
  265. }
  266. $sdp_media_header = $sdp_media_header.' '.implode(' ', $media_header_ids);
  267. $sdp_medias .=
  268. $sdp_media_header.
  269. "\r\nc=IN IP4 ".$media_header_last_ip.
  270. $sdp_media;
  271. //"\r\na=sendrecv";
  272. if(!empty($this->name)) {
  273. $sdp_medias .= "\r\na=mid:".$this->name;
  274. }
  275. } else {
  276. $sdp_medias = $sdp_media;
  277. }
  278. }
  279. if($this->action != 'transport-info') {
  280. $this->sdp .= /*"\r\n".*/$sdp_version;
  281. $this->sdp .= "\r\n".$sdp_origin;
  282. $this->sdp .= "\r\n".$sdp_session_name;
  283. $this->sdp .= "\r\n".$sdp_timing;
  284. }
  285. $this->sdp .= $sdp_medias;
  286. return trim($this->sdp."\r\n");
  287. }
  288. }