mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
wire: add ccan/io helpers to send (unencrypted) messages between damones.
Format is "le16 len; u8 message[len]" same as wire format specified in BOLTs, even though the endian conversion is overkill for local messages. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -4,11 +4,14 @@
|
||||
wire-wrongdir:
|
||||
$(MAKE) -C .. wire-all
|
||||
|
||||
WIRE_HEADERS := wire/wire.h wire/wire_sync.h
|
||||
WIRE_HEADERS := wire/wire.h \
|
||||
wire/wire_sync.h \
|
||||
wire/wire_io.h
|
||||
WIRE_GEN_HEADERS := wire/gen_peer_wire.h wire/gen_onion_wire.h
|
||||
WIRE_GEN_SRC := wire/gen_peer_wire.c
|
||||
WIRE_GEN_ONION_SRC := wire/gen_onion_wire.c
|
||||
WIRE_SRC := wire/wire_sync.c \
|
||||
wire/wire_io.c \
|
||||
wire/fromwire.c \
|
||||
wire/towire.c
|
||||
|
||||
|
||||
129
wire/wire_io.c
Normal file
129
wire/wire_io.c
Normal file
@@ -0,0 +1,129 @@
|
||||
#include <ccan/endian/endian.h>
|
||||
/* FIXME: io_plan needs size_t */
|
||||
#include <unistd.h>
|
||||
#include <ccan/io/io_plan.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <wire/wire_io.h>
|
||||
|
||||
/*
|
||||
* OK, this is a little tricky. ccan/io lets you create your own plans,
|
||||
* beyond the standard io_read/io_write etc. It provides a union to place
|
||||
* scratch data, and it's almost enough for our purposes.
|
||||
*/
|
||||
|
||||
/* 2 bytes for the length header. */
|
||||
#define HEADER_LEN (sizeof(le16))
|
||||
|
||||
/* Since length can only be 64k, this is an impossible value. */
|
||||
#define INSIDE_HEADER_BIT 0x80000000
|
||||
|
||||
/* arg->u2.s contains length we've read, arg->u1.vp contains u8 **data. */
|
||||
static int do_read_wire_header(int fd, struct io_plan_arg *arg)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t len = arg->u2.s & ~INSIDE_HEADER_BIT;
|
||||
u8 *p = *(u8 **)arg->u1.vp;
|
||||
|
||||
ret = read(fd, p + len, HEADER_LEN - len);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
arg->u2.s += ret;
|
||||
|
||||
/* Both bytes read? Set up for normal read of data. */
|
||||
if (arg->u2.s == INSIDE_HEADER_BIT + HEADER_LEN) {
|
||||
arg->u2.s = be16_to_cpu(*(be16 *)p);
|
||||
/* A type-only message is not unheard of, so optimize a little */
|
||||
if (arg->u2.s != HEADER_LEN)
|
||||
tal_resize((u8 **)arg->u1.vp, arg->u2.s);
|
||||
arg->u1.vp = *(u8 **)arg->u1.vp;
|
||||
}
|
||||
|
||||
return arg->u2.s == 0;
|
||||
}
|
||||
|
||||
static int do_read_wire(int fd, struct io_plan_arg *arg)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
/* Still reading header? */
|
||||
if (arg->u2.s & INSIDE_HEADER_BIT)
|
||||
return do_read_wire_header(fd, arg);
|
||||
|
||||
/* Normal read */
|
||||
ret = read(fd, arg->u1.cp, arg->u2.s);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
|
||||
arg->u1.cp += ret;
|
||||
arg->u2.s -= ret;
|
||||
return arg->u2.s == 0;
|
||||
}
|
||||
|
||||
struct io_plan *io_read_wire_(struct io_conn *conn,
|
||||
const tal_t *ctx,
|
||||
u8 **data,
|
||||
struct io_plan *(*next)(struct io_conn *, void *),
|
||||
void *next_arg)
|
||||
{
|
||||
struct io_plan_arg *arg = io_plan_arg(conn, IO_IN);
|
||||
|
||||
/* We allocate data now; saves storing ctx, and lets us read in len. */
|
||||
arg->u1.vp = data;
|
||||
*data = tal_arr(ctx, u8, HEADER_LEN);
|
||||
|
||||
/* We use u2 to store the length we've read. */
|
||||
arg->u2.s = INSIDE_HEADER_BIT;
|
||||
return io_set_plan(conn, IO_IN, do_read_wire, next, next_arg);
|
||||
}
|
||||
|
||||
/* arg->u2.s contains length we've written, arg->u1 contains u8 *data. */
|
||||
static int do_write_wire_header(int fd, struct io_plan_arg *arg)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t len = arg->u2.s & ~INSIDE_HEADER_BIT;
|
||||
be16 hdr = cpu_to_be16(tal_count(arg->u1.const_vp));
|
||||
|
||||
ret = write(fd, (char *)&hdr + len, HEADER_LEN - len);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
arg->u2.s += ret;
|
||||
|
||||
/* Both bytes written? Set up for normal write of data. */
|
||||
if (arg->u2.s == INSIDE_HEADER_BIT + HEADER_LEN)
|
||||
arg->u2.s = be16_to_cpu(hdr);
|
||||
|
||||
return arg->u2.s == 0;
|
||||
}
|
||||
|
||||
static int do_write_wire(int fd, struct io_plan_arg *arg)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
/* Still writing header? */
|
||||
if (arg->u2.s & INSIDE_HEADER_BIT)
|
||||
return do_write_wire_header(fd, arg);
|
||||
|
||||
/* Normal write */
|
||||
ret = write(fd, arg->u1.cp, arg->u2.s);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
|
||||
arg->u1.cp += ret;
|
||||
arg->u2.s -= ret;
|
||||
return arg->u2.s == 0;
|
||||
}
|
||||
|
||||
/* Write message from data (tal_count(data) gives length). */
|
||||
struct io_plan *io_write_wire_(struct io_conn *conn,
|
||||
const u8 *data,
|
||||
struct io_plan *(*next)(struct io_conn *, void *),
|
||||
void *next_arg)
|
||||
{
|
||||
struct io_plan_arg *arg = io_plan_arg(conn, IO_OUT);
|
||||
|
||||
arg->u1.const_vp = data;
|
||||
|
||||
/* We use u2 to store the length we've written. */
|
||||
arg->u2.s = INSIDE_HEADER_BIT;
|
||||
return io_set_plan(conn, IO_OUT, do_write_wire, next, next_arg);
|
||||
}
|
||||
31
wire/wire_io.h
Normal file
31
wire/wire_io.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef LIGHTNING_WIRE_WIRE_IO_H
|
||||
#define LIGHTNING_WIRE_WIRE_IO_H
|
||||
#include "config.h"
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
|
||||
/* Read message into *data, allocating off ctx. */
|
||||
struct io_plan *io_read_wire_(struct io_conn *conn,
|
||||
const tal_t *ctx,
|
||||
u8 **data,
|
||||
struct io_plan *(*next)(struct io_conn *, void *),
|
||||
void *next_arg);
|
||||
|
||||
#define io_read_wire(conn, ctx, data, next, arg) \
|
||||
io_read_wire_((conn), (ctx), (data), \
|
||||
typesafe_cb_preargs(struct io_plan *, void *, \
|
||||
(next), (arg), struct io_conn *), \
|
||||
(arg))
|
||||
|
||||
/* Write message from data (tal_count(data) gives length). */
|
||||
struct io_plan *io_write_wire_(struct io_conn *conn,
|
||||
const u8 *data,
|
||||
struct io_plan *(*next)(struct io_conn *, void *),
|
||||
void *next_arg);
|
||||
|
||||
#define io_write_wire(conn, data, next, arg) \
|
||||
io_write_wire_((conn), (data), \
|
||||
typesafe_cb_preargs(struct io_plan *, void *, \
|
||||
(next), (arg), struct io_conn *), \
|
||||
(arg))
|
||||
#endif /* LIGHTNING_WIRE_WIRE_IO_H */
|
||||
Reference in New Issue
Block a user