Пример #1
0
/* Internal version of start_timer that does not protect itself, assuming this has already been done.
 * Otherwise does as explained above in start_timer.
 */
STATICFNDEF void start_timer_int(TID tid, int4 time_to_expir, void (*handler)(), int4 hdata_len, void *hdata)
{
	ABS_TIME at;

 	assert(0 != time_to_expir);
	sys_get_curr_time(&at);
	if (first_timeset)
	{
		init_timers();
		first_timeset = FALSE;
	}
	/* We expect no timer with id=<tid> to exist in the timer queue currently. This is asserted in "add_timer" call below.
	 * In pro though, we'll be safe and remove any tids that exist before adding a new entry with the same tid - 2009/10.
	 * If a few years pass without the assert failing, it might be safe then to remove the PRO_ONLY code below.
	 */
#	ifndef DEBUG
	if (timeroot && (timeroot->tid == tid))
		sys_canc_timer();
	remove_timer(tid); /* Remove timer from chain */
#	endif
	/* Check if # of free timer slots is less than minimum threshold. If so, allocate more of those while it is safe to do so */
	if ((GT_TIMER_EXPAND_TRIGGER > num_timers_free) && (1 > timer_stack_count))
		gt_timers_alloc();
	add_timer(&at, tid, time_to_expir, handler, hdata_len, hdata);	/* Link new timer into timer chain */
	if ((timeroot->tid == tid) || !timer_active)
		start_first_timer(&at);
}
Пример #2
0
void gtcml_chkreg(void)
{
	cm_lckblkreg *reg, *reg1;

	sys_get_curr_time(&chkreg_time);	/* just once per pass */
	reg1 = reg = blkdlist;

	while (reg)
	{
		gv_cur_region = reg->region->reg;
		if (reg->region->refcnt == 0)
		{
			gtcml_chklck(reg,FALSE);
			assert (reg->lock == 0);
		}
		else if (reg->region->wakeup < ((mlk_ctldata *)FILE_INFO(gv_cur_region)->s_addrs.lock_addrs[0])->wakeups)
		{
			gtcml_chklck(reg,FALSE);
			reg->region->wakeup = ((mlk_ctldata *)FILE_INFO(gv_cur_region)->s_addrs.lock_addrs[0])->wakeups;
			reg->pass = CM_BLKPASS;
		}
		else if (--reg->pass == 0)
		{
			gtcml_chklck(reg,TRUE);
			reg->pass = CM_BLKPASS;
		}

		if (reg->lock == 0)
		{
			if (reg == blkdlist)
			{
				blkdlist = reg->next;
				free(reg);
				reg = reg1 = blkdlist;
			}
			else
			{
				reg1->next = reg->next;
				free(reg);
				reg = reg1->next;
			}
		}
		else
		{
			reg1 = reg;
			reg = reg->next;
		}
	}
}
Пример #3
0
/* Cancel timer.
 * Arguments:	tid - timer id
 */
void cancel_timer(TID tid)
{
        ABS_TIME at;
	sigset_t savemask;

	sigprocmask(SIG_BLOCK, &blockalrm, &savemask);	/* block SIGALRM signal */
	sys_get_curr_time(&at);
	if (tid == 0)
	{
		assert(process_exiting || IS_GTMSECSHR_IMAGE); /* wcs_phase2_commit_wait relies on this flag being set BEFORE
								* cancelling all timers. But secshr doesn't have it.
								*/
		cancel_all_timers();
		uninit_all_timers();
		timer_stack_count = 0;
		sigprocmask(SIG_SETMASK, &savemask, NULL);
		return;
	}
	if (timeroot && (timeroot->tid == tid))		/* if this is the first timer in the chain, stop it */
		sys_canc_timer();
	remove_timer(tid);		/* remove it from the chain */
	start_first_timer(&at);		/* start the first timer in the chain */
	sigprocmask(SIG_SETMASK, &savemask, NULL);
}
Пример #4
0
boolean_t iosocket_wait(io_desc *iod, int4 timepar)
{
	struct 	timeval  	utimeout;
	ABS_TIME		cur_time, end_time;
	struct 	sockaddr_storage    	peer;           /* socket address + port */
	fd_set    		tcp_fd;
	d_socket_struct 	*dsocketptr;
	socket_struct   	*socketptr, *newsocketptr;
	socket_interrupt	*sockintr;
	char            	*errptr;
	int4            	errlen, ii, msec_timeout;
	int			rv, max_fd, len;
	GTM_SOCKLEN_TYPE	size;
	boolean_t		zint_restart;
	mv_stent		*mv_zintdev;
	int			retry_num;
	struct sockaddr		*peer_sa_ptr;
	char			port_buffer[NI_MAXSERV], ipaddr[SA_MAXLEN + 1];
	int			errcode;

	/* check for validity */
	assert(iod->type == gtmsocket);
	dsocketptr = (d_socket_struct *)iod->dev_sp;
	sockintr = &dsocketptr->sock_save_state;
	peer_sa_ptr = ((struct sockaddr *)(&peer));

	/* Check for restart */
	if (!dsocketptr->mupintr)
		/* Simple path, no worries*/
		zint_restart = FALSE;
	else
	{       /* We have a pending wait restart of some sort - check we aren't recursing on this device */
		if (sockwhich_invalid == sockintr->who_saved)
			GTMASSERT;	/* Interrupt should never have an invalid save state */
		if (dollar_zininterrupt)
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO);
		if (sockwhich_wait != sockintr->who_saved)
			GTMASSERT;      /* ZINTRECURSEIO should have caught */
		DBGSOCK((stdout, "socwait: *#*#*#*#*#*#*#  Restarted interrupted wait\n"));
		mv_zintdev = io_find_mvstent(iod, FALSE);
		if (mv_zintdev)
		{
			if (sockintr->end_time_valid)
				/* Restore end_time for timeout */
				end_time = sockintr->end_time;

			/* Done with this mv_stent. Pop it off if we can, else mark it inactive. */
			if (mv_chain == mv_zintdev)
				POP_MV_STENT();         /* pop if top of stack */
			else
			{       /* else mark it unused */
				mv_zintdev->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
				mv_zintdev->mv_st_cont.mvs_zintdev.io_ptr = NULL;
			}
			zint_restart = TRUE;
			DBGSOCK((stdout, "socwait: mv_stent found - endtime: %d/%d\n", end_time.at_sec, end_time.at_usec));
		} else
			DBGSOCK((stdout, "socwait: no mv_stent found !!\n"));
		dsocketptr->mupintr = FALSE;
		sockintr->who_saved = sockwhich_invalid;
	}
	/* check for events */
	FD_ZERO(&tcp_fd);
	while (TRUE)
	{
		max_fd = 0;
		for (ii = 0; ii < dsocketptr->n_socket; ii++)
		{
			socketptr = dsocketptr->socket[ii];
			if ((socket_listening == socketptr->state) || (socket_connected == socketptr->state))
			{
				FD_SET(socketptr->sd, &tcp_fd);
				max_fd = MAX(max_fd, socketptr->sd);
			}
		}
		utimeout.tv_sec = timepar;
		utimeout.tv_usec = 0;
		msec_timeout = timeout2msec(timepar);
		sys_get_curr_time(&cur_time);
		if (!zint_restart || !sockintr->end_time_valid)
			add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
		else
		{       /* end_time taken from restart data. Compute what msec_timeout should be so timeout timer
					   gets set correctly below.
			*/
			DBGSOCK((stdout, "socwait: Taking timeout end time from wait restart data\n"));
			cur_time = sub_abs_time(&end_time, &cur_time);
			if (0 > cur_time.at_sec)
			{
				msec_timeout = -1;
				utimeout.tv_sec = 0;
				utimeout.tv_usec = 0;
			} else
			{
				msec_timeout = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000);
				utimeout.tv_sec = cur_time.at_sec;
				utimeout.tv_usec = (gtm_tv_usec_t)cur_time.at_usec;
			}
		}
		sockintr->end_time_valid = FALSE;
		for ( ; ; )
		{
			rv = select(max_fd + 1, (void *)&tcp_fd, (void *)0, (void *)0,
				    (timepar == NO_M_TIMEOUT ? (struct timeval *)0 : &utimeout));
			if (0 > rv && EINTR == errno)
			{
				if (0 != outofband)
				{
					DBGSOCK((stdout, "socwait: outofband interrupt received (%d) -- "
						 "queueing mv_stent for wait intr\n", outofband));
					PUSH_MV_STENT(MVST_ZINTDEV);
					mv_chain->mv_st_cont.mvs_zintdev.io_ptr = iod;
					mv_chain->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
					sockintr->who_saved = sockwhich_wait;
					sockintr->end_time = end_time;
					sockintr->end_time_valid = TRUE;
					dsocketptr->mupintr = TRUE;
					socketus_interruptus++;
					DBGSOCK((stdout, "socwait: mv_stent queued - endtime: %d/%d  interrupts: %d\n",
						 end_time.at_sec, end_time.at_usec, socketus_interruptus));
					outofband_action(FALSE);
					GTMASSERT;      /* Should *never* return from outofband_action */
					return FALSE;   /* For the compiler.. */
				}
				sys_get_curr_time(&cur_time);
				cur_time = sub_abs_time(&end_time, &cur_time);
				if (0 > cur_time.at_sec)
				{
					rv = 0;		/* time out */
					break;
				}
				utimeout.tv_sec = cur_time.at_sec;
				utimeout.tv_usec = (gtm_tv_usec_t)cur_time.at_usec;
			} else
				break;	/* either other error or done */
		}
		if (rv == 0)
		{
			iod->dollar.key[0] = '\0';
			return FALSE;
		} else  if (rv < 0)
		{
			errptr = (char *)STRERROR(errno);
			errlen = STRLEN(errptr);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKWAIT, 0, ERR_TEXT, 2, errlen, errptr);
			return FALSE;
		}
		/* find out which socket is ready */
		for (ii = 0; ii < dsocketptr->n_socket; ii++)
		{
			socketptr = dsocketptr->socket[ii];
			if (0 != FD_ISSET(socketptr->sd, &tcp_fd))
				break;
		}
		assert(ii < dsocketptr->n_socket);
		if (socket_listening == socketptr->state)
		{
			if (gtm_max_sockets <= dsocketptr->n_socket)
			{
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
				return FALSE;
			}

			size = SIZEOF(struct sockaddr_storage);
			rv = tcp_routines.aa_accept(socketptr->sd, peer_sa_ptr, &size);
			if (-1 == rv)
			{
#				ifdef __hpux
				if (ENOBUFS == errno)
					continue;	/* On HP-UX, ENOBUFS may indicate a transient condition; retry */
#				endif
				errptr = (char *)STRERROR(errno);
				errlen = STRLEN(errptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKACPT, 0, ERR_TEXT, 2, errlen, errptr);
				return FALSE;
			}
			SOCKET_DUP(socketptr, newsocketptr);
			newsocketptr->sd = rv;
			SOCKET_ADDR_COPY(newsocketptr->remote, peer_sa_ptr, size);
			/* translate internal address to numeric ip address */
			GETNAMEINFO(peer_sa_ptr, size, ipaddr, SA_MAXLEN, NULL, 0, NI_NUMERICHOST, errcode);
			if (0 != errcode)
			{
				SOCKET_FREE(newsocketptr);
				RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
				return FALSE;
			}
			if (NULL != newsocketptr->remote.saddr_ip)
				free(newsocketptr->remote.saddr_ip);
			STRNDUP(ipaddr, SA_MAXLEN, newsocketptr->remote.saddr_ip);
			/* translate internal address to port number*/
			GETNAMEINFO(peer_sa_ptr, size, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV, errcode);
			if (0 != errcode)
			{
				SOCKET_FREE(newsocketptr);
				RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
				return FALSE;
			}
			newsocketptr->remote.port = ATOI(port_buffer);
			newsocketptr->state = socket_connected;
			newsocketptr->passive = FALSE;
			newsocketptr->first_read = newsocketptr->first_write = TRUE;
			/* put the new-born socket to the list and create a handle for it */
			iosocket_handle(newsocketptr->handle, &newsocketptr->handle_len, TRUE, dsocketptr);
			dsocketptr->socket[dsocketptr->n_socket++] = newsocketptr;
			dsocketptr->current_socket = dsocketptr->n_socket - 1;
			len = SIZEOF(CONNECTED) - 1;
			memcpy(&iod->dollar.key[0], CONNECTED, len);
			iod->dollar.key[len++] = '|';
			memcpy(&iod->dollar.key[len], newsocketptr->handle, newsocketptr->handle_len);
			len += newsocketptr->handle_len;
			iod->dollar.key[len++] = '|';
			strncpy(&iod->dollar.key[len], newsocketptr->remote.saddr_ip, DD_BUFLEN - 1 - len);
			iod->dollar.key[DD_BUFLEN-1] = '\0';		/* In case we fill the buffer */
		} else
		{
			assert(socket_connected == socketptr->state);
			dsocketptr->current_socket = ii;
			len = SIZEOF(READ) - 1;
			memcpy(&iod->dollar.key[0], READ, len);
			iod->dollar.key[len++] = '|';
			memcpy(&iod->dollar.key[len], socketptr->handle, socketptr->handle_len);
			len += socketptr->handle_len;
			iod->dollar.key[len++] = '|';
			if (NULL != socketptr->remote.saddr_ip)
			{
				strncpy(&iod->dollar.key[len], socketptr->remote.saddr_ip, DD_BUFLEN - 1 - len);
				iod->dollar.key[DD_BUFLEN-1] = '\0';
			} else
				iod->dollar.key[len] = '\0';
		}
		break;
	}
Пример #5
0
/*
 * -----------------------------------------------
 * Maintain in parallel with op_zalloc2
 * Arguments:
 *	timeout	- max. time to wait for locks before giving up
 *      laflag - passed to gvcmx* routines as "laflag" argument;
 *		 originally indicated the request was a Lock or
 *		 zAllocate request (hence the name "laflag"), but
 *		 now capable of holding more values signifying
 *		 additional information
 *
 * Return:
 *	1 - if not timeout specified
 *	if timeout specified:
 *		!= 0 - all the locks int the list obtained, or
 *		0 - blocked
 *	The return result is suited to be placed directly into
 *	the $T variable by the caller if timeout is specified.
 * -----------------------------------------------
 */
int	op_lock2(int4 timeout, unsigned char laflag)	/* timeout is in seconds */
{
	boolean_t	blocked, timer_on;
	signed char	gotit;
	unsigned short	locks_bckout, locks_done;
	int4		msec_timeout;	/* timeout in milliseconds */
	mlk_pvtblk	*pvt_ptr1, *pvt_ptr2, **prior;
	unsigned char	action;
	ABS_TIME	cur_time, end_time, remain_time;
	mv_stent	*mv_zintcmd;

	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	gotit = -1;
	cm_action = laflag;
	out_of_time = FALSE;
	if (timeout < 0)
		timeout = 0;
	else if (TREF(tpnotacidtime) < timeout)
		TPNOTACID_CHECK(LOCKTIMESTR);
	if (!(timer_on = (NO_M_TIMEOUT != timeout)))	/* NOTE assignment */
		msec_timeout = NO_M_TIMEOUT;
	else
	{
		msec_timeout = timeout2msec(timeout);
		if (0 == msec_timeout)
		{
			out_of_time = TRUE;
			timer_on = FALSE;
		} else
		{
			mv_zintcmd = find_mvstent_cmd(ZINTCMD_LOCK, restart_pc, restart_ctxt, FALSE);
			if (mv_zintcmd)
			{
				remain_time = mv_zintcmd->mv_st_cont.mvs_zintcmd.end_or_remain;
				if (0 <= remain_time.at_sec)
					msec_timeout = (int4)(remain_time.at_sec * 1000 + remain_time.at_usec / 1000);
				else
					msec_timeout = 0;
				TAREF1(zintcmd_active, ZINTCMD_LOCK).restart_pc_last
					= mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_prior;
				TAREF1(zintcmd_active, ZINTCMD_LOCK).restart_ctxt_last
					= mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_ctxt_prior;
				TAREF1(zintcmd_active, ZINTCMD_LOCK).count--;
				assert(0 <= TAREF1(zintcmd_active, ZINTCMD_LOCK).count);
				if (mv_chain == mv_zintcmd)
					POP_MV_STENT(); /* just pop if top of stack */
				else
				{       /* flag as not active */
					mv_zintcmd->mv_st_cont.mvs_zintcmd.command = ZINTCMD_NOOP;
					mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_check = NULL;
				}
			}
			if (0 < msec_timeout)
			{
				sys_get_curr_time(&cur_time);
				add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
				start_timer((TID)&timer_on, msec_timeout, wake_alarm, 0, NULL);
			} else
			{
				out_of_time = TRUE;
				timer_on = FALSE;
			}
		}
	}
	lckclr();
	for (blocked = FALSE;  !blocked;)
	{	/* if this is a request for a remote node */
		if (remlkreq)
		{
			if (gotit >= 0)
				gotit = gvcmx_resremlk(cm_action);
			else
				gotit = gvcmx_reqremlk(cm_action, msec_timeout);	/* REQIMMED if 2nd arg == 0 */
			if (!gotit)
			{	/* only REQIMMED returns false */
				blocked = TRUE;
				break;
			}
		}
		for (pvt_ptr1 = mlk_pvt_root, locks_done = 0;  locks_done < lks_this_cmd;  pvt_ptr1 = pvt_ptr1->next, locks_done++)
		{	/* Go thru the list of all locks to be obtained attempting to lock
			 * each one. If any lock could not be obtained, break out of the loop
			 */
			if (!mlk_lock(pvt_ptr1, 0, TRUE))
			{	/* If lock is obtained */
				pvt_ptr1->granted = TRUE;
				switch (laflag)
				{
				case CM_LOCKS:
					pvt_ptr1->level = 1;
					break;
				case INCREMENTAL:
					if (pvt_ptr1->level < 511) /* The same lock can not be incremented more than 511 times. */
						pvt_ptr1->level += pvt_ptr1->translev;
					else
						level_err(pvt_ptr1);
					break;
				default:
					GTMASSERT;
					break;
				}
			} else
			{
				blocked = TRUE;
				break;
			}
		}
		/* If we did not get blocked, we are all done */
		if (!blocked)
			break;
		/* We got blocked and need to keep retrying after some time interval */
		if (remlkreq)
			gvcmx_susremlk(cm_action);
		switch (cm_action)
		{
		case CM_LOCKS:
			action = LOCKED;
			break;
		case INCREMENTAL:
			action = INCREMENTAL;
			break;
		default:
			GTMASSERT;
			break;
		}
		for (pvt_ptr2 = mlk_pvt_root, locks_bckout = 0;  locks_bckout < locks_done;
			pvt_ptr2 = pvt_ptr2->next, locks_bckout++)
		{
			assert(pvt_ptr2->granted && (pvt_ptr2 != pvt_ptr1));
			mlk_bckout(pvt_ptr2, action);
		}
		if (dollar_tlevel && (CDB_STAGNATE <= t_tries))
		{	/* upper TPNOTACID_CHECK conditioned on no short timeout; this one rel_crits to avoid potential deadlock */
			assert(TREF(tpnotacidtime) >= timeout);
			TPNOTACID_CHECK(LOCKTIMESTR);
		}
		for (;;)
		{
			if (out_of_time || outofband)
			{	/* if time expired || control-c, tptimeout, or jobinterrupt encountered */
				if (outofband || !lk_check_own(pvt_ptr1))
				{	/* If CTL-C, check lock owner */
					if (pvt_ptr1->nodptr)		/* Get off pending list to be sent a wake */
						mlk_unpend(pvt_ptr1);
					/* Cancel all remote locks obtained so far */
					if (remlkreq)
					{
						gvcmx_canremlk();
						gvcmz_clrlkreq();
						remlkreq = FALSE;
					}
					if (outofband)
					{
						if (timer_on && !out_of_time)
						{
							cancel_timer((TID)&timer_on);
							timer_on = FALSE;
						}
						if (!out_of_time && (NO_M_TIMEOUT != timeout))
						{	/* get remain = end_time - cur_time */
							sys_get_curr_time(&cur_time);
							remain_time = sub_abs_time(&end_time, &cur_time);
							if (0 <= remain_time.at_sec)
								msec_timeout = (int4)(remain_time.at_sec * 1000
									+ remain_time.at_usec / 1000);
							else
								msec_timeout = 0;	/* treat as out_of_time */
							if (0 >= msec_timeout)
							{
								out_of_time = TRUE;
								timer_on = FALSE;	/* as if LOCK :0 */
								break;
							}
							PUSH_MV_STENT(MVST_ZINTCMD);
							mv_chain->mv_st_cont.mvs_zintcmd.end_or_remain = remain_time;
							mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_check = restart_ctxt;
							mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_check = restart_pc;
							/* save current information from zintcmd_active */
							mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_prior
								= TAREF1(zintcmd_active, ZINTCMD_LOCK).restart_ctxt_last;
							mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_prior
								= TAREF1(zintcmd_active, ZINTCMD_LOCK).restart_pc_last;
							TAREF1(zintcmd_active, ZINTCMD_LOCK).restart_pc_last = restart_pc;
							TAREF1(zintcmd_active, ZINTCMD_LOCK).restart_ctxt_last = restart_ctxt;
							TAREF1(zintcmd_active, ZINTCMD_LOCK).count++;
							mv_chain->mv_st_cont.mvs_zintcmd.command = ZINTCMD_LOCK;
							outofband_action(FALSE);	/* no return */
						}
					}
					break;
				}
			}
			if (!mlk_lock(pvt_ptr1, 0, FALSE))
			{	/* If we got the lock, break out of timer loop */
				blocked = FALSE;
				if (pvt_ptr1 != mlk_pvt_root)
				{
					rel_quant();		/* attempt to get a full timeslice for maximum chance to get all */
					mlk_unlock(pvt_ptr1);
				}
				break;
			}
			if (pvt_ptr1->nodptr)
				lk_check_own(pvt_ptr1);		/* clear an abandoned owner */
			hiber_start_wait_any(LOCK_SELF_WAKE);
		}
		if (blocked && out_of_time)
			break;
	}
	if (remlkreq)
	{
		gvcmz_clrlkreq();
		remlkreq = FALSE;
	}
	if (NO_M_TIMEOUT != timeout)
	{	/* was timed or immediate */
		if (timer_on && !out_of_time)
			cancel_timer((TID)&timer_on);
		if (blocked)
		{
			for (prior = &mlk_pvt_root;  *prior;)
			{
				if (!(*prior)->granted)
				{	/* if entry was never granted, delete list entry */
					mlk_pvtblk_delete(prior);
				} else
					prior = &((*prior)->next);
			}
			mlk_stats.n_user_locks_fail++;
			return (FALSE);
		}
	}
	mlk_stats.n_user_locks_success++;
	return (TRUE);
}
Пример #6
0
short	iott_readfl (mval *v, int4 length, int4 timeout)	/* timeout in seconds */
{
	boolean_t	ret, nonzerotimeout, timed;
	uint4		mask;
	unsigned char	inchar, *temp;
#ifdef __MVS__
	unsigned char	asc_inchar;
#endif
	int		dx, msk_in, msk_num, outlen, rdlen, save_errno, selstat, status, width;
	int4		msec_timeout;			/* timeout in milliseconds */
	io_desc		*io_ptr;
	d_tt_struct	*tt_ptr;
	io_terminator	outofbands;
	io_termmask	mask_term;
	unsigned char	*zb_ptr, *zb_top;
	ABS_TIME	cur_time, end_time;
	fd_set		input_fd;
	struct timeval	input_timeval;
	struct timeval	save_input_timeval;

	error_def(ERR_CTRAP);
	error_def(ERR_IOEOF);
	error_def(ERR_NOPRINCIO);

	assert(stringpool.free >= stringpool.base);
	assert(stringpool.free <= stringpool.top);
	io_ptr = io_curr_device.in;
	tt_ptr = (d_tt_struct *)(io_ptr->dev_sp);
	assert(dev_open == io_ptr->state);
	iott_flush(io_curr_device.out);
	width = io_ptr->width;
	if (stringpool.free + length > stringpool.top)
		stp_gcol (length);
	outlen = 0;
	/* ---------------------------------------------------------
	 * zb_ptr is be used to fill-in the value of $zb as we go
	 * If we drop-out with error or otherwise permaturely,
	 * consider $zb to be null.
	 * ---------------------------------------------------------
	 */
	zb_ptr = io_ptr->dollar.zb;
	zb_top = zb_ptr + sizeof(io_ptr->dollar.zb) - 1;
	*zb_ptr = 0;
	io_ptr->esc_state = START;
	io_ptr->dollar.za = 0;
	io_ptr->dollar.zeof = FALSE;
	v->str.len = 0;
	dx = (int)io_ptr->dollar.x;
	ret = TRUE;
	temp = stringpool.free;
	mask = tt_ptr->term_ctrl;
	mask_term = tt_ptr->mask_term;
	if (mask & TRM_NOTYPEAHD)
		TCFLUSH(tt_ptr->fildes, TCIFLUSH, status);
	if (mask & TRM_READSYNC)
	{
		DOWRITERC(tt_ptr->fildes, &dc1, 1, status);
		if (0 != status)
		{
			io_ptr->dollar.za = 9;
			rts_error(VARLSTCNT(1) status);
		}
	}
	nonzerotimeout = FALSE;
	if (NO_M_TIMEOUT == timeout)
	{
		timed = FALSE;
		input_timeval.tv_sec = 100;
		msec_timeout = NO_M_TIMEOUT;
	} else
	{
		timed = TRUE;
		input_timeval.tv_sec = timeout;
		msec_timeout = timeout2msec(timeout);
		if (!msec_timeout)
			iott_mterm(io_ptr);
		else
		{
			nonzerotimeout = TRUE;
   			sys_get_curr_time(&cur_time);
			add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
		}
	}
	input_timeval.tv_usec = 0;
	do
	{
		if (outofband)
		{
			outlen = 0;
			if (!msec_timeout)
				iott_rterm(io_ptr);
			outofband_action(FALSE);
			break;
		}
		errno = 0;
		FD_ZERO(&input_fd);
		FD_SET(tt_ptr->fildes, &input_fd);
		assert(0 != FD_ISSET(tt_ptr->fildes, &input_fd));
		/* the checks for EINTR below are valid and should not be converted to EINTR
		 * wrapper macros, since the select/read is not retried on EINTR.
		 */
		save_input_timeval = input_timeval;	/* take a copy and pass it because select() below might change it */
		selstat = select(tt_ptr->fildes + 1, (void *)&input_fd, (void *)NULL, (void *)NULL, &save_input_timeval);
		if (selstat < 0)
		{
			if (EINTR != errno)
				goto term_error;
		} else if (0 == selstat)
		{
			if (timed)
			{
				ret = FALSE;
				break;
			}
			continue;	/* select() timeout; keep going */
		} else if (0 < (rdlen = read(tt_ptr->fildes, &inchar, 1)))	/* This read is protected */
		{
			assert(0 != FD_ISSET(tt_ptr->fildes, &input_fd));
			/* --------------------------------------------------
			 * set prin_in_dev_failure to FALSE to indicate that
			 * input device is working now.
			 * --------------------------------------------------
			 */
			prin_in_dev_failure = FALSE;
			if (tt_ptr->canonical)
			{
				if (0 == inchar)
				{
					/* --------------------------------------
					 * This means that the device has hungup
					 * --------------------------------------
					 */
					io_ptr->dollar.zeof = TRUE;
					io_ptr->dollar.x = 0;
					io_ptr->dollar.za = 9;
					io_ptr->dollar.y++;
					if (io_ptr->error_handler.len > 0)
						rts_error(VARLSTCNT(1) ERR_IOEOF);
					break;
				} else
					io_ptr->dollar.zeof = FALSE;
			}
			if (mask & TRM_CONVERT)
				NATIVE_CVT2UPPER(inchar, inchar);
                        GETASCII(asc_inchar,inchar);
			if ((dx >= width) && io_ptr->wrap && !(mask & TRM_NOECHO))
			{
				DOWRITE(tt_ptr->fildes, NATIVE_TTEOL, strlen(NATIVE_TTEOL));
				dx = 0;
			}
			if ((' ' > INPUT_CHAR) && (tt_ptr->enbld_outofbands.mask & (1 << INPUT_CHAR)))
			{
				outlen = 0;
				io_ptr->dollar.za = 9;
				std_dev_outbndset(INPUT_CHAR);	/* it needs ASCII?	*/
				outofband = 0;
				if (!msec_timeout)
					iott_rterm(io_ptr);
				rts_error(VARLSTCNT(3) ERR_CTRAP, 1, ctrap_action_is);
				break;
			}
			if ((0 != (mask & TRM_ESCAPE))
			     && ((NATIVE_ESC == inchar) || (START != io_ptr->esc_state)))
			{
				if (zb_ptr >= zb_top)
				{	/* $zb overflow */
					io_ptr->dollar.za = 2;
					break;
				}
				*zb_ptr++ = inchar;
				iott_escape(zb_ptr - 1, zb_ptr, io_ptr);
				*(zb_ptr - 1) = INPUT_CHAR;     /* need to store ASCII value    */
				if (FINI == io_ptr->esc_state)
					break;
				if (BADESC == io_ptr->esc_state)
				{	/* Escape sequence failed parse */
					io_ptr->dollar.za = 2;
					break;
				}
				/* --------------------------------------------------------------------
				 * In escape sequence...do not process further, but get next character
				 * --------------------------------------------------------------------
				 */
			} else
			{	/* SIMPLIFY THIS! */
				msk_num = (uint4)INPUT_CHAR / NUM_BITS_IN_INT4;
				msk_in = (1 << ((uint4)INPUT_CHAR % NUM_BITS_IN_INT4));
				if (msk_in & mask_term.mask[msk_num])
				{
					*zb_ptr++ = INPUT_CHAR;
					break;
				}
				if (((int)inchar == tt_ptr->ttio_struct->c_cc[VERASE]) && !(mask & TRM_PASTHRU))
				{
					if ((0< outlen) && (0 < dx))
					{
						outlen--;
						dx--;
						*temp--;
						if (!(mask & TRM_NOECHO))
						{
							DOWRITERC(tt_ptr->fildes, eraser, sizeof(eraser), status);
							if (0 != status)
								goto term_error;
						}
					}
				} else
				{
					if (!(mask & TRM_NOECHO))
					{
						DOWRITERC(tt_ptr->fildes, &inchar, 1, status);
						if (0 != status)
							goto term_error;
					}
					*temp++ = inchar;
					outlen++;
					dx++;
				}
			}
		} else if (0 == rdlen)
		{
			if (0 < selstat)
			{	/* this should be the only possibility */
				io_ptr->dollar.zeof = TRUE;
				io_ptr->dollar.x = 0;
				io_ptr->dollar.za = 0;
				io_ptr->dollar.y++;
				if (io_curr_device.in == io_std_device.in)
				{
					if (!prin_in_dev_failure)
						prin_in_dev_failure = TRUE;
					else
					{
                                        	send_msg(VARLSTCNT(1) ERR_NOPRINCIO);
                                        	stop_image_no_core();
					}
                                }
				if (io_ptr->dollar.zeof)
				{
					io_ptr->dollar.za = 9;
					rts_error(VARLSTCNT(1) ERR_IOEOF);
				} else
				{
					io_ptr->dollar.zeof = TRUE;
					io_ptr->dollar.za = 0;
					if (0 < io_ptr->error_handler.len)
						rts_error(VARLSTCNT(1) ERR_IOEOF);
				}
				break;
			}
			if (0 == errno)
			{	/* eof */
				io_ptr->dollar.zeof = TRUE;
				io_ptr->dollar.x = 0;
				io_ptr->dollar.za = 0;
				io_ptr->dollar.y++;
				if (0 < io_ptr->error_handler.len)
					rts_error(VARLSTCNT(1) ERR_IOEOF);
				break;
			}
		} else if (EINTR != errno)	/* rdlen < 0 */
			goto term_error;
		if (nonzerotimeout)
		{
			sys_get_curr_time(&cur_time);
			cur_time = sub_abs_time(&end_time, &cur_time);
			if (0 > cur_time.at_sec)
			{
				ret = FALSE;
				break;
			}
			input_timeval.tv_sec = cur_time.at_sec;
			input_timeval.tv_usec = cur_time.at_usec;
		}
	} while (outlen < length);
	*zb_ptr++ = 0;
	if (!msec_timeout)
	{
		iott_rterm(io_ptr);
		if (0 == outlen)
			ret = FALSE;
	}
	if (mask & TRM_READSYNC)
	{
		DOWRITERC(tt_ptr->fildes, &dc3, 1, status);
		if (0 != status)
		{
			io_ptr->dollar.za = 9;
			rts_error(VARLSTCNT(1) status);
		}
	}
	if (outofband)
	{
		v->str.len = 0;
		io_ptr->dollar.za = 9;
		return(FALSE);
	}
	v->str.len = outlen;
	v->str.addr = (char *)stringpool.free;
	if (!(mask & TRM_NOECHO))
	{
		if ((io_ptr->dollar.x += v->str.len) >= io_ptr->width && io_ptr->wrap)
		{
			io_ptr->dollar.y += (io_ptr->dollar.x / io_ptr->width);
			if (io_ptr->length)
				io_ptr->dollar.y %= io_ptr->length;
			io_ptr->dollar.x %= io_ptr->width;
			if (0 == io_ptr->dollar.x)
				DOWRITE(tt_ptr->fildes, NATIVE_TTEOL, strlen(NATIVE_TTEOL));
		}
	}
	return ((short)ret);

term_error:
	save_errno = errno;
	io_ptr->dollar.za = 9;
	if (!msec_timeout)
		iott_rterm(io_ptr);
	rts_error(VARLSTCNT(1) save_errno);
	return FALSE;
}
Пример #7
0
/*
 * ------------------------------------------
 * Hang the process for a specified time.
 *
 *	Goes to sleep for a positive value.
 *	Any caught signal will terminate the sleep
 *	following the execution of that signal's catching routine.
 *
 * Arguments:
 *	num - time to sleep
 *
 * Return:
 *	none
 * ------------------------------------------
 */
