ringcentral-softphone 1.3.6 → 1.3.7

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 (73) hide show
  1. package/dist/call-session/inbound.mjs +2 -0
  2. package/dist/call-session/inbound.mjs.map +1 -0
  3. package/dist/call-session/index.mjs +2 -0
  4. package/dist/call-session/index.mjs.map +1 -0
  5. package/dist/call-session/outbound.mjs +2 -0
  6. package/dist/call-session/outbound.mjs.map +1 -0
  7. package/dist/call-session/streamer.mjs +2 -0
  8. package/dist/call-session/streamer.mjs.map +1 -0
  9. package/dist/codec-Bh7v8J-S.d.mts +2 -1
  10. package/dist/codec-Bh7v8J-S.d.mts.map +1 -0
  11. package/dist/codec-C-VrtVkq.d.cts +2 -1
  12. package/dist/codec-C-VrtVkq.d.cts.map +1 -0
  13. package/dist/codec.mjs +2 -0
  14. package/dist/codec.mjs.map +1 -0
  15. package/dist/dtmf-B13Fz2VR.d.mts +2 -1
  16. package/dist/dtmf-B13Fz2VR.d.mts.map +1 -0
  17. package/dist/dtmf-DcQ-5vSG.d.cts +2 -1
  18. package/dist/dtmf-DcQ-5vSG.d.cts.map +1 -0
  19. package/dist/dtmf.mjs +2 -0
  20. package/dist/dtmf.mjs.map +1 -0
  21. package/dist/inbound--wGoGqLS.d.mts +2 -1
  22. package/dist/inbound--wGoGqLS.d.mts.map +1 -0
  23. package/dist/inbound-DquvTSj1.d.cts +2 -1
  24. package/dist/inbound-DquvTSj1.d.cts.map +1 -0
  25. package/dist/index--UjWgLK-.d.mts +2 -1
  26. package/dist/index--UjWgLK-.d.mts.map +1 -0
  27. package/dist/index-BhN2W8AV.d.mts +2 -1
  28. package/dist/index-BhN2W8AV.d.mts.map +1 -0
  29. package/dist/index-Cf2Cev52.d.cts +2 -1
  30. package/dist/index-Cf2Cev52.d.cts.map +1 -0
  31. package/dist/index-XMDop59x.d.cts +2 -1
  32. package/dist/index-XMDop59x.d.cts.map +1 -0
  33. package/dist/index.mjs +2 -0
  34. package/dist/index.mjs.map +1 -0
  35. package/dist/request-B_auLSJn.d.cts +2 -1
  36. package/dist/request-B_auLSJn.d.cts.map +1 -0
  37. package/dist/request-pBe7_mYv.d.mts +2 -1
  38. package/dist/request-pBe7_mYv.d.mts.map +1 -0
  39. package/dist/response-LRRpY8lX.d.mts +2 -1
  40. package/dist/response-LRRpY8lX.d.mts.map +1 -0
  41. package/dist/response-ReKvb5x9.d.cts +2 -1
  42. package/dist/response-ReKvb5x9.d.cts.map +1 -0
  43. package/dist/sip-message/inbound/index.mjs +2 -0
  44. package/dist/sip-message/inbound/index.mjs.map +1 -0
  45. package/dist/sip-message/outbound/index.mjs +2 -0
  46. package/dist/sip-message/outbound/index.mjs.map +1 -0
  47. package/dist/sip-message/outbound/request.mjs +2 -0
  48. package/dist/sip-message/outbound/request.mjs.map +1 -0
  49. package/dist/sip-message/outbound/response.mjs +2 -0
  50. package/dist/sip-message/outbound/response.mjs.map +1 -0
  51. package/dist/sip-message/response-codes.d.cts +2 -1
  52. package/dist/sip-message/response-codes.d.cts.map +1 -0
  53. package/dist/sip-message/response-codes.d.mts +2 -1
  54. package/dist/sip-message/response-codes.d.mts.map +1 -0
  55. package/dist/sip-message/response-codes.mjs +2 -0
  56. package/dist/sip-message/response-codes.mjs.map +1 -0
  57. package/dist/sip-message/sip-message.mjs +2 -0
  58. package/dist/sip-message/sip-message.mjs.map +1 -0
  59. package/dist/sip-message-B2D5MPBI.d.cts +2 -1
  60. package/dist/sip-message-B2D5MPBI.d.cts.map +1 -0
  61. package/dist/sip-message-PaPho4qU.d.mts +2 -1
  62. package/dist/sip-message-PaPho4qU.d.mts.map +1 -0
  63. package/dist/types-DOQ9wmX6.d.mts +2 -1
  64. package/dist/types-DOQ9wmX6.d.mts.map +1 -0
  65. package/dist/types-DZxCsbZE.d.cts +2 -1
  66. package/dist/types-DZxCsbZE.d.cts.map +1 -0
  67. package/dist/utils.d.cts +2 -1
  68. package/dist/utils.d.cts.map +1 -0
  69. package/dist/utils.d.mts +2 -1
  70. package/dist/utils.d.mts.map +1 -0
  71. package/dist/utils.mjs +2 -0
  72. package/dist/utils.mjs.map +1 -0
  73. package/package.json +1 -1
@@ -49,3 +49,5 @@ a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:${localKey}
49
49
  };
50
50
  //#endregion
51
51
  export { InboundCallSession as default };
52
+
53
+ //# sourceMappingURL=inbound.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound.mjs","names":[],"sources":["../../src/call-session/inbound.ts"],"sourcesContent":["import type Softphone from \"../index.js\";\nimport { type InboundMessage, OutboundMessage } from \"../sip-message/index.js\";\nimport { localKey, randomInt } from \"../utils.js\";\nimport CallSession from \"./index.js\";\n\nclass InboundCallSession extends CallSession {\n public constructor(softphone: Softphone, inviteMessage: InboundMessage) {\n super(softphone, inviteMessage);\n this.localPeer = inviteMessage.headers.To;\n this.remotePeer = inviteMessage.headers.From;\n // inbound call from call queue, invite message may not have body\n if (inviteMessage.body.length > 0) {\n this.remoteKey = inviteMessage.body.match(\n /AES_CM_128_HMAC_SHA1_80 inline:([\\w+/]+)/,\n )![1];\n }\n }\n\n public async answer() {\n const answerSDP = `\nv=0\no=- ${Date.now()} 0 IN IP4 ${this.softphone.client.localAddress}\ns=rc-softphone-ts\nc=IN IP4 ${this.softphone.client.localAddress}\nt=0 0\nm=audio ${randomInt()} RTP/SAVP ${this.softphone.codec.id} 101\na=rtpmap:${this.softphone.codec.id} ${this.softphone.codec.name}\na=rtpmap:101 telephone-event/8000\na=fmtp:101 0-15\na=sendrecv\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:${localKey}\n`.trim();\n this.sdp = answerSDP;\n const newMessage = new OutboundMessage(\n \"SIP/2.0 200 OK\",\n {\n Via: this.sipMessage.headers.Via,\n \"Call-ID\": this.sipMessage.getHeader(\"Call-ID\"),\n From: this.sipMessage.headers.From,\n To: this.sipMessage.headers.To,\n CSeq: this.sipMessage.headers.CSeq,\n Contact: `<sip:${this.softphone.sipInfo.username}@${this.softphone.client.localAddress}:${this.softphone.client.localPort};transport=TLS;ob>`,\n Allow:\n \"PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS\",\n Supported: \"replaces, 100rel, timer, norefersub\",\n \"Session-Expires\": \"14400;refresher=uac\",\n Require: \"timer\",\n \"Content-Type\": \"application/sdp\",\n },\n answerSDP,\n );\n const ackMessage = await this.softphone.send(newMessage, true);\n\n // for inbound call from call queue, ack message may HAVE body (while invite message has no body)\n if (ackMessage.body.length > 0) {\n this.remoteIP = ackMessage.body.match(/c=IN IP4 ([\\d.]+)/)![1];\n this.remotePort = parseInt(\n ackMessage.body.match(/m=audio (\\d+) /)![1],\n 10,\n );\n this.remoteKey = ackMessage.body.match(\n /AES_CM_128_HMAC_SHA1_80 inline:([\\w+/]+)/,\n )![1];\n }\n\n this.startLocalServices();\n }\n}\n\nexport default InboundCallSession;\n"],"mappings":";;;;;AAKA,IAAM,qBAAN,cAAiC,YAAY;CAC3C,YAAmB,WAAsB,eAA+B;AACtE,QAAM,WAAW,cAAc;AAC/B,OAAK,YAAY,cAAc,QAAQ;AACvC,OAAK,aAAa,cAAc,QAAQ;AAExC,MAAI,cAAc,KAAK,SAAS,EAC9B,MAAK,YAAY,cAAc,KAAK,MAClC,2CACD,CAAE;;CAIP,MAAa,SAAS;EACpB,MAAM,YAAY;;MAEhB,KAAK,KAAK,CAAC,YAAY,KAAK,UAAU,OAAO,aAAa;;WAErD,KAAK,UAAU,OAAO,aAAa;;UAEpC,WAAW,CAAC,YAAY,KAAK,UAAU,MAAM,GAAG;WAC/C,KAAK,UAAU,MAAM,GAAG,GAAG,KAAK,UAAU,MAAM,KAAK;;;;4CAIpB,SAAS;EACnD,MAAM;AACJ,OAAK,MAAM;EACX,MAAM,aAAa,IAAI,gBACrB,kBACA;GACE,KAAK,KAAK,WAAW,QAAQ;GAC7B,WAAW,KAAK,WAAW,UAAU,UAAU;GAC/C,MAAM,KAAK,WAAW,QAAQ;GAC9B,IAAI,KAAK,WAAW,QAAQ;GAC5B,MAAM,KAAK,WAAW,QAAQ;GAC9B,SAAS,QAAQ,KAAK,UAAU,QAAQ,SAAS,GAAG,KAAK,UAAU,OAAO,aAAa,GAAG,KAAK,UAAU,OAAO,UAAU;GAC1H,OACE;GACF,WAAW;GACX,mBAAmB;GACnB,SAAS;GACT,gBAAgB;GACjB,EACD,UACD;EACD,MAAM,aAAa,MAAM,KAAK,UAAU,KAAK,YAAY,KAAK;AAG9D,MAAI,WAAW,KAAK,SAAS,GAAG;AAC9B,QAAK,WAAW,WAAW,KAAK,MAAM,oBAAoB,CAAE;AAC5D,QAAK,aAAa,SAChB,WAAW,KAAK,MAAM,iBAAiB,CAAE,IACzC,GACD;AACD,QAAK,YAAY,WAAW,KAAK,MAC/B,2CACD,CAAE;;AAGL,OAAK,oBAAoB"}
@@ -207,3 +207,5 @@ var CallSession = class extends EventEmitter {
207
207
  };
208
208
  //#endregion
209
209
  export { CallSession as default };
210
+
211
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/call-session/index.ts"],"sourcesContent":["import { Buffer } from \"node:buffer\";\nimport dgram from \"node:dgram\";\nimport EventEmitter from \"node:events\";\nimport waitFor from \"wait-for-async\";\nimport { RtpHeader, RtpPacket, SrtpSession } from \"werift-rtp\";\nimport DTMF from \"../dtmf.js\";\nimport type Softphone from \"../index.js\";\nimport {\n type InboundMessage,\n RequestMessage,\n ResponseMessage,\n} from \"../sip-message/index.js\";\nimport { branch, extractAddress, localKey, randomInt } from \"../utils.js\";\nimport Streamer from \"./streamer.js\";\n\ntype DtmfChar = (typeof DTMF.phoneChars)[number];\n\nconst isDtmfChar = (value: string): value is DtmfChar =>\n (DTMF.phoneChars as readonly string[]).includes(value);\n\nabstract class CallSession extends EventEmitter {\n public softphone: Softphone;\n public sipMessage: InboundMessage;\n public socket!: dgram.Socket;\n public localPeer!: string;\n public remotePeer!: string;\n public remoteIP!: string;\n public remotePort!: number;\n public disposed = false;\n public srtpSession!: SrtpSession;\n public encoder: { encode: (pcm: Buffer) => Buffer };\n public decoder: { decode: (audio: Buffer) => Buffer };\n public sdp!: string;\n\n // for audio streaming\n public ssrc = randomInt();\n public sequenceNumber = randomInt();\n public timestamp = randomInt();\n\n public constructor(softphone: Softphone, sipMessage: InboundMessage) {\n super();\n this.softphone = softphone;\n this.encoder = softphone.codec.createEncoder();\n this.decoder = softphone.codec.createDecoder();\n this.sipMessage = sipMessage;\n // inbound call from call queue, invite message may not have body\n if (this.sipMessage.body.length > 0) {\n this.remoteIP = this.sipMessage.body.match(/c=IN IP4 ([\\d.]+)/)![1];\n this.remotePort = parseInt(\n this.sipMessage.body.match(/m=audio (\\d+) /)![1],\n 10,\n );\n }\n }\n\n public set remoteKey(key: string) {\n const localKeyBuffer = Buffer.from(localKey, \"base64\");\n const remoteKeyBuffer = Buffer.from(key, \"base64\");\n this.srtpSession = new SrtpSession({\n profile: 0x0001,\n keys: {\n localMasterKey: localKeyBuffer.subarray(0, 16),\n localMasterSalt: localKeyBuffer.subarray(16, 30),\n remoteMasterKey: remoteKeyBuffer.subarray(0, 16),\n remoteMasterSalt: remoteKeyBuffer.subarray(16, 30),\n },\n });\n }\n\n public get callId() {\n return this.sipMessage.getHeader(\"Call-ID\");\n }\n\n public send(data: string | Buffer) {\n this.socket.send(data, this.remotePort, this.remoteIP);\n }\n\n public async hangup() {\n const requestMessage = new RequestMessage(\n `BYE sip:${this.softphone.sipInfo.domain} SIP/2.0`,\n {\n \"Call-ID\": this.callId,\n From: this.localPeer,\n To: this.remotePeer,\n Via: `SIP/2.0/TLS ${this.softphone.fakeDomain};branch=${branch()}`,\n },\n );\n await this.softphone.send(requestMessage);\n }\n\n public sendDTMF(char: DtmfChar) {\n const payloads = DTMF.charToPayloads(char);\n const timestamp = this.timestamp;\n let first = true;\n for (const payload of payloads) {\n const rtpHeader = new RtpHeader({\n version: 2,\n padding: false,\n paddingSize: 0,\n extension: false,\n marker: first,\n payloadOffset: 12,\n payloadType: 101,\n sequenceNumber: this.sequenceNumber,\n timestamp,\n ssrc: this.ssrc,\n csrcLength: 0,\n csrc: [],\n extensionProfile: 48862,\n extensionLength: undefined,\n extensions: [],\n });\n const rtpPacket = new RtpPacket(rtpHeader, payload);\n this.send(this.srtpSession.encrypt(rtpPacket.payload, rtpPacket.header));\n this.sequenceNumber = (this.sequenceNumber + 1) % 65536;\n first = false;\n }\n this.timestamp += 800;\n }\n\n public async sendDTMFs(s: string, delay = 500) {\n for (const c of s) {\n if (!isDtmfChar(c)) {\n throw new Error(`invalid phone char: ${c}`);\n }\n this.sendDTMF(c);\n await waitFor({ interval: delay });\n }\n }\n\n // buffer is the content of a audio file, it is supposed to be uncompressed PCM data\n // The audio should be playable by command: play -t raw -b 16 -r 16000 -e signed-integer test.wav\n public streamAudio(input: Buffer) {\n const streamer = new Streamer(this, input);\n streamer.start();\n return streamer;\n }\n\n // send a single rtp packet\n public sendPacket(rtpPacket: RtpPacket) {\n if (this.disposed) {\n return;\n }\n this.send(this.srtpSession.encrypt(rtpPacket.payload, rtpPacket.header));\n }\n\n protected startLocalServices() {\n this.socket = dgram.createSocket(\"udp4\");\n this.socket.on(\"message\", (message) => {\n const rtpPacket = RtpPacket.deSerialize(\n this.srtpSession.decrypt(message),\n );\n this.emit(\"rtpPacket\", rtpPacket);\n if (rtpPacket.header.payloadType === 101) {\n this.emit(\"dtmfPacket\", rtpPacket);\n const char = DTMF.payloadToChar(rtpPacket.payload);\n if (char) {\n this.emit(\"dtmf\", char);\n }\n } else if (rtpPacket.header.payloadType === this.softphone.codec.id) {\n if (\n rtpPacket.payload.length === 4 &&\n rtpPacket.payload[0] >= 0x00 &&\n rtpPacket.payload[0] < 0x0c &&\n rtpPacket.payload[1] === 0x8a &&\n rtpPacket.payload[2] === 0x03 &&\n rtpPacket.payload[3] === 0xc0\n ) {\n // special DTMF packet in audio format\n // first byte 0x00 to 0x0c means DTMF 0 to 9, *, #\n // we ignore it since DTMF is handled by `if (rtpPacket.header.payloadType === 101) {`\n return; // ignore it\n }\n try {\n rtpPacket.payload = this.decoder.decode(rtpPacket.payload);\n this.emit(\"audioPacket\", rtpPacket);\n } catch {\n console.error(\"Audio packet decode failed\", rtpPacket);\n }\n }\n });\n\n // as I tested, we can use a random port here and it still works\n // but it seems that in SDP we need to tell remote our local IP Address, not 127.0.0.1\n this.socket.bind(); // random port\n // send a message to remote server so that it knows where to reply\n this.send(\"hello\");\n\n const byeHandler = (inboundMessage: InboundMessage) => {\n if (inboundMessage.getHeader(\"Call-ID\") !== this.callId) {\n return;\n }\n if (inboundMessage.headers.CSeq.endsWith(\" BYE\")) {\n this.softphone.off(\"message\", byeHandler);\n this.dispose();\n }\n };\n this.softphone.on(\"message\", byeHandler);\n }\n\n protected dispose() {\n this.disposed = true;\n this.emit(\"disposed\");\n this.removeAllListeners();\n this.socket?.removeAllListeners();\n this.socket?.close();\n }\n\n public async transfer(transferTo: string) {\n const requestMessage = new RequestMessage(\n `REFER sip:${this.softphone.sipInfo.username}@${this.softphone.sipInfo.outboundProxy};transport=tls SIP/2.0`,\n {\n Via: `SIP/2.0/TLS ${this.softphone.client.localAddress}:${this.softphone.client.localPort};rport;branch=${branch()};alias`,\n \"Max-Forwards\": 70,\n From: this.localPeer,\n To: this.remotePeer,\n Contact: `<sip:${this.softphone.sipInfo.username}@${this.softphone.client.localAddress}:${this.softphone.client.localPort};transport=TLS;ob>`,\n \"Call-ID\": this.callId,\n Event: \"refer\",\n Expires: 600,\n Supported: \"replaces, 100rel, timer, norefersub\",\n Accept: \"message/sipfrag;version=2.0\",\n \"Allow-Events\": \"presence, message-summary, refer\",\n \"Refer-To\": `sip:${transferTo}@${this.softphone.sipInfo.domain}`,\n \"Referred-By\": `<sip:${this.softphone.sipInfo.username}@${this.softphone.sipInfo.domain}>`,\n },\n );\n await this.softphone.send(requestMessage);\n\n return new Promise<void>((resolve) => {\n const notifyHandler = (inboundMessage: InboundMessage) => {\n if (!inboundMessage.subject.startsWith(\"NOTIFY \")) {\n return;\n }\n const responseMessage = new ResponseMessage(inboundMessage, 200);\n this.softphone.send(responseMessage);\n if (inboundMessage.body.trim() === \"SIP/2.0 200 OK\") {\n this.softphone.off(\"message\", notifyHandler);\n resolve();\n }\n };\n this.softphone.on(\"message\", notifyHandler);\n });\n }\n\n public async toggleReceive(toReceive: boolean) {\n let newSDP = this.sdp;\n if (!toReceive) {\n newSDP = newSDP.replace(/a=sendrecv/, \"a=sendonly\");\n }\n const requestMessage = new RequestMessage(\n `INVITE ${extractAddress(this.remotePeer)} SIP/2.0`,\n {\n \"Call-Id\": this.callId,\n From: this.localPeer,\n To: this.remotePeer,\n Via: `SIP/2.0/TLS ${this.softphone.client.localAddress}:${this.softphone.client.localPort};rport;branch=${branch()};alias`,\n \"Content-Type\": \"application/sdp\",\n Contact: ` <sip:${this.softphone.sipInfo.username}@${this.softphone.client.localAddress}:${this.softphone.client.localPort};transport=TLS;ob>`,\n },\n newSDP,\n );\n const replyMessage = await this.softphone.send(requestMessage, true);\n const ackMessage = new RequestMessage(\n `ACK ${extractAddress(this.remotePeer)} SIP/2.0`,\n {\n \"Call-Id\": this.callId,\n From: this.localPeer,\n To: this.remotePeer,\n Via: replyMessage.headers.Via,\n CSeq: replyMessage.headers.CSeq.replace(\" INVITE\", \" ACK\"),\n },\n );\n await this.softphone.send(ackMessage);\n }\n\n public async hold() {\n return this.toggleReceive(false);\n }\n\n public async unhold() {\n return this.toggleReceive(true);\n }\n}\n\nexport default CallSession;\n"],"mappings":"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"}
@@ -55,3 +55,5 @@ var OutboundCallSession = class extends CallSession {
55
55
  };
56
56
  //#endregion
57
57
  export { OutboundCallSession as default };
