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}
This commit is contained in:
parent
3d2ed19d95
commit
4415315b52
@ -214,6 +214,7 @@ rtc_source_set("p2p_server_utils") {
|
|||||||
":rtc_p2p",
|
":rtc_p2p",
|
||||||
"../rtc_base:checks",
|
"../rtc_base:checks",
|
||||||
"../rtc_base:rtc_base",
|
"../rtc_base:rtc_base",
|
||||||
|
"../rtc_base:rtc_base_tests_utils",
|
||||||
"../rtc_base/third_party/sigslot",
|
"../rtc_base/third_party/sigslot",
|
||||||
"//third_party/abseil-cpp/absl/memory",
|
"//third_party/abseil-cpp/absl/memory",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
#include "rtc_base/helpers.h"
|
#include "rtc_base/helpers.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/numerics/safe_conversions.h"
|
#include "rtc_base/numerics/safe_conversions.h"
|
||||||
#include "rtc_base/socketadapters.h"
|
#include "rtc_base/server_socket_adapters.h"
|
||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include "p2p/base/relayserver.h"
|
#include "p2p/base/relayserver.h"
|
||||||
#include "rtc_base/asynctcpsocket.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/third_party/sigslot/sigslot.h"
|
||||||
#include "rtc_base/thread.h"
|
#include "rtc_base/thread.h"
|
||||||
|
|
||||||
|
|||||||
@ -1156,6 +1156,8 @@ rtc_source_set("rtc_base_tests_utils") {
|
|||||||
"nattypes.h",
|
"nattypes.h",
|
||||||
"proxyserver.cc",
|
"proxyserver.cc",
|
||||||
"proxyserver.h",
|
"proxyserver.h",
|
||||||
|
"server_socket_adapters.cc",
|
||||||
|
"server_socket_adapters.h",
|
||||||
"sigslottester.h",
|
"sigslottester.h",
|
||||||
"sigslottester.h.pump",
|
"sigslottester.h.pump",
|
||||||
"socketstream.cc",
|
"socketstream.cc",
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "rtc_base/asyncsocket.h"
|
#include "rtc_base/asyncsocket.h"
|
||||||
#include "rtc_base/constructormagic.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/socketaddress.h"
|
||||||
#include "rtc_base/stream.h"
|
#include "rtc_base/stream.h"
|
||||||
|
|
||||||
|
|||||||
185
rtc_base/server_socket_adapters.cc
Normal file
185
rtc_base/server_socket_adapters.cc
Normal file
@ -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
|
||||||
72
rtc_base/server_socket_adapters.h
Normal file
72
rtc_base/server_socket_adapters.h
Normal file
@ -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_
|
||||||
@ -130,12 +130,6 @@ void BufferedReadAdapter::OnReadEvent(AsyncSocket* socket) {
|
|||||||
ProcessInput(buffer_, &data_len_);
|
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.
|
// This is a SSL v2 CLIENT_HELLO message.
|
||||||
@ -157,6 +151,13 @@ static const uint8_t kSslClientHello[] = {
|
|||||||
0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea //
|
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.
|
// This is a TLSv1 SERVER_HELLO message.
|
||||||
static const uint8_t kSslServerHello[] = {
|
static const uint8_t kSslServerHello[] = {
|
||||||
0x16, // handshake message
|
0x16, // handshake message
|
||||||
@ -178,6 +179,11 @@ static const uint8_t kSslServerHello[] = {
|
|||||||
0x00 // null compression
|
0x00 // null compression
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// static
|
||||||
|
ArrayView<const uint8_t> AsyncSSLSocket::SslServerHello() {
|
||||||
|
return {kSslServerHello, sizeof(kSslServerHello)};
|
||||||
|
}
|
||||||
|
|
||||||
AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket)
|
AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket)
|
||||||
: BufferedReadAdapter(socket, 1024) {}
|
: BufferedReadAdapter(socket, 1024) {}
|
||||||
|
|
||||||
@ -219,35 +225,6 @@ void AsyncSSLSocket::ProcessInput(char* data, size_t* len) {
|
|||||||
SignalReadEvent(this);
|
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,
|
AsyncHttpsProxySocket::AsyncHttpsProxySocket(AsyncSocket* socket,
|
||||||
@ -714,135 +691,4 @@ void AsyncSocksProxySocket::Error(int error) {
|
|||||||
SignalCloseEvent(this, error);
|
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
|
} // namespace rtc
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "api/array_view.h"
|
||||||
#include "rtc_base/asyncsocket.h"
|
#include "rtc_base/asyncsocket.h"
|
||||||
#include "rtc_base/constructormagic.h"
|
#include "rtc_base/constructormagic.h"
|
||||||
#include "rtc_base/cryptstring.h"
|
#include "rtc_base/cryptstring.h"
|
||||||
@ -55,22 +56,13 @@ class BufferedReadAdapter : public AsyncSocketAdapter {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// 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
|
// Implements a socket adapter that performs the client side of a
|
||||||
// fake SSL handshake. Used for "ssltcp" P2P functionality.
|
// fake SSL handshake. Used for "ssltcp" P2P functionality.
|
||||||
class AsyncSSLSocket : public BufferedReadAdapter {
|
class AsyncSSLSocket : public BufferedReadAdapter {
|
||||||
public:
|
public:
|
||||||
|
static ArrayView<const uint8_t> SslClientHello();
|
||||||
|
static ArrayView<const uint8_t> SslServerHello();
|
||||||
|
|
||||||
explicit AsyncSSLSocket(AsyncSocket* socket);
|
explicit AsyncSSLSocket(AsyncSocket* socket);
|
||||||
|
|
||||||
int Connect(const SocketAddress& addr) override;
|
int Connect(const SocketAddress& addr) override;
|
||||||
@ -81,17 +73,6 @@ class AsyncSSLSocket : public BufferedReadAdapter {
|
|||||||
RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLSocket);
|
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.
|
// Implements a socket adapter that speaks the HTTP/S proxy protocol.
|
||||||
@ -184,37 +165,6 @@ class AsyncSocksProxySocket : public BufferedReadAdapter {
|
|||||||
RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxySocket);
|
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
|
} // namespace rtc
|
||||||
|
|
||||||
#endif // RTC_BASE_SOCKETADAPTERS_H_
|
#endif // RTC_BASE_SOCKETADAPTERS_H_
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user