-
Notifications
You must be signed in to change notification settings - Fork 84
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
Correctly update local media format ids to match those in the offer #498
Conversation
Here is text from https://www.rfc-editor.org/rfc/rfc3264#page-10:
So the same payload number SHOULD be used, but is not mandatory. Better to fix the bug now and then, if someone has time, make numbering match the offer. |
Tested the PR also against Linphone and it worked fine. |
Works also against Grandstream Wave. |
I think we should keep the old behavior, maybe this (untested) could fix the bug: diff --git a/src/sdp/media.c b/src/sdp/media.c
index 6171ffcc..e2efff30 100644
--- a/src/sdp/media.c
+++ b/src/sdp/media.c
@@ -260,6 +260,7 @@ void sdp_media_align_formats(struct sdp_media *m, bool offer)
{
struct sdp_format *rfmt, *lfmt = NULL;
struct le *rle, *lle;
+ int pt_offer = RTP_DYNPT_START;
if (!m || m->disabled || !sa_port(&m->raddr) || m->fmt_ignore)
return;
@@ -307,6 +308,7 @@ void sdp_media_align_formats(struct sdp_media *m, bool offer)
rfmt->ref = lfmt->ref;
+ /* Use payload type from offer - RFC3264 - 6.1 */
if (offer) {
mem_deref(lfmt->id);
lfmt->id = mem_ref(rfmt->id);
@@ -314,11 +316,13 @@ void sdp_media_align_formats(struct sdp_media *m, bool offer)
list_unlink(&lfmt->le);
list_append(&m->lfmtl, &lfmt->le, lfmt);
+ if (lfmt->pt > pt_offer)
+ pt_offer = lfmt->pt;
}
}
+ /* Move unsupported codecs to the end of the list and recalculate pt */
if (offer) {
-
for (lle=m->lfmtl.tail; lle; ) {
lfmt = lle->data;
@@ -326,6 +330,12 @@ void sdp_media_align_formats(struct sdp_media *m, bool offer)
lle = lle->prev;
if (lfmt && !lfmt->sup) {
+ if (lfmt->pt >= RTP_DYNPT_START) {
+ mem_deref(lfmt->id);
+ lfmt->pt = ++pt_offer;
+ re_sdprintf(&lfmt->id, "%i", lfmt->pt);
+ }
+
list_unlink(&lfmt->le);
list_append(&m->lfmtl, &lfmt->le, lfmt);
} |
Sebastian Reimers writes:
I think we should keep the old behavior, maybe this (untested) could
fix the bug:
I can test tomorrow. By the way, does answer from baresip now include all
matching codecs with matching ids and order or only one codec:
```
Although the answerer MAY list the formats in their desired order of
preference, it is RECOMMENDED that unless there is a specific reason,
the answerer list formats in the same relative order they were
present in the offer. In other words, if a stream in the offer lists
audio codecs 8, 22 and 48, in that order, and the answerer only
supports codecs 8 and 48, it is RECOMMENDED that, if the answerer has
no reason to change it, the ordering of codecs in the answer be 8,
48, and not 48, 8.
```
|
Thanks for the diff. I made some tests and it worked OK. One thing that I noticed is that when re-INVITE is sent, all codecs are included on the m-line, which in my opinion is not necessary especially when the order is not correct. For example, when initial INVITE has
response correctly has
Now when answerer sends re-INVITE, also other codecs that answerer supports are included:
The first four are the common ones from the initial exchange and the rest are the ones that only the answerer supports. However their order is not the one has been defined in answerer's accounts file:
For example, AMR-WB should be the first extra codec, but it is the last. My suggestion is to use in the re-INVITE only those codecs that were in the initial exchange. |
If it is too difficult to use in re-INVITE only codecs of the initial exchange, then maybe the order of the extra codecs could be fixed by not starting from the tail:
|
My understanding from 8 Modifying the Session is that re-INVITE could simply use the codecs that are defined in the accounts file of the sender, i.e., full set in given order as long as ids of common codecs are the ones used in the initial exchange. |
So my suggestion is to remove these two lines:
|
By the way, while testing this, I noticed and when baresip puts audio only call on hold by |
FOREACH_STREAM
stream_hold(le->data, hold); What I remember is that "call on hold" is not mentioned specially in RFC. And there a different way to implement this. Most implementations tell the remote to be quiet and receive e.g. a hold-the-line music. Changes of the video stream are completely application dependent. Baresip has no hold-the-line music and does not send anything to the remote during local call-on-hold. In stream.c function if (s->hold)
return 0; So, baresip does not send video to the remote while the call is on-hold locally. I suggest not to change this behavior. Also baresip tells the remote that it does not want to receive video during local on-hold. Maybe we should also not change this behavior. Your other questions: Maybe @sreimers has more insights to answer these? |
This PR does not change on-hold behavior. |
@sreimers How does the PR now look to you? It simplifies your diff by keeping the original codec set, but takes pt ids from the initial offer. The result should be fully RFC 3264 compliant. |
If you remove these lines, unsupported codecs are come first in answer (since matched ones are re-added). I think there is a reason for this (maybe faster codec negotiation), maybe @alfredh can clarify. The code is >10 years old, changing this behavior can lead to problems. Maybe |
Sebastian Reimers writes:
> if (lfmt && !lfmt->sup) {
> + if (lfmt->pt >= RTP_DYNPT_START) {
> + mem_deref(lfmt->id);
> + lfmt->pt = ++pt_offer;
> + re_sdprintf(&lfmt->id, "%i", lfmt->pt);
> + }
> +
> // list_unlink(&lfmt->le);
> // list_append(&m->lfmtl, &lfmt->le, lfmt);
> }
If you remove these lines, unsupported codecs are come first in answer
(since matched ones are re-added). I think there is a reason for this
(maybe faster codec negotiation), maybe @alfredh can clarify. The code
is >10 years old, changing this behavior can lead to problems.
See the PR as it is now. I forgot to mention that I also changed the
for loop to start from head.
The > 10 years code has a bug that needs to be fixed. All that should
matter is that after the fix the code conforms to the RFC.
|
So just to clarify, this PR causes re-INVITEs to use the original local codecs in the original order. Only ids of codecs are changed, since they must match those in the initial offer:
|
@sreimers @cspiel1 |
Maybe we can re-add the old behavior. Can you test if my initial proposal works #498 (comment)? |
I'm a bit lost on which version of media.c #498 (comment) should be applied to. |
Can you provide diff to the current version of media.c? |
diff --git a/src/sdp/media.c b/src/sdp/media.c
index 428ba4ef..8c64eb00 100644
--- a/src/sdp/media.c
+++ b/src/sdp/media.c
@@ -313,24 +313,32 @@ void sdp_media_align_formats(struct sdp_media *m, bool offer)
mem_deref(lfmt->id);
lfmt->id = mem_ref(rfmt->id);
lfmt->pt = atoi(lfmt->id ? lfmt->id : "");
+
+ list_unlink(&lfmt->le);
+ list_append(&m->lfmtl, &lfmt->le, lfmt);
if (lfmt->pt > pt_offer)
pt_offer = lfmt->pt;
}
}
- /* Recalculate pt of unsupported codecs */
+ /* Recalculate pt and reorder unsupported codecs */
if (offer) {
- for (lle=m->lfmtl.head; lle; lle=lle->next) {
+ for (lle = m->lfmtl.tail; lle;) {
lfmt = lle->data;
- if (lfmt && !lfmt->sup)
+ lle = lle->prev;
+
+ if (lfmt && !lfmt->sup) {
if (lfmt->pt >= RTP_DYNPT_START) {
mem_deref(lfmt->id);
lfmt->pt = ++pt_offer;
re_sdprintf(&lfmt->id, "%i", lfmt->pt);
}
+ list_unlink(&lfmt->le);
+ list_append(&m->lfmtl, &lfmt->le, lfmt);
+ }
}
}
} |
Thanks, now the answer has correct codec order. I'll check id conflicts
tomorrow.
|
I made the tests described in baresip/baresip#2073 and they worked fine, i.e., no codec id conflicts. I'll create PR based on the above diff. |
Before this patch, when offer was received, local id of common media was changed to match that in the offer. As result, the id could conflict with some other local media id.
I don't see a need for the id change. Since this is a very serious bug, my suggestion is to the merge this PR. If someone thinks the id needs to be changed then he/she can make another PR that fixes the conflict.
After this PR, the re-INVITE test of baresip/baresip#2073 worked fine.