Nick Mathewson | 2 Feb 18:49 2011
Picon

Re: HTTP and thread safety

On Mon, Jan 31, 2011 at 12:42 PM, Marco <marco.tijuana <at> gmail.com> wrote:
> Hi everyone, simple question..
>
> 2 threads, T1 is in the event loop, T2 does some other things.
> Assume that I have a safe way of communicating between T1 and T2.
>
> I'm planning to use T2 to create http requests objects and then give them to
> T1 to actually perform the request, i.e.:
>
> T2 calls
> - evhttp_connection_base_new
> - evhttp_connection_set_timeout
> - evhttp_connection_set_retries
> - evhttp_connection_set_closecb
> - evhttp_request_new
>
> Then T2 passes the evhttp_connection and evhttp_request to T1, who calls
> evhttp_make_request.
> (again, assume this message passing is implemeted safely)
>
> Is this thread safe?
> Or does any of the functions invoked by T2 modify the event base (owned by
> T1)?

Hm.  All I can go with in response here is that "evhttp is not
threadsafe"; nobody has done the sufficient thread-safety analysis on
it.  From what I can see, evhttp_connection_base_new makes a
non-threadsafe bufferevent, which will indeed add and remove events
from the event base.  bufferevent_set_timeout, called by
evhttp_conection_set_timeout, also manipulates events.
(Continue reading)

Wayne Shao | 2 Feb 20:27 2011
Picon

bufferevent with openssl server

Hi,

I tried to setup an SSL server with libevent. But the read/write callbacks are not invoked after the handshake phase.
Please see the code below. 

Thanks, 
W Shao

The listener callback is as follows:

void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
      struct sockaddr *sa, int socklen, void *user_data) {
  struct event_base *base = (struct event_base*) user_data;
  struct bufferevent *bev;
  
  BIO *sbio=BIO_new_socket(fd,BIO_NOCLOSE);
  ssl=SSL_new(ctx); 

  SSL_set_bio(ssl,sbio,sbio);

  bev = bufferevent_openssl_socket_new(base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
      BEV_OPT_CLOSE_ON_FREE);
  if (!bev) {
    fprintf(stderr, "Error constructing bufferevent!");
    event_base_loopbreak(base);
    return;
  }
  
  // Question: 
  //  Do I need to call SSL_accept at some point?
  
 bev = bufferevent_openssl_filter_new(base,
      bev,
      ssl,
      BUFFEREVENT_SSL_OPEN,
      BEV_OPT_CLOSE_ON_FREE);

  if (!bev) {
    perror("Bufferevent_openssl_new");
  }

  bufferevent_setcb(bev, readcb, writecb, eventcb, NULL);
  bufferevent_enable(bev, EV_WRITE);
  bufferevent_enable(bev, EV_READ);
}
  

Marco | 2 Feb 20:44 2011
Picon

Re: HTTP and thread safety

Thanks Nick, I'll check again myself in the source.

Marco

On Wed, Feb 2, 2011 at 9:49 AM, Nick Mathewson <nickm <at> freehaven.net> wrote:
On Mon, Jan 31, 2011 at 12:42 PM, Marco <marco.tijuana <at> gmail.com> wrote:
> Hi everyone, simple question..
>
> 2 threads, T1 is in the event loop, T2 does some other things.
> Assume that I have a safe way of communicating between T1 and T2.
>
> I'm planning to use T2 to create http requests objects and then give them to
> T1 to actually perform the request, i.e.:
>
> T2 calls
> - evhttp_connection_base_new
> - evhttp_connection_set_timeout
> - evhttp_connection_set_retries
> - evhttp_connection_set_closecb
> - evhttp_request_new
>
> Then T2 passes the evhttp_connection and evhttp_request to T1, who calls
> evhttp_make_request.
> (again, assume this message passing is implemeted safely)
>
> Is this thread safe?
> Or does any of the functions invoked by T2 modify the event base (owned by
> T1)?

Hm.  All I can go with in response here is that "evhttp is not
threadsafe"; nobody has done the sufficient thread-safety analysis on
it.  From what I can see, evhttp_connection_base_new makes a
non-threadsafe bufferevent, which will indeed add and remove events
from the event base.  bufferevent_set_timeout, called by
evhttp_conection_set_timeout, also manipulates events.

