#ifndef __CeSocket_h__
#define __CeSocket_h__
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// dependend include
#include <winsock.h>
#include "CeDebug.h"
//dependend library
#if defined(_WIN32_WCE)
#if defined(_WIN32_WCE_EMULATION) && (_WIN32_WCE < 211)
#pragma comment(lib, "winsockm.lib")
#else
#pragma comment(lib, "winsock.lib")
#endif
#else
#pragma comment(lib, "wsock32.lib")
#endif // _WIN32_WCE
typedef const struct sockaddr* LPCSOCKADDR;
//
// These routines throw the following exception:
//
#define STATUS_CE_SOCKET_EXCEPTION ((DWORD) (0xE0000AAA))
//
// catch with the following block:
//
// __try
// {
// }
// __except (GetExceptionCode() == STATUS_CE_SOCKET_EXCEPTION)
// {
// }
//
class CeSockAddr : public sockaddr_in
{
public:
// constructors
CeSockAddr()
{ sin_family = AF_INET; sin_port = 0; sin_addr.s_addr = 0; } // Default
CeSockAddr(const SOCKADDR& sa)
{ memcpy(this, &sa, sizeof(SOCKADDR)); }
CeSockAddr(const SOCKADDR_IN& sin)
{ memcpy(this, &sin, sizeof(SOCKADDR_IN)); }
CeSockAddr(const ULONG ulAddr, const USHORT ushPort = 0) // parms are host byte ordered
{ sin_family = AF_INET; sin_port = htons(ushPort); sin_addr.s_addr = htonl(ulAddr); }
CeSockAddr(const char* pchIP, const USHORT ushPort = 0) // dotted IP addr string
{ sin_family = AF_INET; sin_port = htons(ushPort); sin_addr.s_addr = inet_addr(pchIP); } // already network byte ordered
// Return the address in dotted-decimal format
#ifndef _WIN32_WCE
// CeString DottedDecimal()
// { return inet_ntoa(sin_addr); } // constructs a new CeString object
#endif
// Get port and address (even though they're public)
USHORT Port() const
{ return ntohs(sin_port); }
ULONG IPAddr() const
{ return ntohl(sin_addr.s_addr); }
void SetPort(USHORT sPort)
{ sin_port = htons(sPort); }
void SetIPAddr(ULONG ulAddr)
{ sin_addr.s_addr = htonl(ulAddr); }
// operators added for efficiency
const CeSockAddr& operator=(const SOCKADDR& sa)
{ memcpy(this, &sa, sizeof(SOCKADDR)); return *this; }
const CeSockAddr& operator=(const SOCKADDR_IN& sin)
{ memcpy(this, &sin, sizeof(SOCKADDR_IN)); return *this; }
operator SOCKADDR()
{ return *((LPSOCKADDR) this); }
operator LPSOCKADDR()
{ return (LPSOCKADDR) this; }
operator LPSOCKADDR_IN()
{ return (LPSOCKADDR_IN) this; }
};
// member functions truly block and must not be used in UI threads
// use this class as an alternative to the MFC CSocket class
class CeSocket
{
private:
SOCKET m_hSocket;
public:
CeSocket()
{ m_hSocket = INVALID_SOCKET; }
operator SOCKET()
{ return m_hSocket; }
void Cleanup();
BOOL Create(int nType = SOCK_STREAM);
void Close();
BOOL Bind(LPCSOCKADDR psa);
BOOL Listen();
BOOL Connect(LPCSOCKADDR psa, const DWORD dwMilliSecs = INFINITE);
BOOL Accept(CeSocket& s, LPSOCKADDR psa);
int Send(const BYTE* pch, const int nSize, const DWORD dwMilliSecs);
int Write(const BYTE* pch, const int nSize, const DWORD dwMilliSecs);
int Receive(BYTE* pch, const int nSize, const DWORD dwMilliSecs);
int SendTo(const BYTE* pch, const int nSize, LPCSOCKADDR psa, const DWORD dwMilliSecs);
int ReceiveFrom(BYTE* pch, const int nSize, LPSOCKADDR psa, const DWORD dwMilliSecs);
BOOL GetPeerAddr(LPSOCKADDR psa) const;
BOOL GetSockAddr(LPSOCKADDR psa) const;
// Generic socket options
BOOL SetOption(int nLevel, int nOption, const void* pVal, int nValLen);
BOOL GetOption(int nLevel, int nOption, void* pVal, int* pValLen) const;
// Specific socket options
BOOL SetWriteTimeout(int nMilliSecs)
{ return SetOption(SOL_SOCKET, SO_SNDTIMEO, &nMilliSecs, sizeof(int)); }
int GetWriteTimeout() const
{
int nMilliSecs = 0, nSize = sizeof(int);
if (!GetOption(SOL_SOCKET, SO_SNDTIMEO, &nMilliSecs, &nSize))
return -1;
return nMilliSecs;
}
BOOL SetReadTimeout(int nMilliSecs)
{ return SetOption(SOL_SOCKET, SO_RCVTIMEO, &nMilliSecs, sizeof(int)); }
int GetReadTimeout() const
{
int nMilliSecs = 0, nSize = sizeof(int);
if (! GetOption(SOL_SOCKET, SO_RCVTIMEO, &nMilliSecs, &nSize))
return -1;
return nMilliSecs;
}
static int GetLastError()
{ return ::WSAGetLastError(); }
#ifdef UNICODE
static CeSockAddr GetHostByName(LPCTSTR pchName, const USHORT ushPort = 0);
#endif // UNICODE
static CeSockAddr GetHostByName(const char *pchName, const USHORT ushPort = 0);
static const char* GetHostByAddr(LPCSOCKADDR psa);
};
#endif // __CeSocket_h__