ringcentral-softphone 0.7.0 → 0.8.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.
Files changed (52) hide show
  1. package/README.md +13 -37
  2. package/demos/inbound-call.ts +52 -0
  3. package/demos/outbound-call.ts +58 -0
  4. package/dist/demos/inbound-call.d.ts +1 -0
  5. package/dist/demos/inbound-call.js +57 -0
  6. package/dist/demos/inbound-call.js.map +1 -0
  7. package/dist/demos/outbound-call.d.ts +1 -0
  8. package/dist/demos/outbound-call.js +60 -0
  9. package/dist/demos/outbound-call.js.map +1 -0
  10. package/dist/src/call-session/inbound.d.ts +8 -0
  11. package/dist/src/call-session/inbound.js +48 -0
  12. package/dist/src/call-session/inbound.js.map +1 -0
  13. package/dist/src/call-session/index.d.ts +26 -0
  14. package/dist/src/call-session/index.js +156 -0
  15. package/dist/src/call-session/index.js.map +1 -0
  16. package/dist/src/call-session/outbound.d.ts +9 -0
  17. package/dist/src/call-session/outbound.js +52 -0
  18. package/dist/src/call-session/outbound.js.map +1 -0
  19. package/dist/src/dtmf.d.ts +8 -0
  20. package/dist/src/dtmf.js +25 -0
  21. package/dist/src/dtmf.js.map +1 -0
  22. package/dist/src/sip-message/inbound/index.d.ts +5 -0
  23. package/dist/src/sip-message/inbound/index.js +23 -0
  24. package/dist/src/sip-message/inbound/index.js.map +1 -0
  25. package/dist/src/sip-message/index.d.ts +5 -0
  26. package/dist/src/sip-message/index.js +17 -0
  27. package/dist/src/sip-message/index.js.map +1 -0
  28. package/dist/src/sip-message/outbound/index.d.ts +5 -0
  29. package/dist/src/sip-message/outbound/index.js +15 -0
  30. package/dist/src/sip-message/outbound/index.js.map +1 -0
  31. package/dist/src/sip-message/outbound/request.d.ts +7 -0
  32. package/dist/src/sip-message/outbound/request.js +29 -0
  33. package/dist/src/sip-message/outbound/request.js.map +1 -0
  34. package/dist/src/sip-message/outbound/response.d.ts +6 -0
  35. package/dist/src/sip-message/outbound/response.js +22 -0
  36. package/dist/src/sip-message/outbound/response.js.map +1 -0
  37. package/dist/src/sip-message/response-codes.d.ts +4 -0
  38. package/dist/src/sip-message/response-codes.js +84 -0
  39. package/dist/src/sip-message/response-codes.js.map +1 -0
  40. package/dist/src/sip-message/sip-message.d.ts +10 -0
  41. package/dist/src/sip-message/sip-message.js +26 -0
  42. package/dist/src/sip-message/sip-message.js.map +1 -0
  43. package/dist/src/softphone.d.ts +26 -0
  44. package/dist/src/softphone.js +178 -0
  45. package/dist/src/softphone.js.map +1 -0
  46. package/dist/src/utils.d.ts +6 -0
  47. package/dist/src/utils.js +37 -0
  48. package/dist/src/utils.js.map +1 -0
  49. package/package.json +3 -2
  50. package/src/call-session/index.ts +45 -0
  51. package/src/softphone.ts +4 -1
  52. package/src/index.ts +0 -97
package/README.md CHANGED
@@ -35,56 +35,31 @@ const softphone = new Softphone({
35
35
  password: process.env.SIP_INFO_PASSWORD,
36
36
  authorizationId: process.env.SIP_INFO_AUTHORIZATION_ID,
37
37
  });
