Browse Source

Merge pull request #670 from paullouisageneau/ws-disable-nagle

Reduce WebSocket latency by disabling the Nagle algorithm
Paul-Louis Ageneau 3 years ago
parent
commit
6002ed7ec8
3 changed files with 31 additions and 17 deletions
  1. 23 15
      src/impl/tcptransport.cpp
  2. 1 0
      src/impl/tcptransport.hpp
  3. 7 2
      src/impl/wstransport.cpp

+ 23 - 15
src/impl/tcptransport.cpp

@@ -47,10 +47,8 @@ TcpTransport::TcpTransport(socket_t sock, state_callback callback)
 
 	PLOG_DEBUG << "Initializing TCP transport with socket";
 
-	// Set non-blocking
-	ctl_t nbio = 1;
-	if (::ioctlsocket(mSock, FIONBIO, &nbio) < 0)
-		throw std::runtime_error("Failed to set socket non-blocking mode");
+	// Configure socket
+	configureSocket();
 
 	// Retrieve hostname and service
 	struct sockaddr_storage addr;
@@ -217,17 +215,8 @@ void TcpTransport::prepare(const sockaddr *addr, socklen_t addrlen) {
 		if (mSock == INVALID_SOCKET)
 			throw std::runtime_error("TCP socket creation failed");
 
-		// Set non-blocking
-		ctl_t nbio = 1;
-		if (::ioctlsocket(mSock, FIONBIO, &nbio) < 0)
-			throw std::runtime_error("Failed to set socket non-blocking mode");
-
-#ifdef __APPLE__
-		// MacOS lacks MSG_NOSIGNAL and requires SO_NOSIGPIPE instead
-		const sockopt_t enabled = 1;
-		if (::setsockopt(mSock, SOL_SOCKET, SO_NOSIGPIPE, &enabled, sizeof(enabled)) < 0)
-			throw std::runtime_error("Failed to disable SIGPIPE for socket");
-#endif
+		// Configure socket
+		configureSocket();
 
 		// Initiate connection
 		int ret = ::connect(mSock, addr, addrlen);
@@ -246,6 +235,25 @@ void TcpTransport::prepare(const sockaddr *addr, socklen_t addrlen) {
 	}
 }
 
+void TcpTransport::configureSocket() {
+	// Set non-blocking
+	ctl_t nbio = 1;
+	if (::ioctlsocket(mSock, FIONBIO, &nbio) < 0)
+		throw std::runtime_error("Failed to set socket non-blocking mode");
+
+	// Disable the Nagle algorithm
+	int nodelay = 1;
+	::setsockopt(mSock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&nodelay),
+	             sizeof(nodelay));
+
+#ifdef __APPLE__
+	// MacOS lacks MSG_NOSIGNAL and requires SO_NOSIGPIPE instead
+	const sockopt_t enabled = 1;
+	if (::setsockopt(mSock, SOL_SOCKET, SO_NOSIGPIPE, &enabled, sizeof(enabled)) < 0)
+		throw std::runtime_error("Failed to disable SIGPIPE for socket");
+#endif
+}
+
 void TcpTransport::setPoll(PollService::Direction direction) {
 	const auto timeout = 10s;
 	PollService::Instance().add(

+ 1 - 0
src/impl/tcptransport.hpp

@@ -51,6 +51,7 @@ public:
 private:
 	void connect();
 	void prepare(const sockaddr *addr, socklen_t addrlen);
+	void configureSocket();
 	void setPoll(PollService::Direction direction);
 	void close();
 

+ 7 - 2
src/impl/wstransport.cpp

@@ -369,8 +369,13 @@ bool WsTransport::sendFrame(const Frame &frame) {
 			frame.payload[i] ^= maskingKey[i % 4];
 	}
 
-	outgoing(make_message(buffer, cur));                                        // header
-	return outgoing(make_message(frame.payload, frame.payload + frame.length)); // payload
+	const size_t length = cur - buffer; // header length
+	auto message = make_message(length + frame.length);
+	std::copy(buffer, buffer + length, message->begin()); // header
+	std::copy(frame.payload, frame.payload + frame.length,
+	          message->begin() + length); // payload
+
+	return outgoing(std::move(message));
 }
 
 } // namespace rtc::impl