void op_hang(mval* num)
{
	int		ms;
	mv_stent	*mv_zintcmd;
	ABS_TIME	cur_time, end_time;
#	ifdef VMS
	uint4 		time[2];
	int4		efn_mask, status;
#	endif
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	ms = 0;
	MV_FORCE_NUM(num);
	if (num->mvtype & MV_INT)
	{
		if (0 < num->m[1])
		{
			assert(MV_BIAS >= 1000);	/* if formats change overflow may need attention */
			ms = num->m[1] * (1000 / MV_BIAS);
		}
	} else if (0 == num->sgn) 		/* if sign is not 0 it means num is negative */
		ms = mval2i(num) * 1000;	/* too big to care about fractional amounts */
	if (ms)
	{
		if (TREF(tpnotacidtime) * 1000 < ms)
			TPNOTACID_CHECK(HANGSTR);
#		if defined(DEBUG) && defined(UNIX)
		if (gtm_white_box_test_case_enabled
			&& (WBTEST_DEFERRED_TIMERS == gtm_white_box_test_case_number)
			&& (3 > gtm_white_box_test_case_count)
			&& (123000 == ms))
		{
			DEFER_INTERRUPTS(INTRPT_NO_TIMER_EVENTS);
			DBGFPF((stderr, "OP_HANG: will sleep for 20 seconds\n"));
			LONG_SLEEP(20);
			DBGFPF((stderr, "OP_HANG: done sleeping\n"));
			ENABLE_INTERRUPTS(INTRPT_NO_TIMER_EVENTS);
			return;
		}
		if (gtm_white_box_test_case_enabled
			&& (WBTEST_BREAKMPC == gtm_white_box_test_case_number)
			&& (0 == gtm_white_box_test_case_count)
			&& (999 == ms))
		{
			frame_pointer->old_frame_pointer->mpc = (unsigned char *)GTM64_ONLY(0xdeadbeef12345678)
				NON_GTM64_ONLY(0xdead1234);
			return;
		}
		/* Upon seeing a .999s hang this white-box test launches a timer that pops with a period of UTIL_OUT_SYSLOG_INTERVAL
		 * and prints a long message via util_out_ptr.
		 */
		if (gtm_white_box_test_case_enabled
			&& (WBTEST_UTIL_OUT_BUFFER_PROTECTION == gtm_white_box_test_case_number)
			&& (0 == gtm_white_box_test_case_count)
			&& (999 == ms))
		{
			start_timer((TID)&util_out_syslog_dump, UTIL_OUT_SYSLOG_INTERVAL, util_out_syslog_dump, 0, NULL);
			return;
		}
#		endif
		sys_get_curr_time(&cur_time);
		mv_zintcmd = find_mvstent_cmd(ZINTCMD_HANG, restart_pc, restart_ctxt, FALSE);
		if (!mv_zintcmd)
			add_int_to_abs_time(&cur_time, ms, &end_time);
		else
		{
			end_time = mv_zintcmd->mv_st_cont.mvs_zintcmd.end_or_remain;
			cur_time = sub_abs_time(&end_time, &cur_time);	/* get remaing time to sleep */
			if (0 <= cur_time.at_sec)
				ms = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000);
			else
				ms = 0;		/* all done */
			/* restore/pop previous zintcmd_active[ZINTCMD_HANG] hints */
			TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_prior;
			TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last
				= mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_ctxt_prior;
			TAREF1(zintcmd_active, ZINTCMD_HANG).count--;
			assert(0 <= TAREF1(zintcmd_active, ZINTCMD_HANG).count);
			if (mv_chain == mv_zintcmd)
				POP_MV_STENT();	/* just pop if top of stack */
			else
			{	/* flag as not active */
				mv_zintcmd->mv_st_cont.mvs_zintcmd.command = ZINTCMD_NOOP;
				mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_check = NULL;
			}
			if (0 == ms)
				return;		/* done HANGing */
		}
		UNIX_ONLY(hiber_start(ms);)
		VMS_ONLY(
			time[0] = -time_low_ms(ms);
			time[1] = -time_high_ms(ms) - 1;
			efn_mask = (1 << efn_outofband | 1 << efn_timer);
			if (SS$_NORMAL != (status = sys$setimr(efn_timer, &time, NULL, &time, 0)))
				rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$setimr"), CALLFROM, status);
			if (SS$_NORMAL != (status = sys$wflor(efn_outofband, efn_mask)))
				rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$wflor"), CALLFROM, status);
		)
		if (outofband)
Пример #8
0
/*
 * ------------------------------------------
 * Hang the process for a specified time.
 *
 *	Goes to sleep for a positive value.
 *	Any caught signal will terminate the sleep
 *	following the execution of that signal's catching routine.
 *
 * 	The actual hang duration should be NO LESS than the specified
 * 	duration for specified durations greater than .001 seconds.
 * 	Certain applications depend on this assumption.
 *
 * Arguments:
 *	num - time to sleep
 *
 * Return:
 *	none
 * ------------------------------------------
 */
void op_hang(mval* num)
{
	int		ms;
	double		tmp;
	mv_stent	*mv_zintcmd;
	ABS_TIME	cur_time, end_time;
#	ifdef VMS
	uint4 		time[2];
	int4		efn_mask, status;
#	endif
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	ms = 0;
	MV_FORCE_NUM(num);
	if (num->mvtype & MV_INT)
	{
		if (0 < num->m[1])
		{
			assert(MV_BIAS >= 1000);	/* if formats change overflow may need attention */
			ms = num->m[1] * (1000 / MV_BIAS);
		}
	} else if (0 == num->sgn) 		/* if sign is not 0 it means num is negative */
	{
		tmp = mval2double(num) * (double)1000;
		ms = ((double)MAXPOSINT4 >= tmp) ? (int)tmp : (int)MAXPOSINT4;
	}
	if (ms)
	{
		if (TREF(tpnotacidtime) * 1000 < ms)
			TPNOTACID_CHECK(HANGSTR);
#		if defined(DEBUG) && defined(UNIX)
		if (WBTEST_ENABLED(WBTEST_DEFERRED_TIMERS) && (3 > gtm_white_box_test_case_count) && (123000 == ms))
		{
			DEFER_INTERRUPTS(INTRPT_NO_TIMER_EVENTS);
			DBGFPF((stderr, "OP_HANG: will sleep for 20 seconds\n"));
			LONG_SLEEP(20);
			DBGFPF((stderr, "OP_HANG: done sleeping\n"));
			ENABLE_INTERRUPTS(INTRPT_NO_TIMER_EVENTS);
			return;
		}
		if (WBTEST_ENABLED(WBTEST_BREAKMPC)&& (0 == gtm_white_box_test_case_count) && (999 == ms))
		{
			frame_pointer->old_frame_pointer->mpc = (unsigned char *)GTM64_ONLY(0xdeadbeef12345678)
				NON_GTM64_ONLY(0xdead1234);
			return;
		}
		if (WBTEST_ENABLED(WBTEST_UTIL_OUT_BUFFER_PROTECTION) && (0 == gtm_white_box_test_case_count) && (999 == ms))
		{	/* Upon seeing a .999s hang this white-box test launches a timer that pops with a period of
		 	 * UTIL_OUT_SYSLOG_INTERVAL and prints a long message via util_out_ptr.
			 */
			start_timer((TID)&util_out_syslog_dump, UTIL_OUT_SYSLOG_INTERVAL, util_out_syslog_dump, 0, NULL);
			return;
		}
#		endif
		sys_get_curr_time(&cur_time);
		mv_zintcmd = find_mvstent_cmd(ZINTCMD_HANG, restart_pc, restart_ctxt, FALSE);
		if (!mv_zintcmd)
			add_int_to_abs_time(&cur_time, ms, &end_time);
		else
		{
			end_time = mv_zintcmd->mv_st_cont.mvs_zintcmd.end_or_remain;
			cur_time = sub_abs_time(&end_time, &cur_time);	/* get remaing time to sleep */
			if (0 <= cur_time.at_sec)
				ms = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000);
			else
				ms = 0;		/* all done */
			/* restore/pop previous zintcmd_active[ZINTCMD_HANG] hints */
			TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_prior;
			TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last
				= mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_ctxt_prior;
			TAREF1(zintcmd_active, ZINTCMD_HANG).count--;
			assert(0 <= TAREF1(zintcmd_active, ZINTCMD_HANG).count);
			if (mv_chain == mv_zintcmd)
				POP_MV_STENT();	/* just pop if top of stack */
			else
			{	/* flag as not active */
				mv_zintcmd->mv_st_cont.mvs_zintcmd.command = ZINTCMD_NOOP;
				mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_check = NULL;
			}
			if (0 == ms)
				return;		/* done HANGing */
		}
#		ifdef UNIX
		if (ms < 10)
			SLEEP_USEC(ms * 1000, TRUE);	/* Finish the sleep if it is less than 10ms. */
		else
			hiber_start(ms);
#		elif defined(VMS)
		time[0] = -time_low_ms(ms);
		time[1] = -time_high_ms(ms) - 1;
		efn_mask = (1 << efn_outofband | 1 << efn_timer);
		if (SS$_NORMAL != (status = sys$setimr(efn_timer, &time, NULL, &time, 0)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$setimr"), CALLFROM, status);
		if (SS$_NORMAL != (status = sys$wflor(efn_outofband, efn_mask)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$wflor"), CALLFROM, status);
		if (outofband)
		{
			if (SS$_WASCLR == (status = sys$readef(efn_timer, &efn_mask)))
			{
				if (SS$_NORMAL != (status = sys$cantim(&time, 0)))
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$cantim"),
						CALLFROM, status);
			} else
				assertpro(SS$_WASSET == status);
		}
#		endif
	} else
		rel_quant();
	if (outofband)
	{
		PUSH_MV_STENT(MVST_ZINTCMD);
		mv_chain->mv_st_cont.mvs_zintcmd.end_or_remain = end_time;
		mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_check = restart_ctxt;
		mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_check = restart_pc;
		/* save current information from zintcmd_active */
		mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_prior = TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last;
		mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_prior = TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last;
		TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = restart_pc;
		TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last = restart_ctxt;
		TAREF1(zintcmd_active, ZINTCMD_HANG).count++;
		mv_chain->mv_st_cont.mvs_zintcmd.command = ZINTCMD_HANG;
		outofband_action(FALSE);
	}
	return;
}
Пример #9
0
void	iosocket_tls(mval *optionmval, int4 timeoutarg, mval *tlsid, mval *password, mval *extraarg)
{	/* note extraarg is not currently used */
	int4			length, flags, timeout, msec_timeout, status, status2, len, errlen, devlen, tls_errno, save_errno;
	io_desc			*iod;
	d_socket_struct 	*dsocketptr;
	socket_struct		*socketptr;
	char			optionstr[MAX_TLSOPTION], idstr[MAX_TLSID_LEN], passwordstr[GTM_PASSPHRASE_MAX_ASCII + 1];
	const char		*errp;
	tls_option		option;
	gtm_tls_socket_t	*tlssocket;
	ABS_TIME		cur_time, end_time;
#	ifdef USE_POLL
	struct pollfd		fds;
#	else
	fd_set			fds, *readfds, *writefds;
	struct timeval		timeout_spec, *timeout_ptr;
#	endif

	iod = io_curr_device.out;
	assert(gtmsocket == iod->type);
	dsocketptr = (d_socket_struct *)iod->dev_sp;
	if (0 >= dsocketptr->n_socket)
	{
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
		return;
	}
	if (dsocketptr->n_socket <= dsocketptr->current_socket)
	{
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CURRSOCKOFR, 2, dsocketptr->current_socket, dsocketptr->n_socket);
		return;
	}
	if (dsocketptr->mupintr)
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO);
	socketptr = dsocketptr->socket[dsocketptr->current_socket];
	ENSURE_DATA_SOCKET(socketptr);
	if (socket_tcpip != socketptr->protocol)
	{
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSPARAM, 4, RTS_ERROR_MVAL(optionmval),
			LEN_AND_LIT("but socket is not TCP"));
		return;
	}
	if (socket_connected != socketptr->state)
	{
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSPARAM, 4, LEN_AND_LIT("/TLS"),
			LEN_AND_LIT("but socket not connected"));
		return;
	}
	if (NULL != tlsid)
	{
		length = tlsid->str.len;
		if (MAX_TLSID_LEN < (length + 1))	/* for null */
		{
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSPARAM, 4, LEN_AND_LIT("TLSID"), LEN_AND_LIT("too long"));
			return;
		}
		STRNCPY_STR(idstr, tlsid->str.addr, length);
		idstr[length] = '\0';
	} else
		idstr[0] = '\0';
	if (NULL != password)
	{
		length = password->str.len;
		if (GTM_PASSPHRASE_MAX_ASCII < length)
		{
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSPARAM, 4, LEN_AND_LIT("passphrase"),
				LEN_AND_LIT("too long"));
			return;
		}
		STRNCPY_STR(passwordstr, password->str.addr, length);
		passwordstr[length] = '\0';
	} else
		passwordstr[0] = '\0';
	length = MIN(MAX_TLSOPTION, optionmval->str.len);
	lower_to_upper((uchar_ptr_t)optionstr, (uchar_ptr_t)optionmval->str.addr, length);
	if (0 == memcmp(optionstr, "CLIENT", length))
		option = tlsopt_client;
	else if (0 == memcmp(optionstr, "SERVER", length))
		option = tlsopt_server;
	else if (0 == memcmp(optionstr, "RENEGOTIATE", length))
		option = tlsopt_renegotiate;
	else
		option = tlsopt_invalid;
	memcpy(iod->dollar.device, "0", SIZEOF("0"));
	if (NO_M_TIMEOUT != timeoutarg)
	{
		msec_timeout = timeout2msec(timeoutarg);
		sys_get_curr_time(&cur_time);
		add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
	} else
		msec_timeout = -1;
	if ((tlsopt_client == option) || (tlsopt_server == option))
	{	/* most of the setup is common */
		if (socketptr->tlsenabled)
		{
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSPARAM, 4, LEN_AND_STR(optionstr),
				LEN_AND_LIT("but TLS already enabled"));
			return;
		}
		assertpro((0 >= socketptr->buffered_length) && (0 >= socketptr->obuffer_length));
		if (NULL == tls_ctx)
		{	/* first use of TLS */
			if (-1 == gtm_tls_loadlibrary())
			{
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSDLLNOOPEN, 0, ERR_TEXT, 2, LEN_AND_STR(dl_err));
				return;
			}
			if (NULL == (tls_ctx = (gtm_tls_init(GTM_TLS_API_VERSION, GTMTLS_OP_INTERACTIVE_MODE))))
			{
				errp = gtm_tls_get_error();
				len = SIZEOF(ONE_COMMA) - 1;
				memcpy(iod->dollar.device, ONE_COMMA, len);
				errlen = STRLEN(errp);
				devlen = MIN((SIZEOF(iod->dollar.device) - len - 1), errlen);
				memcpy(&iod->dollar.device[len], errp, devlen + 1);
				if (devlen < errlen)
					iod->dollar.device[SIZEOF(iod->dollar.device) - 1] = '\0';
				if (socketptr->ioerror)
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSINIT, 0, ERR_TEXT, 2, errlen, errp);
				if (NO_M_TIMEOUT != timeoutarg)
					dollar_truth = FALSE;
				return;
			}
		}
		socketptr->tlsenabled = TRUE;
		flags = GTMTLS_OP_SOCKET_DEV | ((tlsopt_client == option) ? GTMTLS_OP_CLIENT_MODE : 0);
		socketptr->tlssocket = gtm_tls_socket(tls_ctx, NULL, socketptr->sd, idstr, flags);
		if (NULL == socketptr->tlssocket)
		{
			socketptr->tlsenabled = FALSE;
			errp = gtm_tls_get_error();
			len = SIZEOF(ONE_COMMA) - 1;
			memcpy(iod->dollar.device, ONE_COMMA, len);
			errlen = STRLEN(errp);
			devlen = MIN((SIZEOF(iod->dollar.device) - len - 1), errlen);
			memcpy(&iod->dollar.device[len], errp, devlen + 1);
			if (devlen < errlen)
				iod->dollar.device[SIZEOF(iod->dollar.device) - 1] = '\0';
			if (socketptr->ioerror)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSCONVSOCK, 0, ERR_TEXT, 2, errlen, errp);
			if (NO_M_TIMEOUT != timeoutarg)
				dollar_truth = FALSE;
			return;
		}
		status = 0;
#		ifndef	USE_POLL
		if (NO_M_TIMEOUT == timeoutarg)
			timeout_ptr = NULL;
		else
		{
			timeout_spec.tv_sec = msec_timeout / 1000;
			timeout_spec.tv_usec = (msec_timeout % 1000) * 1000;	/* remainder in millsecs to microsecs */
			timeout_ptr = &timeout_spec;
		}
#		endif
		do
		{
			status2 = 0;
			if (0 != status)
			{
#				ifdef USE_POLL
				fds.fd = socketptr->sd;
				fds.events = (GTMTLS_WANT_READ == status) ? POLLIN : POLLOUT;
#				else
				readfds = writefds = NULL;
				assertpro(FD_SETSIZE > socketptr->sd);
				FD_ZERO(&fds);
				FD_SET(socketptr->sd, &fds);
				writefds = (GTMTLS_WANT_WRITE == status) ? &fds : NULL;
				readfds = (GTMTLS_WANT_READ == status) ? &fds : NULL;
#				endif
				POLL_ONLY(if (-1 == (status2 = poll(&fds, 1, msec_timeout))))
				SELECT_ONLY(if (-1 == (status2 = select(socketptr->sd + 1, readfds, writefds, NULL, timeout_ptr))))
				{
					save_errno = errno;
					if (EAGAIN == save_errno)
					{
						rel_quant();	/* allow resources to become available */
						status2 = 0;	/* treat as timeout */
					} else if (EINTR == save_errno)
						status2 = 0;
				}
			} else
				status2 = 1;	/* do accept/connect first time */
			if (0 < status2)
			{
				if (tlsopt_server == option)
					status = gtm_tls_accept((gtm_tls_socket_t *)socketptr->tlssocket);
				else
					status = gtm_tls_connect((gtm_tls_socket_t *)socketptr->tlssocket);
			}
			if ((0 > status2) || ((status != 0) && ((GTMTLS_WANT_READ != status) && (GTMTLS_WANT_WRITE != status))))
			{
				if (0 != status)
				{
					tls_errno = gtm_tls_errno();
					if (0 > tls_errno)
						errp = gtm_tls_get_error();
					else
						errp = STRERROR(tls_errno);
				} else
					errp = STRERROR(save_errno);
				socketptr->tlsenabled = FALSE;
				len = SIZEOF(ONE_COMMA) - 1;
				memcpy(iod->dollar.device, ONE_COMMA, len);
				errlen = STRLEN(errp);
				devlen = MIN((SIZEOF(iod->dollar.device) - len - 1), errlen);
				memcpy(&iod->dollar.device[len], errp, devlen + 1);
				if (devlen < errlen)
					iod->dollar.device[SIZEOF(iod->dollar.device) - 1] = '\0';
				if (socketptr->ioerror)
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSHANDSHAKE, 0,
						ERR_TEXT, 2, errlen, errp);
				return;
			}
			if ((0 != status) && (0 <= status2))	/* not accepted/connected and not error */
			{	/* check for timeout if not error or want read or write */
				if ((0 != timeoutarg) && (NO_M_TIMEOUT != timeoutarg))
				{
					sys_get_curr_time(&cur_time);
					cur_time = sub_abs_time(&end_time, &cur_time);
					if (0 >= cur_time.at_sec)
					{	/* no more time */
						gtm_tls_session_close((gtm_tls_socket_t **)&socketptr->tlssocket);
						socketptr->tlsenabled = FALSE;
						dollar_truth = FALSE;
						return;
					} else
					{	/* adjust msec_timeout for poll/select */
#					ifdef	USE_POLL
						msec_timeout = (cur_time.at_sec * 1000) + (cur_time.at_usec / 1000);
#					else
						timeout_spec.tv_sec = cur_time.at_sec;
						timeout_spec.tv_usec = (gtm_tv_usec_t)cur_time.at_usec;
#					endif
					}
				} else if (0 == timeoutarg)
				{	/* only one chance */
					gtm_tls_session_close((gtm_tls_socket_t **)&socketptr->tlssocket);
					socketptr->tlsenabled = FALSE;
					dollar_truth = FALSE;
					return;
				}
				continue;
			}
		} while ((GTMTLS_WANT_READ == status) || (GTMTLS_WANT_WRITE == status));
		/* turn on output buffering */
		if (0 == socketptr->obuffer_size)
			socketptr->obuffer_size = socketptr->buffer_size;
		socketptr->obuffer_length = socketptr->obuffer_offset = 0;
		socketptr->obuffer_wait_time = DEFAULT_WRITE_WAIT;
		socketptr->obuffer_flush_time = DEFAULT_WRITE_WAIT * 2;	/* until add device parameter */
		socketptr->obuffer = malloc(socketptr->obuffer_size);
	} else if (tlsopt_renegotiate == option)
Пример #10
0
boolean_t iosocket_connect(socket_struct *socketptr, int4 timepar, boolean_t update_bufsiz)
{
	int		temp_1 = 1;
	char		*errptr;
	int4            errlen, msec_timeout, real_errno;
	boolean_t	no_time_left = FALSE;
	short		len;
	d_socket_struct *dsocketptr;
	ABS_TIME        cur_time, end_time;

	error_def(ERR_SOCKINIT);
	error_def(ERR_OPENCONN);
	error_def(ERR_TEXT);
	error_def(ERR_GETSOCKOPTERR);
	error_def(ERR_SETSOCKOPTERR);
	dsocketptr = socketptr->dev;
        assert(NULL != dsocketptr);
        dsocketptr->dollar_key[0] = '\0';
	if (timepar != NO_M_TIMEOUT)
	{
		msec_timeout = timeout2msec(timepar);
		sys_get_curr_time(&cur_time);
		add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
	}
	do
	{
		if (1 != temp_1)
		{
			tcp_routines.aa_close(socketptr->sd);
		}
	        if (-1 == (socketptr->sd = tcp_routines.aa_socket(AF_INET, SOCK_STREAM, 0)))
        	{
                	errptr = (char *)STRERROR(errno);
                	errlen = strlen(errptr);
                	rts_error(VARLSTCNT(5) ERR_SOCKINIT, 3, errno, errlen, errptr);
                	return FALSE;
        	}
		temp_1 = 1;
		if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				SOL_SOCKET, SO_REUSEADDR, &temp_1, sizeof(temp_1)))
        	{
                	errptr = (char *)STRERROR(errno);
                	errlen = strlen(errptr);
                	rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("SO_REUSEADDR"), errno, errlen, errptr);
                	return FALSE;
        	}
#ifdef TCP_NODELAY
		temp_1 = socketptr->nodelay ? 1 : 0;
		if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				IPPROTO_TCP, TCP_NODELAY, &temp_1, sizeof(temp_1)))
        	{
                	errptr = (char *)STRERROR(errno);
                	errlen = strlen(errptr);
                	rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("TCP_NODELAY"), errno, errlen, errptr);
                	return FALSE;
        	}
