Felix Nawothnig | 1 Jun 2010 05:07

How to close bufferevent connection?

Hey.

What's the "suggested" way to close a bufferevent connection?

Currently I do:

        fd = bufferevent_getfd(bev);
        evutil_closesocket(fd);

... followed by a manual:

        my_event_handler(bev, BEV_EVENT_EOF, NULL);

... because it doesn't seem to be called otherwise.

Is this the "correct" way? Is the fact that the event handler not called
a bug?

Cheers,

Felix

***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.

hcpark | 1 Jun 2010 05:24

RE: How to close bufferevent connection?

I used 
	bufferevent_free(bev);

-----Original Message-----
From: owner-libevent-users <at> freehaven.net [mailto:owner-libevent-users <at> freehaven.net] On Behalf
Of Felix Nawothnig
Sent: Tuesday, June 01, 2010 12:07 PM
To: libevent-users <at> freehaven.net
Subject: [Libevent-users] How to close bufferevent connection?

Hey.

What's the "suggested" way to close a bufferevent connection?

Currently I do:

        fd = bufferevent_getfd(bev);
        evutil_closesocket(fd);

... followed by a manual:

        my_event_handler(bev, BEV_EVENT_EOF, NULL);

... because it doesn't seem to be called otherwise.

Is this the "correct" way? Is the fact that the event handler not called
a bug?

Cheers,

(Continue reading)

Felix Nawothnig | 1 Jun 2010 07:52

RE: How to close bufferevent connection?

On Tue, 2010-06-01 at 12:24 +0900, hcpark wrote:
> I used 
> 	bufferevent_free(bev);

Right. Silly me.

Felix

***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.

Hor Meng Yoong | 1 Jun 2010 16:04
Picon

socket message boundary problem

Hi:

  I am using libevent2. Is that a wrapper function/library to send and
receive fixed length message, or variable length message with message
length embedded in the first 2 bytes with libevent2? Thank

Regards
Hor Meng
***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.

Zhuang Yuyao | 2 Jun 2010 13:01
Picon

Re: [HELP] How to safely free a defer callback bufferevent in readcb

I am trying to fix this problem but failed.