38
- softphone.enableDebugMode(); // optional, print all SIP messages
39
- const main = async () => {
40
- await softphone.register();
41
- // inbound call
42
- softphone.on('invite', async (inviteMessage) => {
43
- // answer the call
44
- const callSession = await softphone.answer(inviteMessage);
45
- // receive audio
46
- const writeStream = fs.createWriteStream(`${callSession.callId}.raw`, { flags: 'a' });
47
- callSession.on('audioPacket', (rtpPacket: RtpPacket) => {
48
- writeStream.write(rtpPacket.payload);
49
- });
50
- // either you or the peer hang up
51
- callSession.on('disposed', () => {
52
- writeStream.close();
53
- });
54
- // receive DTMF
55
- callSession.on('dtmf', (digit) => {
56
- console.log('dtmf', digit);
57
- });
58
- });
59
- };
60
- main();
61
38
  ```
62
39
 
63
- For a complete example, see [src/index.ts](src/index.ts)
40
+ For complete examples, see [demos/](demos/)
64
41
 
65
42
 
66
43
  ## Supported features
67
44
 
68
45
  - inbound call
69
46
  - outbound call
70
- - inbund DTMF
47
+ - inbound DTMF
71
48
  - outbound DTMF
72
49
  - reject inbound call
73
50
  - cancel outbound call
74
51
  - hang up ongoing call
75
- - receive remote autio stream
52
+ - receive remote audio stream
53
+ - outbound call caller ID
76
54
 
77
55
 
78
- ## How to test
79
-
80
- Make a phone call to you device's number.
81
-
82
- There will be audio stream coming in. And you can also get the DTMF digits the caller pressed.
56
+ ## Notes
83
57
 
58
+ ### Audio formats
84
59
 
85
- ## Notes
60
+ The codec is "PCMU/8000", bit rate 8, which mean 8 bits per sample, sample rate 8000, which means 8000 samples per second.
86
61
 
87
- ### How to play saved audio file
62
+ You may play saved audio by the following commands:
88
63
 
89
64
  ```
90
65
  ffplay -autoexit -f mulaw -ar 8000 test.raw
@@ -100,13 +75,14 @@ play -b 8 -r 8000 -e mu-law test.raw
100
75
  ## Todo
101
76
 
102
77
  - Try other payload types, such as OPUS
103
- - support callerId
78
+ - tried OPUS/16000, but the received packets are quite small and cannot be played
104
79
  - do not hard code `domain` and `outboundProxy`
105
- - send audio to remote peer
80
+ - I tried `sip10.ringcentral.com:5096` as `outboundProxy`, it requires TLS instead of TCP
81
+ - I made TLS work, however for inbound call there is not INVITE message coming in, for outbound call "488 Not Acceptable Here"
106
82
  - check the code of PJSIP and refactor the code.
107
- - Let user check the call info, such as who is calling, who is being called, etc.
83
+ - Let developer check the call info, such as who is calling, who is being called, etc.
108
84
 
109
85
 
110
86
  ## Dev Notes
111
87
 
