Commit 8cd3db51 authored by Niels Möller's avatar Niels Möller
Browse files

Uniform closing of channels.

Rev: src/channel.c:1.10
Rev: src/channel.h:1.12
parent c2e6060b
...@@ -158,6 +158,8 @@ struct channel_table *make_channel_table(void) ...@@ -158,6 +158,8 @@ struct channel_table *make_channel_table(void)
table->used_channels = 0; table->used_channels = 0;
table->max_channels = MAX_CHANNELS; table->max_channels = MAX_CHANNELS;
table->pending_close = 0;
return table; return table;
}; };
...@@ -220,8 +222,29 @@ struct ssh_channel *lookup_channel(struct channel_table *table, UINT32 i) ...@@ -220,8 +222,29 @@ struct ssh_channel *lookup_channel(struct channel_table *table, UINT32 i)
? table->channels[i] : NULL; ? table->channels[i] : NULL;
} }
/* Channel related messages */ static int channel_process_status(struct channel_table *table,
int channel,
int status)
{
if (status & LSH_CHANNEL_PENDING_CLOSE)
table->pending_close = 1;
if (status & LSH_CHANNEL_FINISHED)
{
/* Clear this bit */
status &= ~LSH_CHANNEL_FINISHED;
dealloc_channel(table, channel);
/* If this was the last channel, close connection */
if (table->pending_close && !table->next_channel)
status |= LSH_CLOSE;
}
return status;
}
/* Channel related messages */
static int do_global_request(struct packet_handler *c, static int do_global_request(struct packet_handler *c,
struct ssh_connection *connection, struct ssh_connection *connection,
struct lsh_string *packet) struct lsh_string *packet)
...@@ -290,6 +313,13 @@ static int do_channel_open(struct packet_handler *c, ...@@ -290,6 +313,13 @@ static int do_channel_open(struct packet_handler *c,
int local_channel_number; int local_channel_number;
lsh_string_free(packet); lsh_string_free(packet);
if (closure->super.table->pending_close)
/* We are waiting for channels to close. Don't open any new ones. */
return A_WRITE(connection->write,
format_open_failure(remote_channel_number,
SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
"Waiting for channels to close.", ""));
if (!type || !(open = ALIST_GET(closure->channel_types, type))) if (!type || !(open = ALIST_GET(closure->channel_types, type)))
return A_WRITE(connection->write, return A_WRITE(connection->write,
...@@ -330,7 +360,8 @@ static int do_channel_open(struct packet_handler *c, ...@@ -330,7 +360,8 @@ static int do_channel_open(struct packet_handler *c,
args args
? format_open_confirmation(channel, local_channel_number, ? format_open_confirmation(channel, local_channel_number,
"%lfS", args) "%lfS", args)
: format_open_confirmation(channel, local_channel_number, "")); : format_open_confirmation(channel, local_channel_number,
""));
} }
lsh_string_free(packet); lsh_string_free(packet);
...@@ -370,7 +401,9 @@ static int do_channel_request(struct packet_handler *c, ...@@ -370,7 +401,9 @@ static int do_channel_request(struct packet_handler *c,
if (type && channel->request_types if (type && channel->request_types
&& ( (req = ALIST_GET(channel->request_types, type)) )) && ( (req = ALIST_GET(channel->request_types, type)) ))
return CHANNEL_REQUEST(req, channel, want_reply, &buffer); return channel_process_status
(closure->table, channel_number,
CHANNEL_REQUEST(req, channel, want_reply, &buffer));
else else
return want_reply return want_reply
? A_WRITE(connection->write, ? A_WRITE(connection->write,
...@@ -420,7 +453,9 @@ static int do_window_adjust(struct packet_handler *c, ...@@ -420,7 +453,9 @@ static int do_window_adjust(struct packet_handler *c,
{ {
channel->send_window_size += size; channel->send_window_size += size;
if (channel->send_window_size && channel->send) if (channel->send_window_size && channel->send)
CHANNEL_SEND(channel); return channel_process_status(closure->table,
channel_number,
CHANNEL_SEND(channel));
} }
return LSH_OK | LSH_GOON; return LSH_OK | LSH_GOON;
} }
...@@ -490,8 +525,10 @@ static int do_channel_data(struct packet_handler *c, ...@@ -490,8 +525,10 @@ static int do_channel_data(struct packet_handler *c,
return res; return res;
} }
return res | CHANNEL_RECIEVE(channel, return channel_process_status(
CHANNEL_DATA, data); closure->table, channel_number,
res | CHANNEL_RECIEVE(channel,
CHANNEL_DATA, data));
} }
return LSH_OK | LSH_GOON; return LSH_OK | LSH_GOON;
} }
...@@ -568,8 +605,10 @@ static int do_channel_extended_data(struct packet_handler *c, ...@@ -568,8 +605,10 @@ static int do_channel_extended_data(struct packet_handler *c,
switch(type) switch(type)
{ {
case SSH_EXTENDED_DATA_STDERR: case SSH_EXTENDED_DATA_STDERR:
return res | CHANNEL_RECIEVE(channel, return channel_process_status(
CHANNEL_STDERR_DATA, data); closure->table, channel_number,
res | CHANNEL_RECIEVE(channel,
CHANNEL_STDERR_DATA, data));
default: default:
werror("Unknown type %d of extended data.\n", werror("Unknown type %d of extended data.\n",
type); type);
...@@ -631,9 +670,12 @@ static int do_channel_eof(struct packet_handler *c, ...@@ -631,9 +670,12 @@ static int do_channel_eof(struct packet_handler *c,
/* Both parties have sent EOF. Initiate close, if we /* Both parties have sent EOF. Initiate close, if we
* havn't done that already. */ * havn't done that already. */
return (channel->flags & CHANNEL_SENT_CLOSE) if (channel->flags & CHANNEL_SENT_CLOSE)
? LSH_OK | LSH_GOON return LSH_OK | LSH_GOON;
: channel_close(channel); else
return channel_process_status(
closure->table, channel_number,
channel_close(channel));
} }
return LSH_OK | LSH_GOON; return LSH_OK | LSH_GOON;
} }
...@@ -680,14 +722,16 @@ static int do_channel_close(struct packet_handler *c, ...@@ -680,14 +722,16 @@ static int do_channel_close(struct packet_handler *c,
channel->flags |= CHANNEL_RECIEVED_CLOSE; channel->flags |= CHANNEL_RECIEVED_CLOSE;
if (channel->flags & (CHANNEL_RECIEVED_EOF | CHANNEL_SENT_EOF)) if (! (channel->flags & (CHANNEL_RECIEVED_EOF | CHANNEL_SENT_EOF)))
{ {
werror("Unexpected channel CLOSE.\n"); werror("Unexpected channel CLOSE.\n");
} }
return (channel->flags & (CHANNEL_SENT_CLOSE)) return channel_process_status(
? LSH_OK | LSH_CHANNEL_FINISHED closure->table, channel_number,
: LSH_OK | LSH_GOON; ( (channel->flags & (CHANNEL_SENT_CLOSE))
? LSH_OK | LSH_CHANNEL_FINISHED
: channel_close(channel)));
} }
werror("CLOSE on non-existant channel %d\n", werror("CLOSE on non-existant channel %d\n",
channel_number); channel_number);
...@@ -734,7 +778,8 @@ static int do_channel_open_confirm(struct packet_handler *c, ...@@ -734,7 +778,8 @@ static int do_channel_open_confirm(struct packet_handler *c,
channel->send_window_size = window_size; channel->send_window_size = window_size;
channel->send_max_packet = max_packet; channel->send_max_packet = max_packet;
return CHANNEL_OPEN_CONFIRM(channel); return channel_process_status(closure->table, local_channel_number,
CHANNEL_OPEN_CONFIRM(channel));
} }
werror("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel %d\n", werror("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel %d\n",
local_channel_number); local_channel_number);
...@@ -783,9 +828,9 @@ static int do_channel_open_failure(struct packet_handler *c, ...@@ -783,9 +828,9 @@ static int do_channel_open_failure(struct packet_handler *c,
int res = CHANNEL_OPEN_FAILURE(channel); int res = CHANNEL_OPEN_FAILURE(channel);
lsh_string_free(packet); lsh_string_free(packet);
dealloc_channel(closure->table, channel_number);
return channel_process_status(closure->table, channel_number,
return res; res | LSH_CHANNEL_FINISHED);
} }
werror("Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE on channel %d\n", werror("Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE on channel %d\n",
channel_number); channel_number);
...@@ -822,8 +867,8 @@ static int do_channel_success(struct packet_handler *c, ...@@ -822,8 +867,8 @@ static int do_channel_success(struct packet_handler *c,
lsh_string_free(packet); lsh_string_free(packet);
if (channel && channel->channel_success) if (channel && channel->channel_success)
return CHANNEL_SUCCESS(channel); return channel_process_status(closure->table, channel_number,
CHANNEL_SUCCESS(channel));
} }
lsh_string_free(packet); lsh_string_free(packet);
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
...@@ -854,8 +899,8 @@ static int do_channel_failure(struct packet_handler *c, ...@@ -854,8 +899,8 @@ static int do_channel_failure(struct packet_handler *c,
lsh_string_free(packet); lsh_string_free(packet);
if (channel && channel->channel_failure) if (channel && channel->channel_failure)
return CHANNEL_FAILURE(channel); return channel_process_status(closure->table, channel_number,
CHANNEL_FAILURE(channel));
} }
lsh_string_free(packet); lsh_string_free(packet);
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
......
...@@ -116,6 +116,7 @@ struct channel_table ...@@ -116,6 +116,7 @@ struct channel_table
* better to store this in the connection struct */ * better to store this in the connection struct */
uid_t user; /* Authenticated user */ uid_t user; /* Authenticated user */
#endif #endif
/* Channels are indexed by local number */ /* Channels are indexed by local number */
struct ssh_channel **channels; struct ssh_channel **channels;
...@@ -127,6 +128,12 @@ struct channel_table ...@@ -127,6 +128,12 @@ struct channel_table
UINT32 next_channel; UINT32 next_channel;
UINT32 used_channels; UINT32 used_channels;
UINT32 max_channels; /* Max number of channels allowed */ UINT32 max_channels; /* Max number of channels allowed */
/* If non-zero, close connection after all active channels have died. */
int pending_close;
/* FIXME: Perhaps we should use an flag to indicate whether or not
* new channels can be opened? */
}; };
/* SSH_MSG_GLOBAL_REQUEST */ /* SSH_MSG_GLOBAL_REQUEST */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment