fis-gtm/sr_port/iosocket_close.c

145 lines
3.9 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 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. *
* *
****************************************************************/
/* iosocket_close.c - close a socket connection
* Parameters-
* iod -- I/O descriptor for the current device.
*
* pp -- mval that carries the device parameters
*
*/
#include "mdef.h"
#include "gtm_string.h"
#include "gtm_iconv.h"
#include "gtm_stdio.h"
#include "gtm_socket.h"
#include "gtm_inet.h"
#include "copy.h"
#include "io_params.h"
#include "io.h"
#include "iotcpdef.h"
#include "iotcproutine.h"
#include "gt_timer.h"
#include "iosocketdef.h"
#include "stringpool.h"
GBLREF tcp_library_struct tcp_routines;
GBLREF io_desc *active_device;
LITREF unsigned char io_params_size[];
error_def(ERR_SOCKNOTFND);
void iosocket_close(io_desc *iod, mval *pp)
{
boolean_t socket_specified = FALSE;
unsigned char ch;
int handle_len;
d_socket_struct *dsocketptr;
socket_struct *socketptr;
char sock_handle[MAX_HANDLE_LEN];
int4 ii, jj, start, end, index;
int p_offset = 0;
boolean_t socket_destroy = FALSE;
assert(iod->type == gtmsocket);
dsocketptr = (d_socket_struct *)iod->dev_sp;
while (iop_eol != (ch = *(pp->str.addr + p_offset++)))
{
switch (ch)
{
case iop_exception:
iod->error_handler.len = *(pp->str.addr + p_offset);
iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
s2pool(&iod->error_handler);
break;
case iop_socket:
handle_len = (short)(*(pp->str.addr + p_offset));
assert(handle_len > 0);
memcpy(sock_handle, (char *)(pp->str.addr + p_offset + 1), handle_len);
socket_specified = TRUE;
break;
case iop_ipchset:
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
if ( (iconv_t)0 != iod->input_conv_cd )
{
ICONV_CLOSE_CD(iod->input_conv_cd);
}
SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1));
if (DEFAULT_CODE_SET != iod->in_code_set)
ICONV_OPEN_CD(iod->input_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1));
#endif
break;
case iop_opchset:
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
if ( (iconv_t)0 != iod->output_conv_cd )
{
ICONV_CLOSE_CD(iod->output_conv_cd);
}
SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1));
if (DEFAULT_CODE_SET != iod->out_code_set)
ICONV_OPEN_CD(iod->output_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
#endif
break;
case iop_destroy:
socket_destroy = TRUE;
break;
case iop_nodestroy:
socket_destroy = FALSE;
break;
default:
break;
}
p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
}
if (socket_specified)
{
if (0 > (index = iosocket_handle(sock_handle, &handle_len, FALSE, dsocketptr)))
{
rts_error(VARLSTCNT(4) ERR_SOCKNOTFND, 2, handle_len, sock_handle);
return;
}
start = end = index;
}
else
{
start = dsocketptr->n_socket - 1;
end = 0;
}
for (ii = start; ii >= end; ii--)
{
socketptr = dsocketptr->socket[ii];
tcp_routines.aa_close(socketptr->sd);
iosocket_delimiter((unsigned char *)NULL, 0, socketptr, TRUE); /* free the delimiter space */
free(socketptr->buffer);
if (NULL != socketptr->zff.addr)
free(socketptr->zff.addr);
free(socketptr);
if (dsocketptr->current_socket >= ii)
dsocketptr->current_socket--;
for (jj = ii + 1; jj <= dsocketptr->n_socket - 1; jj++)
dsocketptr->socket[jj - 1] = dsocketptr->socket[jj];
dsocketptr->n_socket--;
}
if (!socket_specified)
{
iod->state = dev_closed;
if (socket_destroy)
{
active_device = 0;
iosocket_destroy(iod);
}
}
}