112
- - We don't need to explicitly tell remote server our local RTP port vis SIP SDP message. We will have to send a RTP message to the remote server first, so the remote server knows our IP and port. So the port number in SDP message could be fake.
88
+ - We don't need to explicitly tell remote server our local RTP port via SIP SDP message. We will have to send a RTP message to the remote server first, so the remote server knows our IP and port. So the port number in SDP message could be fake.
@@ -0,0 +1,52 @@
1
+ import fs from 'fs';
2
+ import type { RtpPacket } from 'werift-rtp';
3
+
4
+ import Softphone from '../src/softphone';
5
+ // import waitFor from 'wait-for-async';
6
+
7
+ const softphone = new Softphone({
8
+ username: process.env.SIP_INFO_USERNAME,
9
+ password: process.env.SIP_INFO_PASSWORD,
10
+ authorizationId: process.env.SIP_INFO_AUTHORIZATION_ID,
11
+ });
12
+ softphone.enableDebugMode(); // print all SIP messages
13
+
14
+ const main = async () => {
15
+ await softphone.register();
16
+ // detect inbound call
17
+ softphone.on('invite', async (inviteMessage) => {
18
+ // decline the call
19
+ // await waitFor({ interval: 1000 });
20
+ // await softphone.decline(inviteMessage);
21
+
22
+ // answer the call
23
+ const callSession = await softphone.answer(inviteMessage);
24
+
25
+ // receive audio
26
+ const writeStream = fs.createWriteStream(`${callSession.callId}.raw`, { flags: 'a' });
27
+ callSession.on('audioPacket', (rtpPacket: RtpPacket) => {
28
+ writeStream.write(rtpPacket.payload);
29
+ });
30
+
31
+ // either you or the peer hang up
32
+ callSession.once('disposed', () => {
33
+ writeStream.close();
34
+ });
35
+
36
+ // receive DTMF
37
+ callSession.on('dtmf', (digit) => {
38
+ console.log('dtmf', digit);
39
+ });
40
+
41
+ // // send DTMF
42
+ // await waitFor({ interval: 2000 });
43
+ // callSession.sendDTMF('1');
44
+ // await waitFor({ interval: 2000 });
45
+ // callSession.sendDTMF('#');
46
+
47
+ // // hang up the call
48
+ // await waitFor({ interval: 5000 });
49
+ // callSession.hangup();
50
+ });
51
+ };
52
+ main();
@@ -0,0 +1,58 @@
1
+ import fs from 'fs';
2
+ import type { RtpPacket } from 'werift-rtp';
3
+ import waitFor from 'wait-for-async';
4
+
5
+ import Softphone from '../src/softphone';
6
+
7
+ const softphone = new Softphone({
8
+ username: process.env.SIP_INFO_USERNAME,
9
+ password: process.env.SIP_INFO_PASSWORD,
10
+ authorizationId: process.env.SIP_INFO_AUTHORIZATION_ID,
11
+ });
12
+ softphone.enableDebugMode(); // print all SIP messages
13
+
14
+ const main = async () => {
15
+ await softphone.register();
16
+ await waitFor({ interval: 1000 });
17
+ // callee format sample: 16506668888, country code is required, otherwise behavior is undefined
18
+ const callSession = await softphone.call(
19
+ parseInt(process.env.CALLEE_FOR_TESTING!, 10),
20
+ // parseInt(process.env.RINGCENTRAL_CALLER_ID!, 10), // Optionally, you can specify callerId as the second parameter
21
+ );
22
+
23
+ // callee answers the call
24
+ callSession.once('answered', () => {
25
+ // receive audio
26
+ const writeStream = fs.createWriteStream(`${callSession.callId}.raw`, { flags: 'a' });
27
+ callSession.on('audioPacket', (rtpPacket: RtpPacket) => {
28
+ writeStream.write(rtpPacket.payload);
29
+ });
30
+ // either you or the peer hang up
31
+ callSession.once('disposed', () => {
32
+ writeStream.close();
33
+ });
34
+
35
+ // send audio
36
+ callSession.streamAudio(fs.readFileSync('demos/test.raw'));
37
+
38
+ // receive DTMF
39
+ callSession.on('dtmf', (digit) => {
40
+ console.log('dtmf', digit);
41
+ });
42
+
43
+ // // send DTMF
44
+ // await waitFor({ interval: 2000 });
45
+ // callSession.sendDTMF('1');
46
+ // await waitFor({ interval: 2000 });
47
+ // callSession.sendDTMF('#');
48
+
49
+ // // hang up the call
50
+ // await waitFor({ interval: 5000 });
51
+ // callSession.hangup();
52
+ });
53
+
54
+ // // cancel the call (before the peer answers)
55
+ // await waitFor({ interval: 8000 });
56
+ // callSession.cancel();
57
+ };
58
+ main();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const softphone_1 = __importDefault(require("../src/softphone"));
17
+ // import waitFor from 'wait-for-async';
18
+ const softphone = new softphone_1.default({
19
+ username: process.env.SIP_INFO_USERNAME,
20
+ password: process.env.SIP_INFO_PASSWORD,
21
+ authorizationId: process.env.SIP_INFO_AUTHORIZATION_ID,
22
+ });
23
+ softphone.enableDebugMode(); // print all SIP messages
24
+ const main = () => __awaiter(void 0, void 0, void 0, function* () {
25
+ yield softphone.register();
26
+ // detect inbound call
27
+ softphone.on('invite', (inviteMessage) => __awaiter(void 0, void 0, void 0, function* () {
28
+ // decline the call
29
+ // await waitFor({ interval: 1000 });
30
+ // await softphone.decline(inviteMessage);
31
+ // answer the call
32
+ const callSession = yield softphone.answer(inviteMessage);
33
+ // receive audio
34
+ const writeStream = fs_1.default.createWriteStream(`${callSession.callId}.raw`, { flags: 'a' });
35
+ callSession.on('audioPacket', (rtpPacket) => {
36
+ writeStream.write(rtpPacket.payload);
37
+ });
38
+ // either you or the peer hang up
39
+ callSession.once('disposed', () => {
40
+ writeStream.close();
41
+ });
42
+ // receive DTMF
43
+ callSession.on('dtmf', (digit) => {
44
+ console.log('dtmf', digit);
45
+ });
46
+ // // send DTMF
47
+ // await waitFor({ interval: 2000 });
48
+ // callSession.sendDTMF('1');
49
+ // await waitFor({ interval: 2000 });
50
+ // callSession.sendDTMF('#');
51
+ // // hang up the call
52
+ // await waitFor({ interval: 5000 });
53
+ // callSession.hangup();
54
+ }));
55
+ });
56
+ main();
57
+ //# sourceMappingURL=inbound-call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-call.js","sourceRoot":"","sources":["../../demos/inbound-call.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,4CAAoB;AAGpB,iEAAyC;AACzC,wCAAwC;AAExC,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,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;IAC1B,CAAC,CAAA,CAAC,CAAC;AACL,CAAC,CAAA,CAAC;AACF,IAAI,EAAE,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const wait_for_async_1 = __importDefault(require("wait-for-async"));
17
+ const softphone_1 = __importDefault(require("../src/softphone"));
18
+ const softphone = new softphone_1.default({
19
+ username: process.env.SIP_INFO_USERNAME,
20
+ password: process.env.SIP_INFO_PASSWORD,
21
+ authorizationId: process.env.SIP_INFO_AUTHORIZATION_ID,
22
+ });
23
+ softphone.enableDebugMode(); // print all SIP messages
24
+ const main = () => __awaiter(void 0, void 0, void 0, function* () {
25
+ yield softphone.register();
26
+ yield (0, wait_for_async_1.default)({ interval: 1000 });
27
+ // callee format sample: 16506668888, country code is required, otherwise behavior is undefined
28
+ const callSession = yield softphone.call(parseInt(process.env.CALLEE_FOR_TESTING, 10));
29
+ // callee answers the call
30
+ callSession.once('answered', () => {
31
+ // receive audio
32
+ const writeStream = fs_1.default.createWriteStream(`${callSession.callId}.raw`, { flags: 'a' });
33
+ callSession.on('audioPacket', (rtpPacket) => {
34
+ writeStream.write(rtpPacket.payload);
35
+ });
36
+ // either you or the peer hang up
37
+ callSession.once('disposed', () => {
38
+ writeStream.close();
39
+ });
40
+ // send audio
41
+ callSession.streamAudio(fs_1.default.readFileSync('demos/test.raw'));
42
+ // receive DTMF
43
+ callSession.on('dtmf', (digit) => {
44
+ console.log('dtmf', digit);
45
+ });
46
+ // // send DTMF
47
+ // await waitFor({ interval: 2000 });
48
+ // callSession.sendDTMF('1');
49
+ // await waitFor({ interval: 2000 });
50
+ // callSession.sendDTMF('#');
51
+ // // hang up the call
52
+ // await waitFor({ interval: 5000 });
53
+ // callSession.hangup();
54
+ });
55
+ // // cancel the call (before the peer answers)
56
+ // await waitFor({ interval: 8000 });
57
+ // callSession.cancel();
58
+ });
59
+ main();
60
+ //# sourceMappingURL=outbound-call.js.map
@@ -0,0 +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,GAAG,EAAE;QAChC,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,aAAa;QACb,WAAW,CAAC,WAAW,CAAC,YAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAE3D,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;IAC1B,CAAC,CAAC,CAAC;IAEH,+CAA+C;IAC/C,qCAAqC;IACrC,wBAAwB;AAC1B,CAAC,CAAA,CAAC;AACF,IAAI,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type InboundMessage } from '../sip-message';
2
+ import type Softphone from '../softphone';
3
+ import CallSession from '.';
4
+ declare class InboundCallSession extends CallSession {
5
+ constructor(softphone: Softphone, inviteMessage: InboundMessage);
6
+ answer(): Promise<void>;
7
+ }
8
+ export default InboundCallSession;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const sip_message_1 = require("../sip-message");
16
+ const utils_1 = require("../utils");
17
+ const _1 = __importDefault(require("."));
18
+ class InboundCallSession extends _1.default {
19
+ constructor(softphone, inviteMessage) {
20
+ super(softphone, inviteMessage);
21
+ this.localPeer = inviteMessage.headers.To;
22
+ this.remotePeer = inviteMessage.headers.From;
23
+ }
24
+ answer() {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ const answerSDP = `
27
+ v=0
28
+ o=- ${(0, utils_1.randomInt)()} 0 IN IP4 127.0.0.1
29
+ s=rc-softphone-ts
30
+ c=IN IP4 127.0.0.1
31
+ t=0 0
32
+ m=audio ${(0, utils_1.randomInt)()} RTP/AVP 0 101
33
+ a=rtpmap:0 PCMU/8000
34
+ a=rtpmap:101 telephone-event/8000
35
+ a=fmtp:101 0-15
36
+ a=sendrecv
37
+ a=ssrc:${(0, utils_1.randomInt)()} cname:${(0, utils_1.uuid)()}
38
+ `.trim();
39
+ const newMessage = new sip_message_1.ResponseMessage(this.sipMessage, 200, {
40
+ 'Content-Type': 'application/sdp',
41
+ }, answerSDP);
42
+ this.softphone.send(newMessage);
43
+ this.startLocalServices();
44
+ });
45
+ }
46
+ }
47
+ exports.default = InboundCallSession;
48
+ //# sourceMappingURL=inbound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../../src/call-session/inbound.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,gDAAsE;AACtE,oCAA2C;AAE3C,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;;;;;SAKZ,IAAA,iBAAS,GAAE,UAAU,IAAA,YAAI,GAAE;CACnC,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"}
@@ -0,0 +1,26 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
4
+ import EventEmitter from 'events';
5
+ import dgram from 'dgram';
6
+ import { type InboundMessage } from '../sip-message';
7
+ import type Softphone from '../softphone';
8
+ declare abstract class CallSession extends EventEmitter {
9
+ softphone: Softphone;
10
+ sipMessage: InboundMessage;
11
+ socket: dgram.Socket;
12
+ localPeer: string;
13
+ remotePeer: string;
14
+ remoteIP: string;
15
+ remotePort: number;
16
+ disposed: boolean;
17
+ constructor(softphone: Softphone, sipMessage: InboundMessage);
18
+ get callId(): string;
19
+ send(data: string | Buffer): void;
20
+ hangup(): Promise<void>;
21
+ sendDTMF(char: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '*' | '#'): Promise<void>;
22
+ streamAudio(input: Buffer): Promise<void>;
23
+ protected startLocalServices(): Promise<void>;
24
+ private dispose;
25
+ }
26
+ export default CallSession;
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const events_1 = __importDefault(require("events"));
16
+ const dgram_1 = __importDefault(require("dgram"));
17
+ const werift_rtp_1 = require("werift-rtp");
18
+ const sip_message_1 = require("../sip-message");
19
+ const utils_1 = require("../utils");
20
+ const dtmf_1 = __importDefault(require("../dtmf"));
21
+ class CallSession extends events_1.default {
22
+ constructor(softphone, sipMessage) {
23
+ super();
24
+ this.disposed = false;
25
+ this.softphone = softphone;
26
+ this.sipMessage = sipMessage;
27
+ this.remoteIP = this.sipMessage.body.match(/c=IN IP4 ([\d.]+)/)[1];
28
+ this.remotePort = parseInt(this.sipMessage.body.match(/m=audio (\d+) /)[1], 10);
29
+ }
30
+ get callId() {
31
+ return this.sipMessage.headers['Call-Id'];
32
+ }
33
+ send(data) {
34
+ this.socket.send(data, this.remotePort, this.remoteIP);
35
+ }
36
+ hangup() {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ const requestMessage = new sip_message_1.RequestMessage(`BYE sip:${this.softphone.sipInfo.domain} 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.uuid)()}`,
43
+ });
44
+ this.softphone.send(requestMessage);
45
+ });
46
+ }
47
+ sendDTMF(char) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ const timestamp = Math.floor(Date.now() / 1000);
50
+ let sequenceNumber = timestamp % 65536;
51
+ const rtpHeader = new werift_rtp_1.RtpHeader({
52
+ version: 2,
53
+ padding: false,
54
+ paddingSize: 0,
55
+ extension: false,
56
+ marker: false,
57
+ payloadOffset: 12,
58
+ payloadType: 101,
59
+ sequenceNumber,
60
+ timestamp,
61
+ ssrc: (0, utils_1.randomInt)(),
62
+ csrcLength: 0,
63
+ csrc: [],
64
+ extensionProfile: 48862,
65
+ extensionLength: undefined,
66
+ extensions: [],
67
+ });
68
+ for (const payload of dtmf_1.default.charToPayloads(char)) {
69
+ rtpHeader.sequenceNumber = sequenceNumber++;
70
+ const rtpPacket = new werift_rtp_1.RtpPacket(rtpHeader, payload);
71
+ this.send(rtpPacket.serialize());
72
+ }
73
+ });
74
+ }
75
+ // buffer is the content of a audio file, it is supposed to be PCMU/8000 encoded.
76
+ // The audio should be playable by command: ffplay -autoexit -f mulaw -ar 8000 test.raw
77
+ streamAudio(input) {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ let buffer = input;
80
+ let sequenceNumber = (0, utils_1.randomInt)();
81
+ let timestamp = (0, utils_1.randomInt)();
82
+ const ssrc = (0, utils_1.randomInt)();
83
+ const sendPacket = () => {
84
+ if (buffer.length >= 160) {
85
+ const temp = buffer.subarray(0, 160);
86
+ buffer = buffer.subarray(160);
87
+ const rtpPacket = new werift_rtp_1.RtpPacket(new werift_rtp_1.RtpHeader({
88
+ version: 2,
89
+ padding: false,
90
+ paddingSize: 0,
91
+ extension: false,
92
+ marker: false,
93
+ payloadOffset: 12,
94
+ payloadType: 0,
95
+ sequenceNumber,
96
+ timestamp,
97
+ ssrc,
98
+ csrcLength: 0,
99
+ csrc: [],
100
+ extensionProfile: 48862,
101
+ extensionLength: undefined,
102
+ extensions: [],
103
+ }), temp);
104
+ if (this.disposed) {
105
+ return;
106
+ }
107
+ this.send(rtpPacket.serialize());
108
+ sequenceNumber += 1;
109
+ timestamp += 160; // inbound audio use this time interval, in my opinion, it should be 20
110
+ }
111
+ setTimeout(() => sendPacket(), 20);
112
+ };
113
+ sendPacket();
114
+ });
115
+ }
116
+ startLocalServices() {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ this.socket = dgram_1.default.createSocket('udp4');
119
+ this.socket.on('message', (message) => {
120
+ const rtpPacket = werift_rtp_1.RtpPacket.deSerialize(message);
121
+ this.emit('rtpPacket', rtpPacket);
122
+ if (rtpPacket.header.payloadType === 101) {
123
+ this.emit('dtmfPacket', rtpPacket);
124
+ const char = dtmf_1.default.payloadToChar(rtpPacket.payload);
125
+ if (char) {
126
+ this.emit('dtmf', char);
127
+ }
128
+ }
129
+ else {
130
+ this.emit('audioPacket', rtpPacket);
131
+ }
132
+ });
133
+ this.socket.bind();
134
+ // send a message to remote server so that it knows where to reply
135
+ this.send('hello');
136
+ const byeHandler = (inboundMessage) => {
137
+ if (inboundMessage.headers['Call-Id'] !== this.callId) {
138
+ return;
139
+ }
140
+ if (inboundMessage.headers.CSeq.endsWith(' BYE')) {
141
+ this.softphone.off('message', byeHandler);
142
+ this.dispose();
143
+ }
144
+ };
145
+ this.softphone.on('message', byeHandler);
146
+ });
147
+ }
148
+ dispose() {
149
+ this.disposed = true;
150
+ this.emit('disposed');
151
+ this.socket.removeAllListeners();
152
+ this.socket.close();
153
+ }
154
+ }
155
+ exports.default = CallSession;
156
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/call-session/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type InboundMessage } from '../sip-message';
2
+ import type Softphone from '../softphone';
3
+ import CallSession from '.';
4
+ declare class OutboundCallSession extends CallSession {
5
+ constructor(softphone: Softphone, answerMessage: InboundMessage);
6
+ init(): Promise<void>;
7
+ cancel(): Promise<void>;
8
+ }
9
+ export default OutboundCallSession;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const sip_message_1 = require("../sip-message");
16
+ const _1 = __importDefault(require("."));
17
+ const utils_1 = require("../utils");
18
+ class OutboundCallSession extends _1.default {
19
+ constructor(softphone, answerMessage) {
20
+ super(softphone, answerMessage);
21
+ this.localPeer = answerMessage.headers.From;
22
+ this.remotePeer = answerMessage.headers.To;
23
+ this.init();
24
+ }
25
+ init() {
26
+ return __awaiter(this, void 0, void 0, function* () {
27
+ // wait for user to answer the call
28
+ const answerHandler = (message) => {
29
+ if (message.headers.CSeq === this.sipMessage.headers.CSeq) {
30
+ this.softphone.off('message', answerHandler);
31
+ this.emit('answered');
32
+ }
33
+ };
34
+ this.softphone.on('message', answerHandler);
35
+ this.once('answered', () => __awaiter(this, void 0, void 0, function* () { return this.startLocalServices(); }));
36
+ });
37
+ }
38
+ cancel() {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ const requestMessage = new sip_message_1.RequestMessage(`CANCEL ${(0, utils_1.extractAddress)(this.remotePeer)} SIP/2.0`, {
41
+ 'Call-Id': this.callId,
42
+ From: this.localPeer,
43
+ To: (0, utils_1.withoutTag)(this.remotePeer),
44
+ Via: this.sipMessage.headers.Via,
45
+ CSeq: this.sipMessage.headers.CSeq.replace(' INVITE', ' CANCEL'),
46
+ });
47
+ this.softphone.send(requestMessage);
48
+ });
49
+ }
50
+ }
51
+ exports.default = OutboundCallSession;
52
+ //# sourceMappingURL=outbound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound.js","sourceRoot":"","sources":["../../../src/call-session/outbound.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,gDAAqE;AAErE,yCAA4B;AAC5B,oCAAsD;AAEtD,MAAM,mBAAoB,SAAQ,UAAW;IAC3C,YAAmB,SAAoB,EAAE,aAA6B;QACpE,KAAK,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5C,IAAI,CAAC,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAEY,IAAI;;YACf,mCAAmC;YACnC,MAAM,aAAa,GAAG,CAAC,OAAuB,EAAE,EAAE;gBAChD,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;oBAC1D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;oBAC7C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC,CAAC;YACF,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;YAE5C,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAS,EAAE,gDAAC,OAAA,IAAI,CAAC,kBAAkB,EAAE,CAAA,GAAA,CAAC,CAAC;QAC/D,CAAC;KAAA;IAEY,MAAM;;YACjB,MAAM,cAAc,GAAG,IAAI,4BAAc,CAAC,UAAU,IAAA,sBAAc,EAAC,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE;gBAC7F,SAAS,EAAE,IAAI,CAAC,MAAM;gBACtB,IAAI,EAAE,IAAI,CAAC,SAAS;gBACpB,EAAE,EAAE,IAAA,kBAAU,EAAC,IAAI,CAAC,UAAU,CAAC;gBAC/B,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG;gBAChC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;aACjE,CAAC,CAAC;YACH,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACtC,CAAC;KAAA;CACF;AAED,kBAAe,mBAAmB,CAAC"}