58
+
59
+ //# sourceMappingURL=outbound.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound.mjs","names":[],"sources":["../../src/call-session/outbound.ts"],"sourcesContent":["import type Softphone from \"../index.js\";\nimport { type InboundMessage, RequestMessage } from \"../sip-message/index.js\";\nimport { extractAddress, withoutTag } from \"../utils.js\";\nimport CallSession from \"./index.js\";\n\nclass OutboundCallSession extends CallSession {\n public constructor(softphone: Softphone, answerMessage: InboundMessage) {\n super(softphone, answerMessage);\n this.localPeer = answerMessage.headers.From;\n this.remotePeer = answerMessage.headers.To;\n this.remoteKey = answerMessage.body.match(\n /AES_CM_128_HMAC_SHA1_80 inline:([\\w+/]+)/,\n )![1];\n this.init();\n }\n\n public init() {\n // wait for user to answer the call\n const answerHandler = (message: InboundMessage) => {\n if (message.headers.CSeq !== this.sipMessage.headers.CSeq) {\n return;\n }\n if (message.subject.startsWith(\"SIP/2.0 486\")) {\n this.softphone.off(\"message\", answerHandler);\n this.emit(\"busy\");\n this.dispose();\n return;\n }\n if (message.subject.startsWith(\"SIP/2.0 200\")) {\n this.softphone.off(\"message\", answerHandler);\n this.emit(\"answered\");\n\n const ackMessage = new RequestMessage(\n `ACK ${extractAddress(this.remotePeer)} SIP/2.0`,\n {\n \"Call-ID\": this.callId,\n From: this.localPeer,\n To: this.remotePeer,\n Via: this.sipMessage.headers.Via,\n CSeq: this.sipMessage.headers.CSeq.replace(\" INVITE\", \" ACK\"),\n },\n );\n this.softphone.send(ackMessage);\n }\n };\n this.softphone.on(\"message\", answerHandler);\n this.once(\"answered\", () => this.startLocalServices());\n }\n\n public async cancel() {\n const requestMessage = new RequestMessage(\n `CANCEL ${extractAddress(this.remotePeer)} SIP/2.0`,\n {\n \"Call-ID\": this.callId,\n From: this.localPeer,\n To: withoutTag(this.remotePeer),\n Via: this.sipMessage.headers.Via,\n CSeq: this.sipMessage.headers.CSeq.replace(\" INVITE\", \" CANCEL\"),\n },\n );\n await this.softphone.send(requestMessage);\n }\n\n public get sessionId() {\n const header = this.sipMessage.headers[\"p-rc-api-ids\"];\n const match = header.match(/party-id=([^;]+);session-id=([^;]+)/)!;\n return match[2];\n }\n public get partyId() {\n const header = this.sipMessage.headers[\"p-rc-api-ids\"];\n const match = header.match(/party-id=([^;]+);session-id=([^;]+)/)!;\n return match[1];\n }\n}\n\nexport default OutboundCallSession;\n"],"mappings":";;;;;AAKA,IAAM,sBAAN,cAAkC,YAAY;CAC5C,YAAmB,WAAsB,eAA+B;AACtE,QAAM,WAAW,cAAc;AAC/B,OAAK,YAAY,cAAc,QAAQ;AACvC,OAAK,aAAa,cAAc,QAAQ;AACxC,OAAK,YAAY,cAAc,KAAK,MAClC,2CACD,CAAE;AACH,OAAK,MAAM;;CAGb,OAAc;EAEZ,MAAM,iBAAiB,YAA4B;AACjD,OAAI,QAAQ,QAAQ,SAAS,KAAK,WAAW,QAAQ,KACnD;AAEF,OAAI,QAAQ,QAAQ,WAAW,cAAc,EAAE;AAC7C,SAAK,UAAU,IAAI,WAAW,cAAc;AAC5C,SAAK,KAAK,OAAO;AACjB,SAAK,SAAS;AACd;;AAEF,OAAI,QAAQ,QAAQ,WAAW,cAAc,EAAE;AAC7C,SAAK,UAAU,IAAI,WAAW,cAAc;AAC5C,SAAK,KAAK,WAAW;IAErB,MAAM,aAAa,IAAI,eACrB,OAAO,eAAe,KAAK,WAAW,CAAC,WACvC;KACE,WAAW,KAAK;KAChB,MAAM,KAAK;KACX,IAAI,KAAK;KACT,KAAK,KAAK,WAAW,QAAQ;KAC7B,MAAM,KAAK,WAAW,QAAQ,KAAK,QAAQ,WAAW,OAAO;KAC9D,CACF;AACD,SAAK,UAAU,KAAK,WAAW;;;AAGnC,OAAK,UAAU,GAAG,WAAW,cAAc;AAC3C,OAAK,KAAK,kBAAkB,KAAK,oBAAoB,CAAC;;CAGxD,MAAa,SAAS;EACpB,MAAM,iBAAiB,IAAI,eACzB,UAAU,eAAe,KAAK,WAAW,CAAC,WAC1C;GACE,WAAW,KAAK;GAChB,MAAM,KAAK;GACX,IAAI,WAAW,KAAK,WAAW;GAC/B,KAAK,KAAK,WAAW,QAAQ;GAC7B,MAAM,KAAK,WAAW,QAAQ,KAAK,QAAQ,WAAW,UAAU;GACjE,CACF;AACD,QAAM,KAAK,UAAU,KAAK,eAAe;;CAG3C,IAAW,YAAY;AAGrB,SAFe,KAAK,WAAW,QAAQ,gBAClB,MAAM,sCACf,CAAC;;CAEf,IAAW,UAAU;AAGnB,SAFe,KAAK,WAAW,QAAQ,gBAClB,MAAM,sCACf,CAAC"}
@@ -63,3 +63,5 @@ var Streamer = class extends EventEmitter {
63
63
  };
64
64
  //#endregion
65
65
  export { Streamer as default };
66
+
67
+ //# sourceMappingURL=streamer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamer.mjs","names":[],"sources":["../../src/call-session/streamer.ts"],"sourcesContent":["import { Buffer } from \"node:buffer\";\nimport EventEmitter from \"node:events\";\n\nimport { RtpHeader, RtpPacket } from \"werift-rtp\";\n\nimport type CallSession from \"./index.js\";\n\nclass Streamer extends EventEmitter {\n public paused = false;\n private callSession: CallSession;\n private buffer: Buffer;\n private originalBuffer: Buffer;\n\n public constructor(callSession: CallSession, buffer: Buffer) {\n super();\n this.callSession = callSession;\n this.buffer = buffer;\n this.originalBuffer = buffer;\n }\n\n public start() {\n this.buffer = this.originalBuffer;\n this.paused = false;\n this.sendPacket();\n }\n\n public stop() {\n this.buffer = Buffer.alloc(0);\n }\n\n public pause() {\n this.paused = true;\n }\n\n public resume() {\n this.paused = false;\n this.sendPacket();\n }\n\n public get finished() {\n return (\n this.callSession.disposed ||\n this.buffer.length < this.callSession.softphone.codec.packetSize\n );\n }\n\n private sendPacket() {\n if (!this.paused && !this.finished) {\n const temp = this.callSession.encoder.encode(\n this.buffer.subarray(0, this.callSession.softphone.codec.packetSize),\n );\n const rtpPacket = new RtpPacket(\n new RtpHeader({\n version: 2,\n padding: false,\n paddingSize: 0,\n extension: false,\n marker: false,\n payloadOffset: 12,\n payloadType: this.callSession.softphone.codec.id,\n sequenceNumber: this.callSession.sequenceNumber,\n timestamp: this.callSession.timestamp,\n ssrc: this.callSession.ssrc,\n csrcLength: 0,\n csrc: [],\n extensionProfile: 48862,\n extensionLength: undefined,\n extensions: [],\n }),\n temp,\n );\n this.callSession.send(\n this.callSession.srtpSession.encrypt(\n rtpPacket.payload,\n rtpPacket.header,\n ),\n );\n this.callSession.sequenceNumber += 1;\n if (this.callSession.sequenceNumber > 65535) {\n this.callSession.sequenceNumber = 0;\n }\n this.callSession.timestamp +=\n this.callSession.softphone.codec.timestampInterval;\n this.buffer = this.buffer.subarray(\n this.callSession.softphone.codec.packetSize,\n );\n if (this.finished) {\n this.emit(\"finished\");\n } else {\n setTimeout(() => this.sendPacket(), 20);\n }\n }\n }\n}\n\nexport default Streamer;\n"],"mappings":";;;;AAOA,IAAM,WAAN,cAAuB,aAAa;CAClC,SAAgB;CAChB;CACA;CACA;CAEA,YAAmB,aAA0B,QAAgB;AAC3D,SAAO;AACP,OAAK,cAAc;AACnB,OAAK,SAAS;AACd,OAAK,iBAAiB;;CAGxB,QAAe;AACb,OAAK,SAAS,KAAK;AACnB,OAAK,SAAS;AACd,OAAK,YAAY;;CAGnB,OAAc;AACZ,OAAK,SAAS,OAAO,MAAM,EAAE;;CAG/B,QAAe;AACb,OAAK,SAAS;;CAGhB,SAAgB;AACd,OAAK,SAAS;AACd,OAAK,YAAY;;CAGnB,IAAW,WAAW;AACpB,SACE,KAAK,YAAY,YACjB,KAAK,OAAO,SAAS,KAAK,YAAY,UAAU,MAAM;;CAI1D,aAAqB;AACnB,MAAI,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU;GAClC,MAAM,OAAO,KAAK,YAAY,QAAQ,OACpC,KAAK,OAAO,SAAS,GAAG,KAAK,YAAY,UAAU,MAAM,WAAW,CACrE;GACD,MAAM,YAAY,IAAI,UACpB,IAAI,UAAU;IACZ,SAAS;IACT,SAAS;IACT,aAAa;IACb,WAAW;IACX,QAAQ;IACR,eAAe;IACf,aAAa,KAAK,YAAY,UAAU,MAAM;IAC9C,gBAAgB,KAAK,YAAY;IACjC,WAAW,KAAK,YAAY;IAC5B,MAAM,KAAK,YAAY;IACvB,YAAY;IACZ,MAAM,EAAE;IACR,kBAAkB;IAClB,iBAAiB,KAAA;IACjB,YAAY,EAAE;IACf,CAAC,EACF,KACD;AACD,QAAK,YAAY,KACf,KAAK,YAAY,YAAY,QAC3B,UAAU,SACV,UAAU,OACX,CACF;AACD,QAAK,YAAY,kBAAkB;AACnC,OAAI,KAAK,YAAY,iBAAiB,MACpC,MAAK,YAAY,iBAAiB;AAEpC,QAAK,YAAY,aACf,KAAK,YAAY,UAAU,MAAM;AACnC,QAAK,SAAS,KAAK,OAAO,SACxB,KAAK,YAAY,UAAU,MAAM,WAClC;AACD,OAAI,KAAK,SACP,MAAK,KAAK,WAAW;OAErB,kBAAiB,KAAK,YAAY,EAAE,GAAG"}
@@ -15,4 +15,5 @@ declare class Codec {
15
15
  constructor(name: "OPUS/16000" | "OPUS/48000/2" | "PCMU/8000");
16
16
  }
17
17
  //#endregion
18
- export { Codec as t };
18
+ export { Codec as t };
19
+ //# sourceMappingURL=codec-Bh7v8J-S.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec-Bh7v8J-S.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":";;;cAGM,KAAA;EACJ,EAAA;EACA,IAAA;EACA,UAAA;EACA,iBAAA;EACA,aAAA;IAAuB,MAAA,GAAS,GAAA,EAAK,MAAA,KAAW,MAAA;EAAA;EAChD,aAAA;IAAuB,MAAA,GAAS,KAAA,EAAO,MAAA,KAAW,MAAA;EAAA;cACtC,IAAA;AAAA"}
@@ -15,4 +15,5 @@ declare class Codec {
15
15
  constructor(name: "OPUS/16000" | "OPUS/48000/2" | "PCMU/8000");
16
16
  }
17
17
  //#endregion
18
- export { Codec as t };
18
+ export { Codec as t };
19
+ //# sourceMappingURL=codec-C-VrtVkq.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec-C-VrtVkq.d.cts","names":[],"sources":["../src/codec.ts"],"mappings":";;;cAGM,KAAA;EACJ,EAAA;EACA,IAAA;EACA,UAAA;EACA,iBAAA;EACA,aAAA;IAAuB,MAAA,GAAS,GAAA,EAAK,MAAA,KAAW,MAAA;EAAA;EAChD,aAAA;IAAuB,MAAA,GAAS,KAAA,EAAO,MAAA,KAAW,MAAA;EAAA;cACtC,IAAA;AAAA"}
package/dist/codec.mjs CHANGED
@@ -66,3 +66,5 @@ var Codec = class {
66
66
  };
