1

I'm using Twisted to write a proxy server and I'm having issues with checking if a connection to the server was closed.

As it is now, I have

client <-> proxy <-> server

Testing with telnet, the proxy successfully passes messages from the client to the server, and passes the servers response back to the client. However, my issue is if the client issues a command to close the connection between the proxy and the server, the connection between the client and the proxy still remains.

Here is some of my code

    client_factory = protocol.ClientFactory()
    client_factory.protocol = ClientTelnetProtocol
    client_factory.proxy = self

    try: 
        clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        clientsocket.connect(('localhost', 1234))
        clientsocket.close()
        reactor.connectTCP('localhost', 1234, client_factory)
    except Exception as err:
        print(err)
        self.transport.loseConnection()

In the line

reactor.connectTCP('localhost', 1234, client_factory) 

I want to be able to monitor the state of the connection and see if the server closes it, possibly on dataReceived() or if possible, have set up an interrupt when the server closes the connection to the proxy, and have the proxy immediately close the connection to the client.

1 Answers1

1

ITransport will notify its IProtocol of the loss-of-connection event by calling connectionLost on the IProtocol provider. Therefore, if you want to react to that event, you should implement connectionLost on your protocol (ClientTelnetProtocol in this case, it appears?) and put your application logic in that method. This method is called as soon as the ITransport implementation knows the connection has been lost so it should serve your needs (note that it is not an interrupt because Twisted is a (largely) single-threaded cooperative multi-tasking system; so if you have application code that blocks (for example, clientsocket.connect) Twisted won't call any of your callbacks until that completes and the reactor regains control. But as soon as it is given the chance, it will dispatch events (such as connection lost) to handlers (such as connectionLost).

I don't understand why your sample code uses the socket module directly to create and then discard a connection to the destination address. My guess is that you're trying to determine if the server is accepting connections or not. In this case, you may want to use the ClientFactory method clientConnectionFailed to detect that the connection attempted by reactor.connectTCP has failed rather than using the socket module and checking for an exception. You could also use Twisted's endpoint abstraction to get this notification as a Deferred callback instead.

You may also be interested in Tubes which provides an even higher-level abstraction over data flow.

Jean-Paul Calderone
  • 47,755
  • 6
  • 94
  • 122
  • Thanks, that was exactly what I was trying to do but I wasn't able to find the clientConnectionFailed method, so instead I used a cheap work around that I thought of to just set up a socket and try and connect first, and if it were to fail, just abort the connection. – Hanson Duan Dec 01 '17 at 19:00