Ei kuvausta
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.

proxy.js 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. var sip=require('sip');
  2. var util=require('util');
  3. var contexts = {};
  4. function makeContextId(msg) {
  5. var via = msg.headers.via[0];
  6. return [via.params.branch, via.protocol, via.host, via.port, msg.headers['call-id'], msg.headers.cseq.seq];
  7. }
  8. function defaultCallback(rs) {
  9. rs.headers.via.shift();
  10. exports.send(rs);
  11. }
  12. exports.send = function(msg, callback) {
  13. var ctx = contexts[makeContextId(msg)];
  14. if(!ctx) {
  15. sip.send.apply(sip, arguments);
  16. return;
  17. }
  18. return msg.method ? forwardRequest(ctx, msg, callback || defaultCallback) : forwardResponse(ctx, msg);
  19. };
  20. function forwardResponse(ctx, rs, callback) {
  21. if(+rs.status >= 200) {
  22. delete contexts[makeContextId(rs)];
  23. }
  24. sip.send(rs);
  25. }
  26. function sendCancel(rq, via, route) {
  27. sip.send({
  28. method: 'CANCEL',
  29. uri: rq.uri,
  30. headers: {
  31. via: [via],
  32. to: rq.headers.to,
  33. from: rq.headers.from,
  34. 'call-id': rq.headers['call-id'],
  35. route: route,
  36. cseq: {method: 'CANCEL', seq: rq.headers.cseq.seq}
  37. }
  38. });
  39. }
  40. function forwardRequest(ctx, rq, callback) {
  41. var route = rq.headers.route && rq.headers.route.slice();
  42. sip.send(rq, function(rs, remote) {
  43. if(+rs.status < 200) {
  44. var via = rs.headers.via[0];
  45. ctx.cancellers[rs.headers.via[0].params.branch] = function() { sendCancel(rq, via, route); };
  46. if(ctx.cancelled)
  47. sendCancel(rq, via, route);
  48. }
  49. else {
  50. delete ctx.cancellers[rs.headers.via[0].params.branch];
  51. }
  52. callback(rs, remote);
  53. });
  54. }
  55. function onRequest(rq, route, remote) {
  56. var id = makeContextId(rq);
  57. contexts[id] = { cancellers: {} };
  58. try {
  59. route(sip.copyMessage(rq), remote);
  60. } catch(e) {
  61. delete contexts[id];
  62. throw e;
  63. }
  64. };
  65. exports.start = function(options, route) {
  66. sip.start(options, function(rq, remote) {
  67. if(rq.method === 'CANCEL') {
  68. var ctx = contexts[makeContextId(rq)];
  69. if(ctx) {
  70. sip.send(sip.makeResponse(rq, 200));
  71. ctx.cancelled = true;
  72. if(ctx.cancellers) {
  73. Object.keys(ctx.cancellers).forEach(function(c) { ctx.cancellers[c](); });
  74. }
  75. }
  76. else {
  77. sip.send(sip.makeResponse(rq, 481));
  78. }
  79. }
  80. else {
  81. onRequest(rq, route, remote);
  82. }
  83. });
  84. };
  85. exports.stop = sip.stop;