An Echo server as described in RFC862. Written as a learning exercise for using Donatien's network stack. Hopefully of some use to others to get started with socket programming.
Diff: TCPEchoHandler.cpp
- Revision:
- 0:c4e397ba6a9d
diff -r 000000000000 -r c4e397ba6a9d TCPEchoHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TCPEchoHandler.cpp Sat Jun 12 19:05:52 2010 +0000 @@ -0,0 +1,69 @@ +#include "TCPEchoHandler.h" + +// When the constructor's called, initialise the member variables +TCPEchoHandler::TCPEchoHandler(TCPSocket* tcpClientSocket) + : NetService() + , clientSocket(tcpClientSocket) + , closed(0) + , timeoutWatchdog() { + // Wire up the event handler on the client TCP socket + clientSocket->setOnEvent(this, &TCPEchoHandler::onTCPSocketEvent); +} + +TCPEchoHandler::~TCPEchoHandler() { + // Close the socket on destruction + close(); +} + +void TCPEchoHandler::onTCPSocketEvent(TCPSocketEvent e) { + switch (e) { + // If the socket is readable, do stuff + case TCPSOCKET_READABLE: + // Disable the timeout watchdog timer + timeoutWatchdog.detach(); + // Read in any available data into the buffer + char buff[128]; + while ( int len = clientSocket->recv(buff, 128) ) { + // And send straight back out again + clientSocket->send(buff, len); + } + // Reset timeout countdown + setTimeout(ECHO_TIMEOUT); + break; + case TCPSOCKET_CONTIMEOUT: + case TCPSOCKET_CONRST: + case TCPSOCKET_CONABRT: + case TCPSOCKET_ERROR: + case TCPSOCKET_DISCONNECTED: + // Close the socket on any terminal TCP event + close(); + break; + } + +} + +void TCPEchoHandler::close() { + // Prevent recursive calling or calling on an object being destructed by someone else + if ( closed ) + return; + closed = 1; + timeoutWatchdog.detach(); + if ( clientSocket ) { + clientSocket->resetOnEvent(); + clientSocket->close(); + delete clientSocket; //This fn might have been called by this socket (through an event), so DO NOT DESTROY IT HERE + } + // Flags this service as closed - will be destructed and deleted on + // the next call of NetService::poll() by Net::poll() + NetService::close(); +} + +void TCPEchoHandler::setTimeout(unsigned int timeout) { + // Attach our timeout handler to the timeout watchdog timer to close the socket if no activity + timeoutWatchdog.attach_us<TCPEchoHandler>(this, &TCPEchoHandler::onTimeout, ECHO_TIMEOUT * 1000); +} + +void TCPEchoHandler::onTimeout() { + // Nothing fancy, just close the socket and mark this class for destruction + close(); +}