123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- var sip=require('sip');
- var util=require('util');
-
- var contexts = {};
-
- function makeContextId(msg) {
- var via = msg.headers.via[0];
- return [via.params.branch, via.protocol, via.host, via.port, msg.headers['call-id'], msg.headers.cseq.seq];
- }
-
- function defaultCallback(rs) {
- rs.headers.via.shift();
- exports.send(rs);
- }
-
-
- exports.send = function(msg, callback) {
- var ctx = contexts[makeContextId(msg)];
-
- if(!ctx) {
- sip.send.apply(sip, arguments);
- return;
- }
-
- return msg.method ? forwardRequest(ctx, msg, callback || defaultCallback) : forwardResponse(ctx, msg);
- };
-
-
- function forwardResponse(ctx, rs, callback) {
- if(+rs.status >= 200) {
- delete contexts[makeContextId(rs)];
- }
-
- sip.send(rs);
- }
-
-
- function sendCancel(rq, via, route) {
- sip.send({
- method: 'CANCEL',
- uri: rq.uri,
- headers: {
- via: [via],
- to: rq.headers.to,
- from: rq.headers.from,
- 'call-id': rq.headers['call-id'],
- route: route,
- cseq: {method: 'CANCEL', seq: rq.headers.cseq.seq}
- }
- });
- }
-
-
- function forwardRequest(ctx, rq, callback) {
- var route = rq.headers.route && rq.headers.route.slice();
- sip.send(rq, function(rs, remote) {
- if(+rs.status < 200) {
- var via = rs.headers.via[0];
- ctx.cancellers[rs.headers.via[0].params.branch] = function() { sendCancel(rq, via, route); };
-
- if(ctx.cancelled)
- sendCancel(rq, via, route);
- }
- else {
- delete ctx.cancellers[rs.headers.via[0].params.branch];
- }
-
- callback(rs, remote);
- });
- }
-
-
- function onRequest(rq, route, remote) {
- var id = makeContextId(rq);
- contexts[id] = { cancellers: {} };
-
- try {
- route(sip.copyMessage(rq), remote);
- } catch(e) {
- delete contexts[id];
- throw e;
- }
- };
-
-
- exports.start = function(options, route) {
- sip.start(options, function(rq, remote) {
- if(rq.method === 'CANCEL') {
- var ctx = contexts[makeContextId(rq)];
-
- if(ctx) {
- sip.send(sip.makeResponse(rq, 200));
-
- ctx.cancelled = true;
- if(ctx.cancellers) {
- Object.keys(ctx.cancellers).forEach(function(c) { ctx.cancellers[c](); });
- }
- }
- else {
- sip.send(sip.makeResponse(rq, 481));
- }
- }
- else {
- onRequest(rq, route, remote);
- }
- });
- };
-
- exports.stop = sip.stop;
|