If 183 has empty body, don't change the state,
because otherwise it will break the OA model exchange
in later updates during the continued early dialog stage.
Keep pretending to remain in the `Completed` state.
Change-Id: I1053740a179c8589b54a0c856caa438a92521fda
For the cases with option tags are being added/removed
from the headers (e.g. Require, Supported),
we have to cover corner cases.
Introduce according tests into existing core tests
covering headers, as well as python framework part of it.
Change-Id: Iad15add88473f9d64cc6a3d27fc6e996e4a81abf
Do not use the original iterator's position,
when removing the first token from something like:
`Supported: timer, path, replaces`
Instead build the remaining option list by appending
only those kept, trimmed tokens with commas between them.
(P.S.: this is not related to the latest SST changes)
Change-Id: I5a274072dbbc336494a0802ff7e80f0bf0b51813
For the case when ptime sample requests > than the DlbBuffer is.
Actually normal rates (e.g. PCMA/PCMU) have 20ms (ca. 160bytes),
even if the ptime would be 100ms, which is unusual, the size
requested per sample would be ca 1600bytes.
`AmAudio::samples` are `DblBuffer` based,
which has size of `AUDIO_BUFFER_SIZE * 2`, but it's not
contiguous, but exposes only half of it at a time through
the `unsigned char*` overloading operator.
Add the main guard in `AmAudio::get()`, who calculates the actual size
to be requested from the buffer to read into.
Additionally (actually less effective) prevent also overflow
in the implementation itself in `AmAudioFile::read()`, this is where
the `fread()` happens. Just for the case if the path towards it
is different in any other case.
Change-Id: Ifd381f4435f0a16ecee5612da41ea9046f6d22a4
When parsing SDP and not being in the path
of the media stream, `fingerprint` and `setup`
aren't considered as generic attributes and
are parsed into the dedicated SdpMedia fields.
So when preparing SDP to be printed and
to be sent out, take them also into account.
(Looks like was missed when reworking stuff
last time around media processing)
Change-Id: I48437d3587321a04395b70823207292590ea6523
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
For the case when the remote side doesn't explicitly state
it supports the `timer` SIP extension with `Supported: timer`,
try to fallback to `Require: timer` which is a guarantee for the case
with the UAC responsible for the SST timers.
Also add this fallback for the case with requests, e.g. when
UPDATE comes from the remote side to SEMS, and doesn't explicitly
declare the timers support with `Supported: timer` but still adds
the `Require: timer` one (most probably with UAS as a refresher).
Change-Id: Ic2ea79352535413568e4e3e9481cff1a29e43d7a
Normal shutdown already triggers the `clearRtpReceiverRelay()`
in `AmB2BSession::onBeforeDestroy()`, so the destructor should
actually normally see `media_session` ptr nulled.
But it seems in some of the fork/transfer related scenarios
this doesn't happen.
So adding the defensive clean-up on the same manner
the destructor of the `CallLeg` has (it uses the `releaseMediaSession()`,
which is essentially the same: `stop()`; `releaseReference()` and NULLing),
makes it consistent with these other_legs cleanup.
The main reason is caused by a call leg (`AmB2BSession`), which was freed
while the `AmB2BMedia::a` / `AmB2BMedia::b` still points to it.
In this case we can crash during the media-thread DTMF processing.
This fix is a hardening rather than a fix of the root cause.
The root cause still is related to the cleanup path:
certain call leg gets torn down through the path that skips (or maybe even races)
the normal `onBeforeDestroy()`/`clearRtpReceiverRelay()` cleanup,
leaving its shared `AmB2BMedia` with a dangling `a` or `b` pointer.
Meanwhile the `a` / `b` are raw, non-owned pointers, which may remain dangling.
Change-Id: Ia1ee42a27014d2086b37a787f8555e6d7681d4a8
Introduce a pair of getter and setter.
Then use them to appeal to `AmSessionTimerConfig::StrictMode`.
Then move the `AmSessionTimerConfig::StrictMode` to private
scope for incapsulation reasons, this is now possible
because of having the getter and setter.
Change-Id: I1cf6d9bbb30be925b8b885b36cbc123a96d334cb
Upon sending request/reply (`SessionTimer::onSendRequest()` /
`SessionTimer::onSendReply()`) don't re-append `Session-Expires`
(and rest of timer related headers) if this leg doesn't actually
support them.
Appending them may just confuse remote side and it may
act strictly and drop the call (e.g. remote side didn't explicitly
declare it supports timers, but we still sent it `Session-Expires`).
By default we always assume that remote side supports SST timers,
unless not proved the opposite with absent SST related headers
in any first seen 200OK or INVITE/UPDATE request. Then it gets
disabled. This policy is quite explicit and allows to gracefully
step back from SST scheduling, if remote side doesn't support timers.
Change-Id: I8581418c60bde912e01e2429844720dc19034c81
Make both `updateTimer()` overloads be returning true/false,
this will allow to react on the func caller's side to act
accordingly whenever required.
Change-Id: Iba6bfa6b21e74d657652c649064fe0a93ad6f1eb
Check also for requests (as well as for answers) that B2B's profile
actually supports timers, before to proceed with processing.
Change-Id: If86ab5a546040781715812eb882fbdb314462078
Just by default construct as true.
By default we always assume that remote side supports SST timers,
unless not proved the opposite with absent SST related headers
in any first seen 200OK or INVITE/UPDATE request.
Then it gets disabled.
This policy is quite explicit and allows to gracefully
step back from SST scheduling, if remote side doesn't support timers.
Change-Id: I422c76c42d44bcf2e775ffb9afa5842a9def1402
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
Only for UPDATE method for now, track whether remote side
actually declares it supports timers, if not remove.
This may affect things, in case remote side expects timers
should have been declared only once during the session
origination, but all in all remote side must always add
the `Supported: timer` header to keep us explicitly aware.
Additionally: improve logs.
Change-Id: I80d4efbe38701b95549d02830392b93019cc2b85
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
add B2B SBC integration test suite (port from sems-pbx)
Port the 20-test B2B suite from sems-pbx. CE-specific differences:
- sip_port=5062 (avoids conflict with orphaned sockets on :5060)
- default_bl_ttl=0 in t/b2b.conf (disables destination blacklisting
so a 503 response in one test does not block subsequent tests)
- no g729 in load_plugins (codec not present in CE)
- plugin_config_path requires trailing slash
- 100 response matched as "100 [^\r]+" (CE sends "100 Connecting"
instead of "100 Trying")
sems_tester.py: add makeUACSocket/makeUASSocket, recvSIP, recvFromSIP,
sendToSIP, assertSIP helpers; create t/run/ in setUpClass; clean up
PID file in tearDownClass; skip testPreload when rtpe-preload.so is
not loaded.
testEarlyCancelRace: use 10 s socket timeout with inner try/except
so the test passes on loaded CI machines where BYE may arrive late.
Change-Id: Iecb563dee6a27cf46b9883c42154a4486b3f6429
Internally the parsing still happens on pointers, but the externally
visible function will be using string_view eventually, when all other
users are converted.
Change-Id: I87d3be9e41fd96f656ce242edc1c403425f3eb65
If the `postDtmfEvent()` doesn't acquire the ownershop
over the allocated event, then no one actually takes care
to release it.
Modify func to return true/false, and react accordingly
on the caller's side.
Change-Id: If683eeba275d71850f67d961e9a1cdefe3fe6619
In case the override func of virtual `onStop()`
anyhow reaches the AmSession again, and falls into
the scope where the same mutex lock is used (snapshot_lock)
this will be a dead-lock.
Hence preserve such, but manually managing the lock,
and release it, when calling the virtual func.
Change-Id: I7c7c4700767dd3aed1c482559be02e3a97cca407
No need to do local copy operations, because:
- local copy on stack created
- then another copy on stack created when returning
So this does two copy operations.
Instead just do one during return, this is still covered
with the lock guard.
Additionally: split `getMaxSessionNum()` into getter
and setter, because the name is misleading now.
Hence those callers, who want to get the max session number,
are obligated to also update to the new value.
Change-Id: Icc775d9236d5c80de829c55638e1da47ae095289
In some of the usages of manual lock/unlock,
an exception can leave the mutex locked.
So the guard should fit this better.
Change-Id: I3541abe7a0ec63edffe1e180c691531cabb3fccd
If stop bookkeeping is ever called twice or
without a successful start, it wraps to a huge value,
because the `session_num` is `unsigned int`.
Just a guard and throw a warning accordingly,
when 0 is reached.
Change-Id: Ic9cef4aa7ae827fc8ce68808a2e6f5753697ebbb
Out of the `SESSION_THREADPOOL` def block,
because actually used not only with it
(see implementation .cpp file).
Change-Id: I84549ea185b660cdde7619de3ddf5c5034bccfd1
Automatic memory management and less error prone as it avoids manual
pointer manipulations.
No functional change.
Change-Id: Id35f4e4dc8918436589001db4acdf55ff9c60e5f