blob: 55cab80975c36fd1543e84eda512aff382bde74c [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/proxyserver.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012
13#include <algorithm>
nisseede5da42017-01-12 05:15:36 -080014
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "rtc_base/checks.h"
16#include "rtc_base/socketfactory.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000017
18namespace rtc {
19
20// ProxyServer
Yves Gerey665174f2018-06-19 15:03:05 +020021ProxyServer::ProxyServer(SocketFactory* int_factory,
22 const SocketAddress& int_addr,
23 SocketFactory* ext_factory,
24 const SocketAddress& ext_ip)
25 : ext_factory_(ext_factory),
26 ext_ip_(ext_ip.ipaddr(), 0), // strip off port
27 server_socket_(
28 int_factory->CreateAsyncSocket(int_addr.family(), SOCK_STREAM)) {
deadbeef37f5ecf2017-02-27 14:06:41 -080029 RTC_DCHECK(server_socket_.get() != nullptr);
nisseede5da42017-01-12 05:15:36 -080030 RTC_DCHECK(int_addr.family() == AF_INET || int_addr.family() == AF_INET6);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000031 server_socket_->Bind(int_addr);
32 server_socket_->Listen(5);
33 server_socket_->SignalReadEvent.connect(this, &ProxyServer::OnAcceptEvent);
34}
35
36ProxyServer::~ProxyServer() {
Yves Gerey665174f2018-06-19 15:03:05 +020037 for (BindingList::iterator it = bindings_.begin(); it != bindings_.end();
38 ++it) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000039 delete (*it);
40 }
41}
42
deadbeefc5d0d952015-07-16 10:22:21 -070043SocketAddress ProxyServer::GetServerAddress() {
44 return server_socket_->GetLocalAddress();
45}
46
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000047void ProxyServer::OnAcceptEvent(AsyncSocket* socket) {
kwibergee89e782017-08-09 17:22:01 -070048 RTC_DCHECK(socket);
49 RTC_DCHECK_EQ(socket, server_socket_.get());
deadbeef37f5ecf2017-02-27 14:06:41 -080050 AsyncSocket* int_socket = socket->Accept(nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000051 AsyncProxyServerSocket* wrapped_socket = WrapSocket(int_socket);
Yves Gerey665174f2018-06-19 15:03:05 +020052 AsyncSocket* ext_socket =
53 ext_factory_->CreateAsyncSocket(ext_ip_.family(), SOCK_STREAM);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000054 if (ext_socket) {
55 ext_socket->Bind(ext_ip_);
56 bindings_.push_back(new ProxyBinding(wrapped_socket, ext_socket));
57 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +010058 RTC_LOG(LS_ERROR)
59 << "Unable to create external socket on proxy accept event";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000060 }
61}
62
63void ProxyServer::OnBindingDestroyed(ProxyBinding* binding) {
64 BindingList::iterator it =
65 std::find(bindings_.begin(), bindings_.end(), binding);
66 delete (*it);
67 bindings_.erase(it);
68}
69
70// ProxyBinding
71ProxyBinding::ProxyBinding(AsyncProxyServerSocket* int_socket,
72 AsyncSocket* ext_socket)
Yves Gerey665174f2018-06-19 15:03:05 +020073 : int_socket_(int_socket),
74 ext_socket_(ext_socket),
75 connected_(false),
76 out_buffer_(kBufferSize),
77 in_buffer_(kBufferSize) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000078 int_socket_->SignalConnectRequest.connect(this,
79 &ProxyBinding::OnConnectRequest);
80 int_socket_->SignalReadEvent.connect(this, &ProxyBinding::OnInternalRead);
81 int_socket_->SignalWriteEvent.connect(this, &ProxyBinding::OnInternalWrite);
82 int_socket_->SignalCloseEvent.connect(this, &ProxyBinding::OnInternalClose);
83 ext_socket_->SignalConnectEvent.connect(this,
84 &ProxyBinding::OnExternalConnect);
85 ext_socket_->SignalReadEvent.connect(this, &ProxyBinding::OnExternalRead);
86 ext_socket_->SignalWriteEvent.connect(this, &ProxyBinding::OnExternalWrite);
87 ext_socket_->SignalCloseEvent.connect(this, &ProxyBinding::OnExternalClose);
88}
89
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000090ProxyBinding::~ProxyBinding() = default;
91
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000092void ProxyBinding::OnConnectRequest(AsyncProxyServerSocket* socket,
Yves Gerey665174f2018-06-19 15:03:05 +020093 const SocketAddress& addr) {
kwibergee89e782017-08-09 17:22:01 -070094 RTC_DCHECK(!connected_);
95 RTC_DCHECK(ext_socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000096 ext_socket_->Connect(addr);
97 // TODO: handle errors here
98}
99
100void ProxyBinding::OnInternalRead(AsyncSocket* socket) {
101 Read(int_socket_.get(), &out_buffer_);
102 Write(ext_socket_.get(), &out_buffer_);
103}
104
105void ProxyBinding::OnInternalWrite(AsyncSocket* socket) {
106 Write(int_socket_.get(), &in_buffer_);
107}
108
109void ProxyBinding::OnInternalClose(AsyncSocket* socket, int err) {
110 Destroy();
111}
112
113void ProxyBinding::OnExternalConnect(AsyncSocket* socket) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800114 RTC_DCHECK(socket != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000115 connected_ = true;
116 int_socket_->SendConnectResult(0, socket->GetRemoteAddress());
117}
118
119void ProxyBinding::OnExternalRead(AsyncSocket* socket) {
120 Read(ext_socket_.get(), &in_buffer_);
121 Write(int_socket_.get(), &in_buffer_);
122}
123
124void ProxyBinding::OnExternalWrite(AsyncSocket* socket) {
125 Write(ext_socket_.get(), &out_buffer_);
126}
127
128void ProxyBinding::OnExternalClose(AsyncSocket* socket, int err) {
129 if (!connected_) {
130 int_socket_->SendConnectResult(err, SocketAddress());
131 }
132 Destroy();
133}
134
135void ProxyBinding::Read(AsyncSocket* socket, FifoBuffer* buffer) {
136 // Only read if the buffer is empty.
deadbeef37f5ecf2017-02-27 14:06:41 -0800137 RTC_DCHECK(socket != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000138 size_t size;
139 int read;
140 if (buffer->GetBuffered(&size) && size == 0) {
141 void* p = buffer->GetWriteBuffer(&size);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200142 read = socket->Recv(p, size, nullptr);
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000143 buffer->ConsumeWriteBuffer(std::max(read, 0));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000144 }
145}
146
147void ProxyBinding::Write(AsyncSocket* socket, FifoBuffer* buffer) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800148 RTC_DCHECK(socket != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000149 size_t size;
150 int written;
151 const void* p = buffer->GetReadData(&size);
152 written = socket->Send(p, size);
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000153 buffer->ConsumeReadData(std::max(written, 0));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000154}
155
156void ProxyBinding::Destroy() {
157 SignalDestroyed(this);
158}
159
deadbeeff137e972017-03-23 15:45:49 -0700160AsyncProxyServerSocket* SocksProxyServer::WrapSocket(AsyncSocket* socket) {
161 return new AsyncSocksProxyServerSocket(socket);
162}
163
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000164} // namespace rtc