summaryrefslogtreecommitdiff
path: root/Ivy/ThreadedSocket.h
blob: 1a3f40525ecd32781c0934d5edef1f76d7eb6b68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// ThreadedSocket.h: interface for the CThreadedSocket class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_THREADEDSOCKET_H__DC45EFD8_343F_11D3_8A15_00A0245B298A__INCLUDED_)
#define AFX_THREADEDSOCKET_H__DC45EFD8_343F_11D3_8A15_00A0245B298A__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <winsock2.h>

class CThreadedSocketException //: public CException
{
//	DECLARE_DYNAMIC(CThreadedSocketException)
public:
// Constructor
	CThreadedSocketException(char* pchMessage);

public:
	~CThreadedSocketException() {}
	virtual bool GetErrorMessage(string& lpstrError, unsigned int nMaxError,
		unsigned int * pnHelpContext = 0);
	int GetError() { return m_nError; };
private:
	int m_nError;
	char * m_strMessage;
};

class CThreadedSocket  //: public CObject
{
//	DECLARE_DYNAMIC(CThreadedSocket);
//	typedef unsigned int SOCKET;
//	typedef struct sockaddr SOCKADDR;

public:
	CThreadedSocket();
	virtual ~CThreadedSocket();
// Construction
public:
	void Create(unsigned int nSocketPort = 0, int nSocketType=SOCK_STREAM,
		long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
		const char * lpszSocketAddress = 0);

// Attributes
public:
	SOCKET m_hSocket;

	operator SOCKET() const;
	
	void GetPeerName(string & rPeerAddress, unsigned int& rPeerPort);

	void GetSockName(string & rSocketAddress, unsigned int& rSocketPort);

// Operations
public:
	void Socket(int nSocketType=SOCK_STREAM, long lEvent =
		FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
		int nProtocolType = 0, int nAddressFormat = PF_INET);
	virtual void Accept(CThreadedSocket& rConnectedSocket,
		SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL);

	void Bind(unsigned int nSocketPort, const char * lpszSocketAddress = 0);

	virtual void Close();

	bool Connect(const char * lpszHostAddress, unsigned int nHostPort);
	bool Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen);
	
	virtual int Receive(void* lpBuf, int nBufLen, int nFlags = 0);

	int ReceiveFrom(void* lpBuf, int nBufLen,
		string & rSocketAddress, unsigned int & rSocketPort, int nFlags = 0);

	enum { receives = 0, sends = 1, both = 2 };

	virtual void Send(const void* lpBuf, int nBufLen, int nFlags = 0);

	void SendTo(const void* lpBuf, int nBufLen,
		unsigned int nHostPort, const char * lpszHostAddress = 0, int nFlags = 0);
	void AsyncSelect(long lEvent =
		FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);

	
inline CThreadedSocket::operator SOCKET() const
	{ return m_hSocket; }
inline void GetPeerName(SOCKADDR* lpSockAddr, int* lpSockAddrLen)
	{ 
	if ( getpeername(m_hSocket, lpSockAddr, lpSockAddrLen) == SOCKET_ERROR)
		throw( new CThreadedSocketException( "getpeername" ) );
	}
inline void GetSockName(SOCKADDR* lpSockAddr, int* lpSockAddrLen)
	{ if ( getsockname(m_hSocket, lpSockAddr, lpSockAddrLen)== SOCKET_ERROR)
		throw( new CThreadedSocketException( "getsockname" ) );
	}
inline void SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel = SOL_SOCKET)
	{ 
	if ( setsockopt(m_hSocket, nLevel, nOptionName, (LPCSTR)lpOptionValue, nOptionLen)== SOCKET_ERROR)
		throw( new CThreadedSocketException( "setsockopt" ) );
	}
inline void GetSockOpt(int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel = SOL_SOCKET)
	{
	if ( getsockopt(m_hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, lpOptionLen)== SOCKET_ERROR)
		throw( new CThreadedSocketException( "getsockopt" ) );
	}

static inline int CThreadedSocket::GetLastError()
	{ return WSAGetLastError(); }
inline void Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen)
	{ 
	if ( bind(m_hSocket, lpSockAddr, nSockAddrLen)== SOCKET_ERROR ) 
		throw( new CThreadedSocketException( "bind" ));
	}

inline void IOCtl(long lCommand, unsigned long* lpArgument)
	{ if ( ioctlsocket(m_hSocket, lCommand, lpArgument)== SOCKET_ERROR)
		throw( new CThreadedSocketException( "bind" ) );
	}
inline void Listen(int nConnectionBacklog=5)
	{ 
	if (  listen(m_hSocket, nConnectionBacklog)== SOCKET_ERROR)
		throw( new CThreadedSocketException( "listen" ) );
	}
inline int ReceiveFrom(void* lpBuf, int nBufLen, SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags = 0)
	{
	int lg = recvfrom(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags, lpSockAddr, lpSockAddrLen); 
	if ( lg == SOCKET_ERROR )
		throw( new CThreadedSocketException( "recvfrom" ) );
	return lg;
	}
inline bool ShutDown(int nHow = sends)
	{ 
	if (  shutdown(m_hSocket,nHow) == SOCKET_ERROR ) 
		throw( new CThreadedSocketException( "shutdown" ) );
	}
inline void SendTo(const void* lpBuf, int nBufLen, const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags = 0)
	{
	if (  sendto(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags, lpSockAddr, nSockAddrLen)== SOCKET_ERROR )
		throw( new CThreadedSocketException( "sendto" ) );
	}



// Overridable callbacks
protected:
	virtual void OnWakeup();
	virtual void OnReceive(int nErrorCode);
	virtual void OnSend(int nErrorCode);
	virtual void OnOutOfBandData(int nErrorCode);
	virtual void OnAccept(int nErrorCode);
	virtual void OnConnect(int nErrorCode);
	virtual void OnClose(int nErrorCode);
// Implementation 
	void StartListener(long lEvent);
	long m_EventMask;
	unsigned long thread_id;
	HANDLE h_thread;
	WSAEVENT m_hEvent[2];   // socket event for receive and send actions
	unsigned int SocketThread();	//Client Thread

// wrapper for thread routine
static DWORD WINAPI SocketThreadProc( void * pParam );

};

#endif // !defined(AFX_THREADEDSOCKET_H__DC45EFD8_343F_11D3_8A15_00A0245B298A__INCLUDED_)