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

Re: [Libevent-users] Libevent, DBus, Netlink, peeking at packet lengths, etc.



On 16 August 2016 at 20:42, Philip Prindeville
<philipp_subx@xxxxxxxxxxxxxxxxxxxxx> wrote:
> Hi,
>
> I'm fairly new to using libevent, having done most of my event driven
> programming in C++ with either Boost or Perl, but needed to add multiple
> pending transaction support to a Tacacs+ proxy written in C so I decided to
> have a look at libevent.
>
> So far, it all seems pretty straightforward and I'm getting the hang of it.
>
> I did have a question about supporting other socket types besides the usual
> TCP or UDP transports.
>
> Is there a preferred way of supporting Netlink or DBus traffic? I ask
> because I'm thinking of a long-running daemon on a laptop that might need to
> get notifications about roaming onto different network types via Netlink,
> for instance.  I did see this library out there but wasn't sure how complete
> and tested it was:
>
> https://github.com/dex/dbus-service
>
> Also, in the case of handling a protocol with fixed-size records (like
> Tacacs+) running over TCP, is there a preferred way to read a
> packet-at-a-time?  Since it's TCP, you have no record boundaries (unlike UDP
> or TP-4), so you have to find the packet length inside the header.
>
> In my case, in my read callback, I'm doing this as:
>
>       evbuf = bufferevent_get_input(bev);
>
>       n = evbuffer_get_length(evbuf);
>

I've tended to use evbuffer_get_contiguous_space(), since that's the
largest amount of space you can read without buffer copying. Of
course, a TCP write() from your peer needn't end up as one read() at
your end, and hence might not yield contiguous space - so an
evbuffer_get_length() is a useful fallback if the contiguous space is
non-zero but too small for your header.

>       /* evbuffer_pullup() returns NULL if there aren't enough bytes in
>        * the buffer yet to pull-up as many as are requested.
>        */
>       start = evbuffer_pullup(evbuf, TAC_PLUS_HDR_SIZE);
>       if (! start)
>           return;
>
>       th = (HDR *)start;
>
>       /* should probably bcopy th->datalength to a word-aligned buffer
>        * first, in case we're on a platform which doesn't handle word
>        * fetches on unaligned addresses
>        */
>
>       length = ntohl(th->datalength) + TAC_PLUS_HDR_SIZE;
>
>       /* if we're short, we'll get called again when more data arrives
>        */
>       if (n < length)
>            return;
>
>       u_char *pkt = malloc(length);
>
>       /* copy out... */
>       i = evbuffer_remove(evbuf, pkt, length);
>
>       tac_parse_pkt(ctx->sess, ctx, pkt, length);
>
>       free(pkt);
> }
>
> But wondered if there's a better or prototypical way of handling this?
>
> Is it worth setting the socket low-water market to "length" so that we only
> get dispatched one more time if data trickles in?
>
> Also, is there any interest in adding 'profiling' support to the event
> handlers to see how long they run (in real-time, probably using
> gettimeofday()) and generating warnings in debug- (or development-) mode if
> they exceed an upper threshold (say 10ms execution time)?
>
> Thanks,
>
> -Philip
>
> ***********************************************************************
> To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
> unsubscribe libevent-users    in the body.
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.