rllib  1
Public Types | Public Member Functions | Public Attributes | Private Attributes
rlSocket Class Reference

#include <rlsocket.h>

Inheritance diagram for rlSocket:
Inheritance graph
[legend]

List of all members.

Public Types

enum  SocketEnum {
  SOCKET_ERR = -1, SETSOCKOPT_ERR = -2, LISTEN_ERR = -3, ACCEPT_ERR = -4,
  INET_ADDR_ERR = -5, CONNECT_ERR = -6, PORT_ERR = -7
}

Public Member Functions

 rlSocket (const char *adr, int port, int active)
 rlSocket (int socket)
virtual ~rlSocket ()
void setAdr (const char *adr)
void setPort (int port)
int getPort ()
void setActive (int active)
int read (void *buf, int len, int timeout=0)
int readStr (char *buf, int len, int timeout=0)
int write (const void *buf, int len)
int printf (const char *format,...)
int connect ()
int disconnect ()
int select (int timeout=0)
int isConnected ()
int setIPVersion (int version)
int getIPVersion ()
int sendProcessViewBrowserButtonEvent (int id)

Public Attributes

int s
unsigned char sockaddr [16+48]

Private Attributes

char adr [132]
int port
int active
int os
int first
int prefer_ipv6
int rl_ipversion

Detailed Description

class for encapsulating TCP/IP socket calls

Definition at line 31 of file rlsocket.h.


Member Enumeration Documentation

Enumerator:
SOCKET_ERR 
SETSOCKOPT_ERR 
LISTEN_ERR 
ACCEPT_ERR 
INET_ADDR_ERR 
CONNECT_ERR 
PORT_ERR 

Definition at line 35 of file rlsocket.h.

  {
    SOCKET_ERR     = -1,
    SETSOCKOPT_ERR = -2,
    LISTEN_ERR     = -3,
    ACCEPT_ERR     = -4,
    INET_ADDR_ERR  = -5,
    CONNECT_ERR    = -6,
    PORT_ERR       = -7
  };

Constructor & Destructor Documentation

rlSocket::rlSocket ( const char *  adr,
int  port,
int  active 
)
      construct a new rlSocket but do not connect
      adr  = hostname | dotted address
      port = port number of socket
      active = 0 wait for connections with accept()
      active = 1 open the connection with connect()
      active = 2 neither accept() nor connect()
  

Definition at line 94 of file rlsocket.cpp.

{
  rlwsa(); // init sockets on windows
  setAdr(a);
  port = p;
  active = act;
  s = -1;
  os = -1;
  first = 1;
  rl_ipversion = 4;
  memset(sockaddr,0,sizeof(sockaddr));
}
rlSocket::rlSocket ( int  socket)
      construct a new rlSocket
      use connection on open socket
  

Definition at line 107 of file rlsocket.cpp.

{
  adr[0] = '\0';
  port   = -1;
  active = 0;
  s      = socket;
  os     = -1;
  first  = 0;
  rl_ipversion = 4;
  memset(sockaddr,0,sizeof(sockaddr));
}
rlSocket::~rlSocket ( ) [virtual]
      destruct the socket
      attention if active = 0 the socket will still be bound to port
  

Definition at line 119 of file rlsocket.cpp.

{
  disconnect();
  if(os != -1 && active == 0)
  {
#ifdef RLWIN32
    closesocket(os);
#else
    close(os);
#endif
  }
}

Member Function Documentation

int rlSocket::connect ( )
      connect
      return >= 0 socket used
      return < 0  error (see: enum SocketEnum)
  

Definition at line 245 of file rlsocket.cpp.

