1 #include "config.h"
2 #include <assert.h>
3 #include <common/bigsize.h>
4 #include <wire/wire.h>
5
6 #ifndef SUPERVERBOSE
7 #define SUPERVERBOSE(...)
8 #endif
9
bigsize_len(bigsize_t v)10 size_t bigsize_len(bigsize_t v)
11 {
12 if (v < 0xfd) {
13 return 1;
14 } else if (v <= 0xffff) {
15 return 3;
16 } else if (v <= 0xffffffff) {
17 return 5;
18 } else {
19 return 9;
20 }
21 }
22
bigsize_put(u8 buf[BIGSIZE_MAX_LEN],bigsize_t v)23 size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN], bigsize_t v)
24 {
25 u8 *p = buf;
26
27 if (v < 0xfd) {
28 *(p++) = v;
29 } else if (v <= 0xffff) {
30 (*p++) = 0xfd;
31 (*p++) = v >> 8;
32 (*p++) = v;
33 } else if (v <= 0xffffffff) {
34 (*p++) = 0xfe;
35 (*p++) = v >> 24;
36 (*p++) = v >> 16;
37 (*p++) = v >> 8;
38 (*p++) = v;
39 } else {
40 (*p++) = 0xff;
41 (*p++) = v >> 56;
42 (*p++) = v >> 48;
43 (*p++) = v >> 40;
44 (*p++) = v >> 32;
45 (*p++) = v >> 24;
46 (*p++) = v >> 16;
47 (*p++) = v >> 8;
48 (*p++) = v;
49 }
50 return p - buf;
51 }
52
bigsize_get(const u8 * p,size_t max,bigsize_t * val)53 size_t bigsize_get(const u8 *p, size_t max, bigsize_t *val)
54 {
55 if (max < 1) {
56 SUPERVERBOSE("EOF");
57 return 0;
58 }
59
60 switch (*p) {
61 case 0xfd:
62 if (max < 3) {
63 SUPERVERBOSE("unexpected EOF");
64 return 0;
65 }
66 *val = ((u64)p[1] << 8) + p[2];
67 if (*val < 0xfd) {
68 SUPERVERBOSE("decoded bigsize is not canonical");
69 return 0;
70 }
71 return 3;
72 case 0xfe:
73 if (max < 5) {
74 SUPERVERBOSE("unexpected EOF");
75 return 0;
76 }
77 *val = ((u64)p[1] << 24) + ((u64)p[2] << 16)
78 + ((u64)p[3] << 8) + p[4];
79 if ((*val >> 16) == 0) {
80 SUPERVERBOSE("decoded bigsize is not canonical");
81 return 0;
82 }
83 return 5;
84 case 0xff:
85 if (max < 9) {
86 SUPERVERBOSE("unexpected EOF");
87 return 0;
88 }
89 *val = ((u64)p[1] << 56) + ((u64)p[2] << 48)
90 + ((u64)p[3] << 40) + ((u64)p[4] << 32)
91 + ((u64)p[5] << 24) + ((u64)p[6] << 16)
92 + ((u64)p[7] << 8) + p[8];
93 if ((*val >> 32) == 0) {
94 SUPERVERBOSE("decoded bigsize is not canonical");
95 return 0;
96 }
97 return 9;
98 default:
99 *val = *p;
100 return 1;
101 }
102 }
103
fromwire_bigsize(const u8 ** cursor,size_t * max)104 bigsize_t fromwire_bigsize(const u8 **cursor, size_t *max)
105 {
106 bigsize_t v;
107 size_t len = bigsize_get(*cursor, *max, &v);
108
109 if (len == 0) {
110 fromwire_fail(cursor, max);
111 return 0;
112 }
113 assert(len <= *max);
114 fromwire(cursor, max, NULL, len);
115 return v;
116 }
117
towire_bigsize(u8 ** pptr,const bigsize_t val)118 void towire_bigsize(u8 **pptr, const bigsize_t val)
119 {
120 u8 buf[BIGSIZE_MAX_LEN];
121 size_t len;
122
123 len = bigsize_put(buf, val);
124 towire(pptr, buf, len);
125 }
126