I think you *might* be okay here, but I really can't guarantee it
unless somebody takes a good hard look at the evhttp code in question.

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

Nick Mathewson | 2 Feb 21:44 2011
Picon

Re: bufferevent with openssl server

On Wed, Feb 2, 2011 at 2:27 PM, Wayne Shao <wshao99 <at> gmail.com> wrote:
> Hi,
> I tried to setup an SSL server with libevent. But the read/write callbacks
> are not invoked after the handshake phase.
> Please see the code below.
> Thanks,
> W Shao

I think the problem is using BUFFEREVENT_SSL_OPEN.  When you get the
connection,  it *isn't* an open SSL connection, so you need to pass in
BUFFEREVENT_SSL_ACCEPTING.
***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.

Wayne Shao | 2 Feb 22:17 2011

Re: bufferevent with openssl server

I changed it to BUFFEREVENT_SSL_ACCEPTING. The read/write callbacks are still not invoked.


Is there an example SSL server anywhere?

On Wed, Feb 2, 2011 at 12:44 PM, Nick Mathewson <nickm <at> freehaven.net> wrote:
On Wed, Feb 2, 2011 at 2:27 PM, Wayne Shao <wshao99 <at> gmail.com> wrote:
> Hi,
> I tried to setup an SSL server with libevent. But the read/write callbacks
> are not invoked after the handshake phase.
> Please see the code below.
> Thanks,
> W Shao

I think the problem is using BUFFEREVENT_SSL_OPEN.  When you get the
connection,  it *isn't* an open SSL connection, so you need to pass in
BUFFEREVENT_SSL_ACCEPTING.
***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.



--
W. Shao

Wayne Shao | 2 Feb 22:41 2011
Picon

Re: bufferevent with openssl server

corrections:


If I comment out the call bufferevent_openssl_filter_new(), then the client can finish handshake, but the server read/write callback not working. 

The code as above (i.e., with the bufferevent_openssl_filter_new() call)  enters an infinite loop (from the USE_DEBUG build). 

[debug] event_add: event: 0xe1bfe0 (fd 6), EV_READ   call 0x7fca51fec1b0
[debug] Epoll ADD(1) on fd 6 okay. [old events were 0; read change was 1; write change was 0]
[debug] event_add: event: 0xe1af40 (fd 7), EV_READ   call 0x7fca51ff94ce
[debug] Epoll ADD(1) on fd 7 okay. [old events were 0; read change was 1; write change was 0]
[debug] event_add: event: 0xe1a740 (fd 2),    call 0x402044
[debug] evsig_add: 2: changing signal handler
[debug] _evsig_set_handler: evsignal (2) >= sh_old_max (0), resizing
[debug] event_add: event: 0xe1be38 (fd 5), EV_READ   call 0x7fca52003839
[debug] Epoll ADD(1) on fd 5 okay. [old events were 0; read change was 1; write change was 0]
[debug] epoll_dispatch: epoll_wait reports 1
[debug] event_active: 0xe1af40 (fd 7), res 2, callback 0x7fca51ff94ce
[debug] event_process_active: event: 0xe1af40, EV_READ  call 0x7fca51ff94ce
[debug] event_add: event: 0xe1ca80 (fd 8), EV_READ   call 0x7fca51fd5793
[debug] Epoll ADD(1) on fd 8 okay. [old events were 0; read change was 1; write change was 0]
[debug] event_add: event: 0xe1cb08 (fd 8),  EV_WRITE  call 0x7fca51fd5793
[debug] Epoll MOD(5) on fd 8 okay. [old events were 2; read change was 0; write change was 1]
[debug] event_add: event: 0xe1ca80 (fd 8), EV_READ   call 0x7fca51fd5793
[debug] event_add: event: 0xe1cb08 (fd 8),  EV_WRITE  call 0x7fca51fd5793
[debug] epoll_dispatch: epoll_wait reports 1
[debug] event_active: 0xe1ca80 (fd 8), res 2, callback 0x7fca51fd5793
[debug] event_active: 0xe1cb08 (fd 8), res 4, callback 0x7fca51fd5793
[debug] event_process_active: event: 0xe1ca80, EV_READ  call 0x7fca51fd5793
[debug] event_del: 0xe1cb08 (fd 8), callback 0x7fca51fd5793
[debug] Epoll MOD(1) on fd 8 okay. [old events were 6; read change was 0; write change was 2]
[debug] event_add: event: 0xe1ca80 (fd 8), EV_READ   call 0x7fca51fd5793
[debug] epoll_dispatch: epoll_wait reports 1
[debug] event_active: 0xe1ca80 (fd 8), res 2, callback 0x7fca51fd5793
[debug] event_process_active: event: 0xe1ca80, EV_READ  call 0x7fca51fd5793
[debug] event_del: 0xe1cb08 (fd 8), callback 0x7fca51fd5793
[debug] event_add: event: 0xe1ca80 (fd 8), EV_READ   call 0x7fca51fd5793
[debug] epoll_dispatch: epoll_wait reports 1
[debug] event_active: 0xe1ca80 (fd 8), res 2, callback 0x7fca51fd5793
[debug] event_process_active: event: 0xe1ca80, EV_READ  call 0x7fca51fd5793
[debug] event_del: 0xe1cb08 (fd 8), callback 0x7fca51fd5793
 ( and continues ...)