{
  int option;
  int ret;
#ifdef __VMS
  size_t    socklen = sizeof(struct sockaddr);
#else
  socklen_t socklen = sizeof(struct sockaddr);
#endif
  struct sockaddr_in     localAddr;
  struct sockaddr_in     remoteAddr;
  struct hostent        *host;
  struct in_addr         RemoteIpAddress;
#ifdef AF_INET6_IS_AVAILABLE
  struct addrinfo        hints0, hints1;
  struct addrinfo       *res, *ressave;
  int n;
  char portstr[32];
#endif

  if(port <= 0)       return PORT_ERR;
  if(port >= 256*256) return PORT_ERR;
  if(active == 0)
  { // accept calls
    s = -1;
    if(rl_ipversion == 4)
    {
      if(first == 1)
      {
        // create a socket
        os = socket(AF_INET,SOCK_STREAM,0);
        if(os == -1) return SOCKET_ERR;
        // set socket options 
#ifdef __VMS
        option = 1;
        if(setsockopt(os,SOL_SOCKET,SO_KEEPALIVE,&option,sizeof(option)) < 0)
        {
          return SETSOCKOPT_ERR;
        }
#endif
        option = 1;
#ifdef RLWIN32
        setsockopt(os,SOL_SOCKET,SO_REUSEADDR,(const char *) &option,sizeof(option));
#else
        setsockopt(os,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
#endif
        // Bind our server to the agreed upon port number.
        memset(&localAddr,0,sizeof(localAddr));
        localAddr.sin_port = htons((short) port);
        localAddr.sin_family = AF_INET;
bind:
        ret = bind(os, (struct sockaddr *) &localAddr, sizeof(localAddr));
        if(ret == -1)
        {
          rlwthread_sleep(1000);
          goto bind;
        }
        // Prepare to accept client connections.  Allow up to 5 pending 
        // connections.                                            
        ret = listen(os, 5);
        if(ret == -1) return LISTEN_ERR;
      }
      first = 0;

      // accept connections
      s = accept(os, (struct sockaddr *) &sockaddr[0], &socklen);
      if(s == -1) return ACCEPT_ERR;
    }
    else if(rl_ipversion == 6)
    {
#ifdef AF_INET6_IS_AVAILABLE
      if(first == 1)
      {
        memset(&hints0,0,sizeof(hints0));
        hints0.ai_flags = AI_PASSIVE;
        //hints0.ai_family = AF_UNSPEC;
        hints0.ai_family = AF_INET6;
        hints0.ai_socktype = SOCK_STREAM;
        sprintf(portstr,"%d",port);
        //::printf("server getaddrinfo(%s,%s)\n", adr, portstr);
        n = getaddrinfo(adr, portstr, &hints0, &res);
        if(n != 0)
        {
#ifndef RLWIN32
          ::printf("rlSocket:tcp_listen error for %s port=%s : %s\n", adr, portstr, gai_strerror(n));
#endif
          return -1;
        }
        //::printf("done\n");
        ressave = res;
bindv6:
        do
        {
          os = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
          if(os < 0)                                            continue; // error, try next one
#ifdef __VMS
          option = 1;
          if(setsockopt(os,SOL_SOCKET,SO_KEEPALIVE,&option,sizeof(option)) < 0)
          {
            return SETSOCKOPT_ERR;
          }
#endif
          option = 1;
#ifdef RLWIN32
          setsockopt(os,SOL_SOCKET,SO_REUSEADDR,(const char *) &option,sizeof(option));
#else
          setsockopt(os,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
#endif
          if(bind(os, res->ai_addr, res->ai_addrlen) == 0)      break;    // success
          s = os;
          disconnect();                                                   // bind error, close and try next one
        }
        while((res = res->ai_next) != NULL);
        if(res == NULL)                                                   // errno from final socket() or bind()
        {
          ::printf("warning: could not bind to port=%d\n", port);
          rlwthread_sleep(1000);
          goto bindv6;
        }
        // Prepare to accept client connections.  Allow up to 5 pending 
        // connections
        ret = listen(os, 5);
        freeaddrinfo(ressave);
        if(ret == -1) return LISTEN_ERR;
      }
      first = 0;
      // accept connections
      s = accept(os, (struct sockaddr *) &sockaddr[0], &socklen);
      if(s == -1) return ACCEPT_ERR;
#else
      ::printf("rlSocket:ERROR IPV6 not available on this platform\n");
#endif
    }
    else
    {
      ::printf("rlSocket:ERROR: rl_ipversion=%d not known\n", rl_ipversion);
    }
  } // end active == 0 
  else if(active == 1)
  {
    disconnect();
    //::printf("debug: adr=%s port=%d\n",adr,port);
    s = -1;
    if(rl_ipversion == 4)
    {
      os = socket(AF_INET,SOCK_STREAM,0);
      if(os == -1) return SOCKET_ERR;
      s = os;

      //::printf("debug: gethostbyname\n");
      // fill destblk structure 
      host = gethostbyname(adr);
      if(host == NULL)
      {
        // See if the host is specified in "dot address" form
        RemoteIpAddress.s_addr = inet_addr(adr);
        if(RemoteIpAddress.s_addr == INADDR_NONE)
        {
          s = -1;
          return INET_ADDR_ERR; // -1
        }
      }
      else
      {
        memcpy(&RemoteIpAddress,host->h_addr,host->h_length);
      }

      memset(&remoteAddr,0,sizeof(remoteAddr));
      remoteAddr.sin_family = AF_INET;
      remoteAddr.sin_port = htons((short) port);
      remoteAddr.sin_addr = RemoteIpAddress;

      //::printf("debug: connect\n");
      ret = ::connect(s, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr));
      //::printf("debug: connect ret=%d\n",ret);
      if(ret == -1) 
      {
        s = -1;
        return CONNECT_ERR;
      }
    }
    else if(rl_ipversion == 6)
    {
#ifdef AF_INET6_IS_AVAILABLE
      sprintf(portstr,"%d",port);
      memset(&hints1, 0, sizeof(hints1));
      hints1.ai_family = AF_UNSPEC;
      hints1.ai_socktype = SOCK_STREAM;
      n = getaddrinfo(adr, portstr, &hints1, &res);
      if(n != 0)
      {
#ifndef RLWIN32
        ::printf("rlSocket:tcp_connect error for %s port=%s : %s\n", adr, portstr, gai_strerror(n));
#endif
        return -1;
      }
      ressave = res;
      do
      {
        s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if(s < 0)                                            continue; // ignore this one
        if(::connect(s, res->ai_addr, res->ai_addrlen) == 0) break;    // success
        disconnect();                                                  // ignore this one
      }
      while((res = res->ai_next) != NULL);
      if(res == NULL) ::printf("rlSocket:tcp_connect error for %s port=%s\n", adr, portstr);
      freeaddrinfo(ressave);
#else
      ::printf("rlSocket:ERROR IPV6 not available on this platform\n");
#endif
    }
    else
    {
      ::printf("rlSocket:ERROR: rl_ipversion=%d not known\n", rl_ipversion);
    }
  }
  return s;
}
int rlSocket::disconnect ( )
      disconnect
      return = 0
  

Definition at line 464 of file rlsocket.cpp.

{
  if(s != -1)
  {
#ifdef RLWIN32
    closesocket(s);
#else
    close(s);
#endif
  }
  s = -1;
  return 0;
}
int rlSocket::getIPVersion ( )
      return == 4 IPV4
      return == 6 IPV6
  

Definition at line 530 of file rlsocket.cpp.

{
  return rl_ipversion;
}
int rlSocket::getPort ( )
      get port
  

Definition at line 145 of file rlsocket.cpp.

{
  return port;
}
int rlSocket::isConnected ( )
      return == 1 socket is connected
      return == 0 socket is not connected
  

Definition at line 478 of file rlsocket.cpp.

{
  if(s == -1) return 0;
  return 1;
}
int rlSocket::printf ( const char *  format,
  ... 
)
      similar to printf
      return > 0 length of data written
      return < 0 error
  

Definition at line 505 of file rlsocket.cpp.

{
  int ret;
  char message[rl_PRINTF_LENGTH]; // should be big enough

  va_list ap;
  va_start(ap,format);
  ret = rlvsnprintf(message, rl_PRINTF_LENGTH - 1, format, ap);
  va_end(ap);
  if(ret < 0) return ret;
  return write(message,strlen(message));
}
int rlSocket::read ( void *  buf,
int  len,
int  timeout = 0 
)
      read a block of data
      len = length of data to be read
      timeout = 0 wait indefinite
      timeout > 0 wait at maximum for timeout milliseconds
      return > 0 length of message read
      return == 0 timeout
      return < 0 error
  

Definition at line 155 of file rlsocket.cpp.

{
  int  i,ret;
  char *cbuf;

  if(s == -1) return -1;
  if(select(timeout) == 0) return 0; // timeout

  cbuf = (char *) buf;
  i = 0;
  while(i < len)
  {
    ret = recv(s,&cbuf[i],len-i,0);
    if(ret <= 0)
    {
      disconnect();
      return -1;
    }
    i += ret;
    if(i < len)
    {
      if(select(timeout) == 0) return 0; // timeout
    }
  }

  return i;
}
int rlSocket::readStr ( char *  buf,
int  len,
int  timeout = 0 
)
      read a '
' terminated string len = max length of data to be read timeout = 0 wait indefinite timeout > 0 wait at maximum for timeout milliseconds return > 0 length of message read return == 0 timeout return < 0 error

Definition at line 183 of file rlsocket.cpp.

{
  int ret,i;

  if(s == -1) return -1;
  if(select(timeout) == 0) return 0; // timeout

  i = 0;
  while(1)
  {
#ifdef RLWIN32
tryagain:
#endif
    ret = recv(s,&buf[i],1,0);
    if(ret <= 0)
    {
#ifdef RLWIN32
      if(WSAEWOULDBLOCK == WSAGetLastError()) goto tryagain;
#endif
      disconnect();
      buf[i] = '\0';
      return -1;
    }
    if(buf[i] == '\n')
    {
      buf[i+1] = '\0';
      return i+1;
    }
    if(i >= len-1)
    {
      buf[i+1] = '\0';
      return i+1;
    }
    i++;
  }
}
int rlSocket::select ( int  timeout = 0)
      wait for data arriving on socket
      timeout > 0 timeout in milliseconds
      timeout == 0 indefinite timeout
      return = 1 DATA_AVAILABLE
      return = 0 TIMEOUT
  

Definition at line 484 of file rlsocket.cpp.

{
  struct timeval timout;
  fd_set wset,rset,eset;
  int    ret,maxfdp1;

  if(timeout == 0) return 1;
  /* setup sockets to read */
  maxfdp1 = s+1;
  FD_ZERO(&rset);
  FD_SET (s,&rset);
  FD_ZERO(&wset);
  FD_ZERO(&eset);
  timout.tv_sec  =  timeout / 1000;
  timout.tv_usec = (timeout % 1000) * 1000;

  ret = ::select(maxfdp1,&rset,&wset,&eset,&timout);
  if(ret == 0) return 0; /* timeout */
  return 1;
}
int rlSocket::sendProcessViewBrowserButtonEvent ( int  id)
      This method is intendet for data providers implemented as ProcessViewServer
  

Definition at line 518 of file rlsocket.cpp.

{
  return printf("QPushButton(%d)\n",id);
}
void rlSocket::setActive ( int  active)
      set port active = 0|1
  

Definition at line 150 of file rlsocket.cpp.

{
  active = act;
}
void rlSocket::setAdr ( const char *  adr)
      set adr to a different adr than in the constructor
  

Definition at line 132 of file rlsocket.cpp.

{
  adr[0] = '\0';
  if(a == NULL) return;
  if((strlen(a)+1) > sizeof(adr)) return;
  strcpy(adr,a);
}
int rlSocket::setIPVersion ( int  version)
      default: prefer IPV4
      if(ip==6) prefer IPV6
      else      prefer IPV4
  

Definition at line 523 of file rlsocket.cpp.

{
  if(version == 6) rl_ipversion = 6;
  else             rl_ipversion = 4;
  return rl_ipversion;
}
void rlSocket::setPort ( int  port)
      set port to a different port than in the constructor
  

Definition at line 140 of file rlsocket.cpp.

{
  port = p;
}
int rlSocket::write ( const void *  buf,
int  len 
)
      write a block of data
      return > 0 length of data written
      return < 0 error
  

Definition at line 220 of file rlsocket.cpp.

{
  int ret,bytes_left,first_byte;
  const char *cbuf;

  if(s == -1) return -1;
  cbuf = (char *) buf;
  bytes_left = len;
  first_byte = 0;

  while(bytes_left > 0)
  {
    ret = send(s,&cbuf[first_byte],bytes_left,MSG_NOSIGNAL);
    if(ret <= 0)
    {
      disconnect();
      return -1;
    }
    bytes_left -= ret;
    first_byte += ret;
  }

  return first_byte;
}

Member Data Documentation

int rlSocket::active [private]

Definition at line 216 of file rlsocket.h.

char rlSocket::adr[132] [private]

Definition at line 214 of file rlsocket.h.

int rlSocket::first [private]

Definition at line 218 of file rlsocket.h.

int rlSocket::os [private]

Definition at line 217 of file rlsocket.h.

int rlSocket::port [private]

Definition at line 215 of file rlsocket.h.

int rlSocket::prefer_ipv6 [private]

Definition at line 219 of file rlsocket.h.

int rlSocket::rl_ipversion [private]

Definition at line 220 of file rlsocket.h.

      this is the real socket used for communication
      s >= 0  connected
      s == -1 disconnected
  

Definition at line 176 of file rlsocket.h.

unsigned char rlSocket::sockaddr[16+48]
      this array can be casted to (struct sockaddr *) &sockaddr[0];
      in case of active==0 it will store sockaddr of the last client
      (48 bytes spare)
      struct sockaddr {
        unsigned short    sa_family;    // address family, AF_xxx
        char              sa_data[14];  // 14 bytes of protocol address
      };
IPv4 AF_INET sockets:
      struct sockaddr_in {
        short            sin_family;   // e.g. AF_INET, AF_INET6
        unsigned short   sin_port;     // e.g. htons(3490)
        struct in_addr   sin_addr;     // see struct in_addr, below
        char             sin_zero[8];  // zero this if you want to
      };
      struct in_addr {
        unsigned long s_addr;          // load with inet_pton()
      };
IPv6 AF_INET6 sockets:
      struct sockaddr_in6 {
        u_int16_t       sin6_family;   // address family, AF_INET6
        u_int16_t       sin6_port;     // port number, Network Byte Order
        u_int32_t       sin6_flowinfo; // IPv6 flow information
        struct in6_addr sin6_addr;     // IPv6 address
        u_int32_t       sin6_scope_id; // Scope ID
      };
      struct in6_addr {
          unsigned char   s6_addr[16];   // load with inet_pton()
      };
  

Definition at line 211 of file rlsocket.h.


The documentation for this class was generated from the following files: