summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Provos <provos@gmail.com>2008-06-21 02:21:25 +0000
committerNiels Provos <provos@gmail.com>2008-06-21 02:21:25 +0000
commit99a1063e735f70443268b50d14f042c87cb9b99a (patch)
tree2789eb33ecbbb259c280e9c290f183b31ba40d72
parent4c56ba1cede32ba30624208e8e84672531e644e3 (diff)
downloadlibevent-99a1063e735f70443268b50d14f042c87cb9b99a.tar.gz
support 64-bit integers in rpc structs
svn:r856
-rw-r--r--ChangeLog2
-rwxr-xr-xevent_rpcgen.py32
-rw-r--r--event_tagging.c167
-rw-r--r--include/event2/tag.h5
-rw-r--r--test/regress.c25
-rw-r--r--test/regress.rpc3
6 files changed, 171 insertions, 63 deletions
diff --git a/ChangeLog b/ChangeLog
index ad93ea33..682839f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/event_rpcgen.py b/event_rpcgen.py
index ea480a25..b3770830 100755
--- a/event_rpcgen.py
+++ b/event_rpcgen.py
@@ -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)
diff --git a/event_tagging.c b/event_tagging.c
index 62fc4b22..4a39ea2c 100644
--- a/event_tagging.c
+++ b/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;
-
- 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);
+ ENCODE_INT_INTERNAL(data, number);
+}
- 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.
@@ -229,6 +247,18 @@ 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)
+{
+ 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)
{
evtag_marshal(buf, tag, string, strlen(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;
-
- 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;
+ DECODE_INT_INTERNAL(number, 8, pnumber, evbuf, offset);
+}
- 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
diff --git a/include/event2/tag.h b/include/event2/tag.h
index 0d0d8ca1..3f166e79 100644
--- a/include/event2/tag.h
+++ b/include/event2/tag.h
@@ -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);
diff --git a/test/regress.c b/test/regress.c
index 063fb1b9..d267a7ac 100644
--- a/test/regress.c
+++ b/test/regress.c
@@ -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");
diff --git a/test/regress.rpc b/test/regress.rpc
index f8a4b1c1..c0170a78 100644
--- a/test/regress.rpc
+++ b/test/regress.rpc
@@ -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;
}