On Wed, Feb 2, 2011 at 1:17 PM, Wayne Shao <wshao99 <at> gmail.com> wrote:
I changed it to BUFFEREVENT_SSL_ACCEPTING. The read/write callbacks are still not invoked.

Is there an example SSL server anywhere?


On Wed, Feb 2, 2011 at 12:44 PM, Nick Mathewson <nickm <at> freehaven.net> wrote:
On Wed, Feb 2, 2011 at 2:27 PM, Wayne Shao <wshao99 <at> gmail.com> wrote:
> Hi,
> I tried to setup an SSL server with libevent. But the read/write callbacks
> are not invoked after the handshake phase.
> Please see the code below.
> Thanks,
> W Shao

I think the problem is using BUFFEREVENT_SSL_OPEN.  When you get the
connection,  it *isn't* an open SSL connection, so you need to pass in
BUFFEREVENT_SSL_ACCEPTING.
***********************************************************************
To unsubscribe, send an e-mail to majordomo <at> freehaven.net with
unsubscribe libevent-users    in the body.



--
W. Shao



Nick Mathewson | 3 Feb 02:37 2011
Picon

Re: bufferevent with openssl server

On Wed, Feb 2, 2011 at 4:41 PM, Wayne Shao <wshao99 <at> gmail.com> wrote:
> corrections:
> If I comment out the call bufferevent_openssl_filter_new(), then the client
> can finish handshake, but the server read/write callback not working.
> The code as above (i.e., with the bufferevent_openssl_filter_new() call)
> enters an infinite loop (from the USE_DEBUG build).

Oh, I think see what you're doing wrong!  You're using both
bufferevent_openssl_socket_new() and bufferevent_openssl_filter_new()
on the same socket -- that's not necessary.

bufferevent_openssl_socket_new() wraps SSL around an FD without an
underlying bufferevent.  You can use it when you need to speak SSL on
an underlying fd.  Data is written directly to the fd with SSL_read
and SSL_write.

bufferevent_openssl_filter_new() wraps SSL around another bufferevent.
 You can use it when you have some existing non-socket-based
bufferevent that you need to speak SSL over.  When you write data on
the *filtering* bufferevent, it sets it up so that SSL_read and
SSL_write .   The most common use of bufferevent_openssl_filter_new()
is to use SSL over an IOCP-based bufferevent.

If you wrap an fd in an openssl_socket bufferevent, and then wrap
_that_ bufferevent in an openssl_filter bufferevent, you aren't doing
SSL over the fd; you're doing SSL *inside* SSL over that fd.
Apparently that isn't supported well.

So in other words, there are two reasonable ways to set up SSL on an
fd.  The first way is

    bev = bufferevent_openssl_socket_new( ... fd ...);

And the second is

    bev1 = bufferevent_socket_new(... fd ...);
    bev2 = bufferevent_openssl_filter_new(... bev1 ...);

hth,
--

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

Sarita Sarathy | 5 Feb 03:52 2011
Picon

