How to correctly close a connection with Poco::HTTPSClientSession?

3.1k views Asked by At

I run into a problem with Poco::HTTPSClientSession and don't know how to handle it.

Description (or what happens)

A HTTPS connection to a server is established with the use of the Poco::HTTPSClientSession class. Connection establishment, key-exchange, initial data exchange works well.

The client sends one request directly after the session establishment. The HTTP 1.1 feature persistent connections is used (i.e. the connection remains open for some time to handle additional requests). The server waits one minute - no further requests are received over this connection - then sends a close_notify and closes the connection (with a TCP FIN). About two minutes after this the client wants to send the next request. The client sends out a close_notify and closes the connection with a TCP RST.

My Opinion

The client behavior is IMHO not correct. As you can read in RFC 6101 5.4.1. Closure Alerts, the other side should close the connection immediately:

It is required that the other party respond with a close_notify alert of its own and close down the connection immediately, discarding any pending writes.

My Question

I'm not sure how to handle this with Poco. For me it looks that there is the need for some callback handling (at the point of time when the server sends the close_notify). The problem is, that because the 'socket()' method is protected within the Poco::HTTPSClientSession there is no way to install such a close_notify handler - and even I don't know if there is a appropriate callback for this.

Can you please hint me to the class / function to use to correctly close the HTTPS connection of the client when the server sends a close_notify? [Addition after the answer from Joachim Pileborg]: Is there the need to inherit from Poco::HTTPSClientSession to correctly handle the close_notify?

Kind regards - Andreas

1

There are 1 answers

0
majdus On

This is an old question but since there is not any acceptable response I put here my solution if it can help some one.

Do this before sending request to server.

if (mySession->socket().poll(0, Poco::Net::Socket::SELECT_READ) && (mySession->socket().receiveBytes(NULL,0) == 0)) {
    mySession->reset();
}

From Poco documentation :

bool poll(const Poco::Timespan& timeout, int mode) const;
    /// Determines the status of the socket, using a 
    /// call to select().
    /// 
    /// The mode argument is constructed by combining the values
    /// of the SelectMode enumeration.
    ///
    /// Returns true if the next operation corresponding to
    /// mode will not block, false otherwise.

int receiveBytes(void* buffer, int length, int flags = 0);
    /// Receives data from the socket and stores it
    /// in buffer. Up to length bytes are received.
    ///
    /// Returns the number of bytes received. 
    /// A return value of 0 means a graceful shutdown 
    /// of the connection from the peer.
    ///
    /// Throws a TimeoutException if a receive timeout has
    /// been set and nothing is received within that interval.
    /// Throws a NetException (or a subclass) in case of other errors.

The poll method with select_read mode will return true if you have an open readable socket. Use receiveBytes to read the server side graceful shutdown and then reset the socket for next requests.