[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[Libevent-users] out-of-order writes in an evbuffer



I have a problem that should be fairly common for app-level protocol implementations over libevent. I need to send a stream of messages of different types and sizes over a TCP connection managed by a bufferevent. The format of each message on the wire is <length><type><body>, where <length> is a 4-byte length of the message, <type> is a single-byte message type, <body> is the rest of the message. Every message object in my code knows how to serialize itself into an evbuffer, calculating and returning the length of serialized content in the process. However, the length of the message must appear in the evbuffer *before* the body of message. What’s the recommended way to do this with libevent 2.1?

 

I do not want to require every message object to have a function that returns <length> for that message, in addition to the serialization function. This will increase code complexity, and will somewhat reduce its efficiency, since for complex payloads calculating <length> may take about as much CPU as actually serializing the message. So far I looked at the following options:

 

1) evbuffer_reserve_space()/evbuffer_commit_space() looked promising, but the docs say appending data to evbuffer may invalidate the pointers I get back. Is it true even if I pass an iovec of size 1?

2) evbuffer_add_reference() will allocate a new chain, which seems too expensive for reserving 5 bytes on the critical path

3) serializing <body> into a separate evbuffer, then adding it to the bufferevent’s output buffer by reference also looks expensive for 5 bytes

 

Ideally, what I need is evbuffer_[reserve/commit]_space() that gives me a pointer to a small (5-bytes) reserved segment of evbuffer, which will remain valid after one or more subsequent calls  to evbuffer_add() that will compose the body of message.

 

-Mark