1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 8                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2020 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Ruslan Osmanov <osmanov@php.net>                             |
16    +----------------------------------------------------------------------+
17 */
18 
19 #include "src/common.h"
20 #include "src/util.h"
21 #include "src/priv.h"
22 #include "classes/http.h"
23 #include "zend_exceptions.h"
24 #include "ext/spl/spl_exceptions.h"
25 
26 zend_class_entry *php_event_ce;
27 zend_class_entry *php_event_base_ce;
28 zend_class_entry *php_event_config_ce;
29 zend_class_entry *php_event_bevent_ce;
30 zend_class_entry *php_event_buffer_ce;
31 zend_class_entry *php_event_util_ce;
32 #ifdef HAVE_EVENT_EXTRA_LIB
33 zend_class_entry *php_event_dns_base_ce;
34 zend_class_entry *php_event_listener_ce;
35 zend_class_entry *php_event_http_conn_ce;
36 zend_class_entry *php_event_http_ce;
37 zend_class_entry *php_event_http_req_ce;
38 #endif
39 #ifdef HAVE_EVENT_OPENSSL_LIB
40 zend_class_entry *php_event_ssl_context_ce;
41 #endif
42 
43 zend_class_entry *php_event_exception_ce;
44 
45 static HashTable classes;
46 
47 static HashTable event_properties;
48 static HashTable event_bevent_properties;
49 static HashTable event_buffer_properties;
50 static HashTable event_listener_properties;
51 #ifdef HAVE_EVENT_OPENSSL_LIB
52 static HashTable event_ssl_context_properties;
53 int php_event_ssl_data_index;
54 #endif
55 
56 static zend_object_handlers event_event_object_handlers;
57 static zend_object_handlers event_base_object_handlers;
58 static zend_object_handlers event_config_object_handlers;
59 static zend_object_handlers event_bevent_object_handlers;
60 static zend_object_handlers event_buffer_object_handlers;
61 static zend_object_handlers event_util_object_handlers;
62 #if HAVE_EVENT_EXTRA_LIB
63 static zend_object_handlers event_dns_base_object_handlers;
64 static zend_object_handlers event_listener_object_handlers;
65 static zend_object_handlers event_http_conn_object_handlers;
66 static zend_object_handlers event_http_object_handlers;
67 static zend_object_handlers event_http_req_object_handlers;
68 #endif
69 #ifdef HAVE_EVENT_OPENSSL_LIB
70 static zend_object_handlers event_ssl_context_object_handlers;
71 #endif
72 
73 static const zend_module_dep event_deps[] = {
74 #ifdef PHP_EVENT_SOCKETS_SUPPORT
75 	ZEND_MOD_REQUIRED("sockets")
76 #endif
77 	ZEND_MOD_END
78 };
79 
80 /* {{{ event_module_entry */
81 zend_module_entry event_module_entry = {
82 	STANDARD_MODULE_HEADER_EX,
83 	NULL,
84 	event_deps,
85 	"event",
86 	NULL, /*event_functions*/
87 	PHP_MINIT(event),
88 	PHP_MSHUTDOWN(event),
89 	PHP_RINIT(event),
90 	PHP_RSHUTDOWN(event),
91 	PHP_MINFO(event),
92 	PHP_EVENT_VERSION,
93 	STANDARD_MODULE_PROPERTIES
94 };
95 /* }}} */
96 
97 #ifdef COMPILE_DL_EVENT
98 #ifdef ZTS
99 ZEND_TSRMLS_CACHE_DEFINE();
100 #endif
ZEND_GET_MODULE(event)101 ZEND_GET_MODULE(event)
102 #endif
103 
104 
105 zend_class_entry *php_event_get_exception_base(int root) /* {{{ */
106 {
107 	if (!root) {
108 		return spl_ce_RuntimeException;
109 	}
110 	return zend_ce_exception;
111 }
112 /* }}} */
113 
php_event_get_exception(void)114 zend_class_entry *php_event_get_exception(void)/*{{{*/
115 {
116 	return php_event_exception_ce;
117 }/*}}}*/
118 
119 
120 /* {{{ Private functions */
121 
free_prop_handler(zval * el)122 static void free_prop_handler(zval *el)/*{{{*/
123 {
124 	pefree(Z_PTR_P(el), 1);
125 }/*}}}*/
126 
php_event_event_dtor_obj(zend_object * object)127 static void php_event_event_dtor_obj(zend_object *object)/*{{{*/
128 {
129 	Z_EVENT_X_OBJ_T(event) *intern = Z_EVENT_X_FETCH_OBJ(event, object);
130 	PHP_EVENT_ASSERT(intern);
131 
132 	if (!Z_ISUNDEF(intern->data)) {
133 		zval_ptr_dtor(&intern->data);
134 	}
135 
136 	php_event_free_callback(&intern->cb);
137 
138 	zend_objects_destroy_object(object);
139 }/*}}}*/
140 
php_event_base_dtor_obj(zend_object * object)141 static void php_event_base_dtor_obj(zend_object *object)/*{{{*/
142 {
143 #if 0
144 	Z_EVENT_X_OBJ_T(base) *intern = Z_EVENT_X_FETCH_OBJ(base, object);
145 	PHP_EVENT_ASSERT(intern);
146 #endif
147 
148 	zend_objects_destroy_object(object);
149 }/*}}}*/
150 
php_event_config_dtor_obj(zend_object * object)151 static void php_event_config_dtor_obj(zend_object *object)/*{{{*/
152 {
153 #if 0
154 	Z_EVENT_X_OBJ_T(config) *intern = Z_EVENT_X_FETCH_OBJ(config, object);
155 	PHP_EVENT_ASSERT(intern);
156 #endif
157 
158 	zend_objects_destroy_object(object);
159 }/*}}}*/
160 
php_event_bevent_dtor_obj(zend_object * object)161 static void php_event_bevent_dtor_obj(zend_object *object)/*{{{*/
162 {
163 	Z_EVENT_X_OBJ_T(bevent) *intern = Z_EVENT_X_FETCH_OBJ(bevent, object);
164 	PHP_EVENT_ASSERT(intern);
165 
166 #if 0
167 	if (intern->bevent) {
168 		bufferevent_lock(intern->bevent);
169 		bufferevent_disable(intern->bevent, EV_WRITE|EV_READ);
170 		bufferevent_setcb(intern->bevent, NULL, NULL, NULL, NULL);
171 		bufferevent_set_timeouts(intern->bevent, NULL, NULL);
172 		bufferevent_unlock(intern->bevent);
173 	}
174 #endif
175 
176 	if (!Z_ISUNDEF(intern->data)) {
177 		zval_ptr_dtor(&intern->data);
178 	}
179 
180 	if (!Z_ISUNDEF(intern->self)) {
181 		if (Z_REFCOUNT(intern->self) > 1) {
182 			zval_ptr_dtor(&intern->self);
183 		}
184 		ZVAL_UNDEF(&intern->self);
185 	}
186 
187 	if (!Z_ISUNDEF(intern->base)) {
188 		Z_TRY_DELREF(intern->base);
189 		ZVAL_UNDEF(&intern->base);
190 		/*zval_ptr_dtor(&intern->base);*/
191 	}
192 
193 	if (!Z_ISUNDEF(intern->input)) {
194 		zval_ptr_dtor(&intern->input);
195 		ZVAL_UNDEF(&intern->input);
196 	}
197 
198 	if (!Z_ISUNDEF(intern->output)) {
199 		zval_ptr_dtor(&intern->output);
200 		ZVAL_UNDEF(&intern->output);
201 	}
202 
203 	php_event_free_callback(&intern->cb_read);
204 	php_event_free_callback(&intern->cb_write);
205 	php_event_free_callback(&intern->cb_event);
206 
207 	zend_objects_destroy_object(object);
208 }/*}}}*/
209 
php_event_buffer_dtor_obj(zend_object * object)210 static void php_event_buffer_dtor_obj(zend_object *object)/*{{{*/
211 {
212 #if 0
213 	Z_EVENT_X_OBJ_T(buffer) *intern = Z_EVENT_X_FETCH_OBJ(buffer, object);
214 	PHP_EVENT_ASSERT(intern);
215 #endif
216 
217 	zend_objects_destroy_object(object);
218 }/*}}}*/
219 
220 
php_event_event_free_obj(zend_object * object)221 static void php_event_event_free_obj(zend_object *object)/*{{{*/
222 {
223 	Z_EVENT_X_OBJ_T(event) *intern = Z_EVENT_X_FETCH_OBJ(event, object);
224 	PHP_EVENT_ASSERT(intern);
225 
226 	if (intern->event) {
227 		/* No need in event_del(e->event) since event_free makes event non-pending internally */
228 		event_free(intern->event);
229 		intern->event = NULL;
230 	}
231 
232 #if 0
233 	if (intern->stream_res) { /* stdin fd == 0 */
234 		/* In php5 we had decremented resource reference counter */
235 		intern->stream_res = NULL;
236 	}
237 #endif
238 
239 	zend_object_std_dtor(&intern->zo);
240 }/*}}}*/
241 
php_event_base_free_obj(zend_object * object)242 static void php_event_base_free_obj(zend_object *object)/*{{{*/
243 {
244 	Z_EVENT_X_OBJ_T(base) *b = Z_EVENT_X_FETCH_OBJ(base, object);
245 	PHP_EVENT_ASSERT(b);
246 
247 	if (!b->internal && b->base) {
248 		event_base_loopexit(b->base, NULL);
249 		event_base_free(b->base);
250 		b->base = NULL;
251 	}
252 
253 	zend_object_std_dtor(object);
254 }/*}}}*/
255 
php_event_config_free_obj(zend_object * object)256 static void php_event_config_free_obj(zend_object *object)/*{{{*/
257 {
258 	Z_EVENT_X_OBJ_T(config) *intern = Z_EVENT_X_FETCH_OBJ(config, object);
259 	PHP_EVENT_ASSERT(intern);
260 
261 	if (intern->ptr) {
262 		event_config_free(intern->ptr);
263 		intern->ptr = NULL;
264 	}
265 
266 	zend_object_std_dtor(object);
267 }/*}}}*/
268 
php_event_bevent_free_obj(zend_object * object)269 static void php_event_bevent_free_obj(zend_object *object)/*{{{*/
270 {
271 #ifdef HAVE_EVENT_OPENSSL_LIB
272 	SSL *ctx;
273 #endif
274 	Z_EVENT_X_OBJ_T(bevent) *b = Z_EVENT_X_FETCH_OBJ(bevent, object);
275 
276 	if (!b->_internal && b->bevent) {
277 #if defined(HAVE_EVENT_OPENSSL_LIB)
278 		/* See www.wangafu.net/~nickm/libevent-book/Ref6a_advanced_bufferevents.html#_bufferevents_and_ssl */
279 		ctx = bufferevent_openssl_get_ssl(b->bevent);
280 		if (ctx) {
281 			SSL_set_shutdown(ctx, SSL_RECEIVED_SHUTDOWN);
282 			SSL_shutdown(ctx);
283 			SSL_free(ctx);
284 		}
285 #endif
286 
287 		bufferevent_free(b->bevent);
288 		b->bevent = NULL;
289 	}
290 
291 	zend_object_std_dtor(object);
292 }/*}}}*/
293 
php_event_buffer_free_obj(zend_object * object)294 static void php_event_buffer_free_obj(zend_object *object)/*{{{*/
295 {
296 	php_event_buffer_t *b = Z_EVENT_X_FETCH_OBJ(buffer, object);
297 	PHP_EVENT_ASSERT(b);
298 
299 	/* If we got the buffer in, say, a read callback the buffer
300 	 * is destroyed when the callback is done as any normal variable.
301 	 * Zend MM calls destructor which eventually calls this function.
302 	 * We'll definitely crash, if we call evbuffer_free() on an internal
303 	 * bufferevent buffer. */
304 
305 	if (!b->internal && b->buf) {
306 		evbuffer_free(b->buf);
307 		b->buf = NULL;
308 	}
309 
310 	zend_object_std_dtor(object);
311 }/*}}}*/
312 
313 #ifdef HAVE_EVENT_EXTRA_LIB
314 
php_event_dns_base_free_obj(zend_object * object)315 static void php_event_dns_base_free_obj(zend_object *object)/*{{{*/
316 {
317 	php_event_dns_base_t *dnsb = Z_EVENT_X_FETCH_OBJ(dns_base, object);
318 
319 	PHP_EVENT_ASSERT(dnsb);
320 
321 	if (dnsb->dns_base) {
322 		/* Setting fail_requests to 1 makes all in-flight requests get
323 		 * their callbacks invoked with a canceled error code before it
324 		 * frees the base*/
325 		evdns_base_free(dnsb->dns_base, 1);
326 		dnsb->dns_base = NULL;
327 	}
328 
329 	zend_object_std_dtor(object);
330 }/*}}}*/
331 
php_event_listener_free_obj(zend_object * object)332 static void php_event_listener_free_obj(zend_object *object)/*{{{*/
333 {
334 	php_event_listener_t *l = Z_EVENT_X_FETCH_OBJ(listener, object);
335 
336 	PHP_EVENT_ASSERT(l);
337 
338 	if (l->listener) {
339 		evconnlistener_free(l->listener);
340 		l->listener = NULL;
341 	}
342 
343 	zend_object_std_dtor(object);
344 }/*}}}*/
345 
php_event_http_conn_free_obj(zend_object * object)346 static void php_event_http_conn_free_obj(zend_object *object)/*{{{*/
347 {
348 	php_event_http_conn_t *evcon = Z_EVENT_X_FETCH_OBJ(http_conn, object);
349 	PHP_EVENT_ASSERT(evcon);
350 
351 	if (evcon->conn && !evcon->internal) {
352 		evhttp_connection_free(evcon->conn);
353 		evcon->conn = NULL;
354 	}
355 
356 	zend_object_std_dtor(object);
357 }/*}}}*/
358 
php_event_http_free_obj(zend_object * object)359 static void php_event_http_free_obj(zend_object *object)/*{{{*/
360 {
361 	php_event_http_t *http = Z_EVENT_X_FETCH_OBJ(http, object);
362 
363 	PHP_EVENT_ASSERT(http);
364 
365 	if (http->ptr) {
366 		evhttp_free(http->ptr);
367 		http->ptr = NULL;
368 	}
369 
370 	zend_object_std_dtor(object);
371 }/*}}}*/
372 
php_event_http_req_free_obj(zend_object * object)373 static void php_event_http_req_free_obj(zend_object *object)/*{{{*/
374 {
375 #if 0
376 	php_event_http_req_t *http_req = Z_EVENT_X_FETCH_OBJ(http_req, object);
377 	PHP_EVENT_ASSERT(http_req);
378 #endif
379 
380 #if 0
381 	/*
382 	Libevent cleans up http_req->ptr despite the ownership of the pointer
383 	(evhttp_request_own()). So we'll get SEGFAULT here if we call
384 	evhttp_request_free().
385 	*/
386 
387 	if (!http_req->internal && http_req->ptr) {
388 		evhttp_request_free(http_req->ptr);
389 		http_req->ptr = NULL;
390 	}
391 #endif
392 
393 	zend_object_std_dtor(object);
394 }/*}}}*/
395 
396 
php_event_dns_base_dtor_obj(zend_object * object)397 static void php_event_dns_base_dtor_obj(zend_object *object)/*{{{*/
398 {
399 #if 0
400 	Z_EVENT_X_OBJ_T(dns_base) *intern = Z_EVENT_X_FETCH_OBJ(dns_base, object);
401 	PHP_EVENT_ASSERT(intern);
402 #endif
403 
404 	zend_objects_destroy_object(object);
405 }/*}}}*/
406 
php_event_listener_dtor_obj(zend_object * object)407 static void php_event_listener_dtor_obj(zend_object *object)/*{{{*/
408 {
409 	Z_EVENT_X_OBJ_T(listener) *intern = Z_EVENT_X_FETCH_OBJ(listener, object);
410 	PHP_EVENT_ASSERT(intern);
411 
412 	if (!Z_ISUNDEF(intern->data)) {
413 		zval_ptr_dtor(&intern->data);
414 		ZVAL_UNDEF(&intern->data);
415 	}
416 
417 	if (!Z_ISUNDEF(intern->self)) {
418 		if (Z_REFCOUNT(intern->self) > 1) {
419 			zval_ptr_dtor(&intern->self);
420 		}
421 		ZVAL_UNDEF(&intern->self);
422 	}
423 
424 	php_event_free_callback(&intern->cb);
425 	php_event_free_callback(&intern->cb_err);
426 
427 	zend_objects_destroy_object(object);
428 }/*}}}*/
429 
php_event_http_conn_dtor_obj(zend_object * object)430 static void php_event_http_conn_dtor_obj(zend_object *object)/*{{{*/
431 {
432 	Z_EVENT_X_OBJ_T(http_conn) *intern = Z_EVENT_X_FETCH_OBJ(http_conn, object);
433 	PHP_EVENT_ASSERT(intern);
434 
435 	php_event_free_callback(&intern->cb_close);
436 
437 	if (Z_REFCOUNT(intern->self) > 1) {
438 		zval_ptr_dtor(&intern->self);
439 	}
440 
441 	if (!Z_ISUNDEF(intern->data_closecb)) {
442 		zval_ptr_dtor(&intern->data_closecb);
443 	}
444 
445 	if (!Z_ISUNDEF(intern->base)) {
446 		zval_ptr_dtor(&intern->base);
447 	}
448 
449 	if (!Z_ISUNDEF(intern->dns_base)) {
450 		zval_ptr_dtor(&intern->dns_base);
451 	}
452 
453 	zend_objects_destroy_object(object);
454 }/*}}}*/
455 
php_event_http_dtor_obj(zend_object * object)456 static void php_event_http_dtor_obj(zend_object *object)/*{{{*/
457 {
458 	php_event_http_cb_t *cb, *cb_next;
459 	Z_EVENT_X_OBJ_T(http) *intern = Z_EVENT_X_FETCH_OBJ(http, object);
460 	PHP_EVENT_ASSERT(intern);
461 
462 	php_event_free_callback(&intern->cb);
463 
464 	/* Free attached callbacks */
465 	cb = intern->cb_head;
466 	while (cb) {
467 		cb_next = cb->next;
468 		_php_event_free_http_cb(cb);
469 		cb = cb_next;
470 	}
471 
472 	if (!Z_ISUNDEF(intern->data)) {
473 		zval_ptr_dtor(&intern->data);
474 	}
475 
476 	if (!Z_ISUNDEF(intern->base)) {
477 		zval_ptr_dtor(&intern->base);
478 	}
479 
480 	zend_objects_destroy_object(object);
481 }/*}}}*/
482 
php_event_http_req_dtor_obj(zend_object * object)483 static void php_event_http_req_dtor_obj(zend_object *object)/*{{{*/
484 {
485 	Z_EVENT_X_OBJ_T(http_req) *intern = Z_EVENT_X_FETCH_OBJ(http_req, object);
486 	PHP_EVENT_ASSERT(intern);
487 
488 	php_event_free_callback(&intern->cb);
489 
490 	if (!Z_ISUNDEF(intern->self)) {
491 		if (Z_REFCOUNT(intern->self) > 1) {
492 			zval_ptr_dtor(&intern->self);
493 		}
494 	}
495 
496 	if (!Z_ISUNDEF(intern->data)) {
497 		zval_ptr_dtor(&intern->data);
498 	}
499 
500 	zend_objects_destroy_object(object);
501 }/*}}}*/
502 
503 #endif /* HAVE_EVENT_EXTRA_LIB */
504 
505 
506 #ifdef HAVE_EVENT_OPENSSL_LIB
php_event_ssl_context_free_obj(zend_object * object)507 static void php_event_ssl_context_free_obj(zend_object *object)/*{{{*/
508 {
509 	php_event_ssl_context_t *ectx = Z_EVENT_X_FETCH_OBJ(ssl_context, object);
510 
511 	if (ectx->ctx) {
512 		SSL_CTX_free(ectx->ctx);
513 		ectx->ctx = NULL;
514 	}
515 
516 	if (ectx->ht) {
517 		zend_hash_destroy(ectx->ht);
518 		FREE_HASHTABLE(ectx->ht);
519 		ectx->ht = NULL;
520 	}
521 
522 	zend_object_std_dtor(object);
523 }/*}}}*/
524 
php_event_ssl_context_dtor_obj(zend_object * object)525 static void php_event_ssl_context_dtor_obj(zend_object *object)/*{{{*/
526 {
527 #if 0
528 	Z_EVENT_X_OBJ_T(ssl_context) *intern = Z_EVENT_X_FETCH_OBJ(ssl_context, object);
529 	PHP_EVENT_ASSERT(intern);
530 #endif
531 
532 	zend_objects_destroy_object(object);
533 }/*}}}*/
534 #endif /* HAVE_EVENT_OPENSSL_LIB */
535 
event_zend_objects_new(zend_class_entry * ce)536 static zend_object * event_zend_objects_new(zend_class_entry *ce)/*{{{*/
537 {
538 	return zend_objects_new(ce);
539 }/*}}}*/
540 
event_object_create(zend_class_entry * ce)541 static zend_object * event_object_create(zend_class_entry *ce)/*{{{*/
542 {
543 	Z_EVENT_X_OBJ_T(event) *intern;
544 
545 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(event));
546 	intern->zo.handlers = &event_event_object_handlers;
547 
548 	return &intern->zo;
549 }/*}}}*/
550 
event_base_object_create(zend_class_entry * ce)551 static zend_object * event_base_object_create(zend_class_entry *ce)/*{{{*/
552 {
553 	Z_EVENT_X_OBJ_T(base) *intern;
554 
555 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(base));
556 	intern->zo.handlers = &event_base_object_handlers;
557 
558 	return &intern->zo;
559 }/*}}}*/
560 
event_config_object_create(zend_class_entry * ce)561 static zend_object * event_config_object_create(zend_class_entry *ce)/*{{{*/
562 {
563 	Z_EVENT_X_OBJ_T(config) *intern;
564 
565 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(config));
566 	intern->zo.handlers = &event_config_object_handlers;
567 
568 	return &intern->zo;
569 
570 }/*}}}*/
571 
event_bevent_object_create(zend_class_entry * ce)572 static zend_object * event_bevent_object_create(zend_class_entry *ce)/*{{{*/
573 {
574 	Z_EVENT_X_OBJ_T(bevent) *intern;
575 
576 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(bevent));
577 	intern->zo.handlers = &event_bevent_object_handlers;
578 
579 	return &intern->zo;
580 }/*}}}*/
581 
event_buffer_object_create(zend_class_entry * ce)582 static zend_object * event_buffer_object_create(zend_class_entry *ce)/*{{{*/
583 {
584 	Z_EVENT_X_OBJ_T(buffer) *intern;
585 
586 	PHP_EVENT_OBJ_ALLOC(intern, ce,  Z_EVENT_X_OBJ_T(buffer));
587 	intern->zo.handlers = &event_buffer_object_handlers;
588 
589 	return &intern->zo;
590 }/*}}}*/
591 
592 #ifdef HAVE_EVENT_OPENSSL_LIB
event_ssl_context_object_create(zend_class_entry * ce)593 static zend_object * event_ssl_context_object_create(zend_class_entry *ce)/*{{{*/
594 {
595 	Z_EVENT_X_OBJ_T(ssl_context) *intern;
596 
597 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(ssl_context));
598 	intern->zo.handlers = &event_ssl_context_object_handlers;
599 
600 	return &intern->zo;
601 }/*}}}*/
602 #endif
603 
604 #if HAVE_EVENT_EXTRA_LIB
event_dns_base_object_create(zend_class_entry * ce)605 static zend_object * event_dns_base_object_create(zend_class_entry *ce)/*{{{*/
606 {
607 	Z_EVENT_X_OBJ_T(dns_base) *intern;
608 
609 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(dns_base));
610 	intern->zo.handlers = &event_dns_base_object_handlers;
611 
612 	return &intern->zo;
613 }/*}}}*/
614 
event_listener_object_create(zend_class_entry * ce)615 static zend_object * event_listener_object_create(zend_class_entry *ce)/*{{{*/
616 {
617 	Z_EVENT_X_OBJ_T(listener) *intern;
618 
619 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(listener));
620 	intern->zo.handlers = &event_listener_object_handlers;
621 
622 	return &intern->zo;
623 }/*}}}*/
624 
event_http_conn_object_create(zend_class_entry * ce)625 static zend_object * event_http_conn_object_create(zend_class_entry *ce)/*{{{*/
626 {
627 	Z_EVENT_X_OBJ_T(http_conn) *intern;
628 
629 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(http_conn));
630 	intern->zo.handlers = &event_http_conn_object_handlers;
631 
632 	return &intern->zo;
633 }/*}}}*/
634 
event_http_object_create(zend_class_entry * ce)635 static zend_object * event_http_object_create(zend_class_entry *ce)/*{{{*/
636 {
637 	Z_EVENT_X_OBJ_T(http) *intern;
638 
639 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(http));
640 	intern->zo.handlers = &event_http_object_handlers;
641 
642 	return &intern->zo;
643 }/*}}}*/
644 
event_http_req_object_create(zend_class_entry * ce)645 static zend_object * event_http_req_object_create(zend_class_entry *ce)/*{{{*/
646 {
647 	Z_EVENT_X_OBJ_T(http_req) *intern;
648 
649 	PHP_EVENT_OBJ_ALLOC(intern, ce, Z_EVENT_X_OBJ_T(http_req));
650 	intern->zo.handlers = &event_http_req_object_handlers;
651 
652 	return &intern->zo;
653 }/*}}}*/
654 #endif /* HAVE_EVENT_EXTRA_LIB */
655 
656 
657 /* {{{ fatal_error_cb
658  * Is called when Libevent detects a non-recoverable internal error. */
fatal_error_cb(int err)659 static void fatal_error_cb(int err)
660 {
661 	php_error_docref(NULL, E_ERROR, "Libevent detected non-recoverable internal error, code: %d", err);
662 }
663 /* }}} */
664 
665 
666 #if LIBEVENT_VERSION_NUMBER < 0x02001900
667 # define PHP_EVENT_LOG_CONST(name) _ ## name
668 #else
669 # define PHP_EVENT_LOG_CONST(name) name
670 #endif
671 
672 /* {{{ log_cb
673  * Overrides libevent's default error logging(it logs to stderr) */
log_cb(int severity,const char * msg)674 static void log_cb(int severity, const char *msg)
675 {
676 	int error_type;
677 
678 	switch (severity) {
679 		case PHP_EVENT_LOG_CONST(EVENT_LOG_DEBUG):
680 			error_type = E_STRICT;
681 			break;
682 		case PHP_EVENT_LOG_CONST(EVENT_LOG_MSG):
683 			error_type = E_NOTICE;
684 			break;
685 		case PHP_EVENT_LOG_CONST(EVENT_LOG_WARN):
686 			error_type = E_WARNING;
687 			break;
688 		case PHP_EVENT_LOG_CONST(EVENT_LOG_ERR):
689 			error_type = E_ERROR;
690 			break;
691 		default:
692 			error_type = E_NOTICE;
693 			break;
694 	}
695 
696 	php_error_docref(NULL, error_type, "%s", msg);
697 }
698 /* }}} */
699 
700 
read_property_default(void * obj,zval * retval)701 static zval * read_property_default(void *obj, zval *retval)/*{{{*/
702 {
703 	ZVAL_NULL(retval);
704 	php_error_docref(NULL, E_ERROR, "Cannot read property");
705 	return retval;
706 }/*}}}*/
707 
write_property_default(void * obj,zval * newval)708 static int write_property_default(void *obj, zval *newval)/*{{{*/
709 {
710 	php_error_docref(NULL, E_ERROR, "Cannot write property");
711 	return FAILURE;
712 }/*}}}*/
713 
read_property(zval * object,zval * member,int type,void ** cache_slot,zval * rv,void * obj,HashTable * prop_handler)714 static zval * read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv, void *obj, HashTable *prop_handler)/*{{{*/
715 {
716 	zval                      tmp_member;
717 	zval                     *retval;
718 	php_event_prop_handler_t *hnd        = NULL;
719 
720 	if (Z_TYPE_P(member) != IS_STRING) {
721 		ZVAL_COPY(&tmp_member, member);
722 		convert_to_string(&tmp_member);
723 		member = &tmp_member;
724 	}
725 
726 	if (prop_handler != NULL) {
727 		hnd = zend_hash_find_ptr(prop_handler, Z_STR_P(member));
728 	}
729 
730 	if (hnd) {
731 		retval = hnd->read_func(obj, rv);
732 		if (retval == NULL) {
733 			retval = &EG(uninitialized_zval);
734 		}
735 	} else {
736 		const zend_object_handlers *std_hnd = zend_get_std_object_handlers();
737 		retval = std_hnd->read_property(object, member, type, cache_slot, rv);
738 	}
739 
740 	if (member == &tmp_member) {
741 		zval_dtor(&tmp_member);
742 	}
743 
744 	return retval;
745 }/*}}}*/
746 
write_property(zval * object,zval * member,zval * value,void ** cache_slot,void * obj,HashTable * prop_handler)747 static void write_property(zval *object, zval *member, zval *value, void **cache_slot, void *obj, HashTable *prop_handler)/*{{{*/
748 {
749 	zval                      tmp_member;
750 	php_event_prop_handler_t *hnd        = NULL;
751 
752 	if (Z_TYPE_P(member) != IS_STRING) {
753 		ZVAL_COPY(&tmp_member, member);
754 		convert_to_string(&tmp_member);
755 		member = &tmp_member;
756 	}
757 
758 	if (prop_handler != NULL) {
759 	    hnd = zend_hash_find_ptr(prop_handler, Z_STR_P(member));
760 	}
761 
762 	if (hnd) {
763 		hnd->write_func(obj, value);
764 	} else {
765 		const zend_object_handlers *std_hnd = zend_get_std_object_handlers();
766 	    std_hnd->write_property(object, member, value, cache_slot);
767 	}
768 
769 	if (member == &tmp_member) {
770 		zval_dtor(member);
771 	}
772 }/*}}}*/
773 
object_has_property(zval * object,zval * member,int has_set_exists,void ** cache_slot,void * obj,HashTable * prop_handler)774 static int object_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot, void *obj, HashTable *prop_handler)/*{{{*/
775 {
776 	php_event_prop_handler_t *p;
777 	int                       ret = 0;
778 
779 	if ((p = zend_hash_find_ptr(prop_handler, Z_STR_P(member))) != NULL) {
780 		switch (has_set_exists) {
781 			case 2:
782 				ret = 1;
783 				break;
784 			case 1: {
785 						zval rv;
786 						zval *value = read_property(object, member, BP_VAR_IS, cache_slot, &rv, obj, prop_handler);
787 						if (value != &EG(uninitialized_zval)) {
788 							convert_to_boolean(value);
789 							ret = Z_TYPE_P(value) == IS_TRUE ? 1 : 0;
790 						}
791 						break;
792 					}
793 			case 0:{
794 					   zval rv;
795 					   zval *value = read_property(object, member, BP_VAR_IS, cache_slot, &rv, obj, prop_handler);
796 					   if (value != &EG(uninitialized_zval)) {
797 						   ret = Z_TYPE_P(value) != IS_NULL ? 1 : 0;
798 						   zval_ptr_dtor(value);
799 					   }
800 					   break;
801 				   }
802 			default:
803 				   php_error_docref(NULL, E_WARNING, "Invalid value for has_set_exists");
804 		}
805 	} else {
806 		const zend_object_handlers *std_hnd = zend_get_std_object_handlers();
807 		ret = std_hnd->has_property(object, member, has_set_exists, cache_slot);
808 	}
809 
810 	return ret;
811 }/*}}}*/
812 
object_get_debug_info(zval * object,int * is_temp,void * obj,HashTable * prop_handler)813 static HashTable * object_get_debug_info(zval *object, int *is_temp, void *obj, HashTable *prop_handler)/*{{{*/
814 {
815 	HashTable                *props = prop_handler;
816 	HashTable                *retval;
817 	php_event_prop_handler_t *entry;
818 
819 	ALLOC_HASHTABLE(retval);
820 	ZEND_INIT_SYMTABLE_EX(retval, zend_hash_num_elements(props) + 1, 0);
821 
822 	ZEND_HASH_FOREACH_PTR(props, entry) {
823 		zval rv, member;
824 		zval *value;
825 		ZVAL_STR(&member, entry->name);
826 		value = read_property(object, &member, BP_VAR_IS, 0, &rv, obj, prop_handler);
827 		if (value != &EG(uninitialized_zval)) {
828 			zend_hash_add(retval, Z_STR(member), value);
829 		}
830 	} ZEND_HASH_FOREACH_END();
831 
832 	return retval;
833 }/*}}}*/
834 
get_property_ptr_ptr(zval * object,zval * member,int type,void ** cache_slot,void * obj,HashTable * prop_handler)835 static zval * get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot, void *obj, HashTable *prop_handler)/*{{{*/
836 {
837 	zval                     *retval     = NULL;
838 	php_event_prop_handler_t *hnd        = NULL;
839 	zval                      tmp_member;
840 
841 	if (Z_TYPE_P(member) != IS_STRING) {
842 		ZVAL_COPY(&tmp_member, member);
843 		convert_to_string(&tmp_member);
844 		member = &tmp_member;
845 		cache_slot = NULL;
846 	}
847 
848 	if (prop_handler != NULL) {
849 		hnd = zend_hash_find_ptr(prop_handler, Z_STR_P(member));
850 	}
851 
852 	if (hnd && hnd->get_ptr_ptr_func != NULL) {
853 		retval = hnd->get_ptr_ptr_func(obj);
854 	} else {
855 		const zend_object_handlers *std_hnd = zend_get_std_object_handlers();
856 		retval = std_hnd->get_property_ptr_ptr(object, member, type, cache_slot);
857 	}
858 
859 	if (Z_ISUNDEF_P(retval)) {
860 		ZVAL_NULL(retval);
861 	}
862 
863 	if (member == &tmp_member) {
864 		zval_dtor(member);
865 	}
866 
867 	return retval;
868 }/*}}}*/
869 
get_properties(zval * object,void * obj,HashTable * prop_handler)870 static HashTable * get_properties(zval *object, void *obj, HashTable *prop_handler)/*{{{*/
871 {
872 	HashTable                *props = zend_std_get_properties(object);
873 	php_event_prop_handler_t *hnd;
874 	zend_string              *key;
875 
876 	if (prop_handler == NULL) {
877 		return NULL;
878 	}
879 
880 	ZEND_HASH_FOREACH_STR_KEY_PTR(prop_handler, key, hnd) {
881 		zval zret;
882 		if (hnd->read_func && hnd->read_func(obj, &zret)) {
883 			zend_hash_update(props, key, &zret);
884 		}
885 	} ZEND_HASH_FOREACH_END();
886 
887 	return props;
888 }/*}}}*/
get_gc(zval * object,zval ** gc_data,int * gc_count)889 static HashTable * get_gc(zval *object, zval **gc_data, int *gc_count)/*{{{*/
890 {
891 	*gc_data = NULL;
892 	*gc_count = 0;
893 	return zend_std_get_properties(object);
894 }/*}}}*/
895 
896 
897 #if PHP_VERSION_ID >= 70400
898 #define PHP_EVENT_X_PROP_WRITE_HND_DECL(x)                                                                  \
899 static zval *php_event_ ## x ## _write_property(zval *object, zval *member, zval *value, void **cache_slot) \
900 {                                                                                                           \
901 	Z_EVENT_X_OBJ_T(x) *obj = Z_EVENT_X_OBJ_P(x, object);                                                   \
902 	if (EXPECTED(obj)) {                                                                                    \
903 		write_property(object, member, value, cache_slot, (void *)obj, obj->prop_handler);                  \
904 	}                                                                                                       \
905 	return value;                                                                                           \
906 }
907 #else
908 #define PHP_EVENT_X_PROP_WRITE_HND_DECL(x)                                                                  \
909 static void php_event_ ## x ## _write_property(zval *object, zval *member, zval *value, void **cache_slot)  \
910 {                                                                                                           \
911 	Z_EVENT_X_OBJ_T(x) *obj = Z_EVENT_X_OBJ_P(x, object);                                                   \
912 	if (EXPECTED(obj)) {                                                                                    \
913 		write_property(object, member, value, cache_slot, (void *)obj, obj->prop_handler);                  \
914 	}                                                                                                       \
915 }
916 #endif /* PHP_VERSION >= 70400 */
917 
918 #define PHP_EVENT_X_PROP_HND_DECL(x)                                                                                 \
919 PHP_EVENT_X_PROP_WRITE_HND_DECL(x)                                                                                   \
920 static zval * php_event_ ## x ## _read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) { \
921 	Z_EVENT_X_OBJ_T(x) *obj = Z_EVENT_X_OBJ_P(x, object);                                                            \
922 	return (obj ? read_property(object, member, type, cache_slot, rv, (void *)obj, obj->prop_handler) : NULL);       \
923 }                                                                                                                    \
924 static int php_event_ ## x ## _has_property(zval *object, zval *member, int has_set_exists, void **cache_slot)              \
925 {                                                                                                                           \
926 	Z_EVENT_X_OBJ_T(x) *obj = Z_EVENT_X_OBJ_P(x, object);                                                                   \
927 	return (obj ? object_has_property(object, member, has_set_exists, cache_slot, (void *)obj, obj->prop_handler) : 0);     \
928 }                                                                                                                           \
929 static HashTable * php_event_ ## x ## _get_debug_info(zval *object, int *is_temp)        \
930 {                                                                                        \
931 	HashTable *retval;                                                                   \
932 	Z_EVENT_X_OBJ_T(x) *obj = Z_EVENT_X_OBJ_P(x, object);                                \
933 	if (EXPECTED(obj) && obj->prop_handler) {                                            \
934 		retval = object_get_debug_info(object, is_temp, (void *)obj, obj->prop_handler); \
935 	} else {                                                                             \
936 		ALLOC_HASHTABLE(retval);                                                         \
937 		ZEND_INIT_SYMTABLE_EX(retval, 1, 0);                                             \
938 	}                                                                                    \
939 	*is_temp = 1;                                                                        \
940 	return retval;                                                                       \
941 }                                                                                        \
942 static zval * php_event_ ## x ## _get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot)             \
943 {                                                                                                                           \
944 	Z_EVENT_X_OBJ_T(x) *obj = Z_EVENT_X_OBJ_P(x, object);                                                                   \
945 	return (EXPECTED(obj) ? get_property_ptr_ptr(object, member, type, cache_slot, (void *)obj, obj->prop_handler) : NULL); \
946 }                                                                                                                           \
947 static HashTable * php_event_ ## x ## _get_properties(zval *object)                                                         \
948 {                                                                                                                           \
949 	HashTable *retval;                                                                                                      \
950 	Z_EVENT_X_OBJ_T(x) *obj = Z_EVENT_X_OBJ_P(x, object);                                                                   \
951 	if (EXPECTED(obj)) {                                                                                                    \
952 		retval = get_properties(object, (void *)obj, obj->prop_handler);                                                    \
953 	} else {                                                                                                                \
954 		ALLOC_HASHTABLE(retval);                                                                                            \
955 	}                                                                                                                       \
956 	return retval;                                                                                                          \
957 }
958 
959 PHP_EVENT_X_PROP_HND_DECL(base)
PHP_EVENT_X_PROP_HND_DECL(event)960 PHP_EVENT_X_PROP_HND_DECL(event)
961 PHP_EVENT_X_PROP_HND_DECL(config)
962 PHP_EVENT_X_PROP_HND_DECL(buffer)
963 PHP_EVENT_X_PROP_HND_DECL(bevent)
964 
965 #ifdef HAVE_EVENT_EXTRA_LIB
966 PHP_EVENT_X_PROP_HND_DECL(dns_base)
967 PHP_EVENT_X_PROP_HND_DECL(listener)
968 PHP_EVENT_X_PROP_HND_DECL(http)
969 PHP_EVENT_X_PROP_HND_DECL(http_conn)
970 PHP_EVENT_X_PROP_HND_DECL(http_req)
971 #endif /* HAVE_EVENT_EXTRA_LIB */
972 
973 #ifdef HAVE_EVENT_OPENSSL_LIB
974 PHP_EVENT_X_PROP_HND_DECL(ssl_context)
975 #endif /* HAVE_EVENT_OPENSSL_LIB */
976 
977 #define PHP_EVENT_ADD_CLASS_PROPERTIES(a, b)                                 \
978 {                                                                            \
979 	int i = 0;                                                               \
980 	while (b[i].name != NULL) {                                              \
981 		php_event_add_property((a), (b)[i].name, (b)[i].name_length,         \
982 				(php_event_prop_read_t)(b)[i].read_func,                     \
983 				(php_event_prop_write_t)(b)[i].write_func,                   \
984 				(php_event_prop_get_ptr_ptr_t)(b)[i].get_ptr_ptr_func); \
985 		i++;                                                                 \
986 	}                                                                        \
987 }
988 
989 static void php_event_add_property(HashTable *h, const char *name, size_t name_len, php_event_prop_read_t read_func, php_event_prop_write_t write_func, php_event_prop_get_ptr_ptr_t get_ptr_ptr_func) {/*{{{*/
990 	php_event_prop_handler_t p;
991 
992 	p.name             = zend_string_init(name, name_len, 1);
993 	p.read_func        = read_func ? read_func : read_property_default;
994 	p.write_func       = write_func ? write_func: write_property_default;
995 	p.get_ptr_ptr_func = get_ptr_ptr_func;
996 	zend_hash_add_mem(h, p.name, &p, sizeof(php_event_prop_handler_t));
997 	zend_string_release(p.name);
998 }/*}}}*/
999 
1000 
register_classes()1001 static zend_always_inline void register_classes()/*{{{*/
1002 {
1003 	zend_class_entry *ce;
1004 	zend_class_entry ce_exception;
1005 
1006 	PHP_EVENT_REGISTER_CLASS("Event", event_object_create, php_event_ce, php_event_ce_functions);
1007 	ce = php_event_ce;
1008 	ce->ce_flags |= ZEND_ACC_FINAL;
1009 	zend_hash_init(&event_properties, 2, NULL, free_prop_handler, 1);
1010 	PHP_EVENT_ADD_CLASS_PROPERTIES(&event_properties, event_property_entries);
1011 	PHP_EVENT_DECL_PROP_NULL(ce, pending, ZEND_ACC_PUBLIC);
1012 	PHP_EVENT_DECL_PROP_NULL(ce, data,    ZEND_ACC_PUBLIC);
1013 	zend_hash_add_ptr(&classes, ce->name, &event_properties);
1014 
1015 	PHP_EVENT_REGISTER_CLASS("EventBase", event_base_object_create, php_event_base_ce,
1016 			php_event_base_ce_functions);
1017 	ce = php_event_base_ce;
1018 	ce->ce_flags |= ZEND_ACC_FINAL;
1019 
1020 	PHP_EVENT_REGISTER_CLASS("EventConfig", event_config_object_create, php_event_config_ce,
1021 			php_event_config_ce_functions);
1022 	ce = php_event_config_ce;
1023 	ce->ce_flags |= ZEND_ACC_FINAL;
1024 
1025 	PHP_EVENT_REGISTER_CLASS("EventBufferEvent", event_bevent_object_create, php_event_bevent_ce,
1026 			php_event_bevent_ce_functions);
1027 	ce = php_event_bevent_ce;
1028 	ce->ce_flags |= ZEND_ACC_FINAL;
1029 	zend_hash_init(&event_bevent_properties, 4, NULL, free_prop_handler, 1);
1030 	PHP_EVENT_ADD_CLASS_PROPERTIES(&event_bevent_properties, event_bevent_property_entries);
1031 	PHP_EVENT_DECL_PROP_NULL(ce, priority, ZEND_ACC_PUBLIC);
1032 	PHP_EVENT_DECL_PROP_NULL(ce, fd,       ZEND_ACC_PUBLIC);
1033 	PHP_EVENT_DECL_PROP_NULL(ce, input,    ZEND_ACC_PUBLIC);
1034 	PHP_EVENT_DECL_PROP_NULL(ce, output,   ZEND_ACC_PUBLIC);
1035 #if LIBEVENT_VERSION_NUMBER >= 0x02010100
1036 	PHP_EVENT_DECL_PROP_NULL(ce, allow_ssl_dirty_shutdown, ZEND_ACC_PUBLIC);
1037 #endif
1038 	zend_hash_add_ptr(&classes, ce->name, &event_bevent_properties);
1039 
1040 	PHP_EVENT_REGISTER_CLASS("EventBuffer", event_buffer_object_create, php_event_buffer_ce,
1041 			php_event_buffer_ce_functions);
1042 	ce = php_event_buffer_ce;
1043 	zend_hash_init(&event_buffer_properties, 2, NULL, free_prop_handler, 1);
1044 	PHP_EVENT_ADD_CLASS_PROPERTIES(&event_buffer_properties, event_buffer_property_entries);
1045 	PHP_EVENT_DECL_PROP_NULL(ce, length,           ZEND_ACC_PUBLIC);
1046 	PHP_EVENT_DECL_PROP_NULL(ce, contiguous_space, ZEND_ACC_PUBLIC);
1047 	zend_hash_add_ptr(&classes, ce->name, &event_buffer_properties);
1048 
1049 #if HAVE_EVENT_EXTRA_LIB
1050 	PHP_EVENT_REGISTER_CLASS("EventDnsBase", event_dns_base_object_create, php_event_dns_base_ce,
1051 			php_event_dns_base_ce_functions);
1052 	ce = php_event_dns_base_ce;
1053 	ce->ce_flags |= ZEND_ACC_FINAL;
1054 
1055 	PHP_EVENT_REGISTER_CLASS("EventListener", event_listener_object_create, php_event_listener_ce,
1056 			php_event_listener_ce_functions);
1057 	ce = php_event_listener_ce;
1058 	ce->ce_flags |= ZEND_ACC_FINAL;
1059 	zend_hash_init(&event_listener_properties, 1, NULL, free_prop_handler, 1);
1060 	PHP_EVENT_ADD_CLASS_PROPERTIES(&event_listener_properties, event_listener_property_entries);
1061 	PHP_EVENT_DECL_PROP_NULL(ce, fd, ZEND_ACC_PUBLIC);
1062 	zend_hash_add_ptr(&classes, ce->name, &event_listener_properties);
1063 
1064 	PHP_EVENT_REGISTER_CLASS("EventHttpConnection", event_http_conn_object_create,
1065 			php_event_http_conn_ce,
1066 			php_event_http_conn_ce_functions);
1067 	ce = php_event_http_conn_ce;
1068 	ce->ce_flags |= ZEND_ACC_FINAL;
1069 
1070 	PHP_EVENT_REGISTER_CLASS("EventHttp", event_http_object_create, php_event_http_ce,
1071 			php_event_http_ce_functions);
1072 	ce = php_event_http_ce;
1073 	ce->ce_flags |= ZEND_ACC_FINAL;
1074 
1075 	PHP_EVENT_REGISTER_CLASS("EventHttpRequest", event_http_req_object_create, php_event_http_req_ce,
1076 			php_event_http_req_ce_functions);
1077 	ce = php_event_http_req_ce;
1078 	ce->ce_flags |= ZEND_ACC_FINAL;
1079 #endif /* HAVE_EVENT_EXTRA_LIB */
1080 
1081 	PHP_EVENT_REGISTER_CLASS("EventUtil", event_zend_objects_new, php_event_util_ce,
1082 			php_event_util_ce_functions);
1083 	ce = php_event_util_ce;
1084 	ce->ce_flags |= ZEND_ACC_FINAL;
1085 
1086 #ifdef HAVE_EVENT_OPENSSL_LIB
1087 	PHP_EVENT_REGISTER_CLASS("EventSslContext", event_ssl_context_object_create,
1088 			php_event_ssl_context_ce,
1089 			php_event_ssl_context_ce_functions);
1090 	ce = php_event_ssl_context_ce;
1091 	ce->ce_flags |= ZEND_ACC_FINAL;
1092 	zend_hash_init(&event_ssl_context_properties, 2, NULL, free_prop_handler, 1);
1093 	PHP_EVENT_ADD_CLASS_PROPERTIES(&event_ssl_context_properties, event_ssl_context_property_entries);
1094 	PHP_EVENT_DECL_PROP_NULL(ce, local_cert, ZEND_ACC_PUBLIC);
1095 	PHP_EVENT_DECL_PROP_NULL(ce, local_pk,   ZEND_ACC_PUBLIC);
1096 	zend_hash_add_ptr(&classes, ce->name, &event_ssl_context_properties);
1097 #endif /* HAVE_EVENT_OPENSSL_LIB */
1098 
1099 #ifdef PHP_EVENT_NS
1100 	INIT_NS_CLASS_ENTRY(ce_exception, PHP_EVENT_NS, "EventException", NULL);
1101 #else
1102 	INIT_CLASS_ENTRY(ce_exception, "EventException", NULL);
1103 #endif
1104 
1105 	php_event_exception_ce = zend_register_internal_class_ex(&ce_exception, php_event_get_exception_base(0));
1106 	zend_declare_property_null(php_event_exception_ce, "errorInfo", sizeof("errorInfo") - 1, ZEND_ACC_PUBLIC);
1107 }/*}}}*/
1108 
1109 /* Private functions }}} */
1110 
1111 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(event)1112 PHP_MINIT_FUNCTION(event)
1113 {
1114 	memcpy(&event_event_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1115 	PHP_EVENT_SET_X_OBJ_HANDLERS(event);
1116 
1117 #define PHP_EVENT_INIT_X_OBJ_HANDLERS(x) do { \
1118 	memcpy(&PHP_EVENT_X_OBJ_HANDLERS(x), zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
1119 	PHP_EVENT_SET_X_OBJ_HANDLERS(x); \
1120 } while (0)
1121 
1122 	PHP_EVENT_INIT_X_OBJ_HANDLERS(base);
1123 	PHP_EVENT_INIT_X_OBJ_HANDLERS(config);
1124 	PHP_EVENT_INIT_X_OBJ_HANDLERS(bevent);
1125 	PHP_EVENT_INIT_X_OBJ_HANDLERS(buffer);
1126 #if HAVE_EVENT_EXTRA_LIB
1127 	PHP_EVENT_INIT_X_OBJ_HANDLERS(dns_base);
1128 	PHP_EVENT_INIT_X_OBJ_HANDLERS(listener);
1129 	PHP_EVENT_INIT_X_OBJ_HANDLERS(http_conn);
1130 	PHP_EVENT_INIT_X_OBJ_HANDLERS(http);
1131 	PHP_EVENT_INIT_X_OBJ_HANDLERS(http_req);
1132 #endif
1133 #if 0
1134 	PHP_EVENT_INIT_X_OBJ_HANDLERS(util);
1135 #else
1136 	memcpy(&PHP_EVENT_X_OBJ_HANDLERS(util), zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1137 	PHP_EVENT_X_OBJ_HANDLERS(util).clone_obj = NULL;
1138 #if 0
1139 	PHP_EVENT_X_OBJ_HANDLERS(util).get_gc    = get_gc;
1140 #endif
1141 #endif
1142 #ifdef HAVE_EVENT_OPENSSL_LIB
1143 	PHP_EVENT_INIT_X_OBJ_HANDLERS(ssl_context);
1144 #endif
1145 
1146 #ifdef PHP_EVENT_NS
1147 	REGISTER_STRING_CONSTANT("EVENT_NS", PHP_EVENT_NS, CONST_CS | CONST_PERSISTENT);
1148 #else
1149 	REGISTER_STRING_CONSTANT("EVENT_NS", "", CONST_CS | CONST_PERSISTENT);
1150 #endif
1151 
1152 	zend_hash_init(&classes, 4, NULL, NULL, 1);
1153 	register_classes();
1154 
1155 	/* Loop flags */
1156 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_base_ce, LOOP_ONCE,     EVLOOP_ONCE);
1157 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_base_ce, LOOP_NONBLOCK, EVLOOP_NONBLOCK);
1158 
1159 	/* Run-time flags of event base usually passed to event_config_set_flag */
1160 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_base_ce, NOLOCK,               EVENT_BASE_FLAG_NOLOCK);
1161 #if LIBEVENT_VERSION_NUMBER >= 0x02000301
1162 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_base_ce, STARTUP_IOCP,         EVENT_BASE_FLAG_STARTUP_IOCP);
1163 #endif
1164 #if LIBEVENT_VERSION_NUMBER >= 0x02000901
1165 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_base_ce, NO_CACHE_TIME,        EVENT_BASE_FLAG_NO_CACHE_TIME);
1166 #endif
1167 #if LIBEVENT_VERSION_NUMBER >= 0x02000301
1168 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_base_ce, EPOLL_USE_CHANGELIST, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
1169 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_base_ce, IGNORE_ENV,           EVENT_BASE_FLAG_IGNORE_ENV);
1170 #endif
1171 #if LIBEVENT_VERSION_NUMBER >= 0x02010201
1172 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_base_ce, PRECISE_TIMER,        EVENT_BASE_FLAG_PRECISE_TIMER);
1173 #endif
1174 
1175 	/* Event flags */
1176 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ce, ET,      EV_ET);
1177 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ce, PERSIST, EV_PERSIST);
1178 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ce, READ,    EV_READ);
1179 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ce, WRITE,   EV_WRITE);
1180 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ce, SIGNAL,  EV_SIGNAL);
1181 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ce, TIMEOUT, EV_TIMEOUT);
1182 
1183 	/* Features of event_base usually passed to event_config_require_features */
1184 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_config_ce, FEATURE_ET,  EV_FEATURE_ET);
1185 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_config_ce, FEATURE_O1,  EV_FEATURE_O1);
1186 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_config_ce, FEATURE_FDS, EV_FEATURE_FDS);
1187 
1188 	/* Buffer event flags */
1189 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, READING,   BEV_EVENT_READING);
1190 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, WRITING,   BEV_EVENT_WRITING);
1191 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, EOF,       BEV_EVENT_EOF);
1192 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, ERROR,     BEV_EVENT_ERROR);
1193 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, TIMEOUT,   BEV_EVENT_TIMEOUT);
1194 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, CONNECTED, BEV_EVENT_CONNECTED);
1195 
1196 	/* Option flags for bufferevents */
1197 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, OPT_CLOSE_ON_FREE,    BEV_OPT_CLOSE_ON_FREE);
1198 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, OPT_THREADSAFE,       BEV_OPT_THREADSAFE);
1199 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, OPT_DEFER_CALLBACKS,  BEV_OPT_DEFER_CALLBACKS);
1200 #if LIBEVENT_VERSION_NUMBER >= 0x02000500
1201 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, OPT_UNLOCK_CALLBACKS, BEV_OPT_UNLOCK_CALLBACKS);
1202 #endif
1203 #ifdef HAVE_EVENT_OPENSSL_LIB
1204 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, SSL_OPEN,       BUFFEREVENT_SSL_OPEN);
1205 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, SSL_CONNECTING, BUFFEREVENT_SSL_CONNECTING);
1206 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_bevent_ce, SSL_ACCEPTING,  BUFFEREVENT_SSL_ACCEPTING);
1207 #endif
1208 
1209 	/* Address families */
1210 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, AF_INET,   AF_INET);
1211 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, AF_INET6,  AF_INET6);
1212 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, AF_UNIX,   AF_UNIX);
1213 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, AF_UNSPEC, AF_UNSPEC);
1214 
1215 	/* Socket options */
1216 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_DEBUG,     SO_DEBUG);
1217 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_REUSEADDR, SO_REUSEADDR);
1218 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_KEEPALIVE, SO_KEEPALIVE);
1219 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_DONTROUTE, SO_DONTROUTE);
1220 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_LINGER,    SO_LINGER);
1221 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_BROADCAST, SO_BROADCAST);
1222 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_OOBINLINE, SO_OOBINLINE);
1223 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_SNDBUF,    SO_SNDBUF);
1224 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_RCVBUF,    SO_RCVBUF);
1225 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_SNDLOWAT,  SO_SNDLOWAT);
1226 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_RCVLOWAT,  SO_RCVLOWAT);
1227 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_SNDTIMEO,  SO_SNDTIMEO);
1228 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_RCVTIMEO,  SO_RCVTIMEO);
1229 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_TYPE,      SO_TYPE);
1230 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SO_ERROR,     SO_ERROR);
1231 #ifdef TCP_NODELAY
1232 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, TCP_NODELAY, TCP_NODELAY);
1233 #endif
1234 
1235 	/* Socket protocol levels */
1236 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SOL_SOCKET, SOL_SOCKET);
1237 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SOL_TCP,    IPPROTO_TCP);
1238 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SOL_UDP,    IPPROTO_UDP);
1239 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, SOCK_RAW,   SOCK_RAW);
1240 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, IPPROTO_IP, IPPROTO_IP);
1241 #if HAVE_IPV6
1242 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, IPPROTO_IPV6, IPPROTO_IPV6);
1243 #endif
1244 
1245 
1246 #ifdef HAVE_EVENT_EXTRA_LIB
1247 	/* DNS options */
1248 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_dns_base_ce, OPTION_SEARCH,      DNS_OPTION_SEARCH);
1249 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_dns_base_ce, OPTION_NAMESERVERS, DNS_OPTION_NAMESERVERS);
1250 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_dns_base_ce, OPTION_MISC,        DNS_OPTION_MISC);
1251 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_dns_base_ce, OPTION_HOSTSFILE,   DNS_OPTION_HOSTSFILE);
1252 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_dns_base_ce, OPTIONS_ALL,        DNS_OPTIONS_ALL);
1253 
1254 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_listener_ce, OPT_LEAVE_SOCKETS_BLOCKING, LEV_OPT_LEAVE_SOCKETS_BLOCKING);
1255 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_listener_ce, OPT_CLOSE_ON_FREE,          LEV_OPT_CLOSE_ON_FREE);
1256 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_listener_ce, OPT_CLOSE_ON_EXEC,          LEV_OPT_CLOSE_ON_EXEC);
1257 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_listener_ce, OPT_REUSEABLE,              LEV_OPT_REUSEABLE);
1258 # if LIBEVENT_VERSION_NUMBER >= 0x02010100
1259 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_listener_ce, OPT_DISABLED,               LEV_OPT_DISABLED);
1260 # endif
1261 # if LIBEVENT_VERSION_NUMBER >= 0x02000800
1262 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_listener_ce, OPT_THREADSAFE,             LEV_OPT_THREADSAFE);
1263 #endif
1264 # if LIBEVENT_VERSION_NUMBER >= 0x02010100
1265 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_listener_ce, OPT_DEFERRED_ACCEPT,        LEV_OPT_DEFERRED_ACCEPT);
1266 # endif
1267 
1268 	/* EventHttpRequest command types */
1269 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_GET,     EVHTTP_REQ_GET);
1270 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_POST,    EVHTTP_REQ_POST);
1271 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_HEAD,    EVHTTP_REQ_HEAD);
1272 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_PUT,     EVHTTP_REQ_PUT);
1273 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_DELETE,  EVHTTP_REQ_DELETE);
1274 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_OPTIONS, EVHTTP_REQ_OPTIONS);
1275 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_TRACE,   EVHTTP_REQ_TRACE);
1276 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_CONNECT, EVHTTP_REQ_CONNECT);
1277 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, CMD_PATCH,   EVHTTP_REQ_PATCH);
1278 
1279 	/* EventHttpRequest header types */
1280 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, INPUT_HEADER,  PHP_EVENT_REQ_HEADER_INPUT);
1281 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_http_req_ce, OUTPUT_HEADER, PHP_EVENT_REQ_HEADER_OUTPUT);
1282 
1283 #endif /* HAVE_EVENT_EXTRA_LIB */
1284 
1285 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_util_ce, LIBEVENT_VERSION_NUMBER, LIBEVENT_VERSION_NUMBER);
1286 
1287 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_buffer_ce, EOL_ANY,         EVBUFFER_EOL_ANY);
1288 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_buffer_ce, EOL_CRLF,        EVBUFFER_EOL_CRLF);
1289 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_buffer_ce, EOL_CRLF_STRICT, EVBUFFER_EOL_CRLF_STRICT);
1290 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_buffer_ce, EOL_LF,          EVBUFFER_EOL_LF);
1291 #if LIBEVENT_VERSION_NUMBER >= 0x02010100
1292 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_buffer_ce, EOL_NUL,         EVBUFFER_EOL_NUL);
1293 #endif
1294 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_buffer_ce, PTR_SET,         EVBUFFER_PTR_SET);
1295 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_buffer_ce, PTR_ADD,         EVBUFFER_PTR_ADD);
1296 
1297 #ifdef HAVE_EVENT_OPENSSL_LIB
1298 # ifdef HAVE_SSL2
1299 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, SSLv2_CLIENT_METHOD,  PHP_EVENT_SSLv2_CLIENT_METHOD);
1300 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, SSLv2_SERVER_METHOD,  PHP_EVENT_SSLv2_SERVER_METHOD);
1301 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, SSLv23_CLIENT_METHOD, PHP_EVENT_SSLv23_CLIENT_METHOD);
1302 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, SSLv23_SERVER_METHOD, PHP_EVENT_SSLv23_SERVER_METHOD);
1303 # endif
1304 # ifdef HAVE_SSL3
1305 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, SSLv3_CLIENT_METHOD,  PHP_EVENT_SSLv3_CLIENT_METHOD);
1306 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, SSLv3_SERVER_METHOD,  PHP_EVENT_SSLv3_SERVER_METHOD);
1307 # endif
1308 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLS_CLIENT_METHOD,    PHP_EVENT_TLS_CLIENT_METHOD);
1309 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLS_SERVER_METHOD,    PHP_EVENT_TLS_SERVER_METHOD);
1310 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLSv11_CLIENT_METHOD, PHP_EVENT_TLSv11_CLIENT_METHOD);
1311 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLSv11_SERVER_METHOD, PHP_EVENT_TLSv11_SERVER_METHOD);
1312 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLSv12_CLIENT_METHOD, PHP_EVENT_TLSv12_CLIENT_METHOD);
1313 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLSv12_SERVER_METHOD, PHP_EVENT_TLSv12_SERVER_METHOD);
1314 
1315 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_LOCAL_CERT,               PHP_EVENT_OPT_LOCAL_CERT);
1316 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_LOCAL_PK,                 PHP_EVENT_OPT_LOCAL_PK);
1317 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_PASSPHRASE,               PHP_EVENT_OPT_PASSPHRASE);
1318 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_CA_FILE,                  PHP_EVENT_OPT_CA_FILE);
1319 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_CA_PATH,                  PHP_EVENT_OPT_CA_PATH);
1320 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_ALLOW_SELF_SIGNED,        PHP_EVENT_OPT_ALLOW_SELF_SIGNED);
1321 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_VERIFY_PEER,              PHP_EVENT_OPT_VERIFY_PEER);
1322 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_VERIFY_DEPTH,             PHP_EVENT_OPT_VERIFY_DEPTH);
1323 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_CIPHERS,                  PHP_EVENT_OPT_CIPHERS);
1324 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_NO_SSLv2,                 PHP_EVENT_OPT_NO_SSLv2);
1325 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_NO_SSLv3,                 PHP_EVENT_OPT_NO_SSLv3);
1326 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_NO_TLSv1,                 PHP_EVENT_OPT_NO_TLSv1);
1327 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_NO_TLSv1_1,               PHP_EVENT_OPT_NO_TLSv1_1);
1328 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_NO_TLSv1_2,               PHP_EVENT_OPT_NO_TLSv1_2);
1329 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_CIPHER_SERVER_PREFERENCE, PHP_EVENT_OPT_CIPHER_SERVER_PREFERENCE);
1330 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_REQUIRE_CLIENT_CERT,      PHP_EVENT_OPT_REQUIRE_CLIENT_CERT);
1331 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, OPT_VERIFY_CLIENT_ONCE,       PHP_EVENT_OPT_VERIFY_CLIENT_ONCE);
1332 
1333 	PHP_EVENT_REG_CLASS_CONST_STRING(php_event_ssl_context_ce, OPENSSL_VERSION_TEXT,       OPENSSL_VERSION_TEXT);
1334 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce,   OPENSSL_VERSION_NUMBER,     OPENSSL_VERSION_NUMBER);
1335 #ifdef LIBRESSL_VERSION_NUMBER
1336 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce,   LIBRESSL_VERSION_NUMBER,     LIBRESSL_VERSION_NUMBER);
1337 #endif
1338 #ifdef LIBRESSL_VERSION_TEXT
1339 	PHP_EVENT_REG_CLASS_CONST_STRING(php_event_ssl_context_ce, LIBRESSL_VERSION_TEXT,       LIBRESSL_VERSION_TEXT);
1340 #endif
1341 
1342 
1343 	/* Constants for EventSslContext::setMinProtoVersion */
1344 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
1345 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, SSL3_VERSION,    SSL3_VERSION);
1346 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLS1_VERSION,    TLS1_VERSION);
1347 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLS1_1_VERSION,  TLS1_1_VERSION);
1348 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, TLS1_2_VERSION,  TLS1_2_VERSION);
1349 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, DTLS1_VERSION,   DTLS1_VERSION);
1350 # ifdef DTLS1_2_VERSION /* May be missing in libressl*/
1351 	PHP_EVENT_REG_CLASS_CONST_LONG(php_event_ssl_context_ce, DTLS1_2_VERSION, DTLS1_2_VERSION);
1352 # endif
1353 #endif
1354 
1355 	/* Initialize openssl library */
1356 	SSL_load_error_strings();
1357 	SSL_library_init();
1358 	OpenSSL_add_all_ciphers();
1359 	OpenSSL_add_all_digests();
1360 	OpenSSL_add_all_algorithms();
1361 
1362 	/* Create new index which will be used to retreive custom data of the OpenSSL callbacks */
1363 	php_event_ssl_data_index = SSL_get_ex_new_index(0, "PHP EventSslContext index", NULL, NULL, NULL);
1364 #endif /* HAVE_EVENT_OPENSSL_LIB */
1365 
1366 #ifdef PHP_EVENT_DEBUG
1367 	event_enable_debug_mode();
1368 #endif
1369 
1370 #ifdef HAVE_EVENT_PTHREADS_LIB
1371 # ifdef WIN32
1372 	evthread_use_windows_threads();
1373 # else
1374 	if (evthread_use_pthreads()) {
1375 		php_error_docref(NULL, E_ERROR,
1376 				"evthread_use_pthreads failed, submit a bug");
1377 	}
1378 # endif
1379 #endif /* HAVE_EVENT_PTHREADS_LIB */
1380 
1381 	/* Handle libevent's error logging more gracefully than it's default
1382 	 * logging to stderr, or calling abort()/exit() */
1383 	event_set_fatal_callback(fatal_error_cb);
1384 	event_set_log_callback(log_cb);
1385 
1386 
1387 	return SUCCESS;
1388 }
1389 /* }}} */
1390 
1391 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(event)1392 PHP_MSHUTDOWN_FUNCTION(event)
1393 {
1394 #ifdef HAVE_EVENT_OPENSSL_LIB
1395 	CONF_modules_unload(1);
1396 	/* Removes memory allocated when loading digest and cipher names
1397 	 * in the OpenSSL_add_all_ family of functions */
1398 	EVP_cleanup();
1399 	CRYPTO_cleanup_all_ex_data();
1400 # if OPENSSL_VERSION_NUMBER >= 0x10100000L
1401 	/* No need in ERR_remove_thread_state, or ERR_remove_state, since OpenSSL
1402 	 * do all thread initialisation/deinitialisation automatically */
1403 # elif OPENSSL_VERSION_NUMBER >= 0x10000000L
1404 	ERR_remove_thread_state(NULL);
1405 # else
1406 	ERR_remove_state(0);
1407 # endif
1408 	ERR_free_strings();
1409 #endif /* HAVE_EVENT_OPENSSL_LIB */
1410 
1411 #if LIBEVENT_VERSION_NUMBER >= 0x02010000
1412 	/* libevent_global_shutdown is available since libevent 2.1.0-alpha.
1413 	 *
1414 	 * Make sure that libevent has released all internal library-global data
1415 	 * structures. Don't call any of libevent functions below! */
1416 	libevent_global_shutdown();
1417 #endif
1418 
1419 	zend_hash_destroy(&event_properties);
1420 	zend_hash_destroy(&event_bevent_properties);
1421 	zend_hash_destroy(&event_buffer_properties);
1422 	zend_hash_destroy(&event_listener_properties);
1423 #ifdef HAVE_EVENT_OPENSSL_LIB
1424 	zend_hash_destroy(&event_ssl_context_properties);
1425 #endif
1426 
1427 	zend_hash_destroy(&classes);
1428 
1429 	return SUCCESS;
1430 }
1431 /* }}} */
1432 
1433 /*{{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(event)1434 PHP_RINIT_FUNCTION(event)
1435 {
1436 #if defined(COMPILE_DL_EVENT) && defined(ZTS)
1437 	ZEND_TSRMLS_CACHE_UPDATE();
1438 #endif
1439 	return SUCCESS;
1440 }
1441 /*}}}*/
1442 
1443 /*{{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(event)1444 PHP_RSHUTDOWN_FUNCTION(event)
1445 {
1446 	return SUCCESS;
1447 }
1448 /*}}}*/
1449 
1450 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(event)1451 PHP_MINFO_FUNCTION(event)
1452 {
1453 	php_info_print_table_start();
1454 	php_info_print_table_header(2, "Event support", "enabled");
1455 #ifdef PHP_EVENT_SOCKETS_SUPPORT
1456 	php_info_print_table_header(2, "Sockets support", "enabled");
1457 #else
1458 	php_info_print_table_header(2, "Sockets support", "disabled");
1459 #endif
1460 #ifdef PHP_EVENT_DEBUG
1461 	php_info_print_table_row(2, "Debug support", "enabled");
1462 #else
1463 	php_info_print_table_row(2, "Debug support", "disabled");
1464 #endif
1465 #ifdef HAVE_EVENT_EXTRA_LIB
1466 	php_info_print_table_row(2, "Extra functionality support including HTTP, DNS, and RPC", "enabled");
1467 #else
1468 	php_info_print_table_row(2, "Extra functionality support including HTTP, DNS, and RPC", "disabled");
1469 #endif
1470 #ifdef HAVE_EVENT_OPENSSL_LIB
1471 	php_info_print_table_row(2, "OpenSSL support", "enabled");
1472 #else
1473 	php_info_print_table_row(2, "OpenSSL support", "disabled");
1474 #endif
1475 #ifdef HAVE_EVENT_PTHREADS_LIB
1476 	php_info_print_table_row(2, "Thread safety support", "enabled");
1477 #else
1478 	php_info_print_table_row(2, "Thread safety support", "disabled");
1479 #endif
1480 
1481 
1482 	php_info_print_table_row(2, "Extension version", PHP_EVENT_VERSION);
1483 	php_info_print_table_row(2, "libevent2 headers version", LIBEVENT_VERSION);
1484 	php_info_print_table_end();
1485 }
1486 /* }}} */
1487 
1488 /*
1489  * Local variables:
1490  * tab-width: 4
1491  * c-basic-offset: 4
1492  * End:
1493  * vim600: noet sw=4 ts=4 sts=4 fdm=marker
1494  * vim<600: noet sw=4 ts=4 sts=4
1495  */
1496