Giter VIP home page Giter VIP logo

Comments (6)

rj2Skipper avatar rj2Skipper commented on May 22, 2024

further information:
incoming requests DO NOT come from the same tcp-port as responses should be send to

I think the way(s) to go would be:

  • know the serverCertifcateName in SipTlsChannel.SendResponse for out of stream Responses
    or
  • use in stream Response if certficateName unknown

from sipsorcery.

sipsorcery avatar sipsorcery commented on May 22, 2024

It's been a while but I'm pretty sure the SIP standard specifies that when a request is received on a connect oriented protocol, such as TCP or TLS, the response must be sent on the same connection. If the connection gets closed before the response is sent that's an error condition.

For this specific issue the SIP responses on a TLS connection should always re-use the same connection the request was received on.

from sipsorcery.

rj2Skipper avatar rj2Skipper commented on May 22, 2024

Hey Aaron,
my understanding is also to reuse the connection, BUT the implementation of SIPTLSChannel/SIPTCPChannel does not do this.
My findings are:

  • OPTIONS Request from remote port 12345 to local port 5061
  • Via/From/Contact header contain remote port 5061
  • generate SipResponse through SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null)
  • Send Response with transport.SendResponse method...SIPTLSChannel.Send(IPEndPoint dstEndPoint, byte[] buffer, string serverCertificateName)
  • tlsChannel.m_connectedSockets does NOT contain dstEndpoint (dstEndpoint for SIPResponse is remoteServer:5061, but request originated from remoteServer:12345, why 12345 is stored in m_connectedSockets)
  • Send Method tries to Bind/Connect/Authenticate new TCP Connection with local port 5061
    (sometimes I get SocketException(0x80004005) in EndConnect when sending for local port 5061 "Only one usage of each socket address (protocol/network address/port) is normally permitted"
    Exception occurs often when multiple simultanous requests need to be answered)
  • After Authentication SIPResponse is sent to remote port 5061, this works but it's not how it should work
  • Behavior is the same if original SIPRequest Via contains "alias" parameter (RFC 5923)

from sipsorcery.

rj2Skipper avatar rj2Skipper commented on May 22, 2024

Hey Aaron,
After going to lunch and not thinking about anything else, I made another test with SIPSorcery code from Trunk, and found a different behavior (Response is sent on original connection)
Difference in source code is: DRUMROLLPLEASE Parsing Via Header of Request and Creating the Via header of the Response (and automatically identfying dstEndpoint from SIPResponse in succession).
original code: ctor contains line "ViaParameters.Set(m_rportKey, null);", mine does NOT with a comment refering to RFC 3581 and "DO NOT change orignal message or set rport parameter in VIA, if there is no rport parameter in SIPRequest"

so there it is: original SIPSorcery code ALWAYS changes the received Request, which is wrong in my opinion, but leads to the expected result.

While my code respects rport parameters in received SIPRequest, my misconception was to think the rport RFC applies to TCP as it does to UDP. I'm changing my SIPSorcery consumer now to use SipTransport.SendResponse(sipResponse) ONLY IF protocol is UDP or Via contains rport and look where it leads me (else i'm using SipTransport.SendResponse(dstEndpoint, sipResponse), and ONLY changing original received SIPRequest with hardcoded rport parameter in Via if remoteEndpoint.Port != Via.Port).

ciao Ralf

from sipsorcery.

sipsorcery avatar sipsorcery commented on May 22, 2024

"DO NOT change orignal message or set rport parameter in VIA, if there is no rport parameter in SIPRequest"

You're right that's what the spec says. If you look at line 1653 in SIPHeader.cs you'll see why I made the decision to always use rport:

/// The setting of the received parameter is documented in RFC3261 section 18.2.1 and in RFC3581
/// section 4. RFC3581 states that the received parameter value must be set even if it's the same as the
/// address in the sent from field. The setting of the rport parameter is documented in RFC3581 section 4.
/// An attempt was made to comply with the RFC3581 standard and only set the rport parameter if it was included
/// by the client user agent however in the wild there are too many user agents that are behind symmetric NATs
/// not setting an empty rport and if it's not added then they will not be able to communicate.

You are also correct that rport should not be used when a reliable transport channel is used. However, since the rport is only ever being set to the remote socket the SIP request was received from it's hard to envisage a case where the remote socket and rport won't match up. If the remote port used was 12345 then that's what should end up in the rport parameter. Yes technically rport shouldn't be used in this case but it ends up as the same effect.

