version 1.51, 2000/04/28 08:10:20 |
version 1.52, 2000/05/01 18:31:27 |
|
|
} |
} |
|
|
/* |
/* |
* Allocate a new channel object and set its type and socket. This will cause |
* register filedescriptors for a channel, used when allocating a channel or |
* remote_name to be freed. |
* when the channel consumer/producer is ready, e.g. shell exec'd |
*/ |
*/ |
|
|
int |
void |
channel_new(char *ctype, int type, int rfd, int wfd, int efd, |
channel_register_fds(Channel *c, int rfd, int wfd, int efd, int extusage) |
int window, int maxpack, int extended_usage, char *remote_name) |
|
{ |
{ |
int i, found; |
|
Channel *c; |
|
|
|
/* Update the maximum file descriptor value. */ |
/* Update the maximum file descriptor value. */ |
if (rfd > channel_max_fd_value) |
if (rfd > channel_max_fd_value) |
channel_max_fd_value = rfd; |
channel_max_fd_value = rfd; |
|
|
if (efd > channel_max_fd_value) |
if (efd > channel_max_fd_value) |
channel_max_fd_value = efd; |
channel_max_fd_value = efd; |
/* XXX set close-on-exec -markus */ |
/* XXX set close-on-exec -markus */ |
|
c->rfd = rfd; |
|
c->wfd = wfd; |
|
c->sock = (rfd == wfd) ? rfd : -1; |
|
c->efd = efd; |
|
c->extended_usage = extusage; |
|
} |
|
|
|
/* |
|
* Allocate a new channel object and set its type and socket. This will cause |
|
* remote_name to be freed. |
|
*/ |
|
|
|
int |
|
channel_new(char *ctype, int type, int rfd, int wfd, int efd, |
|
int window, int maxpack, int extusage, char *remote_name) |
|
{ |
|
int i, found; |
|
Channel *c; |
|
|
/* Do initial allocation if this is the first call. */ |
/* Do initial allocation if this is the first call. */ |
if (channels_alloc == 0) { |
if (channels_alloc == 0) { |
chan_init(); |
chan_init(); |
|
|
buffer_init(&c->output); |
buffer_init(&c->output); |
buffer_init(&c->extended); |
buffer_init(&c->extended); |
chan_init_iostates(c); |
chan_init_iostates(c); |
|
channel_register_fds(c, rfd, wfd, efd, extusage); |
c->self = found; |
c->self = found; |
c->type = type; |
c->type = type; |
c->ctype = ctype; |
c->ctype = ctype; |
c->rfd = rfd; |
|
c->wfd = wfd; |
|
c->sock = (rfd == wfd) ? rfd : -1; |
|
c->efd = efd; |
|
c->extended_usage = extended_usage; |
|
c->local_window = window; |
c->local_window = window; |
c->local_window_max = window; |
c->local_window_max = window; |
c->local_consumed = 0; |
c->local_consumed = 0; |
|
|
debug("channel %d: new [%s]", found, remote_name); |
debug("channel %d: new [%s]", found, remote_name); |
return found; |
return found; |
} |
} |
|
/* old interface XXX */ |
int |
int |
channel_allocate(int type, int sock, char *remote_name) |
channel_allocate(int type, int sock, char *remote_name) |
{ |
{ |
return channel_new("", type, sock, sock, -1, 0, 0, 0, remote_name); |
return channel_new("", type, sock, sock, -1, 0, 0, 0, remote_name); |
} |
} |
|
|
/* Free the channel and close its socket. */ |
|
|
|
|
/* Close all channel fd/socket. */ |
|
|
void |
void |
|
channel_close_fds(Channel *c) |
|
{ |
|
if (c->sock != -1) { |
|
shutdown(c->sock, SHUT_RDWR); |
|
close(c->sock); |
|
c->sock = -1; |
|
} |
|
if (c->rfd != -1) { |
|
close(c->rfd); |
|
c->rfd = -1; |
|
} |
|
if (c->wfd != -1) { |
|
close(c->wfd); |
|
c->wfd = -1; |
|
} |
|
if (c->efd != -1) { |
|
close(c->efd); |
|
c->efd = -1; |
|
} |
|
} |
|
|
|
/* Free the channel and close its fd/socket. */ |
|
|
|
void |
channel_free(int id) |
channel_free(int id) |
{ |
{ |
Channel *c = channel_lookup(id); |
Channel *c = channel_lookup(id); |
|
|
debug("channel_free: channel %d: dettaching channel user", id); |
debug("channel_free: channel %d: dettaching channel user", id); |
c->dettach_user(c->self, NULL); |
c->dettach_user(c->self, NULL); |
} |
} |
if (c->sock != -1) { |
channel_close_fds(c); |
shutdown(c->sock, SHUT_RDWR); |
|
close(c->sock); |
|
c->sock = -1; |
|
} |
|
if (compat20) { |
|
if (c->rfd != -1) { |
|
close(c->rfd); |
|
c->rfd = -1; |
|
} |
|
if (c->wfd != -1) { |
|
close(c->wfd); |
|
c->wfd = -1; |
|
} |
|
if (c->efd != -1) { |
|
close(c->efd); |
|
c->efd = -1; |
|
} |
|
} |
|
buffer_free(&c->input); |
buffer_free(&c->input); |
buffer_free(&c->output); |
buffer_free(&c->output); |
buffer_free(&c->extended); |
buffer_free(&c->extended); |
|
|
} |
} |
|
|
/* |
/* |
* Closes the sockets of all channels. This is used to close extra file |
* Closes the sockets/fds of all channels. This is used to close extra file |
* descriptors after a fork. |
* descriptors after a fork. |
*/ |
*/ |
|
|
|
|
channel_close_all() |
channel_close_all() |
{ |
{ |
int i; |
int i; |
for (i = 0; i < channels_alloc; i++) { |
for (i = 0; i < channels_alloc; i++) |
if (channels[i].type != SSH_CHANNEL_FREE) |
if (channels[i].type != SSH_CHANNEL_FREE) |
close(channels[i].sock); |
channel_close_fds(&channels[i]); |
} |
|
} |
} |
|
|
/* Returns the maximum file descriptor number used by the channels. */ |
/* Returns the maximum file descriptor number used by the channels. */ |
|
|
Channel *c = channel_lookup(id); |
Channel *c = channel_lookup(id); |
if (c == NULL || c->type != SSH_CHANNEL_LARVAL) |
if (c == NULL || c->type != SSH_CHANNEL_LARVAL) |
fatal("channel_activate for non-larval channel %d.", id); |
fatal("channel_activate for non-larval channel %d.", id); |
if (rfd > channel_max_fd_value) |
|
channel_max_fd_value = rfd; |
channel_register_fds(c, rfd, wfd, efd, extusage); |
if (wfd > channel_max_fd_value) |
|
channel_max_fd_value = wfd; |
|
if (efd > channel_max_fd_value) |
|
channel_max_fd_value = efd; |
|
c->type = SSH_CHANNEL_OPEN; |
c->type = SSH_CHANNEL_OPEN; |
c->rfd = rfd; |
|
c->wfd = wfd; |
|
c->efd = efd; |
|
c->extended_usage = extusage; |
|
/* XXX window size? */ |
/* XXX window size? */ |
c->local_window = c->local_window_max = c->local_maxpacket/2; |
c->local_window = c->local_window_max = c->local_maxpacket/2; |
packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); |
packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); |