make the `run()` more accurately honor the threads stop
request when checking registrations in the inner-loop.
If the thread is on `wait_or_stop()` this should be managed
just quickly and gracefully.
However if we are on the `check_registration()` or
`create_registration()` doing a DI cal, threads stop request
cannot really interrupt it. So tighten it.
Change-Id: I31ef44445817d4eb8e11cf269c2bd4db2eff71ef
If the owner of the `RegThread` (`RegistrationAgentFactory`)
was asked to be destructed, make the destroy process
of the reg thread more ordered as well.
That makes the thread to stop as soon as the app factory
begins its own destruction.
This will help to avoid a possible way to end up with
a stale (or invalid) DI factory ptr.
E.g.: `RegThread` keeps on running, while all the plugins
are being torn down by that time already. In this case
the `RegThread` can simply call `getFactory4Di()` or `di_f->getInstance()`
way after the registrar_client is already partially destroyed.
Change-Id: I10e38174d3856e19f2696f8d874ea166e0a035a8
Instead of blindly sleeping, use the `run_cond.wait_for()`
for the case, when AmThread sends `.notify_all()` upon stopping.
Hence we don't have to block the whole thread for 10 seconds if
suddenly the `stop()` is requested by AmThread at the very beginning
of the sleep.
Add a dedicated `RegThread::wait_or_stop()` wrapper to handle this.
Also differentiate whether the `RegThread::wait_or_stop()` returns
due to timer exceed or there was an actual thread stop requested.
Act accordingly during the `run()` execution.
Change-Id: I1e603c462af983e633c811d10ed2d0ac506f46d3
Check whether the thread was asked to be stopped,
instead on infinitely cycling through the true statement,
relying on the fact `getFactory4Di()` will always return
a safe and valid pointer.
Change-Id: Ibc27b725eaa2c183c50bff603f7d3115cdc57b3d
Gets serialized into the bool on the profile's global level.
Isn't leg specific, but global for the whole session.
Only used to remove SST related headers and option tags
from requests and replies being sent through either
`SBCCallLeg::onSendRequest()` or `SBCCallLeg::onSendReply()`.
Transparent means - do not touch existing SST headers.
SessionTimer implementation factory isn't triggered in this case.
Change-Id: Id98a8abc957be11d140eba2394fed7ebe1302ca7
This is a prolongation of the commit 5085fb134878
In case this very leg (A or B) doesn't support
SST timers, then before sending out the request/reply
to the end-point, make sure to remove SST related stuff:
- `Supported: timer` (option tag)
- `Require: timer` (option tag)
- `Session-Expires` header
- `Min-SE` header
Remove previously introduced manipulations from the
`SBCCallLeg::relayEvent()`, which is rather meant
to process the incoming request/reply event
in the other leg (and not this leg), because then
we mistakingly remove headers checking the wrong leg.
Hence `SBCCallLeg::relayEvent()` -> `AmB2BSession::relayEvent()`
is only responsible to post the relay event for this leg,
and the `SBCCallLeg::onSendRequest()` / `SBCCallLeg::onSendReply()`
are actually handlers for the end view of the SIP message being
sent out.
Additionally: introduce the `SBCCallLeg::onSendReply()` hook,
for the virtual `AmSession::onSendReply()`, that should accordingly
handle SST removal in the scope of SBCCallLeg.
Additionally: introduce the `sessionTimerSupportedByLeg()` static
helper for SBCCallLeg, to check support of SST based on A/B leg awareness.
Change-Id: Icb5d0bc5a62b06e26a46a1bceeb5c73aa8d7bf2a
In case the session originator never declared SST support
(with `aleg_sst_enable=yes`), then remove all possible SST
related headers and `timer` option tags where present.
This gets removed in all sip responses/requests going
towards the caller in this case.
Change-Id: I960fa09d00a8f324665b89d2e3ab0b44cbfcd677
Mirrors the sems-pbx fix for the shared apps/sbc and core code.
When a mid-transfer call is picked up (BLF), SEMS sends a re-INVITE
with the picker's media towards the caller while another re-INVITE is
still pending on that leg. It used to answer 491 and drop the update,
so the call connects with no audio on either side.
The P-Force-491: 0 marker exists to prevent exactly this: it tells the
receiving leg to queue the update instead of 491ing it. But
onB2BEvent() read the marker from the relayed request hdrs - which
SBCCallLeg::relayEvent() has already run the profile's header filter
over. Whitelist profiles don't list the header, so it was stripped and
the 491 fired anyway.
Read the marker earlier, in AmB2BSession::onSipRequest() while the hdrs
are still unfiltered, and carry it as a skip_491 flag on the event. The
queued update is replayed once the pending transaction ends, as before.
This CE codebase has no call_transfer module, so t/test-xdsm-race.py
reproduces the race with generic sbc.putOnHold/sbc.resumeHeld DSM
actions over the same CallLeg.cpp path: the basic race, two stacked
self-updates ahead of a collision, a plain unmarked glare that must
still get 491, and the marker surviving the whitelist filter. Each
collision carries the marker like the real pickup does, so the tests
491 on unpatched code.
Also make the tests robust on a loaded CI: recvB2BINVITE() skips
in-dialog INVITEs (those with a To-tag), and the queued updates are read
by CSeq freshness, so timer-A retransmissions of earlier re-INVITEs
piling up in the socket buffer aren't mistaken for the awaited update.
Change-Id: Ie55f0a2f33a0dde5e2c3dd8dd2fb2c82c67a06c4
Introduce explicit policy for within-dialog SST support:
- whenever remote side (call leg) doesn't explicitly declare
it supports timers (with `Supported: timer`), disable all
previously set timers for this particular leg
- this touches request originator, as well as answerer
- requests: only UPDATE and INVITE methods are affected
- answers: only positive answers are affected
- by default this behavior is always disabled if not enabled
explicitly in the profile's config with `sst_strict_mode`
- sst_strict_mode takes either `yes` or `no`
P.S.: the `sst_strict_mode` must not be initialized to true
by default, because RFC 4028 explicitly tells to support
the operation even when only one UA understands session timers.
So we have to be quite accurate and not enforce the strict mode.
Change-Id: Ie6647eb061a73dc052367dbd291589198487093c
Align the port value accordingly to the requested transport.
Do take the config parameter `contact_hostport` into account
only then, when the contact URI given by DI is empty.
In case DI provides a full contact value, with a transport,
then accordingly inspect it and rebuild from scratch,
using the following uri schema:
`sip + username + @ + host + port + uuid + transport`
Default port values are:
- udp = 5060
- tcp = 5060
- tls = 5061
the config parameter has a value only as a fallback.
Change-Id: Ibf2a7a1d74d438e853c02bfe77478ac62216dbca
Update the usage of the `getParameter()` through
the modules, whereas the default value isn't given.
Change-Id: I4c725639f56b70e5548fa3da321c8452675cdf99
Rework plug-ins parser so that it supports
the multi-line parsing.
E.g.:
load_plugins=wav;\
gsm;\
g729;\
opus;\
g722;\
di_dial;\
...
Change-Id: Ic672ff72db73279d9fd3d52ba9a60fa5f6d7eb25
- Add pyproject.toml and tox.ini with consistent black and pycodestyle
settings.
+ Fix all errors >= E300.
- Place unconditional imports at the beginning of the file.
- Do not import more than one module at the same time.
- Do not use blackslash at EOL within brackets.
- Do not use bare except.
- Do not end statement with semicolon.
- Do not place multiple statements in the same line.
- Use «is» and «is not» instead of «==» and «!=» for None.
- Disambiguate short variable name by giving it a better longer name.
- Remove trailing whitespace.
- Fix expected number of blank lines.
Change-Id: I02a29887a1267f5b843822e0ff05b7dca4416554
The code had not been converted to Python 3.x, and was not even
compiling there, with something like:
$ find -name '*.py' | xargs -n1 python3 -m py_compute
Change-Id: I795f931123d1bccb85670fe0dc6b06c46a9f22c2
Improperly checked return value of `str2int()`
in the `setTimer()` DSM wrapper.
False is failed conversion, true is fine.
Change-Id: I2e2a10b9e25b660ec94322934043717edb4aebf3
src/XmlRpcValue.cpp: In member function ‘std::ostream& XmlRpc::XmlRpcValue::write(std::ostream&) const’:
src/XmlRpcValue.cpp:483:44: warning: ‘%02d’ directive output may be truncated writing between 2 and 11 bytes into a region of size between 8 and 15 [-Wformat-truncation=]
483 | snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d",
| ^~~~
src/XmlRpcValue.cpp:483:40: note: directive argument in the range [-2147483647, 2147483647]
483 | snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/XmlRpcValue.cpp:483:19: note: ‘snprintf’ output between 18 and 70 bytes into a destination of size 19
483 | snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d",
| ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
484 | (1900 + t.tm_year), (1 + t.tm_mon), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Change-Id: I38edb330bc0d0ea17fc215f745fc51e66d56d41f
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
All the subsequent code already relies on the fact
it's not NULL, so makes no sense to actually check
this later again.
Closes Coverity CID 642754.
Change-Id: I0de348d0deff6d36f4d0ecfdb2635c94d1101fb2
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
Just because these have some complication during
the compilation, and these aren't actually used
exclude them for a while to not disturb people
while compiling the whole project:
- conference
- early_announce
- voicemail
Change-Id: Ib8689a0a8077b25ba1d2d433c6b970eded3eb0bd
The following VSC have been added to sems CE:
* vsc_off
* clir
* colr
* dnd
The toggle version of the vsc codes is still NOT added because
reserved for PRO only.
Additionally the code has been reformated to align it with
the PRO version.
Change-Id: I0cf675651eaa13ddc5dc474a5a204686e9398962
If the Content-Length is empty, then it makes no sense
to parse and filter application/sdp body.
Otherwise a parser is going to fail and answer with 488.
Change-Id: I92cdd19319c6f4a4edcfbaeec7bad1be12c8a0b0
Add parsing of Content-Length, for cases
were this length matters (e.g. ct length > 0,
but suddenly there is no SDP body).
Also add a getter for the AmContentType's length.
Change-Id: I92cdd19319c6f4a4edcfbaeec7bad1be12c8a0b1
Reverse inheritence between singleton class and its base.
Change singleton template so that the singleton class doesn't inherit
from its base, but rather that the singelton class inherits from the
singleton template. This removes the need to keep the singleton base
classes separate (with the underscore prefix) plus a `typedef` for the
singleton class, and instead makes the class itself become the
singleton. (The exception being intermediate classes that have multiple
other derived classes, which is only the wheeltimer).
This makes for cleaner typing, but requires use of listing the singleton
template as friend class.
No functional changes.
Change-Id: Ic45cb01f7870ce0ba97188e58340b10fdc0380cb
The destructor is good enough, and it removes ambiguity to the
singleton's own dispose method.
No functional changes.
Change-Id: I7bd2014cbeaab0eb5104c2674d39dd8d7e38affd
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
Force the leg being connected instead of the replaced one
to the rtp_relay_mode = RTP_Direct, because otherwise
legs can get SEMS involved into rtp relay after a transfer
is finished.
Change-Id: Ifb55feaa7813fc303a663ac132b0bfe175772ce0