2 // This file is part of the aMule Project.
4 // Copyright (c) 2004-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2004-2008 Angel Vidal Veiga ( kry@users.sourceforge.net )
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
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
30 #include <deque> // Needed for std::deque
31 #include <memory> // Needed for std::auto_ptr // Do_not_auto_remove (mingw-gcc-3.4.5)
35 #include <zlib.h> // Needed for packet (de)compression
36 #include "../../../Types.h" // Needed for uint32_t
38 #include <wx/defs.h> // Needed for wx/debug.h
39 #include <wx/debug.h> // Needed for wxASSERT
61 * \brief Socket handler for External Communications (EC).
63 * CECSocket takes care of the transmission of EC packets
67 friend class CECPacket
;
71 static const unsigned int EC_SOCKET_BUFFER_SIZE
= 2048;
72 const bool m_use_events
;
74 // Output related data
75 std::deque
<CQueuedData
*> m_output_queue
;
77 // zlib (deflation) buffers
78 std::vector
<unsigned char> m_in_ptr
;
79 std::vector
<unsigned char> m_out_ptr
;
80 std::auto_ptr
<CQueuedData
> m_curr_rx_data
;
81 std::auto_ptr
<CQueuedData
> m_curr_tx_data
;
87 size_t m_bytes_needed
;
91 uint32_t m_curr_packet_len
;
95 CECSocket(bool use_events
);
98 bool ConnectSocket(uint32_t ip
, uint16_t port
);
100 void CloseSocket() { InternalClose(); }
102 bool HaveNotificationSupport();
105 * Sends an EC packet and returns immediately.
107 * @param packet The CECPacket packet to be sent.
109 * This is an asynchronous call, the function returns
110 * immediately and the packet is sent on idle time.
112 * @note It's the caller's responsibilty to \c delete
115 void SendPacket(const CECPacket
*packet
);
118 * Sends an EC packet and waits for a reply.
120 * @param request The CECPacket packet to be sent.
121 * @return The reply packet for the request.
123 * Unlike SendPacket(), this call is synchronous and blocking.
124 * The packet is sent immediately (or at least as soon as possible),
125 * and the function does not return until a reply is received,
126 * or a timeout encountered.
128 * The returned packet will be allocated on the heap with \c new,
129 * or \c NULL is returned in case of an error (timeout).
131 * @note It's the caller's responsibilty to \c delete both
134 * @note OnPacketReceived() won't be called for packets
135 * received via this function.
137 const CECPacket
*SendRecvPacket(const CECPacket
*request
);
140 * Event handler function called when a new packet is received.
142 * @param packet The packet that has been received.
143 * @return The reply packet or \c NULL if no reply needed.
145 * In this function the application should process the received
146 * packet, and create a reply if necessary. The reply must be allocated
147 * on the heap with \c new. If no reply is necessary, the return
148 * value of the function should be \c NULL. The library will \c delete
151 * @note This function won't be called for packets received via the
152 * SendRecvPacket() function.
154 virtual const CECPacket
*OnPacketReceived(const CECPacket
*packet
);
157 * Get a message describing the error.
159 * @param error The code of the error for which a message should be returned.
160 * @return The text descibing the error.
162 virtual std::string
GetLastErrorMsg();
167 * This function is called when an error occurs. Use GetLastError() and
168 * GetErrorMsg() to find out the nature of the error.
170 * The default error handler prints out an error message in debug builds,
171 * and destroys the socket.
173 virtual void OnError();
177 * Socket lost event handler.
179 * This function is called when the socket is lost (either because of a network
180 * failure or because the remote end closed the socket gracefully).
182 * The default handler destroys the socket.
184 virtual void OnLost();
187 * Event handler for connection events.
189 * This function is called when a connection attempt succeeds. When CECSocket
190 * is compiled with ECSOCKET_USE_EVENTS == 0, WaitOnConnect() should be called
193 virtual void OnConnect();
198 bool WouldBlock() { return InternalGetLastError() == EC_ERROR_WOULDBLOCK
; }
199 bool GotError() { return InternalGetLastError() != EC_ERROR_NOERROR
; }
201 void SocketRead(void* ptr
, size_t len
) { InternalRead(ptr
,len
); }
202 void SocketWrite(const void* ptr
, size_t len
) { InternalWrite(ptr
,len
); }
203 bool SocketError() { return InternalError() && GotError(); }
205 size_t GetLastCount() { return InternalLastCount(); }
206 bool WaitSocketConnect(long secs
= -1, long msecs
= 0) { return InternalWaitOnConnect(secs
,msecs
); }
207 bool WaitSocketWrite(long secs
= -1, long msecs
= 0) { return InternalWaitForWrite(secs
,msecs
); }
208 bool WaitSocketRead(long secs
= -1, long msecs
= 0) { return InternalWaitForRead(secs
,msecs
); }
210 bool IsSocketConnected() { return InternalIsConnected(); }
212 void DestroySocket() { return InternalDestroy(); }
216 const CECPacket
*ReadPacket();
217 void WritePacket(const CECPacket
*packet
);
219 // These 4 methods are to be used by CECPacket & CECTag
220 bool ReadNumber(void *buffer
, size_t len
);
221 bool ReadBuffer(void *buffer
, size_t len
);
223 bool WriteNumber(const void *buffer
, size_t len
);
224 bool WriteBuffer(const void *buffer
, size_t len
);
229 size_t ReadBufferFromSocket(void *buffer
, size_t len
);
230 void WriteBufferToSocket(const void *buffer
, size_t len
);
233 virtual void WriteDoneAndQueueEmpty() = 0;
235 virtual bool InternalConnect(uint32_t ip
, uint16_t port
, bool wait
) = 0;
237 virtual size_t InternalLastCount() = 0;
238 virtual bool InternalWaitOnConnect(long secs
= -1, long msecs
= 0) = 0;
239 virtual bool InternalWaitForWrite(long secs
= -1, long msecs
= 0) = 0;
240 virtual bool InternalWaitForRead(long secs
= -1, long msecs
= 0) = 0;
242 virtual int InternalGetLastError() = 0;
244 virtual void InternalClose() = 0;
245 virtual bool InternalError() = 0;
246 virtual void InternalRead(void* ptr
, size_t len
) = 0;
247 virtual void InternalWrite(const void* ptr
, size_t len
) = 0;
249 virtual bool InternalIsConnected() = 0;
250 virtual void InternalDestroy() = 0;
256 std::vector
<unsigned char> m_data
;
257 unsigned char *m_rd_ptr
, *m_wr_ptr
;
259 CQueuedData(size_t len
)
263 m_rd_ptr
= m_wr_ptr
= &m_data
[0];
270 m_rd_ptr
= m_wr_ptr
= &m_data
[0];
273 void Write(const void *data
, size_t len
);
274 void WriteAt(const void *data
, size_t len
, size_t off
);
275 void Read(void *data
, size_t len
);
278 * Pass pointers to zlib. From now on, no Read() calls are allowed
280 void ToZlib(z_stream
&m_z
)
282 m_z
.avail_in
= (uInt
)GetUnreadDataLength();
283 m_z
.next_in
= m_rd_ptr
;
286 void WriteToSocket(CECSocket
*sock
);
287 void ReadFromSocket(CECSocket
*sock
, size_t len
);
289 size_t ReadFromSocketAll(CECSocket
*sock
, size_t len
);
291 size_t GetLength() const;
292 size_t GetDataLength() const;
293 size_t GetRemLength() const;
294 size_t GetUnreadDataLength() const;