Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support forking SIP calls #227

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

alexdowad
Copy link

When a SIP call is forked, the client will send an INVITE with the same Call ID and same From tag as an earlier INVITE, but with a different Branch ID in the topmost Via header.

There were two issues with sofia-sip which prevented it from handling multiple INVITE requests for forked SIP calls; first, its logic for merging SIP requests (as per RFC3261 section 8.2.2.2) did not respect the Branch ID. It would merge requests with a different Branch ID, which is contrary to RFC3261 section 17.2.3.

Second, sofia-sip has some logic for checking whether incoming requests are part of an established SIP dialog or not. The matching criteria were such that incoming INVITE requests for forked calls would be treated as part of the already established dialog, and then an error would be returned to the client, essentially telling the client that this new INVITE is invalid because the call is already established.

Therefore, add some extra matching conditions which ensure that an INVITE establishing a forked call will not be treated as part of the previously established call leg. The matching conditions are as specific as possible, to minimize the chances of unintentionally affecting how other types of SIP messages are handled.

Implementing these new matching conditions can only be done by recording the Branch ID for established calls, so we can check whether another INVITE which comes later has the same Branch ID or a different one. This requires adding a new member to nta_leg_s.

My goal here is to allow FreeSWITCH (via mod_sofia) to be able to successfully proxy INVITE requests for forked SIP calls, when both destinations of the forked call are behind the same FreeSWITCH instance. However, it also means that all other users of libsofia will potentially be able to handle forked calls as well.

@jvarruda
Copy link

Great work @alexdowad

@andywolk how we can have this reviewed?

@ncopa
Copy link
Contributor

ncopa commented Aug 25, 2023

Will this also fix #211?

@alexdowad
Copy link
Author

Will this also fix #211?

Yes, it will.

algitbot pushed a commit to alpinelinux/aports that referenced this pull request Aug 28, 2023
algitbot pushed a commit to alpinelinux/aports that referenced this pull request Aug 28, 2023
algitbot pushed a commit to alpinelinux/aports that referenced this pull request Aug 28, 2023
algitbot pushed a commit to alpinelinux/aports that referenced this pull request Aug 28, 2023
algitbot pushed a commit to alpinelinux/aports that referenced this pull request Aug 28, 2023
@jvarruda
Copy link

As suggested in the last FS Community Call please find attached a sipp scenario that can be used to see the problem before the patch and it working after the patch.

That scenario assumes you have 2 extensions registered in FS (1234 and 1235).

An INVITE is sent to 1234 and after 10 seconds ringing (do not answer it) it will fork the call to 1235 (new INVITE with a different branch parameter in Via header) and later CANCEL the original INVITE.

Before the proposed patch you will see that the second INVITE will be replied with SIP/2.0 482 Request merged
Debug log shows: nta.c:3102 agent_recv_request() nta: INVITE (1) is a merged request

After applying the proposed patch the second INVITE will be processed as as expected.

sipp-sofia-sip.xml.txt

@@ -4316,6 +4319,7 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
su_home_t *home;
url_t *url;
char const *what = NULL;
sip_via_t *via = NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sip_via_t *via = NULL;
const sip_via_t *via = NULL;

To fix the following build error with gcc 14:

nta.c: In function 'nta_leg_tcreate':
./../sip/sofia-sip/sip_tag.h:340:57: error: passing argument 1 of 'siptag_via_vr' from incompatible pointer type [-Wincompatible-pointer-types]
  340 | #define SIPTAG_VIA_REF(x) siptag_via_ref, siptag_via_vr(&(x))
      |                                                         ^~~~
      |                                                         |
      |                                                         sip_via_t ** {aka struct sip_via_s **}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is done, thanks!

When a SIP call is forked, the client will send an INVITE with the
same Call ID and same From tag as an earlier INVITE, but with a
different Branch ID in the topmost Via header.

There were two issues with sofia-sip which prevented call forking from
working; first, its logic for merging SIP requests (as per RFC3261
section 8.2.2.2) did not respect the Branch ID. It would merge requests
with a different Branch ID, which is contrary to RFC3261 section 17.2.3.

Second, sofia-sip has some logic for checking whether incoming requests
are part of an established SIP dialog or not. The matching criteria
were such that incoming INVITE requests forking a call would be
treated as part of the already established dialog, and then an error
would be returned to the client, essentially telling the client that
this new INVITE is invalid because the call is already established.

Therefore, add some extra matching conditions which ensure that an
INVITE forking a call will not be treated as part of the previously
established call leg. The matching conditions are as specific as
possible, to minimize the chances of unintentionally affecting how
other types of SIP messages are handled.

Implementing these new matching conditions can only be done by
recording the Branch ID for established calls, so we can check whether
another INVITE which comes later has the same Branch ID or a different
one. This requires adding a new member to nta_leg_s.

Co-Authored-By: João Arruda <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants