[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [Libevent-users] Using evbuffer_peek
On Thu, Nov 11, 2010 at 11:16 PM, Kevin Bowling
<kevin.bowling@xxxxxxxxxx> wrote:
>
>
> On Thu, Nov 11, 2010 at 9:00 PM, Nick Mathewson <nickm@xxxxxxxxxxxxx> wrote:
>>
>> On Thu, Nov 11, 2010 at 10:42 PM, Kevin Bowling
>> <kevin.bowling@xxxxxxxxxx> wrote:
>> > Hi,
>> >
>> > I've seen a few mails talking about evbuffer_peek, but no solid usage of
>> > it. The doxygen on the libevent page doesn't cover it generating my own
>> > from 2.0.8 has shed little light on its use to me.
>>
>> Ugly? You bet! evbuffer_peek is really only optimized for the case
>> where you do not want to take any performance hit for copying data out
>> of the evbuffer, and you're willing to make your code more complex
>> because of it. Instead, I'd suggest evbuffer_copyout(), which is way
>> easier for what you seem to be doing:
>>
>> uint8_t tmp[3];
>> if (evbuffer_copyout(input, tmp, 3) < 3)
>> return -1;
>> ulen = (tmp[1]<<8) | tmp[2];
>>
>
> Hi Nick,
>
> I've got it working with the copyout method and that works great for this
> simple case. The one thing that wories me is that there are other variable
> length packets with internal length headers after a larger number of bytes.
> Is there any way to offset with copyout, or would it be better to serialize
> and use a pointer or use peek with vectors?
Hm. There isn't a copyout variant that takes an offset. It would be
cool to add one in Libevent 2.1 [*], but for now, 2.0 is in
feature-freeze.
If you need to extract small fields that are very very far into the
buffer, you could write a helper like this:
int
my_evbuffer_copyout_from(struct evbuffer *b, void *buf,
size_t len, struct evbuffer_ptr *ptr)
{
/* FIXME locking is left as an exercise for the reader */
/* FIXME This is totally untested. I'm not even sure if it compiles */
struct evbuffer_iovec *v;
int nvecs, i;
char *cp = buf;
if (!ptr)
return evbuffer_copyout(b, buf, len);
if (evbuffer_get_length(b) < ptr->pos + len)
return -1; /* not enough data */
if (ptr->pos + len < 128) {
/* XXX Not sure if this optimization helps */
char tmp[128];
evbuffer_copyout(b, tmp, ptr->pos + len);
memcpy(buf, tmp+ptr->pos, len);
return 0;
}
/* determine how many vecs we need */
nvecs = evbuffer_peek(b, len, ptr, NULL, 0);
if (nvecs < 1)
return -1;
v = calloc(sizeof(struct evbuffer_iovec), nvecs);
if (v == NULL)
return -1;
if (evbuffer_peek(b, len, ptr, v, nvecs) < 0) {
free(v);
return -1; /* should be impossible, but let's take no chances */
}
for (i = 0; i < nvecs; ++i) {
if (v[i].iov_len <= len) {
memcpy(cp, v[i].iov_base, v[i].iov_len);
cp += v[i].iov_len;
len -= v[i].iov_len;
} else {
memcpy(cp, v[i].iov_base, len);
break;
}
}
free(v);
return 0;
}
[*] If somebody adds a ticket to the "feature requests" tracker at
https://sourceforge.net/tracker/?group_id=50884&atid=461325
--
Nick
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users in the body.