I have a somewhat simple, but specific, question about implementing the transport layer for a SIP UAC.
Do I expect the response to a request on the same socket that I sent the request on, or do I let the UDP or TCP listener pick up the response and then route it to the correct transaction from there? The RFC does not seem to say anything on the matter.
It seems that especially using UDP, which is connection-less, that I should just let the listeners pick up the response, but that seems sort of counter intuitive. Particularly, I have seen plenty of UAC implementations which do not depend on having a Listener in the transport layer.
Also, most implementations I have looked at do not have the UAS receiving loop responding on the socket at all. This would tend to indicate that the client should not be expecting a reply on the socket that it sent the request on.
For clarification:
Suppose my transport layer consists of the following elements:
TCPClient (Sends Requests for a UAC via TCP)
UDPClient (Sends Requests for a UAC vid UDP)
TCPSever (Loop receiving Requests and dispatching to transaction layer via TCP)
UDPServer (Loop receiving Requests and dispatching to transaction layer via UDP)
Obviously, the *Client sends my Requests. The question is, what receives the Response? The *Client waiting on a recv or recvfrom call on the socket it used to send the request, or the *Server?
Conversely, the *Server receives my requests, What sends the Response? The *Client? doesn’t this break the roles of each member a bit?
Update
I did a packet capture on an SIP Invite transaction between Ekiga and a PolyCom server. Ekiga was the client, and the polycom was the server. In the invite request Ekiga used port 5060 in the via header. 5060 is the port that its UAS is listening on, so that would seem to indicate that the UDPServer is receiving the responses to all requests and not the UDPClient that sent the request. Is this valid reasoning?
8
On reading section 18 of RFC3261 about the transport layer, it quite clearly states that the transport layer must be able to receive responses for a transaction on each of
- The TCP socket used for sending the request (
TCPClient
) - A new TCP connection to the address that the request was sent from and the port number as advertised in the ‘sent-by’ field of the ‘Via’ header (
TCPServer
on sending IP address) - A new TCP connection to where the UA is normally listening for new transactions (
TCPServer
) - An UDP datagram on the address that the request was sent from and the port number as advertised in the ‘sent-by’ field of the ‘Via’ header (
UDPServer
on sending IP address) - An UDP datagram where the UA is normally listening for new transactions (
UDPServer
)
So, basically only the UDPClient
can’t receive responses.
As for sending responses, when the request came in on a reliable transport (TCP), try to use the same socket for the response.
If that is not possible, open a new connection as if you are sending an entirely new message. That should give the least surprises.
Regarding the *Server
and *Client
roles: Usually, the Client sends requests and receives responses, while the server receives requests and sends responses. However, for UDP this model does not really work. There you might go for the model that the Client sends datagrams, while the server receives datagrams (independent of whether they are requests or responses).
3
When I did my sip stack I build all the messages in the transport layer and than passed them up to the next layer which had to identify the correct transactions.
Doing so also makes everything easier to test.
8