PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/test/jssipsite/lib/sanityCheck.js

https://gitlab.com/Nowsad.kamrul/cthealthltd
JavaScript | 225 lines | 153 code | 35 blank | 37 comment | 30 complexity | 92613fb9aab710969b758e02ffa22d7f MD5 | raw file
  1. module.exports = sanityCheck;
  2. /**
  3. * Dependencies.
  4. */
  5. var debug = require('debug')('JsSIP:sanityCheck');
  6. var JsSIP_C = require('./Constants');
  7. var SIPMessage = require('./SIPMessage');
  8. var Utils = require('./Utils');
  9. var message, ua, transport,
  10. requests = [],
  11. responses = [],
  12. all = [];
  13. requests.push(rfc3261_8_2_2_1);
  14. requests.push(rfc3261_16_3_4);
  15. requests.push(rfc3261_18_3_request);
  16. requests.push(rfc3261_8_2_2_2);
  17. responses.push(rfc3261_8_1_3_3);
  18. responses.push(rfc3261_18_3_response);
  19. all.push(minimumHeaders);
  20. function sanityCheck(m, u, t) {
  21. var len, pass;
  22. message = m;
  23. ua = u;
  24. transport = t;
  25. len = all.length;
  26. while(len--) {
  27. pass = all[len](message);
  28. if(pass === false) {
  29. return false;
  30. }
  31. }
  32. if(message instanceof SIPMessage.IncomingRequest) {
  33. len = requests.length;
  34. while(len--) {
  35. pass = requests[len](message);
  36. if(pass === false) {
  37. return false;
  38. }
  39. }
  40. }
  41. else if(message instanceof SIPMessage.IncomingResponse) {
  42. len = responses.length;
  43. while(len--) {
  44. pass = responses[len](message);
  45. if(pass === false) {
  46. return false;
  47. }
  48. }
  49. }
  50. //Everything is OK
  51. return true;
  52. }
  53. /*
  54. * Sanity Check for incoming Messages
  55. *
  56. * Requests:
  57. * - _rfc3261_8_2_2_1_ Receive a Request with a non supported URI scheme
  58. * - _rfc3261_16_3_4_ Receive a Request already sent by us
  59. * Does not look at via sent-by but at jssip_id, which is inserted as
  60. * a prefix in all initial requests generated by the ua
  61. * - _rfc3261_18_3_request_ Body Content-Length
  62. * - _rfc3261_8_2_2_2_ Merged Requests
  63. *
  64. * Responses:
  65. * - _rfc3261_8_1_3_3_ Multiple Via headers
  66. * - _rfc3261_18_3_response_ Body Content-Length
  67. *
  68. * All:
  69. * - Minimum headers in a SIP message
  70. */
  71. // Sanity Check functions for requests
  72. function rfc3261_8_2_2_1() {
  73. if(message.s('to').uri.scheme !== 'sip') {
  74. reply(416);
  75. return false;
  76. }
  77. }
  78. function rfc3261_16_3_4() {
  79. if(!message.to_tag) {
  80. if(message.call_id.substr(0, 5) === ua.configuration.jssip_id) {
  81. reply(482);
  82. return false;
  83. }
  84. }
  85. }
  86. function rfc3261_18_3_request() {
  87. var len = Utils.str_utf8_length(message.body),
  88. contentLength = message.getHeader('content-length');
  89. if(len < contentLength) {
  90. reply(400);
  91. return false;
  92. }
  93. }
  94. function rfc3261_8_2_2_2() {
  95. var tr, idx,
  96. fromTag = message.from_tag,
  97. call_id = message.call_id,
  98. cseq = message.cseq;
  99. // Accept any in-dialog request.
  100. if(message.to_tag) {
  101. return;
  102. }
  103. // INVITE request.
  104. if (message.method === JsSIP_C.INVITE) {
  105. // If the branch matches the key of any IST then assume it is a retransmission
  106. // and ignore the INVITE.
  107. // TODO: we should reply the last response.
  108. if (ua.transactions.ist[message.via_branch]) {
  109. return false;
  110. }
  111. // Otherwise check whether it is a merged request.
  112. else {
  113. for(idx in ua.transactions.ist) {
  114. tr = ua.transactions.ist[idx];
  115. if(tr.request.from_tag === fromTag && tr.request.call_id === call_id && tr.request.cseq === cseq) {
  116. reply(482);
  117. return false;
  118. }
  119. }
  120. }
  121. }
  122. // Non INVITE request.
  123. else {
  124. // If the branch matches the key of any NIST then assume it is a retransmission
  125. // and ignore the request.
  126. // TODO: we should reply the last response.
  127. if (ua.transactions.nist[message.via_branch]) {
  128. return false;
  129. }
  130. // Otherwise check whether it is a merged request.
  131. else {
  132. for(idx in ua.transactions.nist) {
  133. tr = ua.transactions.nist[idx];
  134. if(tr.request.from_tag === fromTag && tr.request.call_id === call_id && tr.request.cseq === cseq) {
  135. reply(482);
  136. return false;
  137. }
  138. }
  139. }
  140. }
  141. }
  142. // Sanity Check functions for responses
  143. function rfc3261_8_1_3_3() {
  144. if(message.getHeaders('via').length > 1) {
  145. debug('more than one Via header field present in the response, dropping the response');
  146. return false;
  147. }
  148. }
  149. function rfc3261_18_3_response() {
  150. var
  151. len = Utils.str_utf8_length(message.body),
  152. contentLength = message.getHeader('content-length');
  153. if(len < contentLength) {
  154. debug('message body length is lower than the value in Content-Length header field, dropping the response');
  155. return false;
  156. }
  157. }
  158. // Sanity Check functions for requests and responses
  159. function minimumHeaders() {
  160. var
  161. mandatoryHeaders = ['from', 'to', 'call_id', 'cseq', 'via'],
  162. idx = mandatoryHeaders.length;
  163. while(idx--) {
  164. if(!message.hasHeader(mandatoryHeaders[idx])) {
  165. debug('missing mandatory header field : ' + mandatoryHeaders[idx] + ', dropping the response');
  166. return false;
  167. }
  168. }
  169. }
  170. // Reply
  171. function reply(status_code) {
  172. var to,
  173. response = 'SIP/2.0 ' + status_code + ' ' + JsSIP_C.REASON_PHRASE[status_code] + '\r\n',
  174. vias = message.getHeaders('via'),
  175. length = vias.length,
  176. idx = 0;
  177. for(idx; idx < length; idx++) {
  178. response += 'Via: ' + vias[idx] + '\r\n';
  179. }
  180. to = message.getHeader('To');
  181. if(!message.to_tag) {
  182. to += ';tag=' + Utils.newTag();
  183. }
  184. response += 'To: ' + to + '\r\n';
  185. response += 'From: ' + message.getHeader('From') + '\r\n';
  186. response += 'Call-ID: ' + message.call_id + '\r\n';
  187. response += 'CSeq: ' + message.cseq + ' ' + message.method + '\r\n';
  188. response += '\r\n';
  189. transport.send(response);
  190. }