asio icon indicating copy to clipboard operation
asio copied to clipboard

Should remote_endpoint() throw exception after receive of RST packet from already connected client ?

Open p-jaholkowski opened this issue 7 months ago • 0 comments

Should remote_endpoint() throw exception after receive of RST packet from already connected client ?

I have tls handshake which looks like this:

void ClientSocket::asyncSSLHandshake() { auto shareThis = this->shared_from_this();

auto handshakeHandler = [&, shareThis](const asio::error_code& error) {

	if (0 != error.value())
	{
		asio::ip::address address = this->socketSSL->lowest_layer().remote_endpoint().address();
		printf("ClientSocket::asyncSSLHandshake errorCode=%u, message=%s from address=%s\n", error.value(), error.message().c_str(), address.to_string().c_str());
		return;
	}

	printf("ClientSocket::asyncSSLHandshake handshake accepted\n");

	asio::ip::tcp::no_delay no_delay_option(true);
	asio::socket_base::keep_alive keepAlive(true);
	this->socketSSL->lowest_layer().set_option(no_delay_option);
	this->socketSSL->lowest_layer().set_option(keepAlive);

	// the timeout value
	uint32_t timeout_milli = setup::socketKeepAliveTimeoutMs;

	// platform-specific switch

#if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT // use windows-specific time int32_t timeout = timeout_milli; setsockopt(this->socketSSL->lowest_layer().native_handle(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); setsockopt(this->socketSSL->lowest_layer().native_handle(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout)); #else // assume everything else is posix struct timeval tv; tv.tv_sec = timeout_milli / 1000; tv.tv_usec = (timeout_milli % 1000) * 1000; setsockopt(this->socketSSL->lowest_layer().native_handle(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(this->socketSSL->lowest_layer().native_handle(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); #endif

	this->asyncReadSocket(sizeof(server::message::MessageHeader));
};

this->socketSSL->async_handshake(asio::ssl::stream_base::server, asio::bind_executor(this->readWriteStrand, handshakeHandler));

}

I noticed that server crashes when handshake handler gets asio::error::connection_reset because then called remote_endpoint() throws asio::error::not_connected. I should encapsulate remote_endpoint() in try catch block but I'm wondering if it is possible to display IP address of client which connects to socket and then sends RST packet just after that. When client connects to socket and closes connection normal way (by shutting down the socket) displaying that adress is possible (remote_endpoint() does not throw exception) despite fact that it is not connected anymore just like in case of received RST packet.

Here is the way to simulate both cases:

void normalCloseTest() { char serverIp[] = "195.180.206.158"; char port[] = "777";

asio::io_context io_context;

asio::ip::tcp::resolver resolver(io_context);
asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(serverIp, port);

// Try each endpoint until we successfully establish a connection.
asio::ip::tcp::socket socket(io_context);
asio::connect(socket, endpoints);

asio::streambuf request;
std::ostream request_stream(&request);

socket.close();

}

void RSTPacketCloseTest() { char serverIp[] = "195.180.206.158"; char port[] = "777";

asio::io_context io_context;

asio::ip::tcp::resolver resolver(io_context);
asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(serverIp, port);

// Try each endpoint until we successfully establish a connection.
asio::ip::tcp::socket socket(io_context);
asio::connect(socket, endpoints);

asio::streambuf request;
std::ostream request_stream(&request);

exit();

}

p-jaholkowski avatar Jul 08 '24 19:07 p-jaholkowski