67
67
  //#endregion
68
68
  export { Codec as default };
69
+
70
+ //# sourceMappingURL=codec.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.mjs","names":[],"sources":["../src/codec.ts"],"sourcesContent":["import { Buffer } from \"node:buffer\";\nimport { Decoder, Encoder } from \"@evan/opus\";\n\nclass Codec {\n id: number;\n name: \"OPUS/16000\" | \"OPUS/48000/2\" | \"PCMU/8000\";\n packetSize: number;\n timestampInterval: number;\n createEncoder: () => { encode: (pcm: Buffer) => Buffer };\n createDecoder: () => { decode: (audio: Buffer) => Buffer };\n constructor(name: \"OPUS/16000\" | \"OPUS/48000/2\" | \"PCMU/8000\") {\n this.name = name;\n switch (name) {\n case \"OPUS/16000\": {\n this.createEncoder = () => {\n const encoder = new Encoder({ channels: 1, sample_rate: 16000 });\n return { encode: (pcm: Buffer) => Buffer.from(encoder.encode(pcm)) };\n };\n this.createDecoder = () => {\n const decoder = new Decoder({ channels: 1, sample_rate: 16000 });\n return {\n decode: (opus: Buffer) => Buffer.from(decoder.decode(opus)),\n };\n };\n this.id = 109;\n this.packetSize = 640;\n this.timestampInterval = 320;\n break;\n }\n case \"OPUS/48000/2\": {\n this.createEncoder = () => {\n const encoder = new Encoder({ channels: 2, sample_rate: 48000 });\n return { encode: (pcm: Buffer) => Buffer.from(encoder.encode(pcm)) };\n };\n this.createDecoder = () => {\n const decoder = new Decoder({ channels: 2, sample_rate: 48000 });\n return {\n decode: (opus: Buffer) => Buffer.from(decoder.decode(opus)),\n };\n };\n this.id = 111;\n this.packetSize = 3840;\n this.timestampInterval = 960;\n break;\n }\n case \"PCMU/8000\": {\n this.createEncoder = () => {\n return { encode: (pcm: Buffer) => pcm };\n };\n this.createDecoder = () => {\n return { decode: (audio: Buffer) => audio };\n };\n this.id = 0;\n this.packetSize = 160;\n this.timestampInterval = 160;\n break;\n }\n default: {\n throw new Error(`unsupported codec: ${name}`);\n }\n }\n }\n}\n\nexport default Codec;\n"],"mappings":";;;AAGA,IAAM,QAAN,MAAY;CACV;CACA;CACA;CACA;CACA;CACA;CACA,YAAY,MAAmD;AAC7D,OAAK,OAAO;AACZ,UAAQ,MAAR;GACE,KAAK;AACH,SAAK,sBAAsB;KACzB,MAAM,UAAU,IAAI,QAAQ;MAAE,UAAU;MAAG,aAAa;MAAO,CAAC;AAChE,YAAO,EAAE,SAAS,QAAgB,OAAO,KAAK,QAAQ,OAAO,IAAI,CAAC,EAAE;;AAEtE,SAAK,sBAAsB;KACzB,MAAM,UAAU,IAAI,QAAQ;MAAE,UAAU;MAAG,aAAa;MAAO,CAAC;AAChE,YAAO,EACL,SAAS,SAAiB,OAAO,KAAK,QAAQ,OAAO,KAAK,CAAC,EAC5D;;AAEH,SAAK,KAAK;AACV,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB;GAEF,KAAK;AACH,SAAK,sBAAsB;KACzB,MAAM,UAAU,IAAI,QAAQ;MAAE,UAAU;MAAG,aAAa;MAAO,CAAC;AAChE,YAAO,EAAE,SAAS,QAAgB,OAAO,KAAK,QAAQ,OAAO,IAAI,CAAC,EAAE;;AAEtE,SAAK,sBAAsB;KACzB,MAAM,UAAU,IAAI,QAAQ;MAAE,UAAU;MAAG,aAAa;MAAO,CAAC;AAChE,YAAO,EACL,SAAS,SAAiB,OAAO,KAAK,QAAQ,OAAO,KAAK,CAAC,EAC5D;;AAEH,SAAK,KAAK;AACV,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB;GAEF,KAAK;AACH,SAAK,sBAAsB;AACzB,YAAO,EAAE,SAAS,QAAgB,KAAK;;AAEzC,SAAK,sBAAsB;AACzB,YAAO,EAAE,SAAS,UAAkB,OAAO;;AAE7C,SAAK,KAAK;AACV,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB;GAEF,QACE,OAAM,IAAI,MAAM,sBAAsB,OAAO"}
@@ -7,4 +7,5 @@ declare const DTMF: {
7
7
  payloadToChar(payload: Buffer): "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "*" | "#";
8
8
  };
9
9
  //#endregion
10
- export { DTMF as t };
10
+ export { DTMF as t };
11
+ //# sourceMappingURL=dtmf-B13Fz2VR.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dtmf-B13Fz2VR.d.mts","names":[],"sources":["../src/dtmf.ts"],"mappings":";;;cAoBM,IAAA;;gCAEuB,MAAA,CAAA,WAAA;yBAYJ,MAAA;AAAA"}
@@ -7,4 +7,5 @@ declare const DTMF: {
7
7
  payloadToChar(payload: Buffer): "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "*" | "#";
8
8
  };
9
9
  //#endregion
10
- export { DTMF as t };
10
+ export { DTMF as t };
11
+ //# sourceMappingURL=dtmf-DcQ-5vSG.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dtmf-DcQ-5vSG.d.cts","names":[],"sources":["../src/dtmf.ts"],"mappings":";;;cAoBM,IAAA;;gCAEuB,MAAA,CAAA,WAAA;yBAYJ,MAAA;AAAA"}
package/dist/dtmf.mjs CHANGED
@@ -40,3 +40,5 @@ const DTMF = {
40
40
  };
41
41
  //#endregion
42
42
  export { DTMF as default };
43
+
44
+ //# sourceMappingURL=dtmf.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dtmf.mjs","names":[],"sources":["../src/dtmf.ts"],"sourcesContent":["import { Buffer } from \"node:buffer\";\n\nconst phoneChars = [\n \"0\",\n \"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"*\",\n \"#\",\n] as const;\nconst payloads = [\n 0x00060000, 0x000600a0, 0x00060140, 0x00860320, 0x00860320, 0x00860320,\n];\n\nconst DTMF = {\n phoneChars,\n charToPayloads(char: string) {\n const index = phoneChars.indexOf(char[0] as (typeof phoneChars)[number]);\n if (index === -1) {\n throw new Error(\"invalid phone char\");\n }\n return payloads.map((payload) => {\n const temp = payload + index * 0x01000000;\n const buffer = Buffer.alloc(4);\n buffer.writeIntBE(temp, 0, 4);\n return buffer;\n });\n },\n payloadToChar(payload: Buffer) {\n const intBE = payload.readIntBE(0, 4);\n const index = (intBE - 0x00060000) / 0x01000000;\n return phoneChars[index];\n },\n};\n\nexport default DTMF;\n"],"mappings":";;AAEA,MAAM,aAAa;CACjB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,WAAW;CACf;CAAY;CAAY;CAAY;CAAY;CAAY;CAC7D;AAED,MAAM,OAAO;CACX;CACA,eAAe,MAAc;EAC3B,MAAM,QAAQ,WAAW,QAAQ,KAAK,GAAkC;AACxE,MAAI,UAAU,GACZ,OAAM,IAAI,MAAM,qBAAqB;AAEvC,SAAO,SAAS,KAAK,YAAY;GAC/B,MAAM,OAAO,UAAU,QAAQ;GAC/B,MAAM,SAAS,OAAO,MAAM,EAAE;AAC9B,UAAO,WAAW,MAAM,GAAG,EAAE;AAC7B,UAAO;IACP;;CAEJ,cAAc,SAAiB;AAG7B,SAAO,YAFO,QAAQ,UAAU,GAAG,EACf,GAAG,UAAc;;CAGxC"}
@@ -100,4 +100,5 @@ declare class InboundCallSession extends CallSession {
100
100
  answer(): Promise<void>;
101
101
  }
102
102
  //#endregion
103
- export { Streamer as a, CallSession as i, Softphone as n, OutboundCallSession as r, InboundCallSession as t };
103
+ export { Streamer as a, CallSession as i, Softphone as n, OutboundCallSession as r, InboundCallSession as t };
104
+ //# sourceMappingURL=inbound--wGoGqLS.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound--wGoGqLS.d.mts","names":[],"sources":["../src/call-session/streamer.ts","../src/call-session/index.ts","../src/call-session/outbound.ts","../src/index.ts","../src/call-session/inbound.ts"],"mappings":";;;;;;;;;;;;cAOM,QAAA,SAAiB,YAAA;EACd,MAAA;EAAA,QACC,WAAA;EAAA,QACA,MAAA;EAAA,QACA,cAAA;cAEW,WAAA,EAAa,WAAA,EAAa,MAAA,EAAQ,MAAA;EAO9C,KAAA,CAAA;EAMA,IAAA,CAAA;EAIA,KAAA,CAAA;EAIA,MAAA,CAAA;EAAA,IAKI,QAAA,CAAA;EAAA,QAOH,UAAA;AAAA;;;KC/BL,QAAA,WAAmB,IAAA,CAAK,UAAA;AAAA,uBAKd,WAAA,SAAoB,YAAA;EAC1B,SAAA,EAAW,SAAA;EACX,UAAA,EAAY,cAAA;EACZ,MAAA,EAAS,KAAA,CAAM,MAAA;EACf,SAAA;EACA,UAAA;EACA,QAAA;EACA,UAAA;EACA,QAAA;EACA,WAAA,EAAc,WAAA;EACd,OAAA;IAAW,MAAA,GAAS,GAAA,EAAK,MAAA,KAAW,MAAA;EAAA;EACpC,OAAA;IAAW,MAAA,GAAS,KAAA,EAAO,MAAA,KAAW,MAAA;EAAA;EACtC,GAAA;EAGA,IAAA;EACA,cAAA;EACA,SAAA;cAEY,SAAA,EAAW,SAAA,EAAW,UAAA,EAAY,cAAA;EAAA,IAgB1C,SAAA,CAAU,GAAA;EAAA,IAcV,MAAA,CAAA;EAIJ,IAAA,CAAK,IAAA,WAAe,MAAA;EAId,MAAA,CAAA,GAAM,OAAA;EAaZ,QAAA,CAAS,IAAA,EAAM,QAAA;EA8BT,SAAA,CAAU,CAAA,UAAW,KAAA,YAAW,OAAA;EAYtC,WAAA,CAAY,KAAA,EAAO,MAAA,GAAM,QAAA;EAOzB,UAAA,CAAW,SAAA,EAAW,SAAA;EAAA,UAOnB,kBAAA,CAAA;EAAA,UAsDA,OAAA,CAAA;EAQG,QAAA,CAAS,UAAA,WAAkB,OAAA;EAqC3B,aAAA,CAAc,SAAA,YAAkB,OAAA;EA+BhC,IAAA,CAAA,GAAI,OAAA;EAIJ,MAAA,CAAA,GAAM,OAAA;AAAA;;;cCnRf,mBAAA,SAA4B,WAAA;cACb,SAAA,EAAW,SAAA,EAAW,aAAA,EAAe,cAAA;EAUjD,IAAA,CAAA;EAiCM,MAAA,CAAA,GAAM,OAAA;EAAA,IAcR,SAAA,CAAA;EAAA,IAKA,OAAA,CAAA;AAAA;;;cC7CP,SAAA,SAAkB,YAAA;EACf,OAAA,EAAS,gBAAA;EACT,MAAA,EAAQ,SAAA;EACR,KAAA,EAAO,KAAA;EAEP,UAAA;EACA,SAAA;EAAA,QAEC,cAAA;EAAA,QACA,SAAA;cAEW,OAAA,EAAS,gBAAA;EAAA,QA+CpB,UAAA;EAAA,QACA,cAAA;EAEK,QAAA,CAAA,GAAQ,OAAA;EAuEd,eAAA,CAAA;EAWA,MAAA,CAAA;EAOA,IAAA,CACL,OAAA,EAAS,eAAA,EACT,YAAA,UACC,OAAA,CAAQ,cAAA;EACJ,IAAA,CACL,OAAA,EAAS,eAAA,EACT,YAAA,WACC,OAAA;EAyBU,MAAA,CAAO,aAAA,EAAe,cAAA,GAAc,OAAA,CAAA,kBAAA;EAOpC,OAAA,CAAQ,aAAA,EAAe,cAAA,GAAc,OAAA;EAKrC,IAAA,CAAK,MAAA,WAAc,OAAA,CAAA,mBAAA;AAAA;;;cCpN5B,kBAAA,SAA2B,WAAA;cACZ,SAAA,EAAW,SAAA,EAAW,aAAA,EAAe,cAAA;EAY3C,MAAA,CAAA,GAAM,OAAA;AAAA"}
@@ -100,4 +100,5 @@ declare class InboundCallSession extends CallSession {
100
100
  answer(): Promise<void>;
101
101
  }
