-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathshinysocks.h
157 lines (120 loc) · 3.66 KB
/
shinysocks.h
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#pragma once
//#include <iostream>
#include <atomic>
#include <thread>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <memory>
#if (BOOST_VERSION >= 106900)
# define GET_IO_SERVICE_OR_EXECURTOR() get_executor()
#else
# define GET_IO_SERVICE_OR_EXECURTOR() get_io_service()
#endif
namespace shinysocks {
constexpr const char *GetProgramName() { return "ShinySocks"; }
constexpr const char *GetProgramVersion() { return SHINYSOCKS_VERSION; }
class Closer
{
public:
Closer(bool& closed) : closed_{closed} {}
~Closer() {
closed_ = true;
}
private:
bool& closed_;
};
class Manager
{
class Thread {
public:
Thread() = default;
void Start();
void Stop() {
if (!io_service_.stopped()) {
io_service_.stop();
}
}
boost::asio::io_service& GetIoService() { return io_service_; }
std::thread& GetThread() { return *thread_; }
private:
void Run();
std::unique_ptr<std::thread> thread_;
boost::asio::io_service io_service_;
};
public:
struct Conf {
int io_threads = 2;
};
Manager(Conf& conf);
boost::asio::io_service& GetSomeIoService() {
return threads_[++next_io_service_ % threads_.size()]->GetIoService();
//return threads_[0]->GetIoService();
}
void Shutdown() {
for(auto& th: threads_) {
th->Stop();
}
}
void WaitForAllThreads();
private:
std::vector<std::unique_ptr<Thread>> threads_;
std::atomic_int next_io_service_;
};
class Listener
{
public:
Listener(Manager& manager,
boost::asio::ip::tcp::endpoint endpoint);
void StartAccepting();
private:
void StartAcceptingInt(boost::asio::io_service& ios,
boost::asio::yield_context yield);
Manager& manager_;
const boost::asio::ip::tcp::endpoint endpoint_;
};
class Proxy : public std::enable_shared_from_this<Proxy>
{
public:
enum class Commands { CONNECT = 1 };
enum class ProtocolVer { INVALID = 0, SOCKS4 = 4, SOCKS5 = 5};
enum class ReplyVal { OK, REJECTED, ADDR_NOT_SUPPORTED, CONN_REFUSED,
RESOLVER_FAILED
};
Proxy(boost::asio::ip::tcp::socket&& sck);
~Proxy();
void Run(boost::asio::yield_context yield);
private:
void ParseV4Header(const char *buffer,
const size_t len,
boost::asio::yield_context& yield);
void ParseV5Header(const char *buffer,
const size_t len,
boost::asio::yield_context& yield);
void RunInt(boost::asio::yield_context& yield);
void RelayRoot(boost::asio::ip::tcp::socket& from,
boost::asio::ip::tcp::socket& to,
uint64_t& counter,
boost::asio::yield_context yield);
void Relay(boost::asio::ip::tcp::socket& from,
boost::asio::ip::tcp::socket& to,
uint64_t& counter,
boost::asio::yield_context& yield);
void Reply(ReplyVal replyCode,
boost::asio::ip::tcp::endpoint ep,
boost::asio::yield_context& yield);
int MapReplyToV4(ReplyVal code);
int MapReplyToV5(ReplyVal code);
boost::asio::ip::tcp::socket client_;
boost::asio::ip::tcp::socket server_;
bool closed_ = false;
uint64_t bytes_relayed_to_server_ = 0;
uint64_t bytes_relayed_to_client_ = 0;
int command_ = -1;
uint16_t port_ = 0;
uint32_t ipv4_ = 0;
boost::asio::ip::tcp::endpoint endpoint_;
std::string name_;
std::vector<char> remaining_buffer_;
ProtocolVer protocol_ver_ = ProtocolVer::INVALID;;
};
} // namespace