blob: a1477c8721b05d85e7e5fe295cbb2476b03c61c5 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "rtc_base/proxy_server.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stddef.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000014#include <algorithm>
nisseede5da42017-01-12 05:15:36 -080015
Niels Möllerd9709672019-03-25 08:57:50 +010016#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/checks.h"
Yves Gerey2e00abc2018-10-05 15:39:24 +020018#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "rtc_base/socket_factory.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000020
21namespace rtc {
22
23// ProxyServer
Yves Gerey665174f2018-06-19 15:03:05 +020024ProxyServer::ProxyServer(SocketFactory* int_factory,
25 const SocketAddress& int_addr,
26 SocketFactory* ext_factory,
27 const SocketAddress& ext_ip)
28 : ext_factory_(ext_factory),
29 ext_ip_(ext_ip.ipaddr(), 0), // strip off port
30 server_socket_(
31 int_factory->CreateAsyncSocket(int_addr.family(), SOCK_STREAM)) {
deadbeef37f5ecf2017-02-27 14:06:41 -080032 RTC_DCHECK(server_socket_.get() != nullptr);
nisseede5da42017-01-12 05:15:36 -080033 RTC_DCHECK(int_addr.family() == AF_INET || int_addr.family() == AF_INET6);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000034 server_socket_->Bind(int_addr);
35 server_socket_->Listen(5);
36 server_socket_->SignalReadEvent.connect(this, &ProxyServer::OnAcceptEvent);
37}
38
Niels Möllerd9709672019-03-25 08:57:50 +010039ProxyServer::~ProxyServer() = default;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000040
deadbeefc5d0d952015-07-16 10:22:21 -070041SocketAddress ProxyServer::GetServerAddress() {
42 return server_socket_->GetLocalAddress();
43}
44
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000045void ProxyServer::OnAcceptEvent(AsyncSocket* socket) {
kwibergee89e782017-08-09 17:22:01 -070046 RTC_DCHECK(socket);
47 RTC_DCHECK_EQ(socket, server_socket_.get());
deadbeef37f5ecf2017-02-27 14:06:41 -080048 AsyncSocket* int_socket = socket->Accept(nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000049 AsyncProxyServerSocket* wrapped_socket = WrapSocket(int_socket);
Yves Gerey665174f2018-06-19 15:03:05 +020050 AsyncSocket* ext_socket =
51 ext_factory_->CreateAsyncSocket(ext_ip_.family(), SOCK_STREAM);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000052 if (ext_socket) {
53 ext_socket->Bind(ext_ip_);
Niels Möllerd9709672019-03-25 08:57:50 +010054 bindings_.emplace_back(
55 absl::make_unique<ProxyBinding>(wrapped_socket, ext_socket));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000056 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +010057 RTC_LOG(LS_ERROR)
58 << "Unable to create external socket on proxy accept event";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000059 }
60}
61
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062// ProxyBinding
63ProxyBinding::ProxyBinding(AsyncProxyServerSocket* int_socket,
64 AsyncSocket* ext_socket)
Yves Gerey665174f2018-06-19 15:03:05 +020065 : int_socket_(int_socket),
66 ext_socket_(ext_socket),
67 connected_(false),
68 out_buffer_(kBufferSize),
69 in_buffer_(kBufferSize) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000070 int_socket_->SignalConnectRequest.connect(this,
71 &ProxyBinding::OnConnectRequest);
72 int_socket_->SignalReadEvent.connect(this, &ProxyBinding::OnInternalRead);
73 int_socket_->SignalWriteEvent.connect(this, &ProxyBinding::OnInternalWrite);
74 int_socket_->SignalCloseEvent.connect(this, &ProxyBinding::OnInternalClose);
75 ext_socket_->SignalConnectEvent.connect(this,
76 &ProxyBinding::OnExternalConnect);
77 ext_socket_->SignalReadEvent.connect(this, &ProxyBinding::OnExternalRead);
78 ext_socket_->SignalWriteEvent.connect(this, &ProxyBinding::OnExternalWrite);
79 ext_socket_->SignalCloseEvent.connect(this, &ProxyBinding::OnExternalClose);
80}
81
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000082ProxyBinding::~ProxyBinding() = default;
83
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000084void ProxyBinding::OnConnectRequest(AsyncProxyServerSocket* socket,
Yves Gerey665174f2018-06-19 15:03:05 +020085 const SocketAddress& addr) {
kwibergee89e782017-08-09 17:22:01 -070086 RTC_DCHECK(!connected_);
87 RTC_DCHECK(ext_socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000088 ext_socket_->Connect(addr);
89 // TODO: handle errors here
90}
91
92void ProxyBinding::OnInternalRead(AsyncSocket* socket) {
93 Read(int_socket_.get(), &out_buffer_);
94 Write(ext_socket_.get(), &out_buffer_);
95}
96
97void ProxyBinding::OnInternalWrite(AsyncSocket* socket) {
98 Write(int_socket_.get(), &in_buffer_);
99}
100
101void ProxyBinding::OnInternalClose(AsyncSocket* socket, int err) {
102 Destroy();
103}
104
105void ProxyBinding::OnExternalConnect(AsyncSocket* socket) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800106 RTC_DCHECK(socket != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000107 connected_ = true;
108 int_socket_->SendConnectResult(0, socket->GetRemoteAddress());
109}
110
111void ProxyBinding::OnExternalRead(AsyncSocket* socket) {
112 Read(ext_socket_.get(), &in_buffer_);
113 Write(int_socket_.get(), &in_buffer_);
114}
115
116void ProxyBinding::OnExternalWrite(AsyncSocket* socket) {
117 Write(ext_socket_.get(), &out_buffer_);
118}
119
120void ProxyBinding::OnExternalClose(AsyncSocket* socket, int err) {
121 if (!connected_) {
122 int_socket_->SendConnectResult(err, SocketAddress());
123 }
124 Destroy();
125}
126
127void ProxyBinding::Read(AsyncSocket* socket, FifoBuffer* buffer) {
128 // Only read if the buffer is empty.
deadbeef37f5ecf2017-02-27 14:06:41 -0800129 RTC_DCHECK(socket != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000130 size_t size;
131 int read;
132 if (buffer->GetBuffered(&size) && size == 0) {
133 void* p = buffer->GetWriteBuffer(&size);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200134 read = socket->Recv(p, size, nullptr);
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000135 buffer->ConsumeWriteBuffer(std::max(read, 0));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000136 }
137}
138
139void ProxyBinding::Write(AsyncSocket* socket, FifoBuffer* buffer) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800140 RTC_DCHECK(socket != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000141 size_t size;
142 int written;
143 const void* p = buffer->GetReadData(&size);
144 written = socket->Send(p, size);
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000145 buffer->ConsumeReadData(std::max(written, 0));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000146}
147
148void ProxyBinding::Destroy() {
149 SignalDestroyed(this);
150}
151
deadbeeff137e972017-03-23 15:45:49 -0700152AsyncProxyServerSocket* SocksProxyServer::WrapSocket(AsyncSocket* socket) {
153 return new AsyncSocksProxyServerSocket(socket);
154}
155
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000156} // namespace rtc