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

Changed the closure mechanism. Now, the first argument to all closures

is a pointer to a pointer to itself, which may be changed. They no
longer return themselves (or a replacement).

Rev: src/abstract_io.h:1.5
Rev: src/blocking_write.c:1.3
Rev: src/blocking_write.h:1.3
Rev: src/client.c:1.5
Rev: src/client.h:1.4
Rev: src/debug.c:1.6
Rev: src/debug.h:1.5
Rev: src/encrypt.c:1.6
Rev: src/io.c:1.6
Rev: src/lshd.c:1.2
Rev: src/packet_dispatch.c:1.4
Rev: src/pad.c:1.6
Rev: src/read_line.c:1.3
Rev: src/read_line.h:1.4
Rev: src/read_packet.c:1.3
Rev: src/unpad.c:1.5
Rev: src/void.c:1.6
Rev: src/write_buffer.c:1.4
Rev: src/write_buffer.h:1.4
Rev: src/zlib.c:1.5
parent e80942e0
......@@ -8,9 +8,12 @@
#include "lsh_types.h"
#if 0
struct abstract_read;
typedef int (*abstract_read_f)(struct abstract_read *closure,
typedef int (*abstract_read_f)(struct abstract_read *r,
UINT8 *buffer, UINT32 length);
#endif
/* A read-function returning n means:
*
* n > 0: n bytes were read successfully.
......@@ -23,34 +26,43 @@ typedef int (*abstract_read_f)(struct abstract_read *closure,
struct abstract_read
{
abstract_read_f read;
int (*read)(struct abstract_read **r,
UINT8 *buffer, UINT32 length);
};
#define A_READ(f, buffer, length) (f)->read((f), (buffer), (length))
#define A_READ(f, buffer, length) (f)->read(&(f), (buffer), (length))
#if 0
struct read_handler;
typedef struct read_handler * (*read_handler_f)(struct read_handler *closure,
struct abstract_read *read);
#endif
/* May store a new handler into *h. */
struct read_handler
{
read_handler_f handler;
int (*handler)(struct read_handler **h,
struct abstract_read *read);
};
#define READ_HANDLER(h, read) ((h)->handler((h), (read)))
#define READ_HANDLER(h, read) ((h)->handler(&(h), (read)))
/* FIXME: What should writers return? Perhaps a new writer,
* analogous to read-handlers? */
#if 0
struct abstract_write;
typedef int (*abstract_write_f)(struct abstract_write *closure,
struct lsh_string *packet);
#endif
/* May store a new handler into *w. */
struct abstract_write
{
abstract_write_f write;
int (*write)(struct abstract_write **w,
struct lsh_string *packet);
};
#define A_WRITE(f, packet) ((f)->write((f), (packet)))
#define A_WRITE(f, packet) ((f)->write(&(f), (packet)))
/* A processor that passes its result on to another processor */
struct abstract_write_pipe
......
......@@ -6,9 +6,12 @@
#include <unistd.h>
#endif
static int do_write(struct pad_processor *closure,
static int do_write(struct abstract_write **w,
struct lsh_string *packet)
{
struct packet_blocking_write *closure
= (struct packet_blocking_write *) *w;
UINT32 left = packet->length;
UINT8 *p = packet->data;
......@@ -36,10 +39,10 @@ struct abstract_write *make_blocking_write_procesor(int fd)
struct blocking_write_processor *closure
= xalloc(sizeof(struct blocking_write_processor_processor));
closure->p->f = (abstract_write_f) do_write;
closure->p->f = do_write;
closure->fd = fd;
return (struct abstract_write *) closure;
return &closure->super;
}
......@@ -5,9 +5,9 @@
#ifndef LSH_BLOCKING_WRITE_H_INCLUDED
#define LSH_BLOCKING_WRITE_H_INCLUDED
struct blocking_write_processor
struct packet_blocking_write
{
struct abstract_write w;
struct abstract_write super;
int fd;
};
......
......@@ -19,9 +19,12 @@
struct read_handler *make_client_read_line();
struct callback *make_client_close_handler();
static int client_initiate(struct client_callback *closure,
static int client_initiate(struct fd_callback *c,
int fd)
{
struct client_callback *closure
= (struct client_callback *) c;
struct ssh_connection *connection = ssh_connection_alloc();
struct abstract_write *write =
io_read_write(closure->backend, fd,
......@@ -44,10 +47,13 @@ struct client_line_handler
struct ssh_connection *connection;
};
static struct read_handler *do_line(struct client_line_handler *closure,
static struct read_handler *do_line(struct line_handler **h,
UINT32 length,
UINT8 *line)
{
struct client_line_handler *closure
= (struct client_line_handler *) *h;
if ( (length >= 4) && !memcmp(line, "SSH-", 4))
{
/* Parse and remember format string */
......@@ -55,7 +61,7 @@ static struct read_handler *do_line(struct client_line_handler *closure,
|| ((length >= 9) && !memcmp(line + 4, "1.99-", 5)))
{
struct read_handler *new
= make_read_packet(make_debug_processor(make_packet_void(),
= make_read_packet(make_packet_debug(make_packet_void(),
stderr),
closure->connection->max_packet);
......@@ -73,8 +79,10 @@ static struct read_handler *do_line(struct client_line_handler *closure,
werror_safe(length, line);
werror("\n");
fatal("client.c: do_line: Unsupported version.\n");
/* FIXME: What could be returned here? */
/* FIXME: Clean up properly */
free(closure);
*h = 0;
return 0;
}
}
......@@ -93,10 +101,10 @@ struct read_handler *make_client_read_line(struct ssh_connection *s)
struct client_line_handler *closure
= xalloc(sizeof(struct client_line_handler));
closure->super.handler = (line_handler_f) do_line;
closure->super.handler = do_line;
closure->connection = s;
return make_read_line( (struct line_handler *) closure);
return make_read_line(&closure->super);
}
struct fd_callback *make_client_callback(struct io_backend *b,
......@@ -106,12 +114,12 @@ struct fd_callback *make_client_callback(struct io_backend *b,
{
struct client_callback *connected = xalloc(sizeof(struct client_callback));
connected->c.f = (fd_callback_f) client_initiate;
connected->super.f = client_initiate;
connected->backend = b;
connected->block_size = block_size;
connected->id_comment = comment;
return (struct fd_callback *) connected;
return &connected->super;
}
static int client_die(struct callback *closure)
......
......@@ -9,7 +9,7 @@
struct client_callback
{
struct fd_callback c;
struct fd_callback super;
struct io_backend *backend;
UINT32 block_size;
char *id_comment;
......
......@@ -5,9 +5,12 @@
#include "debug.h"
#include "xalloc.h"
static int do_debug(struct debug_processor *closure,
static int do_debug(struct abstract_write **w,
struct lsh_string *packet)
{
struct packet_debug *closure
= (struct packet_debug *) *w;
UINT32 i;
fprintf(closure->output, "DEBUG: (packet size %d = 0x%x)\n",
......@@ -27,15 +30,15 @@ static int do_debug(struct debug_processor *closure,
}
struct abstract_write *
make_debug_processor(struct abstract_write *continuation, FILE *output)
make_packet_debug(struct abstract_write *continuation, FILE *output)
{
struct debug_processor *closure = xalloc(sizeof(struct debug_processor));
struct packet_debug *closure = xalloc(sizeof(struct packet_debug));
closure->super.super.write = (abstract_write_f) do_debug;
closure->super.super.write = do_debug;
closure->super.next = continuation;
closure->output = output;
return (struct abstract_write *) closure;
return &closure->super.super;
}
......@@ -9,14 +9,14 @@
#include <stdio.h>
#include "abstract_io.h"
struct debug_processor
struct packet_debug
{
struct abstract_write_pipe super;
FILE *output;
};
struct abstract_write *
make_debug_processor(struct abstract_write *continuation, FILE *output);
make_packet_debug(struct abstract_write *continuation, FILE *output);
#endif */ LSH_DEBUG_H_INCLUDED */
......@@ -5,9 +5,12 @@
#include "encrypt.h"
#include "xalloc.h"
static int do_encrypt(struct encrypt_processor *closure,
static int do_encrypt(struct encrypt_processor **c,
struct simple_packet *packet)
{
struct encrypt_processor *closure
= (struct encrypt_processor *) *c;
/* FIXME: Use ssh_format() */
struct simple_packet *new
= lsh_string_alloc(packet->length + closure->mac_size);
......@@ -36,7 +39,7 @@ make_packet_encrypt(struct abstract_write *continuation,
{
struct encrypt_processor *closure = xalloc(sizeof(struct encrypt_processor));
closure->c.p.f = (abstract_write_f) do_encrypt;
closure->super.super.write = do_encrypt;
closure->c.next = continuation;
closure->mac_size = mac_size;
closure->mac_function = mac_function;
......@@ -44,7 +47,7 @@ make_packet_encrypt(struct abstract_write *continuation,
closure->encrypt_function = encrypt_function;
closure->encrypt_state = encrypt_state;
return (struct abstract_write *) closure;
return &closure->super.super;
}
......@@ -22,12 +22,15 @@
struct fd_read
{
struct abstract_read a;
struct abstract_read super;
int fd;
};
static int do_read(struct fd_read *closure, UINT8 *buffer, UINT32 length)
static int do_read(struct abstract_read **r, UINT8 *buffer, UINT32 length)
{
struct fd_read *closure
= (struct fd_read *) *r;
while(1)
{
int res = read(closure->fd, buffer, length);
......@@ -96,7 +99,7 @@ void io_run(struct io_backend *b)
fds = alloca(sizeof(struct pollfd) * nfds);
/* Handle fds in order: read, accept, connect, write, */
/* Handle fds in order: write, read, accept, connect. */
i = 0;
FOR_FDS(struct io_fd, fd, b->io, i++)
......@@ -195,13 +198,12 @@ void io_run(struct io_backend *b)
&& (fds[i].revents & POLLIN))
{
struct fd_read r =
{ { (abstract_read_f) do_read }, fd->fd };
{ { do_read }, fd->fd };
/* The handler function returns a new handler for the
* file, or NULL. */
if (!(fd->handler
= READ_HANDLER(fd->handler,
(struct abstract_read *) &r)))
if (!(READ_HANDLER(fd->handler,
&r.super)))
{
fd->please_close = 1;
}
......@@ -213,6 +215,9 @@ void io_run(struct io_backend *b)
* After a write error, read state must be freed,
* and vice versa. */
UNLINK_FD;
b->nio--;
if (fd->handler)
free(fd->handler);
free(fd->buffer);
free(fd);
continue;
......@@ -444,5 +449,5 @@ struct abstract_write *io_read_write(struct io_backend *b,
b->io = f;
b->nio++;
return (struct abstract_write *) buffer;
return &buffer->super;
}
......@@ -21,15 +21,18 @@ void usage()
int main(int argc, char **argv)
{
char *host = NULL; /* Interface to bind */
char *port = "ssh";
int verbose;
int option;
struct sockaddr_in local;
/* For filtering messages. Could perhaps also be used when converting
* strings to and from UTF8. */
setlocale(LC_CTYPE, "");
while((option = getopt(argc, argv, "dp:q")) != -1)
while((option = getopt(argc, argv, "dp:qi:")) != -1)
switch(option)
{
case 'p':
......@@ -41,6 +44,9 @@ int main(int argc, char **argv)
case 'd':
debug_flag = 1;
break;
case 'i':
host = optarg;
break;
default:
usage();
}
......@@ -48,7 +54,7 @@ int main(int argc, char **argv)
if ( (argc - optind) != 0)
usage();
if (!get_inaddr(&remote, NULL, port, "tcp"))
if (!get_inaddr(&local, host, port, "tcp"))
{
fprintf(stderr, "No such host or service");
exit(1);
......@@ -61,8 +67,8 @@ int main(int argc, char **argv)
BLOCK_SIZE;
};
io_connect(&backend, &remote, NULL,
make_client_callback(backend, BLOCK_SIZE));
io_listen(&backend, &local,
make_server_callback(backend, BLOCK_SIZE));
}
io_run();
......
......@@ -6,9 +6,12 @@
#include "xalloc.h"
#include "werror.h"
static int do_dispatch(struct dispatch_processor *closure,
static int do_dispatch(struct abstract_write **c,,
struct lsh_string *packet)
{
struct dispatch_processor *closure
= (struct dispatch_processor *) *c;
unsigned start;
unsigned end;
unsigned msg;
......@@ -69,7 +72,7 @@ make_dispatch_processor(unsigned size,
closure->table_size = size;
closure->dispatch_table = table;
return (struct abstract_write *) closure;
return &closure->super;
}
......
......@@ -6,9 +6,12 @@
#include "xalloc.h"
#include <assert.h>
static int do_pad(struct pad_processor *closure,
static int do_pad(struct abstract_write **c,
struct lsh_string *packet)
{
struct pad_processor *closure
= (struct pad_processor *) *c;
UINT32 new_size;
UINT8 padding;
......@@ -27,12 +30,6 @@ static int do_pad(struct pad_processor *closure,
/* FIXME: Use ssh_format() */
new = lsh_string_alloc(new_size);
#if 0
ssh = (struct ssh_packet *) new->data;
ssh->length = htonl(new_size);
ssh->padding_length = padding;
#endif
WRITE_UINT32(new->data, new_size - 4);
new->data[4] = padding;
......@@ -53,11 +50,11 @@ make_pad_processor(struct abstract_write *continuation,
{
struct pad_processor *closure = xalloc(sizeof(struct pad_processor));
closure->c.p.f = (abstract_write_f) do_pad;
closure->super.super = do_pad;
closure->c.next = continuation;
closure->block_size = block_size;
closure->random = random;
closure->state = state;
return (struct abstract_write *) closure;
return &closure->super.super;
}
......@@ -15,9 +15,12 @@ struct string_read
UINT32 index;
};
static int do_string_read(struct string_read *closure,
static int do_string_read(struct abstract_read **r,
UINT8 *buffer, UINT32 length)
{
struct string_read *closure
= (struct string_read *) *r;
UINT32 left = closure->line->pos - closure->index;
UINT32 to_read = MIN(length, left);
......@@ -27,14 +30,17 @@ static int do_string_read(struct string_read *closure,
return to_read;
}
static struct read_handler *do_read_line(struct read_line *closure,
static int do_read_line(struct read_handler **h,
struct abstract_read *read)
{
int n = A_READ(read, closure->buffer, MAX_LINE - closure->pos);
struct read_line *closure = (struct read_line *) *h;
UINT8 *eol;
UINT32 length;
struct read_handler *next;
int n = A_READ(read, closure->buffer, MAX_LINE - closure->pos);
if (n<0)
{
return 0;
......@@ -58,32 +64,42 @@ static struct read_handler *do_read_line(struct read_line *closure,
next = PROCESS_LINE(closure->handler, length, closure->buffer);
if (!next)
{
/* Read another line */
/* Number of characters that have been processed */
UINT32 done = eol - closure->buffer + 1;
UINT32 left = closure->pos - done;
memcpy(closure->buffer, closure->buffer + done, left);
closure->pos = left;
}
else
if (next)
{
/* Read no more lines. Instead, pass remaining data to next,
* and return a new read-handler. */
if (closure->pos)
{
struct string_read read =
{ { (abstract_read_f) do_string_read },
{ { do_string_read },
closure,
0 };
while(next && (read.index < closure->pos))
next = READ_HANDLER(next, &read.super);
if (!READ_HANDLER(next, &read.super))
return 0;
}
/* No data left */
free(closure);
return next;
*h = next;
return 1;
}
else
{
if (closure->handler)
{
/* Read another line */
/* Number of characters that have been processed */
UINT32 done = eol - closure->buffer + 1;
UINT32 left = closure->pos - done;
memcpy(closure->buffer, closure->buffer + done, left);
closure->pos = left;
}
else
{
/* Fail */
return 0;
}
}
}
......@@ -91,21 +107,21 @@ static struct read_handler *do_read_line(struct read_line *closure,
if (closure->pos == MAX_LINE)
{
werror("Too long line from server\n");
return NULL;
return 0;
}
return &(closure->super);
return 1;
}
struct read_handler *make_read_line(struct line_handler *handler)
{
struct read_line *closure = xalloc(sizeof(struct read_line));
closure->super.handler = (read_handler_f) do_read_line;
closure->super.handler = do_read_line;
closure->pos = 0;
closure->handler = handler;
return (struct read_handler *) closure;
return &closure->super;
}
......@@ -11,27 +11,32 @@
/* This limit follows the ssh specification */
#define MAX_LINE 255
#if 0
struct line_handler;
typedef struct read_handler * (*line_handler_f)(struct line_handler *closure,
UINT32 length,
UINT8 *line);
#endif
/* May store a new handler into *h. */
struct line_handler
{
line_handler_f handler;
struct read_handler * (*handler)(struct line_handler **h,
UINT32 length,
UINT8 *line);
};
#define PROCESS_LINE(h, length, line) \
((h)->handler((h), (length), (line)))
((h)->handler(&(h), (length), (line)))
struct read_line
{
struct read_handler super; /* Super type */
struct line_handler *handler;
UINT32 pos; /* Line buffer */
UINT8 buffer[MAX_LINE];
struct line_handler *handler;
};
struct read_handler *make_read_line(struct line_handler *handler);
......
......@@ -16,10 +16,10 @@
#define WAIT_CONTENTS 1
#define WAIT_MAC 2
static struct read_handler *do_read_packet(struct read_handler *c,
int do_read_packet(struct read_handler **h,
struct abstract_read *read)
{
struct read_packet *closure = (struct read_packet *) c;
struct read_packet *closure = (struct read_packet *) *h;
while(1)
{
switch(closure->state)
......@@ -39,7 +39,7 @@ static struct read_handler *do_read_packet(struct read_handler *c,
switch(n)
{
case 0:
return c;
return 1;
case A_FAIL:
werror("do_read_packet: read() failed, %s\n", strerror(errno));
/* Fall through */
......@@ -105,7 +105,7 @@ static struct read_handler *do_read_packet(struct read_handler *c,
switch(n)
{
case 0:
return c;
return 1;
case A_FAIL:
werror("do_read_packet: read() failed, %s\n", strerror(errno));
/* Fall through */
......@@ -150,7 +150,7 @@ static struct read_handler *do_read_packet(struct read_handler *c,
switch(n)
{
case 0:
return c;