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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
//
// This file is part of the aMule Project.
//
// Copyright (c) 2011-2011 aMule Team ( admin@amule.org / http://www.amule.org )
// Copyright (c) 2011-2011 Stu Redman ( admin@amule.org / http://www.amule.org )
//
// Any parts of this program derived from the xMule, lMule or eMule project,
// or contributed by third-party developers are copyrighted by their
// respective authors.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
//


#ifndef __LIBSOCKET_H__
#define __LIBSOCKET_H__

#include "config.h"		// Needed for ASIO_SOCKETS
#include "Types.h"
class amuleIPV4Address;

#ifdef ASIO_SOCKETS

// Socket flags (unused in ASIO implementation, just provide the names)
enum {
	MULE_SOCKET_NONE,
	MULE_SOCKET_NOWAIT_READ,
	MULE_SOCKET_NOWAIT_WRITE,
	MULE_SOCKET_NOWAIT,
	MULE_SOCKET_WAITALL_READ,
	MULE_SOCKET_WAITALL_WRITE,
	MULE_SOCKET_WAITALL,
	MULE_SOCKET_BLOCK,
	MULE_SOCKET_REUSEADDR,
	MULE_SOCKET_BROADCAST,
	MULE_SOCKET_NOBIND
};
typedef int muleSocketFlags;

// Socket events (used for proxy notification)
enum {
	MULE_SOCKET_CONNECTION,
	MULE_SOCKET_INPUT,
	MULE_SOCKET_OUTPUT,
	MULE_SOCKET_LOST
};

//
// Abstraction class for library TCP socket
// Can be a wxSocket or an ASIO socket
//

//
// Client TCP socket
//
class CLibSocket
{
	friend class CAsioSocketImpl;
	friend class CAsioSocketServerImpl;
public:
	CLibSocket(int flags = 0);
	virtual ~CLibSocket();

	// wx Stuff
	void	Notify(bool);
	bool	Connect(const amuleIPV4Address& adr, bool wait);
	bool	IsConnected() const;
	bool	IsOk() const;
	void	SetLocal(const amuleIPV4Address& local);
	uint32	Read(void * buffer, uint32 nbytes);
	uint32	Write(const void * buffer, uint32 nbytes);
	void	Close();
	void	Destroy();

	// Get last error, 0 == no error
	int		LastError() const;

	// not supported
	void SetFlags(int) {}
	void Discard() {}
	bool WaitOnConnect(long, long)	{ return true; }
	bool WaitForWrite(long, long)	{ return true; }
	bool WaitForRead(long, long)	{ return true; }

	// new Stuff

	// Check if socket is currently blocking for read or write
	bool	BlocksRead() const;
	bool	BlocksWrite() const;

	// Show we're ready for another event
	void	EventProcessed();

	// Get IP of client
	const wxChar * GetIP() const;

	// True if Destroy() has been called for socket
	bool	IsDestroying() const;

	// Get/set proxy state
	bool GetProxyState() const;
	void SetProxyState(bool state, const amuleIPV4Address * adr = 0);

	// Get peer address (better API than wx)
	wxString	GetPeer();
	uint32		GetPeerInt();

	// Handlers
	virtual void OnConnect(int) {}
	virtual void OnSend(int) {}
	virtual void OnReceive(int) {}
	virtual void OnLost() {}
	virtual void OnProxyEvent(int) {}

private:
	// Replace the internal socket
	void	LinkSocketImpl(class CAsioSocketImpl *);

	class CAsioSocketImpl * m_aSocket;
	void LastCount();	// No. We don't have this. We return it directly with Read() and Write()
	bool Error() const;	// Only use LastError
};


//
// TCP socket server
//
class CLibSocketServer
{
public:
	CLibSocketServer(const amuleIPV4Address& adr, int flags);
	virtual ~CLibSocketServer();
	// Accepts an incoming connection request, and creates a new CLibSocket object which represents the server-side of the connection.
	CLibSocket * Accept(bool wait = true);
	// Accept an incoming connection using the specified socket object.
	bool	AcceptWith(CLibSocket & socket, bool wait);

	virtual	void OnAccept() {}

	bool	IsOk() const;

	void	Close();

	// Not needed here
	void	Discard() {}
	bool	Notify(bool) { return true; }

	// new Stuff

	// Do we have a socket available if AcceptWith() is called ?
	bool	SocketAvailable();
private:
	class CAsioSocketServerImpl * m_aServer;
};


//
// UDP socket
//
class CLibUDPSocket
{
	friend class CAsioUDPSocketImpl;
public:
	CLibUDPSocket(amuleIPV4Address &address, int flags);
	virtual ~CLibUDPSocket();

	// wx Stuff
	bool	IsOk() const;
	virtual uint32 RecvFrom(amuleIPV4Address& addr, void* buf, uint32 nBytes);
	virtual uint32 SendTo(const amuleIPV4Address& addr, const void* buf, uint32 nBytes);
	int		LastError() const;
	void	Close();
	void	Destroy();
	void	SetClientData(class CMuleUDPSocket *);

	// Not needed here
	bool	Notify(bool) { return true; }

	// Check if socket is currently blocking for write
	// Well - we apparently have block in wx. At least we handle it in MuleUDPSocket.
	// But this makes no sense. We send a packet to an IP in background.
	// Either this works after some time, or not. But there is no block.
	bool	BlocksWrite() const { return false; }

private:
	class	CAsioUDPSocketImpl * m_aSocket;
	void	LastCount();	// block this
	bool	Error() const;	// Only use LastError
};


//
// ASIO event loop
//
class CAsioService
{
public:
    CAsioService();
    ~CAsioService();
	void Stop();
private:
	static const int m_numberOfThreads;
	class CAsioServiceThread * m_threads;
};