here is some more information:
1) this issue only happens while both defer callback and
bufferevent_openssl are used, otherwise, there is no such warning.
2) although most of the time, the warning is invoked,  but there is a
few time that the warning does not appear.
3) I add some debug code into epoll.c, function epoll_apply_changes()
(line 220 - 228)
    217     memset(&epev, 0, sizeof(epev));
    218     epev.data.fd = ch->fd;
    219     epev.events = events;
    220     printf("%s:%d %d\n", __FILE__, __LINE__, ch->fd);
    221     printf("Epoll %s on fd %d.  Old events were %d; read
change was %d; write change was %d.\n",
    222             op == EPOLL_CTL_ADD?"ADD":
    223             op == EPOLL_CTL_DEL?"DEL":
    224             op == EPOLL_CTL_MOD?"MOD":"???",
    225             ch->fd,
    226             ch->old_events,
    227             ch->read_change, ch->write_change
    228             );
    229     if (epoll_ctl(epollop->epfd, op, ch->fd, &epev) == -1) {

I found some strange libevent behavior, here is log printed on the
console, fd=10 is the socket connected to the client, fd=11 is the
socket connected to back server.

----begin (no warning)----
01 accepted connection from 192.168.161.1:3692 on 192.168.161.161:446.
(Continue reading)

Hor Meng Yoong | 2 Jun 2010 14:58
Picon

test

test.
***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.

Nick Mathewson | 3 Jun 2010 17:26

Re: libevent with EV_WRITE question

On Sat, May 29, 2010 at 6:44 AM, Sherif Fanous <sherif.fanous <at> gmail.com> wrote:
> Hi
> I have the following scenario, and want to verify the expected outcome
> pthread_wrlock_rdlock(&(server->lock));
> if (server->is_connected) {
>     struct send_packets_args *send_packets_args;
>     send_packets_args = malloc(sizeof (struct send_packets_args));
>     // Initialize send_packets_args to contain buffer to send, and length of
> buffer to send
>     event_base_once(base, server->socket, EV_WRITE, send_packets, (void *)
> send_packets_args, NULL);
>     pthread_wrlock_unlock(&(server->lock));
>     event_base_loop(base, EVLOOP_NONBLOCK);
> } else
>     pthread_wrlock_unlock(&(server->lock));
> In my callback after I'm done with the sending I perform the cleaning up
> (free the send_packets_args)
>
> Now my question, if at the moment I release my read lock above, the
> connection to the server is lost and server->socket is closed. Will the
> callback send_packets get called? I want to know the expected outcome
> because I need to make sure I'm not leaking memory allocated for the
> send_packets_args that gets freed as the final step of the send_packets
> callback.

First off, to clarify, if you want to make sure you're not leaking
memory when an event isn't called, you pretty much need to use
event_add() and and event_del() manually, and not trust to
event_base_once().  If you use event_base_once() and the event never
triggers, then there's no way to delete it.
(Continue reading)

Sherif Fanous | 3 Jun 2010 17:42
Picon

Re: libevent with EV_WRITE question

Thank you for an excellent explanation


Cheers

On Thu, Jun 3, 2010 at 4:26 PM, Nick Mathewson <nickm <at> freehaven.net> wrote:
On Sat, May 29, 2010 at 6:44 AM, Sherif Fanous <sherif.fanous <at> gmail.com> wrote:
> Hi
> I have the following scenario, and want to verify the expected outcome
> pthread_wrlock_rdlock(&(server->lock));
> if (server->is_connected) {
>     struct send_packets_args *send_packets_args;
>     send_packets_args = malloc(sizeof (struct send_packets_args));
>     // Initialize send_packets_args to contain buffer to send, and length of
> buffer to send
>     event_base_once(base, server->socket, EV_WRITE, send_packets, (void *)
> send_packets_args, NULL);
>     pthread_wrlock_unlock(&(server->lock));
>     event_base_loop(base, EVLOOP_NONBLOCK);
> } else
>     pthread_wrlock_unlock(&(server->lock));
> In my callback after I'm done with the sending I perform the cleaning up
> (free the send_packets_args)
>
> Now my question, if at the moment I release my read lock above, the
> connection to the server is lost and server->socket is closed. Will the
> callback send_packets get called? I want to know the expected outcome
> because I need to make sure I'm not leaking memory allocated for the
> send_packets_args that gets freed as the final step of the send_packets
> callback.

First off, to clarify, if you want to make sure you're not leaking
memory when an event isn't called, you pretty much need to use
event_add() and and event_del() manually, and not trust to
event_base_once().  If you use event_base_once() and the event never
triggers, then there's no way to delete it.

But, will it trigger?  I believe so; Libevent seems to report remotely
closed sockets as EV_READ and EV_WRITE on all the backends I can test.
 I'm adding a unit test for this to be sure that it holds everywhere.

Stylistically, though, I believe that it's most common to treat the
availability of the EOF as a -read- event, not a write event.  (That's
because you detect a close by calling read() or recv() and having it
return 0.)  I believe some old versions of Libevent may have screwed
this up on Windows and reported EOF as write instead, though, so be
sure to test for the behavior you want here if you're using an old
version.

yrs,
--
Nick
***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.

Nick Mathewson | 3 Jun 2010 17:51

Re: socket message boundary problem

On Mon, May 31, 2010 at 1:14 PM, Hor Meng Yoong <yoonghm <at> gmail.com> wrote:
> Hi:
>
>   I am using libevent2. Is that a wrapper function/library to send and
> receive fixed length message, or variable length message with message length
> embedded in the first 2 bytes with libevent2? Thank

Got all three of your messages.  No need to send so many!

There's no built-in function to do this, but it's very easy to do with
bufferevents.  Here's some example demo code to show you the general
idea of how it's done:

#include <event2/bufferevent.h>
#include <event2/buffer.h>

#define MSG_LEN 512

int
send_fixed_msg(struct bufferevent *bev, const char *msg)
{
	bufferevent_write(bev, msg, MSG_LEN);
	return 0;
}

void
fixed_msg_readcb(struct bufferevent *bev, void *ctx)
{
	char msg_buf[MSG_LEN];
	struct evbuffer *inp = bufferevent_get_input(bev);
	while (evbuffer_get_length(inp) >= MSG_LEN) {
		evbuffer_remove(inp, msg_buf, MSG_LEN);
		/* Here's where you add code to handle the contents of
		 * msg_buf */
	}
}

void
setup_fixed_msg_bufferevent(struct bufferevent *bev)
{
	/* Set up the read callback to be invoked when we have some bytes that
	   have arrived. In practice, you'd also want to set the other
	   callbacks, and maybe provide some data too. */
	bufferevent_setcb(bev, fixed_msg_readcb, NULL, NULL, NULL);
}

/* Now, variable-length messages.  Let's assume that the message format
 * is a two-byte length value encoded in big-endian (network) order,
 * plus that number of bytes worth of message */
int
send_var_msg(struct bufferevent *bev, const char *msg, int length)
{
	ev_uint16_t len_encoded;
	if (length < 0 || length > 65535)
		return -1;
	len_encoded = htons(length);
	bufferevent_write(bev, &len_encoded, 2);
	bufferevent_write(bev, msg, length);
	return 0;
}

void
var_msg_readcb(struct bufferevent *bev, void *ctx)
{
	struct evbuffer *inp = bufferevent_get_input(bev);
	char msg_buf[65536];
	ev_uint16_t len_encoded;
	int msglen;
	while (1) {
		int len_in_buf = evbuffer_get_length(inp);
		if (len_in_buf < 2)
			return;
		/* We have enough data to read a length field.  For now,
		 * just inspect it but don't remove it.
		 */
		evbuffer_copyout(inp, &len_encoded, 2);
		msglen = ntohs(len_encoded);
	        if (len_in_buf < 2 + msglen) {
			/* The entire message hasn't arrived yet. */
			return;
		}
		/* The message is here; pull it out of the buffer. */
		evbuffer_drain(inp, 2); /*discard the length field */
		evbuffer_remove(inp, msg_buf, msglen);

		/* Here's where you add code to handle the contents of
		 * msg_buf */
	}
}

void
setup_var_msg_bufferevent(struct bufferevent *bev)
{
	/* Set up the read callback to be invoked when we have some bytes that
	   have arrived. In practice, you'd also want to set the other
	   callbacks, and maybe provide some data too. */
	bufferevent_setcb(bev, var_msg_readcb, NULL, NULL, NULL);
}

Note that in practice you might want to use watermarks to avoid
extraneous calls to the _readcb functions.  For more info on the
bufferevent API, check out chapter Ref6 of
http://www.wangafu.net/~nickm/libevent-book/ .

hope this helps,
--

-- 
Nick
***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.

Nick Mathewson | 3 Jun 2010 20:42

Re: How to close bufferevent connection?

On Mon, May 31, 2010 at 11:07 PM, Felix Nawothnig
<felix.nawothnig <at> googlemail.com> wrote:
> Hey.
>
> What's the "suggested" way to close a bufferevent connection?
>
> Currently I do:
>
>        fd = bufferevent_getfd(bev);
>        evutil_closesocket(fd);
>
> ... followed by a manual:
>
>        my_event_handler(bev, BEV_EVENT_EOF, NULL);
>
> ... because it doesn't seem to be called otherwise.
>
> Is this the "correct" way? Is the fact that the event handler not called
> a bug?
>

Two points to expand on hcpark's reply:

1) Calling bufferevent_free() will only close the socket if the
bufferevent was set up with the BEV_OPT_CLOSE_ON_FREE option.  [I
already mentioned this to Felix on Sourceforge, but it's good to keep
in mind.  The default behavior by analogy with event_del and
event_free, neither of which close their underlying fd.]

2)  The BEV_EVENT_EOF event is only generated for an EOF that you
*receive*, not when you close the socket yourself.  Since most
backends (select, poll, etc) don't provide a notice when *you* close
an fd, there's no event generated for that on the bufferevent.
***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.


Gmane