#include <signal.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include "portability.h"#include "proxylib.h"#include "comm_basics.h"#include "utility.h"
Go to the source code of this file.
Functions | |
| ssize_t | gs_twrite (SOCKET fildes, const void *buf, size_t nbyte) |
| ssize_t | gs_writen (SOCKET fd, const void *vptr, size_t n) |
| int | gs_tread (SOCKET d, char *b, int n) |
| ssize_t | gs_readline (int fd, void *vptr, size_t maxlen) |
| SOCKET | gs_establish_socket (in_port_t *port, int reuse) |
| SOCKET | gs_bind_to_first_available_port (in_port_t initport, in_port_t *found_port) |
| int | gs_listen_on_socket (SOCKET sock) |
| int | gs_accept_connection (SOCKET listening_socket) |
| int | gs_close_socket (SOCKET sock) |
| SOCKET | gs_connect_to_host (char *ID, ipaddr_t ipaddr, int port, ipaddr_t proxyIP, int proxyPort) |
| SOCKET | gs_connect_direct (char *host, int port) |
The functions in this file implement GridSolve basic communication infrastructure. Users wanting to use their own communication and authentication mechanism will have to rewrite these functions using their mechanisms. Users behind NATs are advised to use this communication library.
Definition in file comm_basics.c.
| int gs_accept_connection | ( | SOCKET | listening_socket | ) |
Wait for a connection on this socket.
| lisetening_socket | -- the socket to wait for connections on |
Definition at line 292 of file comm_basics.c.
{
struct sockaddr_in addr; /* INET socket address */
socklen_t addrlen; /* address length */
int sock;
addrlen = sizeof(addr);
sock = proxy_accept(listening_socket, (struct sockaddr *) &addr, &addrlen);
while (sock == INVALID_SOCKET && errno_socket() == EINTR) {
sock = proxy_accept(listening_socket, (struct sockaddr *) &addr, &addrlen);
}
return sock;
}


| SOCKET gs_bind_to_first_available_port | ( | in_port_t | initport, | |
| in_port_t * | found_port | |||
| ) |
Bind to the first available port greater than or equal to the parameter 'initport'. After GS_NUM_PORTS_TO_TRY attempts it fails.
| initport | -- the requested port number | |
| found_port | -- on return, set to the actual port number bound |
Definition at line 228 of file comm_basics.c.
{
in_port_t port;
in_port_t tryport;
SOCKET sock;
port = initport;
tryport = port;
/*
* It's important that we don't reuse the addresses here, as we will
* just attempt the next port if the current one fails - no problem...
* This call is typically used where the exact port doesn't matter much,
* but where we have multiple processes on the local host concurrently
* trying this call with the same starting port number. The proxy does
* this, and setting reuse=1 in the gs_establish_socket() call will spawn
* an unholy number of proxy processes.
*/
while ((sock = gs_establish_socket(&tryport, 0)) == -2) {
port++;
tryport = port;
if (port > initport + GS_NUM_PORTS_TO_TRY) {
ERRPRINTF("Impossible to bind to a port\n");
return INVALID_SOCKET;
}
}
if (proxy_is_socket_error(sock))
return INVALID_SOCKET;
*found_port = tryport;
if (*found_port == 0) {
*found_port = initport;
}
return sock;
}

| int gs_close_socket | ( | SOCKET | sock | ) |
Close this socket.
| sock | -- the socket to be closed |
Definition at line 315 of file comm_basics.c.
{
return proxy_close(sock);
}


| SOCKET gs_connect_direct | ( | char * | host, | |
| int | port | |||
| ) |
Connect directly (no proxy) to the specified host/port.
| host | -- hostname to connect to | |
| port | -- port to connect to |
Definition at line 381 of file comm_basics.c.
{
char agent_cid[CID_LEN];
struct hostent *hp;
ipaddr_t ipaddr;
DBGPRINTF("Connecting to host %s port %d\n", host, port);
if ((hp = gethostbyname(host)) == NULL) {
errno = errno_socket();
ERRPRINTF("Could not gethostbyname for %s (errno %d) \n", host, errno);
perror("gethostbyname()");
return INVALID_SOCKET;
}
memcpy((void *) &ipaddr, hp->h_addr_list[0], sizeof(ipaddr));
/* all ones will match any component ID */
memset(agent_cid, 0xFF, CID_LEN);
return gs_connect_to_host(agent_cid, ipaddr, port, 0, 0);
}


| SOCKET gs_connect_to_host | ( | char * | ID, | |
| ipaddr_t | ipaddr, | |||
| int | port, | |||
| ipaddr_t | proxyIP, | |||
| int | proxyPort | |||
| ) |
Establish a connection to the specified host.
| ID | -- the component ID of the host to connect to. | |
| ipaddr | -- the IP address of the host to connect to. If connecting through proxy, set this to 0. | |
| port | -- the port to connect to. | |
| proxyIP | -- the IP address of the host's proxy server. If not proxied, set this to 0. | |
| proxyPort | -- the port number of the proxy server. |
Definition at line 335 of file comm_basics.c.
{
PROXY_COMPONENTADDR servaddr;
char dottedip[20];
char dottedproxy[20];
SOCKET sockfd, option_value = 1;
memcpy(servaddr.ID, ID, CID_LEN);
servaddr.IP = ipaddr;
servaddr.port = htons(port);
servaddr.proxyIP = proxyIP;
servaddr.proxyPort = htons(proxyPort);
sockfd = proxy_socket(AF_INET, SOCK_STREAM, 0);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &option_value,
sizeof(int)) < 0)
DBGPRINTF("Warning: failed to set TCP_NODELAY for fd %d\n", sockfd);
proxy_ip_to_str(servaddr.IP, dottedip);
proxy_ip_to_str(servaddr.proxyIP, dottedproxy);
DBGPRINTF("Connecting to %s:%d (proxy %s:%d)\n", dottedip,
ntohs(servaddr.port), dottedproxy, ntohs(servaddr.proxyPort));
if (proxy_connect(sockfd, &servaddr) < 0) {
ERRPRINTF("Could not connect to %s:%d (proxy %s:%d)\n", dottedip,
ntohs(servaddr.port), dottedproxy, ntohs(servaddr.proxyPort));
proxy_close(sockfd);
return INVALID_SOCKET;
}
return sockfd;
}


