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

Re: [Libevent-users] how to consume partial buffer in bufferevent filter callback



On Tue, Feb 8, 2011 at 2:16 PM, Wayne Shao <wshao99@xxxxxxxxx> wrote:
> Hi,
> I am using a filter to read packets from the peer. The packet format is
> typical header + payload, where total length is encoded in the header.
> In the filter callback, is it possible to only consume part of the source
> buffer?
> e.g, if my protocol packet size is 100 bytes but the source buffer has 130
> bytes, I'd like to read
> the whole packet and leave the remaining and hope to process that in the
> next callback.
> I do not want to copy the whole thing and manage it from a separate buffer.
> Is this possible?

Sure.  You can consume as much or as little data as you like.  If
you're consuming fixed-size 100-byte packets, I'd do it something
like:

   const int PACKET_SIZE = 100;
   while (evbuffer_get_length(source) >= PACKET_SIZE) {
      char packet[PACKET_SIZE];
      evbuffer_remove(input, packet, PACKET_SIZE);
      /* handle packet here */
   }

Or if it's like the situation you describe -- say, you get an 8-byte
header where the first four bytes are the length of the packet body --
I'd do something like this:

   const int HEADER_SIZE = 8;
   while (evbuffer_get_length(source) >= HEADER_SIZE) {
     uint32_t bodylen;
     char header[HEADER_SIZE];
     char *body;
     /* Fetch the header without draining the buffer */
     evbuffer_copyout(source, HEADER, HEADER_SIZE);
     memcpy(bodylen, header, 4);
     bodylen = ntohl(bodylen);
     if (evbuffer_get_length(source) < HEADER_SIZE + bodylen) {
       /* the packet isn't here yet. */
       return BEV_NEED_MORE;
     }
     body = malloc(bodylen);
     if (!body) { /* handle OOM */ }
     /* remove the header from the front of the buffer */
     evbuffer_drain(source, HEADER_SIZE);
     /* Get the body of the packet */
     evbuffer_remove(source, body, bodylen);
     /* Handle the packet here */
   }

One catch is that you only get invoked when there is new data to
filter.  If there are 130 bytes on the buffer, and you handle 100 of
them, you don't get another chance to handle the remaining 30 bytes
until more bytes arrive for you to handle.   So generally, the best
approach for a filter function is to greedily process as much data as
you can.


-- 
Nick
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.