1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_base/proxy_server.h"
12
13 #include <stddef.h>
14
15 #include <memory>
16 #include "rtc_base/checks.h"
17 #include "rtc_base/logging.h"
18 #include "rtc_base/socket_factory.h"
19
20 namespace rtc {
21
22 // ProxyServer
ProxyServer(SocketFactory * int_factory,const SocketAddress & int_addr,SocketFactory * ext_factory,const SocketAddress & ext_ip)23 ProxyServer::ProxyServer(SocketFactory* int_factory,
24 const SocketAddress& int_addr,
25 SocketFactory* ext_factory,
26 const SocketAddress& ext_ip)
27 : ext_factory_(ext_factory),
28 ext_ip_(ext_ip.ipaddr(), 0), // strip off port
29 server_socket_(
30 int_factory->CreateAsyncSocket(int_addr.family(), SOCK_STREAM)) {
31 RTC_DCHECK(server_socket_.get() != nullptr);
32 RTC_DCHECK(int_addr.family() == AF_INET || int_addr.family() == AF_INET6);
33 server_socket_->Bind(int_addr);
34 server_socket_->Listen(5);
35 server_socket_->SignalReadEvent.connect(this, &ProxyServer::OnAcceptEvent);
36 }
37
38 ProxyServer::~ProxyServer() = default;
39
GetServerAddress()40 SocketAddress ProxyServer::GetServerAddress() {
41 return server_socket_->GetLocalAddress();
42 }
43
OnAcceptEvent(AsyncSocket * socket)44 void ProxyServer::OnAcceptEvent(AsyncSocket* socket) {
45 RTC_DCHECK(socket);
46 RTC_DCHECK_EQ(socket, server_socket_.get());
47 AsyncSocket* int_socket = socket->Accept(nullptr);
48 AsyncProxyServerSocket* wrapped_socket = WrapSocket(int_socket);
49 AsyncSocket* ext_socket =
50 ext_factory_->CreateAsyncSocket(ext_ip_.family(), SOCK_STREAM);
51 if (ext_socket) {
52 ext_socket->Bind(ext_ip_);
53 bindings_.emplace_back(
54 std::make_unique<ProxyBinding>(wrapped_socket, ext_socket));
55 } else {
56 RTC_LOG(LS_ERROR)
57 << "Unable to create external socket on proxy accept event";
58 }
59 }
60
61 // ProxyBinding
ProxyBinding(AsyncProxyServerSocket * int_socket,AsyncSocket * ext_socket)62 ProxyBinding::ProxyBinding(AsyncProxyServerSocket* int_socket,
63 AsyncSocket* ext_socket)
64 : int_socket_(int_socket),
65 ext_socket_(ext_socket),
66 connected_(false),
67 out_buffer_(kBufferSize),
68 in_buffer_(kBufferSize) {
69 int_socket_->SignalConnectRequest.connect(this,
70 &ProxyBinding::OnConnectRequest);
71 int_socket_->SignalReadEvent.connect(this, &ProxyBinding::OnInternalRead);
72 int_socket_->SignalWriteEvent.connect(this, &ProxyBinding::OnInternalWrite);
73 int_socket_->SignalCloseEvent.connect(this, &ProxyBinding::OnInternalClose);
74 ext_socket_->SignalConnectEvent.connect(this,
75 &ProxyBinding::OnExternalConnect);
76 ext_socket_->SignalReadEvent.connect(this, &ProxyBinding::OnExternalRead);
77 ext_socket_->SignalWriteEvent.connect(this, &ProxyBinding::OnExternalWrite);
78 ext_socket_->SignalCloseEvent.connect(this, &ProxyBinding::OnExternalClose);
79 }
80
81 ProxyBinding::~ProxyBinding() = default;
82
OnConnectRequest(AsyncProxyServerSocket * socket,const SocketAddress & addr)83 void ProxyBinding::OnConnectRequest(AsyncProxyServerSocket* socket,
84 const SocketAddress& addr) {
85 RTC_DCHECK(!connected_);
86 RTC_DCHECK(ext_socket_);
87 ext_socket_->Connect(addr);
88 // TODO: handle errors here
89 }
90
OnInternalRead(AsyncSocket * socket)91 void ProxyBinding::OnInternalRead(AsyncSocket* socket) {
92 Read(int_socket_.get(), &out_buffer_);
93 Write(ext_socket_.get(), &out_buffer_);
94 }
95
OnInternalWrite(AsyncSocket * socket)96 void ProxyBinding::OnInternalWrite(AsyncSocket* socket) {
97 Write(int_socket_.get(), &in_buffer_);
98 }
99
OnInternalClose(AsyncSocket * socket,int err)100 void ProxyBinding::OnInternalClose(AsyncSocket* socket, int err) {
101 Destroy();
102 }
103
OnExternalConnect(AsyncSocket * socket)104 void ProxyBinding::OnExternalConnect(AsyncSocket* socket) {
105 RTC_DCHECK(socket != nullptr);
106 connected_ = true;
107 int_socket_->SendConnectResult(0, socket->GetRemoteAddress());
108 }
109
OnExternalRead(AsyncSocket * socket)110 void ProxyBinding::OnExternalRead(AsyncSocket* socket) {
111 Read(ext_socket_.get(), &in_buffer_);
112 Write(int_socket_.get(), &in_buffer_);
113 }
114
OnExternalWrite(AsyncSocket * socket)115 void ProxyBinding::OnExternalWrite(AsyncSocket* socket) {
116 Write(ext_socket_.get(), &out_buffer_);
117 }
118
OnExternalClose(AsyncSocket * socket,int err)119 void ProxyBinding::OnExternalClose(AsyncSocket* socket, int err) {
120 if (!connected_) {
121 int_socket_->SendConnectResult(err, SocketAddress());
122 }
123 Destroy();
124 }
125
Read(AsyncSocket * socket,FifoBuffer * buffer)126 void ProxyBinding::Read(AsyncSocket* socket, FifoBuffer* buffer) {
127 // Only read if the buffer is empty.
128 RTC_DCHECK(socket != nullptr);
129 size_t size;
130 int read;
131 if (buffer->GetBuffered(&size) && size == 0) {
132 void* p = buffer->GetWriteBuffer(&size);
133 read = socket->Recv(p, size, nullptr);
134 buffer->ConsumeWriteBuffer(std::max(read, 0));
135 }
136 }
137
Write(AsyncSocket * socket,FifoBuffer * buffer)138 void ProxyBinding::Write(AsyncSocket* socket, FifoBuffer* buffer) {
139 RTC_DCHECK(socket != nullptr);
140 size_t size;
141 int written;
142 const void* p = buffer->GetReadData(&size);
143 written = socket->Send(p, size);
144 buffer->ConsumeReadData(std::max(written, 0));
145 }
146
Destroy()147 void ProxyBinding::Destroy() {
148 SignalDestroyed(this);
149 }
150
WrapSocket(AsyncSocket * socket)151 AsyncProxyServerSocket* SocksProxyServer::WrapSocket(AsyncSocket* socket) {
152 return new AsyncSocksProxyServerSocket(socket);
153 }
154
155 } // namespace rtc
156