Libevent edge trigger support for udp in Solaris


Hi,

We would like to use UDP connections asynchronously in Solaris with edge trigger 
support in Solaris. Does libevent-2.0.10 have this support for Solaris 11. 

The server would have to handle at least 64,000 connections.

As I understand, does the completion port framework in Solaris 11 work with 
edgelevel riggering with UDP?

Thanks

Sarita
Gordiychuck Oleg | 6 Feb 23:07 2011
Picon

Read callback problem



Начало переадресованного сообщения:

От: Gordiychuck Oleg <mybrokenbeat <at> gmail.com>
Дата: 7 лютого 2011 р. 00:04:43 GMT+02:00
Тема: Read callback problem

Hello!

I have a simple network application with simple protocol over TCP\IP. The main idea of protocol is size+message model. So at first i'm sending size of message (coded in big-endian, first 4 bytes) than the whole message.
I'm using event2 and read data from OnRead callback which i set and enabled to bufferevent with next code:

static void OnRead(struct bufferevent *bev, void *user_data)
{
int buf_len = evbuffer_get_length(bufferevent_get_input(bev));
ConnectionContext *ctx = user_data;
uint8_t size_data[4],*data;

printf("bytes avaliable this call: %d\n",buf_len); // always 18 bytes

switch (ctx->state)
       {
case ReadSize:
if (buf_len < 4)
break;
bufferevent_read(bev,size_data,4);
ctx->size = get_be32(size_data);
ctx->state = ReadCommand;
break;
case ReadCommand:
if (buf_len<ctx->size)
break;
data = new uint8_t[ctx->size];
bufferevent_read(bev,data,ctx->size);
/// work with data
delete[] data;
break;
default:
//error handler
}
}

Each time OnRead is called i don't know exactly how much bytes i will need to read. So if understand the mechanism of libevent right OnRead should be called each time there is at least one byte avaliable to read. When i try to send 18 bytes OnRead callback successfully called first time and ctx->state is set to ReadCommand, but callback is not calling second time, when there is 14 bytes avaliable! What am i doing wrong?

Kelly Brock | 7 Feb 05:35 2011

RE: Read callback problem

Hi,

> 	I have a simple network application with simple protocol over
> TCP\IP. The main idea of protocol is size+message model. So at first i'm
> sending size of message (coded in big-endian, first 4 bytes) than the
> whole message.
> 	I'm using event2 and read data from OnRead callback which i set and
> enabled to bufferevent with next code:
> 
> 	static void OnRead(struct bufferevent *bev, void *user_data)
> 	{
> 	int buf_len = evbuffer_get_length(bufferevent_get_input(bev));
> 	ConnectionContext *ctx = user_data;
> 	uint8_t size_data[4],*data;
> 
> 	printf("bytes avaliable this call: %d\n",buf_len); // always 18
> bytes
> 
> 	switch (ctx->state)
> 	       {
> 	case ReadSize:
> 	if (buf_len < 4)
> 	break;
> 	bufferevent_read(bev,size_data,4);
> 	ctx->size = get_be32(size_data);
> 	ctx->state = ReadCommand;
> 	break;
> 	case ReadCommand:
> 	if (buf_len<ctx->size)
> 	break;
> 	data = new uint8_t[ctx->size];
> 	bufferevent_read(bev,data,ctx->size);
> 	/// work with data
> 	delete[] data;
> 	break;
> 	default:
> 	//error handler
> 	}
> 	}
> 
> 	Each time OnRead is called i don't know exactly how much bytes i
> will need to read. So if understand the mechanism of libevent right OnRead
> should be called each time there is at least one byte avaliable to read.
> When i try to send 18 bytes OnRead callback successfully called first time
> and ctx->state is set to ReadCommand, but callback is not calling second
> time, when there is 14 bytes avaliable! What am i doing wrong?

	Depending on the setup and such, I've done this and it works quite
well.  I would wonder what setup you are doing before I would consider
libevent at fault here.  My initial thought is that you have not called
enable on the read callback.  I *believe* that libevent will always call the
read callback the first time data is received after connection, but unless
you enable read it won't call the callback again.

	The code you posted looks like it should function though, so look
into the setup code and of course the other side which is sending.

KB

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


Gmane