topical media & game development 
  
 
 
 
 
  
    
    
  
 lib-of-vs-addons-ofxNetwork-src-ofxTCPManager.cpp / cpp
  include <ofxTCPManager.h>
  include <stdio.h>
  
  //--------------------------------------------------------------------------------
  bool ofxTCPManager::m_bWinsockInit= false;
  
  //--------------------------------------------------------------------------------
  ofxTCPManager::ofxTCPManager()
  {
    // was winsock initialized?
            #ifdef TARGET_WIN32
                  if (!m_bWinsockInit) {
                          unsigned short vr;
                          WSADATA        wsaData;
                          vr = MAKEWORD(2,        2);
                          WSAStartup(vr, &wsaData);
                          m_bWinsockInit=        true;
                  }
          #else
                  //this disables the other apps from shutting down if the client
                  //or server disconnects.
                  signal(SIGPIPE,SIG_IGN);
                  signal(EPIPE,SIG_IGN);
          #endif
  
    nonBlocking = false;
    m_hSocket= INVALID_SOCKET;
    m_dwTimeoutSend= OF_TCP_DEFAULT_TIMEOUT;
    m_dwTimeoutReceive= OF_TCP_DEFAULT_TIMEOUT;
    m_dwTimeoutAccept= OF_TCP_DEFAULT_TIMEOUT;
    m_iListenPort= -1;
  };
  
  //--------------------------------------------------------------------------------
   Closes an open socket.
   NOTE: A closed socket cannot be reused again without a call to "Create()".
  bool ofxTCPManager::Close()
  {
    if (m_hSocket == INVALID_SOCKET) return(false);
  
          #ifdef TARGET_WIN32
                  if(closesocket(m_hSocket) == SOCKET_ERROR)
          #else
                  if(close(m_hSocket) == SOCKET_ERROR)
          #endif
          {
                  return(false);
          }
  
          m_hSocket= INVALID_SOCKET;
  
          #ifdef TARGET_WIN32
                  //This was commented out in the original
                  //WSACleanup();
          #endif
          return(true);
  }
  
  void ofxTCPManager::CleanUp() {
          #ifdef TARGET_WIN32
                  WSACleanup();
          #endif
    m_bWinsockInit = false;
  }
  
  //--------------------------------------------------------------------------------
  bool ofxTCPManager::Create()
  {
    if (m_hSocket != INVALID_SOCKET) return(false);
  
    m_hSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_IP);
  
    return(m_hSocket != INVALID_SOCKET);
  }
  
  //--------------------------------------------------------------------------------
  bool ofxTCPManager::Listen(int iMaxConnections)
  {
    if (m_hSocket == INVALID_SOCKET) return(false);
    m_iMaxConnections = iMaxConnections;
          return(listen(m_hSocket, iMaxConnections) != SOCKET_ERROR);
  }
  
  bool ofxTCPManager::Bind(unsigned short usPort)
  {
          struct sockaddr_in local;
          memset(&local, 0, sizeof(sockaddr_in));
  
          local.sin_family = AF_INET;
          local.sin_addr.s_addr = INADDR_ANY;
          //Port MUST be in Network Byte Order
          local.sin_port = htons(usPort);
  
          if (bind(m_hSocket,(struct sockaddr*)&local,sizeof(local)))
                  return false;
          return true;
  }
  
  //--------------------------------------------------------------------------------
  bool ofxTCPManager::Accept(ofxTCPManager& sConnect)
  {
    sockaddr_in addr;
  
    #ifndef TARGET_WIN32
          socklen_t iSize;
    #else
          int iSize;
    #endif
  
    if (m_hSocket == INVALID_SOCKET) return(false);
  
    if (m_dwTimeoutAccept != NO_TIMEOUT) {
      fd_set fd= {1, m_hSocket};
            timeval tv= {m_dwTimeoutAccept, 0};
            if(select(0, &fd, NULL, NULL, &tv) == 0) {
                    return(false);
            }
    }
  
    iSize= sizeof(sockaddr_in);
    sConnect.m_hSocket= accept(m_hSocket, (sockaddr*)&addr, &iSize);
    return(sConnect.m_hSocket != INVALID_SOCKET);
  }
  
  //--------------------------------------------------------------------------------
  bool ofxTCPManager::Connect(char *pAddrStr, unsigned short usPort)
  {
    sockaddr_in addr_in= {0};
    struct hostent *he;
  
    if (m_hSocket == INVALID_SOCKET) return(false);
  
    if ((he = gethostbyname(pAddrStr)) == NULL)
      return(false);
  
          addr_in.sin_family= AF_INET; // host byte order
          addr_in.sin_port  = htons(usPort); // short, network byte order
          addr_in.sin_addr  = *((struct in_addr *)he->h_addr);
  
          return(connect(m_hSocket, (sockaddr *)&addr_in, sizeof(sockaddr)) != SOCKET_ERROR);
  }
  
  //--------------------------------------------------------------------------------
  Theo added - Choose to set nonBLocking - default mode is to block
  bool ofxTCPManager::SetNonBlocking(bool useNonBlocking)
  {
          nonBlocking                = useNonBlocking;
  
          #ifdef TARGET_WIN32
                  unsigned long arg = nonBlocking;
                  int retVal = ioctlsocket(m_hSocket,FIONBIO,&arg);
          #else
                  int arg = nonBlocking;
                  int retVal = ioctl(m_hSocket,FIONBIO,&arg);
          #endif
  
          return (retVal >= 0);
  }
  
  //--------------------------------------------------------------------------------
  int ofxTCPManager::Write(const char* pBuff, const int iSize)
  {
          int iBytesSent= 0;
          int iBytesTemp;
          const char* pTemp= pBuff;
  
    do {
            iBytesTemp= Send(pTemp, iSize - iBytesSent);
      // error occured?
      if (iBytesTemp == SOCKET_ERROR) return(SOCKET_ERROR);
      if (iBytesTemp == SOCKET_TIMEOUT) return(SOCKET_TIMEOUT);
  
                  iBytesSent+= iBytesTemp;
                  pTemp+= iBytesTemp;
          } while(iBytesSent < iSize);
  
    return(iBytesSent);
  }
  
  //--------------------------------------------------------------------------------
  //Theo added - alternative to GetTickCount for windows
  //This version returns the milliseconds since the unix epoch
  //Should be good enough for what it is being used for here
  //(mainly time comparision)
  ifndef TARGET_WIN32
  unsigned long GetTickCount(){
    timeb bsdTime;
    ftime(&bsdTime);
  
     unsigned long msSinceUnix = (bsdTime.time*1000) + bsdTime.millitm;
     return msSinceUnix;
  }
  endif
  
  //--------------------------------------------------------------------------------
   Return values:
   SOCKET_TIMEOUT indicates timeout
   SOCKET_ERROR in case of a problem.
  int ofxTCPManager::Send(const char* pBuff, const int iSize)
  {
    if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  
    if (m_dwTimeoutSend        != NO_TIMEOUT)
          {
                  fd_set fd;
                  FD_ZERO(&fd);
                  FD_SET(m_hSocket, &fd);
                  timeval        tv=        {m_dwTimeoutSend, 0};
                  if(select(m_hSocket+1,NULL,&fd,NULL,&tv)== 0)
                  {
                          return(SOCKET_TIMEOUT);
                  }
          }
          return(send(m_hSocket, pBuff, iSize, 0));
  }
  
  //--------------------------------------------------------------------------------
   Return values:
   SOCKET_TIMEOUT indicates timeout
   SOCKET_ERROR in case of a problem.
  int ofxTCPManager::SendAll(const char* pBuff, const int iSize)
  {
    if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  
          unsigned long timestamp= GetTickCount();
  
          if (m_dwTimeoutSend        != NO_TIMEOUT)
          {
                  fd_set fd;
                  FD_ZERO(&fd);
                  FD_SET(m_hSocket, &fd);
                  timeval        tv=        {m_dwTimeoutSend, 0};
                  if(select(m_hSocket+1,NULL,&fd,NULL,&tv)== 0)
                  {
                          return(SOCKET_TIMEOUT);
                  }
          }
  
          int total= 0;
          int bytesleft = iSize;
          int ret=-1;
  
          while (total < iSize) {
                  ret = send(m_hSocket, pBuff + total, bytesleft, 0);
                  if (ret == -1) { break; }
                  total += ret;
                  bytesleft -=ret;
                  if (GetTickCount() - timestamp > m_dwTimeoutSend * 1000) return SOCKET_TIMEOUT;
          }
  
          return ret==-1 && bytesleft == iSize?SOCKET_ERROR:total;
  }
  
  //--------------------------------------------------------------------------------
   Return values:
   SOCKET_TIMEOUT indicates timeout
   SOCKET_ERROR in case of a problem.
  
  int ofxTCPManager::Receive(char* pBuff, const int iSize)
  {
    if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  
    if (m_dwTimeoutSend        != NO_TIMEOUT)
            {
                    fd_set fd;
                    FD_ZERO(&fd);
                    FD_SET(m_hSocket, &fd);
                    timeval        tv=        {m_dwTimeoutSend, 0};
                    if(select(m_hSocket+1,&fd,NULL,NULL,&tv)== 0)
                    {
                            return(SOCKET_TIMEOUT);
                    }
            }
          return(recv(m_hSocket, pBuff, iSize, 0));
  }
  
  //--------------------------------------------------------------------------------
   Return values:
   SOCKET_TIMEOUT indicates timeout
   SOCKET_ERROR in case of a problem.
  int ofxTCPManager::ReceiveAll(char* pBuff, const int iSize)
  {
          if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  
          unsigned long timestamp= GetTickCount();
  
          if (m_dwTimeoutSend        != NO_TIMEOUT)
          {
                  fd_set fd;
                  FD_ZERO(&fd);
                  FD_SET(m_hSocket, &fd);
                  timeval        tv=        {m_dwTimeoutSend, 0};
                  if(select(m_hSocket+1,&fd,NULL,NULL,&tv)== 0)
                  {
                          return(SOCKET_TIMEOUT);
                  }
          }
          int totalBytes=0;
  
          unsigned long stamp = GetTickCount();
  
          do {
                  int ret= recv(m_hSocket, pBuff+totalBytes, iSize-totalBytes, 0);
                  if (ret==0 && totalBytes != iSize) return SOCKET_ERROR;
                  if (ret < 0) return SOCKET_ERROR;
                  if (GetTickCount() - timestamp > m_dwTimeoutReceive * 1000) return SOCKET_TIMEOUT;
                  totalBytes += ret;
                  #ifndef TARGET_WIN32
                          usleep(20000); //should be 20ms
                  #else
                          Sleep(20);
                  #endif
                  if (GetTickCount() - stamp > 10000)
                          return SOCKET_TIMEOUT;
          }while(totalBytes < iSize);
  
  /*
          if (totalBytes > 0)
          {
                  char out[400];
                  sprintf(out, "\%d bytes received:", totalBytes);
                  int len = strlen(out);
                  memcpy((char*)out + len, pBuff, totalBytes);
                  len += totalBytes;
                  out[len] = 0;
                  OutputDebugString(out);
          }
  */
          return totalBytes;
  }
  
  //--------------------------------------------------------------------------------
  bool ofxTCPManager::GetRemoteAddr(LPINETADDR pInetAddr)
  {
    if (m_hSocket == INVALID_SOCKET) return(false);
  
          #ifndef TARGET_WIN32
                  socklen_t iSize;
          #else
                  int iSize;
          #endif
  
          iSize= sizeof(sockaddr);
          return(getpeername(m_hSocket, (sockaddr *)pInetAddr, &iSize) != SOCKET_ERROR);
  }
  
  //--------------------------------------------------------------------------------
  bool ofxTCPManager::GetInetAddr(LPINETADDR pInetAddr)
  {
    if (m_hSocket == INVALID_SOCKET) return(false);
  
          #ifndef TARGET_WIN32
                  socklen_t iSize;
          #else
                  int iSize;
          #endif
  
          iSize= sizeof(sockaddr);
          return(getsockname(m_hSocket, (sockaddr *)pInetAddr, &iSize) != SOCKET_ERROR);
  }
  
  void ofxTCPManager::SetTimeoutSend(int timeoutInSeconds) {
          m_dwTimeoutSend= timeoutInSeconds;
  }
  void ofxTCPManager::SetTimeoutReceive(int timeoutInSeconds) {
          m_dwTimeoutReceive= timeoutInSeconds;
  }
  void ofxTCPManager::SetTimeoutAccept(int timeoutInSeconds) {
          m_dwTimeoutAccept= timeoutInSeconds;
  }
  int ofxTCPManager::GetTimeoutSend() {
          return m_dwTimeoutSend;
  }
  int ofxTCPManager::GetTimeoutReceive() {
          return m_dwTimeoutReceive;
  }
  int ofxTCPManager::GetTimeoutAccept() {
          return m_dwTimeoutAccept;
  }
  
  int ofxTCPManager::GetReceiveBufferSize() {
          if (m_hSocket == INVALID_SOCKET) return(false);
  
          #ifndef TARGET_WIN32
                  socklen_t size;
          #else
                  int size;
          #endif
  
          int sizeBuffer=0;
          size = sizeof(int);
          getsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&sizeBuffer, &size);
  
          return sizeBuffer;
  }
  
  bool ofxTCPManager::SetReceiveBufferSize(int sizeInByte) {
          if (m_hSocket == INVALID_SOCKET) return(false);
  
          if ( setsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&sizeInByte, sizeof(sizeInByte)) == 0)
                  return true;
          else
                  return false;
  }
  
  int ofxTCPManager::GetSendBufferSize() {
          if (m_hSocket == INVALID_SOCKET) return(false);
  
          #ifndef TARGET_WIN32
                  socklen_t size;
          #else
                  int size;
          #endif
  
          int sizeBuffer=0;
          size = sizeof(int);
          getsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sizeBuffer, &size);
  
          return sizeBuffer;
  }
  
  bool ofxTCPManager::SetSendBufferSize(int sizeInByte) {
          if (m_hSocket == INVALID_SOCKET) return(false);
  
          if ( setsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sizeInByte, sizeof(sizeInByte)) == 0)
                  return true;
          else
                  return false;
  }
  
  int ofxTCPManager::GetMaxConnections() {
    return m_iMaxConnections;
  }
  
  bool ofxTCPManager::CheckHost(const char *pAddrStr) {
    hostent * hostEntry;
    in_addr iaHost;
    iaHost.s_addr = inet_addr(pAddrStr);
    hostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET);
    return ((!hostEntry) ? false : true);
  }
  
  
  
  
(C) Æliens 
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher. 
In case of other copyright issues, contact the author.