@ -67,9 +67,6 @@ static struct {
/*~ We keep track of clients, but there's not much to keep. */
/*~ We keep track of clients, but there's not much to keep. */
struct client {
struct client {
/* The connection to lightningd itself */
struct client * master ;
/* The ccan/io async io connection for this client: it closes, we die. */
/* The ccan/io async io connection for this client: it closes, we die. */
struct io_conn * conn ;
struct io_conn * conn ;
@ -107,6 +104,12 @@ static size_t num_dbid_zero_clients;
/*~ We need this deep inside bad_req_fmt, so we make it a global. */
/*~ We need this deep inside bad_req_fmt, so we make it a global. */
static struct daemon_conn * status_conn ;
static struct daemon_conn * status_conn ;
/* This is used for various assertions and error cases. */
static bool is_lightningd ( const struct client * client )
{
return client = = dbid_zero_clients [ 0 ] ;
}
/*~ FIXME: This is used by debug.c. Doesn't apply to us, but lets us link. */
/*~ FIXME: This is used by debug.c. Doesn't apply to us, but lets us link. */
extern void dev_disconnect_init ( int fd ) ;
extern void dev_disconnect_init ( int fd ) ;
void dev_disconnect_init ( int fd UNUSED ) { }
void dev_disconnect_init ( int fd UNUSED ) { }
@ -136,7 +139,7 @@ static PRINTF_FMT(4,5)
/*~ If the client was actually lightningd, it's Game Over; we actually
/*~ If the client was actually lightningd, it's Game Over; we actually
* fail in this case , and it will too . */
* fail in this case , and it will too . */
if ( c = = c - > master ) {
if ( is_lightningd ( c ) ) {
status_broken ( " %s " , str ) ;
status_broken ( " %s " , str ) ;
master_badmsg ( fromwire_peektype ( msg_in ) , msg_in ) ;
master_badmsg ( fromwire_peektype ( msg_in ) , msg_in ) ;
}
}
@ -184,13 +187,13 @@ static void destroy_client(struct client *c)
" Failed to remove client dbid % " PRIu64 , c - > dbid ) ;
" Failed to remove client dbid % " PRIu64 , c - > dbid ) ;
}
}
static struct client * new_client ( struct client * master ,
static struct client * new_client ( const tal_t * ctx ,
const struct pubkey * id ,
const struct pubkey * id ,
u64 dbid ,
u64 dbid ,
const u64 capabilities ,
const u64 capabilities ,
int fd )
int fd )
{
{
struct client * c = tal ( master , struct client ) ;
struct client * c = tal ( ctx , struct client ) ;
/*~ All-zero pubkey is used for the initial master connection */
/*~ All-zero pubkey is used for the initial master connection */
if ( id ) {
if ( id ) {
@ -200,23 +203,22 @@ static struct client *new_client(struct client *master,
}
}
c - > dbid = dbid ;
c - > dbid = dbid ;
c - > master = master ;
c - > capabilities = capabilities ;
c - > capabilities = capabilities ;
/*~ This is the core of ccan/io: the connection creation calls a
/*~ This is the core of ccan/io: the connection creation calls a
* callback which returns the initial plan to execute : in our case ,
* callback which returns the initial plan to execute : in our case ,
* read a message . */
* read a message . */
c - > conn = io_new_conn ( master , fd , client_read_next , c ) ;
c - > conn = io_new_conn ( ctx , fd , client_read_next , c ) ;
/*~ tal_steal() moves a pointer to a new parent. At this point, the
/*~ tal_steal() moves a pointer to a new parent. At this point, the
* hierarchy is :
* hierarchy is :
*
*
* master - > c
* ctx - > c
* master - > c - > conn
* ctx - > c - > conn
*
*
* We want to the c - > conn to own ' c ' , so that if the io_conn closes ,
* We want to the c - > conn to own ' c ' , so that if the io_conn closes ,
* the client is freed :
* the client is freed :
*
*
* master - > c - > conn - > c .
* ctx - > c - > conn - > c .
*/
*/
tal_steal ( c - > conn , c ) ;
tal_steal ( c - > conn , c ) ;
@ -511,8 +513,8 @@ static struct io_plan *init_hsm(struct io_conn *conn,
{
{
struct pubkey node_id ;
struct pubkey node_id ;
/* This must be the master . */
/* This must be lightningd . */
assert ( c = = c - > master ) ;
assert ( is_lightningd ( c ) ) ;
/*~ The fromwire_* routines are autogenerated, based on the message
/*~ The fromwire_* routines are autogenerated, based on the message
* definitions in hsm_client_wire . csv . The format of those files is
* definitions in hsm_client_wire . csv . The format of those files is
@ -1201,7 +1203,7 @@ static struct io_plan *send_pending_client_fd(struct io_conn *conn,
{
{
int fd = pending_client_fd ;
int fd = pending_client_fd ;
/* This must be the master. */
/* This must be the master. */
assert ( master = = master - > master ) ;
assert ( is_lightningd ( master ) ) ;
assert ( fd ! = - 1 ) ;
assert ( fd ! = - 1 ) ;
/* This sanity check shouldn't be necessary, but it's cheap. */
/* This sanity check shouldn't be necessary, but it's cheap. */
@ -1229,7 +1231,7 @@ static struct io_plan *pass_client_hsmfd(struct io_conn *conn,
struct pubkey id ;
struct pubkey id ;
/* This must be lightningd itself. */
/* This must be lightningd itself. */
assert ( c = = c - > master ) ;
assert ( is_lightningd ( c ) ) ;
if ( ! fromwire_hsm_client_hsmfd ( msg_in , & id , & dbid , & capabilities ) )
if ( ! fromwire_hsm_client_hsmfd ( msg_in , & id , & dbid , & capabilities ) )
return bad_req ( conn , c , msg_in ) ;
return bad_req ( conn , c , msg_in ) ;
@ -1729,8 +1731,8 @@ int main(int argc, char *argv[])
master = new_client ( NULL , NULL , 0 , HSM_CAP_MASTER | HSM_CAP_SIGN_GOSSIP ,
master = new_client ( NULL , NULL , 0 , HSM_CAP_MASTER | HSM_CAP_SIGN_GOSSIP ,
REQ_FD ) ;
REQ_FD ) ;
/* We're our own master! */
/* First client == lightningd. */
master - > master = master ;
assert ( is_lightningd ( master ) ) ;
/* When conn closes, everything is freed. */
/* When conn closes, everything is freed. */
io_set_finish ( master - > conn , master_gone , master ) ;
io_set_finish ( master - > conn , master_gone , master ) ;