On Thu, Nov 11, 2010 at 11:16 PM, Kevin Bowling <kevin.bowl...@kev009.com> wrote: > > > On Thu, Nov 11, 2010 at 9:00 PM, Nick Mathewson <ni...@freehaven.net> wrote: >> >> On Thu, Nov 11, 2010 at 10:42 PM, Kevin Bowling >> <kevin.bowl...@kev009.com> 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 majord...@freehaven.net with unsubscribe libevent-users in the body.