from sipsorcery.

sipsorcery avatar sipsorcery commented on May 22, 2024

Even though I was pretty sure this wasn't an issue at the time thought I'd just double check. Below are the results from sending an OPTIONS request from a client behind NAT to a server on a static IP address using the TCP channel. The results show that the rport Via header parameter does get set and does not cause any issues. The OPTIONS response gets sent back on the same TCP connection as the request arrived on.

TCP:

Client

sipcmdline -d tcp:67.222.131.146
[19:14:13 DBG] RunCommand tcp:67.222.131.146
[19:14:13 DBG] SIP TCP Channel listener created 0.0.0.0:9060.
[19:14:13 DBG] SIPTCPChannel socket on tcp:0.0.0.0:9060 accept connections thread started.
[19:14:13 DBG] tcp:0.0.0.0:9060
[19:14:13 DBG] OPTIONS sip:67.222.131.146:5060;transport=tcp SIP/2.0
Via: SIP/2.0/TCP 0.0.0.0:9060;branch=z9hG4bK7ac1b044f9aa467d87bd0b1ed9ff35b7;rport
To: <sip:67.222.131.146:5060;transport=tcp>
From: <sip:0.0.0.0:9060;transport=tcp>;tag=YWLNAMPLUQ
Call-ID: 15cbb1e0872e4c2b9e17383757a291ac
CSeq: 1 OPTIONS
Contact: <sip:0.0.0.0:9060;transport=tcp>
Max-Forwards: 70
Allow: ACK, BYE, CANCEL, INFO, INVITE, NOTIFY, OPTIONS, REFER, REGISTER, SUBSCRIBE
Content-Length: 0


[19:14:13 DBG] ConnectAsync SIP TCP Channel connect completed result for 0.0.0.0:9060->67.222.131.146:5060 Success.
[19:14:13 DBG] Response received tcp:0.0.0.0:9060<-tcp:67.222.131.146:5060: OPTIONS 200 Ok
[19:14:14 DBG] SIP/2.0 200 Ok
Via: SIP/2.0/TCP 0.0.0.0:9060;branch=z9hG4bK7ac1b044f9aa467d87bd0b1ed9ff35b7;rport=50768;received=37.228.253.95
To: <sip:67.222.131.146:5060;transport=tcp>
From: <sip:0.0.0.0:9060;transport=tcp>;tag=YWLNAMPLUQ
Call-ID: 15cbb1e0872e4c2b9e17383757a291ac
CSeq: 1 OPTIONS
Allow: ACK, BYE, CANCEL, INFO, INVITE, NOTIFY, OPTIONS, REFER, REGISTER, SUBSCRIBE
Content-Length: 0


[19:14:14 INF] => Got correct response on send 1 of 1 in 769ms.
[19:14:14 DBG] Shutting down the SIP transport...
[19:14:14 DBG] Closing SIP TCP Channel tcp:0.0.0.0:9060.
[19:14:14 DBG] SIP stream disconnected tcp:67.222.131.146:5060 OperationAborted.
[19:14:14 DBG] SIPTCPChannel accepts for tcp:0.0.0.0:9060 cancelled.
[19:14:14 INF] => Command completed successfully.

Server

[13:14:14 DBG] SIP TCP Channel connection accepted from 37.228.253.95:50768.
[13:14:14 INF] tcp:0.0.0.0:5060<-tcp:37.228.253.95:50768: OPTIONS sip:67.222.131.146:5060;transport=tcp SIP/2.0
[13:14:14 DBG] OPTIONS sip:67.222.131.146:5060;transport=tcp SIP/2.0
Via: SIP/2.0/TCP 0.0.0.0:9060;branch=z9hG4bK7ac1b044f9aa467d87bd0b1ed9ff35b7;rport=50768;received=37.228.253.95
To: <sip:67.222.131.146:5060;transport=tcp>
From: <sip:0.0.0.0:9060;transport=tcp>;tag=YWLNAMPLUQ
Call-ID: 15cbb1e0872e4c2b9e17383757a291ac
CSeq: 1 OPTIONS
Contact: <sip:0.0.0.0:9060;transport=tcp>
Max-Forwards: 70
Allow: ACK, BYE, CANCEL, INFO, INVITE, NOTIFY, OPTIONS, REFER, REGISTER, SUBSCRIBE
Content-Length: 0

[13:14:14 DBG] SIP stream disconnected tcp:37.228.253.95:50768 ConnectionReset.

from sipsorcery.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.