@ -77,7 +77,7 @@
/* In developer mode we provide hooks for whitebox testing */
# if DEVELOPER
static u32 max_scids_encode _bytes = - 1U ;
static u32 max_encoding _bytes = - 1U ;
static bool suppress_gossip = false ;
# endif
@ -261,16 +261,14 @@ static void queue_peer_from_store(struct peer *peer,
* simple compression scheme : the first byte indicates the encoding , the
* rest contains the data .
*/
static u8 * encode_short_channel_ids _start ( const tal_t * ctx )
static u8 * encoding _start ( const tal_t * ctx )
{
u8 * encoded = tal_arr ( ctx , u8 , 0 ) ;
towire_u8 ( & encoded , SHORTIDS_ZLIB ) ;
return encoded ;
return tal_arr ( ctx , u8 , 0 ) ;
}
/* Marshal a single short_channel_id */
static void encode _add_short_channel_id ( u8 * * encoded ,
const struct short_channel_id * scid )
static void encoding _add_short_channel_id ( u8 * * encoded ,
const struct short_channel_id * scid )
{
towire_short_channel_id ( encoded , scid ) ;
}
@ -281,7 +279,7 @@ static void encode_add_short_channel_id(u8 **encoded,
* more complex and use separate streams . The upside is that it ' s between
* 2 and 5 times smaller ( assuming optimal Rice encoding + gzip ) . We can add
* that later . */
static u8 * zencode_scids ( const tal_t * ctx , const u8 * scids , size_t len )
static u8 * zencode ( const tal_t * ctx , const u8 * scids , size_t len )
{
u8 * z ;
int err ;
@ -291,50 +289,73 @@ static u8 *zencode_scids(const tal_t *ctx, const u8 *scids, size_t len)
z = tal_arr ( ctx , u8 , len ) ;
err = compress2 ( z , & compressed_len , scids , len , Z_BEST_COMPRESSION ) ;
if ( err = = Z_OK ) {
status_trace ( " short_ids compressed %zu into %lu" ,
status_trace ( " compressed %zu into %lu " ,
len , compressed_len ) ;
tal_resize ( & z , compressed_len ) ;
return z ;
}
status_trace ( " short_ids compress %zu returned %i:"
status_trace ( " compress %zu returned %i: "
" not compresssing " , len , err ) ;
return NULL ;
}
/* Once we've assembled */
static bool encode_short_channel_ids_end ( u8 * * encoded , size_t max_bytes )
/* Try compressing *encoded: fails if result would be longer.
* @ off is offset to place result in * encoded .
*/
static bool encoding_end_zlib ( u8 * * encoded , size_t off )
{
u8 * z ;
size_t len = tal_count ( * encoded ) ;
/* First byte says what encoding we want. */
switch ( ( enum scid_encode_types ) ( * encoded ) [ 0 ] ) {
case SHORTIDS_ZLIB :
/* compress */
z = zencode_scids ( tmpctx , * encoded + 1 , tal_count ( * encoded ) - 1 ) ;
if ( z ) {
/* If successful, copy over and trimp */
tal_resize ( encoded , 1 + tal_count ( z ) ) ;
memcpy ( ( * encoded ) + 1 , z , tal_count ( z ) ) ;
goto check_length ;
}
/* Otherwise, change first byte to 'uncompressed' */
( * encoded ) [ 0 ] = SHORTIDS_UNCOMPRESSED ;
/* Fall thru */
case SHORTIDS_UNCOMPRESSED :
goto check_length ;
}
z = zencode ( tmpctx , * encoded , len ) ;
if ( ! z )
return false ;
status_failed ( STATUS_FAIL_INTERNAL_ERROR ,
" Unknown short_ids encoding %u " , ( * encoded ) [ 0 ] ) ;
/* Successful: copy over and trim */
tal_resize ( encoded , off + tal_count ( z ) ) ;
memcpy ( * encoded + off , z , tal_count ( z ) ) ;
return true ;
}
static void encoding_end_no_compress ( u8 * * encoded , size_t off )
{
size_t len = tal_count ( * encoded ) ;
tal_resize ( encoded , off + len ) ;
memmove ( * encoded + off , * encoded , len ) ;
}
/* Once we've assembled it, try compressing.
* Prepends encoding type to @ encoding . */
static bool encoding_end_prepend_type ( u8 * * encoded , size_t max_bytes )
{
if ( encoding_end_zlib ( encoded , 1 ) )
* * encoded = SHORTIDS_ZLIB ;
else {
encoding_end_no_compress ( encoded , 1 ) ;
* * encoded = SHORTIDS_UNCOMPRESSED ;
}
check_length :
# if DEVELOPER
if ( tal_count ( * encoded ) > max_scids_encode_bytes )
if ( tal_count ( * encoded ) > max_encoding _bytes )
return false ;
# endif
return tal_count ( * encoded ) < = max_bytes ;
}
/* Try compressing, leaving type external */
static UNNEEDED bool encoding_end_external_type ( u8 * * encoded , u8 * type , size_t max_bytes )
{
if ( encoding_end_zlib ( encoded , 0 ) )
* type = SHORTIDS_ZLIB ;
else {
encoding_end_no_compress ( encoded , 0 ) ;
* type = SHORTIDS_UNCOMPRESSED ;
}
return tal_count ( * encoded ) < = max_bytes ;
}
/*~ We have different levels of gossipiness, depending on our needs. */
static u32 gossip_start ( enum gossip_level gossip_level )
{
@ -609,11 +630,11 @@ static bool query_short_channel_ids(struct daemon *daemon,
if ( peer - > scid_query_outstanding )
return false ;
encoded = encode_short_channel_ids _start ( tmpctx ) ;
encoded = encoding _start ( tmpctx ) ;
for ( size_t i = 0 ; i < tal_count ( scids ) ; i + + )
encode _add_short_channel_id ( & encoded , & scids [ i ] ) ;
encoding _add_short_channel_id ( & encoded , & scids [ i ] ) ;
if ( ! encode_short_channel_ids_end ( & encoded , max_encoded_bytes ) ) {
if ( ! encoding_end_prepend_type ( & encoded , max_encoded_bytes ) ) {
status_broken ( " query_short_channel_ids: %zu is too many " ,
tal_count ( scids ) ) ;
return false ;
@ -892,7 +913,7 @@ static bool queue_channel_ranges(struct peer *peer,
u32 tail_blocks )
{
struct routing_state * rstate = peer - > daemon - > rstate ;
u8 * encoded = encode_short_channel_ids _start ( tmpctx ) ;
u8 * encoded_scids = encoding _start ( tmpctx ) ;
struct short_channel_id scid ;
bool scid_ok ;
@ -930,14 +951,14 @@ static bool queue_channel_ranges(struct peer *peer,
if ( blocknum > = first_blocknum + number_of_blocks )
break ;
encode _add_short_channel_id ( & encoded , & scid ) ;
encoding _add_short_channel_id ( & encoded_scids , & scid ) ;
}
/* If we can encode that, fine: send it */
if ( encode_short_channel_ids_end ( & encoded , max_encoded_bytes ) ) {
if ( encoding_end_prepend_type ( & encoded_scids , max_encoded_bytes ) ) {
reply_channel_range ( peer , first_blocknum ,
number_of_blocks + tail_blocks ,
encoded ) ;
encoded_scids ) ;
return true ;
}
@ -2790,10 +2811,10 @@ static struct io_plan *dev_set_max_scids_encode_size(struct io_conn *conn,
const u8 * msg )
{
if ( ! fromwire_gossip_dev_set_max_scids_encode_size ( msg ,
& max_scids_encode _bytes ) )
& max_encoding _bytes ) )
master_badmsg ( WIRE_GOSSIP_DEV_SET_MAX_SCIDS_ENCODE_SIZE , msg ) ;
status_trace ( " Set max_scids_encode_bytes to %u " , max_scids_encode _bytes ) ;
status_trace ( " Set max_scids_encode_bytes to %u " , max_encoding _bytes ) ;
return daemon_conn_read_next ( conn , daemon - > master ) ;
}