| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 | 
							- /*CAsyncSocketEx by Tim Kosse ([email protected])
 
-             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 [email protected]
 
- */
 
- //---------------------------------------------------------------------------
 
- #ifndef AsyncSocketExH
 
- #define AsyncSocketExH
 
- //---------------------------------------------------------------------------
 
- #define FD_FORCEREAD (1<<15)
 
- //---------------------------------------------------------------------------
 
- #include <winsock2.h>
 
- #include <Ws2tcpip.h>
 
- //---------------------------------------------------------------------------
 
- class CAsyncSocketExHelperWindow;
 
- class CAsyncSocketExLayer;
 
- class CCriticalSectionWrapper;
 
- //---------------------------------------------------------------------------
 
- struct t_callbackMsg
 
- {
 
-   CAsyncSocketExLayer* pLayer;
 
-   int nType;
 
-   int nParam1;
 
-   int nParam2;
 
-   char* str;
 
- };
 
- //---------------------------------------------------------------------------
 
- class CAsyncSocketEx
 
- {
 
- public:
 
-   CAsyncSocketEx();
 
-   virtual ~CAsyncSocketEx();
 
-   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);
 
-   // 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(CString& rPeerAddress, UINT& rPeerPort);
 
-   BOOL GetPeerName(SOCKADDR* lpSockAddr, int* lpSockAddrLen);
 
-   // Gets the local name for a socket.
 
-   BOOL GetSockName(CString& rSocketAddress, UINT& rSocketPort);
 
-   BOOL GetSockName(SOCKADDR* lpSockAddr, int* lpSockAddrLen);
 
-   // 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.
 
-   virtual BOOL Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress);
 
-   BOOL BindToAddr(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
 
-   // 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;
 
-   // 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();
 
-   // Add a new notification to the list of pending callbacks
 
-   void AddCallbackNotification(const t_callbackMsg & msg);
 
-   int m_nPendingEvents;
 
-   int GetState() const;
 
-   virtual void SetState(int nState);
 
-   static const TCHAR * GetStateDesc(int nState);
 
-   static bool LogStateChange(int nState1, int nState2);
 
-   int m_nState;
 
-   // 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);
 
-   // Used by Bind with AF_UNSPEC sockets
 
-   UINT m_nSocketPort;
 
-   LPTSTR m_lpszSocketAddress;
 
-   friend CAsyncSocketExHelperWindow;
 
-   // Pending callbacks
 
-   std::list<t_callbackMsg> m_pendingCallbacks;
 
-   virtual void LogSocketMessageRaw(int nMessageType, LPCTSTR pMsg) {};
 
-   virtual bool LoggingSocketMessage(int nMessageType) { return true; };
 
-   virtual int GetSocketOptionVal(int OptionID) const { DebugFail(); return 0; };
 
-   virtual void ConfigureSocket() {};
 
- };
 
- //---------------------------------------------------------------------------
 
- #define LAYERCALLBACK_STATECHANGE 0
 
- #define LAYERCALLBACK_LAYERSPECIFIC 1
 
- //---------------------------------------------------------------------------
 
- enum SocketState
 
- {
 
-   notsock,
 
-   unconnected,
 
-   connecting,
 
-   listening,
 
-   connected,
 
-   closed,
 
-   aborted,
 
-   attached
 
- };
 
- //---------------------------------------------------------------------------
 
- inline TCHAR* Inet6AddrToString(in6_addr & addr)
 
- {
 
-   LPTSTR buf = new TCHAR[512];
 
-   _sntprintf(buf, 512, L"%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;
 
- }
 
- //---------------------------------------------------------------------------
 
- class CCriticalSectionWrapper
 
- {
 
- public:
 
-   CCriticalSectionWrapper()
 
-   {
 
-     m_bInitialized = TRUE;
 
-     InitializeCriticalSection(&m_criticalSection);
 
-   }
 
-   ~CCriticalSectionWrapper()
 
-   {
 
-     if (m_bInitialized)
 
-       DeleteCriticalSection(&m_criticalSection);
 
-     m_bInitialized = FALSE;
 
-   }
 
-   void Lock()
 
-   {
 
-     if (m_bInitialized)
 
-       EnterCriticalSection(&m_criticalSection);
 
-   }
 
-   void Unlock()
 
-   {
 
-     if (m_bInitialized)
 
-       LeaveCriticalSection(&m_criticalSection);
 
-   }
 
- protected:
 
-   CRITICAL_SECTION m_criticalSection;
 
-   BOOL m_bInitialized;
 
- };
 
- //---------------------------------------------------------------------------
 
- #endif // AsyncSocketExH
 
 
  |