{"version":3,"file":"outbound.mjs","names":[],"sources":["../../src/call-session/outbound.ts"],"sourcesContent":["import type dgram from \"node:dgram\";\nimport 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(\n    softphone: Softphone,\n    answerMessage: InboundMessage,\n    socket: dgram.Socket,\n  ) {\n    super(softphone, answerMessage);\n    this.socket = socket;\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":";;;;;AAMA,IAAM,sBAAN,cAAkC,YAAY;CAC5C,YACE,WACA,eACA,QACA;EACA,MAAM,WAAW,cAAc;EAC/B,KAAK,SAAS;EACd,KAAK,YAAY,cAAc,QAAQ;EACvC,KAAK,aAAa,cAAc,QAAQ;EACxC,KAAK,YAAY,cAAc,KAAK,MAClC,2CACD,CAAE;EACH,KAAK,MAAM;;CAGb,OAAc;EAEZ,MAAM,iBAAiB,YAA4B;GACjD,IAAI,QAAQ,QAAQ,SAAS,KAAK,WAAW,QAAQ,MACnD;GAEF,IAAI,QAAQ,QAAQ,WAAW,cAAc,EAAE;IAC7C,KAAK,UAAU,IAAI,WAAW,cAAc;IAC5C,KAAK,KAAK,OAAO;IACjB,KAAK,SAAS;IACd;;GAEF,IAAI,QAAQ,QAAQ,WAAW,cAAc,EAAE;IAC7C,KAAK,UAAU,IAAI,WAAW,cAAc;IAC5C,KAAK,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;IACD,KAAK,UAAU,KAAK,WAAW;;;EAGnC,KAAK,UAAU,GAAG,WAAW,cAAc;EAC3C,KAAK,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;EACD,MAAM,KAAK,UAAU,KAAK,eAAe;;CAG3C,IAAW,YAAY;EAGrB,OAFe,KAAK,WAAW,QAAQ,gBAClB,MAAM,sCACf,CAAC;;CAEf,IAAW,UAAU;EAGnB,OAFe,KAAK,WAAW,QAAQ,gBAClB,MAAM,sCACf,CAAC"}