Skip to content

Commit f6ebbce

Browse files
committed
0 parents  commit f6ebbce

File tree

2 files changed

+301
-0
lines changed

2 files changed

+301
-0
lines changed

Makefile

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#
2+
# TCP Proxy Server
3+
# ~~~~~~~~~~~~~~~~~~~
4+
#
5+
# Copyright (c) 2007 Arash Partow (http://www.partow.net)
6+
# URL: http://www.partow.net/programming/tcpproxy/index.html
7+
#
8+
# Distributed under the Boost Software License, Version 1.0.
9+
#
10+
11+
12+
COMPILER = -c++
13+
OPTIMIZATION_OPT = -O3
14+
OPTIONS = -pedantic -ansi -Wall -Werror $(OPTIMIZATION_OPT) -o
15+
PTHREAD = -lpthread
16+
LINKER_OPT = -L/usr/lib -lstdc++ $(PTHREAD) -lboost_thread -lboost_system
17+
18+
BUILD_LIST+=tcpproxy_server
19+
20+
all: $(BUILD_LIST)
21+
22+
tcpproxy_server: tcpproxy_server.cpp
23+
$(COMPILER) $(OPTIONS) tcpproxy_server tcpproxy_server.cpp $(LINKER_OPT)
24+
25+
strip_bin :
26+
strip -s tcpproxy
27+
28+
clean:
29+
rm -f core *.o *.bak *~ *stackdump *#

tcpproxy_server.cpp