#else /* ASIO_SOCKETS */

// use wx sockets

#include <wx/socket.h>
#include "NetworkFunctions.h"		// Needed for StringIPtoUint32

typedef wxSocketFlags muleSocketFlags;

// Socket flags
#define MULE_SOCKET_NONE		wxSOCKET_NONE
#define MULE_SOCKET_NOWAIT_READ		wxSOCKET_NOWAIT_READ
#define MULE_SOCKET_NOWAIT_WRITE	wxSOCKET_NOWAIT_WRITE
#define MULE_SOCKET_NOWAIT		wxSOCKET_NOWAIT
#define MULE_SOCKET_WAITALL_READ	wxSOCKET_WAITALL_READ
#define MULE_SOCKET_WAITALL_WRITE	wxSOCKET_WAITALL_WRITE
#define MULE_SOCKET_WAITALL		wxSOCKET_WAITALL
#define MULE_SOCKET_BLOCK		wxSOCKET_BLOCK
#define MULE_SOCKET_REUSEADDR		wxSOCKET_REUSEADDR
#define MULE_SOCKET_BROADCAST		wxSOCKET_BROADCAST
#define MULE_SOCKET_NOBIND		wxSOCKET_NOBIND

// Socket events
#define MULE_SOCKET_CONNECTION		wxSOCKET_CONNECTION
#define MULE_SOCKET_INPUT		wxSOCKET_INPUT
#define MULE_SOCKET_OUTPUT		wxSOCKET_OUTPUT
#define MULE_SOCKET_LOST		wxSOCKET_LOST

class CLibSocket : public wxSocketClient
{
public:
	CLibSocket(wxSocketFlags flags = 0) : wxSocketClient(flags), m_isDestroying(false) {}

	// not actually called
	const wxChar * GetIP() const { return wxEmptyString; }
	void EventProcessed() {}
	bool GetProxyState() const { return false; }
	// unused Handlers
	virtual void OnConnect(int) {}
	virtual void OnSend(int) {}
	virtual void OnReceive(int) {}
	virtual void OnLost() {}
	virtual void OnProxyEvent(int) {}

	// methods using amuleIPV4Address
	bool Connect(amuleIPV4Address& adr, bool wait);		// Yes. adr is not const.
	bool GetPeer(amuleIPV4Address& adr);
	void SetLocal(amuleIPV4Address& local);				// Same here.

	// Get last error, 0 == no error
	// BLOCK is also not an error!
	int	LastError() const
	{
		int ret = 0;
		if (wxSocketClient::Error()) {
			ret = wxSocketClient::LastError();
			if (ret == wxSOCKET_WOULDBLOCK) {
				ret = 0;
			}
		}
		return ret;
	}

	// Check if socket is currently blocking for read or write
	bool	BlocksRead() const
	{
		return wxSocketClient::Error() && wxSocketClient::LastError() == wxSOCKET_WOULDBLOCK;
	}

	bool	BlocksWrite() const { return BlocksRead(); }	// no difference here

	uint32 Read(void *buffer, wxUint32 nbytes)
	{
		wxSocketClient::Read(buffer, nbytes);
		return wxSocketClient::LastCount();
	}

	uint32 Write(const void *buffer, wxUint32 nbytes)
	{
		wxSocketClient::Write(buffer, nbytes);
		return wxSocketClient::LastCount();
	}

	void	Destroy()
	{
		if (!m_isDestroying) {
			m_isDestroying = true;
			SetNotify(0);
			Notify(false);
			Close(); // Destroy is supposed to call Close(), but.. it doesn't hurt.
			wxSocketClient::Destroy();
		}
	}

	bool	IsDestroying() const { return m_isDestroying; }

	// Get peer address (better API than wx)
	wxString	GetPeer()
	{
		wxIPV4address adr;
		wxSocketClient::GetPeer(adr);
		return adr.IPAddress();
	}

	uint32		GetPeerInt() { return StringIPtoUint32(GetPeer()); }

private:
	bool	m_isDestroying;		// true if Destroy() was called

	void LastCount();	// block this
	bool Error() const;	// Only use LastError
};


class CLibSocketServer : public wxSocketServer
{
public:
	CLibSocketServer(const amuleIPV4Address &address, wxSocketFlags flags);

	CLibSocket * Accept(bool wait) { return static_cast<CLibSocket*>(wxSocketServer::Accept(wait)); }

	bool SocketAvailable() { return true; }

	virtual	void OnAccept() {}
};


class CLibUDPSocket : public wxDatagramSocket
{
public:
	CLibUDPSocket(amuleIPV4Address &address, wxSocketFlags flags);

	virtual uint32 RecvFrom(amuleIPV4Address& addr, void* buf, uint32 nBytes);

	virtual uint32 SendTo(const amuleIPV4Address& addr, const void* buf, uint32 nBytes);

	// Get last error, 0 == no error
	int	LastError() const
	{
		int ret = 0;
		if (wxDatagramSocket::Error()) {
			ret = wxDatagramSocket::LastError();
			if (ret == wxSOCKET_WOULDBLOCK) {
				ret = 0;
			}
		}
		return ret;
	}

	// Check if socket is currently blocking for write
	// I wonder if this EVER returns true (see Asio)
	bool	BlocksWrite() const
	{
		return wxDatagramSocket::Error() && wxDatagramSocket::LastError() == wxSOCKET_WOULDBLOCK;
	}

private:
	void LastCount();	// block this
	bool Error() const;	// Only use LastError
};


#endif /* ASIO_SOCKETS */

#endif /* __LIBSOCKET_H__ */