forked from hyqhyq3/avsocks
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsplice.hpp
94 lines (84 loc) · 2.89 KB
/
splice.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
* splice.hpp , implements the splice syntactics.
*/
#pragma once
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
namespace asio = boost::asio;
namespace avsocks{
#define ASIO_READ_PLACEHOLDERS asio::placeholders::error,asio::placeholders::bytes_transferred
#define ASIO_WRITE_PLACEHOLDERS asio::placeholders::error,asio::placeholders::bytes_transferred
template < class T , class S1, class S2>
class splice : public boost::enable_shared_from_this<splice<T,S1,S2> >{
public:
using boost::enable_shared_from_this<splice<T,S1,S2> >::shared_from_this;
typedef boost::shared_ptr<splice> pointer;
splice(boost::shared_ptr<T> _owner, S1& _s1, S2& _s2)
:s1(_s1),s2(_s2),owner(_owner){}
void start(){
s1.async_read_some(s1s2buf.prepare(8192),
boost::bind(&splice<T,S1,S2>::s1s2_handle_read,shared_from_this(),ASIO_READ_PLACEHOLDERS)
);
s2.async_read_some(s2s1buf.prepare(8192),
boost::bind(&splice<T,S1,S2>::s2s1_handle_read,shared_from_this(),ASIO_READ_PLACEHOLDERS)
);
}
~splice(){
}
private:
void s1s2_handle_read(const boost::system::error_code & ec, std::size_t bytes_transferred){
if(!ec){
s1s2buf.commit(bytes_transferred);
s2.async_write_some(s1s2buf.data(),
boost::bind(&splice<T,S1,S2>::s1s2_handle_write,shared_from_this(),ASIO_WRITE_PLACEHOLDERS)
);
}
else{
boost::system::error_code ec;
s2.lowest_layer().shutdown(asio::socket_base::shutdown_both,ec);//->close();
}
}
void s1s2_handle_write(const boost::system::error_code & ec, std::size_t bytes_transferred){
if(!ec){
s1s2buf.consume(bytes_transferred);
s1.async_read_some(s1s2buf.prepare(8192),
boost::bind(&splice<T,S1,S2>::s1s2_handle_read,shared_from_this(),ASIO_READ_PLACEHOLDERS)
);
}else{
boost::system::error_code ec;
s2.lowest_layer().shutdown(asio::socket_base::shutdown_both,ec);
}
}
void s2s1_handle_read(const boost::system::error_code & ec, std::size_t bytes_transferred){
if(!ec){
s2s1buf.commit(bytes_transferred);
s1.async_write_some(s2s1buf.data(),
boost::bind(&splice<T,S1,S2>::s2s1_handle_write,shared_from_this(),ASIO_WRITE_PLACEHOLDERS)
);
}else{
boost::system::error_code ec;
s1.lowest_layer().shutdown(asio::socket_base::shutdown_both,ec);
}
}
void s2s1_handle_write(const boost::system::error_code & ec, std::size_t bytes_transferred){
if(!ec){
s2s1buf.consume(bytes_transferred);
s2.async_read_some(s2s1buf.prepare(8192),
boost::bind(&splice<T,S1,S2>::s2s1_handle_read,shared_from_this(),ASIO_READ_PLACEHOLDERS)
);
}else{
boost::system::error_code ec;
s1.lowest_layer().shutdown(asio::socket_base::shutdown_both,ec);
}
}
private:
asio::streambuf s1s2buf,s2s1buf;
S1& s1; //两个 socket
S2& s2; //两个 socket
boost::shared_ptr<T> owner;
};
#undef ASIO_READ_PLACEHOLDERS
#undef ASIO_WRITE_PLACEHOLDERS
} // namespace avsocks.