ringcentral-softphone 0.8.5 → 0.10.0
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/README.md +2 -3
- package/demos/inbound-call.ts +10 -3
- package/demos/outbound-call.ts +8 -1
- package/dist/demos/inbound-call.js +8 -3
- package/dist/demos/inbound-call.js.map +1 -1
- package/dist/demos/outbound-call.js +7 -1
- package/dist/demos/outbound-call.js.map +1 -1
- package/dist/src/call-session/inbound.js.map +1 -1
- package/dist/src/call-session/index.d.ts +4 -1
- package/dist/src/call-session/index.js +64 -35
- package/dist/src/call-session/index.js.map +1 -1
- package/dist/src/softphone.js +6 -4
- package/dist/src/softphone.js.map +1 -1
- package/package.json +12 -12
- package/src/call-session/inbound.ts +1 -1
- package/src/call-session/index.ts +34 -4
- package/src/softphone.ts +6 -4
package/README.md
CHANGED
|
@@ -28,7 +28,6 @@ yarn install ringcentral-softphone
|
|
|
28
28
|
```ts
|
|
29
29
|
import fs from 'fs';
|
|
30
30
|
import Softphone from 'ringcentral-softphone';
|
|
31
|
-
import type { RtpPacket } from 'werift-rtp';
|
|
32
31
|
|
|
33
32
|
const softphone = new Softphone({
|
|
34
33
|
username: process.env.SIP_INFO_USERNAME,
|
|
@@ -52,7 +51,7 @@ For complete examples, see [demos/](demos/)
|
|
|
52
51
|
- receive audio stream from peer
|
|
53
52
|
- stream local audio to remote peer
|
|
54
53
|
- outbound call caller ID
|
|
55
|
-
|
|
54
|
+
- call transfer
|
|
56
55
|
|
|
57
56
|
## Notes
|
|
58
57
|
|
|
@@ -79,7 +78,7 @@ play -b 8 -r 8000 -e mu-law test.raw
|
|
|
79
78
|
- tried OPUS/16000, but the received packets are quite small and cannot be played
|
|
80
79
|
- do not hard code `domain` and `outboundProxy`
|
|
81
80
|
- I tried `sip10.ringcentral.com:5096` as `outboundProxy`, it requires TLS instead of TCP
|
|
82
|
-
- I made TLS work, however for inbound call there is
|
|
81
|
+
- I made TLS work, however for inbound call there is no INVITE message coming in, for outbound call "488 Not Acceptable Here"
|
|
83
82
|
- check the code of PJSIP and refactor the code.
|
|
84
83
|
- Let developer check the call info, such as who is calling, who is being called, etc.
|
|
85
84
|
|
package/demos/inbound-call.ts
CHANGED
|
@@ -2,7 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import type { RtpPacket } from 'werift-rtp';
|
|
3
3
|
|
|
4
4
|
import Softphone from '../src/softphone';
|
|
5
|
-
|
|
5
|
+
import waitFor from 'wait-for-async';
|
|
6
6
|
|
|
7
7
|
const softphone = new Softphone({
|
|
8
8
|
username: process.env.SIP_INFO_USERNAME,
|
|
@@ -28,8 +28,11 @@ const main = async () => {
|
|
|
28
28
|
writeStream.write(rtpPacket.payload);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
// // send audio to remote peer
|
|
32
|
-
// callSession.streamAudio(fs.readFileSync('demos/test.raw'));
|
|
31
|
+
// // // send audio to remote peer
|
|
32
|
+
// const streamer = callSession.streamAudio(fs.readFileSync('demos/test.raw'));
|
|
33
|
+
// await waitFor({ interval: 3000 });
|
|
34
|
+
// // you may interrupt audio sending at any time
|
|
35
|
+
// streamer.stop();
|
|
33
36
|
|
|
34
37
|
// either you or the peer hang up
|
|
35
38
|
callSession.once('disposed', () => {
|
|
@@ -50,6 +53,10 @@ const main = async () => {
|
|
|
50
53
|
// // hang up the call
|
|
51
54
|
// await waitFor({ interval: 5000 });
|
|
52
55
|
// callSession.hangup();
|
|
56
|
+
|
|
57
|
+
// // transfer the call
|
|
58
|
+
// await waitFor({ interval: 2000 });
|
|
59
|
+
// await callSession.transfer(process.env.ANOTHER_CALLEE_FOR_TESTING);
|
|
53
60
|
});
|
|
54
61
|
};
|
|
55
62
|
main();
|
package/demos/outbound-call.ts
CHANGED
|
@@ -33,7 +33,10 @@ const main = async () => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
// // send audio to remote peer
|
|
36
|
-
// callSession.streamAudio(fs.readFileSync('demos/test.raw'));
|
|
36
|
+
// const streamer = callSession.streamAudio(fs.readFileSync('demos/test.raw'));
|
|
37
|
+
// await waitFor({ interval: 3000 });
|
|
38
|
+
// // you may interrupt audio sending at any time
|
|
39
|
+
// streamer.stop();
|
|
37
40
|
|
|
38
41
|
// receive DTMF
|
|
39
42
|
callSession.on('dtmf', (digit) => {
|
|
@@ -49,6 +52,10 @@ const main = async () => {
|
|
|
49
52
|
// // hang up the call
|
|
50
53
|
// await waitFor({ interval: 5000 });
|
|
51
54
|
// callSession.hangup();
|
|
55
|
+
|
|
56
|
+
// // transfer the call
|
|
57
|
+
// await waitFor({ interval: 2000 });
|
|
58
|
+
// await callSession.transfer(process.env.ANOTHER_CALLEE_FOR_TESTING);
|
|
52
59
|
});
|
|
53
60
|
|
|
54
61
|
// // cancel the call (before the peer answers)
|
|
@@ -14,7 +14,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const fs_1 = __importDefault(require("fs"));
|
|
16
16
|
const softphone_1 = __importDefault(require("../src/softphone"));
|
|
17
|
-
// import waitFor from 'wait-for-async';
|
|
18
17
|
const softphone = new softphone_1.default({
|
|
19
18
|
username: process.env.SIP_INFO_USERNAME,
|
|
20
19
|
password: process.env.SIP_INFO_PASSWORD,
|
|
@@ -35,8 +34,11 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
35
34
|
callSession.on('audioPacket', (rtpPacket) => {
|
|
36
35
|
writeStream.write(rtpPacket.payload);
|
|
37
36
|
});
|
|
38
|
-
// // send audio to remote peer
|
|
39
|
-
// callSession.streamAudio(fs.readFileSync('demos/test.raw'));
|
|
37
|
+
// // // send audio to remote peer
|
|
38
|
+
// const streamer = callSession.streamAudio(fs.readFileSync('demos/test.raw'));
|
|
39
|
+
// await waitFor({ interval: 3000 });
|
|
40
|
+
// // you may interrupt audio sending at any time
|
|
41
|
+
// streamer.stop();
|
|
40
42
|
// either you or the peer hang up
|
|
41
43
|
callSession.once('disposed', () => {
|
|
42
44
|
writeStream.close();
|
|
@@ -53,6 +55,9 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
53
55
|
// // hang up the call
|
|
54
56
|
// await waitFor({ interval: 5000 });
|
|
55
57
|
// callSession.hangup();
|
|
58
|
+
// // transfer the call
|
|
59
|
+
// await waitFor({ interval: 2000 });
|
|
60
|
+
// await callSession.transfer(process.env.ANOTHER_CALLEE_FOR_TESTING);
|
|
56
61
|
}));
|
|
57
62
|
});
|
|
58
63
|
main();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbound-call.js","sourceRoot":"","sources":["../../demos/inbound-call.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,4CAAoB;AAGpB,iEAAyC;
|
|
1
|
+
{"version":3,"file":"inbound-call.js","sourceRoot":"","sources":["../../demos/inbound-call.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,4CAAoB;AAGpB,iEAAyC;AAGzC,MAAM,SAAS,GAAG,IAAI,mBAAS,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IACvC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IACvC,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB;CACvD,CAAC,CAAC;AACH,SAAS,CAAC,eAAe,EAAE,CAAC,CAAC,yBAAyB;AAEtD,MAAM,IAAI,GAAG,GAAS,EAAE;IACtB,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC;IAC3B,sBAAsB;IACtB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAO,aAAa,EAAE,EAAE;QAC7C,mBAAmB;QACnB,qCAAqC;QACrC,0CAA0C;QAE1C,kBAAkB;QAClB,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAE1D,gBAAgB;QAChB,MAAM,WAAW,GAAG,YAAE,CAAC,iBAAiB,CAAC,GAAG,WAAW,CAAC,MAAM,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACtF,WAAW,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,SAAoB,EAAE,EAAE;YACrD,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,kCAAkC;QAClC,+EAA+E;QAC/E,qCAAqC;QACrC,iDAAiD;QACjD,mBAAmB;QAEnB,iCAAiC;QACjC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE;YAChC,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,eAAe;QACf,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,eAAe;QACf,qCAAqC;QACrC,6BAA6B;QAC7B,qCAAqC;QACrC,6BAA6B;QAE7B,sBAAsB;QACtB,qCAAqC;QACrC,wBAAwB;QAExB,uBAAuB;QACvB,qCAAqC;QACrC,sEAAsE;IACxE,CAAC,CAAA,CAAC,CAAC;AACL,CAAC,CAAA,CAAC;AACF,IAAI,EAAE,CAAC"}
|
|
@@ -38,7 +38,10 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
38
38
|
writeStream.close();
|
|
39
39
|
});
|
|
40
40
|
// // send audio to remote peer
|
|
41
|
-
// callSession.streamAudio(fs.readFileSync('demos/test.raw'));
|
|
41
|
+
// const streamer = callSession.streamAudio(fs.readFileSync('demos/test.raw'));
|
|
42
|
+
// await waitFor({ interval: 3000 });
|
|
43
|
+
// // you may interrupt audio sending at any time
|
|
44
|
+
// streamer.stop();
|
|
42
45
|
// receive DTMF
|
|
43
46
|
callSession.on('dtmf', (digit) => {
|
|
44
47
|
console.log('dtmf', digit);
|
|
@@ -51,6 +54,9 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
51
54
|
// // hang up the call
|
|
52
55
|
// await waitFor({ interval: 5000 });
|
|
53
56
|
// callSession.hangup();
|
|
57
|
+
// // transfer the call
|
|
58
|
+
// await waitFor({ interval: 2000 });
|
|
59
|
+
// await callSession.transfer(process.env.ANOTHER_CALLEE_FOR_TESTING);
|
|
54
60
|
}));
|
|
55
61
|
// // cancel the call (before the peer answers)
|
|
56
62
|
// await waitFor({ interval: 8000 });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbound-call.js","sourceRoot":"","sources":["../../demos/outbound-call.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,4CAAoB;AAEpB,oEAAqC;AAErC,iEAAyC;AAEzC,MAAM,SAAS,GAAG,IAAI,mBAAS,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IACvC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IACvC,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB;CACvD,CAAC,CAAC;AACH,SAAS,CAAC,eAAe,EAAE,CAAC,CAAC,yBAAyB;AAEtD,MAAM,IAAI,GAAG,GAAS,EAAE;IACtB,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC;IAC3B,MAAM,IAAA,wBAAO,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAClC,+FAA+F;IAC/F,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,IAAI,CACtC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAmB,EAAE,EAAE,CAAC,CAE9C,CAAC;IAEF,0BAA0B;IAC1B,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,GAAS,EAAE;QACtC,gBAAgB;QAChB,MAAM,WAAW,GAAG,YAAE,CAAC,iBAAiB,CAAC,GAAG,WAAW,CAAC,MAAM,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACtF,WAAW,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,SAAoB,EAAE,EAAE;YACrD,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,iCAAiC;QACjC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE;YAChC,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,+BAA+B;QAC/B,
|
|
1
|
+
{"version":3,"file":"outbound-call.js","sourceRoot":"","sources":["../../demos/outbound-call.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,4CAAoB;AAEpB,oEAAqC;AAErC,iEAAyC;AAEzC,MAAM,SAAS,GAAG,IAAI,mBAAS,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IACvC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IACvC,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB;CACvD,CAAC,CAAC;AACH,SAAS,CAAC,eAAe,EAAE,CAAC,CAAC,yBAAyB;AAEtD,MAAM,IAAI,GAAG,GAAS,EAAE;IACtB,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC;IAC3B,MAAM,IAAA,wBAAO,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAClC,+FAA+F;IAC/F,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,IAAI,CACtC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAmB,EAAE,EAAE,CAAC,CAE9C,CAAC;IAEF,0BAA0B;IAC1B,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,GAAS,EAAE;QACtC,gBAAgB;QAChB,MAAM,WAAW,GAAG,YAAE,CAAC,iBAAiB,CAAC,GAAG,WAAW,CAAC,MAAM,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACtF,WAAW,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,SAAoB,EAAE,EAAE;YACrD,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,iCAAiC;QACjC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE;YAChC,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,+BAA+B;QAC/B,+EAA+E;QAC/E,qCAAqC;QACrC,iDAAiD;QACjD,mBAAmB;QAEnB,eAAe;QACf,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,eAAe;QACf,qCAAqC;QACrC,6BAA6B;QAC7B,qCAAqC;QACrC,6BAA6B;QAE7B,sBAAsB;QACtB,qCAAqC;QACrC,wBAAwB;QAExB,uBAAuB;QACvB,qCAAqC;QACrC,sEAAsE;IACxE,CAAC,CAAA,CAAC,CAAC;IAEH,+CAA+C;IAC/C,qCAAqC;IACrC,wBAAwB;AAC1B,CAAC,CAAA,CAAC;AACF,IAAI,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../../src/call-session/inbound.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,gDAAsE;AACtE,
|
|
1
|
+
{"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../../src/call-session/inbound.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,gDAAsE;AACtE,oCAAqC;AAErC,yCAA4B;AAE5B,MAAM,kBAAmB,SAAQ,UAAW;IAC1C,YAAmB,SAAoB,EAAE,aAA6B;QACpE,KAAK,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC;IAC/C,CAAC;IAEY,MAAM;;YACjB,MAAM,SAAS,GAAG;;MAEhB,IAAA,iBAAS,GAAE;;;;UAIP,IAAA,iBAAS,GAAE;;;;;CAKpB,CAAC,IAAI,EAAE,CAAC;YACL,MAAM,UAAU,GAAG,IAAI,6BAAe,CACpC,IAAI,CAAC,UAAU,EACf,GAAG,EACH;gBACE,cAAc,EAAE,iBAAiB;aAClC,EACD,SAAS,CACV,CAAC;YACF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAEhC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC;KAAA;CACF;AAED,kBAAe,kBAAkB,CAAC"}
|
|
@@ -17,9 +17,12 @@ declare abstract class CallSession extends EventEmitter {
|
|
|
17
17
|
constructor(softphone: Softphone, sipMessage: InboundMessage);
|
|
18
18
|
get callId(): string;
|
|
19
19
|
send(data: string | Buffer): void;
|
|
20
|
+
transfer(target: string): Promise<void>;
|
|
20
21
|
hangup(): Promise<void>;
|
|
21
22
|
sendDTMF(char: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '*' | '#'): Promise<void>;
|
|
22
|
-
streamAudio(input: Buffer):
|
|
23
|
+
streamAudio(input: Buffer): {
|
|
24
|
+
stop(): void;
|
|
25
|
+
};
|
|
23
26
|
protected startLocalServices(): Promise<void>;
|
|
24
27
|
private dispose;
|
|
25
28
|
}
|
|
@@ -33,6 +33,31 @@ class CallSession extends events_1.default {
|
|
|
33
33
|
send(data) {
|
|
34
34
|
this.socket.send(data, this.remotePort, this.remoteIP);
|
|
35
35
|
}
|
|
36
|
+
transfer(target) {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
const requestMessage = new sip_message_1.RequestMessage(`REFER sip:${(0, utils_1.extractAddress)(this.remotePeer)} SIP/2.0`, {
|
|
39
|
+
'Call-Id': this.callId,
|
|
40
|
+
From: this.localPeer,
|
|
41
|
+
To: this.remotePeer,
|
|
42
|
+
Via: `SIP/2.0/TCP ${this.softphone.fakeDomain};branch=${(0, utils_1.branch)()}`,
|
|
43
|
+
'Refer-To': `sip:${target}@sip.ringcentral.com`,
|
|
44
|
+
'Referred-By': `<${(0, utils_1.extractAddress)(this.localPeer)}>`,
|
|
45
|
+
});
|
|
46
|
+
this.softphone.send(requestMessage);
|
|
47
|
+
// reply to those NOTIFY messages
|
|
48
|
+
const notifyHandler = (inboundMessage) => {
|
|
49
|
+
if (!inboundMessage.subject.startsWith('NOTIFY ')) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const responseMessage = new sip_message_1.ResponseMessage(inboundMessage, 200);
|
|
53
|
+
this.softphone.send(responseMessage);
|
|
54
|
+
if (inboundMessage.body.endsWith('SIP/2.0 200 OK')) {
|
|
55
|
+
this.softphone.off('message', notifyHandler);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
this.softphone.on('message', notifyHandler);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
36
61
|
hangup() {
|
|
37
62
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
63
|
const requestMessage = new sip_message_1.RequestMessage(`BYE sip:${this.softphone.sipInfo.domain} SIP/2.0`, {
|
|
@@ -75,43 +100,47 @@ class CallSession extends events_1.default {
|
|
|
75
100
|
// buffer is the content of a audio file, it is supposed to be PCMU/8000 encoded.
|
|
76
101
|
// The audio should be playable by command: ffplay -autoexit -f mulaw -ar 8000 test.raw
|
|
77
102
|
streamAudio(input) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
let buffer = input;
|
|
104
|
+
let sequenceNumber = (0, utils_1.randomInt)();
|
|
105
|
+
let timestamp = (0, utils_1.randomInt)();
|
|
106
|
+
const ssrc = (0, utils_1.randomInt)();
|
|
107
|
+
const streamer = {
|
|
108
|
+
stop() {
|
|
109
|
+
buffer = Buffer.alloc(0);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
const sendPacket = () => {
|
|
113
|
+
if (buffer.length >= 160) {
|
|
114
|
+
const temp = buffer.subarray(0, 160);
|
|
115
|
+
buffer = buffer.subarray(160);
|
|
116
|
+
const rtpPacket = new werift_rtp_1.RtpPacket(new werift_rtp_1.RtpHeader({
|
|
117
|
+
version: 2,
|
|
118
|
+
padding: false,
|
|
119
|
+
paddingSize: 0,
|
|
120
|
+
extension: false,
|
|
121
|
+
marker: false,
|
|
122
|
+
payloadOffset: 12,
|
|
123
|
+
payloadType: 0,
|
|
124
|
+
sequenceNumber,
|
|
125
|
+
timestamp,
|
|
126
|
+
ssrc,
|
|
127
|
+
csrcLength: 0,
|
|
128
|
+
csrc: [],
|
|
129
|
+
extensionProfile: 48862,
|
|
130
|
+
extensionLength: undefined,
|
|
131
|
+
extensions: [],
|
|
132
|
+
}), temp);
|
|
133
|
+
if (this.disposed) {
|
|
134
|
+
return;
|
|
110
135
|
}
|
|
136
|
+
this.send(rtpPacket.serialize());
|
|
137
|
+
sequenceNumber += 1;
|
|
138
|
+
timestamp += 160; // inbound audio use this time interval, in my opinion, it should be 20
|
|
111
139
|
setTimeout(() => sendPacket(), 20);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
sendPacket();
|
|
143
|
+
return streamer;
|
|
115
144
|
}
|
|
116
145
|
startLocalServices() {
|
|
117
146
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/call-session/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,kDAA0B;AAC1B,2CAAkD;AAElD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/call-session/index.ts"],"names":[],"mappings":"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"}
|
package/dist/src/softphone.js
CHANGED
|
@@ -43,11 +43,13 @@ class Softphone extends events_1.default {
|
|
|
43
43
|
if (!cache.endsWith('\r\n')) {
|
|
44
44
|
return; // haven't received a complete message yet
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
// received two empty body messages
|
|
47
|
+
const tempMessages = cache.split('\r\nContent-Length: 0\r\n\r\n').filter((message) => message.trim() !== '');
|
|
47
48
|
cache = '';
|
|
48
|
-
for (let i =
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
for (let i = 0; i < tempMessages.length; i++) {
|
|
50
|
+
if (!tempMessages[i].includes('Content-Length: ')) {
|
|
51
|
+
tempMessages[i] = tempMessages[i] + '\r\nContent-Length: 0';
|
|
52
|
+
}
|
|
51
53
|
}
|
|
52
54
|
for (const message of tempMessages) {
|
|
53
55
|
this.emit('message', sip_message_1.InboundMessage.fromString(message));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"softphone.js","sourceRoot":"","sources":["../../src/softphone.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AACA,oDAAkC;AAClC,8CAAsB;AACtB,oEAAqC;AAGrC,+CAAgF;AAChF,mCAAyE;AACzE,qEAAwD;AACxD,uEAA0D;AAE1D,MAAM,SAAU,SAAQ,gBAAY;IAUlC,YAAmB,OAAwB;QACzC,KAAK,EAAE,CAAC;QAPH,eAAU,GAAG,IAAA,YAAI,GAAE,GAAG,UAAU,CAAC;QACjC,cAAS,GAAG,IAAA,YAAI,GAAE,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC;QAG1C,cAAS,GAAG,KAAK,CAAC;QAIxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,qBAAqB,CAAC;QAC9C,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YAC7C,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG,kCAAkC,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,aAAG,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,aAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE;YAC3D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC9B,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,0CAA0C;YACpD,CAAC;YACD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"softphone.js","sourceRoot":"","sources":["../../src/softphone.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ringcentral-softphone",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/src/softphone.js",
|
|
6
6
|
"types": "dist/src/softphone.d.ts",
|
|
@@ -12,24 +12,24 @@
|
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://github.com/ringcentral/ringcentral-softphone-ts",
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@types/node": "^20.
|
|
16
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
17
|
-
"@typescript-eslint/parser": "^
|
|
15
|
+
"@types/node": "^20.11.30",
|
|
16
|
+
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
|
17
|
+
"@typescript-eslint/parser": "^7.3.1",
|
|
18
18
|
"dotenv-override-true": "^6.2.2",
|
|
19
|
-
"eslint": "^8.
|
|
19
|
+
"eslint": "^8.57.0",
|
|
20
20
|
"eslint-config-alloy": "^5.1.2",
|
|
21
21
|
"eslint-config-prettier": "^9.1.0",
|
|
22
22
|
"eslint-plugin-prettier": "^5.1.3",
|
|
23
|
-
"prettier": "^3.
|
|
24
|
-
"sort-package-json": "^2.
|
|
25
|
-
"tsx": "^4.7.
|
|
26
|
-
"ttpt": "^0.8.
|
|
27
|
-
"typescript": "^5.
|
|
23
|
+
"prettier": "^3.2.5",
|
|
24
|
+
"sort-package-json": "^2.8.0",
|
|
25
|
+
"tsx": "^4.7.1",
|
|
26
|
+
"ttpt": "^0.8.7",
|
|
27
|
+
"typescript": "^5.4.3",
|
|
28
28
|
"yarn-upgrade-all": "^0.7.2"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@rc-ex/core": "^1.3.
|
|
31
|
+
"@rc-ex/core": "^1.3.10",
|
|
32
32
|
"wait-for-async": "^0.6.1",
|
|
33
|
-
"werift-rtp": "^0.8.
|
|
33
|
+
"werift-rtp": "^0.8.1"
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -2,9 +2,9 @@ import EventEmitter from 'events';
|
|
|
2
2
|
import dgram from 'dgram';
|
|
3
3
|
import { RtpHeader, RtpPacket } from 'werift-rtp';
|
|
4
4
|
|
|
5
|
-
import { RequestMessage, type InboundMessage } from '../sip-message';
|
|
5
|
+
import { RequestMessage, type InboundMessage, ResponseMessage } from '../sip-message';
|
|
6
6
|
import type Softphone from '../softphone';
|
|
7
|
-
import { branch, randomInt } from '../utils';
|
|
7
|
+
import { branch, extractAddress, randomInt } from '../utils';
|
|
8
8
|
import DTMF from '../dtmf';
|
|
9
9
|
|
|
10
10
|
abstract class CallSession extends EventEmitter {
|
|
@@ -33,6 +33,30 @@ abstract class CallSession extends EventEmitter {
|
|
|
33
33
|
this.socket.send(data, this.remotePort, this.remoteIP);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
public async transfer(target: string) {
|
|
37
|
+
const requestMessage = new RequestMessage(`REFER sip:${extractAddress(this.remotePeer)} SIP/2.0`, {
|
|
38
|
+
'Call-Id': this.callId,
|
|
39
|
+
From: this.localPeer,
|
|
40
|
+
To: this.remotePeer,
|
|
41
|
+
Via: `SIP/2.0/TCP ${this.softphone.fakeDomain};branch=${branch()}`,
|
|
42
|
+
'Refer-To': `sip:${target}@sip.ringcentral.com`,
|
|
43
|
+
'Referred-By': `<${extractAddress(this.localPeer)}>`,
|
|
44
|
+
});
|
|
45
|
+
this.softphone.send(requestMessage);
|
|
46
|
+
// reply to those NOTIFY messages
|
|
47
|
+
const notifyHandler = (inboundMessage: InboundMessage) => {
|
|
48
|
+
if (!inboundMessage.subject.startsWith('NOTIFY ')) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const responseMessage = new ResponseMessage(inboundMessage, 200);
|
|
52
|
+
this.softphone.send(responseMessage);
|
|
53
|
+
if (inboundMessage.body.endsWith('SIP/2.0 200 OK')) {
|
|
54
|
+
this.softphone.off('message', notifyHandler);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
this.softphone.on('message', notifyHandler);
|
|
58
|
+
}
|
|
59
|
+
|
|
36
60
|
public async hangup() {
|
|
37
61
|
const requestMessage = new RequestMessage(`BYE sip:${this.softphone.sipInfo.domain} SIP/2.0`, {
|
|
38
62
|
'Call-Id': this.callId,
|
|
@@ -72,11 +96,16 @@ abstract class CallSession extends EventEmitter {
|
|
|
72
96
|
|
|
73
97
|
// buffer is the content of a audio file, it is supposed to be PCMU/8000 encoded.
|
|
74
98
|
// The audio should be playable by command: ffplay -autoexit -f mulaw -ar 8000 test.raw
|
|
75
|
-
public
|
|
99
|
+
public streamAudio(input: Buffer) {
|
|
76
100
|
let buffer = input;
|
|
77
101
|
let sequenceNumber = randomInt();
|
|
78
102
|
let timestamp = randomInt();
|
|
79
103
|
const ssrc = randomInt();
|
|
104
|
+
const streamer = {
|
|
105
|
+
stop() {
|
|
106
|
+
buffer = Buffer.alloc(0);
|
|
107
|
+
},
|
|
108
|
+
};
|
|
80
109
|
const sendPacket = () => {
|
|
81
110
|
if (buffer.length >= 160) {
|
|
82
111
|
const temp = buffer.subarray(0, 160);
|
|
@@ -107,10 +136,11 @@ abstract class CallSession extends EventEmitter {
|
|
|
107
136
|
this.send(rtpPacket.serialize());
|
|
108
137
|
sequenceNumber += 1;
|
|
109
138
|
timestamp += 160; // inbound audio use this time interval, in my opinion, it should be 20
|
|
139
|
+
setTimeout(() => sendPacket(), 20);
|
|
110
140
|
}
|
|
111
|
-
setTimeout(() => sendPacket(), 20);
|
|
112
141
|
};
|
|
113
142
|
sendPacket();
|
|
143
|
+
return streamer;
|
|
114
144
|
}
|
|
115
145
|
|
|
116
146
|
protected async startLocalServices() {
|
package/src/softphone.ts
CHANGED
|
@@ -40,11 +40,13 @@ class Softphone extends EventEmitter {
|
|
|
40
40
|
if (!cache.endsWith('\r\n')) {
|
|
41
41
|
return; // haven't received a complete message yet
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
// received two empty body messages
|
|
44
|
+
const tempMessages = cache.split('\r\nContent-Length: 0\r\n\r\n').filter((message) => message.trim() !== '');
|
|
44
45
|
cache = '';
|
|
45
|
-
for (let i =
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
for (let i = 0; i < tempMessages.length; i++) {
|
|
47
|
+
if (!tempMessages[i].includes('Content-Length: ')) {
|
|
48
|
+
tempMessages[i] = tempMessages[i] + '\r\nContent-Length: 0';
|
|
49
|
+
}
|
|
48
50
|
}
|
|
49
51
|
for (const message of tempMessages) {
|
|
50
52
|
this.emit('message', InboundMessage.fromString(message));
|