Move ServerSocket code to separate files and into test target
Classes AsyncProxyServerSocket, AsyncSSLServerSocket, and
AsyncSSLServerSocket are used only by test and example code.
Moved to server_socket_adapters.{cc,h}, and to the
rtc_base_tests_utils build target.
In the process, also deleted a few ancient and unattributed TODO
comments.
Bug: webrtc:9798
Change-Id: I21279c92bd8f1354fab7eeaf1f9697fedfc760e1
Reviewed-on: https://webrtc-review.googlesource.com/c/107735
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26039}
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index a2aa5ff..7d26947 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -214,6 +214,7 @@
":rtc_p2p",
"../rtc_base:checks",
"../rtc_base:rtc_base",
+ "../rtc_base:rtc_base_tests_utils",
"../rtc_base/third_party/sigslot",
"//third_party/abseil-cpp/absl/memory",
]
diff --git a/p2p/base/relayserver.cc b/p2p/base/relayserver.cc
index ad6b487..0f712a9 100644
--- a/p2p/base/relayserver.cc
+++ b/p2p/base/relayserver.cc
@@ -22,7 +22,7 @@
#include "rtc_base/helpers.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/socketadapters.h"
+#include "rtc_base/server_socket_adapters.h"
namespace cricket {
diff --git a/p2p/base/testrelayserver.h b/p2p/base/testrelayserver.h
index 5efffc8..9aca2f6 100644
--- a/p2p/base/testrelayserver.h
+++ b/p2p/base/testrelayserver.h
@@ -15,7 +15,7 @@
#include "p2p/base/relayserver.h"
#include "rtc_base/asynctcpsocket.h"
-#include "rtc_base/socketadapters.h"
+#include "rtc_base/server_socket_adapters.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index 1ee1ed5..d8af370 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -1156,6 +1156,8 @@
"nattypes.h",
"proxyserver.cc",
"proxyserver.h",
+ "server_socket_adapters.cc",
+ "server_socket_adapters.h",
"sigslottester.h",
"sigslottester.h.pump",
"socketstream.cc",
diff --git a/rtc_base/proxyserver.h b/rtc_base/proxyserver.h
index 37cadd0..587a49c 100644
--- a/rtc_base/proxyserver.h
+++ b/rtc_base/proxyserver.h
@@ -15,7 +15,7 @@
#include <memory>
#include "rtc_base/asyncsocket.h"
#include "rtc_base/constructormagic.h"
-#include "rtc_base/socketadapters.h"
+#include "rtc_base/server_socket_adapters.h"
#include "rtc_base/socketaddress.h"
#include "rtc_base/stream.h"
diff --git a/rtc_base/server_socket_adapters.cc b/rtc_base/server_socket_adapters.cc
new file mode 100644
index 0000000..64f9bf0
--- /dev/null
+++ b/rtc_base/server_socket_adapters.cc
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string>
+
+#include "rtc_base/bytebuffer.h"
+#include "rtc_base/server_socket_adapters.h"
+
+namespace rtc {
+
+AsyncProxyServerSocket::AsyncProxyServerSocket(AsyncSocket* socket,
+ size_t buffer_size)
+ : BufferedReadAdapter(socket, buffer_size) {}
+
+AsyncProxyServerSocket::~AsyncProxyServerSocket() = default;
+
+AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* socket)
+ : BufferedReadAdapter(socket, 1024) {
+ BufferInput(true);
+}
+
+void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
+ // We only accept client hello messages.
+ const ArrayView<const uint8_t> client_hello =
+ AsyncSSLSocket::SslClientHello();
+ if (*len < client_hello.size()) {
+ return;
+ }
+
+ if (memcmp(client_hello.data(), data, client_hello.size()) != 0) {
+ Close();
+ SignalCloseEvent(this, 0);
+ return;
+ }
+
+ *len -= client_hello.size();
+
+ // Clients should not send more data until the handshake is completed.
+ RTC_DCHECK(*len == 0);
+
+ const ArrayView<const uint8_t> server_hello =
+ AsyncSSLSocket::SslServerHello();
+ // Send a server hello back to the client.
+ DirectSend(server_hello.data(), server_hello.size());
+
+ // Handshake completed for us, redirect input to our parent.
+ BufferInput(false);
+}
+
+AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* socket)
+ : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
+ BufferInput(true);
+}
+
+void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
+ RTC_DCHECK(state_ < SS_CONNECT_PENDING);
+
+ ByteBufferReader response(data, *len);
+ if (state_ == SS_HELLO) {
+ HandleHello(&response);
+ } else if (state_ == SS_AUTH) {
+ HandleAuth(&response);
+ } else if (state_ == SS_CONNECT) {
+ HandleConnect(&response);
+ }
+
+ // Consume parsed data
+ *len = response.Length();
+ memmove(data, response.Data(), *len);
+}
+
+void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) {
+ BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
+}
+
+void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) {
+ uint8_t ver, num_methods;
+ if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&num_methods)) {
+ Error(0);
+ return;
+ }
+
+ if (ver != 5) {
+ Error(0);
+ return;
+ }
+
+ // Handle either no-auth (0) or user/pass auth (2)
+ uint8_t method = 0xFF;
+ if (num_methods > 0 && !request->ReadUInt8(&method)) {
+ Error(0);
+ return;
+ }
+
+ SendHelloReply(method);
+ if (method == 0) {
+ state_ = SS_CONNECT;
+ } else if (method == 2) {
+ state_ = SS_AUTH;
+ } else {
+ state_ = SS_ERROR;
+ }
+}
+
+void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) {
+ ByteBufferWriter response;
+ response.WriteUInt8(5); // Socks Version
+ response.WriteUInt8(method); // Auth method
+ DirectSend(response);
+}
+
+void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) {
+ uint8_t ver, user_len, pass_len;
+ std::string user, pass;
+ if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&user_len) ||
+ !request->ReadString(&user, user_len) || !request->ReadUInt8(&pass_len) ||
+ !request->ReadString(&pass, pass_len)) {
+ Error(0);
+ return;
+ }
+
+ SendAuthReply(0);
+ state_ = SS_CONNECT;
+}
+
+void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) {
+ ByteBufferWriter response;
+ response.WriteUInt8(1); // Negotiation Version
+ response.WriteUInt8(result);
+ DirectSend(response);
+}
+
+void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) {
+ uint8_t ver, command, reserved, addr_type;
+ uint32_t ip;
+ uint16_t port;
+ if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&command) ||
+ !request->ReadUInt8(&reserved) || !request->ReadUInt8(&addr_type) ||
+ !request->ReadUInt32(&ip) || !request->ReadUInt16(&port)) {
+ Error(0);
+ return;
+ }
+
+ if (ver != 5 || command != 1 || reserved != 0 || addr_type != 1) {
+ Error(0);
+ return;
+ }
+
+ SignalConnectRequest(this, SocketAddress(ip, port));
+ state_ = SS_CONNECT_PENDING;
+}
+
+void AsyncSocksProxyServerSocket::SendConnectResult(int result,
+ const SocketAddress& addr) {
+ if (state_ != SS_CONNECT_PENDING)
+ return;
+
+ ByteBufferWriter response;
+ response.WriteUInt8(5); // Socks version
+ response.WriteUInt8((result != 0)); // 0x01 is generic error
+ response.WriteUInt8(0); // reserved
+ response.WriteUInt8(1); // IPv4 address
+ response.WriteUInt32(addr.ip());
+ response.WriteUInt16(addr.port());
+ DirectSend(response);
+ BufferInput(false);
+ state_ = SS_TUNNEL;
+}
+
+void AsyncSocksProxyServerSocket::Error(int error) {
+ state_ = SS_ERROR;
+ BufferInput(false);
+ Close();
+ SetError(SOCKET_EACCES);
+ SignalCloseEvent(this, error);
+}
+
+} // namespace rtc
diff --git a/rtc_base/server_socket_adapters.h b/rtc_base/server_socket_adapters.h
new file mode 100644
index 0000000..e741ba8
--- /dev/null
+++ b/rtc_base/server_socket_adapters.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_SERVER_SOCKET_ADAPTERS_H_
+#define RTC_BASE_SERVER_SOCKET_ADAPTERS_H_
+
+#include "rtc_base/socketadapters.h"
+
+namespace rtc {
+
+// Interface for implementing proxy server sockets.
+class AsyncProxyServerSocket : public BufferedReadAdapter {
+ public:
+ AsyncProxyServerSocket(AsyncSocket* socket, size_t buffer_size);
+ ~AsyncProxyServerSocket() override;
+ sigslot::signal2<AsyncProxyServerSocket*, const SocketAddress&>
+ SignalConnectRequest;
+ virtual void SendConnectResult(int err, const SocketAddress& addr) = 0;
+};
+
+// Implements a socket adapter that performs the server side of a
+// fake SSL handshake. Used when implementing a relay server that does "ssltcp".
+class AsyncSSLServerSocket : public BufferedReadAdapter {
+ public:
+ explicit AsyncSSLServerSocket(AsyncSocket* socket);
+
+ protected:
+ void ProcessInput(char* data, size_t* len) override;
+ RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLServerSocket);
+};
+
+// Implements a proxy server socket for the SOCKS protocol.
+class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket {
+ public:
+ explicit AsyncSocksProxyServerSocket(AsyncSocket* socket);
+
+ private:
+ void ProcessInput(char* data, size_t* len) override;
+ void DirectSend(const ByteBufferWriter& buf);
+
+ void HandleHello(ByteBufferReader* request);
+ void SendHelloReply(uint8_t method);
+ void HandleAuth(ByteBufferReader* request);
+ void SendAuthReply(uint8_t result);
+ void HandleConnect(ByteBufferReader* request);
+ void SendConnectResult(int result, const SocketAddress& addr) override;
+
+ void Error(int error);
+
+ static const int kBufferSize = 1024;
+ enum State {
+ SS_HELLO,
+ SS_AUTH,
+ SS_CONNECT,
+ SS_CONNECT_PENDING,
+ SS_TUNNEL,
+ SS_ERROR
+ };
+ State state_;
+ RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxyServerSocket);
+};
+
+} // namespace rtc
+
+#endif // RTC_BASE_SERVER_SOCKET_ADAPTERS_H_
diff --git a/rtc_base/socketadapters.cc b/rtc_base/socketadapters.cc
index 3bac17b..9587d8d 100644
--- a/rtc_base/socketadapters.cc
+++ b/rtc_base/socketadapters.cc
@@ -130,12 +130,6 @@
ProcessInput(buffer_, &data_len_);
}
-AsyncProxyServerSocket::AsyncProxyServerSocket(AsyncSocket* socket,
- size_t buffer_size)
- : BufferedReadAdapter(socket, buffer_size) {}
-
-AsyncProxyServerSocket::~AsyncProxyServerSocket() = default;
-
///////////////////////////////////////////////////////////////////////////////
// This is a SSL v2 CLIENT_HELLO message.
@@ -157,6 +151,13 @@
0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea //
};
+// static
+ArrayView<const uint8_t> AsyncSSLSocket::SslClientHello() {
+ // Implicit conversion directly from kSslClientHello to ArrayView fails when
+ // built with gcc.
+ return {kSslClientHello, sizeof(kSslClientHello)};
+}
+
// This is a TLSv1 SERVER_HELLO message.
static const uint8_t kSslServerHello[] = {
0x16, // handshake message
@@ -178,6 +179,11 @@
0x00 // null compression
};
+// static
+ArrayView<const uint8_t> AsyncSSLSocket::SslServerHello() {
+ return {kSslServerHello, sizeof(kSslServerHello)};
+}
+
AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket)
: BufferedReadAdapter(socket, 1024) {}
@@ -219,35 +225,6 @@
SignalReadEvent(this);
}
-AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* socket)
- : BufferedReadAdapter(socket, 1024) {
- BufferInput(true);
-}
-
-void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
- // We only accept client hello messages.
- if (*len < sizeof(kSslClientHello)) {
- return;
- }
-
- if (memcmp(kSslClientHello, data, sizeof(kSslClientHello)) != 0) {
- Close();
- SignalCloseEvent(this, 0);
- return;
- }
-
- *len -= sizeof(kSslClientHello);
-
- // Clients should not send more data until the handshake is completed.
- RTC_DCHECK(*len == 0);
-
- // Send a server hello back to the client.
- DirectSend(kSslServerHello, sizeof(kSslServerHello));
-
- // Handshake completed for us, redirect input to our parent.
- BufferInput(false);
-}
-
///////////////////////////////////////////////////////////////////////////////
AsyncHttpsProxySocket::AsyncHttpsProxySocket(AsyncSocket* socket,
@@ -714,135 +691,4 @@
SignalCloseEvent(this, error);
}
-AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* socket)
- : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
- BufferInput(true);
-}
-
-void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
- // TODO: See if the whole message has arrived
- RTC_DCHECK(state_ < SS_CONNECT_PENDING);
-
- ByteBufferReader response(data, *len);
- if (state_ == SS_HELLO) {
- HandleHello(&response);
- } else if (state_ == SS_AUTH) {
- HandleAuth(&response);
- } else if (state_ == SS_CONNECT) {
- HandleConnect(&response);
- }
-
- // Consume parsed data
- *len = response.Length();
- memmove(data, response.Data(), *len);
-}
-
-void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) {
- BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
-}
-
-void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) {
- uint8_t ver, num_methods;
- if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&num_methods)) {
- Error(0);
- return;
- }
-
- if (ver != 5) {
- Error(0);
- return;
- }
-
- // Handle either no-auth (0) or user/pass auth (2)
- uint8_t method = 0xFF;
- if (num_methods > 0 && !request->ReadUInt8(&method)) {
- Error(0);
- return;
- }
-
- // TODO: Ask the server which method to use.
- SendHelloReply(method);
- if (method == 0) {
- state_ = SS_CONNECT;
- } else if (method == 2) {
- state_ = SS_AUTH;
- } else {
- state_ = SS_ERROR;
- }
-}
-
-void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) {
- ByteBufferWriter response;
- response.WriteUInt8(5); // Socks Version
- response.WriteUInt8(method); // Auth method
- DirectSend(response);
-}
-
-void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) {
- uint8_t ver, user_len, pass_len;
- std::string user, pass;
- if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&user_len) ||
- !request->ReadString(&user, user_len) || !request->ReadUInt8(&pass_len) ||
- !request->ReadString(&pass, pass_len)) {
- Error(0);
- return;
- }
-
- // TODO: Allow for checking of credentials.
- SendAuthReply(0);
- state_ = SS_CONNECT;
-}
-
-void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) {
- ByteBufferWriter response;
- response.WriteUInt8(1); // Negotiation Version
- response.WriteUInt8(result);
- DirectSend(response);
-}
-
-void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) {
- uint8_t ver, command, reserved, addr_type;
- uint32_t ip;
- uint16_t port;
- if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&command) ||
- !request->ReadUInt8(&reserved) || !request->ReadUInt8(&addr_type) ||
- !request->ReadUInt32(&ip) || !request->ReadUInt16(&port)) {
- Error(0);
- return;
- }
-
- if (ver != 5 || command != 1 || reserved != 0 || addr_type != 1) {
- Error(0);
- return;
- }
-
- SignalConnectRequest(this, SocketAddress(ip, port));
- state_ = SS_CONNECT_PENDING;
-}
-
-void AsyncSocksProxyServerSocket::SendConnectResult(int result,
- const SocketAddress& addr) {
- if (state_ != SS_CONNECT_PENDING)
- return;
-
- ByteBufferWriter response;
- response.WriteUInt8(5); // Socks version
- response.WriteUInt8((result != 0)); // 0x01 is generic error
- response.WriteUInt8(0); // reserved
- response.WriteUInt8(1); // IPv4 address
- response.WriteUInt32(addr.ip());
- response.WriteUInt16(addr.port());
- DirectSend(response);
- BufferInput(false);
- state_ = SS_TUNNEL;
-}
-
-void AsyncSocksProxyServerSocket::Error(int error) {
- state_ = SS_ERROR;
- BufferInput(false);
- Close();
- SetError(SOCKET_EACCES);
- SignalCloseEvent(this, error);
-}
-
} // namespace rtc
diff --git a/rtc_base/socketadapters.h b/rtc_base/socketadapters.h
index 062f75c..ca55909 100644
--- a/rtc_base/socketadapters.h
+++ b/rtc_base/socketadapters.h
@@ -13,6 +13,7 @@
#include <string>
+#include "api/array_view.h"
#include "rtc_base/asyncsocket.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/cryptstring.h"
@@ -55,22 +56,13 @@
///////////////////////////////////////////////////////////////////////////////
-// Interface for implementing proxy server sockets.
-class AsyncProxyServerSocket : public BufferedReadAdapter {
- public:
- AsyncProxyServerSocket(AsyncSocket* socket, size_t buffer_size);
- ~AsyncProxyServerSocket() override;
- sigslot::signal2<AsyncProxyServerSocket*, const SocketAddress&>
- SignalConnectRequest;
- virtual void SendConnectResult(int err, const SocketAddress& addr) = 0;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
// Implements a socket adapter that performs the client side of a
// fake SSL handshake. Used for "ssltcp" P2P functionality.
class AsyncSSLSocket : public BufferedReadAdapter {
public:
+ static ArrayView<const uint8_t> SslClientHello();
+ static ArrayView<const uint8_t> SslServerHello();
+
explicit AsyncSSLSocket(AsyncSocket* socket);
int Connect(const SocketAddress& addr) override;
@@ -81,17 +73,6 @@
RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLSocket);
};
-// Implements a socket adapter that performs the server side of a
-// fake SSL handshake. Used when implementing a relay server that does "ssltcp".
-class AsyncSSLServerSocket : public BufferedReadAdapter {
- public:
- explicit AsyncSSLServerSocket(AsyncSocket* socket);
-
- protected:
- void ProcessInput(char* data, size_t* len) override;
- RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLServerSocket);
-};
-
///////////////////////////////////////////////////////////////////////////////
// Implements a socket adapter that speaks the HTTP/S proxy protocol.
@@ -184,37 +165,6 @@
RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxySocket);
};
-// Implements a proxy server socket for the SOCKS protocol.
-class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket {
- public:
- explicit AsyncSocksProxyServerSocket(AsyncSocket* socket);
-
- private:
- void ProcessInput(char* data, size_t* len) override;
- void DirectSend(const ByteBufferWriter& buf);
-
- void HandleHello(ByteBufferReader* request);
- void SendHelloReply(uint8_t method);
- void HandleAuth(ByteBufferReader* request);
- void SendAuthReply(uint8_t result);
- void HandleConnect(ByteBufferReader* request);
- void SendConnectResult(int result, const SocketAddress& addr) override;
-
- void Error(int error);
-
- static const int kBufferSize = 1024;
- enum State {
- SS_HELLO,
- SS_AUTH,
- SS_CONNECT,
- SS_CONNECT_PENDING,
- SS_TUNNEL,
- SS_ERROR
- };
- State state_;
- RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxyServerSocket);
-};
-
} // namespace rtc
#endif // RTC_BASE_SOCKETADAPTERS_H_