/*
* Copyright (c) 1996, 1997, 1998, 1999 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software is hereby
* granted provided that (1) source code retains these copyright, permission,
* and disclaimer notices, and (2) redistributions including binaries
* reproduce the notices in supporting documentation.
*
* THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
* IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
* ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* CSL requests users of this software to return to csl-dist@cs.utah.edu any
* improvements that they make and grant CSL redistribution rights.
*/
#include "suntcp-link.h"
/* This is the first attempt at a generic flick runtime.
It's patterned after the Sun RPC transport, right now
cuz that's what it's going to be used for
*/
/* This one must be used by the client to open a connection to the server */
int
flick_client_create(FLICK_TARGET target, FLICK_SERVER_LOCATION server)
{
struct sockaddr_in addr;
int retries = CONNECT_RETRIES; /* Set the number of
retries to be done */
#ifdef _POSIX_TIMERS
struct timespec now;
#else
struct timeval now;
#endif
struct hostent *he = gethostbyname(server.server_name);
if(!he)
return 0;
memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = *(int *)*he->h_addr_list;
addr.sin_family = AF_INET;
addr.sin_port = 0;
#ifdef _POSIX_TIMERS
(void)clock_gettime(CLOCK_REALTIME, &now);
target->header.xid = htonl(getpid() ^ now.tv_sec ^ now.tv_nsec);
#else
(void)gettimeofday(&now, (struct timezone *)0);
target->header.xid = htonl(getpid() ^ now.tv_sec ^ now.tv_usec);
#endif
target->header.dir = htonl(CALL);
target->header.rpcvers = htonl(2);
target->header.prog = htonl(server.prog_num);
target->header.vers = htonl(server.vers_num);
target->port = htons(pmap_getport(&addr,
server.prog_num,
server.vers_num,
IPPROTO_TCP));
if (target->port == 0)
return 0;
addr.sin_port = target->port;
target->socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (target->socket_fd < 0) {
perror("socket");
return 0;
}
{
int val = SOCKET_BUF_SIZE;
errno = 0;
#ifdef SO_SNDBUF
printf("Target sendbuf: %d %d %d\n", setsockopt(target->socket_fd, SOL_SOCKET, SO_SNDBUF, ((void *) &val), sizeof(val)), errno, val);
#else
printf("Target sendbuf: Using default settings\n");
#endif
#ifdef SO_RCVBUF
printf("Target recvbuf: %d %d %d\n", setsockopt(target->socket_fd, SOL_SOCKET, SO_RCVBUF, ((void *) &val), sizeof(val)), errno, val);
#else
printf("Target recvbuf: %Using default settings\n");
#endif
}
while (retries && (connect(target->socket_fd,
(struct sockaddr *) &addr, sizeof(addr)) < 0)) {
switch( errno ) {
case ECONNREFUSED:
case ETIMEDOUT:
perror( "connect" );
fprintf( stderr, "Retrying...\n" );
/* We have to close the socket and make
a new one in order to retry */
close( target->socket_fd );
target->socket_fd
= socket(AF_INET,
SOCK_STREAM,
IPPROTO_TCP);
if (target->socket_fd < 0) {
perror("socket");
return 0; /* return false */
}
/* Delay for some time */
sleep( CONNECT_RETRY_DELAY );
retries--;
break;
/* The rest are considered to be
unrecoverable errors so no retry */
default:
perror( "connect" );
retries = 0;
break;
}
}
if( !retries ) {
perror("connect");
close(target->socket_fd);
return 0;
}
/* Grab the buffers for this target */
target->in = (FLICK_BUFFER *)malloc(sizeof(FLICK_BUFFER));
target->out = (FLICK_BUFFER *)malloc(sizeof(FLICK_BUFFER));
if (!(target->in && target->out))
return 0;
target->in->real_buf_start = target->in->buf_read
= target->in->real_buf_end = 0;
target->in->buf_current = target->in->buf_start = (void *)calloc(8192, 1);
target->in->buf_end = ((char *) target->in->buf_start) + 8188;
target->out->buf_current = target->out->real_buf_start
= target->out->buf_read
= target->out->buf_start
= (void *)calloc(8192, 1);
target->out->buf_end = target->out->real_buf_end
= ((char *) target->out->buf_start) + 8188;
return target->in->buf_current && target->out->buf_current;
}
/* This one must be used by the client to close a connection to the server */
void
flick_client_destroy(FLICK_TARGET target)
{
close(target->socket_fd);
free(target->in->real_buf_start);
free(target->out->buf_start);
free(target->in);
free(target->out);
}
int
flick_client_send_request(FLICK_TARGET target, FLICK_BUFFER *in_buf)
{
return flick_write_buf(in_buf, target->socket_fd);
}
int
flick_client_get_reply(FLICK_TARGET target, FLICK_BUFFER *out_buf)
{
return flick_read_buf(out_buf, target->socket_fd);
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1