2017-03-19 21:32:44 +01:00
|
|
|
#include <ccan/fdpass/fdpass.h>
|
2017-03-19 21:24:14 +01:00
|
|
|
#include <ccan/io/fdpass/fdpass.h>
|
2017-03-10 13:37:20 +01:00
|
|
|
#include <ccan/take/take.h>
|
2017-08-28 18:05:01 +02:00
|
|
|
#include <common/daemon_conn.h>
|
2017-03-10 13:37:20 +01:00
|
|
|
#include <wire/wire_io.h>
|
2017-03-19 21:32:44 +01:00
|
|
|
#include <wire/wire_sync.h>
|
2017-03-10 13:37:20 +01:00
|
|
|
|
|
|
|
struct io_plan *daemon_conn_read_next(struct io_conn *conn,
|
|
|
|
struct daemon_conn *dc)
|
|
|
|
{
|
|
|
|
dc->msg_in = tal_free(dc->msg_in);
|
|
|
|
return io_read_wire(conn, dc->ctx, &dc->msg_in, dc->daemon_conn_recv,
|
|
|
|
dc);
|
|
|
|
}
|
|
|
|
|
2017-03-11 15:20:37 +01:00
|
|
|
struct io_plan *daemon_conn_write_next(struct io_conn *conn,
|
2017-03-10 13:37:20 +01:00
|
|
|
struct daemon_conn *dc)
|
|
|
|
{
|
2018-03-13 16:44:55 +01:00
|
|
|
const u8 *msg;
|
|
|
|
|
|
|
|
again:
|
|
|
|
msg = msg_dequeue(&dc->out);
|
2017-03-10 13:37:20 +01:00
|
|
|
if (msg) {
|
2017-03-19 21:32:44 +01:00
|
|
|
int fd = msg_extract_fd(msg);
|
2017-03-19 21:24:14 +01:00
|
|
|
if (fd >= 0)
|
|
|
|
return io_send_fd(conn, fd, true,
|
|
|
|
daemon_conn_write_next, dc);
|
2017-03-11 15:20:37 +01:00
|
|
|
return io_write_wire(conn, take(msg), daemon_conn_write_next,
|
|
|
|
dc);
|
|
|
|
} else if (dc->msg_queue_cleared_cb) {
|
2018-03-13 16:44:55 +01:00
|
|
|
if (dc->msg_queue_cleared_cb(conn, dc))
|
|
|
|
goto again;
|
2017-03-10 13:37:20 +01:00
|
|
|
}
|
2018-03-13 16:44:55 +01:00
|
|
|
return msg_queue_wait(conn, &dc->out, daemon_conn_write_next, dc);
|
2017-03-10 13:37:20 +01:00
|
|
|
}
|
|
|
|
|
2017-03-19 21:32:44 +01:00
|
|
|
bool daemon_conn_sync_flush(struct daemon_conn *dc)
|
|
|
|
{
|
|
|
|
const u8 *msg;
|
2017-07-04 02:47:02 +02:00
|
|
|
int daemon_fd;
|
2017-03-19 21:32:44 +01:00
|
|
|
|
|
|
|
/* Flush any current packet. */
|
|
|
|
if (!io_flush_sync(dc->conn))
|
|
|
|
return false;
|
|
|
|
|
2017-07-04 02:47:02 +02:00
|
|
|
/* Make fd blocking for the duration */
|
|
|
|
daemon_fd = io_conn_fd(dc->conn);
|
|
|
|
if (!io_fd_block(daemon_fd, true))
|
|
|
|
return false;
|
|
|
|
|
2017-03-19 21:32:44 +01:00
|
|
|
/* Flush existing messages. */
|
|
|
|
while ((msg = msg_dequeue(&dc->out)) != NULL) {
|
2017-03-19 21:32:44 +01:00
|
|
|
int fd = msg_extract_fd(msg);
|
2017-03-19 21:32:44 +01:00
|
|
|
if (fd >= 0) {
|
2017-07-04 02:47:02 +02:00
|
|
|
if (!fdpass_send(daemon_fd, fd))
|
|
|
|
break;
|
|
|
|
} else if (!wire_sync_write(daemon_fd, take(msg)))
|
|
|
|
break;
|
2017-03-19 21:32:44 +01:00
|
|
|
}
|
2017-07-04 02:47:02 +02:00
|
|
|
io_fd_block(daemon_fd, false);
|
|
|
|
|
2018-01-29 05:46:54 +01:00
|
|
|
/* Success if and only if we flushed them all. */
|
2017-07-04 02:47:02 +02:00
|
|
|
return msg == NULL;
|
2017-03-19 21:32:44 +01:00
|
|
|
}
|
|
|
|
|
2017-03-10 13:37:20 +01:00
|
|
|
static struct io_plan *daemon_conn_start(struct io_conn *conn,
|
|
|
|
struct daemon_conn *dc)
|
|
|
|
{
|
|
|
|
dc->conn = conn;
|
|
|
|
return io_duplex(conn, daemon_conn_read_next(conn, dc),
|
|
|
|
daemon_conn_write_next(conn, dc));
|
|
|
|
}
|
|
|
|
|
|
|
|
void daemon_conn_init(tal_t *ctx, struct daemon_conn *dc, int fd,
|
|
|
|
struct io_plan *(*daemon_conn_recv)(struct io_conn *,
|
2017-06-06 05:08:42 +02:00
|
|
|
struct daemon_conn *),
|
|
|
|
void (*finish)(struct io_conn *, struct daemon_conn *dc))
|
2017-03-10 13:37:20 +01:00
|
|
|
{
|
2017-06-06 05:08:42 +02:00
|
|
|
struct io_conn *conn;
|
|
|
|
|
2017-03-10 13:37:20 +01:00
|
|
|
dc->daemon_conn_recv = daemon_conn_recv;
|
|
|
|
|
|
|
|
dc->ctx = ctx;
|
|
|
|
dc->msg_in = NULL;
|
2017-03-13 17:24:05 +01:00
|
|
|
msg_queue_init(&dc->out, dc->ctx);
|
2017-03-11 15:20:37 +01:00
|
|
|
dc->msg_queue_cleared_cb = NULL;
|
2017-06-06 05:08:42 +02:00
|
|
|
conn = io_new_conn(ctx, fd, daemon_conn_start, dc);
|
|
|
|
if (finish)
|
|
|
|
io_set_finish(conn, finish, dc);
|
2017-03-10 13:37:20 +01:00
|
|
|
}
|
|
|
|
|
2017-12-06 07:13:56 +01:00
|
|
|
void daemon_conn_clear(struct daemon_conn *dc)
|
|
|
|
{
|
|
|
|
io_set_finish(dc->conn, NULL, NULL);
|
|
|
|
io_close(dc->conn);
|
|
|
|
}
|
|
|
|
|
2017-03-17 19:45:52 +01:00
|
|
|
void daemon_conn_send(struct daemon_conn *dc, const u8 *msg)
|
2017-03-10 13:37:20 +01:00
|
|
|
{
|
2017-03-13 17:24:05 +01:00
|
|
|
msg_enqueue(&dc->out, msg);
|
2017-03-10 13:37:20 +01:00
|
|
|
}
|
2017-03-19 21:24:14 +01:00
|
|
|
|
|
|
|
void daemon_conn_send_fd(struct daemon_conn *dc, int fd)
|
|
|
|
{
|
|
|
|
msg_enqueue_fd(&dc->out, fd);
|
|
|
|
}
|