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

* src/channel.c (use_channel): New function to take a channel in

use.
(register_channel): New argument take_into_use.
(lookup_channel_reserved): New function that returns channels that
are marked as reserved, but not in use.
(do_channel_open_continue): Call register_channel with
take_in_use=1.
(do_channel_open_confirm): Use lookup_channel_reserved(). Call
use_channel().
(do_channel_open_failure): Use lookup_channel_reserved().
(format_channel_open): Renamed from prepare_channel_open. Don't
call alloc_channel() or register_channel().

* src/channel.h (CHANNEL_FREE, CHANNEL_RESERVED, CHANNEL_IN_USE):
New three-level classification for the in_use table.

* src/channel.c (exc_finish_channel_handler): Use pointer to
connection rather than to its channel table.

Rev: src/channel.c:1.71
Rev: src/channel.h:1.51
parent 3647cb0f
...@@ -156,15 +156,17 @@ struct lsh_string *prepare_window_adjust(struct ssh_channel *channel, ...@@ -156,15 +156,17 @@ struct lsh_string *prepare_window_adjust(struct ssh_channel *channel,
(name exc_finish_channel_handler) (name exc_finish_channel_handler)
(super exception_handler) (super exception_handler)
(vars (vars
(table object channel_table) (connection object ssh_connection)
;; (table object channel_table)
; Non-zero if the channel has already been deallocated. ; Non-zero if the channel has already been deallocated.
(dead . int) (dead . int)
; Local channel number ; Local channel number
(channel_number . UINT32))) (channel_number . UINT32)))
*/ */
static void do_exc_finish_channel_handler(struct exception_handler *s, static void
const struct exception *e) do_exc_finish_channel_handler(struct exception_handler *s,
const struct exception *e)
{ {
CAST(exc_finish_channel_handler, self, s); CAST(exc_finish_channel_handler, self, s);
...@@ -174,10 +176,10 @@ static void do_exc_finish_channel_handler(struct exception_handler *s, ...@@ -174,10 +176,10 @@ static void do_exc_finish_channel_handler(struct exception_handler *s,
if (self->dead) if (self->dead)
werror("channel.c: EXC_FINISH_PENDING on dead channel.\n"); werror("channel.c: EXC_FINISH_PENDING on dead channel.\n");
self->table->pending_close = 1; self->connection->table->pending_close = 1;
if (!self->table->next_channel) if (!self->connection->table->next_channel)
EXCEPTION_RAISE(self->super.parent, &finish_read_exception); EXCEPTION_RAISE(self->connection->e, &finish_read_exception);
break; break;
case EXC_FINISH_CHANNEL: case EXC_FINISH_CHANNEL:
...@@ -197,7 +199,7 @@ static void do_exc_finish_channel_handler(struct exception_handler *s, ...@@ -197,7 +199,7 @@ static void do_exc_finish_channel_handler(struct exception_handler *s,
else else
{ {
struct ssh_channel *channel struct ssh_channel *channel
= self->table->channels[self->channel_number]; = self->connection->table->channels[self->channel_number];
assert(channel); assert(channel);
assert(channel->resources->super.alive); assert(channel->resources->super.alive);
...@@ -207,13 +209,14 @@ static void do_exc_finish_channel_handler(struct exception_handler *s, ...@@ -207,13 +209,14 @@ static void do_exc_finish_channel_handler(struct exception_handler *s,
KILL_RESOURCE_LIST(channel->resources); KILL_RESOURCE_LIST(channel->resources);
dealloc_channel(self->table, self->channel_number); dealloc_channel(self->connection->table, self->channel_number);
self->dead = 1; self->dead = 1;
if (self->table->pending_close && !self->table->next_channel) if (self->connection->table->pending_close &&
!self->connection->table->next_channel)
{ {
/* FIXME: Send a SSH_DISCONNECT_BY_APPLICATION message? */ /* FIXME: Send a SSH_DISCONNECT_BY_APPLICATION message? */
EXCEPTION_RAISE(self->super.parent, &finish_read_exception); EXCEPTION_RAISE(self->connection->e, &finish_read_exception);
} }
} }
break; break;
...@@ -223,7 +226,7 @@ static void do_exc_finish_channel_handler(struct exception_handler *s, ...@@ -223,7 +226,7 @@ static void do_exc_finish_channel_handler(struct exception_handler *s,
} }
static struct exception_handler * static struct exception_handler *
make_exc_finish_channel_handler(struct channel_table *table, make_exc_finish_channel_handler(struct ssh_connection *connection,
UINT32 channel_number, UINT32 channel_number,
struct exception_handler *e, struct exception_handler *e,
const char *context) const char *context)
...@@ -233,7 +236,7 @@ make_exc_finish_channel_handler(struct channel_table *table, ...@@ -233,7 +236,7 @@ make_exc_finish_channel_handler(struct channel_table *table,
self->super.raise = do_exc_finish_channel_handler; self->super.raise = do_exc_finish_channel_handler;
self->super.context = context; self->super.context = context;
self->table = table; self->connection = connection;
self->channel_number = channel_number; self->channel_number = channel_number;
self->dead = 0; self->dead = 0;
...@@ -284,10 +287,10 @@ int alloc_channel(struct channel_table *table) ...@@ -284,10 +287,10 @@ int alloc_channel(struct channel_table *table)
for(i = table->next_channel; i < table->used_channels; i++) for(i = table->next_channel; i < table->used_channels; i++)
{ {
if (!table->in_use[i]) if (table->in_use[i] == CHANNEL_FREE)
{ {
assert(!table->channels[i]); assert(!table->channels[i]);
table->in_use[i] = 1; table->in_use[i] = CHANNEL_RESERVED;
table->next_channel = i+1; table->next_channel = i+1;
verbose("Allocated local channel number %i\n", i); verbose("Allocated local channel number %i\n", i);
...@@ -310,6 +313,7 @@ int alloc_channel(struct channel_table *table) ...@@ -310,6 +313,7 @@ int alloc_channel(struct channel_table *table)
lsh_space_free(table->channels); lsh_space_free(table->channels);
table->channels = new_channels; table->channels = new_channels;
/* FIXME: Use realloc(). */
new_in_use = lsh_space_alloc(new_size); new_in_use = lsh_space_alloc(new_size);
memcpy(new_in_use, table->in_use, table->used_channels); memcpy(new_in_use, table->in_use, table->used_channels);
lsh_space_free(table->in_use); lsh_space_free(table->in_use);
...@@ -320,7 +324,7 @@ int alloc_channel(struct channel_table *table) ...@@ -320,7 +324,7 @@ int alloc_channel(struct channel_table *table)
table->next_channel = table->used_channels = i+1; table->next_channel = table->used_channels = i+1;
table->in_use[i] = 1; table->in_use[i] = CHANNEL_RESERVED;
verbose("Allocated local channel number %i\n", i); verbose("Allocated local channel number %i\n", i);
return i; return i;
...@@ -333,41 +337,73 @@ void dealloc_channel(struct channel_table *table, int i) ...@@ -333,41 +337,73 @@ void dealloc_channel(struct channel_table *table, int i)
verbose("Deallocating local channel %i\n", i); verbose("Deallocating local channel %i\n", i);
table->channels[i] = NULL; table->channels[i] = NULL;
table->in_use[i] = 0; table->in_use[i] = CHANNEL_FREE;
if ( (unsigned) i < table->next_channel) if ( (unsigned) i < table->next_channel)
table->next_channel = i; table->next_channel = i;
} }
void
use_channel(struct ssh_connection *connection,
UINT32 local_channel_number)
{
struct channel_table *table = connection->table;
struct ssh_channel *channel = table->channels[local_channel_number];
assert(channel);
assert(table->in_use[local_channel_number] == CHANNEL_RESERVED);
table->in_use[local_channel_number] = CHANNEL_IN_USE;
verbose("Taking channel %i in use, (local %i).\n",
channel->channel_number, local_channel_number);
}
void void
register_channel(struct ssh_connection *connection, register_channel(struct ssh_connection *connection,
UINT32 local_channel_number, UINT32 local_channel_number,
struct ssh_channel *channel) struct ssh_channel *channel,
int take_into_use)
{ {
struct channel_table *table = connection->table; struct channel_table *table = connection->table;
assert(table->in_use[local_channel_number]); assert(table->in_use[local_channel_number] == CHANNEL_RESERVED);
assert(!table->channels[local_channel_number]); assert(!table->channels[local_channel_number]);
verbose("Taking channel %i in use, (local %i).\n", verbose("Registering local channel %i.\n",
channel->channel_number, local_channel_number); local_channel_number);
table->channels[local_channel_number] = channel;
/* FIXME: Is this the right place to install this exception handler? */ /* FIXME: Is this the right place to install this exception handler? */
channel->e = make_exc_finish_channel_handler(table, channel->e =
local_channel_number, make_exc_finish_channel_handler(connection,
connection->e, local_channel_number,
HANDLER_CONTEXT); channel->e ? channel->e : connection->e,
HANDLER_CONTEXT);
table->channels[local_channel_number] = channel;
if (take_into_use)
use_channel(connection, local_channel_number);
REMEMBER_RESOURCE(connection->resources, &channel->resources->super); REMEMBER_RESOURCE(connection->resources, &channel->resources->super);
} }
struct ssh_channel *lookup_channel(struct channel_table *table, UINT32 i) struct ssh_channel *
lookup_channel(struct channel_table *table, UINT32 i)
{
return ( (i < table->used_channels)
&& (table->in_use[i] == CHANNEL_IN_USE))
? table->channels[i] : NULL;
}
struct ssh_channel *
lookup_channel_reserved(struct channel_table *table, UINT32 i)
{ {
return (i < table->used_channels) return ( (i < table->used_channels)
&& (table->in_use[i] == CHANNEL_RESERVED))
? table->channels[i] : NULL; ? table->channels[i] : NULL;
} }
/* FIXME: It seems suboptimal to send a window adjust message for *every* write that we do. /* FIXME: It seems suboptimal to send a window adjust message for *every* write that we do.
* A better scheme might be as follows: * A better scheme might be as follows:
* *
...@@ -613,7 +649,8 @@ do_channel_open_continue(struct command_continuation *c, ...@@ -613,7 +649,8 @@ do_channel_open_continue(struct command_continuation *c,
channel->write = self->connection->write; channel->write = self->connection->write;
register_channel(self->connection, register_channel(self->connection,
self->local_channel_number, channel); self->local_channel_number, channel,
1);
/* FIXME: Doesn't support sending extra arguments with the /* FIXME: Doesn't support sending extra arguments with the
* confirmation message. */ * confirmation message. */
...@@ -1172,20 +1209,26 @@ do_channel_open_confirm(struct packet_handler *closure UNUSED, ...@@ -1172,20 +1209,26 @@ do_channel_open_confirm(struct packet_handler *closure UNUSED,
&& parse_uint32(&buffer, &max_packet) && parse_uint32(&buffer, &max_packet)
&& parse_eod(&buffer)) && parse_eod(&buffer))
{ {
struct ssh_channel *channel = lookup_channel(connection->table, struct ssh_channel *channel =
local_channel_number); lookup_channel_reserved(connection->table,
local_channel_number);
lsh_string_free(packet); lsh_string_free(packet);
if (channel && channel->open_continuation) if (channel)
{ {
struct command_continuation *c = channel->open_continuation; struct command_continuation *c = channel->open_continuation;
assert(c);
channel->open_continuation = NULL; channel->open_continuation = NULL;
channel->channel_number = remote_channel_number; channel->channel_number = remote_channel_number;
channel->send_window_size = window_size; channel->send_window_size = window_size;
channel->send_max_packet = max_packet; channel->send_max_packet = max_packet;
/* FIXME: Initialize channel->write here? */
use_channel(connection, local_channel_number);
COMMAND_RETURN(c, channel); COMMAND_RETURN(c, channel);
} }
else else
...@@ -1228,16 +1271,19 @@ do_channel_open_failure(struct packet_handler *closure UNUSED, ...@@ -1228,16 +1271,19 @@ do_channel_open_failure(struct packet_handler *closure UNUSED,
&& parse_string(&buffer, &language_length, &language) && parse_string(&buffer, &language_length, &language)
&& parse_eod(&buffer)) && parse_eod(&buffer))
{ {
struct ssh_channel *channel = lookup_channel(connection->table, struct ssh_channel *channel =
channel_number); lookup_channel_reserved(connection->table,
channel_number);
lsh_string_free(packet); lsh_string_free(packet);
if (channel && channel->open_continuation) if (channel)
{ {
static const struct exception finish_exception static const struct exception finish_exception
= STATIC_EXCEPTION(EXC_FINISH_CHANNEL, "CHANNEL_OPEN failed."); = STATIC_EXCEPTION(EXC_FINISH_CHANNEL, "CHANNEL_OPEN failed.");
assert(channel->open_continuation);
/* FIXME: It would be nice to pass the message on. */ /* FIXME: It would be nice to pass the message on. */
EXCEPTION_RAISE(channel->e, EXCEPTION_RAISE(channel->e,
make_channel_open_exception(reason, "Refused by peer")); make_channel_open_exception(reason, "Refused by peer"));
...@@ -1719,34 +1765,25 @@ make_channel_io_exception_handler(struct ssh_channel *channel, ...@@ -1719,34 +1765,25 @@ make_channel_io_exception_handler(struct ssh_channel *channel,
} }
struct lsh_string * struct lsh_string *
prepare_channel_open(struct ssh_connection *connection, format_channel_open(int type, UINT32 local_channel_number,
int type, struct ssh_channel *channel, struct ssh_channel *channel,
const char *format, ...) const char *format, ...)
{ {
int index;
va_list args; va_list args;
UINT32 l1, l2; UINT32 l1, l2;
struct lsh_string *packet; struct lsh_string *packet;
#define OPEN_FORMAT "%c%a%i%i%i" #define OPEN_FORMAT "%c%a%i%i%i"
#define OPEN_ARGS SSH_MSG_CHANNEL_OPEN, type, (UINT32) index, \ #define OPEN_ARGS SSH_MSG_CHANNEL_OPEN, type, local_channel_number, \
channel->rec_window_size, channel->rec_max_packet channel->rec_window_size, channel->rec_max_packet
debug("prepare_channel_open: rec_window_size = %i,\n" debug("format_channel_open: rec_window_size = %i,\n"
" rec_max_packet = %i,\n" " rec_max_packet = %i,\n"
" max_packet = %i\n", " max_window = %i\n",
channel->rec_window_size, channel->rec_window_size,
channel->rec_max_packet, channel->rec_max_packet,
channel->max_window); channel->max_window);
index = alloc_channel(connection->table);
if (index < 0)
return 0;
register_channel(connection, index, channel);
l1 = ssh_format_length(OPEN_FORMAT, OPEN_ARGS); l1 = ssh_format_length(OPEN_FORMAT, OPEN_ARGS);
va_start(args, format); va_start(args, format);
......
...@@ -68,7 +68,13 @@ ...@@ -68,7 +68,13 @@
; is needed for deallocating it. ; is needed for deallocating it.
;; (local_number . UINT32) ;; (local_number . UINT32)
; Where to pass errors ; Where to pass errors. This is used for two different
; purposes: If opening the channel fails, EXC_CHANNEL_OPEN is
; raised. Once the channel is open, this handler is used for
; EXC_FINISH_CHANNEL and EXC_FINISH_PENDING. If the channel was
; opened on the peer's request, the connection's exception
; handler is a parent of the channel's. But that is not true in
; general.
(e object exception_handler) (e object exception_handler)
; Resources associated with the channel. This object is also ; Resources associated with the channel. This object is also
...@@ -129,8 +135,7 @@ ...@@ -129,8 +135,7 @@
; Reply from SSH_MSG_CHANNEL_REQUEST ; Reply from SSH_MSG_CHANNEL_REQUEST
;; (channel_success method int) ;; (channel_success method int)
;; (channel_failure method int))) ;; (channel_failure method int))) */
*/
#define CHANNEL_RECEIVE(s, t, d) \ #define CHANNEL_RECEIVE(s, t, d) \
((s)->receive((s), (t), (d))) ((s)->receive((s), (t), (d)))
...@@ -149,6 +154,11 @@ ...@@ -149,6 +154,11 @@
#define CHANNEL_OPEN_FAILURE(s) \ #define CHANNEL_OPEN_FAILURE(s) \
((s)->open_failure((s))) ((s)->open_failure((s)))
/* Values used in the in_use array. */
#define CHANNEL_FREE 0
#define CHANNEL_RESERVED 1
#define CHANNEL_IN_USE 2
/* GABA: /* GABA:
(class (class
(name channel_table) (name channel_table)
...@@ -289,11 +299,19 @@ struct channel_table *make_channel_table(void); ...@@ -289,11 +299,19 @@ struct channel_table *make_channel_table(void);
int alloc_channel(struct channel_table *table); int alloc_channel(struct channel_table *table);
void dealloc_channel(struct channel_table *table, int i); void dealloc_channel(struct channel_table *table, int i);
void
use_channel(struct ssh_connection *connection,
UINT32 local_channel_number);
void register_channel(struct ssh_connection *connection, void register_channel(struct ssh_connection *connection,
UINT32 local_channel_number, UINT32 local_channel_number,
struct ssh_channel *channel); struct ssh_channel *channel,
int take_into_use);
struct ssh_channel *lookup_channel(struct channel_table *table, UINT32 i); struct ssh_channel *
lookup_channel(struct channel_table *table, UINT32 i);
struct ssh_channel *
lookup_channel_reserved(struct channel_table *table, UINT32 i);
struct abstract_write *make_channel_write(struct ssh_channel *channel); struct abstract_write *make_channel_write(struct ssh_channel *channel);
struct abstract_write *make_channel_write_extended(struct ssh_channel *channel, struct abstract_write *make_channel_write_extended(struct ssh_channel *channel,
...@@ -319,10 +337,16 @@ struct lsh_string *prepare_window_adjust(struct ssh_channel *channel, ...@@ -319,10 +337,16 @@ struct lsh_string *prepare_window_adjust(struct ssh_channel *channel,
void channel_start_receive(struct ssh_channel *channel); void channel_start_receive(struct ssh_channel *channel);
#if 0
struct lsh_string *prepare_channel_open(struct ssh_connection *connection, struct lsh_string *prepare_channel_open(struct ssh_connection *connection,
int type, int type,
struct ssh_channel *channel, struct ssh_channel *channel,
const char *format, ...); const char *format, ...);
#endif
struct lsh_string *
format_channel_open(int type, UINT32 local_channel_number,
struct ssh_channel *channel,
const char *format, ...);
struct lsh_string *format_channel_request(int type, struct lsh_string *format_channel_request(int type,
struct ssh_channel *channel, struct ssh_channel *channel,
......
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