#endif
		if (update_bufsiz)
		{
			if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, sizeof(socketptr->bufsiz)))
			{
				errptr = (char *)STRERROR(errno);
         			errlen = strlen(errptr);
                		rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("SO_RCVBUF"), errno, errlen, errptr);
				return FALSE;
			}
		}
		else
		{
			temp_1 = sizeof(socketptr->bufsiz);
			if (-1 == tcp_routines.aa_getsockopt(socketptr->sd,
				SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, &temp_1))
			{
				errptr = (char *)STRERROR(errno);
         			errlen = strlen(errptr);
                		rts_error(VARLSTCNT(7) ERR_GETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("SO_RCVBUF"), errno, errlen, errptr);
				return FALSE;
			}
		}
		temp_1 = tcp_routines.aa_connect(socketptr->sd,
				(struct sockaddr *)&socketptr->remote.sin, sizeof(socketptr->remote.sin));
		if (temp_1 < 0)
		{
			real_errno = errno;
			no_time_left = TRUE;
			switch (real_errno)
			{
			case ETIMEDOUT	:	/* the other side bound but not listening */
			case ECONNREFUSED :
				if (NO_M_TIMEOUT != timepar)
				{
					sys_get_curr_time(&cur_time);
					cur_time = sub_abs_time(&end_time, &cur_time);
					if (cur_time.at_sec > 0)
						no_time_left = FALSE;
				}
				break;
			case EINTR :
				break;
			default:
				errptr = (char *)STRERROR(real_errno);
				errlen = strlen(errptr);
				rts_error(VARLSTCNT(6) ERR_OPENCONN, 0, ERR_TEXT, 2, errlen, errptr);
				break;
			}
			if (no_time_left)
			{
				return FALSE;
			}
			hiber_start(100);
		}
	} while (temp_1 < 0);
	/* handle the local information later.
	SPRINTF(socketptr->local.saddr_ip, "%s", tcp_routines.aa_inet_ntoa(socketptr->remote.sin.sin_addr));
	socketptr->local.port = GTM_NTOHS(socketptr->remote.sin.sin_port);
	*/
	socketptr->state = socket_connected;
	/* update dollar_key */
        len = sizeof(ESTABLISHED) - 1;
        memcpy(&dsocketptr->dollar_key[0], ESTABLISHED, len);
        dsocketptr->dollar_key[len++] = '|';
        memcpy(&dsocketptr->dollar_key[len], socketptr->handle, socketptr->handle_len);
        len += socketptr->handle_len;
        dsocketptr->dollar_key[len++] = '|';
	memcpy(&dsocketptr->dollar_key[len], socketptr->remote.saddr_ip, strlen(socketptr->remote.saddr_ip));
	len += strlen(socketptr->remote.saddr_ip);
	dsocketptr->dollar_key[len] = '\0';
	return TRUE;
}
Пример #11
0
short	iotcp_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4 timeout)
{
	boolean_t		no_time_left = FALSE, timed;
	char			addr[SA_MAXLEN+1], *errptr, sockaddr[SA_MAXLEN+1],
				temp_addr[SA_MAXLEN+1], temp_ch;
	unsigned char		ch, len;
	int4			length, width;
	unsigned short		port;
	int4			errlen, msec_timeout;
	int			ii, status, size,
				on = 1,
				p_offset = 0,
				temp_1 = -2;
	TID			timer_id;
	ABS_TIME		cur_time, end_time, time_for_read, save_time_for_read;
	d_tcp_struct		*tcpptr, newtcp;
	io_desc			*ioptr;
	struct sockaddr_in	peer;		/* socket address + port */
	fd_set			tcp_fd;
	int			lsock;

	error_def(ERR_DEVPARMNEG);
	error_def(ERR_INVADDRSPEC);
	error_def(ERR_INVPORTSPEC);
	error_def(ERR_IPADDRREQ);
	error_def(ERR_OPENCONN);
	error_def(ERR_SOCKACPT);
	error_def(ERR_SOCKINIT);
	error_def(ERR_SOCKPARMREQ);
	error_def(ERR_SOCKWAIT);
	error_def(ERR_TEXT);

#ifdef	DEBUG_TCP
	PRINTF("iotcp_open.c >>>   tt = %d\n", t);
#endif
	ioptr = dev->iod;
	assert((params) *(pp->str.addr + p_offset) < (unsigned char)n_iops);
	assert(0 != ioptr);
	assert(ioptr->state >= 0 && ioptr->state < n_io_dev_states);
	assert(tcp == ioptr->type);
	if (dev_never_opened == ioptr->state)
	{
		ioptr->dev_sp = (void *)malloc(sizeof(d_tcp_struct));
		memset(ioptr->dev_sp, 0, sizeof(d_tcp_struct));
	}
	tcpptr = (d_tcp_struct *)ioptr->dev_sp;
	if (dev_never_opened == ioptr->state)
	{
		ioptr->state	= dev_closed;
		ioptr->width	= TCPDEF_WIDTH;
		ioptr->length	= TCPDEF_LENGTH;
		ioptr->wrap	= TRUE;
		if (-1 == iotcp_fillroutine())
			assert(FALSE);
	}
	ioptr->dollar.zeof = FALSE;
	newtcp = *tcpptr;
	memcpy(newtcp.dollar_device, LITZERO, sizeof(LITZERO));
	newtcp.passive = FALSE;
	while (iop_eol != *(pp->str.addr + p_offset))
	{
		switch	(ch = *(pp->str.addr + p_offset++))
		{
		case	iop_width:
			GET_LONG(width, pp->str.addr + p_offset);
			if (0 == width)
				newtcp.width = TCPDEF_WIDTH;
			else if (width > 0)
				newtcp.width = width;
			else
				rts_error(VARLSTCNT(1)	ERR_DEVPARMNEG);
			break;
		case	iop_length:
			GET_LONG(length, pp->str.addr + p_offset);
			if (0 == length)
				newtcp.length = TCPDEF_LENGTH;
			else if (length > 0)
				newtcp.length = length;
			else
				rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
			break;
		case	iop_listen:
			newtcp.passive = TRUE;
			break;
		case	iop_socket:
			len = *(pp->str.addr + p_offset);
			memset(sockaddr, 0, SA_MAXLEN+1);
			memcpy(sockaddr, pp->str.addr + p_offset + 1, (len <= SA_MAXLEN) ? len : SA_MAXLEN);
			*temp_addr = '\0';
			*addr = '\0';
			port = 0;
			if (SSCANF(sockaddr, "%[^,], %hu", temp_addr, &port) < 2)
			{
				newtcp.sin.sin_addr.s_addr = INADDR_ANY;
				if (SSCANF(sockaddr, ",%hu", &port) < 1)
				{
					rts_error(VARLSTCNT(1) ERR_INVPORTSPEC);
					return	FALSE;
				}
			} else
			{
				ii = 0;
				temp_ch = temp_addr[0];
				while(ISDIGIT(temp_ch) || ('.' == temp_ch))
				{
					ii++;
					temp_ch = temp_addr[ii];
				}
				if ('\0' != temp_ch)
					SPRINTF(addr, "%s", iotcp_name2ip(temp_addr));
				else
					SPRINTF(addr, "%s", temp_addr);
				if ((in_addr_t)-1 == (newtcp.sin.sin_addr.s_addr = tcp_routines.aa_inet_addr(addr)))
				{
					rts_error(VARLSTCNT(1) ERR_INVADDRSPEC);
					return	FALSE;
				}
			}
			newtcp.sin.sin_port = GTM_HTONS(port);
			newtcp.sin.sin_family = AF_INET;
			break;
		case	iop_exception:
			ioptr->error_handler.len = *(pp->str.addr + p_offset);
			ioptr->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
			s2pool(&ioptr->error_handler);
			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 ((0 == newtcp.sin.sin_port) && (0 == newtcp.sin.sin_addr.s_addr))
	{
		rts_error(VARLSTCNT(1) ERR_SOCKPARMREQ);
		return	FALSE;
	}
	/* active connection must have a complete address specification */
	if ((INADDR_ANY == newtcp.sin.sin_addr.s_addr) && !newtcp.passive)
	{
		rts_error(VARLSTCNT(1) ERR_IPADDRREQ);
		return FALSE;
	}
	if (dev_closed == ioptr->state)
	{
		if (newtcp.passive)		/* passive connection */
		{
			/* no listening socket for this addr?  make one. */
			memcpy(ioptr->dev_sp, &newtcp, sizeof(d_tcp_struct));
			if (!(lsock = iotcp_getlsock(dev)))
				return	FALSE;	/* could not create listening socket */
			timer_id = (TID)iotcp_open;
			out_of_time = FALSE;
			time_for_read.at_sec = ((NO_M_TIMEOUT == timeout) ? 0 : 1);
			time_for_read.at_usec = 0;
			if (NO_M_TIMEOUT == timeout)
			{
				timed = FALSE;
				msec_timeout = NO_M_TIMEOUT;
			} else
			{
				timed = TRUE;
				msec_timeout = timeout2msec(timeout);
				if (msec_timeout > 0)
				{       /* there is time to wait */
					sys_get_curr_time(&cur_time);
					add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
					start_timer(timer_id, msec_timeout, wake_alarm, 0, NULL);
				} else
					out_of_time = TRUE;
			}
			for (status = 0; 0 == status; )
			{
				FD_ZERO(&tcp_fd);
				FD_SET(lsock, &tcp_fd);
				/*
				 * Note: the check for EINTR from the select below should remain, as aa_select is a
				 * function, and not all callers of aa_select behave the same when EINTR is returned.
				 */
                                save_time_for_read = time_for_read;
				status = tcp_routines.aa_select(lsock + 1, (void *)&tcp_fd, (void *)0, (void *)0, &time_for_read);
                                time_for_read = save_time_for_read;
				if (0 > status)
				{
					if (EINTR == errno && FALSE == out_of_time)
						/* interrupted by a signal which is not OUR timer */
						status = 0;
					else
						break;
				}
				if (outofband)
                        		break;
				if (timed)
				{
					if (msec_timeout > 0)
					{
						sys_get_curr_time(&cur_time);
						cur_time = sub_abs_time(&end_time, &cur_time);
						if (cur_time.at_sec <= 0)
						{
							out_of_time = TRUE;
							cancel_timer(timer_id);
							break;
						}
					} else
						break;
				}
#ifdef __linux__
				time_for_read.at_sec = ((NO_M_TIMEOUT == timeout) ? 0 : 1);
				time_for_read.at_usec = 0;
#endif
			}
			if (timed)
			{
				if (0 != msec_timeout)
				{
					cancel_timer(timer_id);
					if (out_of_time || outofband)
						return FALSE;
					/*if (outofband)
						outofband_action(FALSE);*/
				}
			}
			if (0 > status)
			{
				errptr = (char *)STRERROR(errno);
				errlen = strlen(errptr);
				iotcp_rmlsock((io_desc *)dev->iod);
				rts_error(VARLSTCNT(6) ERR_SOCKWAIT, 0, ERR_TEXT, 2, errlen, errptr);
				return FALSE;
			}
			size = sizeof(struct sockaddr_in);
			status = tcp_routines.aa_accept(lsock, &peer, &size);
			if (-1 == status)
			{
				errptr = (char *)STRERROR(errno);
				errlen = strlen(errptr);
				iotcp_rmlsock((io_desc *)dev->iod);
				rts_error(VARLSTCNT(6) ERR_SOCKACPT, 0, ERR_TEXT, 2, errlen, errptr);
				return FALSE;
			}
			SPRINTF(newtcp.saddr, "%s,%d", tcp_routines.aa_inet_ntoa(peer.sin_addr),
				GTM_NTOHS(newtcp.sin.sin_port));
			newtcp.socket = status;
		} else			/*	active connection */
		{
			if (NO_M_TIMEOUT != timeout)
			{
				msec_timeout = timeout2msec(timeout);
				sys_get_curr_time(&cur_time);
				add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
			}
			no_time_left = FALSE;
			temp_1 = 1;
			do
			{
				if(1 != temp_1)
					tcp_routines.aa_close(newtcp.socket);
				newtcp.socket = tcp_routines.aa_socket(AF_INET, SOCK_STREAM, 0);
				if (-1 == newtcp.socket)
				{
					errptr = (char *)STRERROR(errno);
					errlen = strlen(errptr);
					rts_error(VARLSTCNT(5) ERR_SOCKINIT, 3, errno, errlen, errptr);
					return FALSE;
				}
				/*	allow multiple connections to the same IP address */
				if	(-1 == tcp_routines.aa_setsockopt(newtcp.socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
				{
					(void)tcp_routines.aa_close(newtcp.socket);
					errptr = (char *)STRERROR(errno);
					errlen = strlen(errptr);
					rts_error(VARLSTCNT(5) ERR_SOCKINIT, 3, errno, errlen, errptr);
					return FALSE;
				}
				size=sizeof(newtcp.bufsiz);
				if (-1 == tcp_routines.aa_getsockopt(newtcp.socket, SOL_SOCKET, SO_RCVBUF, &newtcp.bufsiz, &size))
				{
					(void)tcp_routines.aa_close(newtcp.socket);
					errptr = (char *)STRERROR(errno);
					errlen = strlen(errptr);
					rts_error(VARLSTCNT(5) ERR_SOCKINIT, 3, errno, errlen, errptr);
					return FALSE;
				}
				/*
				 * Note: the check for EINTR from the connect need not be converted to an EINTR wrapper macro,
				 * since the connect is not retried on EINTR.
				 */
				temp_1 = tcp_routines.aa_connect(newtcp.socket, (struct sockaddr *)&newtcp.sin, sizeof(newtcp.sin));
				if ((temp_1 < 0) && (ECONNREFUSED != errno) && (EINTR != errno))
				{
					(void)tcp_routines.aa_close(newtcp.socket);
					errptr = (char *)STRERROR(errno);
					errlen = strlen(errptr);
					rts_error(VARLSTCNT(6) ERR_OPENCONN, 0, ERR_TEXT, 2, errlen, errptr);
					return FALSE;
				}
				if ((temp_1 < 0) && (EINTR == errno))
				{
					(void)tcp_routines.aa_close(newtcp.socket);
					return FALSE;
				}
				if ((temp_1 < 0) && (NO_M_TIMEOUT != timeout))
				{
					sys_get_curr_time(&cur_time);
					cur_time = sub_abs_time(&end_time, &cur_time);
					if (cur_time.at_sec <= 0)
						no_time_left = TRUE;
				}
				SHORT_SLEEP(100);		/* Sleep for 100 ms */
			}
			while ((TRUE != no_time_left) && (temp_1 < 0));
			if (temp_1 < 0) /* out of time */
			{
				tcp_routines.aa_close(newtcp.socket);
				return FALSE;
			}
#ifdef	ntohs	/* if it's a macro, use it instead of tcp_routines.aa_ntohs */
			SPRINTF(newtcp.saddr, "%s,%d", tcp_routines.aa_inet_ntoa(newtcp.sin.sin_addr),
				ntohs(newtcp.sin.sin_port));
#else
			SPRINTF(newtcp.saddr, "%s,%d", tcp_routines.aa_inet_ntoa(newtcp.sin.sin_addr),
				tcp_routines.aa_ntohs(newtcp.sin.sin_port));
#endif
		}
		memcpy(ioptr->dev_sp, &newtcp, sizeof(d_tcp_struct));
		ioptr->state = dev_open;
	}
#ifdef	DEBUG_TCP
	PRINTF("%s (%d) <<<\n", __FILE__, tcpptr->socket);
#endif
	return TRUE;
}
Пример #12
0
bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mval *mspace)
{
	char		buf1[MAX_TRANS_NAME_LEN];	/* buffer to hold translated name */
	char		dev_type[MAX_DEV_TYPE_LEN];
        int             n;
	mstr		tn;				/* translated name */
	uint4		stat;				/* status */
	int		p_offset;
	unsigned char	ch;
	ABS_TIME	cur_time, end_time;
	bool		out_of_time = FALSE;

	if (0 == naml->iod)
	{
		if (0 == tl->iod)
		{
			tl->iod = (io_desc *)malloc(SIZEOF(io_desc));
			memset((char*)tl->iod, 0, SIZEOF(io_desc));
			tl->iod->pair.in  = tl->iod;
			tl->iod->pair.out = tl->iod;
			tl->iod->trans_name = tl;
			p_offset = 0;
			while (iop_eol != *(pp->str.addr + p_offset))
			{
				if ((iop_tmpmbx == (ch = *(pp->str.addr + p_offset++))) || (iop_prmmbx == ch))
					tl->iod->type = mb;
				else  if (iop_nl == ch)
					tl->iod->type = nl;
				p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
					(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
			}
			if (!tl->iod->type && mspace && mspace->str.len)
			{
				lower_to_upper(dev_type, mspace->str.addr, mspace->str.len);
				if (((SIZEOF("SOCKET") - 1) == mspace->str.len)
					&& (0 == memcmp(dev_type, LIT_AND_LEN("SOCKET"))))
					tl->iod->type = gtmsocket;
				else
					tl->iod->type = us;
			}
			if (!tl->iod->type)
			{
				tn.len = tl->len;
				tn.addr = &tl->dollar_io;
				tl->iod->type = io_type(&tn);
			}
		}
		naml->iod = tl->iod;
	}
	tl->iod->disp_ptr = &io_dev_dispatch[tl->iod->type];
	assert(0 != naml->iod);
	active_device = naml->iod;
	if (dev_never_opened == naml->iod->state)
	{
		naml->iod->wrap = DEFAULT_IOD_WRAP;
		naml->iod->width = DEFAULT_IOD_WIDTH;
		naml->iod->length = DEFAULT_IOD_LENGTH;
		naml->iod->write_filter = write_filter;
	}
	if (dev_open != naml->iod->state)
	{
		naml->iod->dollar.x = 0;
		naml->iod->dollar.y = 0;
		naml->iod->dollar.za = 0;
		naml->iod->dollar.zb[0] = 0;
		naml->iod->dollar.zeof = FALSE;
	}
	if (0 == timeout)
		stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout);	/* ZY: add a parameter timeout */
	else  if (NO_M_TIMEOUT == timeout)
	{
		while (FALSE == (stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout)))	/* ZY: add timeout */
		{
			hiber_start(1000);	/* 1 second */
			if (outofband)
				outofband_action(FALSE);
		}
	} else
	{
		sys_get_curr_time(&cur_time);
		add_int_to_abs_time(&cur_time, timeout * 1000, &end_time);
		while (FALSE == (stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout))	/* ZY: add timeout */
			&& (!out_of_time))
		{
			hiber_start(1000);	/* 1 second */
			if (outofband)
				outofband_action(FALSE);
			sys_get_curr_time(&cur_time);
			if (abs_time_comp(&end_time, &cur_time) <= 0)
				out_of_time = TRUE;
		}
	}
	if (TRUE == stat)
	{
		naml->iod->state = dev_open;
		if (27 == naml->iod->trans_name->dollar_io[0])
		{
			tn.addr = &naml->iod->trans_name->dollar_io[4];
			n = naml->iod->trans_name->len - 4;
			if (n < 0)
				n = 0;
			tn.len = n;
			naml->iod->trans_name = get_log_name(&tn, INSERT);
			naml->iod->trans_name->iod = naml->iod;
		}
	}
	else
	{
		if (dev_open == naml->iod->state && (gtmsocket != naml->iod->type))
			naml->iod->state = dev_closed;
		else if ((gtmsocket == naml->iod->type) && naml->iod->newly_created)
		{
			assert(naml->iod->state != dev_open);
			iosocket_destroy(naml->iod);
		}
	}
	active_device = 0;
	if ((NO_M_TIMEOUT != timeout) && IS_MCODE_RUNNING)
		return (stat);
	return FALSE;
}
Пример #13
0
int tcp_open(char *host, unsigned short port, int4 timeout, boolean_t passive) /* host needs to be NULL terminated */
{
	boolean_t		no_time_left = FALSE, error_given = FALSE;
	char			temp_addr[SA_MAXLEN + 1], addr[SA_MAXLEN + 1];
	char 			*from, *to, *errptr, *temp_ch;
	char			ipname[SA_MAXLEN];
	int			match, sock, sendbufsize, ii, on = 1, temp_1 = -2;
	GTM_SOCKLEN_TYPE	size;
	int4                    rv, msec_timeout;
	struct addrinfo		*ai_ptr = NULL, *remote_ai_ptr = NULL, *remote_ai_head, hints;
	char			port_buffer[NI_MAXSERV], *brack_pos;

	int			host_len, addr_len, port_len;
	char                    msg_buffer[1024];
	mstr                    msg_string;
	ABS_TIME                cur_time, end_time;
	fd_set                  tcp_fd;
	struct sockaddr_storage peer;
	short 			retry_num;
	int 			save_errno, errlen;
	const char		*terrptr;
	int			errcode;
	boolean_t		af;

	msg_string.len = SIZEOF(msg_buffer);
	msg_string.addr = msg_buffer;
	/* ============================= initialize structures ============================== */
	if (NULL != host)
	{
		host_len = strlen(host);
		if ('[' == host[0])
		{
			brack_pos = memchr(host, ']', SA_MAXLEN);
			if (NULL == brack_pos || (&host[1] == brack_pos))
			{
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC);
				return -1;
			}
			addr_len = brack_pos - &(host[1]);
			memcpy(addr, &host[1], addr_len);
			if ('\0' != *(brack_pos + 1))
			{	/* not allowed to have special symbols other than [ and ] */
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC);
				return -1;
			}
		} else
		{	/* IPv4 address only */
			addr_len = strlen(host);
			if (0 == addr_len)
			{
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC);
				return -1;
			}
			memcpy(addr, &host[0], addr_len);
		}
		addr[addr_len] = '\0';
		CLIENT_HINTS(hints);
		port_len = 0;
		I2A(port_buffer, port_len, port);
		port_buffer[port_len]='\0';
		if (0  != (errcode = getaddrinfo(addr, port_buffer, &hints, &remote_ai_head)))
		{
			RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode);
			return -1;
		}
	}

	/* ============================== do the connection ============================== */
	if (passive)
	{
		struct timeval  utimeout, save_utimeout;
		int 		lsock;

		af = ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET);
		lsock = socket(af, SOCK_STREAM, IPPROTO_TCP);
		if (-1 == lsock)
		{
			af = AF_INET;
			if (-1 == (lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
			{
				save_errno = errno;
				errptr = (char *)STRERROR(save_errno);
        	 		errlen = STRLEN(errptr);
				gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, save_errno, errlen, errptr);
				assert(FALSE);
				return -1;
			}
		}
		SERVER_HINTS(hints, af);
		/* We can only listen on our own system */
		port_len = 0;
		I2A(port_buffer, port_len, port);
		port_buffer[port_len]='\0';
		if (0 != (errcode = getaddrinfo(NULL, port_buffer, &hints, &ai_ptr)))
		{
			RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode);
			return -1;

		}
		/* allow multiple connections to the same IP address */
		if (-1 == setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, SIZEOF(on)))
		{
			save_errno = errno;
			(void)close(lsock);
			errptr = (char *)STRERROR(save_errno);
         		errlen = STRLEN(errptr);
                	gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
					LEN_AND_LIT("SO_REUSEADDR"), save_errno, errlen, errptr);
			assert(FALSE);
			return -1;
		}
		if (-1 == bind(lsock, ai_ptr->ai_addr, ai_ptr->ai_addrlen))
		{
			save_errno = errno;
			(void)close(lsock);
			gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
				   LEN_AND_LIT("bind()"), CALLFROM, save_errno);
			return -1;
		}
		freeaddrinfo(ai_ptr);
		/* establish a queue of length MAX_CONN_PENDING for incoming connections */
		if (-1 == listen(lsock, MAX_CONN_PENDING))
		{
			save_errno = errno;
			(void)close(lsock);
			errptr = (char *)STRERROR(save_errno);
			errlen = STRLEN(errptr);
			gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKLISTEN, 0, ERR_TEXT, 2, errlen, errptr);
			assert(FALSE);
			return -1;
		}
		if (NO_M_TIMEOUT != timeout)
		{
			msec_timeout = timeout2msec(timeout);
			sys_get_curr_time(&cur_time);
			add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
			utimeout.tv_sec = timeout;
			utimeout.tv_usec = 0;
		}
		assertpro(FD_SETSIZE > lsock);
		FD_ZERO(&tcp_fd);
		while (TRUE)
		{
			while (TRUE)
			{
				/* The check for EINTR below is valid and should not be converted to an EINTR wrapper macro
				 * since it might be a timeout.
				 */
				FD_SET(lsock, &tcp_fd);
                                save_utimeout = utimeout;
				rv = select(lsock + 1, (void *)&tcp_fd, (void *)0, (void *)0,
					(NO_M_TIMEOUT == timeout) ? (struct timeval *)0 : &utimeout);
				save_errno = errno;
                                utimeout = save_utimeout;
				if ((0 <= rv) || (EINTR != save_errno))
					break;
				if (NO_M_TIMEOUT != timeout)
				{
					sys_get_curr_time(&cur_time);
					cur_time = sub_abs_time(&end_time, &cur_time);
					if (0 >= (utimeout.tv_sec = cur_time.at_sec))
					{
						rv = 0;
						break;
					}
				}
			}
			if (0 == rv)
			{
				(void)close(lsock);
				util_out_print("Listening timed out.\n", TRUE);
				assert(FALSE);
				return -1;
			} else  if (0 > rv)
			{
				(void)close(lsock);
				gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
					   LEN_AND_LIT("select()"), CALLFROM, save_errno);
				assert(FALSE);
				return -1;
			}
			size = SIZEOF(struct sockaddr_storage);
			ACCEPT_SOCKET(lsock, (struct sockaddr*)(&peer), &size, sock);
			if (FD_INVALID == sock)
			{
				save_errno = errno;
#				ifdef __hpux
				if (ENOBUFS == save_errno)
					continue;
#				endif
				(void)close(lsock);
				errptr = (char *)STRERROR(save_errno);
				errlen = STRLEN(errptr);
				gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKACPT, 0, ERR_TEXT, 2, errlen, errptr);
				assert(FALSE);
				return -1;
			}
			GETNAMEINFO((struct sockaddr*)(&peer), size, temp_addr, SA_MAXLEN + 1, NULL, 0, NI_NUMERICHOST, errcode);
			if (0 != errcode)
			{
				RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
				return -1;
			}
