⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channels.c

📁 C++编写
💻 C
📖 第 1 页 / 共 5 页
字号:
		channel_pre[i] = NULL;		channel_post[i] = NULL;	}	if (compat20)		channel_handler_init_20();	else if (compat13)		channel_handler_init_13();	else		channel_handler_init_15();}/* gc dead channels */static voidchannel_garbage_collect(Channel *c){	if (c == NULL)		return;	if (c->detach_user != NULL) {		if (!chan_is_dead(c, 0))			return;		debug("channel %d: gc: notify user", c->self);		c->detach_user(c->self, NULL);		/* if we still have a callback */		if (c->detach_user != NULL)			return;		debug("channel %d: gc: user detached", c->self);	}	if (!chan_is_dead(c, 1))		return;	debug("channel %d: garbage collecting", c->self);	channel_free(c);}static voidchannel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset){	static int did_init = 0;	int i;	Channel *c;	if (!did_init) {		channel_handler_init();		did_init = 1;	}	for (i = 0; i < channels_alloc; i++) {		c = channels[i];		if (c == NULL)			continue;		if (ftab[c->type] != NULL)			(*ftab[c->type])(c, readset, writeset);		channel_garbage_collect(c);	}}/* * Allocate/update select bitmasks and add any bits relevant to channels in * select bitmasks. */voidchannel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,    int *nallocp, int rekeying){	int n;	u_int sz;	n = MAX(*maxfdp, channel_max_fd);	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);	/* perhaps check sz < nalloc/2 and shrink? */	if (*readsetp == NULL || sz > *nallocp) {		*readsetp = xrealloc(*readsetp, sz);		*writesetp = xrealloc(*writesetp, sz);		*nallocp = sz;	}	*maxfdp = n;	memset(*readsetp, 0, sz);	memset(*writesetp, 0, sz);	if (!rekeying)		channel_handler(channel_pre, *readsetp, *writesetp);}/* * After select, perform any appropriate operations for channels which have * events pending. */voidchannel_after_select(fd_set * readset, fd_set * writeset){	channel_handler(channel_post, readset, writeset);}/* If there is data to send to the connection, enqueue some of it now. */voidchannel_output_poll(void){	Channel *c;	int i;	u_int len;	for (i = 0; i < channels_alloc; i++) {		c = channels[i];		if (c == NULL)			continue;		/*		 * We are only interested in channels that can have buffered		 * incoming data.		 */		if (compat13) {			if (c->type != SSH_CHANNEL_OPEN &&			    c->type != SSH_CHANNEL_INPUT_DRAINING)				continue;		} else {			if (c->type != SSH_CHANNEL_OPEN)				continue;		}		if (compat20 &&		    (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {			/* XXX is this true? */			debug3("channel %d: will not send data after close", c->self);			continue;		}		/* Get the amount of buffered data for this channel. */		if ((c->istate == CHAN_INPUT_OPEN ||		    c->istate == CHAN_INPUT_WAIT_DRAIN) &&		    (len = buffer_len(&c->input)) > 0) {			/*			 * Send some data for the other side over the secure			 * connection.			 */			if (compat20) {				if (len > c->remote_window)					len = c->remote_window;				if (len > c->remote_maxpacket)					len = c->remote_maxpacket;			} else {				if (packet_is_interactive()) {					if (len > 1024)						len = 512;				} else {					/* Keep the packets at reasonable size. */					if (len > packet_get_maxsize()/2)						len = packet_get_maxsize()/2;				}			}			if (len > 0) {				packet_start(compat20 ?				    SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);				packet_put_int(c->remote_id);				packet_put_string(buffer_ptr(&c->input), len);				packet_send();				buffer_consume(&c->input, len);				c->remote_window -= len;			}		} else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {			if (compat13)				fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");			/*			 * input-buffer is empty and read-socket shutdown:			 * tell peer, that we will not send more data: send IEOF.			 * hack for extended data: delay EOF if EFD still in use.			 */			if (CHANNEL_EFD_INPUT_ACTIVE(c))			       debug2("channel %d: ibuf_empty delayed efd %d/(%d)",				   c->self, c->efd, buffer_len(&c->extended));			else				chan_ibuf_empty(c);		}		/* Send extended data, i.e. stderr */		if (compat20 &&		    !(c->flags & CHAN_EOF_SENT) &&		    c->remote_window > 0 &&		    (len = buffer_len(&c->extended)) > 0 &&		    c->extended_usage == CHAN_EXTENDED_READ) {			debug2("channel %d: rwin %u elen %u euse %d",			    c->self, c->remote_window, buffer_len(&c->extended),			    c->extended_usage);			if (len > c->remote_window)				len = c->remote_window;			if (len > c->remote_maxpacket)				len = c->remote_maxpacket;			packet_start(SSH2_MSG_CHANNEL_EXTENDED_DATA);			packet_put_int(c->remote_id);			packet_put_int(SSH2_EXTENDED_DATA_STDERR);			packet_put_string(buffer_ptr(&c->extended), len);			packet_send();			buffer_consume(&c->extended, len);			c->remote_window -= len;			debug2("channel %d: sent ext data %d", c->self, len);		}	}}/* -- protocol input */voidchannel_input_data(int type, u_int32_t seq, void *ctxt){	int id;	char *data;	u_int data_len;	Channel *c;	/* Get the channel number and verify it. */	id = packet_get_int();	c = channel_lookup(id);	if (c == NULL)		packet_disconnect("Received data for nonexistent channel %d.", id);	/* Ignore any data for non-open channels (might happen on close) */	if (c->type != SSH_CHANNEL_OPEN &&	    c->type != SSH_CHANNEL_X11_OPEN)		return;	/* same for protocol 1.5 if output end is no longer open */	if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN)		return;	/* Get the data. */	data = packet_get_string(&data_len);	if (compat20) {		if (data_len > c->local_maxpacket) {			log("channel %d: rcvd big packet %d, maxpack %d",			    c->self, data_len, c->local_maxpacket);		}		if (data_len > c->local_window) {			log("channel %d: rcvd too much data %d, win %d",			    c->self, data_len, c->local_window);			xfree(data);			return;		}		c->local_window -= data_len;	}	packet_check_eom();	buffer_append(&c->output, data, data_len);	xfree(data);}voidchannel_input_extended_data(int type, u_int32_t seq, void *ctxt){	int id;	char *data;	u_int data_len, tcode;	Channel *c;	/* Get the channel number and verify it. */	id = packet_get_int();	c = channel_lookup(id);	if (c == NULL)		packet_disconnect("Received extended_data for bad channel %d.", id);	if (c->type != SSH_CHANNEL_OPEN) {		log("channel %d: ext data for non open", id);		return;	}	if (c->flags & CHAN_EOF_RCVD) {		if (datafellows & SSH_BUG_EXTEOF)			debug("channel %d: accepting ext data after eof", id);		else			packet_disconnect("Received extended_data after EOF "			    "on channel %d.", id);	}	tcode = packet_get_int();	if (c->efd == -1 ||	    c->extended_usage != CHAN_EXTENDED_WRITE ||	    tcode != SSH2_EXTENDED_DATA_STDERR) {		log("channel %d: bad ext data", c->self);		return;	}	data = packet_get_string(&data_len);	packet_check_eom();	if (data_len > c->local_window) {		log("channel %d: rcvd too much extended_data %d, win %d",		    c->self, data_len, c->local_window);		xfree(data);		return;	}	debug2("channel %d: rcvd ext data %d", c->self, data_len);	c->local_window -= data_len;	buffer_append(&c->extended, data, data_len);	xfree(data);}voidchannel_input_ieof(int type, u_int32_t seq, void *ctxt){	int id;	Channel *c;	id = packet_get_int();	packet_check_eom();	c = channel_lookup(id);	if (c == NULL)		packet_disconnect("Received ieof for nonexistent channel %d.", id);	chan_rcvd_ieof(c);	/* XXX force input close */	if (c->force_drain && c->istate == CHAN_INPUT_OPEN) {		debug("channel %d: FORCE input drain", c->self);		c->istate = CHAN_INPUT_WAIT_DRAIN;		if (buffer_len(&c->input) == 0)			chan_ibuf_empty(c);	}}voidchannel_input_close(int type, u_int32_t seq, void *ctxt){	int id;	Channel *c;	id = packet_get_int();	packet_check_eom();	c = channel_lookup(id);	if (c == NULL)		packet_disconnect("Received close for nonexistent channel %d.", id);	/*	 * Send a confirmation that we have closed the channel and no more	 * data is coming for it.	 */	packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);	packet_put_int(c->remote_id);	packet_send();	/*	 * If the channel is in closed state, we have sent a close request,	 * and the other side will eventually respond with a confirmation.	 * Thus, we cannot free the channel here, because then there would be	 * no-one to receive the confirmation.  The channel gets freed when	 * the confirmation arrives.	 */	if (c->type != SSH_CHANNEL_CLOSED) {		/*		 * Not a closed channel - mark it as draining, which will		 * cause it to be freed later.		 */		buffer_clear(&c->input);		c->type = SSH_CHANNEL_OUTPUT_DRAINING;	}}/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */voidchannel_input_oclose(int type, u_int32_t seq, void *ctxt){	int id = packet_get_int();	Channel *c = channel_lookup(id);	packet_check_eom();	if (c == NULL)		packet_disconnect("Received oclose for nonexistent channel %d.", id);	chan_rcvd_oclose(c);}voidchannel_input_close_confirmation(int type, u_int32_t seq, void *ctxt){	int id = packet_get_int();	Channel *c = channel_lookup(id);	packet_check_eom();	if (c == NULL)		packet_disconnect("Received close confirmation for "		    "out-of-range channel %d.", id);	if (c->type != SSH_CHANNEL_CLOSED)		packet_disconnect("Received close confirmation for "		    "non-closed channel %d (type %d).", id, c->type);	channel_free(c);}voidchannel_input_open_confirmation(int type, u_int32_t seq, void *ctxt){	int id, remote_id;	Channel *c;	id = packet_get_int();	c = channel_lookup(id);	if (c==NULL || c->type != SSH_CHANNEL_OPENING)		packet_disconnect("Received open confirmation for "		    "non-opening channel %d.", id);	remote_id = packet_get_int();	/* Record the remote channel number and mark that the channel is now open. */	c->remote_id = remote_id;	c->type = SSH_CHANNEL_OPEN;	if (compat20) {		c->remote_window = packet_get_int();		c->remote_maxpacket = packet_get_int();		if (c->confirm) {			debug2("callback start");			c->confirm(c->self, NULL);			debug2("callback done");		}		debug("channel %d: open confirm rwindow %u rmax %u", c->self,		    c->remote_window, c->remote_maxpacket);	}	packet_check_eom();}static char *reason2txt(int reason){	switch (reason) {	case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED:		return "administratively prohibited";	case SSH2_OPEN_CONNECT_FAILED:		return "connect failed";	case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE:		return "unknown channel type";	case SSH2_OPEN_RESOURCE_SHORTAGE:		return "resource shortage";	}	return "unknown reason";}voidchannel_input_open_failure(int type, u_int32_t seq, void *ctxt){	int id, reason;	char *msg = NULL, *lang = NULL;	Channel *c;	id = packet_get_int();	c = channel_lookup(id);	if (c==NULL || c->type != SSH_CHANNEL_OPENING)		packet_disconnect("Received open failure for "		    "non-opening channel %d.", id);	if (compat20) {		reason = packet_get_int();		if (!(datafellows & SSH_BUG_OPENFAILURE)) {			msg  = packet_get_string(NULL);			lang = packet_get_string(NULL);		}		log("channel %d: open failed: %s%s%s", id,		    reason2txt(reason), msg ? ": ": "", msg ? msg : "");		if (msg != NULL)			xfree(msg);		if (lang != NULL)			xfree(lang);	}	packet_check_eom();	/* Free the channel.  This will also close the socket. */	channel_free(c);}voidchannel_input_window_adjust(int type, u_int32_t seq, void *ctxt){	Channel *c;	int id;	u_int adjust;	if (!compat20)		return;	/* Get the channel number and verify it. */	id = packet_get_int();	c = channel_lookup(id);	if (c == NULL || c->type != SSH_CHANNEL_OPEN) {		log("Received window adjust for "		    "non-open channel %d.", id);		return;	}	adjust = packet_get_int();	packet_check_eom();	debug2("channel %d: rcvd adjust %u", id, adjust);	c->remote_window += adjust;}voidchannel_input_port_open(int type, u_int32_t seq, void *ctxt){	Channel *c = NULL;	u_short host_port;	char *host, *originator_string;	int remote_id, sock = -1;	remote_id = packet_get_int();	host = packet_get_string(NULL);	host_port = packet_get_int();	if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -