diff --git a/app.js b/app.js index 6af4038..c653e63 100644 --- a/app.js +++ b/app.js @@ -244,10 +244,6 @@ srf.invite((req, res) => { } return session.replaces(req, res); } - if (req.locals.sdp === '') { - logger.info('no sdp in invite'); - return res.send(488, {headers: {'X-Reason': '3pcc INVITEs without SDP are not currently supported'}}); - } const session = new CallSession(logger, req, res); session.connect(); }); diff --git a/lib/call-session.js b/lib/call-session.js index 6ddd567..8f59818 100644 --- a/lib/call-session.js +++ b/lib/call-session.js @@ -108,7 +108,8 @@ class CallSession extends Emitter { async connect() { const {sdp} = this.req.locals; - this.logger.info('inbound call accepted for routing'); + const is3pcc = this.req.body?.length === 0; + this.logger.info(`inbound ${is3pcc ? '3pcc ' : ''}call accepted for routing`); const engine = this.getRtpEngine(); if (!engine) { this.logger.info('No available rtpengines, rejecting call!'); @@ -183,13 +184,13 @@ class CallSession extends Emitter { else uri = `${scheme}:${host}`; this.logger.info(`uri will be: ${uri}, proxy ${proxy}`); - try { + const sendOfferToRtpEngine = async(remoteSdp) => { const opts = { ...this.rtpEngineOpts.common, ...this.rtpEngineOpts.uac.mediaOpts, 'from-tag': this.rtpEngineOpts.uas.tag, direction: [isPrivateVoipNetwork(this.req.source_address) ? 'private' : 'public', 'private'], - sdp + sdp: remoteSdp }; const startAt = process.hrtime(); const response = await this.offer(opts); @@ -202,7 +203,11 @@ class CallSession extends Emitter { this.logger.error({}, `rtpengine offer failed with ${JSON.stringify(response)}`); throw new Error('rtpengine failed: answer'); } + return response; + }; + try { + const response = await sendOfferToRtpEngine(sdp); let headers = { 'From': createBLegFromHeader(this.req), 'To': this.req.get('To'), @@ -212,9 +217,13 @@ class CallSession extends Emitter { }; if (this.privateSipAddress) headers = {...headers, Contact: ``}; - const spdOfferB = this.siprec && this.xml ? - createSiprecBody(headers, response.sdp, this.xml.type, this.xml.content) : - response.sdp; + let spdOfferB; + if (this.siprec && this.xml) { + spdOfferB = createSiprecBody(headers, response.sdp, this.xml.type, this.xml.content); + } + else if (!is3pcc) { + spdOfferB = response.sdp; + } if (this.req.locals.carrier) { Object.assign(headers, { @@ -281,7 +290,10 @@ class CallSession extends Emitter { '-X-Authenticated-User' ], proxyResponseHeaders: ['all', '-X-Trace-ID'], - localSdpB: spdOfferB, + localSdpB: spdOfferB ? spdOfferB : async(ackBody) => { + const response = await sendOfferToRtpEngine(ackBody); + return response.sdp; + }, localSdpA: async(sdp, res) => { this.rtpEngineOpts.uac.tag = res.getParsedHeader('To').params.tag; const opts = { @@ -292,8 +304,12 @@ class CallSession extends Emitter { sdp }; const startAt = process.hrtime(); - const response = await this.answer(opts); - this.logger.debug({response, opts}, 'response from rtpengine to answer'); + const aOpts = { + ...opts, + ...(is3pcc && {direction: ['private', 'public']}) + }; + const response = await this.answer(aOpts); + this.logger.debug({response, opts: aOpts}, 'response from rtpengine to answer'); const rtt = roundTripTime(startAt); this.stats.histogram('app.rtpengine.response_time', rtt, [ 'direction:inbound', 'command:answer', `rtpengine:${this.rtpengineIp}`]); @@ -313,7 +329,7 @@ class CallSession extends Emitter { } return response.sdp; - } + }, }); // successfully connected diff --git a/test/scenarios/uac-late-media.xml b/test/scenarios/uac-late-media.xml index 8b96729..f5226cc 100644 --- a/test/scenarios/uac-late-media.xml +++ b/test/scenarios/uac-late-media.xml @@ -19,22 +19,21 @@ - + ;tag=[call_number] - To: sut + From: sipp ;tag=[pid]SIPpTag09[call_number] + To: Call-ID: [call_id] CSeq: 1 INVITE Contact: sip:sipp@[local_ip]:[local_port] Max-Forwards: 70 - Subject: uac-no-3pcc - Content-Type: application/sdp + Subject: uac-late-media Content-Length: 0 ]]> @@ -43,27 +42,79 @@ - + + + + + + + + + ;tag=[pid]SIPpTag09[call_number] - To: [service] [peer_tag_param] + To: [peer_tag_param] Call-ID: [call_id] CSeq: 1 ACK - Subject: uac-no-3pcc + Max-Forwards: 70 + Subject: uac-late-media + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[local_ip_type] [local_ip] + t=0 0 + m=audio [auto_media_port] RTP/AVP 8 101 + a=rtpmap:8 PCMA/8000 + a=rtpmap:101 telephone-event/8000 + a=fmtp:101 0-11,16 + + + ]]> + + + + + + + + + + + + + + + ;tag=[pid]SIPpTag09[call_number] + To: [peer_tag_param] + Call-ID: [call_id] + CSeq: 2 BYE + Subject: uac-late-media Content-Length: 0 ]]> - + + + + - \ No newline at end of file + + +