166 lines
4.2 KiB
C
166 lines
4.2 KiB
C
|
/****************************************************************
|
||
|
* *
|
||
|
* Copyright 2001, 2010 Fidelity Information Services, Inc *
|
||
|
* *
|
||
|
* This source code contains the intellectual property *
|
||
|
* of its copyright holder(s), and is made available *
|
||
|
* under a license. If you do not know the terms of *
|
||
|
* the license, please stop and do not read further. *
|
||
|
* *
|
||
|
****************************************************************/
|
||
|
|
||
|
/* gtcm_cn_acpt.c ---
|
||
|
* Accept a client connection.
|
||
|
*/
|
||
|
|
||
|
#include "mdef.h"
|
||
|
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include "gtm_fcntl.h"
|
||
|
#include "gtm_string.h"
|
||
|
#include "gtm_stdio.h"
|
||
|
#include "gtm_unistd.h" /* for close() used by CLOSEFILE_RESET */
|
||
|
#include "gtm_time.h" /* for ctime() and time() */
|
||
|
|
||
|
#include "gtcm.h"
|
||
|
#include "rc_oflow.h"
|
||
|
#include "eintr_wrappers.h"
|
||
|
#include "gtm_socket.h"
|
||
|
#include "gtmio.h"
|
||
|
|
||
|
#ifdef BSD_TCP
|
||
|
#include "gtm_inet.h"
|
||
|
#endif /* defined(BSD_TCP) */
|
||
|
|
||
|
#ifndef lint
|
||
|
static char rcsid[] = "$Header:$";
|
||
|
#endif
|
||
|
|
||
|
GBLREF char *omi_pklog;
|
||
|
GBLREF int one_conn_per_inaddr;
|
||
|
GBLREF int conn_timeout;
|
||
|
|
||
|
int gtcm_cn_acpt(omi_conn_ll *cll, int now) /* now --> current time in seconds */
|
||
|
{
|
||
|
int i;
|
||
|
omi_conn *cptr;
|
||
|
omi_fd fd;
|
||
|
int rc;
|
||
|
|
||
|
#ifdef BSD_TCP
|
||
|
GTM_SOCKLEN_TYPE sln;
|
||
|
struct sockaddr_in sin;
|
||
|
int option, optsize;
|
||
|
|
||
|
/* Accept the connection from the network layer */
|
||
|
sln = SIZEOF(sin);
|
||
|
if ((fd = accept(cll->nve, (struct sockaddr *)&sin, (GTM_SOCKLEN_TYPE *)&sln)) < 0)
|
||
|
return -1;
|
||
|
#endif /* defined(BSD_TCP) */
|
||
|
|
||
|
/* Build the client data structure */
|
||
|
if (!(cptr = (omi_conn *)malloc(SIZEOF(omi_conn))) || !(cptr->buff = (char *)malloc(OMI_BUFSIZ)))
|
||
|
{
|
||
|
if (cptr)
|
||
|
free(cptr);
|
||
|
CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */
|
||
|
return -1;
|
||
|
}
|
||
|
/* Initialize the connection structure */
|
||
|
cptr->next = (omi_conn *)0;
|
||
|
cptr->fd = fd;
|
||
|
cptr->ping_cnt = 0;
|
||
|
cptr->timeout = now + conn_timeout;
|
||
|
cptr->bsiz = OMI_BUFSIZ;
|
||
|
cptr->bptr = cptr->buff;
|
||
|
cptr->xptr = (char *)0;
|
||
|
cptr->blen = 0;
|
||
|
cptr->exts = 0;
|
||
|
cptr->state = OMI_ST_DISC;
|
||
|
cptr->ga = (ga_struct *)0; /* struct gd_addr_struct */
|
||
|
cptr->of = (oof_struct *) malloc(SIZEOF(struct rc_oflow));
|
||
|
memset(cptr->of, 0, SIZEOF(struct rc_oflow));
|
||
|
cptr->pklog = FD_INVALID;
|
||
|
/* Initialize the statistics */
|
||
|
memcpy(&cptr->stats.sin,&sin,SIZEOF(sin));
|
||
|
cptr->stats.bytes_recv = 0;
|
||
|
cptr->stats.bytes_send = 0;
|
||
|
cptr->stats.start = time((time_t *)0);
|
||
|
for (i = 0; i < OMI_OP_MAX; i++)
|
||
|
cptr->stats.xact[i] = 0;
|
||
|
for (i = 0; i < OMI_ER_MAX; i++)
|
||
|
cptr->stats.errs[i] = 0;
|
||
|
|
||
|
/* if we only allowing one connection per internet address, close any existing ones with the same addr. */
|
||
|
if (one_conn_per_inaddr)
|
||
|
{
|
||
|
omi_conn *this, *prev;
|
||
|
|
||
|
for (prev = NULL, this = cll->head; this; prev = this, this = this->next)
|
||
|
{
|
||
|
if (this->stats.sin.sin_addr.s_addr == sin.sin_addr.s_addr)
|
||
|
{
|
||
|
if (cll->tail == this)
|
||
|
cll->tail = cptr;
|
||
|
if (prev)
|
||
|
prev->next = cptr;
|
||
|
else
|
||
|
cll->head = cptr;
|
||
|
cptr->next = this->next;
|
||
|
OMI_DBG_STMP;
|
||
|
OMI_DBG((omi_debug, "%s: dropping old connection to %s\n",
|
||
|
SRVR_NAME, gtcm_hname(&cptr->stats.sin)));
|
||
|
gtcm_cn_disc(this, cll);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
/* not found - add to the end of the list */
|
||
|
if (!this)
|
||
|
{
|
||
|
if (cll->tail)
|
||
|
{
|
||
|
cll->tail->next = cptr;
|
||
|
cll->tail = cptr;
|
||
|
} else
|
||
|
cll->head = cll->tail = cptr;
|
||
|
}
|
||
|
} else
|
||
|
{
|
||
|
/* Insert the client into the list of connections */
|
||
|
if (cll->tail)
|
||
|
{
|
||
|
cll->tail->next = cptr;
|
||
|
cll->tail = cptr;
|
||
|
} else
|
||
|
cll->head = cll->tail = cptr;
|
||
|
}
|
||
|
cptr->stats.id = ++cll->stats.conn;
|
||
|
|
||
|
DEBUG_ONLY(
|
||
|
if (omi_pklog)
|
||
|
{
|
||
|
int errno_save;
|
||
|
char pklog[1024];
|
||
|
|
||
|
(void)SPRINTF(pklog, "%s.%04d", omi_pklog, cptr->stats.id);
|
||
|
if (INV_FD_P((cptr->pklog = OPEN3(pklog, O_WRONLY|O_CREAT|O_APPEND|O_TRUNC, 0644))))
|
||
|
{
|
||
|
errno_save = errno;
|
||
|
OMI_DBG_STMP;
|
||
|
OMI_DBG((omi_debug, "%s: unable to open packet log \"%s\"\n\t%s\n",
|
||
|
SRVR_NAME, pklog, STRERROR(errno_save)));
|
||
|
}
|
||
|
}
|
||
|
)
|
||
|
OMI_DBG((omi_debug, "%s: connection %d from %s by user <%s> at %s", SRVR_NAME,
|
||
|
cptr->stats.id, gtcm_hname(&cptr->stats.sin), cptr->ag_name, GTM_CTIME(&cptr->stats.start)));
|
||
|
option = -1;
|
||
|
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&option, SIZEOF(option)) < 0)
|
||
|
{
|
||
|
PERROR("setsockopt:");
|
||
|
return -1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|