#			ifdef	DEBUG_ONLINE
			PRINTF("Connection is from : %s\n", &temp_addr[0]);
#			endif
			break;
			/* previously there is following check here
			 * if ((0 == temp_sin_addr) || (0 == memcmp(&addr[0], &temp_addr[0], strlen(addr))))
                         * However, temp_sin_addr is always 0 on server side, and addr(local address) shoud not equal to
			 * temp_addr(remote address), so the entire check should be removed
			 */
		}
		(void)close(lsock);
	} else
	{	/* client side (connection side) */
		if (NO_M_TIMEOUT != timeout)
Пример #14
0
boolean_t iosocket_wait(io_desc *iod, int4 timepar)
{
	struct 	timeval  	utimeout;
	ABS_TIME		cur_time, end_time;
	struct 	sockaddr_in     peer;           /* socket address + port */
        fd_set    		tcp_fd;
        d_socket_struct 	*dsocketptr;
        socket_struct   	*socketptr, *newsocketptr;
        char            	*errptr;
        int4            	errlen, ii, msec_timeout;
	int			rv, size, max_fd;
	short			len;
        error_def(ERR_SOCKACPT);
        error_def(ERR_SOCKWAIT);
        error_def(ERR_TEXT);
	/* check for validity */
        assert(iod->type == gtmsocket);
        dsocketptr = (d_socket_struct *)iod->dev_sp;
	/* check for events */
	max_fd = 0;
	FD_ZERO(&tcp_fd);
	for (ii = 0; ii < dsocketptr->n_socket; ii++)
	{
		socketptr = dsocketptr->socket[ii];
		if ((socket_listening == socketptr->state) || (socket_connected == socketptr->state))
		{
			FD_SET(socketptr->sd, &tcp_fd);
			max_fd = MAX(max_fd, socketptr->sd);
		}
	}
	utimeout.tv_sec = timepar;
	utimeout.tv_usec = 0;
	msec_timeout = timeout2msec(timepar);
	sys_get_curr_time(&cur_time);
	add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
	for ( ; ; )
	{
		rv = tcp_routines.aa_select(max_fd + 1, (void *)&tcp_fd, (void *)0, (void *)0,
			(timepar == NO_M_TIMEOUT ? (struct timeval *)0 : &utimeout));
		if (0 > rv && EINTR == errno)
		{
			if (OUTOFBANDNOW(outofband))
			{
				rv = 0;		/* treat as time out */
				break;
			}
			sys_get_curr_time(&cur_time);
			cur_time = sub_abs_time(&end_time, &cur_time);
			if (0 > cur_time.at_sec)
			{
				rv = 0;		/* time out */
				break;
			}
			utimeout.tv_sec = cur_time.at_sec;
			utimeout.tv_usec = cur_time.at_usec;
		}
		else
			break;	/* either other error or done */
	}
	if (rv == 0)
	{
		dsocketptr->dollar_key[0] = '\0';
		return FALSE;
	}
	else  if (rv < 0)
	{
		errptr = (char *)STRERROR(errno);
		errlen = strlen(errptr);
		rts_error(VARLSTCNT(6) ERR_SOCKWAIT, 0, ERR_TEXT, 2, errlen, errptr);
		return FALSE;
	}
	/* find out which socket is ready */
	for (ii = 0; ii < dsocketptr->n_socket; ii++)
	{
		socketptr = dsocketptr->socket[ii];
		if (0 != FD_ISSET(socketptr->sd, &tcp_fd))
			break;
	}
	assert(ii < dsocketptr->n_socket);
	if (socket_listening == socketptr->state)
	{
		size = sizeof(struct sockaddr_in);
		rv = tcp_routines.aa_accept(socketptr->sd, &peer, &size);
		if (rv == -1)
		{
			errptr = (char *)STRERROR(errno);
			errlen = strlen(errptr);
			rts_error(VARLSTCNT(6) ERR_SOCKACPT, 0, ERR_TEXT, 2, errlen, errptr);
			return FALSE;
		}
		/* got the connection, create a new socket in the device socket list */
		newsocketptr = (socket_struct *)malloc(sizeof(socket_struct));
		*newsocketptr = *socketptr;
		newsocketptr->sd = rv;
		memcpy(&newsocketptr->remote.sin, &peer, sizeof(struct sockaddr_in));
		SPRINTF(newsocketptr->remote.saddr_ip, "%s", tcp_routines.aa_inet_ntoa(peer.sin_addr));
		newsocketptr->remote.port = GTM_NTOHS(peer.sin_port);
		newsocketptr->state = socket_connected;
		newsocketptr->passive = FALSE;
		for (ii = 0; ii < newsocketptr->n_delimiter; ii++)
		{
			newsocketptr->delimiter[ii].addr = (char *)malloc(socketptr->delimiter[ii].len);
			memcpy(newsocketptr->delimiter[ii].addr, socketptr->delimiter[ii].addr, socketptr->delimiter[ii].len);
		}
		newsocketptr->buffer = (char *)malloc(socketptr->buffer_size);
		newsocketptr->buffer_size = socketptr->buffer_size;
		newsocketptr->buffered_length = socketptr->buffered_offset = 0;
		/* put the new-born socket to the list and create a handle for it */
		iosocket_handle(newsocketptr->handle, &newsocketptr->handle_len, TRUE, dsocketptr);
		dsocketptr->socket[dsocketptr->n_socket++] = newsocketptr;
		dsocketptr->current_socket = dsocketptr->n_socket - 1;
		len = sizeof(CONNECTED) - 1;
		memcpy(&dsocketptr->dollar_key[0], CONNECTED, len);
		dsocketptr->dollar_key[len++] = '|';
		memcpy(&dsocketptr->dollar_key[len], newsocketptr->handle, newsocketptr->handle_len);
		len += newsocketptr->handle_len;
		dsocketptr->dollar_key[len++] = '|';
		memcpy(&dsocketptr->dollar_key[len], newsocketptr->remote.saddr_ip, strlen(newsocketptr->remote.saddr_ip));
		len += strlen(newsocketptr->remote.saddr_ip);
		dsocketptr->dollar_key[len] = '\0';
	}
	else
	{
		assert(socket_connected == socketptr->state);
		dsocketptr->current_socket = ii;
		len = sizeof(READ) - 1;
		memcpy(&dsocketptr->dollar_key[0], READ, len);
		dsocketptr->dollar_key[len++] = '|';
		memcpy(&dsocketptr->dollar_key[len], socketptr->handle, socketptr->handle_len);
                len += socketptr->handle_len;
                dsocketptr->dollar_key[len++] = '|';
                memcpy(&dsocketptr->dollar_key[len], socketptr->remote.saddr_ip, strlen(socketptr->remote.saddr_ip));
                len += strlen(socketptr->remote.saddr_ip);
                dsocketptr->dollar_key[len] = '\0';
	}
	return TRUE;
}
Пример #15
0
int tcp_open(char *host, unsigned short port, int4 timeout, boolean_t passive) /* host needs to be NULL terminated */
{
	boolean_t		no_time_left = FALSE, error_given = FALSE;
	char			temp_addr[SA_MAXLEN + 1], addr[SA_MAXLEN + 1];
	char 			*from, *to, *errptr, *temp_ch;
	int			match, sock, sendbufsize, size, ii, on = 1, temp_1 = -2;
	int4                    errlen, rv, msec_timeout;
	struct	sockaddr_in	sin;
	in_addr_t		temp_sin_addr;
	char                    msg_buffer[1024];
	mstr                    msg_string;
	ABS_TIME                cur_time, end_time;
	fd_set                  tcp_fd;
	struct sockaddr_in      peer;

	error_def(ERR_INVADDRSPEC);

	temp_sin_addr = 0;
	msg_string.len = sizeof(msg_buffer);
	msg_string.addr = msg_buffer;
	memset((char *)&sin, 0, sizeof(struct sockaddr_in));

	/* ============================= initialize structures ============================== */
	if (NULL != host)
	{
		temp_ch = host;
		while(ISDIGIT(*temp_ch) || ('.' == *temp_ch))
			temp_ch++;
		if ('\0' != *temp_ch)
			SPRINTF(addr, "%s", iotcp_name2ip(host));
		else
			SPRINTF(addr, "%s", host);

		if (-1 == (temp_sin_addr = tcp_routines.aa_inet_addr(addr)))
		{
			gtm_getmsg(ERR_INVADDRSPEC, &msg_string);
			util_out_print(msg_string.addr, TRUE, ERR_INVADDRSPEC);
			return  -1;
		}
	}

	if (passive)
		/* We can only listen on our own system */
		sin.sin_addr.s_addr = INADDR_ANY;
	else
	{
		if (0 == temp_sin_addr)
		{ 	/* If no address was specified */
			util_out_print("An address has to be specified for an active connection.", TRUE);
			return -1;
		}
		/* Set where to send the connection attempt */
		sin.sin_addr.s_addr = temp_sin_addr;
	}
	sin.sin_port = GTM_HTONS(port);
	sin.sin_family = AF_INET;


	/* ============================== do the connection ============================== */

	if (passive)
	{
		struct timeval  utimeout, save_utimeout;
		int 		lsock;

		lsock = tcp_routines.aa_socket(AF_INET, SOCK_STREAM, 0);
		if (-1 == lsock)
		{
			errptr = (char *)STRERROR(errno);
			errlen = strlen(errptr);
			util_out_print(errptr, TRUE, errno);
			return -1;
		}
		/* allow multiple connections to the same IP address */
		if (-1 == tcp_routines.aa_setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
		{
			errptr = (char *)STRERROR(errno);
			errlen = strlen(errptr);
			(void)tcp_routines.aa_close(lsock);
			util_out_print(errptr, TRUE, errno);
			return -1;
		}
		if (-1 == tcp_routines.aa_bind(lsock, (struct sockaddr *)&sin, sizeof(struct sockaddr)))
		{
			errptr = (char *)STRERROR(errno);
			errlen = strlen(errptr);
			(void)tcp_routines.aa_close(lsock);
			util_out_print(errptr, TRUE, errno);
			return -1;
		}
		/* establish a queue of length MAX_CONN_PENDING for incoming connections */
		if (-1 == tcp_routines.aa_listen(lsock, MAX_CONN_PENDING))
		{
			errptr = (char *)STRERROR(errno);
			errlen = strlen(errptr);
			(void)tcp_routines.aa_close(lsock);
			util_out_print(errptr, TRUE, errno);
			return -1;
		}

		if (NO_M_TIMEOUT != timeout)
		{
			msec_timeout = timeout2msec(timeout);
			sys_get_curr_time(&cur_time);
			add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
			utimeout.tv_sec = timeout;
			utimeout.tv_usec = 0;
		}
		while(1)
		{
			while(1)
			{
				/*
				 * the check for EINTR below is valid and should not be converted to an EINTR
				 * wrapper macro, since it might be a timeout.
				 */
				FD_ZERO(&tcp_fd);
				FD_SET(lsock, &tcp_fd);
                                save_utimeout = utimeout;
				rv = tcp_routines.aa_select(lsock + 1, (void *)&tcp_fd, (void *)0, (void *)0,
					(NO_M_TIMEOUT == timeout) ? (struct timeval *)0 : &utimeout);
                                utimeout = save_utimeout;
				if ((0 <= rv) || (EINTR != errno))
					break;
				if (NO_M_TIMEOUT != timeout)
				{
					sys_get_curr_time(&cur_time);
					cur_time = sub_abs_time(&end_time, &cur_time);
					if (0 >= (utimeout.tv_sec = cur_time.at_sec))
					{
						rv = 0;
						break;
					}
				}
			}
			if (0 == rv)
			{
				util_out_print("Listening timed out.\n", TRUE);
				(void)tcp_routines.aa_close(lsock);
				return -1;
			} else  if (0 > rv)
			{
				errptr = (char *)STRERROR(errno);
				errlen = strlen(errptr);
				util_out_print(errptr, TRUE, errno);
				(void)tcp_routines.aa_close(lsock);
				return -1;
			}
			size = sizeof(struct sockaddr_in);
			sock = tcp_routines.aa_accept(lsock, &peer, &size);
			if (-1 == sock)
			{
				errptr = (char *)STRERROR(errno);
				errlen = strlen(errptr);
				util_out_print(errptr, TRUE, errno);
				(void)tcp_routines.aa_close(lsock);
				return -1;
			}
			SPRINTF(&temp_addr[0], "%s", tcp_routines.aa_inet_ntoa(peer.sin_addr));
#ifdef	DEBUG_ONLINE
			PRINTF("Connection is from : %s\n", &temp_addr[0]);
#endif
			/* Check if connection is from whom we want it to be from. Note that this is not a robust check
			   (potential for multiple IP addrs for a resolved name but workarounds for this exist so not a lot
			   of effort has been expended here at this time. Especially since the check is easily spoofed with
			   raw sockets anyway. It is more for the accidental "oops" type check than serious security..
			*/
			if ((0 == temp_sin_addr) || (0 == memcmp(&addr[0], &temp_addr[0], strlen(addr))))
				break;
			else
			{	/* Connection not from expected host */
				(void)tcp_routines.aa_close(sock);
				if (NO_M_TIMEOUT != timeout)
				{
					sys_get_curr_time(&cur_time);
					cur_time = sub_abs_time(&end_time, &cur_time);
					utimeout.tv_sec = ((cur_time.at_sec > 0) ? cur_time.at_sec : 0);
				}
				if (!error_given)
				{
					util_out_print("Connection from !AD rejected and ignored", TRUE,
						       LEN_AND_STR(&temp_addr[0]));
					error_given = TRUE;
				}
			}
		}
		(void)tcp_routines.aa_close(lsock);
	} else
	{
		if (NO_M_TIMEOUT != timeout)
		{
			msec_timeout = timeout2msec(timeout);
			sys_get_curr_time(&cur_time);
			add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
		}
		no_time_left = FALSE;
		temp_1 = 1;
		do
		{
			if (1 != temp_1)
				tcp_routines.aa_close(sock);
			sock = tcp_routines.aa_socket(AF_INET, SOCK_STREAM, 0);
			if (-1 == sock)
			{
				errptr = (char *)STRERROR(errno);
				errlen = strlen(errptr);
				util_out_print(errptr, TRUE, errno);
				return -1;
			}
			/*      allow multiple connections to the same IP address */
			if      (-1 == tcp_routines.aa_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
			{
				(void)tcp_routines.aa_close(sock);
				errptr = (char *)STRERROR(errno);
				errlen = strlen(errptr);
			        util_out_print(errptr, TRUE, errno);
				return -1;
			}
			temp_1 = tcp_routines.aa_connect(sock, (struct sockaddr *)(&sin), sizeof(sin));
			/*
			 * the check for EINTR below is valid and should not be converted to an EINTR
			 * wrapper macro, because other error conditions are checked, and a retry is not
			 * immediately performed.
			 */
			if ((0 > temp_1) && (ECONNREFUSED != errno) && (EINTR != errno))
			{
				(void)tcp_routines.aa_close(sock);
				errptr = (char *)STRERROR(errno);
				errlen = strlen(errptr);
			        util_out_print(errptr, TRUE, errno);
				return -1;
			}
			if ((0 > temp_1) && (EINTR == errno))
			{
				(void)tcp_routines.aa_close(sock);
				util_out_print("Interrupted.", TRUE);
				return -1;
			}
			if ((temp_1 < 0) && (NO_M_TIMEOUT != timeout))
			{
				sys_get_curr_time(&cur_time);
				cur_time = sub_abs_time(&end_time, &cur_time);
				if (cur_time.at_sec <= 0)
					no_time_left = TRUE;
			}
			SHORT_SLEEP(NAP_LENGTH);               /* Sleep for NAP_LENGTH ms */
		} while ((FALSE == no_time_left) && (0 > temp_1));

		if (0 > temp_1) /* out of time */
		{
			tcp_routines.aa_close(sock);
			util_out_print("Connection timed out.", TRUE);
			return -1;
		}
	}

	return sock;
}
Пример #16
0
boolean_t iosocket_bind(socket_struct *socketptr, int4 timepar, boolean_t update_bufsiz)
{
	int			temp_1 = 1;
	char			*errptr;
	int4			errlen, msec_timeout, real_errno;
	short			len;
	in_port_t		actual_port;
	boolean_t		no_time_left = FALSE;
	d_socket_struct		*dsocketptr;
	struct addrinfo		*ai_ptr;
	char			port_buffer[NI_MAXSERV];
	int			errcode;
	ABS_TIME        	cur_time, end_time;
	GTM_SOCKLEN_TYPE	addrlen;
	GTM_SOCKLEN_TYPE	sockbuflen;

	dsocketptr = socketptr->dev;
	ai_ptr = (struct addrinfo*)(&socketptr->local.ai);
	assert(NULL != dsocketptr);
	dsocketptr->iod->dollar.key[0] = '\0';
	if (FD_INVALID != socketptr->temp_sd)
	{
		socketptr->sd = socketptr->temp_sd;
		socketptr->temp_sd = FD_INVALID;
	}
	if (timepar != NO_M_TIMEOUT)
	{
		msec_timeout = timeout2msec(timepar);
		sys_get_curr_time(&cur_time);
		add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
	}

	do
	{
		temp_1 = 1;
		if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				SOL_SOCKET, SO_REUSEADDR, &temp_1, SIZEOF(temp_1)))
		{
		        real_errno = errno;
			errptr = (char *)STRERROR(real_errno);
			errlen = STRLEN(errptr);
			SOCKET_FREE(socketptr);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("SO_REUSEADDR"), real_errno, errlen, errptr);
			return FALSE;
		}
#ifdef TCP_NODELAY
		temp_1 = socketptr->nodelay ? 1 : 0;
		if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				IPPROTO_TCP, TCP_NODELAY, &temp_1, SIZEOF(temp_1)))
		{
		        real_errno = errno;
			errptr = (char *)STRERROR(real_errno);
			errlen = STRLEN(errptr);
			SOCKET_FREE(socketptr);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("TCP_NODELAY"), real_errno, errlen, errptr);
			return FALSE;
		}