102
102
  //#endregion
103
- export { Streamer as a, CallSession as i, Softphone as n, OutboundCallSession as r, InboundCallSession as t };
103
+ export { Streamer as a, CallSession as i, Softphone as n, OutboundCallSession as r, InboundCallSession as t };
104
+ //# sourceMappingURL=inbound-DquvTSj1.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-DquvTSj1.d.cts","names":[],"sources":["../src/call-session/streamer.ts","../src/call-session/index.ts","../src/call-session/outbound.ts","../src/index.ts","../src/call-session/inbound.ts"],"mappings":";;;;;;;;;;;;cAOM,QAAA,SAAiB,YAAA;EACd,MAAA;EAAA,QACC,WAAA;EAAA,QACA,MAAA;EAAA,QACA,cAAA;cAEW,WAAA,EAAa,WAAA,EAAa,MAAA,EAAQ,MAAA;EAO9C,KAAA,CAAA;EAMA,IAAA,CAAA;EAIA,KAAA,CAAA;EAIA,MAAA,CAAA;EAAA,IAKI,QAAA,CAAA;EAAA,QAOH,UAAA;AAAA;;;KC/BL,QAAA,WAAmB,IAAA,CAAK,UAAA;AAAA,uBAKd,WAAA,SAAoB,YAAA;EAC1B,SAAA,EAAW,SAAA;EACX,UAAA,EAAY,cAAA;EACZ,MAAA,EAAS,KAAA,CAAM,MAAA;EACf,SAAA;EACA,UAAA;EACA,QAAA;EACA,UAAA;EACA,QAAA;EACA,WAAA,EAAc,WAAA;EACd,OAAA;IAAW,MAAA,GAAS,GAAA,EAAK,MAAA,KAAW,MAAA;EAAA;EACpC,OAAA;IAAW,MAAA,GAAS,KAAA,EAAO,MAAA,KAAW,MAAA;EAAA;EACtC,GAAA;EAGA,IAAA;EACA,cAAA;EACA,SAAA;cAEY,SAAA,EAAW,SAAA,EAAW,UAAA,EAAY,cAAA;EAAA,IAgB1C,SAAA,CAAU,GAAA;EAAA,IAcV,MAAA,CAAA;EAIJ,IAAA,CAAK,IAAA,WAAe,MAAA;EAId,MAAA,CAAA,GAAM,OAAA;EAaZ,QAAA,CAAS,IAAA,EAAM,QAAA;EA8BT,SAAA,CAAU,CAAA,UAAW,KAAA,YAAW,OAAA;EAYtC,WAAA,CAAY,KAAA,EAAO,MAAA,GAAM,QAAA;EAOzB,UAAA,CAAW,SAAA,EAAW,SAAA;EAAA,UAOnB,kBAAA,CAAA;EAAA,UAsDA,OAAA,CAAA;EAQG,QAAA,CAAS,UAAA,WAAkB,OAAA;EAqC3B,aAAA,CAAc,SAAA,YAAkB,OAAA;EA+BhC,IAAA,CAAA,GAAI,OAAA;EAIJ,MAAA,CAAA,GAAM,OAAA;AAAA;;;cCnRf,mBAAA,SAA4B,WAAA;cACb,SAAA,EAAW,SAAA,EAAW,aAAA,EAAe,cAAA;EAUjD,IAAA,CAAA;EAiCM,MAAA,CAAA,GAAM,OAAA;EAAA,IAcR,SAAA,CAAA;EAAA,IAKA,OAAA,CAAA;AAAA;;;cC7CP,SAAA,SAAkB,YAAA;EACf,OAAA,EAAS,gBAAA;EACT,MAAA,EAAQ,SAAA;EACR,KAAA,EAAO,KAAA;EAEP,UAAA;EACA,SAAA;EAAA,QAEC,cAAA;EAAA,QACA,SAAA;cAEW,OAAA,EAAS,gBAAA;EAAA,QA+CpB,UAAA;EAAA,QACA,cAAA;EAEK,QAAA,CAAA,GAAQ,OAAA;EAuEd,eAAA,CAAA;EAWA,MAAA,CAAA;EAOA,IAAA,CACL,OAAA,EAAS,eAAA,EACT,YAAA,UACC,OAAA,CAAQ,cAAA;EACJ,IAAA,CACL,OAAA,EAAS,eAAA,EACT,YAAA,WACC,OAAA;EAyBU,MAAA,CAAO,aAAA,EAAe,cAAA,GAAc,OAAA,CAAA,kBAAA;EAOpC,OAAA,CAAQ,aAAA,EAAe,cAAA,GAAc,OAAA;EAKrC,IAAA,CAAK,MAAA,WAAc,OAAA,CAAA,mBAAA;AAAA;;;cCpN5B,kBAAA,SAA2B,WAAA;cACZ,SAAA,EAAW,SAAA,EAAW,aAAA,EAAe,cAAA;EAY3C,MAAA,CAAA,GAAM,OAAA;AAAA"}
@@ -5,4 +5,5 @@ declare class OutboundMessage extends SipMessage {
5
5
  constructor(subject?: string, headers?: {}, body?: string);
6
6
  }
7
7
  //#endregion
8
- export { OutboundMessage as t };
8
+ export { OutboundMessage as t };
9
+ //# sourceMappingURL=index--UjWgLK-.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index--UjWgLK-.d.mts","names":[],"sources":["../src/sip-message/outbound/index.ts"],"mappings":";;;cAEM,eAAA,SAAwB,UAAA;cACT,OAAA,WAAc,OAAA,OAAc,IAAA;AAAA"}
@@ -5,4 +5,5 @@ declare class InboundMessage extends SipMessage {
5
5
  static fromString(str: string): SipMessage;
6
6
  }
7
7
  //#endregion
8
- export { InboundMessage as t };
8
+ export { InboundMessage as t };
9
+ //# sourceMappingURL=index-BhN2W8AV.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-BhN2W8AV.d.mts","names":[],"sources":["../src/sip-message/inbound/index.ts"],"mappings":";;;cAGM,cAAA,SAAuB,UAAA;EAAA,OACb,UAAA,CAAW,GAAA,WAAW,UAAA;AAAA"}
@@ -5,4 +5,5 @@ declare class InboundMessage extends SipMessage {
5
5
  static fromString(str: string): SipMessage;
6
6
  }
7
7
  //#endregion
8
- export { InboundMessage as t };
8
+ export { InboundMessage as t };
9
+ //# sourceMappingURL=index-Cf2Cev52.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Cf2Cev52.d.cts","names":[],"sources":["../src/sip-message/inbound/index.ts"],"mappings":";;;cAGM,cAAA,SAAuB,UAAA;EAAA,OACb,UAAA,CAAW,GAAA,WAAW,UAAA;AAAA"}
@@ -5,4 +5,5 @@ declare class OutboundMessage extends SipMessage {
5
5
  constructor(subject?: string, headers?: {}, body?: string);
6
6
  }
7
7
  //#endregion
8
- export { OutboundMessage as t };
8
+ export { OutboundMessage as t };
9
+ //# sourceMappingURL=index-XMDop59x.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-XMDop59x.d.cts","names":[],"sources":["../src/sip-message/outbound/index.ts"],"mappings":";;;cAEM,eAAA,SAAwB,UAAA;cACT,OAAA,WAAc,OAAA,OAAc,IAAA;AAAA"}
package/dist/index.mjs CHANGED
@@ -170,3 +170,5 @@ a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:${localKey}
170
170
  };
171
171
  //#endregion
172
172
  export { Softphone as default };
