mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
e99720344e
Our TLV serializer relies on TLV outputs to be ordered by type number. Prior to this commit we relied on 1) the ordering in the RFC to be correct and 2) users to be using a version of Python that respects stable ordering of dicts (i.e. Python 3.7+) Instead of relying on these implicitly, we now explicitly sort messages by type number when the TLV sets. Resolves #2956. Thanks-To: @ScottTre for the sort function Reported-By: @ZmnSCPxj
326 lines
9.8 KiB
Plaintext
326 lines
9.8 KiB
Plaintext
/* This file was generated by generate-wire.py */
|
|
/* Do not modify this file! Modify the _csv file it was generated from. */
|
|
/* Original template can be found at tools/gen/impl_template */
|
|
|
|
#include <${header_filename}>
|
|
#include <ccan/array_size/array_size.h>
|
|
#include <ccan/mem/mem.h>
|
|
#include <ccan/tal/str/str.h>
|
|
#include <stdio.h>
|
|
% for comment in top_comments:
|
|
/*${comment} */
|
|
% endfor
|
|
% for enum_set in enum_sets:
|
|
|
|
const char *${enum_set['name']}_name(int e)
|
|
{
|
|
static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)];
|
|
|
|
switch ((enum ${enum_set['name']})e) {
|
|
% for msg in enum_set['set']:
|
|
case ${msg.enum_name()}: return "${msg.enum_name()}";
|
|
% endfor
|
|
}
|
|
|
|
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
|
|
return invalidbuf;
|
|
}
|
|
% endfor
|
|
## START PARTIALS
|
|
## Subtype and TLV-msg towire_
|
|
<%def name="towire_subtype_field(fieldname, f, ptr)">\
|
|
% if f.is_array() or f.is_varlen():
|
|
% if f.type_obj.has_array_helper():
|
|
towire_${f.type_obj.name}_array(${ptr}, ${fieldname}, ${f.size('tal_count(' + fieldname + ')')});
|
|
% else:
|
|
for (size_t i = 0; i < ${f.size('tal_count(' + fieldname + ')')}; i++)
|
|
% if f.type_obj.is_assignable() or f.type_obj.has_len_fields():
|
|
towire_${f.type_obj.name}(${ptr}, ${fieldname}[i]);
|
|
% else:
|
|
towire_${f.type_obj.name}(${ptr}, ${fieldname} + i);
|
|
% endif
|
|
% endif
|
|
% elif f.len_field_of:
|
|
towire_${f.type_obj.name}(${ptr}, ${f.name});
|
|
% else:
|
|
towire_${f.type_obj.name}(${ptr}, ${'' if f.type_obj.is_assignable() else '&'}${fieldname});
|
|
% endif
|
|
</%def>
|
|
## Subtype and TLV-msg fromwire
|
|
<%def name="fromwire_subtype_field(fieldname, f, ctx)">\
|
|
<%
|
|
type_ = f.type_obj.name
|
|
typename = f.type_obj.type_name()
|
|
if f.type_obj.is_varsize():
|
|
typename += ' *'
|
|
%>\
|
|
% if f.is_varlen():
|
|
${fieldname} = ${f.size('*plen')} ? tal_arr(${ctx}, ${typename}, ${f.size('*plen')}) : NULL;
|
|
% endif
|
|
% if f.is_array() or f.is_varlen():
|
|
% if f.type_obj.has_array_helper():
|
|
fromwire_${type_}_array(cursor, plen, ${fieldname}, ${f.size('*plen')});
|
|
% else:
|
|
% if f.is_implicit_len():
|
|
for (size_t i = 0; *plen != 0; i++)
|
|
% else:
|
|
for (size_t i = 0; i < ${f.size()}; i++)
|
|
% endif
|
|
% if f.type_obj.is_assignable():
|
|
(${fieldname})[i] = fromwire_${type_}(cursor, plen);
|
|
% elif f.is_varlen() and f.type_obj.is_varsize():
|
|
(${fieldname})[i] = fromwire_${type_}(${ctx}, cursor, plen);
|
|
% else:
|
|
fromwire_${type_}(cursor, plen, ${fieldname} + i);
|
|
% endif
|
|
% endif
|
|
% else:
|
|
% if f.type_obj.is_assignable():
|
|
${ f.name if f.len_field_of else fieldname} = fromwire_${type_}(cursor, plen);
|
|
% elif f.type_obj.is_varsize():
|
|
${fieldname} = *fromwire_${type_}(${ctx}, cursor, plen);
|
|
% else:
|
|
fromwire_${type_}(cursor, plen, &${fieldname});
|
|
% endif
|
|
%endif
|
|
</%def>
|
|
## END PARTIALS
|
|
## FIXME: extract out partials for the method declarations
|
|
## (shared between here and header_template)
|
|
% for subtype in subtypes: ## START Subtypes
|
|
|
|
/* SUBTYPE: ${subtype.name.upper()} */
|
|
% for c in subtype.type_comments:
|
|
/*${c} */
|
|
% endfor
|
|
<%
|
|
static = '' if options.expose_subtypes else 'static '
|
|
%>\
|
|
${static}void towire_${subtype.name}(u8 **p, const ${subtype.type_name()} *${subtype.name})
|
|
{
|
|
% for f in subtype.get_len_fields():
|
|
${f.type_obj.type_name()} ${f.name} = tal_count(${subtype.name}->${f.len_field_of});
|
|
% endfor
|
|
|
|
% for f in subtype.fields.values():
|
|
% for c in f.field_comments:
|
|
/*${c} */
|
|
% endfor
|
|
<%
|
|
fieldname = '{}->{}'.format(subtype.name,f.name)
|
|
%>\
|
|
${towire_subtype_field(fieldname, f, 'p')}\
|
|
% endfor
|
|
}
|
|
% if subtype.is_varsize():
|
|
${static}${subtype.type_name()} *
|
|
fromwire_${subtype.name}(const tal_t *ctx, const u8 **cursor, size_t *plen)
|
|
% else:
|
|
${static}void fromwire_${subtype.name}(${'const tal_t *ctx, ' if subtype.needs_context() else ''}const u8 **cursor, size_t *plen, ${subtype.type_name()} *${subtype.name})
|
|
% endif
|
|
{
|
|
% if subtype.is_varsize():
|
|
${subtype.type_name()} *${subtype.name} = tal(ctx, ${subtype.type_name()});
|
|
% endif
|
|
## Length field declarations
|
|
% for f in subtype.get_len_fields():
|
|
${f.type_obj.type_name()} ${f.name};
|
|
% endfor
|
|
|
|
% for f in subtype.fields.values():
|
|
% for c in f.field_comments:
|
|
/*${c} */
|
|
% endfor
|
|
<%
|
|
fieldname = '{}->{}'.format(subtype.name,f.name)
|
|
ctx = subtype.name
|
|
%> \
|
|
${fromwire_subtype_field(fieldname, f, ctx)}\
|
|
% endfor
|
|
% if subtype.is_varsize():
|
|
|
|
return ${subtype.name};
|
|
% endif
|
|
}
|
|
% endfor ## END Subtypes
|
|
<%def name="fromwire_phrase(f, type_, varsized)" >\
|
|
%if f.type_obj.is_assignable():
|
|
*${f.name} = fromwire_${type_}(&cursor, &plen);
|
|
% elif varsized:
|
|
*${f.name} = fromwire_${type_}(ctx, &cursor, &plen);
|
|
% else:
|
|
fromwire_${type_}(${'ctx, ' if f.needs_context() else ''}&cursor, &plen, ${'*' if f.is_optional else ''}${f.name});
|
|
% endif
|
|
</%def>
|
|
% for tlv in tlvs.values(): ## START TLV's
|
|
|
|
${tlv.type_name()} *${tlv.struct_name()}_new(const tal_t *ctx)
|
|
{
|
|
/* Initialize everything to NULL. (Quiet, C pedants!) */
|
|
return talz(ctx, struct ${tlv.struct_name()});
|
|
}
|
|
|
|
% for msg in tlv.messages.values():
|
|
/* ${tlv.name.upper()} MSG: ${msg.name} */
|
|
static u8 *towire_${msg.struct_name()}(const tal_t *ctx, const void *vrecord)
|
|
{
|
|
const struct ${tlv.struct_name()} *r = vrecord;
|
|
u8 *ptr;
|
|
|
|
if (!r->${msg.name})
|
|
return NULL;
|
|
|
|
% for f in msg.get_len_fields():
|
|
${f.type_obj.type_name()} ${f.name} = tal_count(r->${msg.name}->${f.len_field_of});
|
|
% endfor
|
|
|
|
ptr = tal_arr(ctx, u8, 0);
|
|
% for f in msg.fields.values():
|
|
<% fieldname = 'r->{}->{}'.format(msg.name, f.name) %>\
|
|
${towire_subtype_field(fieldname, f, '&ptr')}\
|
|
% endfor
|
|
return ptr;
|
|
}
|
|
static void fromwire_${msg.struct_name()}(const u8 **cursor, size_t *plen, void *vrecord)
|
|
{
|
|
struct ${tlv.struct_name()} *r = vrecord;
|
|
## Length field declarations
|
|
% for f in msg.get_len_fields():
|
|
${f.type_obj.type_name()} ${f.name};
|
|
% endfor
|
|
|
|
r->${msg.name} = tal(r, struct ${msg.struct_name()});
|
|
% for f in msg.fields.values():
|
|
<%
|
|
fieldname = 'r->{}->{}'.format(msg.name, f.name)
|
|
ctx = 'r->{}'.format(msg.name)
|
|
%>\
|
|
${fromwire_subtype_field(fieldname, f, ctx)}\
|
|
% endfor
|
|
}
|
|
% endfor
|
|
|
|
<% static = '' if tlv.name in options.expose_tlv_type else 'static '
|
|
%>\
|
|
${static}const struct tlv_record_type tlvs_${tlv.name}[] = {
|
|
% for msg in tlv.ordered_msgs():
|
|
{ ${msg.number}, towire_${msg.struct_name()}, fromwire_${msg.struct_name()} },
|
|
% endfor
|
|
};
|
|
% endfor ## END TLV's
|
|
% for msg in messages: ## START Wire Messages
|
|
|
|
/* WIRE: ${msg.name.upper()} */
|
|
% for c in msg.msg_comments:
|
|
/*${c} */
|
|
% endfor
|
|
u8 *towire_${msg.name}(const tal_t *ctx${''.join([f.arg_desc_to() for f in msg.fields.values()])})
|
|
{
|
|
## FIXME: we're ignoring TLV's rn
|
|
% for f in msg.get_len_fields():
|
|
${f.type_obj.type_name()} ${f.name} = tal_count(${f.len_field_of});
|
|
% endfor
|
|
u8 *p = tal_arr(ctx, u8, 0);
|
|
|
|
towire_u16(&p, ${msg.enum_name()});
|
|
% for f in msg.fields.values():
|
|
% for c in f.field_comments:
|
|
/*${c} */
|
|
% endfor
|
|
% if f.is_array() or f.is_varlen():
|
|
% if f.type_obj.has_array_helper():
|
|
towire_${f.type_obj.name}_array(&p, ${f.name}, ${f.size('tal_count(' + f.name + ')')});
|
|
% else:
|
|
for (size_t i = 0; i < ${f.size('tal_count(' + f.name + ')')}; i++)
|
|
% if f.type_obj.is_assignable() or f.type_obj.is_varsize():
|
|
towire_${f.type_obj.name}(&p, ${f.name}[i]);
|
|
% else:
|
|
towire_${f.type_obj.name}(&p, ${f.name} + i);
|
|
% endif
|
|
% endif
|
|
% elif f.type_obj.is_tlv():
|
|
towire_tlvs(&p, tlvs_${f.type_obj.tlv.name}, ARRAY_SIZE(tlvs_${f.type_obj.tlv.name}), ${f.name});
|
|
% elif f.is_optional: ## is optional?
|
|
if (!${f.name})
|
|
towire_bool(&p, false);
|
|
else {
|
|
towire_bool(&p, true);
|
|
towire_${f.type_obj.name}(&p, ${'*' if f.type_obj.is_assignable() else ''}${f.name});
|
|
}
|
|
% else: ## all other cases
|
|
towire_${f.type_obj.name}(&p, ${f.name});
|
|
% endif
|
|
% endfor
|
|
|
|
return memcheck(p, tal_count(p));
|
|
}
|
|
bool fromwire_${msg.name}(${'const tal_t *ctx, ' if msg.needs_context() else ''}const void *p${''.join([f.arg_desc_from() for f in msg.fields.values()])})
|
|
{
|
|
% if msg.get_len_fields():
|
|
% for f in msg.get_len_fields():
|
|
${f.type_obj.type_name()} ${f.name};
|
|
% endfor
|
|
|
|
% endif
|
|
const u8 *cursor = p;
|
|
size_t plen = tal_count(p);
|
|
|
|
if (fromwire_u16(&cursor, &plen) != ${msg.enum_name()})
|
|
return false;
|
|
% for f in msg.fields.values():
|
|
<%
|
|
typename = f.type_obj.type_name()
|
|
if f.type_obj.is_varsize():
|
|
typename = typename + ' *'
|
|
type_ = f.type_obj.name
|
|
varsized = f.type_obj.is_varsize()
|
|
%> \
|
|
% for c in f.field_comments:
|
|
/*${c} */
|
|
% endfor
|
|
% if f.is_varlen():
|
|
// 2nd case ${f.name}
|
|
*${f.name} = ${f.size('plen')} ? tal_arr(ctx, ${typename}, ${f.size('plen')}) : NULL;
|
|
% endif
|
|
% if f.len_field_of:
|
|
${f.name} = fromwire_${type_}(&cursor, &plen);
|
|
% elif f.type_obj.is_tlv():
|
|
fromwire_tlvs(&cursor, &plen, tlvs_${f.type_obj.tlv.name}, ARRAY_SIZE(tlvs_${f.type_obj.tlv.name}), ${f.name});
|
|
% elif f.is_array() or f.is_varlen():
|
|
% if f.type_obj.has_array_helper():
|
|
fromwire_${type_}_array(&cursor, &plen, ${'*' if f.is_varlen() else ''}${f.name}, ${f.size('plen')});
|
|
% else:
|
|
% if f.is_implicit_len():
|
|
for (size_t i = 0; plen != 0; i++)
|
|
% else:
|
|
for (size_t i = 0; i < ${f.size()}; i++)
|
|
% endif
|
|
% if not varsized and not f.type_obj.is_assignable():
|
|
% if f.is_varlen():
|
|
fromwire_${type_}(&cursor, &plen, *${f.name} + i);
|
|
% else:
|
|
fromwire_${type_}(&cursor, &plen, &(${f.name}[i]));
|
|
% endif
|
|
% else:
|
|
(${'' if f.type_obj.is_assignable() and f.is_array() else '*'}${f.name})[i] = fromwire_${type_}(${'*'+f.name+', ' if varsized else ''}&cursor, &plen);
|
|
% endif
|
|
% endif
|
|
% else:
|
|
% if not f.is_optional:
|
|
${fromwire_phrase(f, type_, varsized)}\
|
|
% else: ## Start optional
|
|
if (!fromwire_bool(&cursor, &plen))
|
|
*${f.name} = NULL;
|
|
else {
|
|
% if not varsized:
|
|
*${f.name} = tal(ctx, ${typename});
|
|
% endif
|
|
${'*' if f.type_obj.is_assignable() else ''}${fromwire_phrase(f, type_, varsized)}\
|
|
}
|
|
% endif ## End optional
|
|
% endif
|
|
% endfor
|
|
return cursor != NULL;
|
|
}
|
|
% endfor ## END Wire Messages
|