#endif
		if (update_bufsiz)
		{
			if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, SIZEOF(socketptr->bufsiz)))
			{
			        real_errno = errno;
				errptr = (char *)STRERROR(real_errno);
				errlen = STRLEN(errptr);
				SOCKET_FREE(socketptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
						RTS_ERROR_LITERAL("SO_RCVBUF"), real_errno, errlen, errptr);
				return FALSE;
			}
		} else
		{
			sockbuflen = SIZEOF(socketptr->bufsiz);
			if (-1 == tcp_routines.aa_getsockopt(socketptr->sd,
				SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, &sockbuflen))
			{
			        real_errno = errno;
				errptr = (char *)STRERROR(real_errno);
				errlen = STRLEN(errptr);
				SOCKET_FREE(socketptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_GETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("SO_RCVBUF"), real_errno, errlen, errptr);
				return FALSE;
			}
		}
		temp_1 = tcp_routines.aa_bind(socketptr->sd, SOCKET_LOCAL_ADDR(socketptr), ai_ptr->ai_addrlen);
		if (temp_1 < 0)
		{
			real_errno = errno;
			no_time_left = TRUE;
			switch (real_errno)
			{
				case EADDRINUSE:
					if (NO_M_TIMEOUT != timepar)
					{
						sys_get_curr_time(&cur_time);
						cur_time = sub_abs_time(&end_time, &cur_time);
						if (cur_time.at_sec > 0)
							no_time_left = FALSE;
					}
					break;
				case EINTR:
					break;
				default:
					SOCKET_FREE(socketptr);
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKBIND, 0, real_errno, 0);
					break;
			}
			if (no_time_left)
				return FALSE;
			hiber_start(100);
			tcp_routines.aa_close(socketptr->sd);
			if (-1 == (socketptr->sd = tcp_routines.aa_socket(ai_ptr->ai_family,ai_ptr->ai_socktype,
									  ai_ptr->ai_protocol)))
			{
				real_errno = errno;
				errptr = (char *)STRERROR(real_errno);
				errlen = STRLEN(errptr);
				SOCKET_FREE(socketptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, real_errno, errlen, errptr);
				return FALSE;
			}
		}
	} while (temp_1 < 0);

	/* obtain actual port from the bound address if port 0 was specified */
	addrlen = SOCKET_ADDRLEN(socketptr, ai_ptr, local);
	if (-1 == tcp_routines.aa_getsockname(socketptr->sd, SOCKET_LOCAL_ADDR(socketptr), &addrlen))
	{
		real_errno = errno;
		errptr = (char *)STRERROR(real_errno);
		errlen = STRLEN(errptr);
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, real_errno, errlen, errptr);
	        return FALSE;
	}
	assert(ai_ptr->ai_addrlen == addrlen);
	GETNAMEINFO(SOCKET_LOCAL_ADDR(socketptr), addrlen, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV, errcode);
	if (0 != errcode)
	{
		SOCKET_FREE(socketptr);
		RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
		return FALSE;
	}
	actual_port = ATOI(port_buffer);
	if (0 == socketptr->local.port)
		socketptr->local.port = actual_port;
	assert(socketptr->local.port == actual_port);
	socketptr->state = socket_bound;
	len = SIZEOF(BOUND) - 1;
        memcpy(&dsocketptr->iod->dollar.key[0], BOUND, len);
        dsocketptr->iod->dollar.key[len++] = '|';
        memcpy(&dsocketptr->iod->dollar.key[len], socketptr->handle, socketptr->handle_len);
        len += socketptr->handle_len;
        dsocketptr->iod->dollar.key[len++] = '|';
        SPRINTF(&dsocketptr->iod->dollar.key[len], "%d", socketptr->local.port);
	return TRUE;
}
Пример #17
0
/* Timer handler. This is the main handler routine that is being called by the kernel upon receipt
 * of timer signal. It dispatches to the user handler routine, and removes first timer in a timer
 * queue. If the queue is not empty, it starts the first timer in the queue. The why parameter is a
 * no-op in our case, but is required to maintain compatibility with the system type of __sighandler_t,
 * which is (void*)(int).
 */
