Commits

Ruslan Osmanov committed 9205cec

Fix: evconnlistener_new(_bind) methods didn't work
Refact: event_base resource now stores resource ID for ref couting

Comments (0)

Files changed (4)

 }
 /* }}} */
 
-/* {{{ listener_cb */
-static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *address, int socklen, void *ctx) {
+/* {{{ _php_event_listener_cb */
+static void _php_event_listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *address, int socklen, void *ctx) {
 
 	php_event_listener_t  *l = (php_event_listener_t *) ctx;
 
 	zval   *arg_data     = l->data;
 	zval   *retval_ptr;
 
-	TSRMLS_FETCH_FROM_CTX(l->thread_ctx);
+	php_stream *stream;
 
-	php_printf("listener_cb(): listener = %p, fd = %d, l->rsrc_id = %d, l->stream_id = %d\n",
-			listener, fd, l->rsrc_id, l->stream_id);
+	TSRMLS_FETCH_FROM_CTX(l->thread_ctx);
 
 	/* Call user function having proto:
-	 * void cb (resource $listener, resource $fd, array $address, mixed $data); */
+	 * void cb (resource $listener, resource $fd, array $address, mixed $data);
+	 * $address = array ("IP-address", *server* port)
+	 * Note, address contains the server port(not the one user passed to ex.
+	 * evconnlistener_new_bind()!
+	 */
 
 	if (ZEND_FCI_INITIALIZED(*pfci)) {
 		MAKE_STD_ZVAL(arg_listener);
 		zend_list_addref(l->rsrc_id);
 		args[0] = &arg_listener;
 
-		if (l->stream_id >= 0) {
+		/* Convert the socket created by libevent to PHP stream
+	 	 * and save it's resource ID in l->stream_id */
+
+		if (l->stream_id > 0) {
 			MAKE_STD_ZVAL(arg_fd);
 			ZVAL_RESOURCE(arg_fd, l->stream_id);
 			zend_list_addref(l->stream_id);
 		} else {
-			ALLOC_INIT_ZVAL(arg_fd);
+			stream = php_stream_fopen_from_fd(fd, "r", NULL);
+			if (stream) {
+				MAKE_STD_ZVAL(arg_fd);
+				php_stream_to_zval(stream, arg_fd);
+
+				l->stream_id = Z_LVAL_P(arg_fd);
+				zend_list_addref(l->stream_id);
+			} else {
+				l->stream_id = -1;
+				ALLOC_INIT_ZVAL(arg_fd);
+			}
 		}
 		args[1] = &arg_fd;
 
 static void php_event_base_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
 	/* TODO: what if events bound to the event_base are not destroyed? */
-	struct event_base *base = (struct event_base *) rsrc->ptr;
+	php_event_base_t *b= (php_event_base_t *) rsrc->ptr;
 
-	event_base_free(base);
+	if (b) {
+		event_base_free(b->base);
+		efree(b);
+	}
 }
 /* }}} */
 
 PHP_FUNCTION(evtimer_new)
 {
 	zval                  *zbase;
-	php_event_base_t      *base;
+	php_event_base_t      *b;
 	zend_fcall_info        fci   = empty_fcall_info;
 	zend_fcall_info_cache  fcc   = empty_fcall_info_cache;
 	zval                  *arg   = NULL;
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
 	e = emalloc(sizeof(php_event_t));
 	memset(e, 0, sizeof(php_event_t));
 
-	event = evtimer_new(base, timer_cb, (void *) e);
+	event = evtimer_new(b->base, timer_cb, (void *) e);
 	if (!event) {
 		efree(e);
 		RETURN_FALSE;
 PHP_FUNCTION(evtimer_set)
 {
 	zval                  *zbase;
-	php_event_base_t      *base;
+	php_event_base_t      *b;
 	zval                  *zevent;
 	php_event_t           *e;
 	zend_fcall_info        fci    = empty_fcall_info;
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
 	if (ZEND_FCI_INITIALIZED(fci)) {
 		if (e->fci && ZEND_FCI_INITIALIZED(*e->fci)) {
 
 	e->stream_id = -1; /* stdin fd = 0 */
 
-    if (evtimer_assign(e->event, base, timer_cb, (void *) e)) {
+    if (evtimer_assign(e->event, b->base, timer_cb, (void *) e)) {
     	RETURN_FALSE;
     }
     RETVAL_TRUE;
 PHP_FUNCTION(evsignal_new)
 {
 	zval                  *zbase;
-	php_event_base_t      *base;
+	php_event_base_t      *b;
 	long                   signum;
 	zend_fcall_info        fci    = empty_fcall_info;
 	zend_fcall_info_cache  fcc    = empty_fcall_info_cache;
 		RETURN_FALSE;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
 	e = emalloc(sizeof(php_event_t));
 	memset(e, 0, sizeof(php_event_t));
 
-	event = evsignal_new(base, signum, signal_cb, (void *) e);
+	event = evsignal_new(b->base, signum, signal_cb, (void *) e);
 	if (!event) {
 		efree(e);
 		RETURN_FALSE;
 PHP_FUNCTION(event_new)
 {
 	zval                   *zbase;
-	php_event_base_t       *base;
+	php_event_base_t       *b;
 	zval                  **ppzfd;
 	evutil_socket_t         fd;
 	long                    what;
 		}
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
 	/* TODO: check if a signum bound to different event bases */
 
 	e = emalloc(sizeof(php_event_t));
 	memset(e, 0, sizeof(php_event_t));
 
-	event = event_new(base, fd, what, event_cb, (void *) e);
+	event = event_new(b->base, fd, what, event_cb, (void *) e);
 	if (!event) {
 		efree(e);
 		php_error_docref(NULL TSRMLS_CC, E_ERROR, "event_new failed");
 PHP_FUNCTION(event_set)
 {
 	zval                   *zbase;
-	php_event_base_t       *base;
+	php_event_base_t       *b;
 	zval                   *zevent;
 	php_event_t            *e;
 	zval                  **ppzfd   = NULL;
 		RETURN_FALSE;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
 	/* TODO: check if a signum bound to different event bases */
 
 		Z_ADDREF_P(arg);
 	}
 
-	event_get_assignment(e->event, &base,
+	event_get_assignment(e->event, &b->base,
 			(ppzfd ? NULL : &fd),
 			(short *) (what == -1 ? &what : NULL),
 			NULL /* ignore old callback */ ,
 			NULL /* ignore old callback argument */);
 
-	if (event_assign(e->event, base, fd, what, event_cb, (void *) e)) {
+	if (event_assign(e->event, b->base, fd, what, event_cb, (void *) e)) {
 		RETURN_FALSE;
 	}
 
 PHP_FUNCTION(event_reinit)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 				&zbase) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_reinit(base)) {
+	if (event_reinit(b->base)) {
 		RETURN_TRUE;
 	}
 	RETVAL_FALSE;
  * Returns resource representing new event base */
 PHP_FUNCTION(event_base_new)
 {
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters_none() == FAILURE) {
 		return;
 	}
 
-	base = event_base_new();
+	b = emalloc(sizeof(php_event_base_t));
+	memset(b, 0, sizeof(php_event_base_t));
+
+	b->base = event_base_new();
 
-	if (base) {
-		ZEND_REGISTER_RESOURCE(return_value, base, le_event_base);
+	if (b->base) {
+		b->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, b, le_event_base);
 	} else {
+		efree(b);
 		RETVAL_FALSE;
 	}
 }
  * Creates new event base taking the specified configuration under consideration. */
 PHP_FUNCTION(event_base_new_with_config)
 {
-	php_event_base_t   *base;
+	php_event_base_t   *b;
 	php_event_config_t *cfg;
 	zval               *zcfg;
 
 
 	PHP_EVENT_FETCH_CONFIG(cfg, zcfg);
 
-	base = event_base_new_with_config(cfg);
+	b = emalloc(sizeof(php_event_base_t));
+	memset(b, 0, sizeof(php_event_base_t));
 
-	if (base) {
-		ZEND_REGISTER_RESOURCE(return_value, base, le_event_base);
+	b->base = event_base_new_with_config(cfg);
+
+	if (b->base) {
+		b->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, b, le_event_base);
 	} else {
+		efree(b);
 		RETVAL_FALSE;
 	}
 }
 PHP_FUNCTION(event_base_get_method)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 				&zbase) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	RETVAL_STRING(event_base_get_method(base), 1);
+	RETVAL_STRING(event_base_get_method(b->base), 1);
 }
 /* }}} */
 
 PHP_FUNCTION(event_base_get_features)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 				&zbase) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase)
+	PHP_EVENT_FETCH_BASE(b, zbase)
 
-	RETVAL_LONG(event_base_get_features(base));
+	RETVAL_LONG(event_base_get_features(b->base));
 }
 /* }}} */
 
 {
 	zval             *zbase;
 	long              n_priorities;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl",
 				&zbase, &n_priorities) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_base_priority_init(base, n_priorities)) {
+	if (event_base_priority_init(b->base, n_priorities)) {
 		RETURN_FALSE;
 	}
 	RETVAL_TRUE;
 {
 	zval             *zbase;
 	long              flags = -1;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l",
 				&zbase, &flags) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
 	/* Call event_base_dispatch when flags omitted. */
 	if (flags == -1) {
-		if (event_base_dispatch(base) == -1) {
+		if (event_base_dispatch(b->base) == -1) {
 			RETURN_FALSE;
 		}
-	} else if (event_base_loop(base, flags) == -1) {
+	} else if (event_base_loop(b->base, flags) == -1) {
 		RETURN_FALSE;
 	}
 	RETVAL_TRUE;
 PHP_FUNCTION(event_base_dispatch)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 				&zbase) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_base_dispatch(base) == -1) {
+	if (event_base_dispatch(b->base) == -1) {
 		RETURN_FALSE;
 	}
 	RETVAL_TRUE;
 PHP_FUNCTION(event_base_loopexit)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 	double            timeout = -1;
 	int               res;
 
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
 	if (timeout == -1) {
-		res = event_base_loopexit(base, NULL);
+		res = event_base_loopexit(b->base, NULL);
 	} else {
 		struct timeval tv;
 		PHP_EVENT_TIMEVAL_SET(tv, timeout);
 
-		res = event_base_loopexit(base, &tv);
+		res = event_base_loopexit(b->base, &tv);
 	}
 
 	if (res) {
 PHP_FUNCTION(event_base_loopbreak)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 				&zbase) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_base_loopbreak(base)) {
+	if (event_base_loopbreak(b->base)) {
 		RETURN_FALSE;
 	}
 	RETVAL_TRUE;
 PHP_FUNCTION(event_base_set)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 	zval             *zevent;
 	php_event_t      *e;
 
 		RETURN_FALSE;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_base_set(base, e->event)) {
+	if (event_base_set(b->base, e->event)) {
 		RETURN_FALSE;
 	}
 	RETVAL_TRUE;
 PHP_FUNCTION(event_base_got_break)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 				&zbase) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_base_got_break(base)) {
+	if (event_base_got_break(b->base)) {
 		RETURN_TRUE;
 	}
 	RETVAL_FALSE;
 PHP_FUNCTION(event_base_got_exit)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 				&zbase) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_base_got_exit(base)) {
+	if (event_base_got_exit(b->base)) {
 		RETURN_TRUE;
 	}
 	RETVAL_FALSE;
 PHP_FUNCTION(event_base_gettimeofday_cached)
 {
 	zval                  *zbase;
-	php_event_base_t      *base;
+	php_event_base_t      *b;
 	struct timeval         tv;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_base_gettimeofday_cached(base, &tv)) {
+	if (event_base_gettimeofday_cached(b->base, &tv)) {
 		RETURN_NULL();
 	}
 	
 PHP_FUNCTION(event_base_update_cache_time)
 {
 	zval             *zbase;
-	php_event_base_t *base;
+	php_event_base_t *b;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r",
 				&zbase) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(base, zbase);
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
-	if (event_base_update_cache_time(base)) {
+	if (event_base_update_cache_time(b->base)) {
 		RETURN_FALSE;
 	}
 	RETVAL_TRUE;
  * Passing NULL to socket parameter means that the socket stream should be created later,
  * e.g. by means of bufferevent_socket_connect().
  *
+ * socket parameter may be created as a stream(not necessarily by means of sockets extension)
+ *
  * Returns bufferevent resource optionally associated with socket resource. */
 PHP_FUNCTION(bufferevent_socket_new)
 {
 	zval               **ppzfd   = NULL;
 	evutil_socket_t      fd;
 	long                 options = 0;
-	php_event_bevent_t  *b;
+	php_event_bevent_t  *bev;
 	struct bufferevent  *bevent;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|Z!l",
 		if (ppzfd) {
 			/* sockets_zval_to_fd reports error
 	 	 	 * in case if it is not a valid socket resource */
-			fd = (evutil_socket_t) sockets_zval_to_fd(ppzfd TSRMLS_CC);
+			/*fd = (evutil_socket_t) sockets_zval_to_fd(ppzfd TSRMLS_CC);*/
+			fd = zval_to_fd(ppzfd TSRMLS_CC);
+
 		}
 
 		if (fd < 0) {
 
 	PHP_EVENT_FETCH_BASE(base, zbase);
 
-	b = emalloc(sizeof(php_event_bevent_t));
-	memset(b, 0, sizeof(php_event_bevent_t));
+	bev = emalloc(sizeof(php_event_bevent_t));
+	memset(bev, 0, sizeof(php_event_bevent_t));
 
-	bevent = bufferevent_socket_new(base, fd, options);
+	bevent = bufferevent_socket_new(base->base, fd, options);
 	if (bevent == NULL) {
-		efree(b);
+		efree(bev);
 		php_error_docref(NULL TSRMLS_CC, E_ERROR,
 				"Failed to allocate bufferevent for socket");
 		RETURN_FALSE;
 	}
 
-	b->bevent = bevent;
+	bev->bevent = bevent;
 
 	if (ppzfd) {
 		/* lval of ppzfd is the resource ID */
-		b->stream_id = Z_LVAL_PP(ppzfd);
+		bev->stream_id = Z_LVAL_PP(ppzfd);
 		zend_list_addref(Z_LVAL_PP(ppzfd));
 	} else {
 		/* Should be assigned in bufferevent_socket_connect() later
 		 * (by means of bufferevent_getfd()) */
-		b->stream_id = -1;
+		bev->stream_id = -1;
 	}
 
-	b->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, b, le_event_bevent);
+	/* Make sure base destroyed after the bufferevent */
+	zend_list_addref(base->rsrc_id);
+
+	bev->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, bev, le_event_bevent);
+	/* XXX Normally I wouldn't do it. But if one creates the resource inside a callback,
+	 * particularly called by libevent->event, the resource is destroyed on return automatically.
+	 * See examples/listener.php
+	 * Maybe add some userspace function like bufferevent_ref() */
+	zend_list_addref(bev->rsrc_id);
 }
 /* }}} */
 
 
 	PHP_EVENT_FETCH_BASE(base, zbase);
 
-	if (bufferevent_pair_new(base, options, bevent_pair)) {
+	if (bufferevent_pair_new(base->base, options, bevent_pair)) {
 		RETURN_FALSE;
 	}
 
 	dnsb = emalloc(sizeof(php_event_dns_base_t));
 	memset(dnsb, 0, sizeof(php_event_dns_base_t));
 
-	dnsb->dns_base = evdns_base_new(base, initialize);
+	dnsb->dns_base = evdns_base_new(base->base, initialize);
 
 	if (dnsb->dns_base) {
 		dnsb->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, dnsb, le_event_dns_base);
 	struct evconnlistener *listener;
 	struct sockaddr        sa;
 	socklen_t              sa_len   = sizeof(struct sockaddr);
-	evutil_socket_t        fd;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rfz!llz", &zbase,
-				&fci, &fcc, &zdata, &flags, &backlog, &zaddr) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rfz!llz",
+				&zbase, &fci, &fcc, &zdata, &flags, &backlog, &zaddr) == FAILURE) {
 		return;
 	}
 
 	l = emalloc(sizeof(php_event_listener_t));
 	memset(l, 0, sizeof(php_event_listener_t));
 
-	listener = evconnlistener_new_bind(base, listener_cb, (void *) l,
-			flags, backlog, &sa, sa_len);
+	listener = evconnlistener_new_bind(base->base, _php_event_listener_cb,
+			(void *) l, flags, backlog, &sa, sa_len);
 	if (!listener) {
 		efree(l);
 		RETURN_FALSE;
 	l->base_id = Z_LVAL_P(zbase);
 	zend_list_addref(l->base_id);
 
-	/* Convert the socket created by libevent to PHP stream
-	 * and save it's resource ID in l->stream_id */
-	zval       *zstream;
-	php_stream *stream;
-
-	fd     = evconnlistener_get_fd(listener);
-	stream = php_stream_fopen_from_fd(fd, "r", NULL);
-
-	if (stream) {
-		MAKE_STD_ZVAL(zstream);
-
-		php_stream_to_zval(stream, zstream);
-		l->stream_id = Z_LVAL_P(zstream);
-		zend_list_addref(l->stream_id);
-	} else {
-		l->stream_id = -1;
-	}
-
-
 	TSRMLS_SET_CTX(l->thread_ctx);
 
 	l->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, l, le_event_listener);
 
-	php_printf("evconnlistener_new(): listener = %p, fd = %d, l->stream_id = %d, l->rsrc_id = %d\n",
-			listener, fd, l->stream_id, l->rsrc_id);
-
 	PHP_EVENT_ASSERT(l->rsrc_id);
 }
 /* }}} */
 	l = emalloc(sizeof(php_event_listener_t));
 	memset(l, 0, sizeof(php_event_listener_t));
 
-	listener = evconnlistener_new(base, listener_cb, (void *) l,
-			flags, backlog, fd);
+	listener = evconnlistener_new(base->base, _php_event_listener_cb,
+			(void *) l, flags, backlog, fd);
 	if (!listener) {
 		efree(l);
 		RETURN_FALSE;
 
 	PHP_EVENT_COPY_FCALL_INFO(l->fci, l->fcc, &fci, &fcc);
 
+#if 0
+	/* Don't do this, since libevent calls accept() afterwards, thus producing
+	 * new file descriptor. The new descriptor is available in
+	 * _php_event_listener_cb() callback. */
+
 	if (Z_TYPE_PP(ppzfd) == IS_RESOURCE) {
 		/* lval of ppzfd is the resource ID */
 		l->stream_id = Z_LVAL_PP(ppzfd);
 	} else {
 		l->stream_id = -1;
 	}
+#endif
+	l->stream_id = -1;
+
+	l->base_id = Z_LVAL_P(zbase);
+	zend_list_addref(l->base_id);
 
 	TSRMLS_SET_CTX(l->thread_ctx);
 
 	l->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, l, le_event_listener);
 
-	php_printf("evconnlistener_new(): listener = %p, fd = %d, l->stream_id = %d, l->rsrc_id = %d\n",
-			listener, fd, l->stream_id, l->rsrc_id);
-
 	PHP_EVENT_ASSERT(l->rsrc_id);
 }
 /* }}} */
 	/*
 	 * No sense in the following call, since the callback and the pointer
 	 * remain the same
-	 * evconnlistener_set_cb(l->listener, listener_cb, (void *) l);
+	 * evconnlistener_set_cb(l->listener, _php_event_listener_cb, (void *) l);
 	 */
 }
 /* }}} */
 	*/
 
 	if (l->base_id) {
+		/* Make sure base wouldn't be inexpectedly destroyed */
+		zend_list_addref(l->base_id);
+
 		RETURN_RESOURCE(l->base_id);
 	} else {
 		RETVAL_FALSE;
 echo "step 1\n";
 
 $base = event_base_new();
-$fd   = eio_get_event_stream();
 
 echo "step 2\n";
 
+eio_init();
+
 eio_mkdir($dir, 0750, EIO_PRI_DEFAULT, "my_nop_cb");
 
-$event = event_new($base, $fd,
-	EVENT_READ | EVENT_WRITE | EVENT_PERSIST, function ($fd, $events, $base) {
+$event = event_new($base, eio_get_event_stream(),
+	EVENT_READ | EVENT_PERSIST, function ($fd, $events, $base) {
 	echo "step 5\n";
 
 	while (eio_nreqs()) {

examples/listener.php

 <?php
+/*
+ * Simple echo server based on libevent's connection listener.
+ *
+ * Usage:
+ * 1) In one terminal window run:
+ *
+ * $ php listener.php
+ *
+ * 2) In another terminal window open up connection, e.g.:
+ *
+ * $ nc 127.0.0.1 9876
+ *
+ * 3) start typing. The server should repeat the input.
+ */
+
 function echo_read_cb($bev, $ctx) {
     /* This callback is invoked when there is data to read on $bev. */
     $input  = bufferevent_get_input($bev);
 }
 
 function accept_conn_cb($listener, $fd, $address, $ctx) {
-	echo __FUNCTION__, " args:\n";
-	var_dump($listener, $fd, $address, $ctx);
     /* We got a new connection! Set up a bufferevent for it. */
+
+    //$base = $ctx;
     $base = evconnlistener_get_base($listener);
+
     $bev = bufferevent_socket_new($base, $fd, EVENT_BEV_OPT_CLOSE_ON_FREE);
 
     bufferevent_setcb($bev, "echo_read_cb", NULL, "echo_event_cb", NULL);
 	exit(1);
 }
 
-/*
+/* Variant #1 */
 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
 if (!socket_bind($socket, '0.0.0.0', $port)) {
 	echo "Unable to bind socket\n";
 	exit(1);
 }
+$listener = evconnlistener_new($base, "accept_conn_cb", $base,
+    EVENT_LEV_OPT_CLOSE_ON_FREE | EVENT_LEV_OPT_REUSEABLE, -1, $socket);
+
+/* Variant #2 */
+/*
+$listener = evconnlistener_new_bind($base, "accept_conn_cb", $base,
+    EVENT_LEV_OPT_CLOSE_ON_FREE | EVENT_LEV_OPT_REUSEABLE, -1, "0.0.0.0:$port");
  */
 
-$listener = evconnlistener_new_bind($base, "accept_conn_cb", /* data for callbacks */ NULL,
-    EVENT_LEV_OPT_CLOSE_ON_FREE | EVENT_LEV_OPT_REUSEABLE, /* backlog */ -1, "0.0.0.0:$port");
 if (!$listener) {
     echo "Couldn't create listener";
 	exit(1);
 
 #endif/* HAVE_EVENT_EXTRA_LIB }}} */
 
-typedef struct event_base php_event_base_t;
+typedef struct {
+	struct event_base *base;
+	int                rsrc_id;   /* Resource ID of the event base */
+} php_event_base_t;
 typedef struct event_config php_event_config_t;
 typedef double php_event_timestamp_t;
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.