Consider this sample SIP dialog
A-->--INVITE-->--B CSeq 101
A--<--TRYING--<--B CSeq 101
A--<--200 OK--<--B CSeq 101
A-->-- ACK -->--B CSeq 101
A-->-- INFO -->--B CSeq 2
A--<-- 500 --<--B CSeq 2
...
While working on a SIP handling code, we put a validation for CSeq of a SIP INFO message for a dialog to be greater than the one sent for the INVITE.
However, as shown in the above SIP flow, one of the remote SIP gateways is sending it to be lower, ie 2 instead of the expected 102 or higher.
The RFC https://www.ietf.org/rfc/rfc3261.txt states that
Requests within a dialog MUST contain strictly monotonically
increasing and contiguous CSeq sequence numbers (increasing-by-one) in
each direction
So, is the observed behavior a violation of the RFC?
Yes, it is. You paraphrased the correct text.
The RFC on SIP INFO messages states CSeq header values follow the mechanism in RFC3261:
The Info Package mechanism does not define a delivery order
mechanism. Info Packages can rely on the CSeq header field [RFC3261]
to detect if an INFO request is received out of order.
However, keep in mind you can't rely on the received CSeq number being only one higher than the previously received one (https://www.rfc-editor.org/rfc/rfc3261#section-12.2.2):
It is possible for the
CSeq sequence number to be higher than the remote sequence number by
more than one. This is not an error condition, and a UAS SHOULD be
prepared to receive and process requests with CSeq values more than
one higher than the previous received request. The UAS MUST then set
the remote sequence number to the value of the sequence number in the
CSeq header field value in the request.
If a proxy challenges a request generated by the UAC, the UAC has
to resubmit the request with credentials. The resubmitted request
will have a new CSeq number. The UAS will never see the first
request, and thus, it will notice a gap in the CSeq number space.
Such a gap does not represent any error condition.
Related
I have a question about the contract on Stream API.
More specifically, I'm wondering why Stream.asyncMap is implemented not to break the order of elements in the stream.[1]
I guess there can be some cases where the order of elements is not kept on asyncMap.
For example, if I pass an asynchronous function with HTTP communication to a server where the response latency has large variance, the events might happen in order of (1) HTTP req is sent for the 1st element (2) HTTP req is sent for the 2nd element (3) HTTP res is received for the 2nd element and sent to the downstream (4) HTTP res is received for the 1st element and sent to the downstream. In this case, the output stream will be ordered as [res2, res1] for the shortest latency as a whole.
However, in fact, the implementation is intend this order: (1) HTTP req is sent for the 1st element and pause the subscription (2) HTTP res is received, it is added to the downstream, and the subscription is resumed (3) HTTP req is sent for the 2nd element and (4) HTTP res is received and sent to the downstream.
So I want to know the intention of this implementation. I guess there might be an official contract that Stream API must not break the order, but I'm not sure.
Any insight will be helpful, thanks!
I heard that websocket messages are received in order, because websocket runs over TCP.
Then what is the purpose of 'sequence number'?
This is the explanation of sequence number in websocket.
But I'm wondering why does that sequence number is needed, if we have a 'in-order' received message.
The sequence number allows you to map your requests to responses even if the responses don't come in the order you make them.
HTTP and other relevant protocols support pipelining. Also there is no need for the request responses to be sent back to you in any specific order. Each one may be processed according to its individual cost or dispatched across a server farm and reassembled in an order that is not predetermined. Either way, if they are out of order you will need a key to map the response back to your request.
This question is regarding the ACK request in SIP (Session Initiation Protocol). Quoting RFC-3261 - 18.1.1 Sending Requests
If an element sends a request over TCP because of these message size
constraints, and that request would have otherwise been sent over
UDP, if the attempt to establish the connection generates either an
ICMP Protocol Not Supported, or results in a TCP reset, the element
SHOULD retry the request, using UDP.
This looks OK for the INVITE and other non-invite request except ACK. Below are the points why i think the above statement may not be applicable for ACK.
ACK is just a request and not transaction. So the SIP transaction State Machine must not be applicable for ACK request. Since State Machine is the only place which talks about the retransmission, So the 18.1.1 is not applicable for ACK request. Quoting 3261 - "17.1 Client Transaction" - in favour for above argument.
There are two types of client transaction state machines, depending
on the method of the request passed by the TU. One handles client
transactions for INVITE requests. This type of machine is referred
to as an INVITE client transaction. Another type handles client
transactions for all requests except INVITE and ACK. This is
referred to as a non-INVITE client transaction. There is no client
transaction for ACK. If the TU wishes to send an ACK, it passes one
directly to the transport layer for transmission.
ACK can be re-transmissted only if next B-party retransmits the final response.
Q:- Is my assumption correct that SIP ACK request can not be retransmitted on receiving the transport error (such as connection error, ICMP error)?
Quoting 3261 - "17.1 Client Transaction" -
If the TU wishes to send an ACK, it passes one
directly to the transport layer for transmission.
Q:- What does TU wishes mean? Does it mean that TU can send any time it wish OR it means whenever final response come then only TU sends?
Regards,
Sudhansu
1) Let's go back to basic stuff
"If an element sends a request over TCP because of these message size
constraints, and that request would have otherwise been sent over
UDP, if the attempt to establish the connection generates either an
ICMP Protocol Not Supported, or results in a TCP reset, the element
SHOULD retry the request, using UDP."
My comments :-
"SHOULD retry the request" --> It says SHOULD retry not MUST retry request.
So this is not mandatory at all to send ACK request.
2)
Q:- Is my assumption correct that SIP ACK request can not be retransmitted on receiving the transport error (such as connection error, ICMP error)?
Quoting 3261 - "17.1 Client Transaction" -
If the TU wishes to send an ACK, it passes one directly to the transport layer for transmission.
comments :- This clearly states if TU ( Transaction user ) wishes to {not must} pass ACK request to transport layer for tranmission.
So as per statement, it's application wish that don't do anything once you pass that to ACK to transport layer. OR if on another side if application wants if there any TCP error (ICMP) then it can retransmit same ACK request over UDP.
See RFC will never exclude ACK from this, it is application responsibility & how it is implemented.
Also please can also ask question at Sip-implementors mailing list. You will get more like minded people.
First some clarifications. From [RFC3261 Section 6][1]:
SIP Transaction: A SIP transaction occurs between a client and a
server and comprises all messages from the first request sent
from the client to the server up to a final (non-1xx) response
sent from the server to the client. If the request is INVITE
and the final response is a non-2xx, the transaction also
includes an ACK to the response. The ACK for a 2xx response to
an INVITE request is a separate transaction
So an ACK to a non-2xx is part of the same transaction as the INVITE, any 1xx responses and the final response. In particular it has the same CSeq and the same branch tag. ACKs to non-2xx responses are hop-by-hop.
An ACK to a 2xx is a new transaction (although this is a special ACK transaction, and there are no responses). It has the same CSeq, but a different branch tag. ACKs to 2xx responses go all the way from the client to the server.
On your specific point, section 17 is about the transaction Layer. Here ACKs are only ever re-transmitted in response to a re-transmitted final response. When the Transaction Layer decides it needs to send an ACK, it sends it to the Transport Layer, and it is the Transport Layers job to deliver it.
Section 18 is about the Transport Layer. An ICMP error or a TCP reset are Transport Layer errors, they are not covered by the SIP transaction model. If the Transport Layer needs to promote a message from UDP to TCP, or to fall-back from TCP to UDP, that is separate from the Transaction Layers model. In fact, if the TCP socket cannot be established, the ACK has not been transmitted yet. In this case the Transport Layer isn't retransmitting it, it is attempting to transmit it for the first time, by a different protocol.
In practise, this case is going to be rare. For the size of the ACK to be a problem for UDP, it has to be larger then both the INVITE and the final response - these have already succeeded via UDP. In the usual case the INVITE and final response contain an SDP body; in every success case the 2xx contains a body. The only case where the ACK is going to be larger is if there was no SDP in the INVITE and the ACK adds to the headers or body.
If you hit this case - TCP not supported and ACKs too big for UDP, you may be heading for failure anyway.
[1]: https://www.rfc-editor.org/rfc/rfc3261#section-6
I am trying to implement Fix.4.2 protocol, but It is difficult to understand the message log I attached below. Here Logon(35=A) request was sent with MsgSeqNum(34=1) from client. Then for testing ResendRequest and SequenceReset session level messages I sent a NewOrderSingle request with MsgSeqNum=7 (instead of MsgSeqNum=2, as subsequent messages should have incremeted msgseqnum after logon request). As expected MsgSeqNum is too high than recieved one Fiximulator responded with a ResendRequest(35=2) to send from 2 to 0 (i.e., from 2 to 7). Here why the Fiximulator is not waiting for client's reply ? instead it is sending an heartbeat message. Why the client is sending ResendRequest in response to ResendRequest of Fiximulator instead of sending SequenceReset message ?.
Also explain remaining cases if possible.
Thanks in advance.
What is your status of ResetOnLogon in your config file for the acceptor ? Default value is N so it isn't being reset. Always check your config file or try debugging to figure out issues.
ResetOnLogon Determines if sequence numbers should be reset when recieving a logon request. Acceptors only
I'm reading the XEP-0124 / BOSH specification and do not understand the following sentence in chapter 9.1 Request Acknowledgements:
The only exception is that, after its
session creation response, the
connection manager SHOULD NOT include
an 'ack' attribute in any response if
the value would be the 'rid' of the
request being responded to.
In my words: I should not send an ACK if the respond is dedicated for the last and only request (in connection manager's queue).
But: There is a client with it's own state machine. Maybe the client already send a second request -- where the first one is not replied -- and expect to get two answers. In this case the client except a ACK with RID of the "older" request and the connection manager have to set ACK.
Conclusion: The connection mananager MUST set ACK as long multiple requests are allowed.
I'm not sure, but is this text paragraph dedicated only for the use case where no further request is send by the client but the session creation phase is finished successfully and the connection manager have to send "ping" messages to the client due to "wait" timeouts ?
So, as I read it:
If the highest RID (in sequence) that you have received is 11 (you might have received 14 after that, but it is out of sequence since 12 & 13 are missing), and you are responding on:
The same request, then you should not (it is recommended that you do not, but if you have a good reason to, then you may) send an 'ack' attribute.
An earlier held request (say RID 10) then you should set 'ack' to 11 since that is the highest in-sequence RID that you have received so far.
It's okay if the client sent multiple requests and the server doesn't yet know about them. This is because there is a chance that when the client sent 11, the server has no held connections and it will respond back on the same connection. In that case, there are 2 requests sent out (11 & 12), but the response for each one acks that same request since the server always has something to send back immediately.