ringcentral-softphone 1.2.5 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/call-session/inbound.js +11 -2
- package/dist/cjs/call-session/index.js +5 -2
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/sip-message/outbound/response.js +9 -4
- package/dist/esm/call-session/inbound.js +11 -2
- package/dist/esm/call-session/index.js +5 -2
- package/dist/esm/index.js +3 -1
- package/dist/esm/sip-message/outbound/response.js +9 -4
- package/package.json +3 -2
|
@@ -11,7 +11,10 @@ class InboundCallSession extends index_js_1.default {
|
|
|
11
11
|
super(softphone, inviteMessage);
|
|
12
12
|
this.localPeer = inviteMessage.headers.To;
|
|
13
13
|
this.remotePeer = inviteMessage.headers.From;
|
|
14
|
-
|
|
14
|
+
// inbound call from call queue, invite message may not have body
|
|
15
|
+
if (inviteMessage.body.length > 0) {
|
|
16
|
+
this.remoteKey = inviteMessage.body.match(/AES_CM_128_HMAC_SHA1_80 inline:([\w+/]+)/)[1];
|
|
17
|
+
}
|
|
15
18
|
}
|
|
16
19
|
async answer() {
|
|
17
20
|
const answerSDP = `
|
|
@@ -41,7 +44,13 @@ a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:${utils_js_1.localKey}
|
|
|
41
44
|
Require: "timer",
|
|
42
45
|
"Content-Type": "application/sdp",
|
|
43
46
|
}, answerSDP);
|
|
44
|
-
await this.softphone.send(newMessage);
|
|
47
|
+
const ackMessage = await this.softphone.send(newMessage, true);
|
|
48
|
+
// for inbound call from call queue, ack message may HAVE body (while invite message has no body)
|
|
49
|
+
if (ackMessage.body.length > 0) {
|
|
50
|
+
this.remoteIP = ackMessage.body.match(/c=IN IP4 ([\d.]+)/)[1];
|
|
51
|
+
this.remotePort = parseInt(ackMessage.body.match(/m=audio (\d+) /)[1], 10);
|
|
52
|
+
this.remoteKey = ackMessage.body.match(/AES_CM_128_HMAC_SHA1_80 inline:([\w+/]+)/)[1];
|
|
53
|
+
}
|
|
45
54
|
this.startLocalServices();
|
|
46
55
|
}
|
|
47
56
|
}
|
|
@@ -35,8 +35,11 @@ class CallSession extends node_events_1.default {
|
|
|
35
35
|
this.encoder = softphone.codec.createEncoder();
|
|
36
36
|
this.decoder = softphone.codec.createDecoder();
|
|
37
37
|
this.sipMessage = sipMessage;
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
// inbound call from call queue, invite message may not have body
|
|
39
|
+
if (this.sipMessage.body.length > 0) {
|
|
40
|
+
this.remoteIP = this.sipMessage.body.match(/c=IN IP4 ([\d.]+)/)[1];
|
|
41
|
+
this.remotePort = parseInt(this.sipMessage.body.match(/m=audio (\d+) /)[1], 10);
|
|
42
|
+
}
|
|
40
43
|
}
|
|
41
44
|
set remoteKey(key) {
|
|
42
45
|
const localKeyBuffer = node_buffer_1.Buffer.from(utils_js_1.localKey, "base64");
|
package/dist/cjs/index.js
CHANGED
|
@@ -143,7 +143,9 @@ class Softphone extends node_events_1.default {
|
|
|
143
143
|
}
|
|
144
144
|
return new Promise((resolve) => {
|
|
145
145
|
const messageListerner = (inboundMessage) => {
|
|
146
|
-
|
|
146
|
+
// "12563 INVITE" vs "12563 ACK"
|
|
147
|
+
if (inboundMessage.headers.CSeq.trim().split(/\s+/)[0] !==
|
|
148
|
+
message.headers.CSeq.trim().split(/\s+/)[0]) {
|
|
147
149
|
return;
|
|
148
150
|
}
|
|
149
151
|
if (inboundMessage.subject.startsWith("SIP/2.0 100 ")) {
|
|
@@ -9,10 +9,15 @@ class ResponseMessage extends index_js_1.default {
|
|
|
9
9
|
constructor(inboundMessage, responseCode, headers = {}, body = "") {
|
|
10
10
|
super(undefined, { ...headers }, body);
|
|
11
11
|
this.subject = `SIP/2.0 ${responseCode} ${response_codes_js_1.default[responseCode]}`;
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const requiredKeys = new Set(["via", "from", "to", "call-id", "cseq"]);
|
|
13
|
+
const allKeys = Object.keys(inboundMessage.headers).reduce((acc, key) => {
|
|
14
|
+
acc[key.toLowerCase()] = key;
|
|
15
|
+
return acc;
|
|
16
|
+
}, {});
|
|
17
|
+
for (const key of requiredKeys) {
|
|
18
|
+
if (allKeys[key]) {
|
|
19
|
+
const originalKey = allKeys[key];
|
|
20
|
+
this.headers[originalKey] = inboundMessage.headers[originalKey];
|
|
16
21
|
}
|
|
17
22
|
}
|
|
18
23
|
}
|
|
@@ -6,7 +6,10 @@ class InboundCallSession extends CallSession {
|
|
|
6
6
|
super(softphone, inviteMessage);
|
|
7
7
|
this.localPeer = inviteMessage.headers.To;
|
|
8
8
|
this.remotePeer = inviteMessage.headers.From;
|
|
9
|
-
|
|
9
|
+
// inbound call from call queue, invite message may not have body
|
|
10
|
+
if (inviteMessage.body.length > 0) {
|
|
11
|
+
this.remoteKey = inviteMessage.body.match(/AES_CM_128_HMAC_SHA1_80 inline:([\w+/]+)/)[1];
|
|
12
|
+
}
|
|
10
13
|
}
|
|
11
14
|
async answer() {
|
|
12
15
|
const answerSDP = `
|
|
@@ -36,7 +39,13 @@ a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:${localKey}
|
|
|
36
39
|
Require: "timer",
|
|
37
40
|
"Content-Type": "application/sdp",
|
|
38
41
|
}, answerSDP);
|
|
39
|
-
await this.softphone.send(newMessage);
|
|
42
|
+
const ackMessage = await this.softphone.send(newMessage, true);
|
|
43
|
+
// for inbound call from call queue, ack message may HAVE body (while invite message has no body)
|
|
44
|
+
if (ackMessage.body.length > 0) {
|
|
45
|
+
this.remoteIP = ackMessage.body.match(/c=IN IP4 ([\d.]+)/)[1];
|
|
46
|
+
this.remotePort = parseInt(ackMessage.body.match(/m=audio (\d+) /)[1], 10);
|
|
47
|
+
this.remoteKey = ackMessage.body.match(/AES_CM_128_HMAC_SHA1_80 inline:([\w+/]+)/)[1];
|
|
48
|
+
}
|
|
40
49
|
this.startLocalServices();
|
|
41
50
|
}
|
|
42
51
|
}
|
|
@@ -30,8 +30,11 @@ class CallSession extends EventEmitter {
|
|
|
30
30
|
this.encoder = softphone.codec.createEncoder();
|
|
31
31
|
this.decoder = softphone.codec.createDecoder();
|
|
32
32
|
this.sipMessage = sipMessage;
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
// inbound call from call queue, invite message may not have body
|
|
34
|
+
if (this.sipMessage.body.length > 0) {
|
|
35
|
+
this.remoteIP = this.sipMessage.body.match(/c=IN IP4 ([\d.]+)/)[1];
|
|
36
|
+
this.remotePort = parseInt(this.sipMessage.body.match(/m=audio (\d+) /)[1], 10);
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
39
|
set remoteKey(key) {
|
|
37
40
|
const localKeyBuffer = Buffer.from(localKey, "base64");
|
package/dist/esm/index.js
CHANGED
|
@@ -138,7 +138,9 @@ class Softphone extends EventEmitter {
|
|
|
138
138
|
}
|
|
139
139
|
return new Promise((resolve) => {
|
|
140
140
|
const messageListerner = (inboundMessage) => {
|
|
141
|
-
|
|
141
|
+
// "12563 INVITE" vs "12563 ACK"
|
|
142
|
+
if (inboundMessage.headers.CSeq.trim().split(/\s+/)[0] !==
|
|
143
|
+
message.headers.CSeq.trim().split(/\s+/)[0]) {
|
|
142
144
|
return;
|
|
143
145
|
}
|
|
144
146
|
if (inboundMessage.subject.startsWith("SIP/2.0 100 ")) {
|
|
@@ -4,10 +4,15 @@ class ResponseMessage extends OutboundMessage {
|
|
|
4
4
|
constructor(inboundMessage, responseCode, headers = {}, body = "") {
|
|
5
5
|
super(undefined, { ...headers }, body);
|
|
6
6
|
this.subject = `SIP/2.0 ${responseCode} ${responseCodes[responseCode]}`;
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const requiredKeys = new Set(["via", "from", "to", "call-id", "cseq"]);
|
|
8
|
+
const allKeys = Object.keys(inboundMessage.headers).reduce((acc, key) => {
|
|
9
|
+
acc[key.toLowerCase()] = key;
|
|
10
|
+
return acc;
|
|
11
|
+
}, {});
|
|
12
|
+
for (const key of requiredKeys) {
|
|
13
|
+
if (allKeys[key]) {
|
|
14
|
+
const originalKey = allKeys[key];
|
|
15
|
+
this.headers[originalKey] = inboundMessage.headers[originalKey];
|
|
11
16
|
}
|
|
12
17
|
}
|
|
13
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ringcentral-softphone",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"homepage": "https://github.com/ringcentral/ringcentral-softphone-ts",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"types": "dist/esm/index.d.ts",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"in": "rm -rf *.wav && tsx -r dotenv-override-true/config demos/inbound-call.ts",
|
|
26
26
|
"out": "rm -rf *.wav && tsx -r dotenv-override-true/config demos/outbound-call.ts",
|
|
27
27
|
"join": "rm -rf *.wav && tsx -r dotenv-override-true/config demos/join-rcv-meeting.ts",
|
|
28
|
+
"multi": "tsx -r dotenv-override-true/config demos/multiple-calls-sequentially.ts",
|
|
28
29
|
"build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json",
|
|
29
30
|
"prepublishOnly": "yarn build",
|
|
30
31
|
"postpublish": "rm -rf dist"
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
"werift-rtp": "^0.8.8"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^25.0
|
|
40
|
+
"@types/node": "^25.2.0",
|
|
40
41
|
"dotenv-override-true": "^6.2.2",
|
|
41
42
|
"tsx": "^4.21.0",
|
|
42
43
|
"typescript": "^5.9.3",
|