From bc1aa9c656c8aa390329329ac0fdc6c2de89d547 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 20 Feb 2019 06:52:54 +0000 Subject: [PATCH] Add BinarySink wrappers on existing forms of output. There's now a stdio_sink, whose write function calls fwrite on the given FILE *; a bufchain_sink, whose write function appends to the given bufchain; and on Windows there's a handle_sink whose write function writes to the given 'struct handle'. (That is, not the raw Windows HANDLE, but our event-loop-friendly wrapper on it.) Not yet used for anything, but they're about to be. --- defs.h | 3 +++ marshal.c | 24 ++++++++++++++++++++++++ marshal.h | 19 +++++++++++++++++++ windows/winhandl.c | 12 ++++++++++++ windows/winstuff.h | 7 +++++++ 5 files changed, 65 insertions(+) diff --git a/defs.h b/defs.h index 01108176..21150181 100644 --- a/defs.h +++ b/defs.h @@ -40,6 +40,9 @@ typedef struct RSAKey RSAKey; typedef struct BinarySink BinarySink; typedef struct BinarySource BinarySource; +typedef struct stdio_sink stdio_sink; +typedef struct bufchain_sink bufchain_sink; +typedef struct handle_sink handle_sink; typedef struct IdempotentCallback IdempotentCallback; diff --git a/marshal.c b/marshal.c index 0ecbd258..a9b1074a 100644 --- a/marshal.c +++ b/marshal.c @@ -234,3 +234,27 @@ ptrlen BinarySource_get_pstring(BinarySource *src) return make_ptrlen(consume(len), len); } + +static void stdio_sink_write(BinarySink *bs, const void *data, size_t len) +{ + stdio_sink *sink = BinarySink_DOWNCAST(bs, stdio_sink); + fwrite(data, 1, len, sink->fp); +} + +void stdio_sink_init(stdio_sink *sink, FILE *fp) +{ + sink->fp = fp; + BinarySink_INIT(sink, stdio_sink_write); +} + +static void bufchain_sink_write(BinarySink *bs, const void *data, size_t len) +{ + bufchain_sink *sink = BinarySink_DOWNCAST(bs, bufchain_sink); + bufchain_add(sink->ch, data, len); +} + +void bufchain_sink_init(bufchain_sink *sink, bufchain *ch) +{ + sink->ch = ch; + BinarySink_INIT(sink, bufchain_sink_write); +} diff --git a/marshal.h b/marshal.h index a7442d0d..817620ea 100644 --- a/marshal.h +++ b/marshal.h @@ -3,6 +3,8 @@ #include "defs.h" +#include + /* * A sort of 'abstract base class' or 'interface' or 'trait' which is * the common feature of all types that want to accept data formatted @@ -301,4 +303,21 @@ ptrlen BinarySource_get_pstring(BinarySource *); mp_int *BinarySource_get_mp_ssh1(BinarySource *src); mp_int *BinarySource_get_mp_ssh2(BinarySource *src); +/* + * A couple of useful standard BinarySink implementations, which live + * as sensibly here as anywhere else: one that makes a BinarySink + * whose effect is to write to a stdio stream, and one whose effect is + * to append to a bufchain. + */ +struct stdio_sink { + FILE *fp; + BinarySink_IMPLEMENTATION; +}; +struct bufchain_sink { + bufchain *ch; + BinarySink_IMPLEMENTATION; +}; +void stdio_sink_init(stdio_sink *sink, FILE *fp); +void bufchain_sink_init(bufchain_sink *sink, bufchain *ch); + #endif /* PUTTY_MARSHAL_H */ diff --git a/windows/winhandl.c b/windows/winhandl.c index d3c95f88..739e2666 100644 --- a/windows/winhandl.c +++ b/windows/winhandl.c @@ -715,3 +715,15 @@ void *handle_get_privdata(struct handle *h) { return h->u.g.privdata; } + +static void handle_sink_write(BinarySink *bs, const void *data, size_t len) +{ + handle_sink *sink = BinarySink_DOWNCAST(bs, handle_sink); + handle_write(sink->h, data, len); +} + +void handle_sink_init(handle_sink *sink, struct handle *h) +{ + sink->h = h; + BinarySink_INIT(sink, handle_sink_write); +} diff --git a/windows/winstuff.h b/windows/winstuff.h index c2da098b..ee6a055a 100644 --- a/windows/winstuff.h +++ b/windows/winstuff.h @@ -24,6 +24,7 @@ #endif #include "defs.h" +#include "marshal.h" #include "tree234.h" @@ -621,6 +622,12 @@ size_t handle_backlog(struct handle *h); void *handle_get_privdata(struct handle *h); struct handle *handle_add_foreign_event(HANDLE event, void (*callback)(void *), void *ctx); +/* Analogue of stdio_sink in marshal.h, for a Windows handle */ +struct handle_sink { + struct handle *h; + BinarySink_IMPLEMENTATION; +}; +void handle_sink_init(handle_sink *sink, struct handle *h); /* * winpgntc.c needs to schedule callbacks for asynchronous agent