From 2541d717969505872e82dc13c3554607bdefdefd Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Fri, 25 Aug 2017 10:23:20 +0000 Subject: [PATCH 01/19] add support for udp client random port --- sip.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sip.js b/sip.js index 04bc7fc..367f5d5 100644 --- a/sip.js +++ b/sip.js @@ -730,11 +730,15 @@ function makeUdpTransport(options, callback) { } var address = options.address || '0.0.0.0'; - var port = options.port || 5060; + var port = typeof(options.port) == undefined ? 5060 : options.port; var socket = dgram.createSocket(net.isIPv6(address) ? 'udp6' : 'udp4', onMessage); socket.bind(port, address); + socket.on("listening", function() { + options.port = socket.address().port; + }); + function open(remote, error) { return { send: function(m) { From a530d0ade2045211703932f3f4317e52db78de2d Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Mon, 29 Jan 2018 13:08:36 +0000 Subject: [PATCH 02/19] expose transaction to app --- sip.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sip.js b/sip.js index 500a905..697ede2 100644 --- a/sip.js +++ b/sip.js @@ -1444,7 +1444,8 @@ exports.create = function(options, callback) { destroy: function() { transaction.destroy(); transport.destroy(); - } + }, + transaction, } } @@ -1457,5 +1458,6 @@ exports.start = function(options, callback) { exports.decodeFlowUri = r.decodeFlowUri; exports.isFlowUri = r.isFlowUri; exports.hostname = r.hostname; + exports.transaction = r.transaction; } From 802743051a2afc17404ebd0635f0c693a5efbac2 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Sat, 10 Feb 2018 04:06:19 +0000 Subject: [PATCH 03/19] add check for flow --- sip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sip.js b/sip.js index 697ede2..67661ff 100644 --- a/sip.js +++ b/sip.js @@ -1396,7 +1396,7 @@ exports.create = function(options, callback) { (function(callback) { if(hop.host === hostname) { - var flow = decodeFlowToken(hop.user); + var flow = hop.user ? decodeFlowToken(hop.user) : undefined; callback(flow ? [flow] : []); } else From 1adbe1cda91c35656500e4b156e35f8866b5a5ff Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Tue, 25 Dec 2018 08:10:56 +0000 Subject: [PATCH 04/19] add check for empty / undefined / null when doing deep copy --- sip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sip.js b/sip.js index 5378e87..14ada0f 100644 --- a/sip.js +++ b/sip.js @@ -406,7 +406,7 @@ exports.makeResponse = makeResponse; function clone(o, deep) { if(typeof o === 'object') { var r = Array.isArray(o) ? [] : {}; - Object.keys(o).forEach(function(k) { r[k] = deep ? clone(o[k], deep): o[k]; }); + Object.keys(o).forEach(function(k) { r[k] = deep && o[k] ? clone(o[k], deep): o[k]; }); return r; } From 72a117b699476ebd9b48d6cb0ac2597372bca34e Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Tue, 25 Dec 2018 08:11:21 +0000 Subject: [PATCH 05/19] bubble up when there is an error --- sip.js | 1 + 1 file changed, 1 insertion(+) diff --git a/sip.js b/sip.js index 14ada0f..9811b95 100644 --- a/sip.js +++ b/sip.js @@ -1293,6 +1293,7 @@ function sequentialSearch(transaction, connect, addresses, rq, callback) { var client = transaction(connect(address, function(err) { if(err) { console.log("err: ", err); + return callback(makeResponse(rq, 503, 'Unreachable') ); } client.message(makeResponse(rq, 503)); }), rq, function() { onresponse.apply(null, arguments); }); From 08c7c4fdf4691dd8994924108e8f0bd101964750 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Tue, 25 Dec 2018 08:12:02 +0000 Subject: [PATCH 06/19] handle cases where there could be 2 processes in same host --- sip.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sip.js b/sip.js index 9811b95..48c8234 100644 --- a/sip.js +++ b/sip.js @@ -1385,7 +1385,7 @@ exports.create = function(options, callback) { if(m.headers.route && m.headers.route.length > 0) { hop = parseUri(m.headers.route[0].uri); - if(hop.host === hostname) { + if(hop.host === hostname && hop.port === options.port) { m.headers.route.shift(); } else if(hop.params.lr === undefined ) { @@ -1396,7 +1396,7 @@ exports.create = function(options, callback) { } (function(callback) { - if(hop.host === hostname) { + if(hop.host === hostname && hop.port === options.port) { var flow = hop.user ? decodeFlowToken(hop.user) : undefined; callback(flow ? [flow] : []); } From 6865f9433d2b4a70cfec554113896334ecab99c0 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Wed, 9 Jan 2019 14:42:05 +0000 Subject: [PATCH 07/19] handle cancel --- sip.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sip.js b/sip.js index 48c8234..16c5a61 100644 --- a/sip.js +++ b/sip.js @@ -1343,6 +1343,10 @@ exports.create = function(options, callback) { } } else { + // high level logic should decide what to do with unmatched cancel - stateful/stateless proxy + if (m.method == 'CANCEL') { + return callback(m, remote); + } t.message && t.message(m, remote); } } From fb00f4316e3fe7031f379302d7e8b8bea5226914 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Mon, 14 Jan 2019 15:14:18 +0000 Subject: [PATCH 08/19] add cancel and expsose getContext --- proxy.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/proxy.js b/proxy.js index aae068e..4866b80 100644 --- a/proxy.js +++ b/proxy.js @@ -5,7 +5,7 @@ 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]; + return [via.params.branch, via.protocol, via.host, via.port || '', msg.headers['call-id'], msg.headers.cseq.seq]; } function defaultCallback(rs) { @@ -53,6 +53,15 @@ function sendCancel(rq, via, route) { function forwardRequest(ctx, rq, callback) { var route = rq.headers.route && rq.headers.route.slice(); + if (!ctx.cancellers[rq.headers.via[0].params.branch]) + ctx.cancellers[rq.headers.via[0].params.branch] = function() { + const rsc = sip.makeResponse(rq, 481); + const t = sip.transaction.getClient(rsc); + t.message && t.message(rsc); + rq.headers.via.shift(); + const rss = sip.makeResponse(rq, 481); + sip.send(rss); + }; sip.send(rq, function(rs, remote) { if(+rs.status < 200) { var via = rs.headers.via[0]; @@ -108,3 +117,6 @@ exports.start = function(options, route) { exports.stop = sip.stop; +exports.getContext = (rq) => { + return contexts[makeContextId(rq)]; +} From 3480b214e41a8f155e87c2c52c44c90b5e6ff105 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Tue, 5 Feb 2019 14:50:35 +0000 Subject: [PATCH 09/19] handle default port on sip.js --- sip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sip.js b/sip.js index 16c5a61..1a5e90d 100644 --- a/sip.js +++ b/sip.js @@ -218,7 +218,7 @@ function parseUri(s) { user: r[2], password: r[3], host: r[4], - port: +r[5], + port: (r[5] ? +r[5] : 5060), params: (r[6].match(/([^;=]+)(=([^;=]+))?/g) || []) .map(function(s) { return s.split('='); }) .reduce(function(params, x) { params[x[0]]=x[1] || null; return params;}, {}), From 03974d1a74f35ed11950d13ec2377d8fd64b9c30 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Tue, 5 Feb 2019 14:51:03 +0000 Subject: [PATCH 10/19] handle default port on proxy.js --- proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy.js b/proxy.js index 4866b80..417b916 100644 --- a/proxy.js +++ b/proxy.js @@ -5,7 +5,7 @@ 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]; + return [via.params.branch, via.protocol, via.host, via.port || 5060, msg.headers['call-id'], msg.headers.cseq.seq]; } function defaultCallback(rs) { From 9c57a231fba697aba38fc520e8882b6b7ef0eabc Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Tue, 5 Feb 2019 14:51:17 +0000 Subject: [PATCH 11/19] add message to 481 --- proxy.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proxy.js b/proxy.js index 417b916..bba81ae 100644 --- a/proxy.js +++ b/proxy.js @@ -55,11 +55,11 @@ function forwardRequest(ctx, rq, callback) { var route = rq.headers.route && rq.headers.route.slice(); if (!ctx.cancellers[rq.headers.via[0].params.branch]) ctx.cancellers[rq.headers.via[0].params.branch] = function() { - const rsc = sip.makeResponse(rq, 481); + const rsc = sip.makeResponse(rq, 481, "Call doesn't exist"); const t = sip.transaction.getClient(rsc); - t.message && t.message(rsc); + t && t.message && t.message(rsc); rq.headers.via.shift(); - const rss = sip.makeResponse(rq, 481); + const rss = sip.makeResponse(rq, 481, "Call doesn't exist"); sip.send(rss); }; sip.send(rq, function(rs, remote) { @@ -106,7 +106,7 @@ exports.start = function(options, route) { } } else { - sip.send(sip.makeResponse(rq, 481)); + sip.send(sip.makeResponse(rq, 481, "Call doesn't exist")); } } else { From b421116b227fa6e231272afed1738303b819c0cc Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Thu, 28 Feb 2019 19:06:14 +0000 Subject: [PATCH 12/19] remove unnecessary cancel handler --- proxy.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/proxy.js b/proxy.js index bba81ae..024954f 100644 --- a/proxy.js +++ b/proxy.js @@ -53,15 +53,6 @@ function sendCancel(rq, via, route) { function forwardRequest(ctx, rq, callback) { var route = rq.headers.route && rq.headers.route.slice(); - if (!ctx.cancellers[rq.headers.via[0].params.branch]) - ctx.cancellers[rq.headers.via[0].params.branch] = function() { - const rsc = sip.makeResponse(rq, 481, "Call doesn't exist"); - const t = sip.transaction.getClient(rsc); - t && t.message && t.message(rsc); - rq.headers.via.shift(); - const rss = sip.makeResponse(rq, 481, "Call doesn't exist"); - sip.send(rss); - }; sip.send(rq, function(rs, remote) { if(+rs.status < 200) { var via = rs.headers.via[0]; From 4867b1340816d5d0e7a5ca1e2b893b11dbf3d079 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Wed, 27 Mar 2019 03:13:03 +0000 Subject: [PATCH 13/19] better 503 handling --- sip.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sip.js b/sip.js index 1a5e90d..c77a70a 100644 --- a/sip.js +++ b/sip.js @@ -1284,6 +1284,7 @@ function sequentialSearch(transaction, connect, addresses, rq, callback) { var onresponse; var lastStatusCode; + var lastStatusReason; function next() { onresponse = searching; @@ -1295,21 +1296,22 @@ function sequentialSearch(transaction, connect, addresses, rq, callback) { console.log("err: ", err); return callback(makeResponse(rq, 503, 'Unreachable') ); } - client.message(makeResponse(rq, 503)); + client.message(makeResponse(rq, 503, 'Server Error')); }), rq, function() { onresponse.apply(null, arguments); }); } catch(e) { - onresponse(address.local ? makeResponse(rq, 430) : makeResponse(rq, 503)); + onresponse(address.local ? makeResponse(rq, 430) : makeResponse(rq, 503, 'Service Error')); } } else { onresponse = callback; - onresponse(makeResponse(rq, lastStatusCode || 404)); + onresponse(makeResponse(rq, lastStatusCode || 404, lastStatusReason || '')); } } function searching(rs) { lastStatusCode = rs.status; + lastStatusReason = rs.reason; if(rs.status === 503) return next(); else if(rs.status > 100) From e9c21a7f36b3cdce24d2bc3ed9d5b311a1976305 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Fri, 19 Apr 2019 17:08:04 +0000 Subject: [PATCH 14/19] add error log if cancel fails --- proxy.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proxy.js b/proxy.js index 024954f..cbc2566 100644 --- a/proxy.js +++ b/proxy.js @@ -94,9 +94,12 @@ exports.start = function(options, route) { ctx.cancelled = true; if(ctx.cancellers) { Object.keys(ctx.cancellers).forEach(function(c) { ctx.cancellers[c](); }); + } else { + console.error(rq.headers['call-id'], 'CANCEL - Cancellers doesn\'t exist'); } } else { + console.error(rq.headers['call-id'], 'CANCEL - Call doesn\'t exist'); sip.send(sip.makeResponse(rq, 481, "Call doesn't exist")); } } From dbfd346beb054db371287deb61403982fa106855 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Sat, 20 Apr 2019 02:35:21 +0000 Subject: [PATCH 15/19] cancel should bubble up --- proxy.js | 1 + sip.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/proxy.js b/proxy.js index cbc2566..f7e2a7a 100644 --- a/proxy.js +++ b/proxy.js @@ -102,6 +102,7 @@ exports.start = function(options, route) { console.error(rq.headers['call-id'], 'CANCEL - Call doesn\'t exist'); sip.send(sip.makeResponse(rq, 481, "Call doesn't exist")); } + route(rq, remote) } else { onRequest(rq, route, remote); diff --git a/sip.js b/sip.js index c77a70a..2d98495 100644 --- a/sip.js +++ b/sip.js @@ -1345,7 +1345,7 @@ exports.create = function(options, callback) { } } else { - // high level logic should decide what to do with unmatched cancel - stateful/stateless proxy + // rare case, high level logic should decide what to do with this case of cancel - stateful/stateless proxy if (m.method == 'CANCEL') { return callback(m, remote); } From 0eb25a263cff52c27b92d6fd2061876a704735b0 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Sun, 21 Apr 2019 02:45:41 +0000 Subject: [PATCH 16/19] udp should have priority --- sip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sip.js b/sip.js index 2d98495..2237b81 100644 --- a/sip.js +++ b/sip.js @@ -918,7 +918,7 @@ function resolve(uri, action) { }); } else { - var protocols = uri.params.transport ? [uri.params.transport] : ['tcp', 'udp', 'tls']; + var protocols = uri.params.transport ? [uri.params.transport] : ['udp', 'tcp', 'tls']; var n = protocols.length; var addresses = []; From fa2a5c8681de26f2acd9497465f2bade4fb3dd31 Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Sat, 14 Sep 2019 06:41:04 +0000 Subject: [PATCH 17/19] fix dynamic port use case - flow broken --- sip.js | 1 + 1 file changed, 1 insertion(+) diff --git a/sip.js b/sip.js index 2237b81..9028d1d 100644 --- a/sip.js +++ b/sip.js @@ -781,6 +781,7 @@ function makeUdpTransport(options, callback) { socket.on("listening", function() { options.port = socket.address().port; + port = socket.address().port; }); function open(remote, error) { From b35c29c5c1460af697399ed03d9efa96a8140d4f Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Wed, 16 Dec 2020 23:24:26 +0800 Subject: [PATCH 18/19] slice should have arg --- proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy.js b/proxy.js index f7e2a7a..77c0752 100644 --- a/proxy.js +++ b/proxy.js @@ -52,7 +52,7 @@ function sendCancel(rq, via, route) { function forwardRequest(ctx, rq, callback) { - var route = rq.headers.route && rq.headers.route.slice(); + var route = rq.headers.route && rq.headers.route.slice(1); sip.send(rq, function(rs, remote) { if(+rs.status < 200) { var via = rs.headers.via[0]; From e48e0b807242beb512d0910a546f1d8565d379ce Mon Sep 17 00:00:00 2001 From: Kelvin Chua Date: Wed, 16 Dec 2020 23:36:29 +0800 Subject: [PATCH 19/19] revert - useless --- proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy.js b/proxy.js index 77c0752..f7e2a7a 100644 --- a/proxy.js +++ b/proxy.js @@ -52,7 +52,7 @@ function sendCancel(rq, via, route) { function forwardRequest(ctx, rq, callback) { - var route = rq.headers.route && rq.headers.route.slice(1); + 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];