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

Call Timeout bug fix/discussion #439

Open
mikaelwills opened this issue May 13, 2024 · 5 comments
Open

Call Timeout bug fix/discussion #439

mikaelwills opened this issue May 13, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@mikaelwills
Copy link
Contributor

Ive come across a possible bug and also made a fix but want to discuss first to see if my assumptions are correct or if there's something else causing the issue, Im using a 3cx Server.

In a nutshell, if i make a call between two dart-sip-ua clients but don't accept the call, letting it ring and time out, the client that made the call receieves a 200 OK, CallStateEnum is set to confirmed and it behaves like the call was accepted.

Whether the remote client accepts or lets the call timeout, the local client always receives a 200 OK from 3cx.
In digging into the RFC standards it seems like the UAS should be sending a 408 back if the call timed out not a 200 OK?

Heres my fix but it would be great if someone with more experience with SIP flow could point out if this is would be the right way to handle it.

What ive found is the difference between an accepted 200 and a timed out 200 is the m=audio tag in the SDP.
In an accepted 200 the audio field is: m=audio 56189 UDP/TLS/RTP/SAVPF which has a media stream port of 56189.
In a timed out 200 the audio field is: m=audio 0 UDP/TLS/RTP/SAVPF which has a media stream port of 0 which i believe is it indicating there is no audio stream.

On line 2404 in _receiveInviteResponse() in rtc_session.dart
Along with checking if the response.body is null or is empty indicating there is a missing SDP, ive also pulled out the media port from the SDP and if that is 0 also terminate the call and set it to failed.
With this fix it fixes the bug in my situation and when the remote doesnt accept the local behaves properly.

My overall questions are.. is 3cx sending incorrect SIP messages back for the situation, is this a bug of 3cx and not of the dart sip-ua package meaning this fix shouldn't be added?

@mikaelwills mikaelwills added the bug Something isn't working label May 13, 2024
@silverspluussh
Copy link

Ive come across a possible bug and also made a fix but want to discuss first to see if my assumptions are correct or if there's something else causing the issue, Im using a 3cx Server.

In a nutshell, if i make a call between two dart-sip-ua clients but don't accept the call, letting it ring and time out, the client that made the call receieves a 200 OK, CallStateEnum is set to confirmed and it behaves like the call was accepted.

Whether the remote client accepts or lets the call timeout, the local client always receives a 200 OK from 3cx. In digging into the RFC standards it seems like the UAS should be sending a 408 back if the call timed out not a 200 OK?

Heres my fix but it would be great if someone with more experience with SIP flow could point out if this is would be the right way to handle it.

What ive found is the difference between an accepted 200 and a timed out 200 is the m=audio tag in the SDP. In an accepted 200 the audio field is: m=audio 56189 UDP/TLS/RTP/SAVPF which has a media stream port of 56189. In a timed out 200 the audio field is: m=audio 0 UDP/TLS/RTP/SAVPF which has a media stream port of 0 which i believe is it indicating there is no audio stream.

On line 2404 in _receiveInviteResponse() in rtc_session.dart Along with checking if the response.body is null or is empty indicating there is a missing SDP, ive also pulled out the media port from the SDP and if that is 0 also terminate the call and set it to failed. With this fix it fixes the bug in my situation and when the remote doesnt accept the local behaves properly.

My overall questions are.. is 3cx sending incorrect SIP messages back for the situation, is this a bug of 3cx and not of the dart sip-ua package meaning this fix shouldn't be added?

if it won't be a problem can i you post the fix code below. I am currently encountering similar errors with the latest dart sip ua

@mikaelwills
Copy link
Contributor Author

mikaelwills commented Jun 20, 2024

Ya sure, just be careful that im not sure if this is a 'fix' or not. I'm putting together a pull request soon which will include other things and a lot of infrastructure to support upgrading a call from audio to video so i might end up putting this in that.

But with this 'fix' in ive noticed that somtimes when making a call it fails because this port is.
What I want to try figure out... in those situations where im trying to make a call (not waiting for a response like in the original scenario) is it kinda normal to see a mediaPort of 0 before maybe a new message comes through with the media port assigned so is this fix shooting myself in the foot unneccesarily so to speak in a call that would other wise work normally.