+272
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
//
2+
// tcpproxy_server.cpp
3+
// ~~~~~~~~~~~~~~~~~~~
4+
//
5+
// Copyright (c) 2007 Arash Partow (http://www.partow.net)
6+
// URL: http://www.partow.net/programming/tcpproxy/index.html
7+
//
8+
// Distributed under the Boost Software License, Version 1.0.
9+
//
10+
11+
#include <cstdlib>
12+
#include <cstddef>
13+
#include <iostream>
14+
#include <string>
15+
16+
#include <boost/shared_ptr.hpp>
17+
#include <boost/enable_shared_from_this.hpp>
18+
#include <boost/bind.hpp>
19+
#include <boost/function.hpp>
20+
#include <boost/asio.hpp>
21+
22+
namespace tcp_proxy
23+
{
24+
namespace ip = boost::asio::ip;
25+
26+
class tcp_bridge : public boost::enable_shared_from_this<tcp_bridge>
27+
{
28+
private:
29+
30+
typedef boost::function <void (const boost::system::error_code&, const size_t& )> handler_type;
31+
typedef ip::tcp::socket socket_type;
32+
33+
public:
34+
35+
typedef tcp_bridge type;
36+
typedef boost::shared_ptr<type> ptr_type;
37+
38+
tcp_bridge(boost::asio::io_service& ios)
39+
: client_socket_(ios),
40+
remote_socket_(ios)
41+
{}
42+
43+
socket_type& socket()
44+
{
45+
return client_socket_;
46+
}
47+
48+
void start(const std::string& remote_host, unsigned short remote_port)
49+
{
50+
remote_socket_.async_connect(
51+
ip::tcp::endpoint(
52+
boost::asio::ip::address::from_string(remote_host),
53+
remote_port),
54+
boost::bind(&type::handle_remote_connect,
55+
shared_from_this(),
56+
boost::asio::placeholders::error));
57+
}
58+
59+
void handle_remote_connect(const boost::system::error_code& error)
60+
{
61+
if (!error)
62+
{
63+
remote_write_ = boost::bind(&type::handle_remote_write,
64+
shared_from_this(),
65+
boost::asio::placeholders::error);
66+
67+
client_write_ = boost::bind(&type::handle_client_write,
68+
shared_from_this(),
69+
boost::asio::placeholders::error);
70+
71+
remote_read_ = boost::bind(&type::handle_remote_read,
72+
shared_from_this(),
73+
boost::asio::placeholders::error,
74+
boost::asio::placeholders::bytes_transferred);
75+
76+
client_read_ = boost::bind(&type::handle_client_read,
77+
shared_from_this(),
78+
boost::asio::placeholders::error,
79+
boost::asio::placeholders::bytes_transferred);
80+
81+
remote_socket_.async_read_some(
82+
boost::asio::buffer(remote_data_, max_data_length),
83+
remote_read_);
84+
85+
client_socket_.async_read_some(
86+
boost::asio::buffer(client_data_, max_data_length),
87+
client_read_);
88+
}
89+
else
90+
close();
91+
}
92+
93+
private:
94+
95+
void handle_client_write(const boost::system::error_code& error)
96+
{
97+
if (!error)
98+
{
99+
remote_socket_.async_read_some(
100+
boost::asio::buffer(remote_data_, max_data_length),
101+
remote_read_);
102+
}
103+
else
104+
close();
105+
}
106+
107+
void handle_client_read(const boost::system::error_code& error,
108+
const size_t& bytes_transferred)
109+
{
110+
if (!error)
111+
{
112+
async_write(remote_socket_,
113+
boost::asio::buffer(client_data_,bytes_transferred),
114+
remote_write_);
115+
}
116+
else
117+
close();
118+
}
119+
120+
void handle_remote_write(const boost::system::error_code& error)
121+
{
122+
if (!error)
123+
{
124+
client_socket_.async_read_some(
125+
boost::asio::buffer(client_data_, max_data_length),
126+
client_read_);
127+
}
128+
else
129+
close();
130+
}
131+
132+
void handle_remote_read(const boost::system::error_code& error,
133+
const size_t& bytes_transferred)
134+
{
135+
if (!error)
136+
{
137+
async_write(client_socket_,
138+
boost::asio::buffer(remote_data_, bytes_transferred),
139+
client_write_);
140+
}
141+
else
142+
close();
143+
}
144+
145+
void close()
146+
{
147+
if (client_socket_.is_open()) client_socket_.close();
148+
if (remote_socket_.is_open()) remote_socket_.close();
149+
}
150+
151+
socket_type client_socket_;
152+
socket_type remote_socket_;
153+
154+
enum { max_data_length = 4096 };
155+
char client_data_[max_data_length];
156+
char remote_data_[max_data_length];
157+
158+
handler_type client_write_;
159+
handler_type remote_write_;
160+
handler_type client_read_;
161+
handler_type remote_read_;
162+
163+
public:
164+
165+
static inline ptr_type create(boost::asio::io_service& ios)
166+
{
167+
return ptr_type(new type(ios));
168+
}
169+
170+
class acceptor
171+
{
172+
private:
173+
typedef boost::function<void (const boost::system::error_code&)> handler_type;
174+
175+
public:
176+
177+
acceptor(boost::asio::io_service& ios,
178+
unsigned short local_port,
179+
unsigned short remote_port,
180+
const std::string& local_host,
181+
const std::string& remote_host)
182+
: io_service_(ios),
183+
localhost_address(boost::asio::ip::address_v4::from_string(local_host)),
184+
acceptor_(ios,ip::tcp::endpoint(localhost_address,local_port)),
185+
remote_port_(remote_port),
186+
remote_host_(remote_host)
187+
{}
188+
189+
bool accept_connections()
190+
{
191+
try
192+
{
193+
session_ = type::create(io_service_);
194+
acceptor_.async_accept(session_->socket(),
195+
boost::bind(&acceptor::handle_accept,this,
196+
boost::asio::placeholders::error));
197+
}
198+
catch(std::exception& e)
199+
{
200+
std::cerr << "acceptor exception: " << e.what() << std::endl;
201+
return false;
202+
}
203+
return true;
204+
}
205+
206+
private:
207+
208+
void handle_accept(const boost::system::error_code& error)
209+
{
210+
if (!error)
211+
{
212+
session_->start(remote_host_,remote_port_);
213+
if (!accept_connections())
214+
{
215+
std::cerr << "Failed to accept." << std::endl;
216+
}
217+
}
218+
else
219+
{
220+
std::cerr << error.message() << std::endl;
221+
}
222+
}
223+
224+
boost::asio::io_service& io_service_;
225+
ip::address_v4 localhost_address;
226+
ip::tcp::acceptor acceptor_;
227+
ptr_type session_;
228+
handler_type handle_;
229+
unsigned short remote_port_;
230+
std::string remote_host_;
231+
};
232+
233+
};
234+
}
235+
236+
int main(int argc, char* argv[])
237+
{
238+
if (argc != 5)
239+
{
240+
std::cerr << "usage: tcpproxy_server <local host ip> <local port> <remote host ip> <remote port>" << std::endl;
241+
return 1;
242+
}
243+
244+
const unsigned short local_port = static_cast<unsigned short>(::atoi(argv[2]));
245+
const unsigned short remote_port = static_cast<unsigned short>(::atoi(argv[4]));
246+
const std::string local_host = argv[1];
247+
const std::string remote_host = argv[3];
248+
249+
boost::asio::io_service ios;
250+
251+
try
252+
{
253+
tcp_proxy::tcp_bridge::acceptor acceptor(ios,
254+
local_port,remote_port,
255+
local_host,remote_host);
256+
acceptor.accept_connections();
257+
ios.run();
258+
}
259+
catch(std::exception& e)
260+
{
261+
std::cerr << e.what() << std::endl;
262+
return 1;
263+
}
264+
265+
return 0;
266+
}
267+
268+
269+
/*
270+
* Note: build command:
271+
* c++ -pedantic -ansi -Wall -Werror -O3 -o tcpproxy_server tcpproxy_server.cpp -L/usr/lib -lstdc++ -lpthread -lboost_thread -lboost_system
272+
*/

0 commit comments

Comments
 (0)