diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 22524fc26..c3f04b10f 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include #include @@ -1925,6 +1927,44 @@ static struct io_plan *handle_memleak(struct io_conn *conn, } #endif /* DEVELOPER */ +u8 *hsmd_status_bad_request(struct hsmd_client *client, const u8 *msg, const char *error) +{ + /* Extract the pointer to the hsmd representation of the + * client which has access to the underlying connection. */ + struct client *c = (struct client*)client->extra; + bad_req_fmt(c->conn, c, msg, "%s", error); + + /* We often use `return hsmd_status_bad_request` to drop out, and NULL + * means we encountered an error. */ + return NULL; +} + +void hsmd_status_fmt(enum log_level level, const struct node_id *peer, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + status_vfmt(level, peer, fmt, ap); + va_end(ap); +} + +void hsmd_status_failed(enum status_failreason reason, const char *fmt, ...) +{ + va_list ap; + char *str; + + va_start(ap, fmt); + str = tal_vfmt(NULL, fmt, ap); + va_end(ap); + + /* Give a nice backtrace when this happens! */ + if (reason == STATUS_FAIL_INTERNAL_ERROR) + send_backtrace(str); + + status_send_fatal(take(towire_status_fail(NULL, reason, str))); +} + /*~ This is the core of the HSM daemon: handling requests. */ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) { diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 47ba68e72..3d92d4382 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -120,6 +120,28 @@ bool check_client_capabilities(struct hsmd_client *client, enum hsmd_wire t) return false; } +/*~ ccan/compiler.h defines PRINTF_FMT as the gcc compiler hint so it will + * check that fmt and other trailing arguments really are the correct type. + */ +/* This function is used to format an error message before passing it + * to the library user specified hsmd_status_bad_request */ +/* Temporarily pre-declare until we use the function, then we can make + * it static again. */ +u8 *hsmd_status_bad_request_fmt(struct hsmd_client *client, const u8 *msg, + const char *fmt, ...) PRINTF_FMT(3, 4); + +u8 *hsmd_status_bad_request_fmt(struct hsmd_client *client, const u8 *msg, + const char *fmt, ...) +{ + va_list ap; + char *str; + + va_start(ap, fmt); + str = tal_fmt(tmpctx, fmt, ap); + va_end(ap); + return hsmd_status_bad_request(client, msg, str); +} + u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, const u8 *msg) { diff --git a/hsmd/libhsmd.h b/hsmd/libhsmd.h index 3e1cfcf0a..eab9504f9 100644 --- a/hsmd/libhsmd.h +++ b/hsmd/libhsmd.h @@ -57,6 +57,23 @@ struct hsmd_client *hsmd_client_new_peer(const tal_t *ctx, u64 capabilities, u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, const u8 *msg); +/* Functions to report debugging information or errors. These must be + * implemented by the user of the library. */ +u8 *hsmd_status_bad_request(struct hsmd_client *client, const u8 *msg, + const char *error); + +/* Send a printf-style debugging trace. */ +void hsmd_status_fmt(enum log_level level, + const struct node_id *peer, + const char *fmt, ...) + PRINTF_FMT(3,4); + +#define hsmd_status_debug(...) \ + hsmd_status_fmt(LOG_DBG, NULL, __VA_ARGS__) + +void hsmd_status_failed(enum status_failreason code, + const char *fmt, ...) PRINTF_FMT(2,3); + /* The following declarations are here only temporarily while we migrate logic from hsmd.c to libhsmd.c */ /*~ Nobody will ever find it here! hsm_secret is our root secret, the bip32