SampleSocketPort.cpp
#include "SampleSocketPort.h"
SampleSocketPort::SampleSocketPort(SocketService *pService, TCPSocket & tcpSocket) :
SocketPort(pService, tcpSocket) {
tpport_t port;
InetHostAddress ia = getPeer( & port );
cerr << "connecting from " << ia.getHostname() << ":" << port << endl;
setCompletion( false );
m_bOpen = true;
m_bDoDisconnect = false;
m_bTimedOut = false;
m_bReceptionStarted = false;
m_nLastBytesAvail = 0;
m_pBuf = new char[MAX_RXBUF];
}
SampleSocketPort::~SampleSocketPort()
{
endSocket();
delete [] m_pBuf;
}
void SampleSocketPort::pending(void)
{
if(!m_bOpen)
return;
int nBytesAvail = peek(m_pBuf, MAX_RXBUF);
if(!m_bReceptionStarted)
{
ResetReadTimeout(MAX_RXTIMEOUT);
m_bReceptionStarted = true;
}
else {
if(m_bTimedOut)
{
ResetReadTimeout(MAX_RXTIMEOUT);
m_nLastBytesAvail = 0;
m_bReceptionStarted = false;
OnRxTimeout();
return;
}
}
if(m_nLastBytesAvail == nBytesAvail)
{
if(nBytesAvail == 0)
{
if(!m_bDoDisconnect) {
CloseSocket();
}
}
return;
}
if(nBytesAvail > MAX_RXBUF) {
cerr << "TCP/IP overflow..." << endl;
FlushRxData();
m_nLastBytesAvail = 0;
m_bReceptionStarted = false;
return;
}
m_nLastBytesAvail = nBytesAvail;
for(int i=0; i < nBytesAvail; i++) {
if(m_pBuf[i] == '\r') {
if(i+1 < nBytesAvail) {
if(m_pBuf[i+1] == '\n')
{
m_nLastBytesAvail = 0;
m_bReceptionStarted = false;
int nLen = i+2;
char *pszRxData = new char[nLen+1];
receive(pszRxData, nLen);
pszRxData[nLen] = '\0';
OnDataReceived(pszRxData, nLen);
delete [] pszRxData;
return;
}
}
}
}
}
void SampleSocketPort::disconnect(void)
{
if(m_bOpen) {
m_bDoDisconnect = true;
CloseSocket();
}
}
void SampleSocketPort::expired(void)
{
if(m_bDoDisconnect && m_bOpen) {
CloseSocket();
}
else if(m_bOpen && m_bReceptionStarted) {
m_bTimedOut = true;
}
}
bool SampleSocketPort::CloseSocket(void)
{
if(m_bOpen && m_bDoDisconnect)
{
m_bOpen = false;
OnConnectionClosed();
delete this;
}
else if(m_bOpen) {
m_bDoDisconnect = true;
setTimer(DISCONNECT_MS);
}
return(true);
}
ssize_t SampleSocketPort::DoSend(void *buf, size_t len)
{
if(m_bDoDisconnect)
return((ssize_t)len);
ssize_t nSent = send(buf, len);
while(!isPending(Socket::pendingOutput, 0))
{
if(m_bDoDisconnect || !m_bOpen) {
return((ssize_t)len);
}
Thread::yield();
}
return(nSent);
}
bool SampleSocketPort::WriteData(const char *szTxData, const size_t nByteCount)
{
ssize_t nLen = nByteCount;
if(nLen == -1)
nLen = (ssize_t)strlen(szTxData);
size_t nBytesToSend = nLen;
while(m_bOpen && nLen) {
nLen -= DoSend((void *)&(szTxData[nBytesToSend - nLen]), nLen);
}
return(true);
}
#define WITH_EXAMPLE
#ifdef WITH_EXAMPLE
int g_nOpenPorts = 0;
class ReverserPort : public SampleSocketPort
{
public:
ReverserPort(SocketService *pService, TCPSocket & tcpSocket) :
SampleSocketPort(pService, tcpSocket) {
g_nOpenPorts++;
}
virtual ~ReverserPort() {
g_nOpenPorts--;
}
virtual void OnConnectionClosed(void)
{ cerr << "Connection Closed!" << endl; }
virtual void OnDataReceived(char *pszData, unsigned int nByteCount) {
size_t nLen = strlen(pszData);
char *szToSend = new char[nLen+1];
size_t nIndex = nLen-3;
size_t i;
for(i=0; i < nLen - 2; i++) {
szToSend[i] = pszData[nIndex - i];
}
szToSend[i++] = '\r';
szToSend[i++] = '\n';
szToSend[nLen] = '\0';
WriteData(szToSend, nLen);
delete [] szToSend;
}
};
class ReverserServer : public SampleSocketServiceServer
{
public:
ReverserServer(InetHostAddress & machine, int port) :
TCPSocket(machine, port), Thread(), SampleSocketServiceServer(machine, port) {
}
virtual ~ReverserServer() {
}
virtual SocketPort *CreateSocketPort(SocketService *pService, TCPSocket & Socket) {
return(new ReverserPort(pService, Socket));
}
};
int main(void)
{
InetHostAddress LocalHost;
LocalHost = htonl(INADDR_ANY);
ReverserServer *Server = NULL;
try {
Server = new ReverserServer(LocalHost, 3999);
Server->StartServer();
}
catch(...) {
cerr << "Failed to start server" << endl;
return(false);
}
cerr << "Waiting for connections...type \"quit\" to exit." << endl;
char cmd[255];
cin.getline(cmd, 255);
while(strcmp(cmd, "quit") != 0) {
cin.getline(cmd, 255);
}
Server->StopServer();
delete Server;
return 0;
}
#endif //WITH_EXAMPLE