#include "stdafx.h"
#include "csmartsocket.h"
#include "gmud32.h"
#define new DEBUG_NEW
CSmartSocket::CSmartSocket()
{
m_pParent=0;
m_pRecieveBuf = new char[BUFFSIZE];
m_pCombineBuf= new char[BUFFSIZE];
m_pFragBuf = new char[BUFFSIZE];
*m_pFragBuf=*m_pRecieveBuf=*m_pCombineBuf=0;
m_bConnected=FALSE;
m_bPaused=FALSE;
}
CSmartSocket::~CSmartSocket()
{
delete m_pRecieveBuf;
delete m_pCombineBuf;
delete m_pFragBuf;
}
CSmartSocket::SetParentWnd(CWnd *pParent)
{
m_pParent=pParent;
return TRUE;
}
BOOL __cdecl CSmartSocket::Printf(LPSTR format, ...)
{
ASSERT_VALID(this);
if(!m_bConnected)
return FALSE;
// do the sprintf stuff
LPSTR buffer = new char[BUFFSIZE];
va_list marker;
va_start(marker,format);
vsprintf(buffer,format,marker);
va_end(marker);
// add it to our output buffer
m_asOutBuffer.Add(buffer);
delete buffer;
AsyncSelect(FD_READ|FD_WRITE|FD_CLOSE);
return TRUE;
}
void CSmartSocket::OnConnect(int nErrorCode)
{
if(!nErrorCode)
m_bConnected=TRUE;
m_pParent->SendMessage(WM_SOCKET_CONNECTED,nErrorCode);
m_bPaused=FALSE;
}
void CSmartSocket::OnSend(int nErrorCode )
{
if(nErrorCode)
TRACE("\nError in send: (%d) - %s.",nErrorCode,SockerrToString(nErrorCode));
if(m_asOutBuffer.GetSize())
{
if(Send(m_asOutBuffer[0],m_asOutBuffer[0].GetLength())==SOCKET_ERROR)
TRACE("\nError in send function.");
else
m_asOutBuffer.RemoveAt(0);
}
}
void CSmartSocket::OnClose(int nErrorCode)
{
m_bConnected=FALSE;
Close();
m_pParent->PostMessage(WM_SOCKET_DISCONNECTED,nErrorCode);
TRACE("\n\nOnClose Called.");
Pause(FALSE);
}
BOOL CSmartSocket::HardClose()
{
TRACE("\nSocket thinks it's connected? (%d)",m_bConnected);
m_bConnected=FALSE;
LINGER linger;
if( m_hSocket == INVALID_SOCKET )
{
// Ignore invalid sockets.
TRACE("\nHard Close Aborted, not a valid socket");
return FALSE;
}
linger.l_onoff = TRUE;
linger.l_linger = 0;
SetSockOpt(SO_LINGER,(CHAR FAR *)&linger,sizeof(linger) );
// Close the socket.
TRACE("\nHard Close Performed.");
Close();
m_hSocket = INVALID_SOCKET;
m_pParent->SendMessage(WM_SOCKET_DISCONNECTED);
return TRUE;
}
BOOL CSmartSocket::IsConnected()
{
return m_bConnected;
}
// over-ridden functions
void CSmartSocket::OnReceive(int nErrorCode )
{
if(m_bPaused)
return;
static int recursion = -1;
recursion ++;
if(recursion)
{
TRACE("\nRecursion: %d",recursion);
}
ASSERT_VALID(this);
if(nErrorCode)
TRACE("\nError in receive: (%d) - %s.",nErrorCode,SockerrToString(nErrorCode));
LPSTR pBuf = new char [BUFFSIZE];
LPSTR pAdjBuf = pBuf; // adjusted buffer for frag merging.
if(*m_pFragBuf) // special routine to avoid sending out incomplete ansi sequences.
{
strcpy(pBuf,m_pFragBuf); // first copy the frag
*m_pFragBuf=0;
pAdjBuf+=strlen(pBuf);
}
int retcode=1;
retcode = Receive(pAdjBuf,BUFFSIZE-50);
if(retcode>0 && retcode !=SOCKET_ERROR)
{
pAdjBuf[retcode]=0; // null terminate it.
if(GetApp()->m_bAnsi) // special routine to avoid sending out incomplete ansi sequences.
{
// check the combined string for a trailing fragment
LPSTR pCheck=pAdjBuf+(retcode-1);
// pCheck should be pointing at the last char...
while(pCheck>pBuf)
{
if(isdigit(*pCheck) && pCheck>pBuf)
pCheck--;
if(isdigit(*pCheck)&& pCheck>pBuf)
pCheck--;
if(*pCheck==';'&& pCheck>pBuf)
pCheck--;
else if(*pCheck=='['&& pCheck>pBuf)
pCheck--;
else
break;
}
if(*pCheck==27) // we have a fragment
{
strcpy(m_pFragBuf,pCheck); // copy it for storage
*pCheck=0; // truncate the string
}
// okay we're now ready to send the ansi-complete string.
AfxCheckMemory();
m_pParent->PostMessage(WM_SOCKET_STRING_RECIEVED,0,(long)pBuf);
}
else
m_pParent->PostMessage(WM_SOCKET_STRING_RECIEVED,0,(long)pBuf);
}
else
{
delete pBuf;
}
recursion--;
}
CSmartSocket::Pause( BOOL bPause)
{
if(bPause)
{
m_bPaused=TRUE;
}
else
{
m_bPaused=FALSE;
OnReceive(0);
}
return bPause;
}
LPSTR CSmartSocket::SockerrToString( UINT serr )
{
switch( serr )
{
case WSAENAMETOOLONG :
return "Name too long";
case WSANOTINITIALISED :
return "Not initialized";
case WSASYSNOTREADY :
return "System not ready";
case WSAVERNOTSUPPORTED :
return "Version is not supported";
case WSAESHUTDOWN :
return "Can't send after socket shutdown";
case WSAEINTR :
return "Interrupted system call";
case WSAHOST_NOT_FOUND :
return "Host not found";
case WSATRY_AGAIN :
return "Try again";
case WSANO_RECOVERY :
return "Non-recoverable error";
case WSANO_DATA :
return "Hostname lookup failure";
case WSAEBADF :
return "Bad file number";
case WSAEWOULDBLOCK :
return "Operation would block";
case WSAEINPROGRESS :
return "Operation now in progress";
case WSAEALREADY :
return "Operation already in progress";
case WSAEFAULT :
return "Bad address";
case WSAEDESTADDRREQ :
return "Destination address required";
case WSAEMSGSIZE :
return "Message too long";
case WSAEPFNOSUPPORT :
return "Protocol family not supported";
case WSAENOTEMPTY :
return "Directory not empty";
case WSAEPROCLIM :
return "EPROCLIM returned";
case WSAEUSERS :
return "EUSERS returned";
case WSAEDQUOT :
return "Disk quota exceeded";
case WSAESTALE :
return "ESTALE returned";
case WSAEINVAL :
return "Invalid argument";
case WSAEMFILE :
return "Too many open files";
case WSAEACCES :
return "Access denied";
case WSAELOOP :
return "Too many levels of symbolic links";
case WSAEREMOTE :
return "The object is remote";
case WSAENOTSOCK :
return "Socket operation on non-socket";
case WSAEADDRNOTAVAIL :
return "Can't assign requested address";
case WSAEADDRINUSE :
return "Address already in use";
case WSAEAFNOSUPPORT :
return "Address family not supported by protocol family";
case WSAESOCKTNOSUPPORT :
return "Socket type not supported";
case WSAEPROTONOSUPPORT :
return "Protocol not supported";
case WSAENOBUFS :
return "No buffer space is supported";
case WSAETIMEDOUT :
return "Connection timed out";
case WSAEISCONN :
return "Socket is already connected";
case WSAENOTCONN :
return "Socket is not connected";
case WSAENOPROTOOPT :
return "Bad protocol option";
case WSAECONNRESET :
return "Connection reset by peer";
case WSAECONNABORTED :
return "Software caused connection abort";
case WSAENETDOWN :
return "Network is down";
case WSAENETRESET :
return "Network was reset";
case WSAECONNREFUSED :
return "Connection refused";
case WSAEHOSTDOWN :
return "Host is down";
case WSAEHOSTUNREACH :
return "Host is unreachable";
case WSAEPROTOTYPE :
return "Protocol is wrong type for socket";
case WSAEOPNOTSUPP :
return "Operation not supported on socket";
case WSAENETUNREACH :
return "ICMP network unreachable";
case WSAETOOMANYREFS :
return "Too many references";
default :
return "Unknown";
}
}