Status: | Needs review |
---|---|
Proposed branch: | lp:~maksis/adchpp/adchpp-hbri |
Merge into: | lp:adchpp |
Diff against target: |
1149 lines (+457/-101) 19 files modified
adchpp/AdcCommand.cpp (+1/-1) adchpp/AdcCommand.h (+5/-1) adchpp/Client.h (+2/-0) adchpp/ClientManager.cpp (+229/-55) adchpp/ClientManager.h (+12/-2) adchpp/Entity.cpp (+37/-3) adchpp/Entity.h (+12/-1) adchpp/ManagedSocket.cpp (+38/-2) adchpp/ManagedSocket.h (+7/-1) adchpp/ServerInfo.h (+4/-1) adchpp/SocketManager.cpp (+65/-26) adchpp/SocketManager.h (+4/-0) adchpp/Util.cpp (+5/-1) adchpp/Util.h (+2/-1) adchppd/adchppd.cpp (+7/-0) changelog.txt (+7/-0) etc/adchpp.xml (+13/-2) swig/adchpp.i (+6/-3) swig/lua.i (+1/-1) |
To merge this branch: | bzr merge lp:~maksis/adchpp/adchpp-hbri |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dcplusplus-team | Pending | ||
Review via email: mp+194959@code.launchpad.net |
Commit message
Description of the change
* Add support for hybrid IPv4/IPv6 client connectivity: http://
* [L#1088638] Allow clients to reconnect in event of overflow
* [L#1106226] Fix a crash when joining the hub with a local IPv6 address
* Make login timeout work independently from other connecting users
* Allow configuring custom bind addresses
> hmm, it's unfortunate i forgot to answer that forum post but i still don't see
> why this has to be a new extension, and especially why it needs a new
> extension.
especially why it needs a new ADC command*
maksis (maksis) wrote : | # |
> hmm, it's unfortunate i forgot to answer that forum post
I don't think that it's too late yet. Starting a third thread for protocol discussion makes it even more difficult to track later.
Janne (barajag) wrote : | # |
it's fun to see Maksis work as usual. fix the big bugs too while you are working hehe
Nice work m8
Janne (barajag) wrote : | # |
is Adch++ dead now or what??????????
Unmerged revisions
- 665. By maksis
-
Sync
- 664. By maksis
-
Merge
- 663. By maksis
-
Merge
- 662. By maksis
-
Don't strip supports for the secondary IP protocol on INF updates
- 661. By maksis
-
Remove string::pop_back() for better compatibility
- 660. By maksis
-
Readd 629 and 630
- 659. By maksis
-
Revert some changes, update changelog
- 658. By maksis
-
- Remove extra TCP/UDP supports from clients
- Dont advertise the HBRI support if there is no configured hub address for both protocols - 657. By maksis
-
HBRI works also for registered users
- 656. By maksis
-
Resolve the configured hub addresses, bug fixes
Preview Diff
1 | === modified file 'adchpp/AdcCommand.cpp' | |||
2 | --- adchpp/AdcCommand.cpp 2014-04-11 18:47:46 +0000 | |||
3 | +++ adchpp/AdcCommand.cpp 2014-05-01 19:31:53 +0000 | |||
4 | @@ -40,7 +40,7 @@ | |||
5 | 40 | AdcCommand::AdcCommand() : cmdInt(0), priority(PRIORITY_NORMAL), from(INVALID_SID), to(INVALID_SID), type(TYPE_INFO) { } | 40 | AdcCommand::AdcCommand() : cmdInt(0), priority(PRIORITY_NORMAL), from(INVALID_SID), to(INVALID_SID), type(TYPE_INFO) { } |
6 | 41 | 41 | ||
7 | 42 | AdcCommand::AdcCommand(Severity sev, Error err, const string& desc, char aType /* = TYPE_INFO */) : cmdInt(CMD_STA), priority(PRIORITY_NORMAL), from(HUB_SID), to(INVALID_SID), type(aType) { | 42 | AdcCommand::AdcCommand(Severity sev, Error err, const string& desc, char aType /* = TYPE_INFO */) : cmdInt(CMD_STA), priority(PRIORITY_NORMAL), from(HUB_SID), to(INVALID_SID), type(aType) { |
9 | 43 | addParam(Util::toString(sev * 100 + err)); | 43 | addParam((sev == SEV_SUCCESS && err == SUCCESS) ? "000" : Util::toString(sev * 100 + err)); |
10 | 44 | addParam(desc); | 44 | addParam(desc); |
11 | 45 | } | 45 | } |
12 | 46 | 46 | ||
13 | 47 | 47 | ||
14 | === modified file 'adchpp/AdcCommand.h' | |||
15 | --- adchpp/AdcCommand.h 2014-04-11 18:47:46 +0000 | |||
16 | +++ adchpp/AdcCommand.h 2014-05-01 19:31:53 +0000 | |||
17 | @@ -36,6 +36,7 @@ | |||
18 | 36 | }; | 36 | }; |
19 | 37 | 37 | ||
20 | 38 | enum Error { | 38 | enum Error { |
21 | 39 | SUCCESS = 0, | ||
22 | 39 | ERROR_GENERIC = 0, | 40 | ERROR_GENERIC = 0, |
23 | 40 | ERROR_HUB_GENERIC = 10, | 41 | ERROR_HUB_GENERIC = 10, |
24 | 41 | ERROR_HUB_FULL = 11, | 42 | ERROR_HUB_FULL = 11, |
25 | @@ -63,7 +64,8 @@ | |||
26 | 63 | ERROR_FILE_NOT_AVAILABLE = 51, | 64 | ERROR_FILE_NOT_AVAILABLE = 51, |
27 | 64 | ERROR_FILE_PART_NOT_AVAILABLE = 52, | 65 | ERROR_FILE_PART_NOT_AVAILABLE = 52, |
28 | 65 | ERROR_SLOTS_FULL = 53, | 66 | ERROR_SLOTS_FULL = 53, |
30 | 66 | ERROR_NO_CLIENT_HASH = 54 | 67 | ERROR_NO_CLIENT_HASH = 54, |
31 | 68 | ERROR_HBRI_TIMEOUT = 55 | ||
32 | 67 | }; | 69 | }; |
33 | 68 | 70 | ||
34 | 69 | enum Severity { | 71 | enum Severity { |
35 | @@ -109,6 +111,7 @@ | |||
36 | 109 | C(CMD, 'C','M','D'); | 111 | C(CMD, 'C','M','D'); |
37 | 110 | C(NAT, 'N','A','T'); | 112 | C(NAT, 'N','A','T'); |
38 | 111 | C(RNT, 'R','N','T'); | 113 | C(RNT, 'R','N','T'); |
39 | 114 | C(TCP, 'T','C','P'); | ||
40 | 112 | #undef C | 115 | #undef C |
41 | 113 | 116 | ||
42 | 114 | static const uint32_t HUB_SID = static_cast<uint32_t>(-1); | 117 | static const uint32_t HUB_SID = static_cast<uint32_t>(-1); |
43 | @@ -225,6 +228,7 @@ | |||
44 | 225 | C(CMD); | 228 | C(CMD); |
45 | 226 | C(NAT); | 229 | C(NAT); |
46 | 227 | C(RNT); | 230 | C(RNT); |
47 | 231 | C(TCP); | ||
48 | 228 | default: | 232 | default: |
49 | 229 | dcdebug("Unknown ADC command: %.50s\n", cmd.toString().c_str()); | 233 | dcdebug("Unknown ADC command: %.50s\n", cmd.toString().c_str()); |
50 | 230 | return true; | 234 | return true; |
51 | 231 | 235 | ||
52 | === modified file 'adchpp/Client.h' | |||
53 | --- adchpp/Client.h 2014-04-11 18:47:46 +0000 | |||
54 | +++ adchpp/Client.h 2014-05-01 19:31:53 +0000 | |||
55 | @@ -43,6 +43,8 @@ | |||
56 | 43 | /** @param reason The statistic to update */ | 43 | /** @param reason The statistic to update */ |
57 | 44 | ADCHPP_DLL virtual void disconnect(Util::Reason reason, const std::string &info = Util::emptyString) throw(); | 44 | ADCHPP_DLL virtual void disconnect(Util::Reason reason, const std::string &info = Util::emptyString) throw(); |
58 | 45 | const std::string& getIp() const throw() { return socket->getIp(); } | 45 | const std::string& getIp() const throw() { return socket->getIp(); } |
59 | 46 | bool getHbriParams(AdcCommand& cmd) const throw() { return socket->getHbriParams(cmd); } | ||
60 | 47 | bool isV6() const { return socket->isV6(); } | ||
61 | 46 | 48 | ||
62 | 47 | /** | 49 | /** |
63 | 48 | * Set data mode for aBytes bytes. | 50 | * Set data mode for aBytes bytes. |
64 | 49 | 51 | ||
65 | === modified file 'adchpp/ClientManager.cpp' | |||
66 | --- adchpp/ClientManager.cpp 2014-04-11 18:47:46 +0000 | |||
67 | +++ adchpp/ClientManager.cpp 2014-05-01 19:31:53 +0000 | |||
68 | @@ -20,6 +20,7 @@ | |||
69 | 20 | 20 | ||
70 | 21 | #include "ClientManager.h" | 21 | #include "ClientManager.h" |
71 | 22 | 22 | ||
72 | 23 | #include "Core.h" | ||
73 | 23 | #include "File.h" | 24 | #include "File.h" |
74 | 24 | #include "Client.h" | 25 | #include "Client.h" |
75 | 25 | #include "LogManager.h" | 26 | #include "LogManager.h" |
76 | @@ -33,6 +34,15 @@ | |||
77 | 33 | #include <boost/asio/ip/address_v6.hpp> | 34 | #include <boost/asio/ip/address_v6.hpp> |
78 | 34 | #include <boost/locale.hpp> | 35 | #include <boost/locale.hpp> |
79 | 35 | 36 | ||
80 | 37 | #include <boost/range/algorithm/find.hpp> | ||
81 | 38 | #include <boost/range/algorithm/find_if.hpp> | ||
82 | 39 | #include <boost/range/algorithm/remove_if.hpp> | ||
83 | 40 | #include <boost/range/adaptor/map.hpp> | ||
84 | 41 | |||
85 | 42 | using boost::adaptors::map_values; | ||
86 | 43 | using boost::range::find; | ||
87 | 44 | using boost::range::find_if; | ||
88 | 45 | |||
89 | 36 | namespace adchpp { | 46 | namespace adchpp { |
90 | 37 | 47 | ||
91 | 38 | using namespace std; | 48 | using namespace std; |
92 | @@ -43,10 +53,52 @@ | |||
93 | 43 | core(core), | 53 | core(core), |
94 | 44 | hub(*this), | 54 | hub(*this), |
95 | 45 | maxCommandSize(16 * 1024), | 55 | maxCommandSize(16 * 1024), |
97 | 46 | logTimeout(30 * 1000) | 56 | logTimeout(30 * 1000), |
98 | 57 | hbriTimeout(5000) | ||
99 | 47 | { | 58 | { |
100 | 59 | core.getSocketManager().addTimedJob(1000, std::bind(&ClientManager::onTimerSecond, this)); | ||
101 | 60 | } | ||
102 | 61 | |||
103 | 62 | void ClientManager::prepareSupports(bool addHbri) { | ||
104 | 48 | hub.addSupports(AdcCommand::toFourCC("BASE")); | 63 | hub.addSupports(AdcCommand::toFourCC("BASE")); |
105 | 49 | hub.addSupports(AdcCommand::toFourCC("TIGR")); | 64 | hub.addSupports(AdcCommand::toFourCC("TIGR")); |
106 | 65 | |||
107 | 66 | if (addHbri) | ||
108 | 67 | hub.addSupports(AdcCommand::toFourCC("HBRI")); | ||
109 | 68 | } | ||
110 | 69 | |||
111 | 70 | void ClientManager::onTimerSecond() { | ||
112 | 71 | // HBRI | ||
113 | 72 | auto timeoutHbri = time::now() - time::millisec(hbriTimeout); | ||
114 | 73 | for (auto i = hbriTokens.begin(); i != hbriTokens.end();) { | ||
115 | 74 | if (timeoutHbri > i->second.second) { | ||
116 | 75 | auto cc = dynamic_cast<Client*>(i->second.first); | ||
117 | 76 | i = hbriTokens.erase(i); | ||
118 | 77 | |||
119 | 78 | dcdebug("ClientManager: HBRI timeout in state %d\n", cc->getState()); | ||
120 | 79 | |||
121 | 80 | std::string proto = cc->isV6() ? "IPv4" : "IPv6"; | ||
122 | 81 | AdcCommand sta(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_HBRI_TIMEOUT, proto + " validation timed out"); | ||
123 | 82 | cc->send(sta); | ||
124 | 83 | |||
125 | 84 | cc->unsetFlag(Entity::FLAG_VALIDATE_HBRI); | ||
126 | 85 | cc->stripProtocolSupports(); | ||
127 | 86 | if (cc->getState() == Entity::STATE_HBRI) | ||
128 | 87 | enterNormal(*cc, true, true); | ||
129 | 88 | } else { | ||
130 | 89 | i++; | ||
131 | 90 | } | ||
132 | 91 | } | ||
133 | 92 | |||
134 | 93 | // Logins | ||
135 | 94 | auto timeoutLogin = time::now() - time::millisec(getLogTimeout()); | ||
136 | 95 | while (!logins.empty() && (timeoutLogin > logins.front().second)) { | ||
137 | 96 | auto cc = logins.front().first; | ||
138 | 97 | |||
139 | 98 | dcdebug("ClientManager: Login timeout in state %d\n", cc->getState()); | ||
140 | 99 | cc->disconnect(Util::REASON_LOGIN_TIMEOUT); | ||
141 | 100 | logins.pop_front(); | ||
142 | 101 | } | ||
143 | 50 | } | 102 | } |
144 | 51 | 103 | ||
145 | 52 | Bot* ClientManager::createBot(const Bot::SendHandler& handler) { | 104 | Bot* ClientManager::createBot(const Bot::SendHandler& handler) { |
146 | @@ -149,16 +201,6 @@ | |||
147 | 149 | 201 | ||
148 | 150 | void ClientManager::onConnected(Client& c) throw() { | 202 | void ClientManager::onConnected(Client& c) throw() { |
149 | 151 | dcdebug("%s connected\n", AdcCommand::fromSID(c.getSID()).c_str()); | 203 | dcdebug("%s connected\n", AdcCommand::fromSID(c.getSID()).c_str()); |
150 | 152 | // First let's check if any clients have passed the login timeout... | ||
151 | 153 | auto timeout = time::now() - time::millisec(getLogTimeout()); | ||
152 | 154 | |||
153 | 155 | while(!logins.empty() && (timeout > logins.front().second)) { | ||
154 | 156 | Client* cc = logins.front().first; | ||
155 | 157 | |||
156 | 158 | dcdebug("ClientManager: Login timeout in state %d\n", cc->getState()); | ||
157 | 159 | cc->disconnect(Util::REASON_LOGIN_TIMEOUT); | ||
158 | 160 | logins.pop_front(); | ||
159 | 161 | } | ||
160 | 162 | 204 | ||
161 | 163 | logins.push_back(make_pair(&c, time::now())); | 205 | logins.push_back(make_pair(&c, time::now())); |
162 | 164 | 206 | ||
163 | @@ -225,6 +267,7 @@ | |||
164 | 225 | badState(c, cmd); | 267 | badState(c, cmd); |
165 | 226 | return false; | 268 | return false; |
166 | 227 | } | 269 | } |
167 | 270 | |||
168 | 228 | return true; | 271 | return true; |
169 | 229 | } | 272 | } |
170 | 230 | 273 | ||
171 | @@ -245,26 +288,32 @@ | |||
172 | 245 | } | 288 | } |
173 | 246 | 289 | ||
174 | 247 | bool ClientManager::verifyINF(Entity& c, AdcCommand& cmd) throw() { | 290 | bool ClientManager::verifyINF(Entity& c, AdcCommand& cmd) throw() { |
175 | 291 | if (!verifyCID(c, cmd)) | ||
176 | 292 | return false; | ||
177 | 293 | |||
178 | 294 | if (!verifyNick(c, cmd)) | ||
179 | 295 | return false; | ||
180 | 296 | |||
181 | 297 | if (cmd.getParam("DE", 0, strtmp)) { | ||
182 | 298 | if (!Util::validateCharset(strtmp, 32)) { | ||
183 | 299 | disconnect(c, Util::REASON_INVALID_DESCRIPTION, "Invalid character in description"); | ||
184 | 300 | return false; | ||
185 | 301 | } | ||
186 | 302 | } | ||
187 | 303 | |||
188 | 248 | Client* cc = dynamic_cast<Client*>(&c); | 304 | Client* cc = dynamic_cast<Client*>(&c); |
189 | 249 | 305 | ||
190 | 250 | if(cc) { | 306 | if(cc) { |
207 | 251 | if(!verifyIp(*cc, cmd)) | 307 | if(!verifyIp(*cc, cmd, false)) |
208 | 252 | return false; | 308 | return false; |
209 | 253 | } | 309 | } |
210 | 254 | 310 | ||
195 | 255 | if(!verifyCID(c, cmd)) | ||
196 | 256 | return false; | ||
197 | 257 | |||
198 | 258 | if(!verifyNick(c, cmd)) | ||
199 | 259 | return false; | ||
200 | 260 | |||
201 | 261 | if(cmd.getParam("DE", 0, strtmp)) { | ||
202 | 262 | if(!Util::validateCharset(strtmp, 32)) { | ||
203 | 263 | disconnect(c, Util::REASON_INVALID_DESCRIPTION, "Invalid character in description"); | ||
204 | 264 | return false; | ||
205 | 265 | } | ||
206 | 266 | } | ||
211 | 267 | c.updateFields(cmd); | 311 | c.updateFields(cmd); |
212 | 312 | |||
213 | 313 | string tmp; | ||
214 | 314 | if (cmd.getParam("SU", 0, tmp) && !c.isSet(Entity::FLAG_VALIDATE_HBRI) && c.getState() != Entity::STATE_HBRI) | ||
215 | 315 | c.stripProtocolSupports(); | ||
216 | 316 | |||
217 | 268 | return true; | 317 | return true; |
218 | 269 | } | 318 | } |
219 | 270 | 319 | ||
220 | @@ -307,13 +356,35 @@ | |||
221 | 307 | } | 356 | } |
222 | 308 | 357 | ||
223 | 309 | if(overflowing > 3 && overflowing > (entities.size() / 4)) { | 358 | if(overflowing > 3 && overflowing > (entities.size() / 4)) { |
225 | 310 | disconnect(c, Util::REASON_NO_BANDWIDTH, "Not enough bandwidth available, please try again later", AdcCommand::ERROR_HUB_FULL); | 359 | disconnect(c, Util::REASON_NO_BANDWIDTH, "Not enough bandwidth available, please try again later", AdcCommand::ERROR_HUB_FULL, Util::emptyString, 1); |
226 | 311 | return false; | 360 | return false; |
227 | 312 | } | 361 | } |
228 | 313 | 362 | ||
229 | 314 | return true; | 363 | return true; |
230 | 315 | } | 364 | } |
231 | 316 | 365 | ||
232 | 366 | bool ClientManager::sendHBRI(Entity& c) { | ||
233 | 367 | if (c.hasSupport(AdcCommand::toFourCC("HBRI"))) { | ||
234 | 368 | AdcCommand cmd(AdcCommand::CMD_TCP); | ||
235 | 369 | if (!dynamic_cast<Client*>(&c)->getHbriParams(cmd)) { | ||
236 | 370 | return false; | ||
237 | 371 | } | ||
238 | 372 | |||
239 | 373 | c.setFlag(Entity::FLAG_VALIDATE_HBRI); | ||
240 | 374 | if (c.getState() != Entity::STATE_NORMAL) | ||
241 | 375 | c.setState(Entity::STATE_HBRI); | ||
242 | 376 | |||
243 | 377 | auto token = Util::toString(Util::rand()); | ||
244 | 378 | hbriTokens.insert(make_pair(token, make_pair(&c, time::now()))); | ||
245 | 379 | |||
246 | 380 | cmd.addParam("TO", token); | ||
247 | 381 | c.send(cmd); | ||
248 | 382 | return true; | ||
249 | 383 | } | ||
250 | 384 | |||
251 | 385 | return false; | ||
252 | 386 | } | ||
253 | 387 | |||
254 | 317 | bool ClientManager::handle(AdcCommand::INF, Entity& c, AdcCommand& cmd) throw() { | 388 | bool ClientManager::handle(AdcCommand::INF, Entity& c, AdcCommand& cmd) throw() { |
255 | 318 | if(c.getState() != Entity::STATE_IDENTIFY && c.getState() != Entity::STATE_NORMAL) { | 389 | if(c.getState() != Entity::STATE_IDENTIFY && c.getState() != Entity::STATE_NORMAL) { |
256 | 319 | badState(c, cmd); | 390 | badState(c, cmd); |
257 | @@ -335,23 +406,98 @@ | |||
258 | 335 | return true; | 406 | return true; |
259 | 336 | } | 407 | } |
260 | 337 | 408 | ||
262 | 338 | bool ClientManager::verifyIp(Client& c, AdcCommand& cmd) throw() { | 409 | static const int allowedCount = 3; |
263 | 410 | static const char* allowedV4[allowedCount] = { "I4", "U4", "SU" }; | ||
264 | 411 | static const char* allowedV6[allowedCount] = { "I6", "U6", "SU" }; | ||
265 | 412 | bool ClientManager::handle(AdcCommand::TCP, Entity& c, AdcCommand& cmd) throw() { | ||
266 | 413 | dcdebug("Received HBRI TCP: %s", cmd.toString().c_str()); | ||
267 | 414 | |||
268 | 415 | string error; | ||
269 | 416 | string token; | ||
270 | 417 | if(cmd.getParam("TO", 0, token)) { | ||
271 | 418 | auto p = hbriTokens.find(token); | ||
272 | 419 | if (p != hbriTokens.end()) { | ||
273 | 420 | Client* mainCC = dynamic_cast<Client*>(p->second.first); | ||
274 | 421 | mainCC->unsetFlag(Entity::FLAG_VALIDATE_HBRI); | ||
275 | 422 | |||
276 | 423 | if (mainCC->getState() != Entity::STATE_HBRI && mainCC->getState() != Entity::STATE_NORMAL) { | ||
277 | 424 | badState(c, cmd); | ||
278 | 425 | return false; | ||
279 | 426 | } | ||
280 | 427 | |||
281 | 428 | hbriTokens.erase(p); | ||
282 | 429 | |||
283 | 430 | if (!verifyIp(*dynamic_cast<Client*>(&c), cmd, true)) | ||
284 | 431 | return false; | ||
285 | 432 | |||
286 | 433 | // disconnect the validation connection | ||
287 | 434 | AdcCommand sta(AdcCommand::SEV_SUCCESS, AdcCommand::SUCCESS, "Validation succeed"); | ||
288 | 435 | c.send(sta); | ||
289 | 436 | c.disconnect(Util::REASON_HBRI); | ||
290 | 437 | |||
291 | 438 | // remove extra parameters | ||
292 | 439 | auto& params = cmd.getParameters(); | ||
293 | 440 | const auto& allowed = dynamic_cast<Client*>(&c)->isV6() ? allowedV6 : allowedV4; | ||
294 | 441 | |||
295 | 442 | params.erase(boost::remove_if(params, [&](const string& s) { | ||
296 | 443 | return find(allowed, allowed + allowedCount, s.substr(0, 2)) == &allowed[allowedCount]; | ||
297 | 444 | }), params.end()); | ||
298 | 445 | |||
299 | 446 | // update the fields for the main entity | ||
300 | 447 | mainCC->updateFields(cmd); | ||
301 | 448 | |||
302 | 449 | if (mainCC->getState() == Entity::STATE_HBRI) { | ||
303 | 450 | // continue with the normal login | ||
304 | 451 | enterNormal(*mainCC, true, true); | ||
305 | 452 | } else { | ||
306 | 453 | // send the updated fields | ||
307 | 454 | AdcCommand inf(AdcCommand::CMD_INF, AdcCommand::TYPE_BROADCAST, mainCC->getSID()); | ||
308 | 455 | inf.getParameters() = cmd.getParameters(); | ||
309 | 456 | sendToAll(inf.getBuffer()); | ||
310 | 457 | } | ||
311 | 458 | return true; | ||
312 | 459 | } else { | ||
313 | 460 | error = "Unknown validation token"; | ||
314 | 461 | } | ||
315 | 462 | } else { | ||
316 | 463 | error = "Validation token missing"; | ||
317 | 464 | } | ||
318 | 465 | |||
319 | 466 | dcassert(!error.empty()); | ||
320 | 467 | AdcCommand sta(AdcCommand::SEV_FATAL, AdcCommand::ERROR_LOGIN_GENERIC, error); | ||
321 | 468 | c.send(sta); | ||
322 | 469 | |||
323 | 470 | c.disconnect(Util::REASON_HBRI); | ||
324 | 471 | return true; | ||
325 | 472 | } | ||
326 | 473 | |||
327 | 474 | bool ClientManager::verifyIp(Client& c, AdcCommand& cmd, bool isHbriConn) throw() { | ||
328 | 339 | if(c.isSet(Entity::FLAG_OK_IP)) | 475 | if(c.isSet(Entity::FLAG_OK_IP)) |
329 | 340 | return true; | 476 | return true; |
330 | 341 | 477 | ||
331 | 342 | using namespace boost::asio::ip; | 478 | using namespace boost::asio::ip; |
332 | 343 | 479 | ||
334 | 344 | auto remote = address::from_string(c.getIp()); | 480 | address remote; |
335 | 481 | |||
336 | 482 | try { | ||
337 | 483 | remote = address::from_string(c.getIp()); | ||
338 | 484 | } catch(const boost::system::system_error&) { | ||
339 | 485 | printf("Error when reading IP %s\n", c.getIp().c_str()); | ||
340 | 486 | return false; | ||
341 | 487 | } | ||
342 | 488 | |||
343 | 345 | std::string ip; | 489 | std::string ip; |
344 | 346 | 490 | ||
346 | 347 | if(remote.is_v4() || (remote.is_v6() && remote.to_v6().is_v4_mapped())) { | 491 | bool doValidation = false; |
347 | 492 | if (!c.isV6()) { | ||
348 | 348 | auto v4 = remote.is_v4() ? remote.to_v4() : remote.to_v6().to_v4(); | 493 | auto v4 = remote.is_v4() ? remote.to_v4() : remote.to_v6().to_v4(); |
349 | 349 | 494 | ||
350 | 350 | if(cmd.getParam("I4", 0, ip)) { | 495 | if(cmd.getParam("I4", 0, ip)) { |
351 | 351 | dcdebug("%s verifying IP %s\n", AdcCommand::fromSID(c.getSID()).c_str(), ip.c_str()); | 496 | dcdebug("%s verifying IP %s\n", AdcCommand::fromSID(c.getSID()).c_str(), ip.c_str()); |
352 | 352 | if(ip.empty() || address_v4::from_string(ip) == address_v4::any()) { | 497 | if(ip.empty() || address_v4::from_string(ip) == address_v4::any()) { |
353 | 353 | cmd.delParam("I4", 0); | 498 | cmd.delParam("I4", 0); |
355 | 354 | } else if(address_v4::from_string(ip) != v4 && !Util::isPrivateIp(c.getIp())) { | 499 | cmd.addParam("I4", c.getIp()); |
356 | 500 | } else if(address_v4::from_string(ip) != v4 && !Util::isPrivateIp(c.getIp(), false)) { | ||
357 | 355 | disconnect(c, Util::REASON_INVALID_IP, "Your IP is " + c.getIp() + | 501 | disconnect(c, Util::REASON_INVALID_IP, "Your IP is " + c.getIp() + |
358 | 356 | ", reconfigure your client settings", AdcCommand::ERROR_BAD_IP, "IP" + c.getIp()); | 502 | ", reconfigure your client settings", AdcCommand::ERROR_BAD_IP, "IP" + c.getIp()); |
359 | 357 | return false; | 503 | return false; |
360 | @@ -360,21 +506,24 @@ | |||
361 | 360 | } | 506 | } |
362 | 361 | } | 507 | } |
363 | 362 | 508 | ||
374 | 363 | if(!c.hasField("I4")) { | 509 | if (!isHbriConn) { |
375 | 364 | c.setField("I4", v4.to_string()); | 510 | if(!c.hasField("I4")) { |
376 | 365 | } | 511 | c.setField("I4", v4.to_string()); |
377 | 366 | 512 | } | |
378 | 367 | if(c.getState() != Entity::STATE_NORMAL) { | 513 | |
379 | 368 | cmd.addParam("I4", v4.to_string()); | 514 | string tmp; |
380 | 369 | } | 515 | doValidation = cmd.getParam("I6", 0, tmp) && !tmp.empty(); |
381 | 370 | 516 | } | |
382 | 371 | cmd.delParam("I6", 0); // We can't check this so we remove it instead...fix? | 517 | |
383 | 372 | } else if(remote.is_v6()) { | 518 | cmd.delParam("U6", 0); |
384 | 519 | cmd.delParam("I6", 0); | ||
385 | 520 | } else { | ||
386 | 373 | if(cmd.getParam("I6", 0, ip)) { | 521 | if(cmd.getParam("I6", 0, ip)) { |
387 | 374 | dcdebug("%s verifying IPv6 %s\n", AdcCommand::fromSID(c.getSID()).c_str(), ip.c_str()); | 522 | dcdebug("%s verifying IPv6 %s\n", AdcCommand::fromSID(c.getSID()).c_str(), ip.c_str()); |
388 | 375 | if(ip.empty() || address_v6::from_string(ip) == address_v6::any()) { | 523 | if(ip.empty() || address_v6::from_string(ip) == address_v6::any()) { |
389 | 376 | cmd.delParam("I6", 0); | 524 | cmd.delParam("I6", 0); |
391 | 377 | } else if(address_v6::from_string(ip) != remote.to_v6() && !Util::isPrivateIp(c.getIp())) { | 525 | cmd.addParam("I6", c.getIp()); |
392 | 526 | } else if(address_v6::from_string(ip) != remote.to_v6() && !Util::isPrivateIp(c.getIp(), true)) { | ||
393 | 378 | disconnect(c, Util::REASON_INVALID_IP, "Your IP is " + c.getIp() + | 527 | disconnect(c, Util::REASON_INVALID_IP, "Your IP is " + c.getIp() + |
394 | 379 | ", reconfigure your client settings", AdcCommand::ERROR_BAD_IP, "IP" + c.getIp()); | 528 | ", reconfigure your client settings", AdcCommand::ERROR_BAD_IP, "IP" + c.getIp()); |
395 | 380 | return false; | 529 | return false; |
396 | @@ -383,15 +532,25 @@ | |||
397 | 383 | } | 532 | } |
398 | 384 | } | 533 | } |
399 | 385 | 534 | ||
409 | 386 | if(!c.hasField("I6")) { | 535 | if (!isHbriConn) { |
410 | 387 | c.setField("I6", c.getIp()); | 536 | if (!c.hasField("I6")) { |
411 | 388 | } | 537 | c.setField("I6", c.getIp()); |
412 | 389 | 538 | } | |
413 | 390 | if(c.getState() != Entity::STATE_NORMAL) { | 539 | |
414 | 391 | cmd.addParam("I6", c.getIp()); | 540 | string tmp; |
415 | 392 | } | 541 | doValidation = cmd.getParam("I4", 0, tmp) && !tmp.empty(); |
416 | 393 | 542 | } | |
417 | 394 | cmd.delParam("I4", 0); // We can't check this so we remove it instead...fix? | 543 | |
418 | 544 | cmd.delParam("I4", 0); | ||
419 | 545 | cmd.delParam("U4", 0); | ||
420 | 546 | } | ||
421 | 547 | |||
422 | 548 | if (doValidation) { | ||
423 | 549 | if (c.getState() == Entity::STATE_NORMAL) { | ||
424 | 550 | sendHBRI(c); | ||
425 | 551 | } else { | ||
426 | 552 | c.setFlag(Entity::FLAG_VALIDATE_HBRI); | ||
427 | 553 | } | ||
428 | 395 | } | 554 | } |
429 | 396 | 555 | ||
430 | 397 | return true; | 556 | return true; |
431 | @@ -516,7 +675,7 @@ | |||
432 | 516 | signalState_(c, oldState); | 675 | signalState_(c, oldState); |
433 | 517 | } | 676 | } |
434 | 518 | 677 | ||
436 | 519 | void ClientManager::disconnect(Entity& c, Util::Reason reason, const std::string& info, AdcCommand::Error error, const std::string& staParam) { | 678 | void ClientManager::disconnect(Entity& c, Util::Reason reason, const std::string& info, AdcCommand::Error error, const std::string& staParam, int aReconnectTime) { |
437 | 520 | // send a fatal STA | 679 | // send a fatal STA |
438 | 521 | AdcCommand sta(AdcCommand::SEV_FATAL, error, info); | 680 | AdcCommand sta(AdcCommand::SEV_FATAL, error, info); |
439 | 522 | if(!staParam.empty()) | 681 | if(!staParam.empty()) |
440 | @@ -525,7 +684,7 @@ | |||
441 | 525 | 684 | ||
442 | 526 | // send a QUI | 685 | // send a QUI |
443 | 527 | c.send(AdcCommand(AdcCommand::CMD_QUI).addParam(AdcCommand::fromSID(c.getSID())) | 686 | c.send(AdcCommand(AdcCommand::CMD_QUI).addParam(AdcCommand::fromSID(c.getSID())) |
445 | 528 | .addParam("DI", "1").addParam("MS", info).addParam("TL", "-1")); | 687 | .addParam("DI", "1").addParam("MS", info).addParam("TL", Util::toString(aReconnectTime))); |
446 | 529 | 688 | ||
447 | 530 | c.disconnect(reason); | 689 | c.disconnect(reason); |
448 | 531 | } | 690 | } |
449 | @@ -562,6 +721,14 @@ | |||
450 | 562 | } | 721 | } |
451 | 563 | 722 | ||
452 | 564 | bool ClientManager::enterNormal(Entity& c, bool sendData, bool sendOwnInf) throw() { | 723 | bool ClientManager::enterNormal(Entity& c, bool sendData, bool sendOwnInf) throw() { |
453 | 724 | if (c.isSet(Entity::FLAG_VALIDATE_HBRI)) { | ||
454 | 725 | if (sendHBRI(c)) { | ||
455 | 726 | return false; | ||
456 | 727 | } | ||
457 | 728 | |||
458 | 729 | c.unsetFlag(Entity::FLAG_VALIDATE_HBRI); | ||
459 | 730 | } | ||
460 | 731 | |||
461 | 565 | dcassert(c.getState() == Entity::STATE_IDENTIFY || c.getState() == Entity::STATE_VERIFY); | 732 | dcassert(c.getState() == Entity::STATE_IDENTIFY || c.getState() == Entity::STATE_VERIFY); |
462 | 566 | dcdebug("%s entering NORMAL\n", AdcCommand::fromSID(c.getSID()).c_str()); | 733 | dcdebug("%s entering NORMAL\n", AdcCommand::fromSID(c.getSID()).c_str()); |
463 | 567 | 734 | ||
464 | @@ -596,6 +763,13 @@ | |||
465 | 596 | if(i != logins.end()) { | 763 | if(i != logins.end()) { |
466 | 597 | logins.erase(i); | 764 | logins.erase(i); |
467 | 598 | } | 765 | } |
468 | 766 | |||
469 | 767 | if (e.hasSupport(AdcCommand::toFourCC("HBRI"))) { | ||
470 | 768 | auto i = find_if(hbriTokens | map_values, CompareFirst<Entity*, time::ptime>(c)).base(); | ||
471 | 769 | if (i != hbriTokens.end()) { | ||
472 | 770 | hbriTokens.erase(i); | ||
473 | 771 | } | ||
474 | 772 | } | ||
475 | 599 | } | 773 | } |
476 | 600 | 774 | ||
477 | 601 | void ClientManager::removeEntity(Entity& c, Util::Reason reason, const std::string &info) throw() { | 775 | void ClientManager::removeEntity(Entity& c, Util::Reason reason, const std::string &info) throw() { |
478 | @@ -644,4 +818,4 @@ | |||
479 | 644 | removeEntity(c, reason, info); | 818 | removeEntity(c, reason, info); |
480 | 645 | } | 819 | } |
481 | 646 | 820 | ||
483 | 647 | } | 821 | } |
484 | 648 | \ No newline at end of file | 822 | \ No newline at end of file |
485 | 649 | 823 | ||
486 | === modified file 'adchpp/ClientManager.h' | |||
487 | --- adchpp/ClientManager.h 2014-04-11 18:47:46 +0000 | |||
488 | +++ adchpp/ClientManager.h 2014-05-01 19:31:53 +0000 | |||
489 | @@ -131,7 +131,7 @@ | |||
490 | 131 | /** | 131 | /** |
491 | 132 | * Verify that IP is correct and replace any zero addresses. | 132 | * Verify that IP is correct and replace any zero addresses. |
492 | 133 | */ | 133 | */ |
494 | 134 | ADCHPP_DLL bool verifyIp(Client& c, AdcCommand& cmd) throw(); | 134 | ADCHPP_DLL bool verifyIp(Client& c, AdcCommand& cmd, bool isHbriConn) throw(); |
495 | 135 | 135 | ||
496 | 136 | /** | 136 | /** |
497 | 137 | * Verify that CID is correct and corresponds to PID | 137 | * Verify that CID is correct and corresponds to PID |
498 | @@ -169,10 +169,13 @@ | |||
499 | 169 | void setMaxCommandSize(size_t newSize) { maxCommandSize = newSize; } | 169 | void setMaxCommandSize(size_t newSize) { maxCommandSize = newSize; } |
500 | 170 | size_t getMaxCommandSize() const { return maxCommandSize; } | 170 | size_t getMaxCommandSize() const { return maxCommandSize; } |
501 | 171 | 171 | ||
502 | 172 | void setHbriTimeout(size_t millis) { hbriTimeout = millis; } | ||
503 | 173 | size_t getHbriTimeout() const { return hbriTimeout; } | ||
504 | 172 | void setLogTimeout(size_t millis) { logTimeout = millis; } | 174 | void setLogTimeout(size_t millis) { logTimeout = millis; } |
505 | 173 | size_t getLogTimeout() const { return logTimeout; } | 175 | size_t getLogTimeout() const { return logTimeout; } |
506 | 174 | 176 | ||
507 | 175 | Core &getCore() const { return core; } | 177 | Core &getCore() const { return core; } |
508 | 178 | void prepareSupports(bool addHbri); | ||
509 | 176 | private: | 179 | private: |
510 | 177 | friend class Core; | 180 | friend class Core; |
511 | 178 | friend class Client; | 181 | friend class Client; |
512 | @@ -183,6 +186,9 @@ | |||
513 | 183 | 186 | ||
514 | 184 | std::list<std::pair<Client*, time::ptime> > logins; | 187 | std::list<std::pair<Client*, time::ptime> > logins; |
515 | 185 | 188 | ||
516 | 189 | typedef std::unordered_map<std::string, std::pair<Entity*, time::ptime>> TokenMap; | ||
517 | 190 | TokenMap hbriTokens; | ||
518 | 191 | |||
519 | 186 | EntityMap entities; | 192 | EntityMap entities; |
520 | 187 | typedef std::unordered_map<std::string, Entity*> NickMap; | 193 | typedef std::unordered_map<std::string, Entity*> NickMap; |
521 | 188 | NickMap nicks; | 194 | NickMap nicks; |
522 | @@ -193,6 +199,7 @@ | |||
523 | 193 | 199 | ||
524 | 194 | size_t maxCommandSize; | 200 | size_t maxCommandSize; |
525 | 195 | size_t logTimeout; | 201 | size_t logTimeout; |
526 | 202 | size_t hbriTimeout; | ||
527 | 196 | 203 | ||
528 | 197 | // Temporary string to use whenever a temporary string is needed (to avoid (de)allocating memory all the time...) | 204 | // Temporary string to use whenever a temporary string is needed (to avoid (de)allocating memory all the time...) |
529 | 198 | std::string strtmp; | 205 | std::string strtmp; |
530 | @@ -203,6 +210,7 @@ | |||
531 | 203 | 210 | ||
532 | 204 | uint32_t makeSID(); | 211 | uint32_t makeSID(); |
533 | 205 | 212 | ||
534 | 213 | bool sendHBRI(Entity& c); | ||
535 | 206 | void maybeSend(Entity& c, const AdcCommand& cmd); | 214 | void maybeSend(Entity& c, const AdcCommand& cmd); |
536 | 207 | 215 | ||
537 | 208 | void removeLogins(Entity& c) throw(); | 216 | void removeLogins(Entity& c) throw(); |
538 | @@ -210,6 +218,7 @@ | |||
539 | 210 | 218 | ||
540 | 211 | bool handle(AdcCommand::SUP, Entity& c, AdcCommand& cmd) throw(); | 219 | bool handle(AdcCommand::SUP, Entity& c, AdcCommand& cmd) throw(); |
541 | 212 | bool handle(AdcCommand::INF, Entity& c, AdcCommand& cmd) throw(); | 220 | bool handle(AdcCommand::INF, Entity& c, AdcCommand& cmd) throw(); |
542 | 221 | bool handle(AdcCommand::TCP, Entity& c, AdcCommand& cmd) throw(); | ||
543 | 213 | bool handleDefault(Entity& c, AdcCommand& cmd) throw(); | 222 | bool handleDefault(Entity& c, AdcCommand& cmd) throw(); |
544 | 214 | 223 | ||
545 | 215 | template<typename T> bool handle(T, Entity& c, AdcCommand& cmd) throw() { return handleDefault(c, cmd); } | 224 | template<typename T> bool handle(T, Entity& c, AdcCommand& cmd) throw() { return handleDefault(c, cmd); } |
546 | @@ -225,7 +234,7 @@ | |||
547 | 225 | void badState(Entity& c, const AdcCommand& cmd) throw(); | 234 | void badState(Entity& c, const AdcCommand& cmd) throw(); |
548 | 226 | /** send a fatal STA, a QUI with TL-1, then disconnect. */ | 235 | /** send a fatal STA, a QUI with TL-1, then disconnect. */ |
549 | 227 | void disconnect(Entity& c, Util::Reason reason, const std::string& info, | 236 | void disconnect(Entity& c, Util::Reason reason, const std::string& info, |
551 | 228 | AdcCommand::Error error = AdcCommand::ERROR_PROTOCOL_GENERIC, const std::string& staParam = Util::emptyString); | 237 | AdcCommand::Error error = AdcCommand::ERROR_PROTOCOL_GENERIC, const std::string& staParam = Util::emptyString, int aReconnectTime = -1); |
552 | 229 | 238 | ||
553 | 230 | SignalConnected::Signal signalConnected_; | 239 | SignalConnected::Signal signalConnected_; |
554 | 231 | SignalReady::Signal signalReady_; | 240 | SignalReady::Signal signalReady_; |
555 | @@ -236,6 +245,7 @@ | |||
556 | 236 | SignalDisconnected::Signal signalDisconnected_; | 245 | SignalDisconnected::Signal signalDisconnected_; |
557 | 237 | 246 | ||
558 | 238 | ClientManager(Core &core) throw(); | 247 | ClientManager(Core &core) throw(); |
559 | 248 | void onTimerSecond(); | ||
560 | 239 | }; | 249 | }; |
561 | 240 | 250 | ||
562 | 241 | } | 251 | } |
563 | 242 | 252 | ||
564 | === modified file 'adchpp/Entity.cpp' | |||
565 | --- adchpp/Entity.cpp 2014-04-11 18:47:46 +0000 | |||
566 | +++ adchpp/Entity.cpp 2014-05-01 19:31:53 +0000 | |||
567 | @@ -48,10 +48,9 @@ | |||
568 | 48 | 48 | ||
569 | 49 | if(code == AdcCommand::toField("SU")) { | 49 | if(code == AdcCommand::toField("SU")) { |
570 | 50 | filters.clear(); | 50 | filters.clear(); |
573 | 51 | 51 | if ((value.size() + 1) % 5 == 0) { | |
572 | 52 | if((value.size() + 1) % 5 == 0) { | ||
574 | 53 | filters.reserve((value.size() + 1) / 5); | 52 | filters.reserve((value.size() + 1) / 5); |
576 | 54 | for(size_t i = 0; i < value.size(); i += 5) { | 53 | for (size_t i = 0; i < value.size(); i += 5) { |
577 | 55 | filters.push_back(AdcCommand::toFourCC(value.data() + i)); | 54 | filters.push_back(AdcCommand::toFourCC(value.data() + i)); |
578 | 56 | } | 55 | } |
579 | 57 | } | 56 | } |
580 | @@ -154,6 +153,41 @@ | |||
581 | 154 | } | 153 | } |
582 | 155 | } | 154 | } |
583 | 156 | 155 | ||
584 | 156 | bool Entity::hasClientSupport(uint32_t feature) const { | ||
585 | 157 | return std::find(filters.begin(), filters.end(), feature) != filters.end(); | ||
586 | 158 | } | ||
587 | 159 | |||
588 | 160 | bool Entity::removeClientSupport(uint32_t feature) { | ||
589 | 161 | auto f = std::find(filters.begin(), filters.end(), feature); | ||
590 | 162 | if (f == filters.end()) { | ||
591 | 163 | return false; | ||
592 | 164 | } | ||
593 | 165 | |||
594 | 166 | filters.erase(f); | ||
595 | 167 | |||
596 | 168 | auto& supports = fields.find(AdcCommand::toField("SU"))->second; | ||
597 | 169 | |||
598 | 170 | auto p = supports.find(AdcCommand::fromFourCC(feature)); | ||
599 | 171 | dcassert(p != std::string::npos); | ||
600 | 172 | supports.erase(p, 5); | ||
601 | 173 | |||
602 | 174 | if (!supports.empty() && supports.back() == ',') | ||
603 | 175 | supports.erase(supports.size() - 1); | ||
604 | 176 | |||
605 | 177 | return true; | ||
606 | 178 | } | ||
607 | 179 | |||
608 | 180 | static const int protoSupportCount = 2; | ||
609 | 181 | static uint32_t supports4[protoSupportCount] = { AdcCommand::toFourCC("TCP4"), AdcCommand::toFourCC("UDP4") }; | ||
610 | 182 | static uint32_t supports6[protoSupportCount] = { AdcCommand::toFourCC("TCP6"), AdcCommand::toFourCC("UDP6") }; | ||
611 | 183 | |||
612 | 184 | void Entity::stripProtocolSupports() throw() { | ||
613 | 185 | const auto& sup = dynamic_cast<Client*>(this)->isV6() ? supports4 : supports6; | ||
614 | 186 | for (auto i = 0; i < protoSupportCount; ++i) { | ||
615 | 187 | removeClientSupport(sup[i]); | ||
616 | 188 | } | ||
617 | 189 | } | ||
618 | 190 | |||
619 | 157 | bool Entity::isFiltered(const std::string& features) const { | 191 | bool Entity::isFiltered(const std::string& features) const { |
620 | 158 | if(filters.empty()) { | 192 | if(filters.empty()) { |
621 | 159 | return true; | 193 | return true; |
622 | 160 | 194 | ||
623 | === modified file 'adchpp/Entity.h' | |||
624 | --- adchpp/Entity.h 2014-04-11 18:47:46 +0000 | |||
625 | +++ adchpp/Entity.h 2014-05-01 19:31:53 +0000 | |||
626 | @@ -33,6 +33,8 @@ | |||
627 | 33 | enum State { | 33 | enum State { |
628 | 34 | /** Initial protocol negotiation (wait for SUP) */ | 34 | /** Initial protocol negotiation (wait for SUP) */ |
629 | 35 | STATE_PROTOCOL, | 35 | STATE_PROTOCOL, |
630 | 36 | /** Validating the secondary address */ | ||
631 | 37 | STATE_HBRI, | ||
632 | 36 | /** Identify the connecting client (wait for INF) */ | 38 | /** Identify the connecting client (wait for INF) */ |
633 | 37 | STATE_IDENTIFY, | 39 | STATE_IDENTIFY, |
634 | 38 | /** Verify the client (wait for PAS) */ | 40 | /** Verify the client (wait for PAS) */ |
635 | @@ -63,7 +65,10 @@ | |||
636 | 63 | FLAG_OK_IP = 0x400, | 65 | FLAG_OK_IP = 0x400, |
637 | 64 | 66 | ||
638 | 65 | /** This entity is now a ghost being disconnected, totally ignored by ADCH++ */ | 67 | /** This entity is now a ghost being disconnected, totally ignored by ADCH++ */ |
640 | 66 | FLAG_GHOST = 0x800 | 68 | FLAG_GHOST = 0x800, |
641 | 69 | |||
642 | 70 | /** Set in the login phase if the users provides an IP for another protocol **/ | ||
643 | 71 | FLAG_VALIDATE_HBRI = 0x1000 | ||
644 | 67 | }; | 72 | }; |
645 | 68 | 73 | ||
646 | 69 | 74 | ||
647 | @@ -87,6 +92,12 @@ | |||
648 | 87 | ADCHPP_DLL bool hasSupport(uint32_t feature) const; | 92 | ADCHPP_DLL bool hasSupport(uint32_t feature) const; |
649 | 88 | ADCHPP_DLL bool removeSupports(uint32_t feature); | 93 | ADCHPP_DLL bool removeSupports(uint32_t feature); |
650 | 89 | 94 | ||
651 | 95 | ADCHPP_DLL bool hasClientSupport(uint32_t feature) const; | ||
652 | 96 | ADCHPP_DLL bool removeClientSupport(uint32_t feature); | ||
653 | 97 | |||
654 | 98 | /** Remove supports for the protocol that wasn't used for connecting **/ | ||
655 | 99 | ADCHPP_DLL void stripProtocolSupports() throw(); | ||
656 | 100 | |||
657 | 90 | ADCHPP_DLL const BufferPtr& getSUP() const; | 101 | ADCHPP_DLL const BufferPtr& getSUP() const; |
658 | 91 | 102 | ||
659 | 92 | uint32_t getSID() const { return sid; } | 103 | uint32_t getSID() const { return sid; } |
660 | 93 | 104 | ||
661 | === modified file 'adchpp/ManagedSocket.cpp' | |||
662 | --- adchpp/ManagedSocket.cpp 2014-04-11 18:47:46 +0000 | |||
663 | +++ adchpp/ManagedSocket.cpp 2014-05-01 19:31:53 +0000 | |||
664 | @@ -22,18 +22,21 @@ | |||
665 | 22 | 22 | ||
666 | 23 | #include "SocketManager.h" | 23 | #include "SocketManager.h" |
667 | 24 | 24 | ||
668 | 25 | #include <boost/asio/ip/address.hpp> | ||
669 | 26 | |||
670 | 25 | namespace adchpp { | 27 | namespace adchpp { |
671 | 26 | 28 | ||
672 | 27 | using namespace std; | 29 | using namespace std; |
673 | 28 | 30 | ||
674 | 29 | using namespace boost::asio; | 31 | using namespace boost::asio; |
675 | 30 | 32 | ||
677 | 31 | ManagedSocket::ManagedSocket(SocketManager &sm, const AsyncStreamPtr &sock_) : | 33 | ManagedSocket::ManagedSocket(SocketManager &sm, const AsyncStreamPtr &sock_, const ServerInfoPtr& aServer) : |
678 | 32 | sock(sock_), | 34 | sock(sock_), |
679 | 33 | overflow(time::not_a_date_time), | 35 | overflow(time::not_a_date_time), |
680 | 34 | disc(time::not_a_date_time), | 36 | disc(time::not_a_date_time), |
681 | 35 | lastWrite(time::not_a_date_time), | 37 | lastWrite(time::not_a_date_time), |
683 | 36 | sm(sm) | 38 | sm(sm), |
684 | 39 | server(aServer) | ||
685 | 37 | { } | 40 | { } |
686 | 38 | 41 | ||
687 | 39 | ManagedSocket::~ManagedSocket() throw() { | 42 | ManagedSocket::~ManagedSocket() throw() { |
688 | @@ -251,6 +254,39 @@ | |||
689 | 251 | std::string info; | 254 | std::string info; |
690 | 252 | }; | 255 | }; |
691 | 253 | 256 | ||
692 | 257 | bool ManagedSocket::getHbriParams(AdcCommand& cmd) const throw() { | ||
693 | 258 | if (!isV6()) { | ||
694 | 259 | if (!server->address6.empty()) { | ||
695 | 260 | cmd.addParam("I6", server->address6); | ||
696 | 261 | } else { | ||
697 | 262 | return false; | ||
698 | 263 | } | ||
699 | 264 | |||
700 | 265 | cmd.addParam("P6", server->port); | ||
701 | 266 | } else { | ||
702 | 267 | if (!server->address4.empty()) { | ||
703 | 268 | cmd.addParam("I4", server->address4); | ||
704 | 269 | } else { | ||
705 | 270 | return false; | ||
706 | 271 | } | ||
707 | 272 | |||
708 | 273 | cmd.addParam("P4", server->port); | ||
709 | 274 | } | ||
710 | 275 | |||
711 | 276 | return true; | ||
712 | 277 | } | ||
713 | 278 | |||
714 | 279 | bool ManagedSocket::isV6() const throw() { | ||
715 | 280 | using namespace boost::asio::ip; | ||
716 | 281 | |||
717 | 282 | address remote; | ||
718 | 283 | remote = address::from_string(ip); | ||
719 | 284 | if (remote.is_v4() || (remote.is_v6() && remote.to_v6().is_v4_mapped())) | ||
720 | 285 | return false; | ||
721 | 286 | |||
722 | 287 | return true; | ||
723 | 288 | } | ||
724 | 289 | |||
725 | 254 | void ManagedSocket::disconnect(Util::Reason reason, const std::string &info) throw() { | 290 | void ManagedSocket::disconnect(Util::Reason reason, const std::string &info) throw() { |
726 | 255 | if(disconnecting()) { | 291 | if(disconnecting()) { |
727 | 256 | return; | 292 | return; |
728 | 257 | 293 | ||
729 | === modified file 'adchpp/ManagedSocket.h' | |||
730 | --- adchpp/ManagedSocket.h 2014-04-11 18:47:46 +0000 | |||
731 | +++ adchpp/ManagedSocket.h 2014-05-01 19:31:53 +0000 | |||
732 | @@ -22,6 +22,8 @@ | |||
733 | 22 | #include "common.h" | 22 | #include "common.h" |
734 | 23 | 23 | ||
735 | 24 | #include "forward.h" | 24 | #include "forward.h" |
736 | 25 | |||
737 | 26 | #include "AdcCommand.h" | ||
738 | 25 | #include "Signal.h" | 27 | #include "Signal.h" |
739 | 26 | #include "Util.h" | 28 | #include "Util.h" |
740 | 27 | #include "Buffer.h" | 29 | #include "Buffer.h" |
741 | @@ -35,7 +37,7 @@ | |||
742 | 35 | */ | 37 | */ |
743 | 36 | class ManagedSocket : private boost::noncopyable, public enable_shared_from_this<ManagedSocket> { | 38 | class ManagedSocket : private boost::noncopyable, public enable_shared_from_this<ManagedSocket> { |
744 | 37 | public: | 39 | public: |
746 | 38 | ManagedSocket(SocketManager &sm, const AsyncStreamPtr& sock_); | 40 | ManagedSocket(SocketManager &sm, const AsyncStreamPtr& sock_, const ServerInfoPtr& aServer); |
747 | 39 | 41 | ||
748 | 40 | /** Asynchronous write */ | 42 | /** Asynchronous write */ |
749 | 41 | ADCHPP_DLL void write(const BufferPtr& buf, bool lowPrio = false) throw(); | 43 | ADCHPP_DLL void write(const BufferPtr& buf, bool lowPrio = false) throw(); |
750 | @@ -68,6 +70,8 @@ | |||
751 | 68 | 70 | ||
752 | 69 | ~ManagedSocket() throw(); | 71 | ~ManagedSocket() throw(); |
753 | 70 | 72 | ||
754 | 73 | bool getHbriParams(AdcCommand& cmd) const throw(); | ||
755 | 74 | bool isV6() const throw(); | ||
756 | 71 | private: | 75 | private: |
757 | 72 | friend class SocketManager; | 76 | friend class SocketManager; |
758 | 73 | friend class SocketFactory; | 77 | friend class SocketFactory; |
759 | @@ -110,6 +114,8 @@ | |||
760 | 110 | FailedHandler failedHandler; | 114 | FailedHandler failedHandler; |
761 | 111 | 115 | ||
762 | 112 | SocketManager &sm; | 116 | SocketManager &sm; |
763 | 117 | |||
764 | 118 | ServerInfoPtr server; | ||
765 | 113 | }; | 119 | }; |
766 | 114 | 120 | ||
767 | 115 | } | 121 | } |
768 | 116 | 122 | ||
769 | === modified file 'adchpp/ServerInfo.h' | |||
770 | --- adchpp/ServerInfo.h 2014-04-11 18:47:46 +0000 | |||
771 | +++ adchpp/ServerInfo.h 2014-05-01 19:31:53 +0000 | |||
772 | @@ -22,7 +22,10 @@ | |||
773 | 22 | namespace adchpp { | 22 | namespace adchpp { |
774 | 23 | 23 | ||
775 | 24 | struct ServerInfo { | 24 | struct ServerInfo { |
777 | 25 | std::string ip; | 25 | std::string bind4; |
778 | 26 | std::string bind6; | ||
779 | 27 | std::string address4; | ||
780 | 28 | std::string address6; | ||
781 | 26 | std::string port; | 29 | std::string port; |
782 | 27 | 30 | ||
783 | 28 | struct TLSInfo { | 31 | struct TLSInfo { |
784 | 29 | 32 | ||
785 | === modified file 'adchpp/SocketManager.cpp' | |||
786 | --- adchpp/SocketManager.cpp 2014-04-11 18:47:46 +0000 | |||
787 | +++ adchpp/SocketManager.cpp 2014-05-01 19:31:53 +0000 | |||
788 | @@ -20,6 +20,7 @@ | |||
789 | 20 | 20 | ||
790 | 21 | #include "SocketManager.h" | 21 | #include "SocketManager.h" |
791 | 22 | 22 | ||
792 | 23 | #include "ClientManager.h" | ||
793 | 23 | #include "LogManager.h" | 24 | #include "LogManager.h" |
794 | 24 | #include "ManagedSocket.h" | 25 | #include "ManagedSocket.h" |
795 | 25 | #include "ServerInfo.h" | 26 | #include "ServerInfo.h" |
796 | @@ -47,7 +48,9 @@ | |||
797 | 47 | bufferSize(1024), | 48 | bufferSize(1024), |
798 | 48 | maxBufferSize(16 * 1024), | 49 | maxBufferSize(16 * 1024), |
799 | 49 | overflowTimeout(60 * 1000), | 50 | overflowTimeout(60 * 1000), |
801 | 50 | disconnectTimeout(10 * 1000) | 51 | disconnectTimeout(10 * 1000), |
802 | 52 | hasV4Address(false), | ||
803 | 53 | hasV6Address(false) | ||
804 | 51 | { | 54 | { |
805 | 52 | } | 55 | } |
806 | 53 | 56 | ||
807 | @@ -192,10 +195,11 @@ | |||
808 | 192 | 195 | ||
809 | 193 | class SocketFactory : public enable_shared_from_this<SocketFactory>, boost::noncopyable { | 196 | class SocketFactory : public enable_shared_from_this<SocketFactory>, boost::noncopyable { |
810 | 194 | public: | 197 | public: |
812 | 195 | SocketFactory(SocketManager& sm, const SocketManager::IncomingHandler& handler_, const ServerInfo& info, const ip::tcp::endpoint& endpoint) : | 198 | SocketFactory(SocketManager& sm, const SocketManager::IncomingHandler& handler_, ServerInfoPtr& info, const ip::tcp::endpoint& endpoint) : |
813 | 196 | sm(sm), | 199 | sm(sm), |
814 | 197 | acceptor(sm.io), | 200 | acceptor(sm.io), |
816 | 198 | handler(handler_) | 201 | handler(handler_), |
817 | 202 | si(info) | ||
818 | 199 | { | 203 | { |
819 | 200 | acceptor.open(endpoint.protocol()); | 204 | acceptor.open(endpoint.protocol()); |
820 | 201 | acceptor.set_option(socket_base::reuse_address(true)); | 205 | acceptor.set_option(socket_base::reuse_address(true)); |
821 | @@ -203,21 +207,23 @@ | |||
822 | 203 | acceptor.set_option(ip::v6_only(true)); | 207 | acceptor.set_option(ip::v6_only(true)); |
823 | 204 | } | 208 | } |
824 | 205 | 209 | ||
825 | 210 | auto a = endpoint.address().to_string(); | ||
826 | 211 | |||
827 | 206 | acceptor.bind(endpoint); | 212 | acceptor.bind(endpoint); |
828 | 207 | acceptor.listen(socket_base::max_connections); | 213 | acceptor.listen(socket_base::max_connections); |
829 | 208 | 214 | ||
830 | 209 | LOGC(sm.getCore(), SocketManager::className, | 215 | LOGC(sm.getCore(), SocketManager::className, |
831 | 210 | "Listening on " + formatEndpoint(endpoint) + | 216 | "Listening on " + formatEndpoint(endpoint) + |
833 | 211 | " (Encrypted: " + (info.secure() ? "Yes)" : "No)")); | 217 | " (Encrypted: " + (info->secure() ? "Yes)" : "No)")); |
834 | 212 | 218 | ||
835 | 213 | #ifdef HAVE_OPENSSL | 219 | #ifdef HAVE_OPENSSL |
837 | 214 | if(info.secure()) { | 220 | if(info->secure()) { |
838 | 215 | context.reset(new ssl::context(sm.io, ssl::context::tlsv1_server)); | 221 | context.reset(new ssl::context(sm.io, ssl::context::tlsv1_server)); |
839 | 216 | context->set_options(ssl::context::no_sslv2 | ssl::context::no_sslv3 | ssl::context::single_dh_use); | 222 | context->set_options(ssl::context::no_sslv2 | ssl::context::no_sslv3 | ssl::context::single_dh_use); |
840 | 217 | //context->set_password_callback(boost::bind(&server::get_password, this)); | 223 | //context->set_password_callback(boost::bind(&server::get_password, this)); |
844 | 218 | context->use_certificate_chain_file(info.TLSParams.cert); | 224 | context->use_certificate_chain_file(info->TLSParams.cert); |
845 | 219 | context->use_private_key_file(info.TLSParams.pkey, ssl::context::pem); | 225 | context->use_private_key_file(info->TLSParams.pkey, ssl::context::pem); |
846 | 220 | context->use_tmp_dh_file(info.TLSParams.dh); | 226 | context->use_tmp_dh_file(info->TLSParams.dh); |
847 | 221 | } | 227 | } |
848 | 222 | #endif | 228 | #endif |
849 | 223 | } | 229 | } |
850 | @@ -230,12 +236,12 @@ | |||
851 | 230 | #ifdef HAVE_OPENSSL | 236 | #ifdef HAVE_OPENSSL |
852 | 231 | if(context) { | 237 | if(context) { |
853 | 232 | auto s = make_shared<TLSSocketStream>(sm.io, *context); | 238 | auto s = make_shared<TLSSocketStream>(sm.io, *context); |
855 | 233 | auto socket = make_shared<ManagedSocket>(sm, s); | 239 | auto socket = make_shared<ManagedSocket>(sm, s, si); |
856 | 234 | acceptor.async_accept(s->sock.lowest_layer(), std::bind(&SocketFactory::handleAccept, shared_from_this(), std::placeholders::_1, socket)); | 240 | acceptor.async_accept(s->sock.lowest_layer(), std::bind(&SocketFactory::handleAccept, shared_from_this(), std::placeholders::_1, socket)); |
857 | 235 | } else { | 241 | } else { |
858 | 236 | #endif | 242 | #endif |
859 | 237 | auto s = make_shared<SimpleSocketStream>(sm.io); | 243 | auto s = make_shared<SimpleSocketStream>(sm.io); |
861 | 238 | auto socket = make_shared<ManagedSocket>(sm, s); | 244 | auto socket = make_shared<ManagedSocket>(sm, s, si); |
862 | 239 | acceptor.async_accept(s->sock.lowest_layer(), std::bind(&SocketFactory::handleAccept, shared_from_this(), std::placeholders::_1, socket)); | 245 | acceptor.async_accept(s->sock.lowest_layer(), std::bind(&SocketFactory::handleAccept, shared_from_this(), std::placeholders::_1, socket)); |
863 | 240 | #ifdef HAVE_OPENSSL | 246 | #ifdef HAVE_OPENSSL |
864 | 241 | } | 247 | } |
865 | @@ -245,7 +251,9 @@ | |||
866 | 245 | void handleAccept(const error_code& ec, const ManagedSocketPtr& socket) { | 251 | void handleAccept(const error_code& ec, const ManagedSocketPtr& socket) { |
867 | 246 | if(!ec) { | 252 | if(!ec) { |
868 | 247 | socket->sock->setOptions(sm.getBufferSize()); | 253 | socket->sock->setOptions(sm.getBufferSize()); |
870 | 248 | socket->setIp(socket->sock->getIp()); | 254 | auto ip = socket->sock->getIp(); |
871 | 255 | auto p = ip.find("%"); | ||
872 | 256 | socket->setIp(p != string::npos ? ip.substr(0, p) : ip); | ||
873 | 249 | } | 257 | } |
874 | 250 | 258 | ||
875 | 251 | completeAccept(ec, socket); | 259 | completeAccept(ec, socket); |
876 | @@ -263,37 +271,68 @@ | |||
877 | 263 | SocketManager &sm; | 271 | SocketManager &sm; |
878 | 264 | ip::tcp::acceptor acceptor; | 272 | ip::tcp::acceptor acceptor; |
879 | 265 | SocketManager::IncomingHandler handler; | 273 | SocketManager::IncomingHandler handler; |
881 | 266 | 274 | ServerInfoPtr si; | |
882 | 267 | #ifdef HAVE_OPENSSL | 275 | #ifdef HAVE_OPENSSL |
883 | 268 | unique_ptr<ssl::context> context; | 276 | unique_ptr<ssl::context> context; |
884 | 269 | #endif | 277 | #endif |
885 | 270 | 278 | ||
886 | 271 | }; | 279 | }; |
887 | 272 | 280 | ||
888 | 281 | void SocketManager::prepareProtocol(ServerInfoPtr& si, bool v6) { | ||
889 | 282 | const string proto = v6 ? "IPv6" : "IPv4"; | ||
890 | 283 | try { | ||
891 | 284 | using ip::tcp; | ||
892 | 285 | tcp::resolver r(io); | ||
893 | 286 | |||
894 | 287 | // Resolve the public address | ||
895 | 288 | string& hubAddress = v6 ? si->address6 : si->address4; | ||
896 | 289 | if (!hubAddress.empty()) { | ||
897 | 290 | try { | ||
898 | 291 | auto remote = r.resolve(tcp::resolver::query(v6 ? tcp::v6() : tcp::v4(), hubAddress, si->port, | ||
899 | 292 | tcp::resolver::query::address_configured | tcp::resolver::query::passive)); | ||
900 | 293 | hubAddress = remote->endpoint().address().to_string(); | ||
901 | 294 | v6 ? hasV6Address = true : hasV4Address = true; | ||
902 | 295 | } catch (const std::exception& e) { | ||
903 | 296 | LOG(SocketManager::className, "Error when resolving the " + proto + " hub address " + hubAddress + ": " + e.what()); | ||
904 | 297 | hubAddress = Util::emptyString; | ||
905 | 298 | } | ||
906 | 299 | } | ||
907 | 300 | |||
908 | 301 | // Resolve the bind address | ||
909 | 302 | auto local = r.resolve(tcp::resolver::query(v6 ? tcp::v6() : tcp::v4(), v6 ? si->bind6 : si->bind4, si->port, | ||
910 | 303 | tcp::resolver::query::address_configured | tcp::resolver::query::passive)); | ||
911 | 304 | |||
912 | 305 | for (auto i = local; i != tcp::resolver::iterator(); ++i) { | ||
913 | 306 | auto factory = make_shared<SocketFactory>(*this, incomingHandler, si, *i); | ||
914 | 307 | factory->prepareAccept(); | ||
915 | 308 | factories.push_back(factory); | ||
916 | 309 | } | ||
917 | 310 | } catch (const std::exception& e) { | ||
918 | 311 | LOG(SocketManager::className, "Error while loading " + proto + " server on port " + si->port + ": " + e.what()); | ||
919 | 312 | } | ||
920 | 313 | } | ||
921 | 314 | |||
922 | 273 | int SocketManager::run() { | 315 | int SocketManager::run() { |
923 | 316 | //Sleep(10000); | ||
924 | 274 | LOG(SocketManager::className, "Starting"); | 317 | LOG(SocketManager::className, "Starting"); |
925 | 275 | 318 | ||
926 | 276 | work.reset(new io_service::work(io)); | 319 | work.reset(new io_service::work(io)); |
927 | 277 | 320 | ||
928 | 278 | for(auto i = servers.begin(), iend = servers.end(); i != iend; ++i) { | 321 | for(auto i = servers.begin(), iend = servers.end(); i != iend; ++i) { |
929 | 279 | auto& si = *i; | 322 | auto& si = *i; |
944 | 280 | 323 | bool listenAll = si->bind4.empty() && si->bind6.empty(); | |
945 | 281 | try { | 324 | |
946 | 282 | using ip::tcp; | 325 | if (!si->bind4.empty() || listenAll) { |
947 | 283 | tcp::resolver r(io); | 326 | prepareProtocol(si, false); |
948 | 284 | auto local = r.resolve(tcp::resolver::query(si->ip, si->port, | 327 | } |
949 | 285 | tcp::resolver::query::address_configured | tcp::resolver::query::passive)); | 328 | |
950 | 286 | 329 | if (!si->bind6.empty() || listenAll) { | |
951 | 287 | for(auto i = local; i != tcp::resolver::iterator(); ++i) { | 330 | prepareProtocol(si, true); |
938 | 288 | SocketFactoryPtr factory = make_shared<SocketFactory>(*this, incomingHandler, *si, *i); | ||
939 | 289 | factory->prepareAccept(); | ||
940 | 290 | factories.push_back(factory); | ||
941 | 291 | } | ||
942 | 292 | } catch(const std::exception& e) { | ||
943 | 293 | LOG(SocketManager::className, "Error while loading server on port " + si->port +": " + e.what()); | ||
952 | 294 | } | 331 | } |
953 | 295 | } | 332 | } |
954 | 296 | 333 | ||
955 | 334 | core.getClientManager().prepareSupports(hasV4Address && hasV6Address); | ||
956 | 335 | |||
957 | 297 | io.run(); | 336 | io.run(); |
958 | 298 | 337 | ||
959 | 299 | io.reset(); | 338 | io.reset(); |
960 | 300 | 339 | ||
961 | === modified file 'adchpp/SocketManager.h' | |||
962 | --- adchpp/SocketManager.h 2014-04-11 18:47:46 +0000 | |||
963 | +++ adchpp/SocketManager.h 2014-05-01 19:31:53 +0000 | |||
964 | @@ -94,6 +94,7 @@ | |||
965 | 94 | friend class ManagedSocket; | 94 | friend class ManagedSocket; |
966 | 95 | friend class SocketFactory; | 95 | friend class SocketFactory; |
967 | 96 | 96 | ||
968 | 97 | void prepareProtocol(ServerInfoPtr& si, bool v6); | ||
969 | 97 | void closeFactories(); | 98 | void closeFactories(); |
970 | 98 | 99 | ||
971 | 99 | Core &core; | 100 | Core &core; |
972 | @@ -126,6 +127,9 @@ | |||
973 | 126 | void onLoad(const SimpleXML& xml) throw(); | 127 | void onLoad(const SimpleXML& xml) throw(); |
974 | 127 | 128 | ||
975 | 128 | SocketManager(Core &core); | 129 | SocketManager(Core &core); |
976 | 130 | |||
977 | 131 | bool hasV4Address; | ||
978 | 132 | bool hasV6Address; | ||
979 | 129 | }; | 133 | }; |
980 | 130 | 134 | ||
981 | 131 | } | 135 | } |
982 | 132 | 136 | ||
983 | === modified file 'adchpp/Util.cpp' | |||
984 | --- adchpp/Util.cpp 2014-04-11 18:47:46 +0000 | |||
985 | +++ adchpp/Util.cpp 2014-05-01 19:31:53 +0000 | |||
986 | @@ -338,7 +338,11 @@ | |||
987 | 338 | } | 338 | } |
988 | 339 | #endif | 339 | #endif |
989 | 340 | 340 | ||
991 | 341 | bool Util::isPrivateIp(std::string const& ip) { | 341 | bool Util::isPrivateIp(std::string const& ip, bool v6) { |
992 | 342 | if (v6) { | ||
993 | 343 | return strncmp(ip.c_str(), "fe80", 4) == 0; | ||
994 | 344 | } | ||
995 | 345 | |||
996 | 342 | struct in_addr addr; | 346 | struct in_addr addr; |
997 | 343 | 347 | ||
998 | 344 | addr.s_addr = inet_addr(ip.c_str()); | 348 | addr.s_addr = inet_addr(ip.c_str()); |
999 | 345 | 349 | ||
1000 | === modified file 'adchpp/Util.h' | |||
1001 | --- adchpp/Util.h 2014-04-11 18:47:46 +0000 | |||
1002 | +++ adchpp/Util.h 2014-05-01 19:31:53 +0000 | |||
1003 | @@ -102,6 +102,7 @@ | |||
1004 | 102 | REASON_INVALID_DESCRIPTION, | 102 | REASON_INVALID_DESCRIPTION, |
1005 | 103 | REASON_WRITE_TIMEOUT, | 103 | REASON_WRITE_TIMEOUT, |
1006 | 104 | REASON_SOCKET_ERROR, | 104 | REASON_SOCKET_ERROR, |
1007 | 105 | REASON_HBRI, | ||
1008 | 105 | REASON_LAST, | 106 | REASON_LAST, |
1009 | 106 | }; | 107 | }; |
1010 | 107 | 108 | ||
1011 | @@ -228,7 +229,7 @@ | |||
1012 | 228 | static uint32_t rand(uint32_t low, uint32_t high) { return rand(high-low) + low; } | 229 | static uint32_t rand(uint32_t low, uint32_t high) { return rand(high-low) + low; } |
1013 | 229 | static double randd() { return ((double)rand()) / ((double)0xffffffff); } | 230 | static double randd() { return ((double)rand()) / ((double)0xffffffff); } |
1014 | 230 | 231 | ||
1016 | 231 | ADCHPP_DLL static bool isPrivateIp(std::string const& ip); | 232 | ADCHPP_DLL static bool isPrivateIp(std::string const& ip, bool v6); |
1017 | 232 | ADCHPP_DLL static bool validateCharset(std::string const& field, int p); | 233 | ADCHPP_DLL static bool validateCharset(std::string const& field, int p); |
1018 | 233 | }; | 234 | }; |
1019 | 234 | 235 | ||
1020 | 235 | 236 | ||
1021 | === modified file 'adchppd/adchppd.cpp' | |||
1022 | --- adchppd/adchppd.cpp 2014-04-11 18:47:46 +0000 | |||
1023 | +++ adchppd/adchppd.cpp 2014-05-01 19:31:53 +0000 | |||
1024 | @@ -72,6 +72,8 @@ | |||
1025 | 72 | core.getSocketManager().setDisconnectTimeout(Util::toInt(xml.getChildData())); | 72 | core.getSocketManager().setDisconnectTimeout(Util::toInt(xml.getChildData())); |
1026 | 73 | } else if(xml.getChildName() == "LogTimeout") { | 73 | } else if(xml.getChildName() == "LogTimeout") { |
1027 | 74 | core.getClientManager().setLogTimeout(Util::toInt(xml.getChildData())); | 74 | core.getClientManager().setLogTimeout(Util::toInt(xml.getChildData())); |
1028 | 75 | } else if (xml.getChildName() == "HbriTimeout") { | ||
1029 | 76 | core.getClientManager().setHbriTimeout(Util::toInt(xml.getChildData())); | ||
1030 | 75 | } | 77 | } |
1031 | 76 | } | 78 | } |
1032 | 77 | 79 | ||
1033 | @@ -85,6 +87,11 @@ | |||
1034 | 85 | ServerInfoPtr server = make_shared<ServerInfo>(); | 87 | ServerInfoPtr server = make_shared<ServerInfo>(); |
1035 | 86 | server->port = xml.getChildAttrib("Port", Util::emptyString); | 88 | server->port = xml.getChildAttrib("Port", Util::emptyString); |
1036 | 87 | 89 | ||
1037 | 90 | server->bind4 = xml.getChildAttrib("BindAddress4", Util::emptyString); | ||
1038 | 91 | server->bind6 = xml.getChildAttrib("BindAddress6", Util::emptyString); | ||
1039 | 92 | server->address4 = xml.getChildAttrib("HubAddress4", Util::emptyString); | ||
1040 | 93 | server->address6 = xml.getChildAttrib("HubAddress6", Util::emptyString); | ||
1041 | 94 | |||
1042 | 88 | if(xml.getBoolChildAttrib("TLS")) { | 95 | if(xml.getBoolChildAttrib("TLS")) { |
1043 | 89 | server->TLSParams.cert = File::makeAbsolutePath(xml.getChildAttrib("Certificate")); | 96 | server->TLSParams.cert = File::makeAbsolutePath(xml.getChildAttrib("Certificate")); |
1044 | 90 | server->TLSParams.pkey = File::makeAbsolutePath(xml.getChildAttrib("PrivateKey")); | 97 | server->TLSParams.pkey = File::makeAbsolutePath(xml.getChildAttrib("PrivateKey")); |
1045 | 91 | 98 | ||
1046 | === modified file 'changelog.txt' | |||
1047 | --- changelog.txt 2014-04-14 17:40:14 +0000 | |||
1048 | +++ changelog.txt 2014-05-01 19:31:53 +0000 | |||
1049 | @@ -2,6 +2,13 @@ | |||
1050 | 2 | * [L#1206293] Fix crashes after calling +reload | 2 | * [L#1206293] Fix crashes after calling +reload |
1051 | 3 | * [L#1206293] Fix commands that output entity info | 3 | * [L#1206293] Fix commands that output entity info |
1052 | 4 | 4 | ||
1053 | 5 | * Add support for hybrid IPv4/IPv6 client connectivity (maksis) | ||
1054 | 6 | * [L#1088638] Allow clients to reconnect in event of overflow (maksis) | ||
1055 | 7 | * [L#1106226] Fix a crash when joining the hub with a local IPv6 address (maksis) | ||
1056 | 8 | * Make login timeout work independently from other connecting users (maksis) | ||
1057 | 9 | * Allow configuring custom bind addresses (maksis) | ||
1058 | 10 | * Improve Lua scripts | ||
1059 | 11 | |||
1060 | 5 | -- 2.11.1 2014-04-10 -- | 12 | -- 2.11.1 2014-04-10 -- |
1061 | 6 | * Improve Lua scripts | 13 | * Improve Lua scripts |
1062 | 7 | 14 | ||
1063 | 8 | 15 | ||
1064 | === modified file 'etc/adchpp.xml' | |||
1065 | --- etc/adchpp.xml 2013-07-19 19:47:27 +0000 | |||
1066 | +++ etc/adchpp.xml 2014-05-01 19:31:53 +0000 | |||
1067 | @@ -51,6 +51,10 @@ | |||
1068 | 51 | 51 | ||
1069 | 52 | <!-- Timeout (ms) before disconnecting users whose login process is taking too long. --> | 52 | <!-- Timeout (ms) before disconnecting users whose login process is taking too long. --> |
1070 | 53 | <LogTimeout>10000</LogTimeout> | 53 | <LogTimeout>10000</LogTimeout> |
1071 | 54 | |||
1072 | 55 | <!-- Timeout (ms) before aborting validation for the secondary IP protocol. | ||
1073 | 56 | The login procedure will continue normally with the primary IP protocol then. --> | ||
1074 | 57 | <HbriTimeout>3000</HbriTimeout> | ||
1075 | 54 | </Settings> | 58 | </Settings> |
1076 | 55 | 59 | ||
1077 | 56 | <Servers> | 60 | <Servers> |
1078 | @@ -59,15 +63,22 @@ | |||
1079 | 59 | 63 | ||
1080 | 60 | To create secure connections, set TLS="1" and define the following (preferably absolute) | 64 | To create secure connections, set TLS="1" and define the following (preferably absolute) |
1081 | 61 | paths: Certificate, PrivateKey, TrustedPath, DHParams. An example secure server setting: | 65 | paths: Certificate, PrivateKey, TrustedPath, DHParams. An example secure server setting: |
1083 | 62 | <Server Port="2780" TLS="1" Certificate="certs/cacert.pem" PrivateKey="certs/privkey.pem" TrustedPath="certs/trusted/" DHParams="certs/dhparam.pem"/> | 66 | <Server Port="2780" TLS="1" Certificate="certs/cacert.pem" PrivateKey="certs/privkey.pem" TrustedPath="certs/trusted/" DHParams="certs/dhparam.pem" BindAddress4="0.0.0.0" BindAddress6="::"/> |
1084 | 63 | 67 | ||
1085 | 64 | Simple OpenSSL commands to generate files used for secure connections: | 68 | Simple OpenSSL commands to generate files used for secure connections: |
1086 | 65 | openssl genrsa -out privkey.pem 2048 | 69 | openssl genrsa -out privkey.pem 2048 |
1087 | 66 | openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095 | 70 | openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095 |
1088 | 67 | openssl dhparam -outform PEM -out dhparam.pem 1024 | 71 | openssl dhparam -outform PEM -out dhparam.pem 1024 |
1090 | 68 | 72 | ||
1091 | 69 | Alternatively, you can use the cert generator contributed on | 73 | Alternatively, you can use the cert generator contributed on |
1092 | 70 | <http://launchpadlibrarian.net/31960965/Cert_Generator.7z>. | 74 | <http://launchpadlibrarian.net/31960965/Cert_Generator.7z>. |
1093 | 75 | |||
1094 | 76 | To allow hybrid connectivity, add address fields for the used protocols: HubAddress4 and HubAddress6. You may also use the same | ||
1095 | 77 | DNS entry for both if it has A and AAAA records. You may also use plain IP addresses. | ||
1096 | 78 | Example: | ||
1097 | 79 | <Server Port="2780" HubAddress4="mydomain4.net" HubAddress6="mydomain6.net"/> | ||
1098 | 80 | |||
1099 | 81 | Bind addresses may be set with: BindAddress4 and BindAddress6 (connections will be accepted for both protocols if none is set) | ||
1100 | 71 | 82 | ||
1101 | 72 | --> | 83 | --> |
1102 | 73 | <Server Port="2780"/> | 84 | <Server Port="2780"/> |
1103 | 74 | 85 | ||
1104 | === modified file 'swig/adchpp.i' | |||
1105 | --- swig/adchpp.i 2013-07-19 19:47:27 +0000 | |||
1106 | +++ swig/adchpp.i 2014-05-01 19:31:53 +0000 | |||
1107 | @@ -126,7 +126,10 @@ | |||
1108 | 126 | typedef shared_ptr<ManagedConnection> ManagedConnectionPtr; | 126 | typedef shared_ptr<ManagedConnection> ManagedConnectionPtr; |
1109 | 127 | 127 | ||
1110 | 128 | struct ServerInfo { | 128 | struct ServerInfo { |
1112 | 129 | std::string ip; | 129 | std::string bind4; |
1113 | 130 | std::string bind6; | ||
1114 | 131 | std::string address4; | ||
1115 | 132 | std::string address6; | ||
1116 | 130 | std::string port; | 133 | std::string port; |
1117 | 131 | 134 | ||
1118 | 132 | TLSInfo TLSParams; | 135 | TLSInfo TLSParams; |
1119 | @@ -291,7 +294,7 @@ | |||
1120 | 291 | static uint32_t rand(uint32_t low, uint32_t high); | 294 | static uint32_t rand(uint32_t low, uint32_t high); |
1121 | 292 | static double randd(); | 295 | static double randd(); |
1122 | 293 | 296 | ||
1124 | 294 | static bool isPrivateIp(std::string const& ip); | 297 | static bool isPrivateIp(std::string const& ip, bool v6); |
1125 | 295 | static bool validateCharset(std::string const& field, int p); | 298 | static bool validateCharset(std::string const& field, int p); |
1126 | 296 | 299 | ||
1127 | 297 | }; | 300 | }; |
1128 | @@ -723,7 +726,7 @@ | |||
1129 | 723 | bool verifyPassword(Entity& c, const std::string& password, const ByteVector& salt, const std::string& suppliedHash); | 726 | bool verifyPassword(Entity& c, const std::string& password, const ByteVector& salt, const std::string& suppliedHash); |
1130 | 724 | bool verifyHashedPassword(Entity& c, const ByteVector& hashedPassword, int64_t hashedPasswordLen, | 727 | bool verifyHashedPassword(Entity& c, const ByteVector& hashedPassword, int64_t hashedPasswordLen, |
1131 | 725 | const ByteVector& salt, const std::string& suppliedHash) throw(); | 728 | const ByteVector& salt, const std::string& suppliedHash) throw(); |
1133 | 726 | bool verifyIp(Client& c, AdcCommand& cmd) throw(); | 729 | bool verifyIp(Client& c, AdcCommand& cmd, bool isHbriConn) throw(); |
1134 | 727 | bool verifyCID(Entity& c, AdcCommand& cmd) throw(); | 730 | bool verifyCID(Entity& c, AdcCommand& cmd) throw(); |
1135 | 728 | bool verifyOverflow(Entity& c); | 731 | bool verifyOverflow(Entity& c); |
1136 | 729 | void setState(Entity& c, Entity::State newState) throw(); | 732 | void setState(Entity& c, Entity::State newState) throw(); |
1137 | 730 | 733 | ||
1138 | === modified file 'swig/lua.i' | |||
1139 | --- swig/lua.i 2014-04-13 15:01:43 +0000 | |||
1140 | +++ swig/lua.i 2014-05-01 19:31:53 +0000 | |||
1141 | @@ -322,7 +322,7 @@ | |||
1142 | 322 | if(ret) { | 322 | if(ret) { |
1143 | 323 | return *reinterpret_cast<SWIGLUA_REF*>(ret); | 323 | return *reinterpret_cast<SWIGLUA_REF*>(ret); |
1144 | 324 | } | 324 | } |
1146 | 325 | return {0, 0}; | 325 | return SWIGLUA_REF(); |
1147 | 326 | } | 326 | } |
1148 | 327 | 327 | ||
1149 | 328 | void setPluginData(const PluginDataHandle& handle, SWIGLUA_REF data) { | 328 | void setPluginData(const PluginDataHandle& handle, SWIGLUA_REF data) { |
hmm, it's unfortunate i forgot to answer that forum post but i still don't see why this has to be a new extension, and especially why it needs a new extension.
i exposed a simpler alternative here: <https:/ /bugs.launchpad .net/adchpp/ +bug/309402/ comments/ 40>
it relies on the quality of the PID/CID system, which is assumed to be reliable in ADC where hubs are trusted.