Workaround for crash on closing the last search tab
[amule.git] / src / LibSocket.h
blob8d4503418a2fcdcefd9d00bc0310a733e2634ac0
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2011-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2011-2011 Stu Redman ( admin@amule.org / http://www.amule.org )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #ifndef __LIBSOCKET_H__
28 #define __LIBSOCKET_H__
30 #ifdef HAVE_CONFIG_H
31 # include "config.h" // Needed for ASIO_SOCKETS
32 #endif
34 #include "Types.h"
35 class amuleIPV4Address;
37 #ifdef ASIO_SOCKETS
39 // Socket flags (unused in ASIO implementation, just provide the names)
40 enum {
41 MULE_SOCKET_NONE,
42 MULE_SOCKET_NOWAIT_READ,
43 MULE_SOCKET_NOWAIT_WRITE,
44 MULE_SOCKET_NOWAIT,
45 MULE_SOCKET_WAITALL_READ,
46 MULE_SOCKET_WAITALL_WRITE,
47 MULE_SOCKET_WAITALL,
48 MULE_SOCKET_BLOCK,
49 MULE_SOCKET_REUSEADDR,
50 MULE_SOCKET_BROADCAST,
51 MULE_SOCKET_NOBIND
53 typedef int muleSocketFlags;
55 // Socket events (used for proxy notification)
56 enum {
57 MULE_SOCKET_CONNECTION,
58 MULE_SOCKET_INPUT,
59 MULE_SOCKET_OUTPUT,
60 MULE_SOCKET_LOST
64 // Abstraction class for library TCP socket
65 // Can be a wxSocket or an ASIO socket
69 // Client TCP socket
71 class CLibSocket
73 friend class CAsioSocketImpl;
74 friend class CAsioSocketServerImpl;
75 public:
76 CLibSocket(int flags = 0);
77 virtual ~CLibSocket();
79 // wx Stuff
80 void Notify(bool);
81 bool Connect(const amuleIPV4Address& adr, bool wait);
82 bool IsConnected() const;
83 bool IsOk() const;
84 void SetLocal(const amuleIPV4Address& local);
85 uint32 Read(void * buffer, uint32 nbytes);
86 uint32 Write(const void * buffer, uint32 nbytes);
87 void Close();
88 void Destroy();
90 // Get last error, 0 == no error
91 int LastError() const;
93 // not supported
94 void SetFlags(int) {}
95 void Discard() {}
96 bool WaitOnConnect(long, long) { return true; }
97 bool WaitForWrite(long, long) { return true; }
98 bool WaitForRead(long, long) { return true; }
100 // new Stuff
102 // Check if socket is currently blocking for read or write
103 bool BlocksRead() const;
104 bool BlocksWrite() const;
106 // Show we're ready for another event
107 void EventProcessed();
109 // Get IP of client
110 const wxChar * GetIP() const;
112 // True if Destroy() has been called for socket
113 bool IsDestroying() const;
115 // Get/set proxy state
116 bool GetProxyState() const;
117 void SetProxyState(bool state, const amuleIPV4Address * adr = 0);
119 // Get peer address (better API than wx)
120 wxString GetPeer();
121 uint32 GetPeerInt();
123 // Handlers
124 virtual void OnConnect(int) {}
125 virtual void OnSend(int) {}
126 virtual void OnReceive(int) {}
127 virtual void OnLost() {}
128 virtual void OnProxyEvent(int) {}
130 private:
131 // Replace the internal socket
132 void LinkSocketImpl(class CAsioSocketImpl *);
134 class CAsioSocketImpl * m_aSocket;
135 void LastCount(); // No. We don't have this. We return it directly with Read() and Write()
136 bool Error() const; // Only use LastError
141 // TCP socket server
143 class CLibSocketServer
145 public:
146 CLibSocketServer(const amuleIPV4Address& adr, int flags);
147 virtual ~CLibSocketServer();
148 // Accepts an incoming connection request, and creates a new CLibSocket object which represents the server-side of the connection.
149 CLibSocket * Accept(bool wait = true);
150 // Accept an incoming connection using the specified socket object.
151 bool AcceptWith(CLibSocket & socket, bool wait);
153 virtual void OnAccept() {}
155 bool IsOk() const;
157 void Close();
159 // Not needed here
160 void Discard() {}
161 bool Notify(bool) { return true; }
163 // new Stuff
165 // Do we have a socket available if AcceptWith() is called ?
166 bool SocketAvailable();
167 private:
168 class CAsioSocketServerImpl * m_aServer;
173 // UDP socket
175 class CLibUDPSocket
177 friend class CAsioUDPSocketImpl;
178 public:
179 CLibUDPSocket(amuleIPV4Address &address, int flags);
180 virtual ~CLibUDPSocket();
182 // wx Stuff
183 bool IsOk() const;
184 virtual uint32 RecvFrom(amuleIPV4Address& addr, void* buf, uint32 nBytes);
185 virtual uint32 SendTo(const amuleIPV4Address& addr, const void* buf, uint32 nBytes);
186 int LastError() const;
187 void Close();
188 void Destroy();
189 void SetClientData(class CMuleUDPSocket *);
191 // Not needed here
192 bool Notify(bool) { return true; }
194 // Check if socket is currently blocking for write
195 // Well - we apparently have block in wx. At least we handle it in MuleUDPSocket.
196 // But this makes no sense. We send a packet to an IP in background.
197 // Either this works after some time, or not. But there is no block.
198 bool BlocksWrite() const { return false; }
200 private:
201 class CAsioUDPSocketImpl * m_aSocket;
202 void LastCount(); // block this
203 bool Error() const; // Only use LastError
208 // ASIO event loop
210 class CAsioService
212 public:
213 CAsioService();
214 ~CAsioService();
215 void Stop();
216 private:
217 static const int m_numberOfThreads;
218 class CAsioServiceThread * m_threads;
222 #else /* ASIO_SOCKETS */
224 // use wx sockets
226 #include <wx/socket.h>
227 #include "NetworkFunctions.h" // Needed for StringIPtoUint32
229 typedef wxSocketFlags muleSocketFlags;
231 // Socket flags
232 #define MULE_SOCKET_NONE wxSOCKET_NONE
233 #define MULE_SOCKET_NOWAIT_READ wxSOCKET_NOWAIT_READ
234 #define MULE_SOCKET_NOWAIT_WRITE wxSOCKET_NOWAIT_WRITE
235 #define MULE_SOCKET_NOWAIT wxSOCKET_NOWAIT
236 #define MULE_SOCKET_WAITALL_READ wxSOCKET_WAITALL_READ
237 #define MULE_SOCKET_WAITALL_WRITE wxSOCKET_WAITALL_WRITE
238 #define MULE_SOCKET_WAITALL wxSOCKET_WAITALL
239 #define MULE_SOCKET_BLOCK wxSOCKET_BLOCK
240 #define MULE_SOCKET_REUSEADDR wxSOCKET_REUSEADDR
241 #define MULE_SOCKET_BROADCAST wxSOCKET_BROADCAST
242 #define MULE_SOCKET_NOBIND wxSOCKET_NOBIND
244 // Socket events
245 #define MULE_SOCKET_CONNECTION wxSOCKET_CONNECTION
246 #define MULE_SOCKET_INPUT wxSOCKET_INPUT
247 #define MULE_SOCKET_OUTPUT wxSOCKET_OUTPUT
248 #define MULE_SOCKET_LOST wxSOCKET_LOST
250 class CLibSocket : public wxSocketClient
252 public:
253 CLibSocket(wxSocketFlags flags = 0) : wxSocketClient(flags), m_isDestroying(false) {}
255 // not actually called
256 const wxChar * GetIP() const { return wxEmptyString; }
257 void EventProcessed() {}
258 bool GetProxyState() const { return false; }
259 // unused Handlers
260 virtual void OnConnect(int) {}
261 virtual void OnSend(int) {}
262 virtual void OnReceive(int) {}
263 virtual void OnLost() {}
264 virtual void OnProxyEvent(int) {}
266 // methods using amuleIPV4Address
267 bool Connect(amuleIPV4Address& adr, bool wait); // Yes. adr is not const.
268 bool GetPeer(amuleIPV4Address& adr);
269 void SetLocal(amuleIPV4Address& local); // Same here.
271 // Get last error, 0 == no error
272 // BLOCK is also not an error!
273 int LastError() const
275 int ret = 0;
276 if (wxSocketClient::Error()) {
277 ret = wxSocketClient::LastError();
278 if (ret == wxSOCKET_WOULDBLOCK) {
279 ret = 0;
282 return ret;
285 // Check if socket is currently blocking for read or write
286 bool BlocksRead() const
288 return wxSocketClient::Error() && wxSocketClient::LastError() == wxSOCKET_WOULDBLOCK;
291 bool BlocksWrite() const { return BlocksRead(); } // no difference here
293 uint32 Read(void *buffer, wxUint32 nbytes)
295 wxSocketClient::Read(buffer, nbytes);
296 return wxSocketClient::LastCount();
299 uint32 Write(const void *buffer, wxUint32 nbytes)
301 wxSocketClient::Write(buffer, nbytes);
302 return wxSocketClient::LastCount();
305 void Destroy()
307 if (!m_isDestroying) {
308 m_isDestroying = true;
309 SetNotify(0);
310 Notify(false);
311 Close(); // Destroy is suposed to call Close(), but.. it doesn't hurt.
312 wxSocketClient::Destroy();
316 bool IsDestroying() const { return m_isDestroying; }
318 // Get peer address (better API than wx)
319 wxString GetPeer()
321 wxIPV4address adr;
322 wxSocketClient::GetPeer(adr);
323 return adr.IPAddress();
326 uint32 GetPeerInt() { return StringIPtoUint32(GetPeer()); }
328 private:
329 bool m_isDestroying; // true if Destroy() was called
331 void LastCount(); // block this
332 bool Error() const; // Only use LastError
336 class CLibSocketServer : public wxSocketServer
338 public:
339 CLibSocketServer(const amuleIPV4Address &address, wxSocketFlags flags);
341 CLibSocket * Accept(bool wait) { return static_cast<CLibSocket*>(wxSocketServer::Accept(wait)); }
343 bool SocketAvailable() { return true; }
345 virtual void OnAccept() {}
349 class CLibUDPSocket : public wxDatagramSocket
351 public:
352 CLibUDPSocket(amuleIPV4Address &address, wxSocketFlags flags);
354 virtual uint32 RecvFrom(amuleIPV4Address& addr, void* buf, uint32 nBytes);
356 virtual uint32 SendTo(const amuleIPV4Address& addr, const void* buf, uint32 nBytes);
358 // Get last error, 0 == no error
359 int LastError() const
361 int ret = 0;
362 if (wxDatagramSocket::Error()) {
363 ret = wxDatagramSocket::LastError();
364 if (ret == wxSOCKET_WOULDBLOCK) {
365 ret = 0;
368 return ret;
371 // Check if socket is currently blocking for write
372 // I wonder if this EVER returns true (see Asio)
373 bool BlocksWrite() const
375 return wxDatagramSocket::Error() && wxDatagramSocket::LastError() == wxSOCKET_WOULDBLOCK;
378 private:
379 void LastCount(); // block this
380 bool Error() const; // Only use LastError
384 #endif /* ASIO_SOCKETS */
386 #endif /* __LIBSOCKET_H__ */