mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-20 02:27:51 +01:00
83ee68ab06
Callers were supposed to call "tlv_fields_valid" after fromwire_tlv, but few did. Make this the default, and call the underlying function directly where we want to be more flexible (one place). This loses the ability to allow misordered fields, or to pass through *any* even fields. We restore that for special cases in the next patch. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
400 lines
12 KiB
Plaintext
400 lines
12 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 <assert.h>
|
|
#include <ccan/array_size/array_size.h>
|
|
#include <ccan/mem/mem.h>
|
|
#include <ccan/tal/str/str.h>
|
|
#include <common/utils.h>
|
|
#include <stdio.h>
|
|
% for i in includes:
|
|
${i}
|
|
% endfor
|
|
|
|
#ifndef SUPERVERBOSE
|
|
#define SUPERVERBOSE(...)
|
|
#endif
|
|
|
|
% 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;
|
|
}
|
|
|
|
bool ${enum_set['name']}_is_defined(u16 type)
|
|
{
|
|
switch ((enum ${enum_set['name']})type) {
|
|
% for msg in enum_set['set']:
|
|
case ${msg.enum_name()}:;
|
|
% endfor
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
% endfor
|
|
## START PARTIALS
|
|
## Subtype and TLV-msg towire_
|
|
<%def name="towire_subtype_field(fieldname, f, type_obj, is_single_ptr, ptr)">\
|
|
% if f.is_array() or f.is_varlen():
|
|
% if type_obj.has_array_helper():
|
|
towire_${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 type_obj.is_assignable() or type_obj.is_varsize():
|
|
towire_${type_obj.name}(${ptr}, ${fieldname}[i]);
|
|
% else:
|
|
towire_${type_obj.name}(${ptr}, ${fieldname} + i);
|
|
% endif
|
|
% endif
|
|
% elif f.len_field_of:
|
|
towire_${type_obj.name}(${ptr}, ${f.name});
|
|
% elif is_single_ptr:
|
|
towire_${type_obj.name}(${ptr}, ${'*' if type_obj.is_assignable() else ''}${fieldname});
|
|
% else:
|
|
towire_${type_obj.name}(${ptr}, ${'' if type_obj.is_assignable() or type_obj.is_varsize() else '&'}${fieldname});
|
|
% endif
|
|
</%def>
|
|
## Subtype and TLV-msg fromwire
|
|
<%def name="fromwire_subtype_field(fieldname, f, ctx, is_ptr)">\
|
|
<%
|
|
type_ = f.type_obj.name
|
|
typename = f.type_obj.type_name()
|
|
if f.type_obj.is_varsize():
|
|
typename += ' *'
|
|
%>\
|
|
% if f.is_array() or f.is_varlen():
|
|
% if f.type_obj.has_array_helper():
|
|
## We assume array helpers only deal with things literally transcribed!!
|
|
% if f.is_varlen():
|
|
${fieldname} = tal_arr(${ctx}, ${typename}, ${f.size('*plen')});
|
|
% endif
|
|
fromwire_${type_}_array(cursor, plen, ${fieldname}, ${f.size('*plen')});
|
|
% else:
|
|
% if f.is_varlen():
|
|
${fieldname} = ${f.size('*plen')} ? tal_arr(${ctx}, ${typename}, 0) : NULL;
|
|
% endif
|
|
% if f.is_implicit_len():
|
|
for (size_t i = 0; *plen != 0; i++) {
|
|
% else:
|
|
for (size_t i = 0; i < ${f.size()}; i++) {
|
|
% endif
|
|
${typename} tmp;
|
|
% if f.type_obj.is_assignable():
|
|
tmp = fromwire_${type_}(cursor, plen);
|
|
% elif f.is_varlen() and f.type_obj.is_varsize():
|
|
tmp = fromwire_${type_}(${ctx}, cursor, plen);
|
|
% else:
|
|
fromwire_${type_}(cursor, plen, &tmp);
|
|
% endif
|
|
tal_arr_expand(&${fieldname}, tmp);
|
|
}
|
|
% endif
|
|
% else:
|
|
% if is_ptr:
|
|
${fieldname} = tal(${ctx}, ${typename});
|
|
<% fieldname = '*' + fieldname %>
|
|
% endif
|
|
% 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, f.type_obj, False, '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, False)}\
|
|
% 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!) */
|
|
${tlv.type_name()} *inst = talz(ctx, struct ${tlv.struct_name()});
|
|
|
|
/* Initialized the fields to an empty array. */
|
|
inst->fields = tal_arr(inst, struct tlv_field, 0);
|
|
return inst;
|
|
}
|
|
|
|
% 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():
|
|
<%
|
|
if msg.singleton():
|
|
fieldname = 'r->{}'.format(msg.name)
|
|
type_obj = msg.singleton().type_obj
|
|
else:
|
|
fieldname = 'r->{}->{}'.format(msg.name, f.name)
|
|
type_obj = f.type_obj
|
|
%>
|
|
${towire_subtype_field(fieldname, f, type_obj, msg.singleton(), '&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
|
|
|
|
% if not msg.singleton():
|
|
r->${msg.name} = tal(r, struct ${msg.struct_name()});
|
|
% endif
|
|
% for f in msg.fields.values():
|
|
<%
|
|
if msg.singleton():
|
|
fieldname = 'r->{}'.format(msg.name)
|
|
ctx = 'r'
|
|
else:
|
|
fieldname = 'r->{}->{}'.format(msg.name, f.name)
|
|
ctx = 'r->{}'.format(msg.name)
|
|
%>\
|
|
${fromwire_subtype_field(fieldname, f, ctx, msg.singleton() and not f.type_obj.is_varsize())}\
|
|
% 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
|
|
};
|
|
|
|
void towire_${tlv.name}(u8 **pptr, const struct ${tlv.struct_name()} *record)
|
|
{
|
|
towire_tlv(pptr, tlvs_${tlv.name}, ${len(tlv.messages)}, record);
|
|
}
|
|
|
|
|
|
struct ${tlv.name} *fromwire_${tlv.name}(const tal_t *ctx, const u8 **cursor, size_t *max)
|
|
{
|
|
struct ${tlv.name} *record = ${tlv.name}_new(ctx);
|
|
if (!fromwire_tlv(cursor, max, tlvs_${tlv.name}, ${len(tlv.messages)}, record, &record->fields, NULL, NULL, NULL))
|
|
return tal_free(record);
|
|
return record;
|
|
}
|
|
% endfor ## END TLV's
|
|
% for msg in messages: ## START Wire Messages
|
|
|
|
% if msg.if_token:
|
|
#if ${msg.if_token}
|
|
% endif
|
|
/* 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_${f.type_obj.tlv.name}(&p, ${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() or f.type_obj.is_tlv()
|
|
%> \
|
|
% 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():
|
|
*${f.name} = fromwire_${f.type_obj.tlv.name}(ctx, &cursor, &plen);
|
|
if (!*${f.name})
|
|
return false;
|
|
% 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;
|
|
}
|
|
% if msg.if_token:
|
|
#endif /* ${msg.if_token} */
|
|
% endif
|
|
% endfor ## END Wire Messages
|