~qwertitis-deactivatedaccount/linuxdcpp/i18n

276 by Razzloss
Copied dcpp/ from 0705-branch
1
/*
2
 * Copyright (C) 2001-2008 Jacek Sieka, arnetheduck on gmail point com
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
 */
18
19
#include "stdinc.h"
20
#include "DCPlusPlus.h"
21
22
#include "Socket.h"
23
24
#include "SettingsManager.h"
25
#include "TimerManager.h"
26
27
namespace dcpp {
28
29
string Socket::udpServer;
30
uint16_t Socket::udpPort;
31
32
#define checkconnected() if(!isConnected()) throw SocketException(ENOTCONN))
33
34
#ifdef _DEBUG
35
36
SocketException::SocketException(int aError) throw() {
37
	error = "SocketException: " + errorToString(aError);
38
	dcdebug("Thrown: %s\n", error.c_str());
39
}
40
41
#else // _DEBUG
42
43
SocketException::SocketException(int aError) throw() : Exception(errorToString(aError)) { }
44
45
#endif
46
47
Socket::Stats Socket::stats = { 0, 0 };
48
49
static const uint32_t SOCKS_TIMEOUT = 30000;
50
51
string SocketException::errorToString(int aError) throw() {
52
	string msg = Util::translateError(aError);
53
	if(msg.empty()) {
54
		msg = str(F_("Unknown error: 0x%1$x") % aError);
55
	}
56
	return msg;
57
}
58
59
void Socket::create(int aType /* = TYPE_TCP */) throw(SocketException) {
60
	if(sock != INVALID_SOCKET)
61
		disconnect();
62
63
	switch(aType) {
64
	case TYPE_TCP:
65
		sock = checksocket(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
66
		break;
67
	case TYPE_UDP:
68
		sock = checksocket(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
69
		break;
70
	default:
71
		dcasserta(0);
72
	}
73
	type = aType;
74
	setBlocking(true);
75
}
76
77
void Socket::accept(const Socket& listeningSocket) throw(SocketException) {
78
	if(sock != INVALID_SOCKET) {
79
		disconnect();
80
	}
81
	sockaddr_in sock_addr;
82
	socklen_t sz = sizeof(sock_addr);
83
84
	do {
85
		sock = ::accept(listeningSocket.sock, (sockaddr*)&sock_addr, &sz);
86
	} while (sock == SOCKET_ERROR && getLastError() == EINTR);
87
	check(sock);
88
89
#ifdef _WIN32
90
	// Make sure we disable any inherited windows message things for this socket.
91
	::WSAAsyncSelect(sock, NULL, 0, 0);
92
#endif
93
94
	type = TYPE_TCP;
95
96
	setIp(inet_ntoa(sock_addr.sin_addr));
97
	connected = true;
98
	setBlocking(true);
99
}
100
101
102
uint16_t Socket::bind(uint16_t aPort, const string& aIp /* = 0.0.0.0 */) throw (SocketException){
103
	sockaddr_in sock_addr;
104
105
	sock_addr.sin_family = AF_INET;
106
	sock_addr.sin_port = htons(aPort);
107
	sock_addr.sin_addr.s_addr = inet_addr(aIp.c_str());
108
	if(::bind(sock, (sockaddr *)&sock_addr, sizeof(sock_addr)) == SOCKET_ERROR) {
109
		dcdebug("Bind failed, retrying with INADDR_ANY: %s\n", SocketException(getLastError()).getError().c_str());
110
		sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
111
		check(::bind(sock, (sockaddr *)&sock_addr, sizeof(sock_addr)));
112
	}
113
	socklen_t size = sizeof(sock_addr);
114
	getsockname(sock, (sockaddr*)&sock_addr, (socklen_t*)&size);
115
	return ntohs(sock_addr.sin_port);
116
}
117
118
void Socket::listen() throw(SocketException) {
119
	check(::listen(sock, 20));
120
	connected = true;
121
}
122
123
void Socket::connect(const string& aAddr, uint16_t aPort) throw(SocketException) {
124
	sockaddr_in serv_addr;
125
126
	if(sock == INVALID_SOCKET) {
127
		create(TYPE_TCP);
128
	}
129
130
	string addr = resolve(aAddr);
131
132
	memset(&serv_addr, 0, sizeof(serv_addr));
133
	serv_addr.sin_port = htons(aPort);
134
	serv_addr.sin_family = AF_INET;
135
	serv_addr.sin_addr.s_addr = inet_addr(addr.c_str());
136
137
	int result;
138
	do {
139
		result = ::connect(sock,(sockaddr*)&serv_addr,sizeof(serv_addr));
140
	} while (result < 0 && getLastError() == EINTR);
141
	check(result, true);
142
143
	connected = true;
144
	setIp(addr);
145
}
146
147
namespace {
148
	inline uint32_t timeLeft(uint32_t start, uint32_t timeout) {
149
		if(timeout == 0) {
150
			return 0;
151
		}
152
		uint64_t now = GET_TICK();
153
		if(start + timeout < now)
154
			throw SocketException(_("Connection timeout"));
155
		return start + timeout - now;
156
	}
157
}
158
159
void Socket::socksConnect(const string& aAddr, uint16_t aPort, uint32_t timeout) throw(SocketException) {
160
161
	if(SETTING(SOCKS_SERVER).empty() || SETTING(SOCKS_PORT) == 0) {
162
		throw SocketException(_("The socks server failed establish a connection"));
163
	}
164
165
	bool oldblock = getBlocking();
166
	setBlocking(false);
167
168
	uint64_t start = GET_TICK();
169
170
	connect(SETTING(SOCKS_SERVER), static_cast<uint16_t>(SETTING(SOCKS_PORT)));
171
172
	if(wait(timeLeft(start, timeout), WAIT_CONNECT) != WAIT_CONNECT) {
173
		throw SocketException(_("The socks server failed establish a connection"));
174
	}
175
176
	socksAuth(timeLeft(start, timeout));
177
178
	ByteVector connStr;
179
180
	// Authenticated, let's get on with it...
181
	connStr.push_back(5);			// SOCKSv5
182
	connStr.push_back(1);			// Connect
183
	connStr.push_back(0);			// Reserved
184
185
	if(BOOLSETTING(SOCKS_RESOLVE)) {
186
		connStr.push_back(3);		// Address type: domain name
187
		connStr.push_back((uint8_t)aAddr.size());
188
		connStr.insert(connStr.end(), aAddr.begin(), aAddr.end());
189
	} else {
190
		connStr.push_back(1);		// Address type: IPv4;
191
		unsigned long addr = inet_addr(resolve(aAddr).c_str());
192
		uint8_t* paddr = (uint8_t*)&addr;
193
		connStr.insert(connStr.end(), paddr, paddr+4);
194
	}
195
196
	uint16_t port = htons(aPort);
197
	uint8_t* pport = (uint8_t*)&port;
198
	connStr.push_back(pport[0]);
199
	connStr.push_back(pport[1]);
200
201
	writeAll(&connStr[0], connStr.size(), timeLeft(start, timeout));
202
203
	// We assume we'll get a ipv4 address back...therefore, 10 bytes...
204
	/// @todo add support for ipv6
205
	if(readAll(&connStr[0], 10, timeLeft(start, timeout)) != 10) {
206
		throw SocketException(_("The socks server failed establish a connection"));
207
	}
208
209
	if(connStr[0] != 5 || connStr[1] != 0) {
210
		throw SocketException(_("The socks server failed establish a connection"));
211
	}
212
213
	in_addr sock_addr;
214
215
	memset(&sock_addr, 0, sizeof(sock_addr));
216
	sock_addr.s_addr = *((unsigned long*)&connStr[4]);
217
	setIp(inet_ntoa(sock_addr));
218
219
	if(oldblock)
220
		setBlocking(oldblock);
221
}
222
223
void Socket::socksAuth(uint32_t timeout) throw(SocketException) {
224
	vector<uint8_t> connStr;
225
226
	uint64_t start = GET_TICK();
227
228
	if(SETTING(SOCKS_USER).empty() && SETTING(SOCKS_PASSWORD).empty()) {
229
		// No username and pw, easier...=)
230
		connStr.push_back(5);			// SOCKSv5
231
		connStr.push_back(1);			// 1 method
232
		connStr.push_back(0);			// Method 0: No auth...
233
234
		writeAll(&connStr[0], 3, timeLeft(start, timeout));
235
236
		if(readAll(&connStr[0], 2, timeLeft(start, timeout)) != 2) {
237
			throw SocketException(_("The socks server failed establish a connection"));
238
		}
239
240
		if(connStr[1] != 0) {
241
			throw SocketException(_("The socks server requires authentication"));
242
		}
243
	} else {
244
		// We try the username and password auth type (no, we don't support gssapi)
245
246
		connStr.push_back(5);			// SOCKSv5
247
		connStr.push_back(1);			// 1 method
248
		connStr.push_back(2);			// Method 2: Name/Password...
249
		writeAll(&connStr[0], 3, timeLeft(start, timeout));
250
251
		if(readAll(&connStr[0], 2, timeLeft(start, timeout)) != 2) {
252
			throw SocketException(_("The socks server failed establish a connection"));
253
		}
254
		if(connStr[1] != 2) {
255
			throw SocketException(_("The socks server doesn't support login / password authentication"));
256
		}
257
258
		connStr.clear();
259
		// Now we send the username / pw...
260
		connStr.push_back(1);
261
		connStr.push_back((uint8_t)SETTING(SOCKS_USER).length());
262
		connStr.insert(connStr.end(), SETTING(SOCKS_USER).begin(), SETTING(SOCKS_USER).end());
263
		connStr.push_back((uint8_t)SETTING(SOCKS_PASSWORD).length());
264
		connStr.insert(connStr.end(), SETTING(SOCKS_PASSWORD).begin(), SETTING(SOCKS_PASSWORD).end());
265
266
		writeAll(&connStr[0], connStr.size(), timeLeft(start, timeout));
267
268
		if(readAll(&connStr[0], 2, timeLeft(start, timeout)) != 2) {
269
			throw SocketException(_("Socks server authentication failed (bad login / password?)"));
270
		}
271
272
		if(connStr[1] != 0) {
273
			throw SocketException(_("Socks server authentication failed (bad login / password?)"));
274
		}
275
	}
276
}
277
278
int Socket::getSocketOptInt(int option) throw(SocketException) {
279
	int val;
280
	socklen_t len = sizeof(val);
281
	check(::getsockopt(sock, SOL_SOCKET, option, (char*)&val, &len));
282
	return val;
283
}
284
285
void Socket::setSocketOpt(int option, int val) throw(SocketException) {
286
	int len = sizeof(val);
287
	check(::setsockopt(sock, SOL_SOCKET, option, (char*)&val, len));
288
}
289
290
int Socket::read(void* aBuffer, int aBufLen) throw(SocketException) {
291
	int len = 0;
292
293
	dcassert(type == TYPE_TCP || type == TYPE_UDP);
294
	do {
295
		if(type == TYPE_TCP) {
296
			len = ::recv(sock, (char*)aBuffer, aBufLen, 0);
297
		} else {
298
			len = ::recvfrom(sock, (char*)aBuffer, aBufLen, 0, NULL, NULL);
299
		}
300
	} while (len < 0 && getLastError() == EINTR);
301
	check(len, true);
302
303
	if(len > 0) {
304
		stats.totalDown += len;
305
	}
306
307
	return len;
308
}
309
310
int Socket::read(void* aBuffer, int aBufLen, string &aIP) throw(SocketException) {
311
	dcassert(type == TYPE_UDP);
312
313
	sockaddr_in remote_addr = { 0 };
314
	socklen_t addr_length = sizeof(remote_addr);
315
316
	int len;
317
	do {
318
		len = ::recvfrom(sock, (char*)aBuffer, aBufLen, 0, (sockaddr*)&remote_addr, &addr_length);
319
	} while (len < 0 && getLastError() == EINTR);
320
321
	check(len, true);
322
	if(len > 0) {
323
		aIP = inet_ntoa(remote_addr.sin_addr);
324
		stats.totalDown += len;
325
	} else {
326
		aIP.clear();
327
	}
328
	return len;
329
}
330
331
int Socket::readAll(void* aBuffer, int aBufLen, uint32_t timeout) throw(SocketException) {
332
	uint8_t* buf = (uint8_t*)aBuffer;
333
	int i = 0;
334
	while(i < aBufLen) {
335
		int j = read(buf + i, aBufLen - i);
336
		if(j == 0) {
337
			return i;
338
		} else if(j == -1) {
339
			if(wait(timeout, WAIT_READ) != WAIT_READ) {
340
				return i;
341
			}
342
			continue;
343
		}
344
345
		i += j;
346
	}
347
	return i;
348
}
349
350
void Socket::writeAll(const void* aBuffer, int aLen, uint32_t timeout) throw(SocketException) {
351
	const uint8_t* buf = (const uint8_t*)aBuffer;
352
	int pos = 0;
353
	// No use sending more than this at a time...
354
	int sendSize = getSocketOptInt(SO_SNDBUF);
355
356
	while(pos < aLen) {
357
		int i = write(buf+pos, (int)min(aLen-pos, sendSize));
358
		if(i == -1) {
359
			wait(timeout, WAIT_WRITE);
360
		} else {
361
			pos+=i;
362
			stats.totalUp += i;
363
		}
364
	}
365
}
366
367
int Socket::write(const void* aBuffer, int aLen) throw(SocketException) {
368
	int sent;
369
	do {
370
		sent = ::send(sock, (const char*)aBuffer, aLen, 0);
371
	} while (sent < 0 && getLastError() == EINTR);
372
373
	check(sent, true);
374
	if(sent > 0) {
375
		stats.totalUp += sent;
376
	}
377
	return sent;
378
}
379
380
/**
381
* Sends data, will block until all data has been sent or an exception occurs
382
* @param aBuffer Buffer with data
383
* @param aLen Data length
384
* @throw SocketExcpetion Send failed.
385
*/
386
void Socket::writeTo(const string& aAddr, uint16_t aPort, const void* aBuffer, int aLen, bool proxy) throw(SocketException) {
387
	if(aLen <= 0)
388
		return;
389
390
	uint8_t* buf = (uint8_t*)aBuffer;
391
	if(sock == INVALID_SOCKET) {
392
		create(TYPE_UDP);
393
	}
394
395
	dcassert(type == TYPE_UDP);
396
397
	sockaddr_in serv_addr;
398
399
	if(aAddr.empty() || aPort == 0) {
400
		throw SocketException(EADDRNOTAVAIL);
401
	}
402
403
	memset(&serv_addr, 0, sizeof(serv_addr));
404
405
	int sent;
406
	if(SETTING(OUTGOING_CONNECTIONS) == SettingsManager::OUTGOING_SOCKS5 && proxy) {
407
		if(udpServer.empty() || udpPort == 0) {
408
			throw SocketException(_("Failed to set up the socks server for UDP relay (check socks address and port)"));
409
		}
410
411
		serv_addr.sin_port = htons(udpPort);
412
		serv_addr.sin_family = AF_INET;
413
		serv_addr.sin_addr.s_addr = inet_addr(udpServer.c_str());
414
415
		string s = BOOLSETTING(SOCKS_RESOLVE) ? resolve(ip) : ip;
416
417
		vector<uint8_t> connStr;
418
419
		connStr.push_back(0);		// Reserved
420
		connStr.push_back(0);		// Reserved
421
		connStr.push_back(0);		// Fragment number, always 0 in our case...
422
423
		if(BOOLSETTING(SOCKS_RESOLVE)) {
424
			connStr.push_back(3);
425
			connStr.push_back((uint8_t)s.size());
426
			connStr.insert(connStr.end(), aAddr.begin(), aAddr.end());
427
		} else {
428
			connStr.push_back(1);		// Address type: IPv4;
429
			unsigned long addr = inet_addr(resolve(aAddr).c_str());
430
			uint8_t* paddr = (uint8_t*)&addr;
431
			connStr.insert(connStr.end(), paddr, paddr+4);
432
		}
433
434
		connStr.insert(connStr.end(), buf, buf + aLen);
435
436
		do {
437
			sent = ::sendto(sock, (const char*)&connStr[0], connStr.size(), 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
438
		} while (sent < 0 && getLastError() == EINTR);
439
	} else {
440
		serv_addr.sin_port = htons(aPort);
441
		serv_addr.sin_family = AF_INET;
442
		serv_addr.sin_addr.s_addr = inet_addr(resolve(aAddr).c_str());
443
		do {
444
			sent = ::sendto(sock, (const char*)aBuffer, (int)aLen, 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
445
		} while (sent < 0 && getLastError() == EINTR);
446
	}
447
448
	check(sent);
449
	stats.totalUp += sent;
450
}
451
452
/**
453
 * Blocks until timeout is reached one of the specified conditions have been fulfilled
454
 * @param millis Max milliseconds to block.
455
 * @param waitFor WAIT_*** flags that set what we're waiting for, set to the combination of flags that
456
 *				  triggered the wait stop on return (==WAIT_NONE on timeout)
457
 * @return WAIT_*** ored together of the current state.
458
 * @throw SocketException Select or the connection attempt failed.
459
 */
460
int Socket::wait(uint32_t millis, int waitFor) throw(SocketException) {
461
	timeval tv;
462
	fd_set rfd, wfd, efd;
463
	fd_set *rfdp = NULL, *wfdp = NULL;
464
	tv.tv_sec = millis/1000;
465
	tv.tv_usec = (millis%1000)*1000;
466
467
	if(waitFor & WAIT_CONNECT) {
468
		dcassert(!(waitFor & WAIT_READ) && !(waitFor & WAIT_WRITE));
469
470
		int result;
471
		do {
472
			FD_ZERO(&wfd);
473
			FD_ZERO(&efd);
474
475
			FD_SET(sock, &wfd);
476
			FD_SET(sock, &efd);
477
			result = select((int)(sock+1), 0, &wfd, &efd, &tv);
478
		} while (result < 0 && getLastError() == EINTR);
479
		check(result);
480
481
		if(FD_ISSET(sock, &wfd)) {
482
			return WAIT_CONNECT;
483
		}
484
485
		if(FD_ISSET(sock, &efd)) {
486
			int y = 0;
487
			socklen_t z = sizeof(y);
488
			check(getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*)&y, &z));
489
490
			if(y != 0)
491
				throw SocketException(y);
492
			// No errors! We're connected (?)...
493
			return WAIT_CONNECT;
494
		}
495
		return 0;
496
	}
497
498
	int result;
499
	do {
500
		if(waitFor & WAIT_READ) {
501
			dcassert(!(waitFor & WAIT_CONNECT));
502
			rfdp = &rfd;
503
			FD_ZERO(rfdp);
504
			FD_SET(sock, rfdp);
505
		}
506
		if(waitFor & WAIT_WRITE) {
507
			dcassert(!(waitFor & WAIT_CONNECT));
508
			wfdp = &wfd;
509
			FD_ZERO(wfdp);
510
			FD_SET(sock, wfdp);
511
		}
512
513
		result = select((int)(sock+1), rfdp, wfdp, NULL, &tv);
514
	} while (result < 0 && getLastError() == EINTR);
515
	check(result);
516
517
	waitFor = WAIT_NONE;
518
519
	if(rfdp && FD_ISSET(sock, rfdp)) {
520
		waitFor |= WAIT_READ;
521
	}
522
	if(wfdp && FD_ISSET(sock, wfdp)) {
523
		waitFor |= WAIT_WRITE;
524
	}
525
526
	return waitFor;
527
}
528
529
string Socket::resolve(const string& aDns) {
530
	sockaddr_in sock_addr;
531
532
	memset(&sock_addr, 0, sizeof(sock_addr));
533
	sock_addr.sin_port = 0;
534
	sock_addr.sin_family = AF_INET;
535
	sock_addr.sin_addr.s_addr = inet_addr(aDns.c_str());
536
537
	if (sock_addr.sin_addr.s_addr == INADDR_NONE) {   /* server address is a name or invalid */
538
		hostent* host;
539
		host = gethostbyname(aDns.c_str());
540
		if (host == NULL) {
541
			return Util::emptyString;
542
		}
543
		sock_addr.sin_addr.s_addr = *((uint32_t*)host->h_addr);
544
		return inet_ntoa(sock_addr.sin_addr);
545
	} else {
546
		return aDns;
547
	}
548
}
549
550
string Socket::getLocalIp() throw() {
551
	if(sock == INVALID_SOCKET)
552
		return Util::emptyString;
553
554
	sockaddr_in sock_addr;
555
	socklen_t len = sizeof(sock_addr);
556
	if(getsockname(sock, (sockaddr*)&sock_addr, &len) == 0) {
557
		return inet_ntoa(sock_addr.sin_addr);
558
	}
559
	return Util::emptyString;
560
}
561
562
void Socket::socksUpdated() {
563
	udpServer.clear();
564
	udpPort = 0;
565
566
	if(SETTING(OUTGOING_CONNECTIONS) == SettingsManager::OUTGOING_SOCKS5) {
567
		try {
568
			Socket s;
569
			s.setBlocking(false);
570
			s.connect(SETTING(SOCKS_SERVER), static_cast<uint16_t>(SETTING(SOCKS_PORT)));
571
			s.socksAuth(SOCKS_TIMEOUT);
572
573
			char connStr[10];
574
			connStr[0] = 5;			// SOCKSv5
575
			connStr[1] = 3;			// UDP Associate
576
			connStr[2] = 0;			// Reserved
577
			connStr[3] = 1;			// Address type: IPv4;
578
			*((long*)(&connStr[4])) = 0;		// No specific outgoing UDP address
579
			*((uint16_t*)(&connStr[8])) = 0;	// No specific port...
580
581
			s.writeAll(connStr, 10, SOCKS_TIMEOUT);
582
583
			// We assume we'll get a ipv4 address back...therefore, 10 bytes...if not, things
584
			// will break, but hey...noone's perfect (and I'm tired...)...
585
			if(s.readAll(connStr, 10, SOCKS_TIMEOUT) != 10) {
586
				return;
587
			}
588
589
			if(connStr[0] != 5 || connStr[1] != 0) {
590
				return;
591
			}
592
593
			udpPort = static_cast<uint16_t>(ntohs(*((uint16_t*)(&connStr[8]))));
594
595
			in_addr serv_addr;
596
597
			memset(&serv_addr, 0, sizeof(serv_addr));
598
			serv_addr.s_addr = *((long*)(&connStr[4]));
599
			udpServer = inet_ntoa(serv_addr);
600
		} catch(const SocketException&) {
601
			dcdebug("Socket: Failed to register with socks server\n");
602
		}
603
	}
604
}
605
606
void Socket::shutdown() throw() {
607
	if(sock != INVALID_SOCKET)
608
		::shutdown(sock, 2);
609
}
610
611
void Socket::close() throw() {
612
	if(sock != INVALID_SOCKET) {
613
#ifdef _WIN32
614
		::closesocket(sock);
615
#else
616
		::close(sock);
617
#endif
618
		connected = false;
619
		sock = INVALID_SOCKET;
620
	}
621
}
622
623
void Socket::disconnect() throw() {
624
	shutdown();
625
	close();
626
}
627
628
} // namespace dcpp