Initial Commit
This commit is contained in:
372
database/FileZillaFTP/source/AsyncSocketEx.h
Normal file
372
database/FileZillaFTP/source/AsyncSocketEx.h
Normal file
@@ -0,0 +1,372 @@
|
||||
/*CAsyncSocketEx by Tim Kosse (Tim.Kosse@gmx.de)
|
||||
Version 1.3 (2003-04-26)
|
||||
--------------------------------------------------------
|
||||
|
||||
Introduction:
|
||||
-------------
|
||||
|
||||
CAsyncSocketEx is a replacement for the MFC class CAsyncSocket.
|
||||
This class was written because CAsyncSocket is not the fastest WinSock
|
||||
wrapper and it's very hard to add new functionality to CAsyncSocket
|
||||
derived classes. This class offers the same functionality as CAsyncSocket.
|
||||
Also, CAsyncSocketEx offers some enhancements which were not possible with
|
||||
CAsyncSocket without some tricks.
|
||||
|
||||
How do I use it?
|
||||
----------------
|
||||
Basically exactly like CAsyncSocket.
|
||||
To use CAsyncSocketEx, just replace all occurrences of CAsyncSocket in your
|
||||
code with CAsyncSocketEx. If you did not enhance CAsyncSocket yourself in
|
||||
any way, you won't have to change anything else in your code.
|
||||
|
||||
Why is CAsyncSocketEx faster?
|
||||
-----------------------------
|
||||
|
||||
CAsyncSocketEx is slightly faster when dispatching notification event messages.
|
||||
First have a look at the way CAsyncSocket works. For each thread that uses
|
||||
CAsyncSocket, a window is created. CAsyncSocket calls WSAAsyncSelect with
|
||||
the handle of that window. Until here, CAsyncSocketEx works the same way.
|
||||
But CAsyncSocket uses only one window message (WM_SOCKET_NOTIFY) for all
|
||||
sockets within one thread. When the window recieve WM_SOCKET_NOTIFY, wParam
|
||||
contains the socket handle and the window looks up an CAsyncSocket instance
|
||||
using a map. CAsyncSocketEx works differently. It's helper window uses a
|
||||
wide range of different window messages (WM_USER through 0xBFFF) and passes
|
||||
a different message to WSAAsyncSelect for each socket. When a message in
|
||||
the specified range is received, CAsyncSocketEx looks up the pointer to a
|
||||
CAsyncSocketEx instance in an Array using the index of message - WM_USER.
|
||||
As you can see, CAsyncSocketEx uses the helper window in a more efficient
|
||||
way, as it don't have to use the slow maps to lookup it's own instance.
|
||||
Still, speed increase is not very much, but it may be noticeable when using
|
||||
a lot of sockets at the same time.
|
||||
Please note that the changes do not affect the raw data throughput rate,
|
||||
CAsyncSocketEx only dispatches the notification messages faster.
|
||||
|
||||
What else does CAsyncSocketEx offer?
|
||||
------------------------------------
|
||||
|
||||
CAsyncSocketEx offers a flexible layer system. One example is the proxy layer.
|
||||
Just create an instance of the proxy layer, configure it and add it to the layer
|
||||
chain of your CAsyncSocketEx instance. After that, you can connect through
|
||||
proxies.
|
||||
Benefit: You don't have to change much to use the layer system.
|
||||
Another layer that is currently in development is the SSL layer to establish
|
||||
SSL encrypted connections.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Feel free to use this class, as long as you don't claim that you wrote it
|
||||
and this copyright notice stays intact in the source files.
|
||||
If you use this class in commercial applications, please send a short message
|
||||
to tim.kosse@gmx.de
|
||||
*/
|
||||
|
||||
#if !defined(AFX_ASYNCSOCKETEX_H__AA9E4531_63B1_442F_9A71_09B2FEEDF34E__INCLUDED_)
|
||||
#define AFX_ASYNCSOCKETEX_H__AA9E4531_63B1_442F_9A71_09B2FEEDF34E__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#ifdef _AFX
|
||||
#define CStdString CString
|
||||
#define CStdStringW CStringW
|
||||
#define CStdStringA CStringA
|
||||
#endif //_AFX
|
||||
|
||||
#define FD_FORCEREAD (1<<15)
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <Ws2tcpip.h>
|
||||
|
||||
class CAsyncSocketExHelperWindow;
|
||||
|
||||
extern "C" {
|
||||
typedef int (FAR PASCAL *t_getaddrinfo)(const char* nodename, const char* servname, const struct addrinfo* hints, struct addrinfo** res);
|
||||
typedef void (FAR PASCAL *t_freeaddrinfo)(struct addrinfo* ai);
|
||||
}
|
||||
|
||||
#ifndef NOLAYERS
|
||||
class CAsyncSocketExLayer;
|
||||
|
||||
struct t_callbackMsg
|
||||
{
|
||||
CAsyncSocketExLayer* pLayer;
|
||||
int nType;
|
||||
int nParam1;
|
||||
int nParam2;
|
||||
char* str;
|
||||
};
|
||||
|
||||
#endif //NOLAYERS
|
||||
|
||||
class CCriticalSectionWrapper;
|
||||
class CAsyncSocketEx
|
||||
{
|
||||
public:
|
||||
///////////////////////////////////////
|
||||
//Functions that imitate CAsyncSocket//
|
||||
///////////////////////////////////////
|
||||
|
||||
//Construction
|
||||
//------------
|
||||
|
||||
//Constructs a CAsyncSocketEx object.
|
||||
CAsyncSocketEx();
|
||||
virtual ~CAsyncSocketEx();
|
||||
|
||||
//Creates a socket.
|
||||
BOOL Create(UINT nSocketPort = 0, int nSocketType = SOCK_STREAM,
|
||||
long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
|
||||
LPCTSTR lpszSocketAddress = NULL, int nFamily = AF_INET, bool reusable = false);
|
||||
|
||||
//Attributes
|
||||
//---------
|
||||
|
||||
//Attaches a socket handle to a CAsyncSocketEx object.
|
||||
BOOL Attach( SOCKET hSocket,
|
||||
long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT |
|
||||
FD_CONNECT | FD_CLOSE );
|
||||
|
||||
//Detaches a socket handle from a CAsyncSocketEx object.
|
||||
SOCKET Detach( );
|
||||
|
||||
//Gets the error status for the last operation that failed.
|
||||
static int GetLastError();
|
||||
|
||||
//Gets the address of the peer socket to which the socket is connected.
|
||||
BOOL GetPeerName( CStdString& rPeerAddress, UINT& rPeerPort );
|
||||
|
||||
//Gets the local name for a socket.
|
||||
BOOL GetSockName( CStdString& rSocketAddress, UINT& rSocketPort );
|
||||
|
||||
//Retrieves a socket option.
|
||||
BOOL GetSockOpt(int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel = SOL_SOCKET);
|
||||
|
||||
//Sets a socket option.
|
||||
BOOL SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel = SOL_SOCKET);
|
||||
|
||||
//Gets the socket family
|
||||
int GetFamily() const;
|
||||
|
||||
//Sets the socket family
|
||||
bool SetFamily(int nFamily);
|
||||
|
||||
//Operations
|
||||
//----------
|
||||
|
||||
//Accepts a connection on the socket.
|
||||
virtual BOOL Accept( CAsyncSocketEx& rConnectedSocket, SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL );
|
||||
|
||||
//Requests event notification for the socket.
|
||||
BOOL AsyncSelect( long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE );
|
||||
|
||||
//Associates a local address with the socket.
|
||||
BOOL Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress);
|
||||
BOOL Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen);
|
||||
|
||||
//Closes the socket.
|
||||
virtual void Close();
|
||||
|
||||
//Establishes a connection to a peer socket.
|
||||
virtual BOOL Connect(LPCTSTR lpszHostAddress, UINT nHostPort);
|
||||
virtual BOOL Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen);
|
||||
|
||||
//Controls the mode of the socket.
|
||||
BOOL IOCtl( long lCommand, DWORD* lpArgument );
|
||||
|
||||
//Establishes a socket to listen for incoming connection requests.
|
||||
BOOL Listen( int nConnectionBacklog = 5 );
|
||||
|
||||
//Receives data from the socket.
|
||||
virtual int Receive(void* lpBuf, int nBufLen, int nFlags = 0);
|
||||
|
||||
//Sends data to a connected socket.
|
||||
virtual int Send(const void* lpBuf, int nBufLen, int nFlags = 0);
|
||||
|
||||
//Disables Send and/or Receive calls on the socket.
|
||||
BOOL ShutDown( int nHow = sends );
|
||||
enum { receives = 0, sends = 1, both = 2 };
|
||||
|
||||
//Overridable Notification Functions
|
||||
//----------------------------------
|
||||
|
||||
//Notifies a listening socket that it can accept pending connection requests by calling Accept.
|
||||
virtual void OnAccept(int nErrorCode);
|
||||
|
||||
//Notifies a socket that the socket connected to it has closed.
|
||||
virtual void OnClose(int nErrorCode);
|
||||
|
||||
//Notifies a connecting socket that the connection attempt is complete, whether successfully or in error.
|
||||
virtual void OnConnect(int nErrorCode);
|
||||
|
||||
//Notifies a listening socket that there is data to be retrieved by calling Receive.
|
||||
virtual void OnReceive(int nErrorCode);
|
||||
|
||||
//Notifies a socket that it can send data by calling Send.
|
||||
virtual void OnSend(int nErrorCode);
|
||||
|
||||
////////////////////////
|
||||
//Additional functions//
|
||||
////////////////////////
|
||||
|
||||
#ifndef NOLAYERS
|
||||
//Resets layer chain.
|
||||
void RemoveAllLayers();
|
||||
|
||||
//Attaches a new layer to the socket.
|
||||
BOOL AddLayer(CAsyncSocketExLayer *pLayer);
|
||||
|
||||
//Is a layer attached to the socket?
|
||||
BOOL IsLayerAttached() const;
|
||||
#endif //NOLAYERS
|
||||
|
||||
//Returns the handle of the socket.
|
||||
SOCKET GetSocketHandle();
|
||||
|
||||
//Trigers an event on the socket
|
||||
// Any combination of FD_READ, FD_WRITE, FD_CLOSE, FD_ACCEPT, FD_CONNECT and FD_FORCEREAD is valid for lEvent.
|
||||
BOOL TriggerEvent(long lEvent);
|
||||
|
||||
protected:
|
||||
//Strucure to hold the socket data
|
||||
struct t_AsyncSocketExData
|
||||
{
|
||||
SOCKET hSocket; //Socket handle
|
||||
int nSocketIndex; //Index of socket, required by CAsyncSocketExHelperWindow
|
||||
int nFamily;
|
||||
addrinfo *addrInfo, *nextAddr; // Iterate through protocols on connect failure
|
||||
bool onCloseCalled; // Set to true on first received OnClose event
|
||||
} m_SocketData;
|
||||
|
||||
//If using layers, only the events specified with m_lEvent will send to the event handlers.
|
||||
long m_lEvent;
|
||||
|
||||
//AsyncGetHostByName
|
||||
char *m_pAsyncGetHostByNameBuffer; //Buffer for hostend structure
|
||||
HANDLE m_hAsyncGetHostByNameHandle; //TaskHandle
|
||||
int m_nAsyncGetHostByNamePort; //Port to connect to
|
||||
|
||||
//Returns the handle of the helper window
|
||||
HWND GetHelperWindowHandle();
|
||||
|
||||
//Attaches socket handle to helper window
|
||||
void AttachHandle(SOCKET hSocket);
|
||||
|
||||
//Detaches socket handle to helper window
|
||||
void DetachHandle(SOCKET hSocket);
|
||||
|
||||
//Critical section for thread synchronization
|
||||
static CCriticalSectionWrapper m_sGlobalCriticalSection;
|
||||
|
||||
//Pointer to the data of the local thread
|
||||
struct t_AsyncSocketExThreadData
|
||||
{
|
||||
CAsyncSocketExHelperWindow *m_pHelperWindow;
|
||||
int nInstanceCount;
|
||||
DWORD nThreadId;
|
||||
std::list<CAsyncSocketEx*> layerCloseNotify;
|
||||
} *m_pLocalAsyncSocketExThreadData;
|
||||
|
||||
//List of the data structures for all threads
|
||||
static struct t_AsyncSocketExThreadDataList
|
||||
{
|
||||
t_AsyncSocketExThreadDataList *pNext;
|
||||
t_AsyncSocketExThreadData *pThreadData;
|
||||
} *m_spAsyncSocketExThreadDataList;
|
||||
|
||||
//Initializes Thread data and helper window, fills m_pLocalAsyncSocketExThreadData
|
||||
BOOL InitAsyncSocketExInstance();
|
||||
|
||||
//Destroys helper window after last instance of CAsyncSocketEx in current thread has been closed
|
||||
void FreeAsyncSocketExInstance();
|
||||
|
||||
// Iterate through protocols on failure
|
||||
bool TryNextProtocol();
|
||||
|
||||
void ResendCloseNotify();
|
||||
|
||||
#ifndef NOLAYERS
|
||||
// Add a new notification to the list of pending callbacks
|
||||
void AddCallbackNotification(const t_callbackMsg& msg);
|
||||
#endif // NOLAYERS
|
||||
|
||||
#ifndef NOSOCKETSTATES
|
||||
int m_nPendingEvents;
|
||||
|
||||
int GetState() const;
|
||||
void SetState(int nState);
|
||||
|
||||
int m_nState;
|
||||
#endif //NOSOCKETSTATES
|
||||
|
||||
#ifndef NOLAYERS
|
||||
//Layer chain
|
||||
CAsyncSocketExLayer *m_pFirstLayer;
|
||||
CAsyncSocketExLayer *m_pLastLayer;
|
||||
|
||||
friend CAsyncSocketExLayer;
|
||||
|
||||
//Called by the layers to notify application of some events
|
||||
virtual int OnLayerCallback(std::list<t_callbackMsg>& callbacks);
|
||||
#endif //NOLAYERS
|
||||
|
||||
// Used by Bind with AF_UNSPEC sockets
|
||||
UINT m_nSocketPort;
|
||||
LPTSTR m_lpszSocketAddress;
|
||||
|
||||
// imported IPv6 functions
|
||||
static HMODULE m_hDll;
|
||||
|
||||
static t_getaddrinfo p_getaddrinfo;
|
||||
static t_freeaddrinfo p_freeaddrinfo;
|
||||
|
||||
friend CAsyncSocketExHelperWindow;
|
||||
|
||||
#ifndef NOLAYERS
|
||||
// Pending callbacks
|
||||
std::list<t_callbackMsg> m_pendingCallbacks;
|
||||
#endif // NOLAYERS
|
||||
|
||||
private:
|
||||
BOOL GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen );
|
||||
BOOL GetSockName( SOCKADDR* lpSockAddr, int* lpSockAddrLen );
|
||||
};
|
||||
|
||||
#ifndef NOLAYERS
|
||||
#define LAYERCALLBACK_STATECHANGE 0
|
||||
#define LAYERCALLBACK_LAYERSPECIFIC 1
|
||||
#endif //NOLAYERS
|
||||
|
||||
enum SocketState
|
||||
{
|
||||
notsock,
|
||||
unconnected,
|
||||
connecting,
|
||||
listening,
|
||||
connected,
|
||||
closed,
|
||||
aborted,
|
||||
attached
|
||||
};
|
||||
|
||||
#ifdef _UNICODE
|
||||
#define _sntprintf _snwprintf
|
||||
#else
|
||||
#define _sntprintf _snprintf
|
||||
#endif
|
||||
|
||||
inline TCHAR* Inet6AddrToString(in6_addr& addr)
|
||||
{
|
||||
LPTSTR buf = new TCHAR[512];
|
||||
|
||||
_sntprintf(buf, 512, _T("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"),
|
||||
addr.s6_bytes[0], addr.s6_bytes[1], addr.s6_bytes[2], addr.s6_bytes[3],
|
||||
addr.s6_bytes[4], addr.s6_bytes[5], addr.s6_bytes[6], addr.s6_bytes[7],
|
||||
addr.s6_bytes[8], addr.s6_bytes[9], addr.s6_bytes[10], addr.s6_bytes[11],
|
||||
addr.s6_bytes[12], addr.s6_bytes[13], addr.s6_bytes[14], addr.s6_bytes[15]);
|
||||
|
||||
return buf ;
|
||||
}
|
||||
|
||||
#endif // !defined(AFX_ASYNCSOCKETEX_H__AA9E4531_63B1_442F_9A71_09B2FEEDF34E__INCLUDED_)
|
||||
Reference in New Issue
Block a user