| SOCKET gs_establish_socket | ( | in_port_t * | port, | |
| int | reuse | |||
| ) |
Get a socket and bind to it. Use the proxy library (gs_socket, gs_bind) to get a new socket descriptor and bind to it.
| port | -- Port number to be bound (on return this parameter is set to the actual value bound) | |
| reuse | -- If TRUE, the DO_REUSEADDR option is set to allow reuse of the requested port. |
Definition at line 170 of file comm_basics.c.
{
SOCKET desc;
struct sockaddr_in addr;
socklen_t addr_length;
int option_value = 1;
if ((desc = proxy_socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
return INVALID_SOCKET;
}
/* TODO */
if (reuse) {
if (setsockopt(desc, SOL_SOCKET, SO_REUSEADDR,
(char *) (&option_value), sizeof(int)) == -1) {
return INVALID_SOCKET;
}
}
if(setsockopt(desc, IPPROTO_TCP, TCP_NODELAY, (char *) &option_value,
sizeof(int)) < 0)
DBGPRINTF("Warning: failed to set TCP_NODELAY for fd %d\n", desc);
memset((char *) &addr, 0x0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(*port);
if (proxy_bind(desc, (struct sockaddr *) &addr, sizeof(addr))) {
if (errno_socket() == EADDRINUSE) {
proxy_close(desc);
return -2;
}
proxy_close(desc);
return INVALID_SOCKET;
}
addr_length = sizeof(addr);
if((proxy_getsockname(desc, (struct sockaddr *) &addr, &addr_length)) == -1) {
proxy_close(desc);
return INVALID_SOCKET;
}
*port = ntohs(addr.sin_port);
return (desc);
}


| int gs_listen_on_socket | ( | SOCKET | sock | ) |
Set socket as listening.
| sock | -- the socket descriptor |
Definition at line 277 of file comm_basics.c.
{
return proxy_listen(sock, PROXY_MAX_CONNECTIONS);
}


| ssize_t gs_readline | ( | int | fd, | |
| void * | vptr, | |||
| size_t | maxlen | |||
| ) |
Reads from descriptor until newline.
| fd | -- descriptor to read from | |
| vptr | -- pointer to buffer to store string | |
| maxlen | -- length of vptr |
Definition at line 132 of file comm_basics.c.
{
int n, rc;
char c, *ptr;
ptr = vptr;
for (n = 1; n < (int)maxlen; n++) {
if ((rc = proxy_tread(fd, &c, 1, PROXY_TIMEOUT_DEFAULT)) == 1) {
*ptr++ = c;
if (c == '\n')
break; /* newline is stored, like fgets() */
} else if (rc == 0) {
if (n == 1)
return (0); /* EOF, no data read */
else
break; /* EOF, some data was read */
} else
return (-1); /* error, errno set by read() */
}
*ptr = 0; /* null terminate like fgets() */
return (n);
}


| int gs_tread | ( | SOCKET | d, | |
| char * | b, | |||
| int | n | |||
| ) |
Read bytes from a descriptor (socket).
| d | -- the descriptor (socket) to read from | |
| b | -- the buffer containing the data to be read | |
| n | -- the number of bytes to read |
Definition at line 106 of file comm_basics.c.
{
static int sig = 1;
int retval = -1;
if (sig) {
(void) gs_signal(GS_SIGPIPE, SIG_IGN);
sig = 0;
}
retval = proxy_tread(d, b, n, PROXY_TIMEOUT_DEFAULT);
return retval;
}


| ssize_t gs_twrite | ( | SOCKET | fildes, | |
| const void * | buf, | |||
| size_t | nbyte | |||
| ) |
Write bytes to a descriptor (socket).
| fildes | -- the descriptor (socket) to write to | |
| buf | -- the buffer containing the data to be written | |
| nbyte | -- the number of bytes to write |
Definition at line 46 of file comm_basics.c.
{
static int sig = 1;
if (sig) {
(void) gs_signal(GS_SIGPIPE, SIG_IGN);
sig = 0;
}
return gs_writen(fildes, buf, nbyte);
}


| ssize_t gs_writen | ( | SOCKET | fd, | |
| const void * | vptr, | |||
| size_t | n | |||
| ) |
Write until all bytes have been written (borrowed from Stevens "Unix Network Programming").
| fd | -- the descriptor (socket) to write to | |
| vptr | -- the buffer containing the data to be written | |
| n | -- the number of bytes to write |
Definition at line 71 of file comm_basics.c.
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
DBGPRINTF("ns_writen: write %d bytes to socket %d num %d char %c\n",
n, fd, *((int *)ptr), (char)*ptr);
nleft = n;
while (nleft > 0) {
if ( (nwritten = write_socket(fd, ptr, nleft)) == SOCKET_ERROR) {
if (errno_socket() == EINTR)
nwritten = 0; /* and call write() agai n */
else
return(-1); /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}

1.6.3-20100507