but this is the 'fix' (i keep using the airquote cause i dont know if its actually a fix ha) starting on line 2463 of rtc_session.dart (unless ive changed other things and the lines dont match up with yours, but its inside _receiveInviteResponse()

} else if (utils.test2XX(status_code)) {
      dynamic mediaPort = response.sdp?['media'][0]['port'] ?? 0;
      logger.d('200 receieved with media port: $mediaPort');

      if (response.body == null || response.body!.isEmpty || mediaPort == 0) {
        print('\n Call failed mediaport: $mediaPort\n');
        _acceptAndTerminate(response, 400, DartSIP_C.CausesType.MISSING_SDP);
        _failed(
            'remote',
            null,
            null,
            response,
            400,
            DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION,
            'Missing SDP ${mediaPort == 0 ? "No media stream port" : ""}');
        return;
      }
      ```

@silverspluussh
Copy link

okay thanks .Let me try as a fix. Will give feedback

@silverspluussh
Copy link

Ya sure, just be careful that im not sure if this is a 'fix' or not. I'm putting together a pull request soon which will include other things and a lot of infrastructure to support upgrading a call from audio to video so i might end up putting this in that.

But with this 'fix' in ive noticed that somtimes when making a call it fails because this port is. What I want to try figure out... in those situations where im trying to make a call (not waiting for a response like in the original scenario) is it kinda normal to see a mediaPort of 0 before maybe a new message comes through with the media port assigned so is this fix shooting myself in the foot unneccesarily so to speak in a call that would other wise work normally.

but this is the 'fix' (i keep using the airquote cause i dont know if its actually a fix ha) starting on line 2463 of rtc_session.dart (unless ive changed other things and the lines dont match up with yours, but its inside _receiveInviteResponse()

} else if (utils.test2XX(status_code)) {
      dynamic mediaPort = response.sdp?['media'][0]['port'] ?? 0;
      logger.d('200 receieved with media port: $mediaPort');

      if (response.body == null || response.body!.isEmpty || mediaPort == 0) {
        print('\n Call failed mediaport: $mediaPort\n');
        _acceptAndTerminate(response, 400, DartSIP_C.CausesType.MISSING_SDP);
        _failed(
            'remote',
            null,
            null,
            response,
            400,
            DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION,
            'Missing SDP ${mediaPort == 0 ? "No media stream port" : ""}');
        return;
      }
      ```

thanks for the solution. However it may not be the solution to the issue on my code. here is my debug error:
I/flutter (31722): [2024-06-20 13:59:44.262] Level.debug sip_ua_helper.dart:263 ::: call failed with cause: Code: [488], Cause: WebRTC Error, Reason: SetRemoteDescription(offer) failed
I/flutter (31722): [2024-06-20 13:59:44.264] Level.error rtc_session.dart:652 ::: emit "peerconnection:setremotedescriptionfailed" [error:Unable to RTCPeerConnection::setRemoteDescription: peerConnectionSetRemoteDescription(): WEBRTC_SET_REMOTE_DESCRIPTION_ERROR: Failed to set remote offer sdp: Called with SDP without DTLS fingerprint.]

@mikaelwills
Copy link
Contributor Author

Ya sure, just be careful that im not sure if this is a 'fix' or not. I'm putting together a pull request soon which will include other things and a lot of infrastructure to support upgrading a call from audio to video so i might end up putting this in that.
But with this 'fix' in ive noticed that somtimes when making a call it fails because this port is. What I want to try figure out... in those situations where im trying to make a call (not waiting for a response like in the original scenario) is it kinda normal to see a mediaPort of 0 before maybe a new message comes through with the media port assigned so is this fix shooting myself in the foot unneccesarily so to speak in a call that would other wise work normally.
but this is the 'fix' (i keep using the airquote cause i dont know if its actually a fix ha) starting on line 2463 of rtc_session.dart (unless ive changed other things and the lines dont match up with yours, but its inside _receiveInviteResponse()

} else if (utils.test2XX(status_code)) {
      dynamic mediaPort = response.sdp?['media'][0]['port'] ?? 0;
      logger.d('200 receieved with media port: $mediaPort');

      if (response.body == null || response.body!.isEmpty || mediaPort == 0) {
        print('\n Call failed mediaport: $mediaPort\n');
        _acceptAndTerminate(response, 400, DartSIP_C.CausesType.MISSING_SDP);
        _failed(
            'remote',
            null,
            null,
            response,
            400,
            DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION,
            'Missing SDP ${mediaPort == 0 ? "No media stream port" : ""}');
        return;
      }
      ```

thanks for the solution. However it may not be the solution to the issue on my code. here is my debug error: I/flutter (31722): [2024-06-20 13:59:44.262] Level.debug sip_ua_helper.dart:263 ::: call failed with cause: Code: [488], Cause: WebRTC Error, Reason: SetRemoteDescription(offer) failed I/flutter (31722): [2024-06-20 13:59:44.264] Level.error rtc_session.dart:652 ::: emit "peerconnection:setremotedescriptionfailed" [error:Unable to RTCPeerConnection::setRemoteDescription: peerConnectionSetRemoteDescription(): WEBRTC_SET_REMOTE_DESCRIPTION_ERROR: Failed to set remote offer sdp: Called with SDP without DTLS fingerprint.]

Ah yep the SDP coming from your SIP server didnt include a DTLS fingerprint, what server are you using? You need to go onto it and enable DTLS/SRTP on each extension

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants