File: SampleSocketPort.h

package info (click to toggle)
libcommoncpp2 1.8.1-10
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 5,300 kB
  • sloc: cpp: 29,221; sh: 10,352; ansic: 1,134; makefile: 238; xml: 5
file content (198 lines) | stat: -rw-r--r-- 5,563 bytes parent folder | download | duplicates (7)
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/**
 *
 *	This class demonstrates use of the CommonC++ SocketPort class.
 *
 *	Copyright 2001 - Nick Liebmann <nick@ukmail.org>
 *
 *	This sample code is distributed under the same terms and conditions of the CommonC++ library.
 */

#include <cc++/socketport.h>

#ifdef	CCXX_NAMESPACES
using namespace ost;
using namespace std;
#endif

#define MAX_RXBUF		32768		/**< Specifies the maximum number of bytes in a 'packet' */
#define MAX_RXTIMEOUT	10000		/**< Specifies how long we will wait for a complete packet */
#define	DISCONNECT_MS	500			/**< Specifies the timeout for the diconnect timer */

class SampleSocketPort : public SocketPort
{
public:
	SampleSocketPort(SocketService *pService, TCPSocket & tcpSocket);
	virtual ~SampleSocketPort();

	/**
	 *	Overridden from class SocketPort.
	 *	Called when data is available in the receive buffer.
	 */
	virtual void pending();

	/**
	 *	Overridden from class SocketPort.
	 *	Called when the socket has been disconnected from the client-side.
	 *	Under some conditions this function is NOT called, which is why we have
	 *	some additional disconnection functionality within pending().
	 */
	virtual void disconnect(void);

	/**
	 *	Overridden from class SocketPort.
	 *	This function is called by the system when our timer expires.
	 *	We use the timer for 2 things:
	 *	1) To determine whether reception has timed out. (Timer started in pending())
	 *	2) To call CloseInterface to safely destroy the port.
	 */
	virtual void expired(void);


	/**
	 *	This function will send the specified number of bytes, or the whole string
	 *	(without the terminating '\0')
	 */
	bool WriteData(const char *szTxData, const size_t nByteCount = -1);

	/**
	 *	Our function to provide uniform closure of the Socket.
	 *	Can be called from the outside!
	 */
	bool CloseSocket(void);

	/**
	 *	This function should be called from pending() when the first bytes of our
	 *	data has been received. If the complete data has not been received by the time
	 *	this expires we consider this an error.
	 *
	 */
	void ResetReadTimeout(timeout_t timeout) {
		m_bTimedOut = false;
		setTimer(timeout);
	}

	/**
	 *	This function should be use in the event of a reception error, to flush out
	 *	the receive buffer.
	 */
	void FlushRxData(void) {
		while(receive(m_pBuf, MAX_RXBUF) > 0);
		cerr << "FLUSHED" << endl;
	}


	/*
	 *	Some virtual function placeholders.....
	 */

	/**
	 *	This function is called just before the port is closed.
	 *	Do not send any data from this function!
	 */
	virtual void OnConnectionClosed(void) {
		cerr << "Connection Closed!" << endl;
	}
	/**
	 *	Called when the receive timeout occurs
	 */
	virtual void OnRxTimeout(void) {
		cerr << "Receive timeout occurred" << endl;
		FlushRxData();
	}
	/**
	 *	Called when a 'packet' of data has been received.
	 */
	virtual void OnDataReceived(char *pszData, unsigned int nByteCount) {
	}
protected:
	bool m_bOpen;				/**< Flag set to true while Socket is open */
	bool m_bDoDisconnect;		/**< Flag set to true when disconnection event has occurred */
	bool m_bTimedOut;			/**< Flag set to true when reception has timed out */
	bool m_bReceptionStarted;	/**< Flag set to true when the first bytes of a transmission have arrived */
	int m_nLastBytesAvail;		/**< Count of last number of bytes received in pending() */
	char *m_pBuf;				/**< Buffer used to store received data for parsing */

	/**
	 *	Little utility function for sending data to the client.
	 *	@return Number of bytes sent to client
	 */
	ssize_t DoSend(void *buf, size_t len);
};


/*
 *	This class implements a Thread that manages a SocketService. Simply
 *	create an instance of this class with the specified address and port, and
 *	signal the semaphore when you want it to start.
 *
 *	A new SampleSocketPort object will be created for every connection that arrives.
 *
 */

class SampleSocketServiceServer :  public virtual TCPSocket, public virtual Thread
{
public:
	SampleSocketServiceServer(InetHostAddress & machine, int port) :
					TCPSocket(machine, port), Thread(), m_bQuitServer(true) {
		m_pSocketService = new SocketService(0);

		//IMPORTANT SOCKET SERVICE MUST NOW BE EXPLICITLY STARTED
		m_pSocketService->start();
	}

	virtual ~SampleSocketServiceServer()
	{ terminate(); delete m_pSocketService; }

	virtual void run(void) {
   		waitMutex.enterMutex();
   		m_bQuitServer = false;
		while(!m_bQuitServer) {
			try {
				// new does all the work to accept a new connection
				// and attach itself to the SocketService.
				CreateSocketPort(m_pSocketService, *((TCPSocket *)this));
			}
			catch ( ... ) {
				// Bummer - there was an error.
				cerr << "SampleSocketPort create failed\n";
				exit();
			}
		}
		waitMutex.leaveMutex();
	}
	/**
	 *	This abstract function is used to create a SocketPort of the desired type.
	 */
	virtual SocketPort *CreateSocketPort(SocketService *pService, TCPSocket & Socket) = 0;
	virtual void StartServer() {
		m_bQuitServer = true;
		start();
		while(m_bQuitServer) {
			Thread::yield();
		}
	}

	/**
	 *	If the server is not stopped like this then the SocketPort created in CreateSocketPort
	 *	is leaked. This allows it to complete construction, and be deleted cleanly.
	 */
	virtual void StopServer() {
		m_bQuitServer = true;

		InetHostAddress host;
		tpport_t port;
		host = getLocal(&port);

		//This is required so that CreateSocketPort can return.
		TCPStream strm(host, port);

		waitMutex.enterMutex();
		waitMutex.leaveMutex();
	}
protected:
	SocketService *m_pSocketService;
	bool m_bQuitServer;
	Mutex waitMutex;
private:
};