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

* src/channel.c (global_request_status): New class.

(make_global_request_status): New function.
(global_request_response): New class.
(do_global_request_response): New function.
(make_global_request_response): New function.
(do_global_request): Pass a callback object to the handler.

* src/channel.h (channel_table): New attributes
active_global_requests and pending_global_requests.
(global_request_callback): New class.
(global_request): Let the handler method take a
global_request_callback as argument.

Rev: src/channel.c:1.39
Rev: src/channel.h:1.33
parent 1c7e71d5
......@@ -310,6 +310,80 @@ static int channel_process_status(struct channel_table *table,
#define END(s) foo_finish: do { lsh_string_free((s)); return foo_res; } while(0)
/* Channel related messages */
/* GABA:
(class
(name global_request_status)
(vars
; -1 for still active requests,
; 0 for failure,
; 1 for success
(status . int)))
*/
static struct global_request_status *make_global_request_status(void)
{
NEW(global_request_status, self);
self->status = -1;
return self;
}
/* GABA:
(class
(name global_request_response)
(super global_request_callback)
(vars
(active object global_request_status)))
*/
static int
do_global_request_response(struct global_request_callback *c,
int success)
{
CAST(global_request_response, self, c);
struct object_queue *q = self->super.connection->channels->active_global_requests;
int res = 0;
assert( self->active->status == -1);
assert( (success == 0) || (success == 1) );
assert( !object_queue_is_empty(q));
self->active->status = success;
for (;;)
{
CAST(global_request_status, n, object_queue_peek_head(q));
if (!n || (n->status < 0))
return res;
object_queue_remove_head(q);
res |= A_WRITE(self->super.connection->write,
(n->status
? format_global_success()
: format_global_failure()));
if (LSH_CLOSEDP(res))
return res;
}
}
static struct global_request_callback *
make_global_request_response(struct ssh_connection *connection,
struct global_request_status *active)
{
NEW(global_request_response, self);
self->super.connection = connection;
self->super.response = do_global_request_response;
self->active = active;
return &self->super;
}
static int do_global_request(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
......@@ -330,12 +404,22 @@ static int do_global_request(struct packet_handler *c,
&& parse_boolean(&buffer, &want_reply))
{
struct global_request *req;
struct global_request_callback *c = NULL;
if (!name || !(req = ALIST_GET(closure->global_requests, name)))
RETURN (A_WRITE(connection->write,
format_global_failure()));
RETURN (GLOBAL_REQUEST(req, connection, want_reply, &buffer));
if (want_reply)
{
struct global_request_status *a = make_global_request_status();
object_queue_add_tail(connection->channels->active_global_requests,
&a->super);
c = make_global_request_response(connection, a);
}
RETURN (GLOBAL_REQUEST(req, connection, &buffer, c));
}
RETURN (LSH_FAIL | LSH_DIE);
......@@ -374,7 +458,7 @@ static int do_channel_open_response(struct channel_open_callback *c,
"(shouldn't happen...)", ""));
}
/* FIXME: This copying could just as wel be done by the
/* FIXME: This copying could just as well be done by the
* CHANNEL_OPEN handler? Then we can remove the corresponding fields
* from the closure as well. */
channel->send_window_size = closure->window_size;
......
......@@ -110,7 +110,7 @@
;; (open_failure method int)
(open_continuation object command_continuation)
;; Queue of channel requests that we expect replies on
; Queue of channel requests that we expect replies on
(pending_requests struct object_queue)))
; Reply from SSH_MSG_CHANNEL_REQUEST
......@@ -161,6 +161,13 @@
(used_channels simple UINT32)
(max_channels simple UINT32) ; Max number of channels allowed
; Global requests that we have received, and should reply to
; in the right order
(active_global_requests object object_queue)
; Queue of global requests that we expect replies on.
(pending_global_requests object object_queue)
; If non-zero, close connection after all active channels have
; died.
(pending_close simple int)
......@@ -171,15 +178,28 @@
*/
/* SSH_MSG_GLOBAL_REQUEST */
/* GABA:
(class
(name global_request_callback)
(vars
(response method int "int success")
(connection object ssh_connection)))
*/
#define GLOBAL_REQUEST_CALLBACK(c, s) \
((c) ? ((c)->response((c), (s))) : LSH_OK | LSH_GOON)
/* GABA:
(class
(name global_request)
(vars
(handler method int "struct ssh_connection *connection"
"int want_reply" "struct simple_buffer *args")))
"struct simple_buffer *args"
"struct global_request_callback *response")))
*/
#define GLOBAL_REQUEST(r, c, w, a) ((r)->handler((r), (c), (w), (a)))
#define GLOBAL_REQUEST(r, c, a, n) ((r)->handler((r), (c), (a), (n)))
/* SSH_MSG_CHANNEL_OPEN */
......@@ -197,7 +217,7 @@
"struct lsh_string *args")
(connection object ssh_connection)))
*/
/* xxCLASS:
(class
(name channel_open_response)
......@@ -245,7 +265,7 @@
#define CHANNEL_REQUEST(s, c, conn, w, a) \
((s)->handler((s), (c), (conn), (w), (a)))
/* GABA:
/* ;;GABA:
(class
(name connection_startup)
(vars
......@@ -253,7 +273,7 @@
"struct ssh_connection *connection")))
*/
#define CONNECTION_START(c, s) ((c)->start((c), (s)))
/* #define CONNECTION_START(c, s) ((c)->start((c), (s))) */
void init_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