Mercurial > ecos
diff host/tools/Utils/common/eCosSocket.cpp @ 82:6736c52df507 ecos-sw-2000-04-14
Merge from eCos master repository on 2000-04-14-13:35:46-BST
| author | jlarmour |
|---|---|
| date | Tue, 18 Apr 2000 21:51:55 +0000 |
| parents | |
| children | 9034ec3868e5 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/host/tools/Utils/common/eCosSocket.cpp @@ -0,0 +1,820 @@ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This program is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//================================================================= +// +// eCosSocket.cpp +// +// Socket test class +// +//================================================================= +//================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): sdf +// Contributors: sdf +// Date: 1999-04-01 +// Description: This class abstracts tcp/ip sockets for use in the testing infrastructure +// Usage: +// +//####DESCRIPTIONEND#### + +#include "eCosStd.h" +#include "eCosSocket.h" +#include "eCosSerial.h" +#include "eCosThreadUtils.h" +#include "eCosTrace.h" +#include <map> + +enum {ERR_TIMEOUT=20000, ERR_READ_AFTER_CLOSE=20001}; + +// Blocking read on one or other of the data sources: +// Result: -1 - socket error occurred +// 1 - data read from socket +// -2 - serial error occurred +// 2 - data read from serial + +CeCosSocket::SSReadResult CeCosSocket::SSRead (CeCosSerial &serial,CeCosSocket &socket,void *pBuf,unsigned int nSize,unsigned int &nRead,bool *pbStop) +{ + SSReadResult rc=SS_STOPPED; + bool bBlocking=serial.GetBlockingReads(); + bool bBlockingModified=false; + while(0==pbStop || !(*pbStop)){ + if(!socket.Peek(nRead)){ + rc=SS_SOCKET_ERROR; + break; + } else if(nRead){ + nRead=MIN(nRead,nSize); + rc=socket.recv(pBuf,nRead)?SS_SOCKET_READ:SS_SOCKET_ERROR; + break; + } else { + if(bBlocking){ + serial.SetBlockingReads(false); + bBlockingModified=true; + bBlocking=false; + } + if(serial.Read(pBuf,nSize,nRead)){ + if(nRead>0){ + rc=SS_SERIAL_READ; + break; + } + } else { + rc=SS_SERIAL_ERROR; + break; + } + } + CeCosThreadUtils::Sleep(10); + } + if(bBlockingModified){ + serial.SetBlockingReads(true); + } + return rc; +} + +// ctors and dtors + +CeCosSocket::CeCosSocket (): +m_nDefaultTimeout(10*1000), +m_nSock(-1), +m_nClient(0) +{ + VTRACE(_T("Create socket instance %08x\n"),(unsigned int)this); +} + +CeCosSocket::CeCosSocket (int sock /*result of previous call of Listen*/, bool *pbStop): +m_nDefaultTimeout(10*1000), +m_nSock(-1), +m_nClient(0) +{ + VTRACE(_T("Create socket instance %08x\n"),(unsigned int)this); + Accept(sock,pbStop); +} + +CeCosSocket::CeCosSocket (LPCTSTR pszHostPort,Duration dTimeout): +m_nDefaultTimeout(10*1000), +m_nSock(-1), +m_nClient(0) +{ + VTRACE(_T("Create socket instance %08x\n"),(unsigned int)this); + Connect(pszHostPort,dTimeout); +} + +bool CeCosSocket::Accept(int sock /*result of previous call of Listen*/, bool *pbStop) +{ + m_nSock=-1; + while(0==pbStop||!*pbStop){ + struct sockaddr cli_addr; +#ifndef _WIN32 + unsigned +#endif + int clilen=sizeof(struct sockaddr); + m_nSock=::accept(sock, (struct sockaddr *) &cli_addr, &clilen); + SaveError(); + if(-1==m_nSock){ + if(WOULDBLOCK==SocketError()){ + CeCosThreadUtils::Sleep(100); + continue; + } + } else { + memcpy(&m_nClient,cli_addr.sa_data+2,4); + TRACE(_T("Connection accepted from %s - socket %d\n"),(LPCTSTR )ClientName(m_nClient),m_nSock); + SetSocketOptions(); + break; + } + } + return -1!=m_nSock; +} + +int CeCosSocket::Listen(int nTcpPort) +{ + // Create socket + int sock=::socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) { + ERROR(_T("Couldn't create socket\n")); + } else { + VTRACE(_T("Created socket %d listening on port %d\n"),sock,nTcpPort); + // Bind socket to address + struct sockaddr_in serv_addr; + memset(&serv_addr, 0, sizeof serv_addr); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port=htons((short)nTcpPort); + serv_addr.sin_addr.s_addr = INADDR_ANY; + + if (::bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { + TRACE(_T("Couldn't bind socket on port %d\n"),nTcpPort); + CloseSocket(sock); + } else if (-1==::listen(sock, SOMAXCONN)){ + CloseSocket(sock); + TRACE(_T("socket error on listen - port %d\n"),nTcpPort); + } else { +#ifdef _WIN32 + int nTrue=1; + bool rc=(0==::ioctlsocket(sock, FIONBIO, (unsigned long *)&nTrue)); +#else //UNIX + int flags=::fcntl(sock,F_GETFL); + flags|=O_NONBLOCK; + bool rc=(0==::fcntl (sock, F_SETFL, flags)); +#endif + if(!rc){ + TRACE(_T("Failed to set socket options on socket %d\n"),sock); + } + } + } + return sock; +} + +bool CeCosSocket::Connect(LPCTSTR pszHostPort,Duration dTimeout) +{ + dTimeout=TimeoutDuration(dTimeout); + struct sockaddr_in serv_addr; + + VTRACE(_T("Connect: %s timeout=%d\n"),pszHostPort,dTimeout); + + // Get the target host address + String strHost; + int nPort; + CeCosSocket::ParseHostPort(pszHostPort,strHost,nPort); + String strErr; + + char *ip=GetHostByName(strHost).GetCString(); + memset(&serv_addr, 0, sizeof serv_addr); + // Create socket + m_nSock = ::socket(AF_INET, SOCK_STREAM, 0); + if (-1 == m_nSock) { + TRACE(_T("Could not create socket [%s]\n"),pszHostPort); + } else { +#ifdef _WIN32 + SetSocketOptions(); +#endif + VTRACE(_T("Created socket %d connected to %s\n"),m_nSock,pszHostPort); + // Bind socket to address + serv_addr.sin_family = AF_INET; + serv_addr.sin_port=htons((short)nPort); + SaveError(); + serv_addr.sin_addr.s_addr = inet_addr(ip); + + // Connect to server + VTRACE(_T("Connect() : connecting to server\n")); + int cc=::connect(m_nSock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); + SaveError(); + String strMsg; + if(-1==cc){ + if( +#ifdef _WIN32 + WOULDBLOCK==SocketError() +#else // UNIX + EINPROGRESS==SocketError() +#endif + ){ + // Allow dTimeout milliseconds for connect to complete + fd_set set; + FD_ZERO(&set); +#ifdef _WIN32 +#pragma warning( push ) +#pragma warning( disable : 4127 ) // conditional expression is constant +#endif + FD_SET((unsigned)m_nSock, &set); +#ifdef _WIN32 +#pragma warning( pop ) +#endif + struct timeval tv; + tv.tv_sec = dTimeout/1000; + tv.tv_usec = 1000*(dTimeout % 1000); + switch(::select(m_nSock, NULL, &set , NULL, &tv)){ + case 0: + m_nErr=ERR_TIMEOUT; + strMsg.Format(_T("attempt timed out after %d seconds"),dTimeout/1000); + break; + case -1: + SaveError(); + strMsg=SocketErrString(); + break; + default: + cc=0; + } + } else { + strMsg=SocketErrString(); + } + } + + if(-1==cc){ + TRACE(_T("Could not connect to %s - %s\n"),pszHostPort,(LPCTSTR)strMsg); + CloseSocket(m_nSock); + } else { +#ifndef _WIN32 + SetSocketOptions(); +#endif + } + } + delete [] ip; + return -1!=m_nSock; +} + +bool CeCosSocket::sendrecv(bool bSend,const void *pData,unsigned int nLength, + LPCTSTR pszMsg,Duration dTimeout,CeCosSocket::StopFunc pFnStop,void *pParam) +{ + + dTimeout=TimeoutDuration(dTimeout); + + LPCTSTR pszSR=(bSend?_T("sending"):_T("receiving")); + LPTSTR c=(LPTSTR )pData; + Time ft0=Now(); + int nTodo=nLength; + while((nTodo>0) && ((0==pFnStop) || (!pFnStop(pParam)))){ + int s=bSend?::send(m_nSock, (const char *)c, nTodo, 0): ::recv(m_nSock, (char *)c, nTodo, 0); + if(0==s && !bSend){ + m_nErr=ERR_READ_AFTER_CLOSE; + } else { + SaveError(); + } + if(-1==s && WOULDBLOCK==SocketError()){ + Duration d=Duration(Now()-ft0); + if(d>dTimeout){ + TRACE(_T("%d/%d mSec timeout on socket %d %s %s - processed %d/%d bytes\n") , + d,dTimeout,m_nSock,pszSR,pszMsg, + nLength-nTodo,nLength); + m_nErr=ERR_TIMEOUT; + break; + } + CeCosThreadUtils::Sleep(100); + } else if (s>0) { + c+=s; + nTodo-=s; + ft0=Now(); + } else { + TRACE(_T("Error on socket %d %s %s - %s\n") ,m_nSock, pszSR, pszMsg, (LPCTSTR )SocketErrString()); + break; + } + } + return 0==nTodo; +} + +// Graceful socket closedown +CeCosSocket::~CeCosSocket() +{ + Close(); + VTRACE(_T("Delete socket instance %08x\n"),(unsigned int)this); +} + +bool CeCosSocket::CloseSocket(int &sock) +{ + bool rc=false; + if(-1!=sock){ + VTRACE(_T("Closing socket %d\n"),sock); + try{ + shutdown(sock,0);// SD_BOTH +#ifdef _WIN32 + rc=(0==closesocket(sock)); +#else // UNIX + rc=(0==close(sock)); +#endif + } + catch(...) { + TRACE(_T("!!! Exception caught in CeCosSocket::CloseSocket!!!\n")); + } + sock=-1; + } + return rc; +} + +bool CeCosSocket::SetSocketOptions() +{ + bool rc; +#ifdef _WIN32 + int nTrue=1; + rc=(0==::ioctlsocket(m_nSock, FIONBIO, (unsigned long *)&nTrue)); + SaveError(); +#else // UNIX + int flags=::fcntl(m_nSock,F_GETFL); + SaveError(); + flags|=O_NONBLOCK; + rc=(0==::fcntl (m_nSock, F_SETFL, flags)); + SaveError(); +#endif + int bLinger=0; + setsockopt(m_nSock,SOL_SOCKET,SO_LINGER,(const char *)&bLinger, sizeof(bLinger)); + if(!rc){ + TRACE(_T("Failed to set socket options socket %d - %s\n"),m_nSock,(LPCTSTR )SocketErrString()); + } + return rc; +} + +String CeCosSocket::SocketErrString(int nErr) +{ + String str; +#ifdef _WIN32 + switch(nErr){ + case ERR_TIMEOUT: str=_T("Read operation timed out");break; + case ERR_READ_AFTER_CLOSE: str=_T("Read operation after socket closed");break; + + case WSAEACCES: str=_T("Permission denied");break; + case WSAEADDRINUSE: str=_T("Address already in use");break; + case WSAEADDRNOTAVAIL: str=_T("Cannot assign requested address");break; + case WSAEAFNOSUPPORT: str=_T("Address family not supported by protocol family");break; + case WSAEALREADY: str=_T("Operation already in progress");break; + case WSAECONNABORTED: str=_T("Software caused connection abort");break; + case WSAECONNREFUSED: str=_T("Connection refused");break; + case WSAECONNRESET: str=_T("Connection reset by peer");break; + case WSAEDESTADDRREQ: str=_T("Destination address required");break; + case WSAEFAULT: str=_T("Bad address");break; + case WSAEHOSTDOWN: str=_T("Host is down");break; + case WSAEHOSTUNREACH: str=_T("No route to host");break; + case WSAEINPROGRESS: str=_T("Operation now in progress");break; + case WSAEINTR: str=_T("Interrupted function call");break; + case WSAEINVAL: str=_T("Invalid argument");break; + case WSAEISCONN: str=_T("Socket is already connected");break; + case WSAEMFILE: str=_T("Too many open files");break; + case WSAEMSGSIZE: str=_T("Message too long");break; + case WSAENETDOWN: str=_T("Network is down");break; + case WSAENETRESET: str=_T("Network dropped connection on reset");break; + case WSAENETUNREACH: str=_T("Network is unreachable");break; + case WSAENOBUFS: str=_T("No buffer space available");break; + case WSAENOPROTOOPT: str=_T("Bad protocol option");break; + case WSAENOTCONN: str=_T("Socket is not connected");break; + case WSAENOTSOCK: str=_T("Socket operation on non-socket");break; + case WSAEOPNOTSUPP: str=_T("Operation not supported");break; + case WSAEPFNOSUPPORT: str=_T("Protocol family not supported");break; + case WSAEPROCLIM: str=_T("Too many processes");break; + case WSAEPROTONOSUPPORT: str=_T("Protocol not supported");break; + case WSAEPROTOTYPE: str=_T("Protocol wrong type for socket");break; + case WSAESHUTDOWN: str=_T("Cannot send after socket shutdown");break; + case WSAESOCKTNOSUPPORT: str=_T("Socket type not supported");break; + case WSAETIMEDOUT: str=_T("Connection timed out");break; + case WSATYPE_NOT_FOUND: str=_T("Class type not found");break; + case WSAEWOULDBLOCK: str=_T("Resource temporarily unavailable");break; + case WSAHOST_NOT_FOUND: str=_T("Host not found");break; + case WSA_INVALID_HANDLE: str=_T("Specified event object handle is invalid");break; + case WSA_INVALID_PARAMETER: str=_T("One or more parameters are invalid");break; + //case WSAINVALIDPROCTABLE: str=_T("Invalid procedure table from service provider");break; + //case WSAINVALIDPROVIDER: str=_T("Invalid service provider version number");break; + case WSA_IO_INCOMPLETE: str=_T("Overlapped I/O event object not in signaled state");break; + case WSA_IO_PENDING: str=_T("Overlapped operations will complete later");break; + case WSA_NOT_ENOUGH_MEMORY: str=_T("Insufficient memory available");break; + case WSANOTINITIALISED: str=_T("Successful case WSAStartup not yet:performed");break; + case WSANO_DATA: str=_T("Valid name, no data record of requested type");break; + case WSANO_RECOVERY: str=_T("This is a non-recoverable error");break; + //case WSAPROVIDERFAILEDINIT: str=_T("Unable to initialize a service provider");break; + case WSASYSCALLFAILURE: str=_T("System call failure");break; + case WSASYSNOTREADY: str=_T("Network subsystem is unavailable");break; + case WSATRY_AGAIN: str=_T("Non-authoritative host not found");break; + case WSAVERNOTSUPPORTED: str=_T("WINSOCK.DLL version out of range");break; + case WSAEDISCON: str=_T("Graceful shutdown in progress");break; + case WSA_OPERATION_ABORTED: str=_T("Overlapped operation aborted");break; + default: + str.Format(_T("Unknown error %d (0x%08x)"),nErr,nErr); + } +#else // UNIX + switch(nErr){ + case ERR_TIMEOUT: str=_T("Read operation timed out");break; + case ERR_READ_AFTER_CLOSE: str=_T("Read operation after socket closed");break; + default: + str=strerror(errno); + } +#endif + return str; +} + +bool CeCosSocket::sendInteger(int n,LPCTSTR pszMsg,Duration dTimeout) +{ + // This has to support cross-architectural endianness + unsigned char c[sizeof(int)]; + for(unsigned int i=0;i<sizeof(int);i++){ + c[i]=(unsigned char)(n&0xff); + n>>=8; + } + return send (c, sizeof(int),pszMsg,dTimeout); +} + +bool CeCosSocket::recvInteger(int & n,LPCTSTR pszMsg,Duration dTimeout) +{ + // This has to support cross-architectural endianness + unsigned char c[sizeof(int)]; + bool rc=recv (c, sizeof(int),pszMsg,dTimeout); + n=0; + if(rc){ + for(int i=sizeof(int)-1;i>=0;--i){ + n<<=8; + n|=c[i]; + } + } + return rc; +} + +// Socket communications for strings are always non-UNICODE: +bool CeCosSocket::recvString (String &str,LPCTSTR pszMsg,Duration dTimeout) +{ + int nLength; + bool rc=false; + if(recvInteger(nLength,pszMsg,dTimeout)){ + if(0==nLength){ + rc=true; + } else { + Buffer b(1+nLength); + char *c=(char *)b.Data(); + if(c){ + rc=recv(c,nLength,pszMsg,dTimeout); + c[nLength]='\0'; + str=String::CStrToUnicodeStr(c); + } + } + } + return rc; +} + +// Socket communications for strings are always non-UNICODE: +bool CeCosSocket::sendString (const String &str,LPCTSTR pszMsg,Duration dTimeout) +{ + char *psz=str.GetCString(); + int nLength=strlen(psz); + bool rc=sendInteger(nLength,pszMsg,dTimeout) && (0==nLength || send(psz,nLength,pszMsg,dTimeout)); + delete [] psz; + return rc; +} + + +// Give indication of bytes available to be read (but don't read them) +bool CeCosSocket::Peek (unsigned int &nAvail) +{ + char buf[8192]; + int n=::recv(m_nSock, buf, sizeof buf, MSG_PEEK); + nAvail=0; + bool rc=false; + switch(n) { + case -1: + SaveError(); + if(WOULDBLOCK==SocketError()){ + rc=true; // nAvail stays==0 + } else { + ERROR(_T("Peek: err=%d %s\n"),SocketError(),(LPCTSTR)SocketErrString()); + } + break; + case 0: + m_nErr=ERR_READ_AFTER_CLOSE; + break; + default: + rc=true; + nAvail=n; + } + return rc; +} + +// Connect tcp/ip port and serial port together. +// Traffic is passed through pFunc, passed parameter pParam. +// The pFunc function: +// may reallocate pBuf (using malloc/realloc etc...) +// must leave pBuf allocated on exit +// should not close either serial or socket +// should leave writing to its caller +// should return false if it wishes to terminate the connection (after caller has written output) +bool CeCosSocket::ConnectSocketToSerial (CeCosSocket &socket,CeCosSerial &serial,FilterFunc *pSerialToSocketFilterFunc/*=0*/,void *pSerialParam/*=0*/,FilterFunc *pSocketToSerialFilterFunc/*=0*/,void *pSocketParam/*=0*/,bool *pbStop/*=0*/) +{ + serial.ClearError(); + enum {BUFSIZE=8192}; + void *pBuf=malloc(BUFSIZE); + TRACE(_T("ConnectSocketToSerial: connected\n")); + bool rc=true; + try { + /* + { //hack + unsigned int nWritten;//hack + serial.Write(_T("+"),1,nWritten);//hack + }//hack + */ + while(rc && (0==pbStop || !(*pbStop))){ + unsigned int nRead=0; + switch(SSRead (serial,socket,pBuf,BUFSIZE,nRead,pbStop)){ + case SS_SERIAL_READ: + VTRACE(_T("Serial:%d\n"),nRead); + if(pSerialToSocketFilterFunc){ + rc=pSerialToSocketFilterFunc(pBuf,nRead,serial,socket,pSerialParam); + } + if(nRead && !socket.send(pBuf,nRead)){ + TRACE(_T("Failed to write to socket\n")); + rc=false; + } + break; + case SS_SOCKET_READ: + unsigned int nWritten; + VTRACE(_T("Socket:%d\n"),nRead); + if(pSocketToSerialFilterFunc){ + rc=pSocketToSerialFilterFunc(pBuf,nRead,serial,socket,pSocketParam); + } + { + LPTSTR c=(LPTSTR )pBuf; + int nToWrite=nRead; + while(nToWrite>0){ + if(!serial.Write(pBuf,nRead,nWritten)){ + TRACE(_T("Failed to write to serial\n")); + rc=false; + break; + } + nToWrite-=nWritten; + c+=nWritten; + } + } + break; + // Error conditions: + case SS_SERIAL_ERROR: + TRACE(_T("SSRead serial error - %s\n"),(LPCTSTR)serial.ErrString()); + rc=false; + break; + case SS_SOCKET_ERROR: + TRACE(_T("SSRead socket error - %s\n"),(LPCTSTR)socket.SocketErrString()); + rc=false; + break; + case SS_STOPPED: + TRACE(_T("SSRead stopped\n")); + rc=false; + break; + } + } + } + catch (...){ + ERROR(_T("!!! ConnectSocketToSerial exception caught!!!\n")); + free(pBuf); + throw; + } + free(pBuf); + return rc; +} + +// Connect two tcp/ip ports together. +// Traffic is passed through pFunc, passed parameter pParam. +// The pFunc function: +// may reallocate pBuf (using malloc/realloc etc...) +// must leave pBuf allocated on exit +// should not close either serial or socket +// should leave writing to its caller +// should return false if it wishes to terminate the connection (after caller has written output) +bool CeCosSocket::ConnectSocketToSocket (CeCosSocket &o,FilterFunc *pSocketToSocketFilterFunc1,FilterFunc *pSocketToSocketFilterFunc2,void *pParam,bool *pbStop) +{ + enum {BUFSIZE=8192}; + void *pBuf=malloc(BUFSIZE); + TRACE(_T("ConnectSocketToSocket: connected\n")); + bool rc=true; + try { + while(rc && (0==pbStop || !(*pbStop))){ + fd_set set; + FD_ZERO(&set); + FD_SET((unsigned)m_nSock, &set); + FD_SET((unsigned)o.m_nSock, &set); + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + switch(::select(m_nSock,&set,0,0,&tv)){ + case -1: + rc=false; + break; + case 1: + case 2: + { + unsigned int nAvail=0; + if(FD_ISSET((unsigned)m_nSock, &set) && Peek(nAvail) && recv(pBuf,nAvail)){ + //rc=pSocketToSocketFilterFunc1(pBuf,nAvail,socket,this,o); + o.send(pBuf,nAvail); + } + if(FD_ISSET((unsigned)o.m_nSock, &set) && o.Peek(nAvail) && o.recv(pBuf,nAvail)){ + //rc=pSocketToSocketFilterFunc2(pBuf,nAvail,socket,o,this); + send(pBuf,nAvail); + } + } + case 0: + break; + } + } + } + catch (...){ + TRACE(_T("!!! ConnectSocketToSocket exception caught!!!\n")); + rc=false; + } + free(pBuf); + return rc; +} + +bool CeCosSocket::ConnectSocketToSerial ( + int nListenSock,LPCTSTR pszPort, int nBaud, + FilterFunc *pSerialToSocketFilterFunc/*=0*/,void *pSerialParam/*=0*/,FilterFunc *pSocketToSerialFilterFunc/*=0*/,void *pSocketParam/*=0*/, + bool *pbStop) +{ + bool rc=false; + try{ + TRACE(_T("ConnectSocketToSerial : socket %d <--> %s\n"),nListenSock,pszPort); + + CeCosSerial serial; + serial.SetBlockingReads(false); + // Open serial device. + if (!serial.Open(pszPort,nBaud)){ + ERROR(_T("Couldn't open port %s\n"),pszPort); + } else { + // Flush the serial buffer. + serial.Flush(); + + TRACE(_T("ConnectSocketToSerial: waiting for connection...\n")); + CeCosSocket socket; + if(!socket.Accept(nListenSock,pbStop)){ + ERROR(_T("ConnectSocketToSerial - couldn't accept\n")); + } else { + rc=ConnectSocketToSerial (socket,serial,pSerialToSocketFilterFunc,pSerialParam,pSocketToSerialFilterFunc,pSocketParam,pbStop); + } + } + TRACE(_T("ConnectSocketToSerial : done\n")); + } + catch(...){ + TRACE(_T("ConnectSocketToSerial !!!exception handled!!!\n")); + } + return rc; +} + +String CeCosSocket::ClientName(int nClient) +{ + char ip[4]; + memcpy(ip,&nClient,4); + struct hostent *he=::gethostbyaddr((const char *)ip,4,AF_INET); + String str; + if(he){ + str=String::CStrToUnicodeStr(he->h_name); + } else { + str.Format(_T("%u.%u.%u.%u"),ip[0],ip[1],ip[2],ip[3]); + } + return str; +} + +String CeCosSocket::HostPort(LPCTSTR pszHost,int nPort) +{ + String str; + str.Format(_T("%s:%d"),pszHost,nPort); + return str; +} + +// Split the string into host:port parts. Result tells us whether it was successful. +bool CeCosSocket::ParseHostPort (LPCTSTR pszHostPort, String &strHost, int &nPort) +{ + int n=_stscanf(pszHostPort,_T("%[^:]:%d"),strHost.GetBuffer(_tcslen(pszHostPort)),&nPort); + strHost.ReleaseBuffer(); + return 2==n && nPort>0 && nPort<=0xffff; +} + +// Is the string in the form host:port? +bool CeCosSocket::IsLegalHostPort (LPCTSTR pszHostPort) +{ + int nPort=0; + String strHost; + return ParseHostPort(pszHostPort,strHost,nPort); +} + +// Translate a timeout that may be one of the special values DEFAULTTIMEOUT or NOTIMEOUT to a value in milliseconds. +Duration CeCosSocket::TimeoutDuration(Duration dTimeout) +{ + switch(dTimeout){ + case DEFAULTTIMEOUT: + dTimeout=m_nDefaultTimeout; + break; + case NOTIMEOUT: + dTimeout=0x7fffffff; + break; + default: + break; + } + return dTimeout; +} + +String CeCosSocket::SocketErrString() { + return SocketErrString(m_nErr); +} + + +bool CeCosSocket::SameHost(LPCTSTR host1, LPCTSTR host2) +{ + return 0==_tcscmp(host1,host2) || (GetHostByName(host1)==GetHostByName(host2)); +} + +bool CeCosSocket::Init() +{ +#ifdef _WIN32 + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD( 2, 0 ); + WSAStartup( wVersionRequested, &wsaData ); +#endif + return true; +} + +void CeCosSocket::Term() +{ +#ifdef _WIN32 + WSACleanup(); +#endif +} + +LPCTSTR CeCosSocket::MyHostName() +{ + static String str; + if(str.empty()){ + char szMyname[256]; + if(0==gethostname(szMyname,sizeof szMyname)){ + str=String::CStrToUnicodeStr(szMyname); + } + } + return str; +} + +LPCTSTR CeCosSocket::MySimpleHostName() +{ + static String str; + if(str.empty()){ + str=MyHostName(); + // Remove all after a '.' + LPCTSTR c=_tcschr(str,_TCHAR('.')); + if(c){ + str.resize(c-(LPCTSTR)str); + } + } + return str; +} + +const String CeCosSocket::GetHostByName(LPCTSTR pszHost) +{ + typedef std::map<String,String> MapStringToString; + static MapStringToString hostmap; + MapStringToString::iterator it=hostmap.find(pszHost); + if(hostmap.end()==it){ + char *h=0; // avoid erroneous gcc warning message + h=String(pszHost).GetCString(); + char ip[16]; + struct hostent* host_dat; + if (0!=(host_dat=::gethostbyname(h))){ + char *c=inet_ntoa( *( (struct in_addr *)host_dat->h_addr_list[0] ) ); + if(c){ + strcpy(ip,c); + hostmap[pszHost]=String::CStrToUnicodeStr(ip); + } + } + delete [] h; + return String::CStrToUnicodeStr(ip); + } else { + return it->second; + } +} + + \ No newline at end of file