173
+
174
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import EventEmitter from \"node:events\";\nimport tls, { type TLSSocket } from \"node:tls\";\n\nimport waitFor from \"wait-for-async\";\n\nimport InboundCallSession from \"./call-session/inbound.js\";\nimport OutboundCallSession from \"./call-session/outbound.js\";\nimport Codec from \"./codec.js\";\nimport {\n InboundMessage,\n OutboundMessage,\n RequestMessage,\n ResponseMessage,\n} from \"./sip-message/index.js\";\nimport type { SoftPhoneOptions } from \"./types.js\";\nimport {\n branch,\n generateAuthorization,\n localKey,\n randomInt,\n uuid,\n} from \"./utils.js\";\n\nclass Softphone extends EventEmitter {\n public sipInfo: SoftPhoneOptions;\n public client: TLSSocket;\n public codec: Codec;\n\n public fakeDomain = `${uuid()}.invalid`;\n public fakeEmail = `${uuid()}@${this.fakeDomain}`;\n\n private intervalHandle?: NodeJS.Timeout;\n private connected = false;\n\n public constructor(sipInfo: SoftPhoneOptions) {\n super();\n if (sipInfo.codec === undefined) {\n sipInfo.codec = \"OPUS/16000\";\n }\n this.codec = new Codec(sipInfo.codec);\n this.sipInfo = sipInfo;\n if (this.sipInfo.domain === undefined) {\n this.sipInfo.domain = \"sip.ringcentral.com\";\n }\n if (this.sipInfo.outboundProxy === undefined) {\n this.sipInfo.outboundProxy = \"sip10.ringcentral.com:5096\";\n }\n const tokens = this.sipInfo.outboundProxy!.split(\":\");\n this.client = tls.connect(\n {\n host: tokens[0],\n port: parseInt(tokens[1], 10),\n rejectUnauthorized: !this.sipInfo.ignoreTlsCertErrors,\n },\n () => {\n this.connected = true;\n },\n );\n\n let cache = \"\";\n this.client.on(\"data\", (data) => {\n cache += data.toString(\"utf-8\");\n if (!cache.endsWith(\"\\r\\n\")) {\n return; // haven't received a complete message yet\n }\n // received two empty body messages\n const tempMessages = cache\n .split(\"\\r\\nContent-Length: 0\\r\\n\\r\\n\")\n .filter((message) => message.trim() !== \"\");\n cache = \"\";\n for (let i = 0; i < tempMessages.length; i++) {\n if (!tempMessages[i].includes(\"Content-Length: \")) {\n tempMessages[i] = `${tempMessages[i]}\\r\\nContent-Length: 0`;\n }\n }\n for (const message of tempMessages) {\n this.emit(\"message\", InboundMessage.fromString(message));\n }\n });\n }\n\n private instanceId = uuid();\n private registerCallId = uuid();\n\n public async register() {\n if (!this.connected) {\n await waitFor({\n interval: 100,\n times: 100,\n condition: () => this.connected,\n });\n if (!this.connected) {\n throw new Error(\"Failed to register: connect to TLS timeout\");\n }\n }\n const sipRegister = async () => {\n const fromTag = uuid();\n const requestMessage = new RequestMessage(\n `REGISTER sip:${this.sipInfo.domain} SIP/2.0`,\n {\n Via: `SIP/2.0/TLS ${this.client.localAddress}:${this.client.localPort};rport;branch=${branch()};alias`,\n \"Max-Forwards\": \"70\",\n From: `<sip:${this.sipInfo.username}@${this.sipInfo.domain}>;tag=${fromTag}`,\n To: `<sip:${this.sipInfo.username}@${this.sipInfo.domain}>`,\n \"Call-ID\": this.registerCallId,\n Contact: `<sip:${this.sipInfo.username}@${this.client.localAddress}:${this.client.localPort};transport=TLS;ob>;reg-id=1;+sip.instance=\"<urn:uuid:${this.instanceId}>\"`,\n Expires: 3600,\n Allow:\n \"PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS\",\n },\n );\n const inboundMessage = await this.send(requestMessage, true);\n if (inboundMessage.subject.startsWith(\"SIP/2.0 200 \")) {\n // sometimes the server will return 200 OK directly\n return;\n }\n const wwwAuth = inboundMessage.getHeader(\"Www-Authenticate\")!;\n const nonce = wwwAuth.match(/, nonce=\"(.+?)\"/)![1];\n const newMessage = requestMessage.fork();\n newMessage.headers.Authorization = generateAuthorization(\n this.sipInfo,\n nonce,\n \"REGISTER\",\n );\n const message = await this.send(newMessage, true);\n if (!message.subject.startsWith(\"SIP/2.0 200 \")) {\n throw new Error(`Failed to register: ${message.subject}`);\n }\n };\n await sipRegister();\n this.intervalHandle = setInterval(\n () => {\n sipRegister().catch((error) => {\n this.emit(\"registrationError\", error);\n });\n },\n 30 * 1000, // refresh registration every 30 seconds\n );\n this.on(\"message\", (inboundMessage) => {\n if (!inboundMessage.subject.startsWith(\"INVITE sip:\")) {\n return;\n }\n const outboundMessage = new OutboundMessage(\"SIP/2.0 100 Trying\", {\n Via: inboundMessage.headers.Via,\n \"Call-ID\": inboundMessage.getHeader(\"Call-ID\"),\n From: inboundMessage.headers.From,\n To: inboundMessage.headers.To,\n CSeq: inboundMessage.headers.CSeq,\n \"Content-Length\": \"0\",\n });\n this.send(outboundMessage);\n this.emit(\"invite\", inboundMessage);\n });\n }\n\n public enableDebugMode() {\n this.on(\"message\", (message) =>\n console.log(`Receiving...(${new Date()})\\n${message.toString()}`),\n );\n const tlsWrite = this.client.write.bind(this.client);\n this.client.write = (message) => {\n console.log(`Sending...(${new Date()})\\n${message}`);\n return tlsWrite(message);\n };\n }\n\n public revoke() {\n clearInterval(this.intervalHandle);\n this.removeAllListeners();\n this.client.removeAllListeners();\n this.client.destroy();\n }\n\n public send(\n message: OutboundMessage,\n waitForReply?: true,\n ): Promise<InboundMessage>;\n public send(\n message: OutboundMessage,\n waitForReply?: false,\n ): Promise<undefined>;\n public send(message: OutboundMessage, waitForReply = false) {\n this.client.write(message.toString());\n if (!waitForReply) {\n return Promise.resolve(undefined);\n }\n return new Promise<InboundMessage>((resolve) => {\n const messageListerner = (inboundMessage: InboundMessage) => {\n // \"12563 INVITE\" vs \"12563 ACK\"\n if (\n inboundMessage.headers.CSeq.trim().split(/\\s+/)[0] !==\n message.headers.CSeq.trim().split(/\\s+/)[0]\n ) {\n return;\n }\n if (inboundMessage.subject.startsWith(\"SIP/2.0 100 \")) {\n return; // ignore\n }\n this.off(\"message\", messageListerner);\n resolve(inboundMessage);\n };\n this.on(\"message\", messageListerner);\n });\n }\n\n public async answer(inviteMessage: InboundMessage) {\n const inboundCallSession = new InboundCallSession(this, inviteMessage);\n await inboundCallSession.answer();\n return inboundCallSession;\n }\n\n // decline an inbound call\n public async decline(inviteMessage: InboundMessage) {\n const newMessage = new ResponseMessage(inviteMessage, 603);\n await this.send(newMessage);\n }\n\n public async call(callee: string) {\n const offerSDP = `\nv=0\no=- ${Date.now()} 0 IN IP4 ${this.client.localAddress}\ns=rc-softphone-ts\nc=IN IP4 ${this.client.localAddress}\nt=0 0\nm=audio ${randomInt()} RTP/SAVP ${this.codec.id} 101\na=rtpmap:${this.codec.id} ${this.codec.name}\na=rtpmap:101 telephone-event/8000\na=fmtp:101 0-15\na=sendrecv\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:${localKey}\n `.trim();\n const inviteMessage = new RequestMessage(\n `INVITE sip:${callee}@${this.sipInfo.domain} SIP/2.0`,\n {\n Via: `SIP/2.0/TLS ${this.client.localAddress}:${this.client.localPort};rport;branch=${branch()};alias`,\n \"Max-Forwards\": 70,\n From: `<sip:${this.sipInfo.username}@${this.sipInfo.domain}>;tag=${uuid()}`,\n To: `<sip:${callee}@${this.sipInfo.domain}>`,\n Contact: ` <sip:${this.sipInfo.username}@${this.client.localAddress}:${this.client.localPort};transport=TLS;ob>`,\n \"Call-ID\": uuid(),\n Route: `<sip:${this.sipInfo.outboundProxy};transport=tls;lr>`,\n Allow: `PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS`,\n Supported: `replaces, 100rel, timer, norefersub`,\n \"Session-Expires\": 1800,\n \"Min-SE\": 90,\n \"Content-Type\": \"application/sdp\",\n },\n offerSDP,\n );\n const inboundMessage = await this.send(inviteMessage, true);\n const proxyAuthenticate = inboundMessage.getHeader(\"Proxy-Authenticate\")!;\n const nonce = proxyAuthenticate.match(/, nonce=\"(.+?)\"/)![1];\n const newMessage = inviteMessage.fork();\n newMessage.headers[\"Proxy-Authorization\"] = generateAuthorization(\n this.sipInfo,\n nonce,\n \"INVITE\",\n );\n const progressMessage = await this.send(newMessage, true);\n const outboundCallSession = new OutboundCallSession(this, progressMessage);\n outboundCallSession.sdp = offerSDP;\n return outboundCallSession;\n }\n}\n\nexport default Softphone;\n"],"mappings":"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"}
@@ -7,4 +7,5 @@ declare class RequestMessage extends OutboundMessage {
7
7
  fork(): RequestMessage;
8
8
  }
9
9
  //#endregion
10
- export { RequestMessage as t };
10
+ export { RequestMessage as t };
11
+ //# sourceMappingURL=request-B_auLSJn.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-B_auLSJn.d.cts","names":[],"sources":["../src/sip-message/outbound/request.ts"],"mappings":";;;cAKM,cAAA,SAAuB,eAAA;cACR,OAAA,WAAc,OAAA,OAAc,IAAA;EAOxC,OAAA,CAAA;EAIA,IAAA,CAAA,GAAI,cAAA;AAAA"}
@@ -7,4 +7,5 @@ declare class RequestMessage extends OutboundMessage {
7
7
  fork(): RequestMessage;
8
8
  }
9
9
  //#endregion
10
- export { RequestMessage as t };
10
+ export { RequestMessage as t };
11
+ //# sourceMappingURL=request-pBe7_mYv.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-pBe7_mYv.d.mts","names":[],"sources":["../src/sip-message/outbound/request.ts"],"mappings":";;;cAKM,cAAA,SAAuB,eAAA;cACR,OAAA,WAAc,OAAA,OAAc,IAAA;EAOxC,OAAA,CAAA;EAIA,IAAA,CAAA,GAAI,cAAA;AAAA"}
@@ -6,4 +6,5 @@ declare class ResponseMessage extends OutboundMessage {
6
6
  constructor(inboundMessage: InboundMessage, responseCode: number, headers?: {}, body?: string);
7
7
  }
8
8
  //#endregion
9
- export { ResponseMessage as t };
9
+ export { ResponseMessage as t };
10
+ //# sourceMappingURL=response-LRRpY8lX.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-LRRpY8lX.d.mts","names":[],"sources":["../src/sip-message/outbound/response.ts"],"mappings":";;;;cAIM,eAAA,SAAwB,eAAA;cAE1B,cAAA,EAAgB,cAAA,EAChB,YAAA,UACA,OAAA,OACA,IAAA;AAAA"}
@@ -6,4 +6,5 @@ declare class ResponseMessage extends OutboundMessage {
6
6
  constructor(inboundMessage: InboundMessage, responseCode: number, headers?: {}, body?: string);
7
7
  }
8
8
  //#endregion
9
- export { ResponseMessage as t };
9
+ export { ResponseMessage as t };
10
+ //# sourceMappingURL=response-ReKvb5x9.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-ReKvb5x9.d.cts","names":[],"sources":["../src/sip-message/outbound/response.ts"],"mappings":";;;;cAIM,eAAA,SAAwB,eAAA;cAE1B,cAAA,EAAgB,cAAA,EAChB,YAAA,UACA,OAAA,OACA,IAAA;AAAA"}
@@ -15,3 +15,5 @@ var InboundMessage = class extends SipMessage {
15
15
  };
16
16
  //#endregion
17
17
  export { InboundMessage as default };
