2019-07-24 01:54:21 +02:00
/* This file was generated by generate-wire.py */
2020-08-25 04:19:58 +02:00
/* Do not modify this file! Modify the .csv file it was generated from. */
2019-07-15 02:10:01 +02:00
/* Original template can be found at tools/gen/impl_template */
#include <${header_filename}>
2019-11-18 19:52:20 +01:00
#include <assert.h>
2019-07-20 01:21:25 +02:00
#include <ccan/array_size/array_size.h>
2019-07-15 02:10:01 +02:00
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
2020-05-15 12:32:43 +02:00
#include <common/utils.h>
2019-07-15 02:10:01 +02:00
#include <stdio.h>
2019-11-18 19:52:20 +01:00
#ifndef SUPERVERBOSE
#define SUPERVERBOSE(...)
#endif
2019-07-19 18:33:03 +02:00
% for comment in top_comments:
/*${comment} */
% endfor
2019-07-15 02:10:01 +02:00
% for enum_set in enum_sets:
2019-07-19 18:33:03 +02:00
2019-07-15 02:10:01 +02:00
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;
}
2019-12-04 16:51:47 +01:00
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;
}
2019-07-15 02:10:01 +02:00
% endfor
2019-07-20 01:21:25 +02:00
## START PARTIALS
## Subtype and TLV-msg towire_
2020-05-06 12:41:54 +02:00
<%def name="towire_subtype_field(fieldname, f, type_obj, is_single_ptr, ptr)">\
2019-07-20 01:21:25 +02:00
% if f.is_array() or f.is_varlen():
2020-05-06 12:41:54 +02:00
% if type_obj.has_array_helper():
towire_${type_obj.name}_array(${ptr}, ${fieldname}, ${f.size('tal_count(' + fieldname + ')')});
2019-07-20 01:21:25 +02:00
% else:
2019-11-26 15:56:36 +01:00
for (size_t i = 0; i < ${f.size('tal_count(' + fieldname + ')')}; i++)
2020-08-25 05:25:13 +02:00
% if type_obj.is_assignable() or type_obj.is_varsize():
2020-05-06 12:41:54 +02:00
towire_${type_obj.name}(${ptr}, ${fieldname}[i]);
2019-07-20 01:21:25 +02:00
% else:
2020-05-06 12:41:54 +02:00
towire_${type_obj.name}(${ptr}, ${fieldname} + i);
2019-07-20 01:21:25 +02:00
% endif
% endif
% elif f.len_field_of:
2020-05-06 12:41:54 +02:00
towire_${type_obj.name}(${ptr}, ${f.name});
% elif is_single_ptr:
towire_${type_obj.name}(${ptr}, ${'*' if type_obj.is_assignable() else ''}${fieldname});
2019-07-20 01:21:25 +02:00
% else:
tools/generate-wire.py: fix varsize assignment.
Code like this is suspicious:
subtype_varsize_struct->field_0 = *fromwire_test_features(subtype_varsize_struct, cursor, plen);
In fact, it is a memory leak since we copy and don't free the fromwire
result. Really, field_0 should be a pointer.
We don't hit this case (yet!) in spec-generated code, but I did for
bolt13.
Here's the difference in gen_test output:
```patch
diff -ur /tmp/before/test/gen_test.c /tmp/after/test/gen_test.c
--- /tmp/before/test/gen_test.c 2020-05-07 16:23:31.651611235 +0930
+++ /tmp/after/test/gen_test.c 2020-05-07 16:20:54.232574482 +0930
@@ -214,12 +214,12 @@
static void towire_subtype_varsize_struct(u8 **p, const struct subtype_varsize_struct *subtype_varsize_struct)
{
- towire_test_features(p, &subtype_varsize_struct->field_0);
+ towire_test_features(p, subtype_varsize_struct->field_0);
}
static void fromwire_subtype_varsize_struct(const u8 **cursor, size_t *plen, struct subtype_varsize_struct *subtype_varsize_struct)
{
- subtype_varsize_struct->field_0 = *fromwire_test_features(subtype_varsize_struct, cursor, plen);
+ subtype_varsize_struct->field_0 = fromwire_test_features(subtype_varsize_struct, cursor, plen);
}
/* SUBTYPE: SUBTYPE_VAR_LEN */
@@ -373,7 +373,7 @@
ptr = tal_arr(ctx, u8, 0);
- towire_test_features(&ptr, &r->tlv3->features);
+ towire_test_features(&ptr, r->tlv3->features);
towire_amount_msat(&ptr, r->tlv3->amount_msat_1);
@@ -385,7 +385,7 @@
struct tlv_test_n1 *r = vrecord;
r->tlv3 = tal(r, struct tlv_test_n1_tlv3);
- r->tlv3->features = *fromwire_test_features(r->tlv3, cursor, plen);
+ r->tlv3->features = fromwire_test_features(r->tlv3, cursor, plen);
r->tlv3->amount_msat_1 = fromwire_amount_msat(cursor, plen);
r->tlv3->amount_msat_2 = fromwire_amount_msat(cursor, plen);
}
@@ -824,11 +824,11 @@
towire_test_short_id(&ptr, &r->tlv3->subtype);
- towire_subtype_var_len(&ptr, &r->tlv3->varlen_subtype);
+ towire_subtype_var_len(&ptr, r->tlv3->varlen_subtype);
- towire_subtype_var_assign(&ptr, &r->tlv3->varlen_assigned);
+ towire_subtype_var_assign(&ptr, r->tlv3->varlen_assigned);
- towire_subtype_varlen_varsize(&ptr, &r->tlv3->test_sbt_varlen_varsize);
+ towire_subtype_varlen_varsize(&ptr, r->tlv3->test_sbt_varlen_varsize);
for (size_t i = 0; i < 2; i++)
towire_u32(&ptr, r->tlv3->arr_assign[i]);
@@ -868,9 +868,9 @@
r->tlv3 = tal(r, struct tlv_test_n3_tlv3);
fromwire_test_short_id(cursor, plen, &r->tlv3->subtype);
- r->tlv3->varlen_subtype = *fromwire_subtype_var_len(r->tlv3, cursor, plen);
- r->tlv3->varlen_assigned = *fromwire_subtype_var_assign(r->tlv3, cursor, plen);
- r->tlv3->test_sbt_varlen_varsize = *fromwire_subtype_varlen_varsize(r->tlv3, cursor, plen);
+ r->tlv3->varlen_subtype = fromwire_subtype_var_len(r->tlv3, cursor, plen);
+ r->tlv3->varlen_assigned = fromwire_subtype_var_assign(r->tlv3, cursor, plen);
+ r->tlv3->test_sbt_varlen_varsize = fromwire_subtype_varlen_varsize(r->tlv3, cursor, plen);
for (size_t i = 0; i < 2; i++) {
u32 tmp;
tmp = fromwire_u32(cursor, plen);
diff -ur /tmp/before/test/gen_test.h /tmp/after/test/gen_test.h
--- /tmp/before/test/gen_test.h 2020-05-07 16:23:30.399617108 +0930
+++ /tmp/after/test/gen_test.h 2020-05-07 16:20:52.912584680 +0930
@@ -45,7 +45,7 @@
struct test_short_id field_1;
};
struct subtype_varsize_struct {
- struct test_features field_0;
+ struct test_features *field_0;
};
struct subtype_var_len {
struct test_short_id *field_2;
@@ -60,15 +60,15 @@
struct test_short_id field3[2];
};
struct tlv_test_n1_tlv3 {
- struct test_features features;
+ struct test_features *features;
struct amount_msat amount_msat_1;
struct amount_msat amount_msat_2;
};
struct tlv_test_n3_tlv3 {
struct test_short_id subtype;
- struct subtype_var_len varlen_subtype;
- struct subtype_var_assign varlen_assigned;
- struct subtype_varlen_varsize test_sbt_varlen_varsize;
+ struct subtype_var_len *varlen_subtype;
+ struct subtype_var_assign *varlen_assigned;
+ struct subtype_varlen_varsize *test_sbt_varlen_varsize;
/* array assigtest_nable */
u32 arr_assign[2];
/* array structs */
Binary files /tmp/before/test/gen_test.o and /tmp/after/test/gen_test.o differ
Binary files /tmp/before/test/run-test-wire and /tmp/after/test/run-test-wire differ
Binary files /tmp/before/test/run-test-wire.o and /tmp/after/test/run-test-wire.o differ
```
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-08-25 05:24:13 +02:00
towire_${type_obj.name}(${ptr}, ${'' if type_obj.is_assignable() or type_obj.is_varsize() else '&'}${fieldname});
2019-07-20 01:21:25 +02:00
% endif
</%def>
2019-07-25 17:58:14 +02:00
## Subtype and TLV-msg fromwire
2020-05-06 12:41:54 +02:00
<%def name="fromwire_subtype_field(fieldname, f, ctx, is_ptr)">\
2019-07-20 01:21:25 +02:00
<%
type_ = f.type_obj.name
typename = f.type_obj.type_name()
2019-07-25 17:58:14 +02:00
if f.type_obj.is_varsize():
typename += ' *'
2019-07-20 01:21:25 +02:00
%>\
% if f.is_array() or f.is_varlen():
% if f.type_obj.has_array_helper():
2019-12-13 05:49:46 +01:00
## We assume array helpers only deal with things literally transcribed!!
% if f.is_varlen():
${fieldname} = ${f.size('*plen')} ? tal_arr(${ctx}, ${typename}, ${f.size('*plen')}) : NULL;
% endif
2019-07-28 02:52:43 +02:00
fromwire_${type_}_array(cursor, plen, ${fieldname}, ${f.size('*plen')});
2019-07-20 01:21:25 +02:00
% else:
2019-12-13 05:49:46 +01:00
% if f.is_varlen():
${fieldname} = ${f.size('*plen')} ? tal_arr(${ctx}, ${typename}, 0) : NULL;
% endif
2019-07-28 02:52:43 +02:00
% if f.is_implicit_len():
2019-12-13 05:49:46 +01:00
for (size_t i = 0; *plen != 0; i++) {
2019-07-28 02:52:43 +02:00
% else:
2019-12-13 05:49:46 +01:00
for (size_t i = 0; i < ${f.size()}; i++) {
2019-07-28 02:52:43 +02:00
% endif
2019-12-13 05:49:46 +01:00
${typename} tmp;
2019-07-20 01:21:25 +02:00
% if f.type_obj.is_assignable():
2019-12-13 05:49:46 +01:00
tmp = fromwire_${type_}(cursor, plen);
2019-07-20 01:21:25 +02:00
% elif f.is_varlen() and f.type_obj.is_varsize():
2019-12-13 05:49:46 +01:00
tmp = fromwire_${type_}(${ctx}, cursor, plen);
2019-07-20 01:21:25 +02:00
% else:
2019-12-13 05:49:46 +01:00
fromwire_${type_}(cursor, plen, &tmp);
2019-07-20 01:21:25 +02:00
% endif
2019-12-13 05:49:46 +01:00
tal_arr_expand(&${fieldname}, tmp);
}
2019-07-20 01:21:25 +02:00
% endif
% else:
2020-05-06 12:41:54 +02:00
% if is_ptr:
${fieldname} = tal(${ctx}, ${typename});
<% fieldname = '*' + fieldname %>
% endif
2019-07-20 01:21:25 +02:00
% 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():
tools/generate-wire.py: fix varsize assignment.
Code like this is suspicious:
subtype_varsize_struct->field_0 = *fromwire_test_features(subtype_varsize_struct, cursor, plen);
In fact, it is a memory leak since we copy and don't free the fromwire
result. Really, field_0 should be a pointer.
We don't hit this case (yet!) in spec-generated code, but I did for
bolt13.
Here's the difference in gen_test output:
```patch
diff -ur /tmp/before/test/gen_test.c /tmp/after/test/gen_test.c
--- /tmp/before/test/gen_test.c 2020-05-07 16:23:31.651611235 +0930
+++ /tmp/after/test/gen_test.c 2020-05-07 16:20:54.232574482 +0930
@@ -214,12 +214,12 @@
static void towire_subtype_varsize_struct(u8 **p, const struct subtype_varsize_struct *subtype_varsize_struct)
{
- towire_test_features(p, &subtype_varsize_struct->field_0);
+ towire_test_features(p, subtype_varsize_struct->field_0);
}
static void fromwire_subtype_varsize_struct(const u8 **cursor, size_t *plen, struct subtype_varsize_struct *subtype_varsize_struct)
{
- subtype_varsize_struct->field_0 = *fromwire_test_features(subtype_varsize_struct, cursor, plen);
+ subtype_varsize_struct->field_0 = fromwire_test_features(subtype_varsize_struct, cursor, plen);
}
/* SUBTYPE: SUBTYPE_VAR_LEN */
@@ -373,7 +373,7 @@
ptr = tal_arr(ctx, u8, 0);
- towire_test_features(&ptr, &r->tlv3->features);
+ towire_test_features(&ptr, r->tlv3->features);
towire_amount_msat(&ptr, r->tlv3->amount_msat_1);
@@ -385,7 +385,7 @@
struct tlv_test_n1 *r = vrecord;
r->tlv3 = tal(r, struct tlv_test_n1_tlv3);
- r->tlv3->features = *fromwire_test_features(r->tlv3, cursor, plen);
+ r->tlv3->features = fromwire_test_features(r->tlv3, cursor, plen);
r->tlv3->amount_msat_1 = fromwire_amount_msat(cursor, plen);
r->tlv3->amount_msat_2 = fromwire_amount_msat(cursor, plen);
}
@@ -824,11 +824,11 @@
towire_test_short_id(&ptr, &r->tlv3->subtype);
- towire_subtype_var_len(&ptr, &r->tlv3->varlen_subtype);
+ towire_subtype_var_len(&ptr, r->tlv3->varlen_subtype);
- towire_subtype_var_assign(&ptr, &r->tlv3->varlen_assigned);
+ towire_subtype_var_assign(&ptr, r->tlv3->varlen_assigned);
- towire_subtype_varlen_varsize(&ptr, &r->tlv3->test_sbt_varlen_varsize);
+ towire_subtype_varlen_varsize(&ptr, r->tlv3->test_sbt_varlen_varsize);
for (size_t i = 0; i < 2; i++)
towire_u32(&ptr, r->tlv3->arr_assign[i]);
@@ -868,9 +868,9 @@
r->tlv3 = tal(r, struct tlv_test_n3_tlv3);
fromwire_test_short_id(cursor, plen, &r->tlv3->subtype);
- r->tlv3->varlen_subtype = *fromwire_subtype_var_len(r->tlv3, cursor, plen);
- r->tlv3->varlen_assigned = *fromwire_subtype_var_assign(r->tlv3, cursor, plen);
- r->tlv3->test_sbt_varlen_varsize = *fromwire_subtype_varlen_varsize(r->tlv3, cursor, plen);
+ r->tlv3->varlen_subtype = fromwire_subtype_var_len(r->tlv3, cursor, plen);
+ r->tlv3->varlen_assigned = fromwire_subtype_var_assign(r->tlv3, cursor, plen);
+ r->tlv3->test_sbt_varlen_varsize = fromwire_subtype_varlen_varsize(r->tlv3, cursor, plen);
for (size_t i = 0; i < 2; i++) {
u32 tmp;
tmp = fromwire_u32(cursor, plen);
diff -ur /tmp/before/test/gen_test.h /tmp/after/test/gen_test.h
--- /tmp/before/test/gen_test.h 2020-05-07 16:23:30.399617108 +0930
+++ /tmp/after/test/gen_test.h 2020-05-07 16:20:52.912584680 +0930
@@ -45,7 +45,7 @@
struct test_short_id field_1;
};
struct subtype_varsize_struct {
- struct test_features field_0;
+ struct test_features *field_0;
};
struct subtype_var_len {
struct test_short_id *field_2;
@@ -60,15 +60,15 @@
struct test_short_id field3[2];
};
struct tlv_test_n1_tlv3 {
- struct test_features features;
+ struct test_features *features;
struct amount_msat amount_msat_1;
struct amount_msat amount_msat_2;
};
struct tlv_test_n3_tlv3 {
struct test_short_id subtype;
- struct subtype_var_len varlen_subtype;
- struct subtype_var_assign varlen_assigned;
- struct subtype_varlen_varsize test_sbt_varlen_varsize;
+ struct subtype_var_len *varlen_subtype;
+ struct subtype_var_assign *varlen_assigned;
+ struct subtype_varlen_varsize *test_sbt_varlen_varsize;
/* array assigtest_nable */
u32 arr_assign[2];
/* array structs */
Binary files /tmp/before/test/gen_test.o and /tmp/after/test/gen_test.o differ
Binary files /tmp/before/test/run-test-wire and /tmp/after/test/run-test-wire differ
Binary files /tmp/before/test/run-test-wire.o and /tmp/after/test/run-test-wire.o differ
```
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-08-25 05:24:13 +02:00
${fieldname} = fromwire_${type_}(${ctx}, cursor, plen);
2019-07-20 01:21:25 +02:00
% else:
fromwire_${type_}(cursor, plen, &${fieldname});
% endif
%endif
</%def>
## END PARTIALS
2019-07-15 02:10:01 +02:00
## FIXME: extract out partials for the method declarations
## (shared between here and header_template)
2019-07-20 01:21:25 +02:00
% for subtype in subtypes: ## START Subtypes
2019-07-19 18:57:38 +02:00
2019-07-15 02:10:01 +02:00
/* SUBTYPE: ${subtype.name.upper()} */
2019-07-18 00:26:21 +02:00
% for c in subtype.type_comments:
2019-07-19 18:33:03 +02:00
/*${c} */
2019-07-18 00:26:21 +02:00
% endfor
2019-07-19 18:57:38 +02:00
<%
static = '' if options.expose_subtypes else 'static '
%>\
${static}void towire_${subtype.name}(u8 **p, const ${subtype.type_name()} *${subtype.name})
2019-07-15 02:10:01 +02:00
{
% 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():
2019-07-18 00:26:21 +02:00
% for c in f.field_comments:
2019-07-19 18:33:03 +02:00
/*${c} */
2019-07-18 00:26:21 +02:00
% endfor
2019-07-15 02:10:01 +02:00
<%
2020-05-06 12:41:54 +02:00
fieldname = '{}->{}'.format(subtype.name,f.name)
2019-07-19 18:54:39 +02:00
%>\
2020-05-06 12:41:54 +02:00
${towire_subtype_field(fieldname, f, f.type_obj, False, 'p')}\
2019-07-15 02:10:01 +02:00
% endfor
}
2019-07-19 18:54:39 +02:00
% 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
2019-07-15 02:10:01 +02:00
{
2019-07-19 18:54:39 +02:00
% if subtype.is_varsize():
${subtype.type_name()} *${subtype.name} = tal(ctx, ${subtype.type_name()});
% endif
2019-07-15 02:10:01 +02:00
## Length field declarations
% for f in subtype.get_len_fields():
${f.type_obj.type_name()} ${f.name};
% endfor
% for f in subtype.fields.values():
2019-07-18 00:26:21 +02:00
% for c in f.field_comments:
2019-07-23 21:18:43 +02:00
/*${c} */
2019-07-18 00:26:21 +02:00
% endfor
2019-07-15 02:10:01 +02:00
<%
fieldname = '{}->{}'.format(subtype.name,f.name)
2019-07-20 01:21:25 +02:00
ctx = subtype.name
2019-07-15 02:10:01 +02:00
%> \
2020-05-06 12:41:54 +02:00
${fromwire_subtype_field(fieldname, f, ctx, False)}\
2019-07-15 02:10:01 +02:00
% endfor
2019-07-19 18:54:39 +02:00
% if subtype.is_varsize():
2019-07-15 02:10:01 +02:00
2019-07-18 00:26:21 +02:00
return ${subtype.name};
2019-07-19 18:54:39 +02:00
% endif
2019-07-15 02:10:01 +02:00
}
2019-07-19 18:54:39 +02:00
% 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>
2019-07-20 01:21:25 +02:00
% for tlv in tlvs.values(): ## START TLV's
2019-07-21 05:04:59 +02:00
${tlv.type_name()} *${tlv.struct_name()}_new(const tal_t *ctx)
2019-07-20 01:21:25 +02:00
{
/* Initialize everything to NULL. (Quiet, C pedants!) */
2019-11-18 15:53:27 +01:00
${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;
2019-07-20 01:21:25 +02:00
}
% 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():
2020-05-06 12:41:54 +02:00
<%
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')}\
2019-07-20 01:21:25 +02:00
% 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
2020-05-06 12:41:54 +02:00
% if not msg.singleton():
2019-07-20 01:21:25 +02:00
r->${msg.name} = tal(r, struct ${msg.struct_name()});
2020-05-06 12:41:54 +02:00
% endif
2019-07-20 01:21:25 +02:00
% for f in msg.fields.values():
<%
2020-05-06 12:41:54 +02:00
if msg.singleton():
fieldname = 'r->{}'.format(msg.name)
ctx = 'r'
else:
fieldname = 'r->{}->{}'.format(msg.name, f.name)
ctx = 'r->{}'.format(msg.name)
2019-07-20 01:21:25 +02:00
%>\
2020-05-06 12:41:54 +02:00
${fromwire_subtype_field(fieldname, f, ctx, msg.singleton())}\
2019-07-20 01:21:25 +02:00
% endfor
}
% endfor
2019-08-01 06:57:10 +02:00
<% static = '' if tlv.name in options.expose_tlv_type else 'static '
%>\
${static}const struct tlv_record_type tlvs_${tlv.name}[] = {
2019-08-21 04:46:32 +02:00
% for msg in tlv.ordered_msgs():
2019-07-20 01:21:25 +02:00
{ ${msg.number}, towire_${msg.struct_name()}, fromwire_${msg.struct_name()} },
% endfor
};
2019-11-18 19:52:20 +01:00
2019-11-27 15:20:02 +01:00
void towire_${tlv.name}(u8 **pptr,
const void *record)
{
size_t num_types = ${len(tlv.messages)};
const struct tlv_record_type *types = tlvs_${tlv.name};
if (!record)
return;
for (size_t i = 0; i < num_types; i++) {
u8 *val;
if (i != 0)
assert(types[i].type > types[i-1].type);
val = types[i].towire(NULL, record);
if (!val)
continue;
/* BOLT #1:
*
* The sending node:
...
* - MUST minimally encode `type` and `length`.
*/
towire_bigsize(pptr, types[i].type);
towire_bigsize(pptr, tal_bytelen(val));
towire(pptr, val, tal_bytelen(val));
tal_free(val);
}
}
2019-11-18 19:52:20 +01:00
bool fromwire_${tlv.name}(const u8 **cursor, size_t *max, struct ${tlv.struct_name()} *record)
{
size_t num_types = ${len(tlv.messages)};
const struct tlv_record_type *types = tlvs_${tlv.name};
while (*max > 0) {
struct tlv_field field;
/* BOLT #1:
*
2020-09-09 07:48:21 +02:00
* The `type` is encoded using the BigSize format.
2019-11-18 19:52:20 +01:00
*/
field.numtype = fromwire_bigsize(cursor, max);
/* BOLT #1:
* - if a `type` or `length` is not minimally encoded:
* - MUST fail to parse the `tlv_stream`.
*/
if (!*cursor) {
SUPERVERBOSE("type");
goto fail;
}
field.length = fromwire_bigsize(cursor, max);
/* BOLT #1:
* - if a `type` or `length` is not minimally encoded:
* - MUST fail to parse the `tlv_stream`.
*/
if (!*cursor) {
SUPERVERBOSE("length");
goto fail;
}
/* BOLT #1:
* - if `length` exceeds the number of bytes remaining in the
* message:
* - MUST fail to parse the `tlv_stream`.
*/
if (field.length > *max) {
SUPERVERBOSE("value");
goto fail;
}
field.value = tal_dup_arr(record, u8, *cursor, field.length, 0);
/* BOLT #1:
* - if `type` is known:
* - MUST decode the next `length` bytes using the known
* encoding for `type`.
*/
field.meta = NULL;
2019-11-26 16:05:45 +01:00
for (size_t i = 0; i < num_types; i++) {
if (types[i].type == field.numtype)
field.meta = &types[i];
}
2019-11-18 19:52:20 +01:00
if (field.meta) {
/* Length of message can't exceed 16 bits anyway. */
size_t tlvlen = field.length;
field.meta->fromwire(cursor, &tlvlen, record);
if (!*cursor)
goto fail;
/* BOLT #1:
* - if `length` is not exactly equal to that required
* for the known encoding for `type`:
* - MUST fail to parse the `tlv_stream`.
*/
if (tlvlen != 0) {
SUPERVERBOSE("greater than encoding length");
goto fail;
}
} else {
/* We didn't read from *cursor through a fromwire, so
* update manually. */
*cursor += field.length;
}
/* We've read bytes in ->fromwire, so update max */
*max -= field.length;
tal_arr_expand(&record->fields, field);
}
return true;
fail:
fromwire_fail(cursor, max);
return false;
}
2019-11-18 20:02:55 +01:00
2019-11-25 22:46:55 +01:00
bool ${tlv.name}_is_valid(const struct ${tlv.struct_name()} *record, size_t *err_index)
2019-11-18 20:02:55 +01:00
{
size_t numfields = tal_count(record->fields);
bool first = true;
u64 prev_type = 0;
for (int i=0; i<numfields; i++) {
struct tlv_field *f = &record->fields[i];
if (f->numtype % 2 == 0 && f->meta == NULL) {
/* BOLT #1:
* - otherwise, if `type` is unknown:
* - if `type` is even:
* - MUST fail to parse the `tlv_stream`.
* - otherwise, if `type` is odd:
* - MUST discard the next `length` bytes.
*/
2019-11-25 22:46:55 +01:00
SUPERVERBOSE("unknown even");
if (err_index != NULL)
*err_index = i;
return false;
2019-11-18 20:02:55 +01:00
} else if (!first && f->numtype <= prev_type) {
/* BOLT #1:
2020-09-09 07:48:21 +02:00
* - if decoded `type`s are not strictly-increasing
* (including situations when two or more occurrences
* of the same `type` are met):
2019-11-18 20:02:55 +01:00
* - MUST fail to parse the `tlv_stream`.
*/
if (f->numtype == prev_type)
SUPERVERBOSE("duplicate tlv type");
else
SUPERVERBOSE("invalid ordering");
2019-11-25 22:46:55 +01:00
if (err_index != NULL)
*err_index = i;
return false;
2019-11-18 20:02:55 +01:00
}
first = false;
prev_type = f->numtype;
}
2019-11-25 22:46:55 +01:00
return true;
2019-11-18 20:02:55 +01:00
}
2019-07-20 01:21:25 +02:00
% endfor ## END TLV's
% for msg in messages: ## START Wire Messages
2019-07-19 18:54:39 +02:00
2019-09-20 19:49:45 +02:00
% if msg.if_token:
#if ${msg.if_token}
% endif
2019-07-15 02:10:01 +02:00
/* WIRE: ${msg.name.upper()} */
2019-07-18 00:26:21 +02:00
% for c in msg.msg_comments:
2019-07-23 21:18:43 +02:00
/*${c} */
2019-07-18 00:26:21 +02:00
% endfor
2019-07-19 18:56:39 +02:00
u8 *towire_${msg.name}(const tal_t *ctx${''.join([f.arg_desc_to() for f in msg.fields.values()])})
2019-07-15 02:10:01 +02:00
{
## 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():
2019-07-18 00:26:21 +02:00
% for c in f.field_comments:
2019-07-23 21:18:43 +02:00
/*${c} */
2019-07-18 00:26:21 +02:00
% endfor
2019-07-19 18:54:39 +02:00
% if f.is_array() or f.is_varlen():
2019-07-15 02:10:01 +02:00
% if f.type_obj.has_array_helper():
2019-07-28 02:52:43 +02:00
towire_${f.type_obj.name}_array(&p, ${f.name}, ${f.size('tal_count(' + f.name + ')')});
2019-07-15 02:10:01 +02:00
% else:
2019-07-28 02:52:43 +02:00
for (size_t i = 0; i < ${f.size('tal_count(' + f.name + ')')}; i++)
2019-07-19 18:54:39 +02:00
% if f.type_obj.is_assignable() or f.type_obj.is_varsize():
2019-07-15 02:10:01 +02:00
towire_${f.type_obj.name}(&p, ${f.name}[i]);
% else:
towire_${f.type_obj.name}(&p, ${f.name} + i);
% endif
% endif
2019-07-20 01:21:25 +02:00
% elif f.type_obj.is_tlv():
2019-11-27 16:07:59 +01:00
towire_${f.type_obj.tlv.name}(&p, ${f.name});
2019-07-15 02:10:01 +02:00
% 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));
}
2019-07-19 18:54:39 +02:00
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()])})
2019-07-15 02:10:01 +02:00
{
% 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()
2019-07-19 18:54:39 +02:00
if f.type_obj.is_varsize():
2019-07-15 02:10:01 +02:00
typename = typename + ' *'
type_ = f.type_obj.name
2019-07-19 18:54:39 +02:00
varsized = f.type_obj.is_varsize()
2019-07-15 02:10:01 +02:00
%> \
2019-07-18 00:26:21 +02:00
% for c in f.field_comments:
2019-07-23 21:18:43 +02:00
/*${c} */
2019-07-18 00:26:21 +02:00
% endfor
2019-07-19 18:54:39 +02:00
% if f.is_varlen():
2019-07-15 02:10:01 +02:00
// 2nd case ${f.name}
2019-07-28 02:52:43 +02:00
*${f.name} = ${f.size('plen')} ? tal_arr(ctx, ${typename}, ${f.size('plen')}) : NULL;
2019-07-15 02:10:01 +02:00
% endif
% if f.len_field_of:
${f.name} = fromwire_${type_}(&cursor, &plen);
2019-07-20 01:21:25 +02:00
% elif f.type_obj.is_tlv():
2019-11-25 23:30:10 +01:00
fromwire_${f.type_obj.tlv.name}(&cursor, &plen, ${f.name});
2019-07-19 18:54:39 +02:00
% elif f.is_array() or f.is_varlen():
2019-07-15 02:10:01 +02:00
% if f.type_obj.has_array_helper():
2019-07-28 02:52:43 +02:00
fromwire_${type_}_array(&cursor, &plen, ${'*' if f.is_varlen() else ''}${f.name}, ${f.size('plen')});
2019-07-15 02:10:01 +02:00
% else:
2019-07-28 02:52:43 +02:00
% if f.is_implicit_len():
for (size_t i = 0; plen != 0; i++)
% else:
2019-07-15 02:10:01 +02:00
for (size_t i = 0; i < ${f.size()}; i++)
2019-07-28 02:52:43 +02:00
% endif
2019-07-19 18:54:39 +02:00
% 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
2019-07-15 02:10:01 +02:00
% else:
2019-07-19 18:54:39 +02:00
(${'' if f.type_obj.is_assignable() and f.is_array() else '*'}${f.name})[i] = fromwire_${type_}(${'*'+f.name+', ' if varsized else ''}&cursor, &plen);
2019-07-15 02:10:01 +02:00
% endif
% endif
% else:
2019-07-19 18:54:39 +02:00
% 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
2019-07-24 01:39:42 +02:00
${'*' if f.type_obj.is_assignable() else ''}${fromwire_phrase(f, type_, varsized)}\
2019-07-19 18:54:39 +02:00
}
% endif ## End optional
2019-07-15 02:10:01 +02:00
% endif
% endfor
return cursor != NULL;
}
2019-09-20 19:49:45 +02:00
% if msg.if_token:
#endif /* ${msg.if_token} */
% endif
2019-07-20 01:21:25 +02:00
% endfor ## END Wire Messages