STATICFNDEF void timer_handler(int why)
{
	int4		cmp;
	GT_TIMER	*tpop, *tpop_prev = NULL;
	ABS_TIME	at;
	sigset_t	savemask;
	int		save_errno, timer_defer_cnt, offset;
	TID 		*deferred_tid;
	boolean_t	tid_found;
	char 		*save_util_outptr;
	va_list		save_last_va_list_ptr;
	boolean_t	util_copy_saved = FALSE;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
#	ifdef DEBUG
	if (IS_GTM_IMAGE)
	{
		tpop = find_timer((TID)heartbeat_timer_ptr, &tpop);
		assert(process_exiting || (((NULL != tpop) && heartbeat_started) || ((NULL == tpop) && !heartbeat_started)));
	}
#	endif
	if (0 < timer_stack_count)
		return;
	timer_stack_count++;
	deferred_timers_check_needed = FALSE;
	save_errno = errno;
	timer_active = FALSE;				/* timer has popped; system timer not active anymore */
	sys_get_curr_time(&at);
	tpop = (GT_TIMER *)timeroot;
	timer_defer_cnt = 0;				/* reset the deferred timer count, since we are in timer_handler */
	SAVE_UTIL_OUT_BUFFER(save_util_outptr, save_last_va_list_ptr, util_copy_saved);
	while (tpop)					/* fire all handlers that expired */
	{
		cmp = abs_time_comp(&at, (ABS_TIME *)&tpop->expir_time);
		if (cmp < 0)
			break;
		/* A timer might pop while we are in the non-zero intrpt_ok_state zone, which could cause collisions. Instead,
		 * we will defer timer events and drive them once the deferral is removed, unless the timer is safe.
		 */
		if ((INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) && (FALSE == process_exiting) || tpop->safe)
		{
			if (NULL != tpop_prev)
				tpop_prev->next = tpop->next;
			else
				timeroot = tpop->next;
			if (tpop->safe)
			{
				safe_timer_cnt--;
				assert(0 <= safe_timer_cnt);
			}
			if (NULL != tpop->handler)	/* if there is a handler, call it */
			{
#				ifdef DEBUG
				if (gtm_white_box_test_case_enabled
					&& (WBTEST_DEFERRED_TIMERS == gtm_white_box_test_case_number)
					&& ((void *)tpop->handler != (void*)heartbeat_timer_ptr))
				{
					DBGFPF((stderr, "TIMER_HANDLER: handled a timer\n"));
					timer_pop_cnt++;
				}
#				endif
				timer_in_handler = TRUE;
				(*tpop->handler)(tpop->tid, tpop->hd_len, tpop->hd_data);
				timer_in_handler = FALSE;
				if (!tpop->safe)		/* if safe, avoid a system call */
					sys_get_curr_time(&at);	/* refresh current time if called a handler */
			}
			tpop->next = (GT_TIMER *)timefree;	/* put timer block on the free chain */
			timefree = tpop;
			if (NULL != tpop_prev)
				tpop = tpop_prev->next;
			else
				tpop = (GT_TIMER *)timeroot;
			num_timers_free++;
			assert(0 < num_timers_free);
		} else
		{
			timer_defer_cnt++;
#			ifdef DEBUG
			if (gtm_white_box_test_case_enabled
				&& (WBTEST_DEFERRED_TIMERS == gtm_white_box_test_case_number))
			{
				if (!deferred_tids)
				{
					deferred_tids = (TID *)malloc(SIZEOF(TID) * 2);
					*deferred_tids = tpop->tid;
					*(deferred_tids + 1) = -1;
					DBGFPF((stderr, "TIMER_HANDLER: deferred a timer\n"));
				} else
				{
					tid_found = FALSE;
					deferred_tid = deferred_tids;
					while (-1 != *deferred_tid)
					{
						if (*deferred_tid == tpop->tid)
						{
							tid_found = TRUE;
							break;
						}
						deferred_tid++;
					}
					if (!tid_found)
					{
						offset = deferred_tid - deferred_tids;
						deferred_tid = (TID *)malloc((offset + 2) * SIZEOF(TID));
						memcpy(deferred_tid, deferred_tids, offset * SIZEOF(TID));
						free(deferred_tids);
						deferred_tids = deferred_tid;
						*(deferred_tids + offset++) = tpop->tid;
						*(deferred_tids + offset) = -1;
						DBGFPF((stderr, "TIMER_HANDLER: deferred a timer\n"));
					}
				}
			}
#			endif
			tpop_prev = tpop;
			tpop = tpop->next;
			if (0 == safe_timer_cnt)	/* no more safe timers left, so quit */
				break;
		}
	}
	RESTORE_UTIL_OUT_BUFFER(save_util_outptr, save_last_va_list_ptr, util_copy_saved);
	if (((FALSE == process_exiting) && (INTRPT_OK_TO_INTERRUPT == intrpt_ok_state)) || (0 < safe_timer_cnt))
		start_first_timer(&at);
	else if ((NULL != timeroot) || (0 < timer_defer_cnt))
		deferred_timers_check_needed = TRUE;
	errno = save_errno;		/* restore mainline errno */
	timer_stack_count--;
}
Пример #18
0
int	iotcp_readfl(mval *v, int4 width, int4 timeout)
/* 0 == width is a flag that the caller is read and the length is not actually fixed */
/* timeout in seconds */
{
	/* VMS uses the UCX interface; should support others that emulate it */
	boolean_t	ret, timed, vari;
	int		flags, len, real_errno, save_errno;
	int		i;
	io_desc		*io_ptr;
	d_tcp_struct	*tcpptr;
	int4		status;
	int4		msec_timeout;	/* timeout in milliseconds */
	TID		timer_id;
	ABS_TIME	cur_time, end_time, time_for_read, lcl_time_for_read, zero;
	fd_set		tcp_fd;
	char		*errptr;
	int4		errlen;

	error_def(ERR_IOEOF);
	error_def(ERR_TEXT);
	error_def(ERR_GETSOCKOPTERR);
	error_def(ERR_SETSOCKOPTERR);

#ifdef DEBUG_TCP
	PRINTF("%s >>>\n", __FILE__);
#endif
	assert(stringpool.free >= stringpool.base);
	assert(stringpool.free <= stringpool.top);
	if (0 == width)
	{	/* op_readfl won't do this; must be a call from iotcp_read */
		vari = TRUE;
		width = MAX_READLEN;
	} else
	{
		vari = FALSE;
		width = (width < MAX_READLEN) ? width : MAX_READLEN;
	}
	if (stringpool.free + width > stringpool.top)
		stp_gcol(width);
	io_ptr = io_curr_device.in;
	assert(dev_open == io_ptr->state);
	tcpptr = (d_tcp_struct *)(io_ptr->dev_sp);
	if (io_ptr->dollar.x && (TCP_WRITE == tcpptr->lastop))
	{	/* switching from write to read */
#ifdef C9A06001531
		/* pending change request C9A06-001531 */
		if (!io_ptr->dollar.za)
			iotcp_wteol(1, io_ptr);
#endif
		io_ptr->dollar.x = 0;
	}
	tcpptr->lastop = TCP_READ;
	ret = TRUE;
	timer_id = (TID)iotcp_readfl;
	out_of_time = FALSE;
	time_for_read.at_sec = ((0 == timeout) ? 0 : 1);
	time_for_read.at_usec = 0;
	if (NO_M_TIMEOUT == timeout)
	{
		timed = FALSE;
		msec_timeout = NO_M_TIMEOUT;
	} else
	{
		timed = TRUE;
		msec_timeout = timeout2msec(timeout);
		if (msec_timeout > 0)
		{	/* there is time to wait */
#ifdef UNIX
			/* set blocking I/O */
			FCNTL2(tcpptr->socket, F_GETFL, flags);
			if (flags < 0)
			{
				save_errno = errno;
				errptr = (char *)STRERROR(errno);
				rts_error(VARLSTCNT(7) ERR_GETSOCKOPTERR, 5, LEN_AND_LIT("F_GETFL FOR NON BLOCKING I/O"),
						save_errno, LEN_AND_STR(errptr));
			}
			FCNTL3(tcpptr->socket, F_SETFL, flags & (~(O_NDELAY | O_NONBLOCK)), fcntl_res);
			if (fcntl_res < 0)
			{
				save_errno = errno;
				errptr = (char *)STRERROR(errno);
				rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("F_SETFL FOR NON BLOCKING I/O"),
						save_errno, LEN_AND_STR(errptr));
			}
#endif
			sys_get_curr_time(&cur_time);
			add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
			start_timer(timer_id, msec_timeout, wake_alarm, 0, NULL);
		} else
			out_of_time = TRUE;
	}
	for (i = 0, status = 0; status >= 0; )
	{
		FD_ZERO(&tcp_fd);
		FD_SET(tcpptr->socket, &tcp_fd);
		assert(0 != FD_ISSET(tcpptr->socket, &tcp_fd));
		assert(((1 == time_for_read.at_sec) || (0 == time_for_read.at_sec)) && (0 == time_for_read.at_usec));
		/*
		 * the check for EINTR below is valid and should not be converted to an EINTR
		 * wrapper macro, since it might be a timeout.
		 */
		lcl_time_for_read = time_for_read;
		status = tcp_routines.aa_select(tcpptr->socket + 1, (void *)(&tcp_fd), (void *)0, (void *)0,
							&lcl_time_for_read);
		if (status > 0)
		{
			status = tcp_routines.aa_recv(tcpptr->socket, (char *)(stringpool.free +  i), width - i, 0);
			if ((0 == status) || ((-1 == status) && (ECONNRESET == errno || EPIPE == errno || EINVAL == errno)))
			{ /* lost connection. */
				if (0 == status)
					errno = ECONNRESET;
				real_errno = errno;
				status = -2;
				break;
			}

		}
		if (status < 0)
		{
			if (EINTR == errno && FALSE == out_of_time)
			{	/* interrupted by a signal which is not OUR timer, continue looping */
				status = 0;
			} else
				real_errno = errno;
		} else
			real_errno = 0;
		if (outofband)
			break;
		if (timed)
		{
			if (msec_timeout > 0)
			{
				sys_get_curr_time(&cur_time);
				cur_time = sub_abs_time(&end_time, &cur_time);
				if (cur_time.at_sec <= 0)
				{
					out_of_time = TRUE;
					cancel_timer(timer_id);
					if (status > 0)
						i += status;
					break;
				}
			} else
			{
				if (status > 0)
					i += status;
				break;
			}
		}
		if (0 > status)
			break;
		i += status;
		if ((vari && (0 != i)) || (i >= width))
			break;
	}
	if (EINTR == real_errno)
		status = 0;	/* don't treat a <CTRL-C> or timeout as an error */
	if (timed)
	{
		if (0 == msec_timeout)
		{
			if (0 == status)
				ret = FALSE;
		} else
		{
#ifdef UNIX
			real_errno = errno;
			FCNTL3(tcpptr->socket, F_SETFL, flags, fcntl_res);
			if (fcntl_res < 0)
			{
				save_errno = errno;
				errptr = (char *)STRERROR(errno);
				rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("F_SETFL FOR RESTORING SOCKET OPTIONS"),
					  	save_errno, LEN_AND_STR(errptr));
			}
			errno = real_errno;
#endif
			if (out_of_time && (i < width))
				ret = FALSE;
			else
				cancel_timer(timer_id);
		}
	}
	if (i > 0)
	{	/* there's somthing to return */
		v->str.len = i;
		v->str.addr = (char *)stringpool.free;
		if (((io_ptr->dollar.x += i) >= io_ptr->width) && (TRUE == io_ptr->wrap))
		{
			io_ptr->dollar.y += (io_ptr->dollar.x / io_ptr->width);
			if (0 != io_ptr->length)
				io_ptr->dollar.y %= io_ptr->length;
			io_ptr->dollar.x %= io_ptr->width;
		}
	} else
		v->str.len = 0;
#ifdef DEBUG_TCP
	PRINTF("%s <<<\n", __FILE__);
#endif
	len = sizeof("1,") - 1;
	if (status >= 0)
	{	/* no real problems */
		io_ptr->dollar.za = 0;
/*	the handling of urgent data doesn't work and never has, the design should be changed to use a /URGENT controlnmemonic
 *	because there is really only one character available at a time
		zero.at_sec = zero.at_usec = 0;
		FD_ZERO(&tcp_fd);
		FD_SET(tcpptr->socket, &tcp_fd);
		if (tcp_routines.aa_select(tcpptr->socket + 1, (void *)(tcpptr->urgent ? &tcp_fd : 0), (void *)0,
								(void *)(tcpptr->urgent ? 0 : &tcp_fd), &zero) > 0)
		{
			memcpy(tcpptr->dollar_device, "1,", len);
			if (tcpptr->urgent)
			{
				memcpy(&tcpptr->dollar_device[len], "No ",sizeof("No "));
				len += sizeof("No ") - 1;
			}
			memcpy(&tcpptr->dollar_device[len], "Urgent Data", sizeof("Urgent Data"));
		} else
*/
			memcpy(tcpptr->dollar_device, "0", sizeof("0"));
	} else
	{	/* there's a significant problem */
		if (0 == i)
			io_ptr->dollar.x = 0;
		io_ptr->dollar.za = 9;
		memcpy(tcpptr->dollar_device, "1,", len);
		errptr = (char *)STRERROR(errno);
		errlen = STRLEN(errptr);
		memcpy(&tcpptr->dollar_device[len], errptr, errlen);
		if (io_ptr->dollar.zeof || -1 == status || 0 < io_ptr->error_handler.len)
		{
			io_ptr->dollar.zeof = TRUE;
			rts_error(VARLSTCNT(6) ERR_IOEOF, 0, ERR_TEXT, 2, errlen, errptr);
		} else
			io_ptr->dollar.zeof = TRUE;
	}
	return (ret);
}