filedescriptor explicite close method on eventbufferevent object...

Issue #10 resolved
Mathieu CARBONNEAUX created an issue

when upgrade (like in smtp starttls protocol extension) eventbufferevent to ssl like that: $newbev = EventBufferEvent::sslFilter($base, $originalbev, $sslctx, EventBufferEvent::SSL_ACCEPTING);

if the $originalbev eventbufferevent has the OPT_CLOSE_ON_FREE when replace and dereferance the $originalbev and use the $newbev the $originalbev close the filedescriptor...

and when working for ssl with libevent is not recommanded to use on the sslfilter... http://www.wangafu.net/~nickm/libevent-book/Ref6a_advanced_bufferevents.html

***Note that when BEV_OPT_CLOSE_ON_FREE is set on a SSL bufferevent, a clean shutdown will not be performed on the SSL connection. This has two problems: first, the connection will seem to have been "broken" by the other side, rather than having been closed cleanly: the other party will not be able to tell whether you closed the connection, or whether it was broken by an attacker or third party.


the probleme when not use this option OPT_CLOSE_ON_FREE is that the $fd of the eventbufferevent cannot be manipulated by php function close($fd) or socket_close($fd)...then they canot abel to explictly close it...

the only solution to explicitely close the socket $fd of the eventbufferevent without modify the extension are :

     if ($bev = new EventBufferEvent($base, $originalbev->fd, EventBufferEvent::OPT_CLOSE_ON_FREE))
      {
        $bev->free();
        unset($bev);
      }

like that the new eventbufferevent reuse the fd with OPT_CLOSE_ON_FREE and when free it they close it...

but i think is not the clean way to do that...

the good way is to add close method on eventbufferevent to abel to close this $fd explicitely when OPT_CLOSE_ON_FREE are not set...

diff --git a/classes/buffer_event.c b/classes/buffer_event.c
index 4dcbab2..41bc7ca 100644
--- a/classes/buffer_event.c
+++ b/classes/buffer_event.c
@@ -345,6 +345,25 @@ PHP_METHOD(EventBufferEvent, __construct)
 }
 /* }}} */

+/* {{{ proto bool EventBufferEvent::close(void); */
+PHP_METHOD(EventBufferEvent, close)
+{
+       zval               *zbevent = getThis();
+       php_event_bevent_t *bev;
+       evutil_socket_t fd;
+       int ret=-1;
+
+       PHP_EVENT_FETCH_BEVENT(bev, zbevent);
+
+       if (bev->bevent) {
+         fd = bufferevent_getfd(bev->bevent);
+         ret=close(fd);
+         if (ret==-1) RETURN_FALSE;
+       }
+       RETVAL_TRUE;
+}
+/* }}} */
+
 /* {{{ proto void EventBufferEvent::free(void); */
 PHP_METHOD(EventBufferEvent, free)
 {
diff --git a/src/fe.c b/src/fe.c
index 11c3794..98c6da5 100644
--- a/src/fe.c
+++ b/src/fe.c
@@ -552,6 +553,7 @@ const zend_function_entry php_event_config_ce_functions[] = {/* {{{ */

 const zend_function_entry php_event_bevent_ce_functions[] = {/* {{{ */
        PHP_ME(EventBufferEvent, __construct,       arginfo_bufferevent__construct,    ZEND_ACC_PUBLIC  | ZEND_ACC_CTOR)
+       PHP_ME(EventBufferEvent, close,             arginfo_event__void,               ZEND_ACC_PUBLIC)
        PHP_ME(EventBufferEvent, free,              arginfo_event__void,               ZEND_ACC_PUBLIC)
        PHP_ME(EventBufferEvent, connect,           arginfo_bufferevent_connect,       ZEND_ACC_PUBLIC)
        PHP_ME(EventBufferEvent, connectHost,       arginfo_bufferevent_connecthost,   ZEND_ACC_PUBLIC)
diff --git a/src/fe.h b/src/fe.h
index 0f89336..5d93049 100644
--- a/src/fe.h
+++ b/src/fe.h
@@ -62,6 +63,7 @@ PHP_METHOD(EventConfig, setMaxDispatchInterval);
 #endif

 PHP_METHOD(EventBufferEvent, __construct);
+PHP_METHOD(EventBufferEvent, close);
 PHP_METHOD(EventBufferEvent, free);
 PHP_METHOD(EventBufferEvent, createPair);
 PHP_METHOD(EventBufferEvent, connect);

or to make $fd usable with php close and socket_close...

Comments (5)

  1. Ruslan Osmanov repo owner

    Personally, I'd find a way around with OPT_CLOSE_ON_FREE... However, the method is added to master. Please check it out.

    Thanks.

  2. Mathieu CARBONNEAUX reporter

    ??? but when free the parent bevent they close the fd !?

    like that:

                  $bev->disable(Event::READ | Event::WRITE);
                  $newbev = EventBufferEvent::sslFilter($base,
                      $bev, $sslctx,
                      EventBufferEvent::SSL_ACCEPTING);
                  if (!$newbev)
                  {
                      die("error in going in ssl");
                  }
                  $bev->free();
                  $bev=$newbev;
                  $bev->setTimeouts(30,30);
                  $bev->setCallbacks([$this, "ev_read"], NULL, [$this, 'ev_error'], $this);
                  $bev->enable(Event::READ);
    
  3. Log in to comment