From 731b041b71cecc4b1fa17f2a63e045ff7157eb24 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Thu, 27 Jun 2024 11:50:32 +0200 Subject: [PATCH] MT#60408 core: add functions to accept pending invites Core in CE is missing currently functions to accept pending invitations, introduce them from PRO version: - `acceptPendingInviteB2B()` - `acceptPendingInvite()` Additionally: - add a helper to create fake replies `createFakeReply()` Change-Id: Icc5be22051f68f269d4b93637f2b3b59498dbd25 --- core/AmB2BSession.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++ core/AmB2BSession.h | 9 +++++ 2 files changed, 99 insertions(+) diff --git a/core/AmB2BSession.cpp b/core/AmB2BSession.cpp index 6c2b7daf..a753d63f 100644 --- a/core/AmB2BSession.cpp +++ b/core/AmB2BSession.cpp @@ -210,6 +210,96 @@ void AmB2BSession::relayError(const string &method, unsigned cseq, bool forward, } } +void AmB2BSession::createFakeReply(AmMimeBody *sdp, AmMimeBody& reply_body) { + + int rtp_int_tmp = getRtpInterface(); + string rtp_local_ip = AmConfig::RTP_Ifs[rtp_int_tmp].LocalIP; + + AmSdp s; + + if (!sdp || s.parse((const char*)sdp->getPayload())) { + /* no offer in the INVITE (or can't be parsed), we have to append fake offer + into the reply */ + s.version = 0; + s.origin.user = "sems"; + s.sessionName = "sems"; + s.conn.network = NT_IN; + s.conn.addrType = AT_V4; + + /* MT#55582, removed. + s.conn.address = "0.0.0.0"; + */ + + /* re-fill the empty connection address with the media_ip */ + if (s.conn.address.empty()) s.conn.address = rtp_local_ip; + + s.media.push_back(SdpMedia()); + SdpMedia &m = s.media.back(); + m.type = MT_AUDIO; + m.transport = TP_RTPAVP; + m.send = false; + m.recv = false; + m.payloads.push_back(SdpPayload(0)); + } + + /* MT#55582, removed, because in case of generating a faked reply + during the media session refreshment (e.g. call pickup after the AA), + it leads to a held media session + + if (!s.conn.address.empty()) s.conn.address = "0.0.0.0"; + for (vector::iterator i = s.media.begin(); i != s.media.end(); ++i) { + //i->port = 0; + if (!i->conn.address.empty()) i->conn.address = "0.0.0.0"; + }*/ + + /* re-fill the empty connection address with the media_ip */ + if (s.conn.address.empty()) { + s.conn.address = rtp_local_ip; + DBG("RTP Connection address was empty, and has been rested to: <%s>\n", s.conn.address.c_str()); + } + + /* same here, but for the rest media sessions in SDP */ + for (vector::iterator i = s.media.begin(); i != s.media.end(); ++i) { + if (i->conn.address.empty()) i->conn.address = rtp_local_ip; + } + + string body_str; + s.print(body_str); + reply_body.parse(SIP_APPLICATION_SDP, (const unsigned char*)body_str.c_str(), body_str.length()); + try { + updateLocalBody(reply_body); + } catch (...) { /* throw ? */ } + + DBG("created pending INVITE reply body: %s\n", body_str.c_str()); +} + +void AmB2BSession::acceptPendingInvite(AmSipRequest *invite) +{ + // reply the INVITE with fake 200 reply + + AmMimeBody *sdp = invite->body.hasContentType(SIP_APPLICATION_SDP); + AmMimeBody body; + + createFakeReply(sdp, body); + + DBG("Replying to pending invite with 200 OK\n"); + dlg->reply(*invite, 200, "OK", &body); +} + +void AmB2BSession::acceptPendingInviteB2B(AmSipRequest& invite) +{ + AmMimeBody *sdp = invite.body.hasContentType(SIP_APPLICATION_SDP); + AmSipReply n_reply; + createFakeReply(sdp, n_reply.body); + n_reply.code = 200; + n_reply.reason = "OK"; + n_reply.cseq = invite.cseq; + n_reply.cseq_method = SIP_METH_INVITE; + n_reply.from_tag = dlg->getLocalTag(); + DBG("Relaying B2B-event (fake 200 OK)\n"); + relayEvent(new B2BSipReplyEvent(n_reply, true, SIP_METH_INVITE, getLocalTag())); +} + void AmB2BSession::onB2BEvent(B2BEvent* ev) { DBG("AmB2BSession::onB2BEvent\n"); diff --git a/core/AmB2BSession.h b/core/AmB2BSession.h index 95ba10d9..dca3b776 100644 --- a/core/AmB2BSession.h +++ b/core/AmB2BSession.h @@ -207,6 +207,15 @@ private: /** send a relayed SIP Reply */ int relaySip(const AmSipRequest& orig, const AmSipReply& reply); + /** generate fake body (c=0.0.0.0) reply */ + void createFakeReply(AmMimeBody *sdp, AmMimeBody& reply_body); + + /** generate 200 SIP reply on a pending INVITE (uses fake body) */ + virtual void acceptPendingInvite(AmSipRequest *invite); + + /** generate 200 B2B reply on a pending INVITE (uses fake body) */ + void acceptPendingInviteB2B(AmSipRequest& invite); + public: void sl_reply(const string &method, unsigned cseq, bool forward, int sip_code, const char *reason);