|
rllib
1
|
#include <rlsocket.h>

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 |
class for encapsulating TCP/IP socket calls
Definition at line 31 of file rlsocket.h.
| enum rlSocket::SocketEnum |
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
};
| 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.
| rlSocket::rlSocket | ( | int | socket | ) |
| 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
}
}
| 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 | ( | ) |
| int rlSocket::getIPVersion | ( | ) |
return == 4 IPV4
return == 6 IPV6
Definition at line 530 of file rlsocket.cpp.
{
return rl_ipversion;
}
| int rlSocket::getPort | ( | ) |
| 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 | ) |
| void rlSocket::setAdr | ( | const char * | adr | ) |
set adr to a different adr than in the constructor
Definition at line 132 of file rlsocket.cpp.
| 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;
}
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.
| int rlSocket::s |
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.
1.7.5.1