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