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

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,8 +61,8 @@ 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(),
stderr),
= make_read_packet(make_packet_debug(make_packet_void(),
stderr),
closure->connection->max_packet);
closure->connection->server_version
......@@ -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);
......@@ -35,7 +38,7 @@ static int do_read(struct fd_read *closure, UINT8 *buffer, UINT32 length)
return A_EOF;
if (res > 0)
return res;
switch(errno)
{
case EINTR:
......@@ -60,7 +63,7 @@ static int do_read(struct fd_read *closure, UINT8 *buffer, UINT32 length)
/* UNLINK_FD must be followed by a continue, to avoid updating _fd */
#define UNLINK_FD (*_fd = (*_fd)->next)
void io_run(struct io_backend *b)
{
while(1)
......@@ -70,141 +73,140 @@ void io_run(struct io_backend *b)
nfds_t nfds;
int timeout;
int res;
nfds = b->nio + b->nlisten + b->nconnect;
if (b->callouts)
{
time_t now = time(NULL);
if (now >= b->callouts->when)
timeout = 0;
else
{
if (b->callouts->when > now + MAX_TIMEOUT)
timeout = MAX_TIMEOUT * 1000;
else
timeout = (b->callouts->when - now) * 1000;
}
}
{
time_t now = time(NULL);
if (now >= b->callouts->when)
timeout = 0;
else
{
if (b->callouts->when > now + MAX_TIMEOUT)
timeout = MAX_TIMEOUT * 1000;
else
timeout = (b->callouts->when - now) * 1000;
}
}
else
{
if (!nfds)
/* All done */
break;
timeout = -1;
}
{
if (!nfds)
/* All done */
break;
timeout = -1;
}
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++)
{
fds[i].fd = fd->on_hold ? -1 : fd->fd;
fds[i].events = 0;
if (!fd->on_hold)
fds[i].events |= POLLIN;
/* pre_write returns 0 if the buffer is empty */
if (write_buffer_pre_write(fd->buffer))
fds[i].events |= POLLOUT;
}
{
fds[i].fd = fd->on_hold ? -1 : fd->fd;
fds[i].events = 0;
if (!fd->on_hold)
fds[i].events |= POLLIN;
/* pre_write returns 0 if the buffer is empty */
if (write_buffer_pre_write(fd->buffer))
fds[i].events |= POLLOUT;
}
END_FOR_FDS;
FOR_FDS(struct listen_fd, fd, b->listen, i++)
{
fds[i].fd = fd->fd;
fds[i].events = POLLIN;
}
{
fds[i].fd = fd->fd;
fds[i].events = POLLIN;
}
END_FOR_FDS;
FOR_FDS(struct connect_fd, fd, b->connect, i++)
{
fds[i].fd = fd->fd;
fds[i].events = POLLOUT;
}
{
fds[i].fd = fd->fd;
fds[i].events = POLLOUT;
}
END_FOR_FDS;
res = poll(fds, nfds, timeout);
if (!res)
{
/* Timeout. Run the callout */
struct callout *f = b->callouts;
if (!CALLBACK(f->callout))
fatal("What now?");
b->callouts = f->next;
free(f);
}
{
/* Timeout. Run the callout */
struct callout *f = b->callouts;
if (!CALLBACK(f->callout))
fatal("What now?");
b->callouts = f->next;
free(f);
}
if (res<0)
{
switch(errno)
{
case EAGAIN:
case EINTR:
continue;
default:
fatal("io_run:poll failed: %s", strerror(errno));
}
}
{
switch(errno)
{
case EAGAIN:
case EINTR:
continue;
default:
fatal("io_run:poll failed: %s", strerror(errno));
}
}
else
{ /* Process files */
i = 0;
/* Handle writing first */
FOR_FDS(struct io_fd, fd, b->io, i++)
{
if (fds[i].revents & POLLOUT)
{
UINT32 size = MIN(fd->buffer->end - fd->buffer->start,
fd->buffer->block_size);
int res = write(fd->fd,
fd->buffer->buffer + fd->buffer->start,
size);
if (!res)
fatal("Closed?");
if (res < 0)
switch(errno)
{
case EINTR:
case EAGAIN:
break;
default:
werror("io.c: write failed, %s\n", strerror(errno));
CALLBACK(fd->close_callback);
fd->please_close = 1;
break;
}
else if (!res)
fatal("What now?");
else
fd->buffer->start += res;
}
}
END_FOR_FDS;
/* Handle reading */
i = 0; /* Start over */
FOR_FDS(struct io_fd, fd, b->io, i++)
{
if (!fd->please_close
&& (fds[i].revents & POLLIN))
{
struct fd_read r =
{ { (abstract_read_f) 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)))
{
fd->please_close = 1;
}
{ /* Process files */
i = 0;
/* Handle writing first */
FOR_FDS(struct io_fd, fd, b->io, i++)
{
if (fds[i].revents & POLLOUT)
{
UINT32 size = MIN(fd->buffer->end - fd->buffer->start,
fd->buffer->block_size);
int res = write(fd->fd,
fd->buffer->buffer + fd->buffer->start,
size);
if (!res)
fatal("Closed?");
if (res < 0)
switch(errno)
{
case EINTR:
case EAGAIN:
break;
default:
werror("io.c: write failed, %s\n", strerror(errno));
CALLBACK(fd->close_callback);
fd->please_close = 1;
break;
}
else if (!res)
fatal("What now?");
else
fd->buffer->start += res;
}
}
END_FOR_FDS;
/* Handle reading */
i = 0; /* Start over */
FOR_FDS(struct io_fd, fd, b->io, i++)
{
if (!fd->please_close
&& (fds[i].revents & POLLIN))
{
struct fd_read r =
{ { do_read }, fd->fd };
/* The handler function returns a new handler for the
* file, or NULL. */
if (!(READ_HANDLER(fd->handler,
&r.super)))
{
fd->please_close = 1;
}
}
if (fd->please_close)
{
......@@ -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;
......@@ -260,7 +265,7 @@ void io_run(struct io_backend *b)
}
END_FOR_FDS;
}
}
}
}
/*
......@@ -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));