mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-12 05:48:51 -04:00
support 64-bit integers in rpc structs
svn:r856
This commit is contained in:
parent
4c56ba1ced
commit
99a1063e73
@ -110,7 +110,7 @@ Changes in current version:
|
||||
o allow min_heap_erase to be called on removed members; from liusifan.
|
||||
o Rename INPUT and OUTPUT to EVRPC_INPUT and EVRPC_OUTPUT. Retain INPUT/OUTPUT aliases on on-win32 platforms for backwards compatibility.
|
||||
o Do not use SO_REUSEADDR when connecting
|
||||
|
||||
o Support 64-bit integers in RPC structs
|
||||
|
||||
Changes in 1.4.0:
|
||||
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
||||
|
@ -575,12 +575,17 @@ class EntryBytes(Entry):
|
||||
Entry.Verify(self)
|
||||
|
||||
class EntryInt(Entry):
|
||||
def __init__(self, type, name, tag):
|
||||
def __init__(self, type, name, tag, bits=32):
|
||||
# Init base class
|
||||
Entry.__init__(self, type, name, tag)
|
||||
|
||||
self._can_be_array = 1
|
||||
self._ctype = 'ev_uint32_t'
|
||||
if bits == 32:
|
||||
self._ctype = 'ev_uint32_t'
|
||||
self._marshal_type = 'int'
|
||||
if bits == 64:
|
||||
self._ctype = 'ev_uint64_t'
|
||||
self._marshal_type = 'int64'
|
||||
|
||||
def GetInitializer(self):
|
||||
return "0"
|
||||
@ -598,23 +603,26 @@ class EntryInt(Entry):
|
||||
'value' : value } ]
|
||||
|
||||
def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
|
||||
code = ['if (evtag_unmarshal_int(%(buf)s, %(tag)s, &%(var)s) == -1) {',
|
||||
' event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
|
||||
' return (-1);',
|
||||
'}' ]
|
||||
code = [
|
||||
'if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {',
|
||||
' event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
|
||||
' return (-1);',
|
||||
'}' ]
|
||||
code = '\n'.join(code) % self.GetTranslation({
|
||||
'ma' : self._marshal_type,
|
||||
'buf' : buf,
|
||||
'tag' : tag_name,
|
||||
'var' : var_name })
|
||||
return code.split('\n')
|
||||
|
||||
def CodeMarshal(self, buf, tag_name, var_name, var_len):
|
||||
code = ['evtag_marshal_int(%s, %s, %s);' % (
|
||||
buf, tag_name, var_name)]
|
||||
code = [
|
||||
'evtag_marshal_%s(%s, %s, %s);' % (
|
||||
self._marshal_type, buf, tag_name, var_name)]
|
||||
return code
|
||||
|
||||
def Declaration(self):
|
||||
dcl = ['ev_uint32_t %s_data;' % self._name]
|
||||
dcl = ['%s %s_data;' % (self._ctype, self._name)]
|
||||
|
||||
return dcl
|
||||
|
||||
@ -1338,6 +1346,8 @@ def ProcessOneEntry(factory, newstruct, entry):
|
||||
newentry = factory.EntryVarBytes(entry_type, name, tag)
|
||||
elif entry_type == 'int' and not fixed_length:
|
||||
newentry = factory.EntryInt(entry_type, name, tag)
|
||||
elif entry_type == 'int64' and not fixed_length:
|
||||
newentry = factory.EntryInt(entry_type, name, tag, bits=64)
|
||||
elif entry_type == 'string' and not fixed_length:
|
||||
newentry = factory.EntryString(entry_type, name, tag)
|
||||
else:
|
||||
@ -1593,8 +1603,8 @@ class CCodeGenerator:
|
||||
def EntryVarBytes(self, entry_type, name, tag):
|
||||
return EntryVarBytes(entry_type, name, tag)
|
||||
|
||||
def EntryInt(self, entry_type, name, tag):
|
||||
return EntryInt(entry_type, name, tag)
|
||||
def EntryInt(self, entry_type, name, tag, bits=32):
|
||||
return EntryInt(entry_type, name, tag, bits)
|
||||
|
||||
def EntryString(self, entry_type, name, tag):
|
||||
return EntryString(entry_type, name, tag)
|
||||
|
167
event_tagging.c
167
event_tagging.c
@ -87,29 +87,39 @@ evtag_init(void)
|
||||
* @return the number of bytes written into data.
|
||||
*/
|
||||
|
||||
#define ENCODE_INT_INTERNAL(data, number) do { \
|
||||
int off = 1, nibbles = 0; \
|
||||
\
|
||||
memset(data, 0, sizeof(number)+1); \
|
||||
while (number) { \
|
||||
if (off & 0x1) \
|
||||
data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); \
|
||||
else \
|
||||
data[off/2] = (data[off/2] & 0x0f) | \
|
||||
((number & 0x0f) << 4); \
|
||||
number >>= 4; \
|
||||
off++; \
|
||||
} \
|
||||
\
|
||||
if (off > 2) \
|
||||
nibbles = off - 2; \
|
||||
\
|
||||
/* Off - 1 is the number of encoded nibbles */ \
|
||||
data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); \
|
||||
\
|
||||
return ((off + 1) / 2); \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
encode_int_internal(ev_uint8_t *data, ev_uint32_t number)
|
||||
{
|
||||
int off = 1, nibbles = 0;
|
||||
ENCODE_INT_INTERNAL(data, number);
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(ev_uint32_t)+1);
|
||||
while (number) {
|
||||
if (off & 0x1)
|
||||
data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f);
|
||||
else
|
||||
data[off/2] = (data[off/2] & 0x0f) |
|
||||
((number & 0x0f) << 4);
|
||||
number >>= 4;
|
||||
off++;
|
||||
}
|
||||
|
||||
if (off > 2)
|
||||
nibbles = off - 2;
|
||||
|
||||
/* Off - 1 is the number of encoded nibbles */
|
||||
data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);
|
||||
|
||||
return ((off + 1) / 2);
|
||||
static inline int
|
||||
encode_int64_internal(ev_uint8_t *data, ev_uint64_t number)
|
||||
{
|
||||
ENCODE_INT_INTERNAL(data, number);
|
||||
}
|
||||
|
||||
void
|
||||
@ -120,6 +130,14 @@ encode_int(struct evbuffer *evbuf, ev_uint32_t number)
|
||||
evbuffer_add(evbuf, data, len);
|
||||
}
|
||||
|
||||
void
|
||||
encode_int64(struct evbuffer *evbuf, ev_uint64_t number)
|
||||
{
|
||||
ev_uint8_t data[9];
|
||||
int len = encode_int64_internal(data, number);
|
||||
evbuffer_add(evbuf, data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support variable length encoding of tags; we use the high bit in each
|
||||
* octet as a continuation signal.
|
||||
@ -228,6 +246,18 @@ evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
|
||||
evbuffer_add(evbuf, data, len);
|
||||
}
|
||||
|
||||
void
|
||||
evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
ev_uint64_t integer)
|
||||
{
|
||||
ev_uint8_t data[9];
|
||||
int len = encode_int64_internal(data, integer);
|
||||
|
||||
evtag_encode_tag(evbuf, tag);
|
||||
encode_int(evbuf, len);
|
||||
evbuffer_add(evbuf, data, len);
|
||||
}
|
||||
|
||||
void
|
||||
evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
|
||||
{
|
||||
@ -243,6 +273,39 @@ evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *t
|
||||
evtag_marshal(evbuf, tag, data, len);
|
||||
}
|
||||
|
||||
#define DECODE_INT_INTERNAL(number, maxnibbles, pnumber, evbuf, offset) \
|
||||
do { \
|
||||
ev_uint8_t *data; \
|
||||
int len = EVBUFFER_LENGTH(evbuf) - offset; \
|
||||
int nibbles = 0; \
|
||||
\
|
||||
if (len <= 0) \
|
||||
return (-1); \
|
||||
\
|
||||
/* XXX(niels): faster? */ \
|
||||
data = evbuffer_pullup(evbuf, offset + 1) + offset; \
|
||||
\
|
||||
nibbles = ((data[0] & 0xf0) >> 4) + 1; \
|
||||
if (nibbles > maxnibbles || (nibbles >> 1) + 1 > len) \
|
||||
return (-1); \
|
||||
len = (nibbles >> 1) + 1; \
|
||||
\
|
||||
data = evbuffer_pullup(evbuf, offset + len) + offset; \
|
||||
\
|
||||
while (nibbles > 0) { \
|
||||
number <<= 4; \
|
||||
if (nibbles & 0x1) \
|
||||
number |= data[nibbles >> 1] & 0x0f; \
|
||||
else \
|
||||
number |= (data[nibbles >> 1] & 0xf0) >> 4; \
|
||||
nibbles--; \
|
||||
} \
|
||||
\
|
||||
*pnumber = number; \
|
||||
\
|
||||
return (len); \
|
||||
} while (0)
|
||||
|
||||
/* Internal: decode an integer from an evbuffer, without draining it.
|
||||
* Only integers up to 32-bits are supported.
|
||||
*
|
||||
@ -251,39 +314,19 @@ evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *t
|
||||
* @param pnumber a pointer to receive the integer.
|
||||
* @return The length of the number as encoded, or -1 on error.
|
||||
*/
|
||||
|
||||
static int
|
||||
decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int offset)
|
||||
{
|
||||
ev_uint32_t number = 0;
|
||||
ev_uint8_t *data;
|
||||
int len = EVBUFFER_LENGTH(evbuf) - offset;
|
||||
int nibbles = 0;
|
||||
DECODE_INT_INTERNAL(number, 8, pnumber, evbuf, offset);
|
||||
}
|
||||
|
||||
if (len <= 0)
|
||||
return (-1);
|
||||
|
||||
/* XXX(niels): faster? */
|
||||
data = evbuffer_pullup(evbuf, offset + 1) + offset;
|
||||
|
||||
nibbles = ((data[0] & 0xf0) >> 4) + 1;
|
||||
if (nibbles > 8 || (nibbles >> 1) + 1 > len)
|
||||
return (-1);
|
||||
len = (nibbles >> 1) + 1;
|
||||
|
||||
data = evbuffer_pullup(evbuf, offset + len) + offset;
|
||||
|
||||
while (nibbles > 0) {
|
||||
number <<= 4;
|
||||
if (nibbles & 0x1)
|
||||
number |= data[nibbles >> 1] & 0x0f;
|
||||
else
|
||||
number |= (data[nibbles >> 1] & 0xf0) >> 4;
|
||||
nibbles--;
|
||||
}
|
||||
|
||||
*pnumber = number;
|
||||
|
||||
return (len);
|
||||
static int
|
||||
decode_int64_internal(ev_uint64_t *pnumber, struct evbuffer *evbuf, int offset)
|
||||
{
|
||||
ev_uint64_t number = 0;
|
||||
DECODE_INT_INTERNAL(number, 16, pnumber, evbuf, offset);
|
||||
}
|
||||
|
||||
int
|
||||
@ -391,16 +434,14 @@ evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
ev_uint32_t len;
|
||||
ev_uint32_t integer;
|
||||
int result;
|
||||
|
||||
if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
|
||||
return (-1);
|
||||
if (need_tag != tag)
|
||||
return (-1);
|
||||
if (evtag_decode_int(&integer, evbuf) == -1)
|
||||
if (evtag_decode_int(&len, evbuf) == -1)
|
||||
return (-1);
|
||||
len = integer;
|
||||
|
||||
if (EVBUFFER_LENGTH(evbuf) < len)
|
||||
return (-1);
|
||||
@ -413,6 +454,32 @@ evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
ev_uint64_t *pinteger)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
ev_uint32_t len;
|
||||
int result;
|
||||
|
||||
if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
|
||||
return (-1);
|
||||
if (need_tag != tag)
|
||||
return (-1);
|
||||
if (evtag_decode_int(&len, evbuf) == -1)
|
||||
return (-1);
|
||||
|
||||
if (EVBUFFER_LENGTH(evbuf) < len)
|
||||
return (-1);
|
||||
|
||||
result = decode_int64_internal(pinteger, evbuf, 0);
|
||||
evbuffer_drain(evbuf, len);
|
||||
if (result < 0 || result > len) /* XXX Should this be != rather than > ?*/
|
||||
return (-1);
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Unmarshal a fixed length tag */
|
||||
|
||||
int
|
||||
|
@ -89,9 +89,12 @@ void evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
@param number a 32-bit integer
|
||||
*/
|
||||
void encode_int(struct evbuffer *evbuf, ev_uint32_t number);
|
||||
void encode_int64(struct evbuffer *evbuf, ev_uint64_t number);
|
||||
|
||||
void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
ev_uint32_t integer);
|
||||
void evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
ev_uint64_t integer);
|
||||
|
||||
void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag,
|
||||
const char *string);
|
||||
@ -108,6 +111,8 @@ int evtag_consume(struct evbuffer *evbuf);
|
||||
|
||||
int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
ev_uint32_t *pinteger);
|
||||
int evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
ev_uint64_t *pinteger);
|
||||
|
||||
int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag,
|
||||
void *data, size_t len);
|
||||
|
@ -1947,6 +1947,10 @@ rpc_test(void)
|
||||
fprintf(stderr, "Failed to add note.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
EVTAG_ASSIGN(run, large_number, 0xdead0a0bcafebeefLL);
|
||||
EVTAG_ADD(run, other_numbers, 0xdead0a0b);
|
||||
EVTAG_ADD(run, other_numbers, 0xbeefcafe);
|
||||
}
|
||||
|
||||
if (msg_complete(msg) == -1) {
|
||||
@ -2002,6 +2006,8 @@ rpc_test(void)
|
||||
} else {
|
||||
/* verify the notes */
|
||||
char *note_one, *note_two;
|
||||
ev_uint64_t large_number;
|
||||
ev_uint32_t short_number;
|
||||
|
||||
if (EVTAG_LEN(run, notes) != 2) {
|
||||
fprintf(stderr, "Wrong number of note strings.\n");
|
||||
@ -2019,7 +2025,24 @@ rpc_test(void)
|
||||
fprintf(stderr, "Incorrect note strings encoded.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (EVTAG_GET(run, large_number, &large_number) == -1 ||
|
||||
large_number != 0xdead0a0bcafebeefLL) {
|
||||
fprintf(stderr, "Incorrrect large_number.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (EVTAG_LEN(run, other_numbers) != 2) {
|
||||
fprintf(stderr, "Wrong number of other_numbers.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (EVTAG_GET(run, other_numbers, 0, &short_number) == -1) {
|
||||
fprintf(stderr, "Could not get short number.\n");
|
||||
exit(1);
|
||||
}
|
||||
assert(short_number == 0xdead0a0b);
|
||||
|
||||
}
|
||||
if (EVTAG_LEN(attack, how_often) != 3) {
|
||||
fprintf(stderr, "Wrong number of how_often ints.\n");
|
||||
|
@ -19,4 +19,7 @@ struct run {
|
||||
|
||||
bytes fixed_bytes[24] = 3;
|
||||
array string notes = 4;
|
||||
|
||||
optional int64 large_number = 5;
|
||||
array int other_numbers = 6;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user