Properly place the clear RTP receivers handler.
Instead of doing directly from the destructor,
do it on state change (onBeforeDestroy) via
the down to up virtual function realization search.
Is triggered by `AmSession::finalize()`.
Closes Coverity CID 642748.
Change-Id: I4c224425e9fbecedef3d29a6658f1723313b19c4
This commit introduces a new RTP transport model,
based on the AmRtpTransport abstraction, providing a more modular and
efficient approach to RTP handling compared to the legacy model.
General things:
- Introduction of new RTP receiver and transport abstractions
- The new model coexists with the legacy RTP handling
to preserve backward compatibility
Architecture overview:
- A new AmRtpTransport layer is introduced to encapsulate RTP transport logic
and decouple it from AmRtpStream and session-level code
- Transport-specific functionality is implemented via dedicated classes:
- AmRtpTransport: base abstraction responsible for RTP/RTCP packet flow,
lifecycle management, and interaction with streams
- AmRtpUdpSocket: UDP-based RTP socket implementation
- AmRtpSocketPair: manages RTP/RTCP socket pairs and their coordination
- AmRtpStream is refactored to rely on the transport interface
instead of directly managing sockets and low-level I/O
Integration details:
- SIP session and dialog logic (AmSession, AmSipDialog) is updated to work with
the new transport model
- SBC call legs and call profiles are extended to support transport selection
and lifecycle handling
- SDP processing (AmSdp) is updated to reflect transport capabilities and
address handling changes
This refactoring improves separation of concerns, reduces coupling between RTP
streaming and transport mechanics, and provides a cleaner foundation for future
RTP extensions and optimizations.
Code provenance and license:
- part of the code was written by Fokus GmbH
- part of the code was written by Sipwise GmbH
- part of the code base copyrighted by Fokus GmbH was provided by them in
the form of backports under the GPL license.
- these changes are covered by the GPL, matching the existing project license
Change-Id: I313c4abd9b54f805c1e668c019cf6fb8c4a9e46d
If this is an SDP answer (provided by non-fwd 200OK),
don't hesitate to update the original leg originated this
INVITE transaction.
Originally this was prevented by the
56115ed5dd00f7ce9271e97e5933a9745eb31435
of the original (root) SEMS project, in order to fix
some of the Click2Dial scenarios of the according
Click2Dial app. Original message from it:
don't refresh for establishing transaction
fixes click2dial application.
In the B2BUA, usually a refresh is done if the established session
description has changed on the other leg (e.g. initiated by SST
refresh from the middle). This fix prevents that refresh for the
initial transaction, where the re-INVITE to caller is done explicitely.
It seems that this commit somehow introduces this logic also
for those legs, which aren't actually establishing but are in need
for the SDP media updates. So just remove it.
Change-Id: I3acf7d3d9ceaa3c8d7a8ba0f7a5c6973646bc2af
Rework the payload to be a string instead of the raw char array.
This eliminates cases when we actually need to track that this char array
is indeed null-terminated and deprives us from doing other tricks to
properly maintain this char array.
Also no need to return const of payload anymore, because simply copied
during return. Data protection ensured by not giving a reference to the payload,
modifiable still during the first time setting this payload.
Rework also other users, such as nested call into AmSdp provided `parse()`.
Now `parse()` takes a string, and already in a local scope handles a char array
copy of this given string. This is only because the `parse_sdp_line_ex()` still
requires a refactor to be working with strings instead of char array.
Additionally: move parser helpers of AmSdp to const char pointers,
instead of working on a plain char pointer. This is because the SDP body
parser has been moved from the referenced pointer `char *&`
to the `const char *` pointer. This allows to not have additionally
heap allocated SDP body C-string for parsing purposes.
No functional change.
Change-Id: Ic3ee6c349b62e7e5e0cd4de722f9ed923862a7cb
Preamble: no functional changes.
AmSdp::parse() mixes int values with bool,
what makes the behavior not really clear, not defined
and can lead to the unpredicted result (even though the
compiler *should* actually fix that, but one ought to
not rely on this).
Hence make the parse method only be working with bool values.
Then, reverse the return value so that it's clear
that wrongly parsed is `false`, and good parsed is `true`.
Refactor all users accordingly.
Also rework those users, who indeed need `int` value
be returned, e.g. when having -1.
Do the same thing with the `parse_sdp_line_ex()` helper,
whereas parse() is the only user of it. And also reverse
the interpretation of true/false.
Then, make `parse()` working with a plain `char*`, so not a const.
Because doing a tricks like:
cast `char*` to const (user level) -> cast `const char*` to non-const
in a function (in a old C-like manner), has really no sense.
Refactor everything accordingly.
Other than that, refactor AmMimeBody:
Refactor it to work with a plain `char *` pointer instead of working
with `unsigned char *`, which nowadays has really no sense and
rather is a rudiment of C-like code base coming from the past.
Convert `payload` from `unsigned char*` to `char *` accordingly.
Refactor everything in AmMimeBody implementation accordingly.
Remove rudiment C-like casting everywhere, where possible.
Update `parseMultipart()` to work with a plain `const char *`
instead of `const unsigned char*`
P.S.: leave a list of TODO's for further rework, which
is not directly related to this scope of rework.
Change-Id: Ie1e132429245e0d2cc740d5b1c1fc17cf037a820
When using that, the return value must always
be checked, because the parsing itself can indeed fail.
Fixes such things as:
** CID 583412: Error handling issues (CHECKED_RETURN)
/core/AmB2BSession.cpp: 340 in AmB2BSession::acceptPendingInvite(AmSipRequest *, const AmMimeBody *)()
_____________________________________________________________________________________________
*** CID 583412: Error handling issues (CHECKED_RETURN)
/core/AmB2BSession.cpp: 340 in AmB2BSession::acceptPendingInvite(AmSipRequest *, const AmMimeBody *)()
334 return;
335 }
336
337 /* port must reflect actual port in SDP offer coming in */
338 if (sdp) {
339 AmSdp fake_sdp;
>>> CID 583412: Error handling issues (CHECKED_RETURN)
>>> Calling "parse" without checking return value (as is done elsewhere 12 out of 15 times).
340 fake_sdp.parse((const char *)sdp->getPayload());
341 desired_port = getMediaPort(fake_sdp);
342 }
343
344 if (desired_port) {
345 ILOG_DLG(L_DBG, "Desired port for fake 200OK is '%d'\n", desired_port);
Change-Id: I7bd177a624ebe2df2629863eb31f97f99bd921bb
Set the port in fake SDP answer (to the other side)
coming from the leg, which now replaces the previously
existing one, to the port gotten from the replace INVITE.
Otherwise, if to use the port from the pending transaction
(towards pick-up'er) it confuses rtpengine with a case
when same port talks to himself, and then can later be
used to update the pick-uper's leg once again.
Change-Id: I4c001f7956a005b64285c05586839f01216cfd91
Don't re-exploit the connection information and port
(taken from the coming SDP offer) for creation of faked
SDP answer (200OK). This is confusing and can break things
in rtpengine monologues handling.
Better to create fake SDP answer based on already learned
local SDP port and entirely connection information.
Change-Id: Id71453022fd6c93f6743f1046588447b52c38c07
In case of INVITE pending UAC transactions for the other leg,
and new coming in (like 200OK send to this leg, and just right
after that re-INVITE), just provide a fake SDP answer (200OK)
in the meanwhile.
And expect that a finished UAC transaction on the other side,
must trigger a consequent update for this leg, what will finish
these media negotiations.
Change-Id: I190dfcd5467c728e2192940dfac8454f708cecaf
In the following funcs:
- AmB2BSession::acceptPendingInviteB2B()
- AmB2BSession::acceptPendingInvite()
That ensures we do not interfere into SDP
when creating fictitious replies.
Change-Id: Ic2e6ccc273cd6079c4b21839cfee38455e60ebc2
Make the way we get call-id when calling ILOG_DLG()
file specific, which allows to define locally
(within a target file) how to get the call-id value.
Change-Id: I4af87edf9d1ea52d9678b3354bc797cf1f5f0b54
Move it to the dlg level, because of complex visibility.
In other words, when working on the dialog level and e.g.
generating new SDP body using `dlg.oa`, there is no way
to save it.
Moving it to the dlg level, gives a control over it on
the whole amount of inheritance levels plus dlg.
Change-Id: Iebb13e3e58f2558dc060e23270d99d690fa54572
If requested by `b2b_build_pai_from_hdr` DSM parameter,
then get the value of PAI using this parameter and pass
it further for `B2BSipReplyEvent` processing.
Use event params to pass the value.
`b2b_build_pai_from_hdr` keeps the name of header
coming in the latest reply, from which the PAI's value
is to be built.
Update the `reinviteCaller()` function's signature,
to pass headers towards `dlg->sendRequest()`.
Change-Id: Ic6e66e326f26a830c3ed06c19a6ab7be4ebe0135
Re-use previously offered SDP body, when processing
a call session with an involvement of DSM, and getting
newer SIP invite having no SDP offer.
This affects applications using the B2B `connectCollee()`
functionality and doesn't actually touch the B2B core itself.
(Which would be wrong if changed in a usual core SDP
processing, whereas original request can be empty and
an offer/answer is postponed to 200OK/ACK exchange)
(Re)invites towards DSM applications technically must
not be empty, because DSMs don't support late offering.
In order to overcome that just pretend that empty
re-INVITEs are using previous body version.
Change-Id: I252eb9f32e7dc073454a2258b176f77bf15d35c9
Introduce getters for headers in requests
and replies:
- `B2B.getHeaderRequest()`
- `B2B.getHeaderReply()`
Change-Id: I1dfc24658a9e044407f95de9507032f1b041b451
SDP session origin id and version are limited by it's size
to 64 bits (8 bytes), that is because we are using `unsigned long long`
type for both id and version. Hence the maximum value it can hold
is two sixty-forth power, so equals: 18,446,744,073,709,551,615
In case one intentionally sets it to something like:
"o=- 18446744073709551615 18446744073709551615 IN IP4 192.168.0.1"
SEMS gets overwhelmed with that conversion inside the code make
it just to a string literal 'F'.
To overcome it, just use __uint128 (which is of 128bits size)
for the session origin id and version.
Change-Id: I2ad9659aa81dad79969749053dc3fd0d69e2cbd2
Use `unsigned long long` for SDP session id and version
instead of unsigned int.
Refactor all usage of them accordingly.
Additionally intrdouce new utils functions for conversion:
- `ulonglong2str()` - converts `unsigned long long` to `string`
- `str2ull()` - converts `string` to `unsigned long long`
Change-Id: I4210349a5442d4173b14227497f4a01d68cad7a4
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
Sync the `CallLeg::onB2BReconnect()` with PRO code version,
and add second part of SDP origin manipulation fix.
Change-Id: I7d7558bc88ab91d00bac72a22e1f713afd218233
Because of messy organizing of the code in the function,
it's not possible to read that and work with that.
Original ticket number: 0055878
Change-Id: I6c093ccc09015c9d4745af6b3c21365220b81386
The new parameter of the 'P-DSM-App:' header is introduced:
- ';reset-to-tag=''
It affects the processing of 18X (especially it relates to 183).
If this is set to '1', then the To-tag stored as the remote tag in
the 'dlg' object, must be updated to the latest one provided by this 183.
This fixes the case as the following one:
- A calls B (B is an owner of the callqueue)
- B starts ringing, and provides the To-tag with 180
- this in its turn, will initiate generation of own "internally"
generated To-tags in all the internal legs between Proxy <-> B2B,
which are crossed by this 180
- B responds with 486 Busy and a processing gets inside the route[ROUTE_EARLY_REJECT]
- the brand-new INVITE is generated and sent to the DSM early_dbprompt app
- A brand-new 183 is provided by the DSM app, which has another (new) To-tag
- this will mismatch in the very original leg with Proxy and B2B
and 183 will be not sent towards the caller, which makes impossible
to provide an early reject playback to it
Original ticket number: 0055878
Change-Id: I96abbe0b8427d40752967607d2fdd0e11145a06a
We have to add more SIP response codes, which will be checked against
the isDSMPlaybackFinished(). So that when the DSM playback is finished,
the call is properly released on the caller's side.
Exceptionally 487 is added, for cases like:
a call to HG, where nobody answers and the timeout triggers
a cancelation of all the legs.
Change-Id: I1f7cf81dd5966843713fc41c21ea0249174c13ab
We have to optimize our code:
- substitute all repeating (DSM related) code with a helper static functions
- remove all excessive stuff, which plays no role
Change-Id: I27170509d84a634dc4a9a865ea8395e4e8cc2f3d
Introduce a new header file "global_defs.h" in order to use that
for global definitions or macroses, which are not particularly
related to the SIP headers. Such as DSM applications names.
This will simplify handling and decrease hardcoding all around
the project.
With this commit additionally:
- stop hardcoding values related to DSM applications specific names
- move all the DSM definitions into the global_defs.h or defs.h
Change-Id: I389f632434f0ae1e62540e8df584fdc5e1e07e39
We need to add the 'early-dbprompt' DSM application into
the processing of the 480 replies, which have
'P-DSM-App: <app-name>;playback=finished' parameter set.
Change-Id: I3e561f510d8e56ca7d0cece714c0330f3bfa9ecd
Since the P-Early-Announce has gotten deprecated, it's required
to stop using it. And instead start using the P-DSM-App header, which
now carries the same information as parameter ';early-annonce='.
Change-Id: I7f0f378143d0b6600a239084cd51935a31df3d08
B2BSipReply
We have to update the media session with the caller, if the 183 response
with the 'P-Early-Announce: force' has been received.
Change-Id: Iec67c6b6cc5284afbcfb492fc53108439a427b1d
Because of messy organizing of the code in the function,
it's not possible to read that and work with that.
Change-Id: Iab28ba34ba0cc970e3f100f8cc61bcbbdabee2bb
B2BSipReply
We have to update the media session with the caller, if the 183 response
with the 'P-Early-Announce: force' has been received.
Change-Id: Ib39dc124ef5e8934ff617d562b222bd07dfcacc1
If we get the 480 reply from the office-hours DSM application,
and there is a header 'P-DSM-App: office-hours' added, with
a parameter ';playback=finished', then it means the following:
- there was either AA or transfer involved into the call, before
the call got to the DSM office-hours
- caller remains in the hold state (so there was 200/ACK)
- the office-hours playback has been finished, and now we mustn't
forward 480 to the caller's leg, but just terminate it with BYE
Change-Id: I389c6993185008c51c61bacd8eb23ac1562871b8
Because of messy organizing of the code in the function,
it's not possible to read that and work with that.
Change-Id: I558685c46358caabe55193c1e27d9531728ea7d6
There is a need to add an exception processing for 183 Session Progress,
and the following in-dialog requests/responses, in case the 183
has been previously sent to the B2B with the hf
'P-Early-Announce: force'.
This adds the following behavior.
When 183 is received, and the caller has been updated with the
new media capabilities, according to those needed to embed early
media into the media session with the caller (via re-INVITE), then:
- even though the 183 is treated similarly to 200OK in terms of media
updates, do not send ACK to the leg going towards DSM,
becausethe sems-b2b giving the DSM, it's still in stage INVITE/183
- do not re-negotiate the leg going towards the DSM,
after the caller has been updated with the new media (a usual behavior)
because the sems-b2b giving the DSM still considers the dialog here
in the Early stage
- do not set the leg going towards DSM into the Connected state,
because by the fact, it's still in the Early stage, and setting of
it into the Connected state, will break processing of BYE / CANCEL.
- upon receiving the BYE from the caller (after the DSM announce is heard),
answer right away with 200OK, but do not forward BYE to the let going
towards DSM. Instead initiate the CANCEL towards it, because this leg
is technically still in the Early stage of the dialog.
Original ticket number: TT#187351
Change-Id: Id6e05202add1bcbd358eecbcd5e2cbda1a995b32
applications which are doing outbound calls should implement
onFailedOutboundCall if the behavior should be different than
setting stopped.
Reported by Andrei Samusenko