Yes! Thank you so much! For future reference I'm posting in my modified
code, and I can verify that this at least works on the primitive example
server.
void readcb(struct bufferevent *bev, void *ptr)
{
struct evbuffer *input = bufferevent_get_input(bev);
char *request_line;
size_t len;
while ( NULL != (request_line = evbuffer_readln( input, &len,
EVBUFFER_EOL_CRLF ))){
printf("<line>%s</line>\n", request_line ); fflush( stdout );
free( request_line );
}
}
int main(int argc, char **argv)
{
/* ... */
bufferevent_setcb(bev, readcb, NULL, NULL, base);
/* ... */
}
Thanks a lot....
-Ø
On Tue, Feb 2, 2016 at 3:13 PM, Azat Khuzhin <[email protected]> wrote:
> On Tue, Feb 2, 2016 at 4:32 PM, Øystein Schønning-Johansen
> <[email protected]> wrote:
> > It is probably a misconception on my side. I'm pretty good at
> > misconceptions. :-)
> >
> > To illustrate, I set up a really naive server in python:
> >>>> import socket
> >>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> >>>> s.bind(('', 8888))
> >>>> s.listen(10)
> >>>> while 1:
> > ... conn, addr = s.accept()
> > ... conn.send(b"Line 1\nLine 2\nLine 3\nLast line\n")
> > ... conn.close()
>
> I use this:
> $ nc -lp 8888 <<<$'line 1\nline 2'
>
> > OK, then I code a simple client. (There are som short-cuts to avoid a
> lot of
> > code, but this compiles and runs with -std=gnu99)
> >
> > #include <event2/dns.h>
> > #include <event2/bufferevent.h>
> > #include <event2/buffer.h>
> > #include <event2/util.h>
> > #include <event2/event.h>
> >
> > #include <stdlib.h>
> > #include <stdio.h>
> >
> > void buffercb(struct evbuffer *input, const struct evbuffer_cb_info
> *info,
> > void *ptr)
> > {
> > #if 1
> > char *request_line;
> > size_t len;
> >
> > request_line = evbuffer_readln( input, &len, EVBUFFER_EOL_CRLF );
>
> Gotcha, buffercb() is a readcb of evbuffer, IOW it is invoked *every
> time* you read from/to this *evbuffer*, see?
> IOW when libevent calls buffercb(), buffercb() will call
> evbuffer_readln(), and evbuffer_readln() also will call buffercb(),
> and because of this recursion you have latest-first behavior.
>
> > if ( request_line ){
> > printf("%s\n", request_line ); fflush( stdout );
> > free( request_line );
> > }
> > }
> >
> > int main(int argc, char **argv)
> > {
> > struct event_base *base;
> > struct evdns_base *dns_base;
> > struct bufferevent *bev;
> >
> > if( argc != 3 ){
> > printf("Usage: %s host port", argv[0]);
> > return -1;
> > }
> >
> > base = event_base_new();
> > dns_base = evdns_base_new(base, 1);
> >
> > bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
> > bufferevent_setcb(bev, NULL, NULL, NULL, base);
> > bufferevent_enable(bev, EV_READ|EV_WRITE);
> > bufferevent_socket_connect_hostname(
> > bev, dns_base, AF_UNSPEC, argv[1], atoi(argv[2]));
> >
> > evbuffer_add_cb( bufferevent_get_input(bev), buffercb, NULL );
>
> That's why it is better to use "readcb" over bufferevent that
> installed via bufferevent_setcb() instead of callbacks over evbuffer.
>
> Of course you can remove that callback in buffercb(), and translate
> that evbuffer_readln() into loop, but this is not how things should
> work.
>
> >
> > event_base_dispatch(base);
> > return 0;
> > }
> ***********************************************************************
> To unsubscribe, send an e-mail to [email protected] with
> unsubscribe libevent-users in the body.
>