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.

Dependencies:   mbed

Committer:
darran
Date:
Sat Jun 12 19:05:52 2010 +0000
Revision:
0:c4e397ba6a9d

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
darran 0:c4e397ba6a9d 1 #include "TCPEchoHandler.h"
darran 0:c4e397ba6a9d 2
darran 0:c4e397ba6a9d 3 // When the constructor's called, initialise the member variables
darran 0:c4e397ba6a9d 4 TCPEchoHandler::TCPEchoHandler(TCPSocket* tcpClientSocket)
darran 0:c4e397ba6a9d 5 : NetService()
darran 0:c4e397ba6a9d 6 , clientSocket(tcpClientSocket)
darran 0:c4e397ba6a9d 7 , closed(0)
darran 0:c4e397ba6a9d 8 , timeoutWatchdog() {
darran 0:c4e397ba6a9d 9 // Wire up the event handler on the client TCP socket
darran 0:c4e397ba6a9d 10 clientSocket->setOnEvent(this, &TCPEchoHandler::onTCPSocketEvent);
darran 0:c4e397ba6a9d 11 }
darran 0:c4e397ba6a9d 12
darran 0:c4e397ba6a9d 13 TCPEchoHandler::~TCPEchoHandler() {
darran 0:c4e397ba6a9d 14 // Close the socket on destruction
darran 0:c4e397ba6a9d 15 close();
darran 0:c4e397ba6a9d 16 }
darran 0:c4e397ba6a9d 17
darran 0:c4e397ba6a9d 18 void TCPEchoHandler::onTCPSocketEvent(TCPSocketEvent e) {
darran 0:c4e397ba6a9d 19 switch (e) {
darran 0:c4e397ba6a9d 20 // If the socket is readable, do stuff
darran 0:c4e397ba6a9d 21 case TCPSOCKET_READABLE:
darran 0:c4e397ba6a9d 22 // Disable the timeout watchdog timer
darran 0:c4e397ba6a9d 23 timeoutWatchdog.detach();
darran 0:c4e397ba6a9d 24 // Read in any available data into the buffer
darran 0:c4e397ba6a9d 25 char buff[128];
darran 0:c4e397ba6a9d 26 while ( int len = clientSocket->recv(buff, 128) ) {
darran 0:c4e397ba6a9d 27 // And send straight back out again
darran 0:c4e397ba6a9d 28 clientSocket->send(buff, len);
darran 0:c4e397ba6a9d 29 }
darran 0:c4e397ba6a9d 30 // Reset timeout countdown
darran 0:c4e397ba6a9d 31 setTimeout(ECHO_TIMEOUT);
darran 0:c4e397ba6a9d 32 break;
darran 0:c4e397ba6a9d 33 case TCPSOCKET_CONTIMEOUT:
darran 0:c4e397ba6a9d 34 case TCPSOCKET_CONRST:
darran 0:c4e397ba6a9d 35 case TCPSOCKET_CONABRT:
darran 0:c4e397ba6a9d 36 case TCPSOCKET_ERROR:
darran 0:c4e397ba6a9d 37 case TCPSOCKET_DISCONNECTED:
darran 0:c4e397ba6a9d 38 // Close the socket on any terminal TCP event
darran 0:c4e397ba6a9d 39 close();
darran 0:c4e397ba6a9d 40 break;
darran 0:c4e397ba6a9d 41 }
darran 0:c4e397ba6a9d 42
darran 0:c4e397ba6a9d 43 }
darran 0:c4e397ba6a9d 44
darran 0:c4e397ba6a9d 45 void TCPEchoHandler::close() {
darran 0:c4e397ba6a9d 46 // Prevent recursive calling or calling on an object being destructed by someone else
darran 0:c4e397ba6a9d 47 if ( closed )
darran 0:c4e397ba6a9d 48 return;
darran 0:c4e397ba6a9d 49 closed = 1;
darran 0:c4e397ba6a9d 50 timeoutWatchdog.detach();
darran 0:c4e397ba6a9d 51 if ( clientSocket ) {
darran 0:c4e397ba6a9d 52 clientSocket->resetOnEvent();
darran 0:c4e397ba6a9d 53 clientSocket->close();
darran 0:c4e397ba6a9d 54 delete clientSocket; //This fn might have been called by this socket (through an event), so DO NOT DESTROY IT HERE
darran 0:c4e397ba6a9d 55 }
darran 0:c4e397ba6a9d 56 // Flags this service as closed - will be destructed and deleted on
darran 0:c4e397ba6a9d 57 // the next call of NetService::poll() by Net::poll()
darran 0:c4e397ba6a9d 58 NetService::close();
darran 0:c4e397ba6a9d 59 }
darran 0:c4e397ba6a9d 60
darran 0:c4e397ba6a9d 61 void TCPEchoHandler::setTimeout(unsigned int timeout) {
darran 0:c4e397ba6a9d 62 // Attach our timeout handler to the timeout watchdog timer to close the socket if no activity
darran 0:c4e397ba6a9d 63 timeoutWatchdog.attach_us<TCPEchoHandler>(this, &TCPEchoHandler::onTimeout, ECHO_TIMEOUT * 1000);
darran 0:c4e397ba6a9d 64 }
darran 0:c4e397ba6a9d 65
darran 0:c4e397ba6a9d 66 void TCPEchoHandler::onTimeout() {
darran 0:c4e397ba6a9d 67 // Nothing fancy, just close the socket and mark this class for destruction
darran 0:c4e397ba6a9d 68 close();
darran 0:c4e397ba6a9d 69 }