18
+
19
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/sip-message/inbound/index.ts"],"sourcesContent":["import { uuid } from \"../../utils.js\";\nimport SipMessage from \"../sip-message.js\";\n\nclass InboundMessage extends SipMessage {\n public static fromString(str: string) {\n const sipMessage = new SipMessage();\n const [init, ...body] = str.split(\"\\r\\n\\r\\n\");\n sipMessage.body = body.join(\"\\r\\n\\r\\n\");\n const [subject, ...headers] = init.split(\"\\r\\n\");\n sipMessage.subject = subject;\n sipMessage.headers = Object.fromEntries(\n headers.map((line) => line.split(\": \")),\n );\n if (sipMessage.headers.To && !sipMessage.headers.To.includes(\";tag=\")) {\n sipMessage.headers.To += `;tag=${uuid()}`; // generate local tag\n }\n return sipMessage;\n }\n}\n\nexport default InboundMessage;\n"],"mappings":";;;AAGA,IAAM,iBAAN,cAA6B,WAAW;CACtC,OAAc,WAAW,KAAa;EACpC,MAAM,aAAa,IAAI,YAAY;EACnC,MAAM,CAAC,MAAM,GAAG,QAAQ,IAAI,MAAM,WAAW;AAC7C,aAAW,OAAO,KAAK,KAAK,WAAW;EACvC,MAAM,CAAC,SAAS,GAAG,WAAW,KAAK,MAAM,OAAO;AAChD,aAAW,UAAU;AACrB,aAAW,UAAU,OAAO,YAC1B,QAAQ,KAAK,SAAS,KAAK,MAAM,KAAK,CAAC,CACxC;AACD,MAAI,WAAW,QAAQ,MAAM,CAAC,WAAW,QAAQ,GAAG,SAAS,QAAQ,CACnE,YAAW,QAAQ,MAAM,QAAQ,MAAM;AAEzC,SAAO"}
@@ -9,3 +9,5 @@ var OutboundMessage = class extends SipMessage {
9
9
  };
10
10
  //#endregion
11
11
  export { OutboundMessage as default };
12
+
13
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/sip-message/outbound/index.ts"],"sourcesContent":["import SipMessage from \"../sip-message.js\";\n\nclass OutboundMessage extends SipMessage {\n public constructor(subject = \"\", headers = {}, body = \"\") {\n super(subject, headers, body);\n this.headers[\"Content-Length\"] = this.body.length.toString();\n this.headers[\"User-Agent\"] = \"ringcentral-softphone-ts\";\n }\n}\n\nexport default OutboundMessage;\n"],"mappings":";;AAEA,IAAM,kBAAN,cAA8B,WAAW;CACvC,YAAmB,UAAU,IAAI,UAAU,EAAE,EAAE,OAAO,IAAI;AACxD,QAAM,SAAS,SAAS,KAAK;AAC7B,OAAK,QAAQ,oBAAoB,KAAK,KAAK,OAAO,UAAU;AAC5D,OAAK,QAAQ,gBAAgB"}
@@ -19,3 +19,5 @@ var RequestMessage = class RequestMessage extends OutboundMessage {
19
19
  };
20
20
  //#endregion
21
21
  export { RequestMessage as default };
22
+
23
+ //# sourceMappingURL=request.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.mjs","names":[],"sources":["../../../src/sip-message/outbound/request.ts"],"sourcesContent":["import { branch } from \"../../utils.js\";\nimport OutboundMessage from \"./index.js\";\n\nlet cseq = Math.floor(Math.random() * 10000);\n\nclass RequestMessage extends OutboundMessage {\n public constructor(subject = \"\", headers = {}, body = \"\") {\n super(subject, headers, body);\n if (this.headers.CSeq === undefined) {\n this.newCseq();\n }\n }\n\n public newCseq() {\n this.headers.CSeq = `${++cseq} ${this.subject.split(\" \")[0]}`;\n }\n\n public fork() {\n const newMessage = new RequestMessage(\n this.subject,\n { ...this.headers },\n this.body,\n );\n newMessage.newCseq();\n if (newMessage.headers.Via) {\n newMessage.headers.Via = newMessage.headers.Via.replace(\n /;branch=.+?$/,\n `;branch=${branch()}`,\n );\n }\n return newMessage;\n }\n}\n\nexport default RequestMessage;\n"],"mappings":";;;AAGA,IAAI,OAAO,KAAK,MAAM,KAAK,QAAQ,GAAG,IAAM;AAE5C,IAAM,iBAAN,MAAM,uBAAuB,gBAAgB;CAC3C,YAAmB,UAAU,IAAI,UAAU,EAAE,EAAE,OAAO,IAAI;AACxD,QAAM,SAAS,SAAS,KAAK;AAC7B,MAAI,KAAK,QAAQ,SAAS,KAAA,EACxB,MAAK,SAAS;;CAIlB,UAAiB;AACf,OAAK,QAAQ,OAAO,GAAG,EAAE,KAAK,GAAG,KAAK,QAAQ,MAAM,IAAI,CAAC;;CAG3D,OAAc;EACZ,MAAM,aAAa,IAAI,eACrB,KAAK,SACL,EAAE,GAAG,KAAK,SAAS,EACnB,KAAK,KACN;AACD,aAAW,SAAS;AACpB,MAAI,WAAW,QAAQ,IACrB,YAAW,QAAQ,MAAM,WAAW,QAAQ,IAAI,QAC9C,gBACA,WAAW,QAAQ,GACpB;AAEH,SAAO"}
@@ -24,3 +24,5 @@ var ResponseMessage = class extends OutboundMessage {
24
24
  };
25
25
  //#endregion
26
26
  export { ResponseMessage as default };
27
+
28
+ //# sourceMappingURL=response.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.mjs","names":[],"sources":["../../../src/sip-message/outbound/response.ts"],"sourcesContent":["import type InboundMessage from \"../inbound/index.js\";\nimport responseCodes from \"../response-codes.js\";\nimport OutboundMessage from \"./index.js\";\n\nclass ResponseMessage extends OutboundMessage {\n public constructor(\n inboundMessage: InboundMessage,\n responseCode: number,\n headers = {},\n body = \"\",\n ) {\n super(undefined, { ...headers }, body);\n this.subject = `SIP/2.0 ${responseCode} ${responseCodes[responseCode]}`;\n const requiredKeys = new Set([\"via\", \"from\", \"to\", \"call-id\", \"cseq\"]);\n const allKeys = Object.keys(inboundMessage.headers).reduce(\n (acc, key) => {\n acc[key.toLowerCase()] = key;\n return acc;\n },\n {} as Record<string, string>,\n );\n for (const key of requiredKeys) {\n if (allKeys[key]) {\n const originalKey = allKeys[key];\n this.headers[originalKey] = inboundMessage.headers[originalKey];\n }\n }\n }\n}\n\nexport default ResponseMessage;\n"],"mappings":";;;AAIA,IAAM,kBAAN,cAA8B,gBAAgB;CAC5C,YACE,gBACA,cACA,UAAU,EAAE,EACZ,OAAO,IACP;AACA,QAAM,KAAA,GAAW,EAAE,GAAG,SAAS,EAAE,KAAK;AACtC,OAAK,UAAU,WAAW,aAAa,GAAG,cAAc;EACxD,MAAM,eAAe,IAAI,IAAI;GAAC;GAAO;GAAQ;GAAM;GAAW;GAAO,CAAC;EACtE,MAAM,UAAU,OAAO,KAAK,eAAe,QAAQ,CAAC,QACjD,KAAK,QAAQ;AACZ,OAAI,IAAI,aAAa,IAAI;AACzB,UAAO;KAET,EAAE,CACH;AACD,OAAK,MAAM,OAAO,aAChB,KAAI,QAAQ,MAAM;GAChB,MAAM,cAAc,QAAQ;AAC5B,QAAK,QAAQ,eAAe,eAAe,QAAQ"}
@@ -2,4 +2,5 @@
2
2
  declare const responseCodes: {
3
3
  [key: number]: string;
4
4
  };
5
- export = responseCodes;
5
+ export = responseCodes;
6
+ //# sourceMappingURL=response-codes.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-codes.d.cts","names":[],"sources":["../../src/sip-message/response-codes.ts"],"mappings":";cACM,aAAA;EAAA,CACH,GAAA;AAAA;AAAA"}
@@ -3,4 +3,5 @@ declare const responseCodes: {
3
3
  [key: number]: string;
4
4
  };
5
5
  //#endregion
6
- export { responseCodes as default };
6
+ export { responseCodes as default };
7
+ //# sourceMappingURL=response-codes.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-codes.d.mts","names":[],"sources":["../../src/sip-message/response-codes.ts"],"mappings":";cACM,aAAA;EAAA,CACH,GAAA;AAAA"}
@@ -80,3 +80,5 @@ const responseCodes = {
80
80
  };
81
81
  //#endregion
82
82
  export { responseCodes as default };
83
+
84
+ //# sourceMappingURL=response-codes.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-codes.mjs","names":[],"sources":["../../src/sip-message/response-codes.ts"],"sourcesContent":["// Ref: https://en.wikipedia.org/wiki/List_of_SIP_response_codes'\nconst responseCodes: {\n [key: number]: string;\n} = {\n 100: \"Trying\",\n 180: \"Ringing\",\n 181: \"Call is Being Forwarded\",\n 182: \"Queued\",\n 183: \"Session Progress\",\n 199: \"Early Dialog Terminated\",\n 200: \"OK\",\n 202: \"Accepted\",\n 204: \"No Notification\",\n 300: \"Multiple Choices\",\n 301: \"Moved Permanently\",\n 302: \"Moved Temporarily\",\n 305: \"Use Proxy\",\n 380: \"Alternative Service\",\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 402: \"Payment Required\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 405: \"Method Not Allowed\",\n 406: \"Not Acceptable\",\n 407: \"Proxy Authentication Required\",\n 408: \"Request Timeout\",\n 409: \"Conflict\",\n 410: \"Gone\",\n 411: \"Length Required\",\n 412: \"Conditional Request Failed\",\n 413: \"Request Entity Too Large\",\n 414: \"Request-URI Too Long\",\n 415: \"Unsupported Media Type\",\n 416: \"Unsupported URI Scheme\",\n 417: \"Unknown Resource-Priority\",\n 420: \"Bad Extension\",\n 421: \"Extension Required\",\n 422: \"Session Interval Too Small\",\n 423: \"Interval Too Brief\",\n 424: \"Bad Location Information\",\n 425: \"Bad Alert Message\",\n 428: \"Use Identity Header\",\n 429: \"Provide Referrer Identity\",\n 430: \"Flow Failed\",\n 433: \"Anonymity Disallowed\",\n 436: \"Bad Identity-Info\",\n 437: \"Unsupported Certificate\",\n 438: \"Invalid Identity Header\",\n 439: \"First Hop Lacks Outbound Support\",\n 440: \"Max-Breadth Exceeded\",\n 469: \"Bad Info Package\",\n 470: \"Consent Needed\",\n 480: \"Temporarily Unavailable\",\n 481: \"Call/Transaction Does Not Exist\",\n 482: \"Loop Detected\",\n 483: \"Too Many Hops\",\n 484: \"Address Incomplete\",\n 485: \"Ambiguous\",\n 486: \"Busy Here\",\n 487: \"Request Terminated\",\n 488: \"Not Acceptable Here\",\n 489: \"Bad Event\",\n 491: \"Request Pending\",\n 493: \"Undecipherable\",\n 494: \"Security Agreement Required\",\n 500: \"Server Internal Error\",\n 501: \"Not Implemented\",\n 502: \"Bad Gateway\",\n 503: \"Service Unavailable\",\n 504: \"Server Time-out\",\n 505: \"Version Not Supported\",\n 513: \"Message Too Large\",\n 555: \"Push Notification Service Not Supported\",\n 580: \"Precondition Failure\",\n 600: \"Busy Everywhere\",\n 603: \"Decline\",\n 604: \"Does Not Exist Anywhere\",\n 606: \"Not Acceptable\",\n 607: \"Unwanted\",\n 608: \"Rejected\",\n};\n\nexport default responseCodes;\n"],"mappings":";AACA,MAAM,gBAEF;CACF,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACN"}
@@ -24,3 +24,5 @@ var SipMessage = class {
24
24
  };
