diff --git a/common/crypto_sync.c b/common/crypto_sync.c index 0f132411c..5b2e168a0 100644 --- a/common/crypto_sync.c +++ b/common/crypto_sync.c @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include #include @@ -48,6 +51,51 @@ void sync_crypto_write(struct crypto_state *cs, int fd, const void *msg TAKES) #endif } +/* We're happy for the kernel to batch update and gossip messages, but a + * commitment message, for example, should be instantly sent. There's no + * great way of doing this, unfortunately. + * + * Setting TCP_NODELAY on Linux flushes the socket, which really means + * we'd want to toggle on then off it *after* sending. But Linux has + * TCP_CORK. On FreeBSD, it seems (looking at source) not to, so + * there we'd want to set it before the send, and reenable it + * afterwards. Even if this is wrong on other non-Linux platforms, it + * only means one extra packet. + */ +void sync_crypto_write_no_delay(struct crypto_state *cs, int fd, + const void *msg TAKES) +{ + int val; + int opt; + const char *optname; + static bool complained = false; + +#ifdef TCP_CORK + opt = TCP_CORK; + optname = "TCP_CORK"; +#elif defined(TCP_NODELAY) + opt = TCP_NODELAY; + optname = "TCP_NODELAY"; +#else +#error "Please report platform with neither TCP_CORK nor TCP_NODELAY?" +#endif + + val = 1; + if (setsockopt(fd, IPPROTO_TCP, opt, &val, sizeof(val)) != 0) { + /* This actually happens in testing, where we blackhole the fd */ + if (!complained) { + status_broken("setsockopt %s=1: %s", + optname, + strerror(errno)); + complained = true; + } + } + sync_crypto_write(cs, fd, msg); + + val = 0; + setsockopt(fd, IPPROTO_TCP, opt, &val, sizeof(val)); +} + u8 *sync_crypto_read(const tal_t *ctx, struct crypto_state *cs, int fd) { u8 hdr[18], *enc, *dec; diff --git a/common/crypto_sync.h b/common/crypto_sync.h index 31f05c4ef..b86c67db9 100644 --- a/common/crypto_sync.h +++ b/common/crypto_sync.h @@ -9,6 +9,10 @@ struct crypto_state; /* Exits with peer_failed_connection_lost() if write fails. */ void sync_crypto_write(struct crypto_state *cs, int fd, const void *msg TAKES); +/* Same, but disabled nagle for this message. */ +void sync_crypto_write_no_delay(struct crypto_state *cs, int fd, + const void *msg TAKES); + /* Exits with peer_failed_connection_lost() if can't read packet. */ u8 *sync_crypto_read(const tal_t *ctx, struct crypto_state *cs, int fd);