Browse Source

lightningd/ping: ping support.

A spec update brings ping support.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 8 years ago
committed by Christian Decker
parent
commit
d5be8d26f2
  1. 1
      lightningd/Makefile
  2. 21
      lightningd/channel/channel.c
  3. 30
      lightningd/gossip/gossip.c
  4. 53
      lightningd/ping.c
  5. 13
      lightningd/ping.h
  6. 7
      wire/gen_peer_wire_csv
  7. 2
      wire/peer_wire.c

1
lightningd/Makefile

@ -51,6 +51,7 @@ LIGHTNINGD_LIB_SRC := \
lightningd/key_derive.c \
lightningd/msg_queue.c \
lightningd/peer_failed.c \
lightningd/ping.c \
lightningd/status.c \
lightningd/utxo.c

21
lightningd/channel/channel.c

@ -28,6 +28,7 @@
#include <lightningd/key_derive.h>
#include <lightningd/msg_queue.h>
#include <lightningd/peer_failed.h>
#include <lightningd/ping.h>
#include <lightningd/status.h>
#include <secp256k1.h>
#include <signal.h>
@ -819,6 +820,20 @@ static void handle_peer_fail_htlc(struct peer *peer, const u8 *msg)
abort();
}
static void handle_ping(struct peer *peer, const u8 *msg)
{
u8 *pong;
if (!check_ping_make_pong(peer, msg, &pong))
peer_failed(io_conn_fd(peer->peer_conn),
&peer->pcs.cs,
&peer->channel_id,
WIRE_CHANNEL_PEER_BAD_MESSAGE,
"Bad ping");
if (pong)
msg_enqueue(&peer->peer_out, take(pong));
}
static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg)
{
enum wire_type type = fromwire_peektype(msg);
@ -868,6 +883,12 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg)
case WIRE_UPDATE_FAIL_HTLC:
handle_peer_fail_htlc(peer, msg);
goto done;
case WIRE_PING:
handle_ping(peer, msg);
goto done;
/* We don't send pings, so don't expect pongs. */
case WIRE_PONG:
case WIRE_INIT:
case WIRE_ERROR:
case WIRE_OPEN_CHANNEL:

30
lightningd/gossip/gossip.c

@ -21,6 +21,7 @@
#include <lightningd/debug.h>
#include <lightningd/gossip/gen_gossip_wire.h>
#include <lightningd/gossip_msg.h>
#include <lightningd/ping.h>
#include <lightningd/status.h>
#include <secp256k1_ecdh.h>
#include <sodium/randombytes.h>
@ -168,6 +169,20 @@ static void handle_gossip_msg(struct routing_state *rstate, u8 *msg)
}
}
static bool handle_ping(struct peer *peer, u8 *ping)
{
u8 *pong;
if (!check_ping_make_pong(peer, ping, &pong)) {
peer->error = "Bad ping";
return false;
}
if (pong)
msg_enqueue(&peer->peer_out, take(pong));
return true;
}
static struct io_plan *peer_msgin(struct io_conn *conn,
struct peer *peer, u8 *msg)
{
@ -190,6 +205,21 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
peer->error = "Duplicate INIT message received";
return io_close(conn);
case WIRE_PING:
if (!handle_ping(peer, msg))
return io_close(conn);
return peer_read_message(conn, &peer->pcs, peer_msgin);
case WIRE_PONG:
/* BOLT #1:
*
* A node receiving a `pong` message MAY fail the channels if
* `byteslen` does not correspond to any `ping`
* `num_pong_bytes` value it has sent.
*/
peer->error = "Unexpected pong received";
return io_close(conn);
case WIRE_OPEN_CHANNEL:
case WIRE_ACCEPT_CHANNEL:
case WIRE_FUNDING_CREATED:

53
lightningd/ping.c

@ -0,0 +1,53 @@
#include <lightningd/ping.h>
#include <wire/gen_peer_wire.h>
bool check_ping_make_pong(const tal_t *ctx, const u8 *ping, u8 **pong)
{
u16 num_pong_bytes;
u8 *ignored;
if (!fromwire_ping(ctx, ping, NULL, &num_pong_bytes, &ignored))
return false;
tal_free(ignored);
/* FIXME: */
/* BOLT #1:
*
* A node receiving a `ping` message SHOULD fail the channels if it
* has received significantly in excess of one `ping` per 30 seconds,
*/
/* BOLT #1:
*
* ... otherwise if `num_pong_bytes` is less than 65532 it MUST
* respond by sending a `pong` message with `byteslen` equal to
* `num_pong_bytes`, otherwise it MUST ignore the `ping`.
*/
if (num_pong_bytes < 65532) {
/* BOLT #1:
*
* A node sending `pong` or `ping` SHOULD set `ignored` to
* zeroes, but MUST NOT set `ignored` to sensitive data such
* as secrets, or portions of initialized memory.
*/
ignored = tal_arrz(ctx, u8, num_pong_bytes);
*pong = towire_pong(ctx, ignored);
tal_free(ignored);
}
return true;
}
u8 *make_ping(const tal_t *ctx, u16 num_pong_bytes, u16 padlen)
{
/* BOLT #1:
*
* A node sending `pong` or `ping` SHOULD set `ignored` to zeroes, but
* MUST NOT set `ignored` to sensitive data such as secrets, or
* portions of initialized memory.
*/
u8 *ping, *ignored = tal_arrz(ctx, u8, padlen);
ping = towire_ping(ctx, num_pong_bytes, ignored);
tal_free(ignored);
return ping;
}

13
lightningd/ping.h

@ -0,0 +1,13 @@
#ifndef LIGHTNING_LIGHTNINGD_PING_H
#define LIGHTNING_LIGHTNINGD_PING_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
/* Returns false on error, otherwise *pong set if reply needed. */
bool check_ping_make_pong(const tal_t *ctx, const u8 *ping, u8 **pong);
/* Make a ping packet requesting num_pong_bytes */
u8 *make_ping(const tal_t *ctx, u16 num_pong_bytes, u16 padlen);
#endif /* LIGHTNING_LIGHTNINGD_PING_H */

7
wire/gen_peer_wire_csv

@ -7,6 +7,13 @@ error,17
error,0,channel-id,32
error,32,len,2
error,34,data,len
ping,18
ping,0,num_pong_bytes,2
ping,2,byteslen,2
ping,4,ignored,byteslen
pong,19
pong,0,byteslen,2
pong,2,ignored,byteslen
open_channel,32
open_channel,0,chain-hash,32
open_channel,32,temporary-channel-id,32

2
wire/peer_wire.c

@ -23,6 +23,8 @@ static bool unknown_type(enum wire_type t)
case WIRE_CHANNEL_ANNOUNCEMENT:
case WIRE_NODE_ANNOUNCEMENT:
case WIRE_CHANNEL_UPDATE:
case WIRE_PING:
case WIRE_PONG:
return false;
}
return true;

Loading…
Cancel
Save