25
25
  //#endregion
26
26
  export { SipMessage as default };
27
+
28
+ //# sourceMappingURL=sip-message.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sip-message.mjs","names":[],"sources":["../../src/sip-message/sip-message.ts"],"sourcesContent":["class SipMessage {\n public subject: string;\n public headers: {\n [key: string]: string;\n };\n public body: string;\n\n public constructor(subject = \"\", headers = {}, body = \"\") {\n this.subject = subject;\n this.headers = headers;\n this.body = body\n .trim()\n .split(/[\\r\\n]+/)\n .join(\"\\r\\n\");\n if (this.body.length > 0) {\n this.body += \"\\r\\n\";\n }\n }\n\n public toString() {\n const r = [\n this.subject,\n ...Object.keys(this.headers).map((key) => `${key}: ${this.headers[key]}`),\n \"\",\n this.body,\n ].join(\"\\r\\n\");\n return r;\n }\n\n public getHeader(key: string): string | undefined {\n const foundKey = Object.keys(this.headers).find(\n (k) => k.toLowerCase() === key.toLowerCase(),\n );\n if (foundKey) {\n return this.headers[foundKey];\n }\n }\n}\n\nexport default SipMessage;\n"],"mappings":";AAAA,IAAM,aAAN,MAAiB;CACf;CACA;CAGA;CAEA,YAAmB,UAAU,IAAI,UAAU,EAAE,EAAE,OAAO,IAAI;AACxD,OAAK,UAAU;AACf,OAAK,UAAU;AACf,OAAK,OAAO,KACT,MAAM,CACN,MAAM,UAAU,CAChB,KAAK,OAAO;AACf,MAAI,KAAK,KAAK,SAAS,EACrB,MAAK,QAAQ;;CAIjB,WAAkB;AAOhB,SANU;GACR,KAAK;GACL,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,KAAK,QAAQ,GAAG,IAAI,IAAI,KAAK,QAAQ,OAAO;GACzE;GACA,KAAK;GACN,CAAC,KAAK,OACC;;CAGV,UAAiB,KAAiC;EAChD,MAAM,WAAW,OAAO,KAAK,KAAK,QAAQ,CAAC,MACxC,MAAM,EAAE,aAAa,KAAK,IAAI,aAAa,CAC7C;AACD,MAAI,SACF,QAAO,KAAK,QAAQ"}
@@ -10,4 +10,5 @@ declare class SipMessage {
10
10
  getHeader(key: string): string | undefined;
11
11
  }
12
12
  //#endregion
13
- export { SipMessage as t };
13
+ export { SipMessage as t };
14
+ //# sourceMappingURL=sip-message-B2D5MPBI.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sip-message-B2D5MPBI.d.cts","names":[],"sources":["../src/sip-message/sip-message.ts"],"mappings":";cAAM,UAAA;EACG,OAAA;EACA,OAAA;IAAA,CACJ,GAAA;EAAA;EAEI,IAAA;cAEY,OAAA,WAAc,OAAA,OAAc,IAAA;EAYxC,QAAA,CAAA;EAUA,SAAA,CAAU,GAAA;AAAA"}
@@ -10,4 +10,5 @@ declare class SipMessage {
10
10
  getHeader(key: string): string | undefined;
11
11
  }
12
12
  //#endregion
13
- export { SipMessage as t };
13
+ export { SipMessage as t };
14
+ //# sourceMappingURL=sip-message-PaPho4qU.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sip-message-PaPho4qU.d.mts","names":[],"sources":["../src/sip-message/sip-message.ts"],"mappings":";cAAM,UAAA;EACG,OAAA;EACA,OAAA;IAAA,CACJ,GAAA;EAAA;EAEI,IAAA;cAEY,OAAA,WAAc,OAAA,OAAc,IAAA;EAYxC,QAAA,CAAA;EAUA,SAAA,CAAU,GAAA;AAAA"}
@@ -9,4 +9,5 @@ type SoftPhoneOptions = {
9
9
  ignoreTlsCertErrors?: boolean;
10
10
  };
11
11
  //#endregion
12
- export { SoftPhoneOptions as t };
12
+ export { SoftPhoneOptions as t };
13
+ //# sourceMappingURL=types-DOQ9wmX6.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DOQ9wmX6.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";KAAY,gBAAA;EACV,MAAA;EACA,aAAA;EACA,QAAA;EACA,QAAA;EACA,eAAA;EACA,KAAA;EACA,mBAAA;AAAA"}
@@ -9,4 +9,5 @@ type SoftPhoneOptions = {
9
9
  ignoreTlsCertErrors?: boolean;
10
10
  };
11
11
  //#endregion
12
- export { SoftPhoneOptions as t };
12
+ export { SoftPhoneOptions as t };
13
+ //# sourceMappingURL=types-DZxCsbZE.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DZxCsbZE.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";KAAY,gBAAA;EACV,MAAA;EACA,aAAA;EACA,QAAA;EACA,QAAA;EACA,eAAA;EACA,KAAA;EACA,mBAAA;AAAA"}
package/dist/utils.d.cts CHANGED
@@ -9,4 +9,5 @@ declare const withoutTag: (s: string) => string;
9
9
  declare const extractAddress: (s: string) => string | undefined;
10
10
  declare const localKey: string;
11
11
  //#endregion
12
- export { branch, extractAddress, generateAuthorization, localKey, randomInt, uuid, withoutTag };
12
+ export { branch, extractAddress, generateAuthorization, localKey, randomInt, uuid, withoutTag };
13
+ //# sourceMappingURL=utils.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.cts","names":[],"sources":["../src/utils.ts"],"mappings":";;;cAmBa,qBAAA,GACX,OAAA,EAAS,gBAAA,EACT,KAAA,UACA,MAAA;AAAA,cAmBW,IAAA;AAAA,cACA,MAAA;AAAA,cAEA,SAAA;AAAA,cAGA,UAAA,GAAc,CAAA;AAAA,cACd,cAAA,GAAkB,CAAA;AAAA,cAGlB,QAAA"}
package/dist/utils.d.mts CHANGED
@@ -9,4 +9,5 @@ declare const withoutTag: (s: string) => string;
9
9
  declare const extractAddress: (s: string) => string | undefined;
10
10
  declare const localKey: string;
11
11
  //#endregion
12
- export { branch, extractAddress, generateAuthorization, localKey, randomInt, uuid, withoutTag };
12
+ export { branch, extractAddress, generateAuthorization, localKey, randomInt, uuid, withoutTag };
13
+ //# sourceMappingURL=utils.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.mts","names":[],"sources":["../src/utils.ts"],"mappings":";;;cAmBa,qBAAA,GACX,OAAA,EAAS,gBAAA,EACT,KAAA,UACA,MAAA;AAAA,cAmBW,IAAA;AAAA,cACA,MAAA;AAAA,cAEA,SAAA;AAAA,cAGA,UAAA,GAAc,CAAA;AAAA,cACd,cAAA,GAAkB,CAAA;AAAA,cAGlB,QAAA"}
package/dist/utils.mjs CHANGED
@@ -23,3 +23,5 @@ const extractAddress = (s) => s.match(/<(sip:.+?)>/)?.[1];
23
23
  const localKey = crypto.randomBytes(30).toString("base64").replace(/=+$/, "");
24
24
  //#endregion
25
25
  export { branch, extractAddress, generateAuthorization, localKey, randomInt, uuid, withoutTag };
26
+
27
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import crypto from \"node:crypto\";\n\nimport type { SoftPhoneOptions } from \"./types.js\";\n\nconst md5 = (s: string) => crypto.createHash(\"md5\").update(s).digest(\"hex\");\n\nconst generateResponse = (\n sipInfo: SoftPhoneOptions,\n endpoint: string,\n nonce: string,\n) => {\n const ha1 = md5(\n `${sipInfo.authorizationId}:${sipInfo.domain}:${sipInfo.password}`,\n );\n const ha2 = md5(endpoint);\n const response = md5(`${ha1}:${nonce}:${ha2}`);\n return response;\n};\n\nexport const generateAuthorization = (\n sipInfo: SoftPhoneOptions,\n nonce: string,\n method: \"REGISTER\" | \"INVITE\",\n) => {\n const authObj = {\n \"Digest algorithm\": \"MD5\",\n username: sipInfo.authorizationId,\n realm: sipInfo.domain,\n nonce,\n uri: `sip:${sipInfo.domain}`,\n response: generateResponse(\n sipInfo,\n `${method}:sip:${sipInfo.domain}`,\n nonce,\n ),\n };\n return Object.entries(authObj)\n .map(([key, value]) => `${key}=\"${value}\"`)\n .join(\", \");\n};\n\nexport const uuid = () => crypto.randomUUID();\nexport const branch = () => `z9hG4bK-${uuid()}`;\n\nexport const randomInt = () =>\n Math.floor(Math.random() * (65535 - 1024 + 1)) + 1024;\n\nexport const withoutTag = (s: string) => s.replace(/;tag=.*$/, \"\");\nexport const extractAddress = (s: string) => s.match(/<(sip:.+?)>/)?.[1];\n\nconst keyAndSalt = crypto.randomBytes(30);\nexport const localKey = keyAndSalt.toString(\"base64\").replace(/=+$/, \"\");\n"],"mappings":";;AAIA,MAAM,OAAO,MAAc,OAAO,WAAW,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,MAAM;AAE3E,MAAM,oBACJ,SACA,UACA,UACG;AAMH,QADiB,IAAI,GAJT,IACV,GAAG,QAAQ,gBAAgB,GAAG,QAAQ,OAAO,GAAG,QAAQ,WAG/B,CAAC,GAAG,MAAM,GADzB,IAAI,SAC2B,GAC5B;;AAGjB,MAAa,yBACX,SACA,OACA,WACG;CACH,MAAM,UAAU;EACd,oBAAoB;EACpB,UAAU,QAAQ;EAClB,OAAO,QAAQ;EACf;EACA,KAAK,OAAO,QAAQ;EACpB,UAAU,iBACR,SACA,GAAG,OAAO,OAAO,QAAQ,UACzB,MACD;EACF;AACD,QAAO,OAAO,QAAQ,QAAQ,CAC3B,KAAK,CAAC,KAAK,WAAW,GAAG,IAAI,IAAI,MAAM,GAAG,CAC1C,KAAK,KAAK;;AAGf,MAAa,aAAa,OAAO,YAAY;AAC7C,MAAa,eAAe,WAAW,MAAM;AAE7C,MAAa,kBACX,KAAK,MAAM,KAAK,QAAQ,GAAI,MAAkB,GAAG;AAEnD,MAAa,cAAc,MAAc,EAAE,QAAQ,YAAY,GAAG;AAClE,MAAa,kBAAkB,MAAc,EAAE,MAAM,cAAc,GAAG;AAGtE,MAAa,WADM,OAAO,YAAY,GACd,CAAW,SAAS,SAAS,CAAC,QAAQ,OAAO,GAAG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ringcentral-softphone",
3
- "version": "1.3.6",
3
+ "version": "1.3.7",
4
4
  "homepage": "https://github.com/ringcentral/ringcentral-softphone-ts",
5
5
  "license": "MIT",
6
6
  "type": "module",