< Previous by Date Date Index Next by Date >
< Previous in Thread Thread Index Next in Thread >

Re: [reSIProcate-users] Transmission to broken TCP connection


Title: RE: [reSIProcate-users] Transmission to broken TCP connection

A couple of monthes later ...

OK, now I've had time to look into this, and made a first approximation of a solution. Before tidying things up and fixing some things that don't scale well I would appreciate some feedback about the strategy, so the solution doesn't miss anything essential or creates problems for other parts of the stack.

What I have done is to let the ConnectionManager send a TransportFailure message whenever a read operation indicates an error. (A Tuple is added to TransportFailure, and the transaction ID is 0 in this situation.) I'm not sure if perhaps cases where the connection is closed in a controlled manner should be treated similarly - then the extra message is not necessary, as the ConnectionBase destructor sends a ConnectionTerminated.

When this message is handled by TransactionState another TransportFailure is created for all transactions in controller.mClientTransactionMap using the indicated connection, and are in states Calling or Trying. (As a side note I wonder a bit about why the code (processTransportFailure) does a failover in state Proceeding for INVITE transactions.)

For this solution to work transactions need to know which flow they are using, and that's currently not true in all cases, so I have also invented a FlowIndication message that is sent by TcpBaseTransport::processAllWriteRequests when it has selected a connection.

As the stack obviously does at least some of what the transaction user is supposed to do according to 17.1.4 of RFC 3261, the result will be an attempt at another DNS result, or a 503 result to the TU, and as far as I can see this is along the lines of the RFC.

Does this solution seem reasonable?

Rgds,
Mats


-----Original Message-----
From: Adam Roach [mailto:adam@xxxxxxxxxxx]
Sent: Thu 2009-10-15 17:23
To: Mats Behre
Cc: resiprocate-users@xxxxxxxxxxxxxxx; 'resiprocate-devel'
Subject: Re: [reSIProcate-users] Transmission to broken TCP connection

On 10/15/09 03:27, Oct 15, Mats Behre wrote:
>
> So, it seems that when the message is sent the read side detects that
> the connection is down (with a code that
> is unrecognised by TCP, but decoded as WSAECONNRESET in
> Transport::error), but it doesn't appear as if our
> application is notified.
> This may be kind of a grey area; RFC 3261 (18.4) specifies that if the
> result of sending a request
> is a connection failure, the transport user SHOULD be informed, and
> 17.1.4 says the the TU SHOULD
> be notified. I believe our application takes the role of the TU, and
> is responsible for further actions.
> Is this situation covered by "the result is a connection failure"? I
> think it can be argued that it is.
>
> The problem from our point of view is that it takes a long time
> (transaction timeout) before the application
> finds out about the failure. Is there anything we can do to avoid this?
>
[I'm copying the devel list on this, as it has recently come up there as
well]

This is a known shortcoming of the current TCP transport design.
Ideally, a socket failure on write would cause the TCP transport to
re-initiate a connection and re-attempt sending the message that failed
(with care not to get into a loop of try/fail/try/fail, ad infinitum).
If the second attempt fails, the transport should then inform the TU. I
haven't done any analysis to see how much work this would take, but it
sounds like a fairly easy fix -- unfortunately, I don't have any cycles
to work on it myself.

If you'd like to dig into things and propose a patch, I would start with
resip/stack/TcpTransport.{cxx,hxx} and
resip/stack/TcpBaseTransport.{cxx,hxx}.

/a