From 1b6d14d4038672f649263371f117398bab15c28d Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Wed, 24 Aug 2016 13:50:14 -0700 Subject: [PATCH] PHP7 Compat Retains PHP5 compat through several ifdef checks for ZEND_ENGINE_2/ZEND_ENGINE_3 When we're ready to drop PHP5 support, this code can be cleaned up noticably. --- mosquitto.c | 576 ++++++++++++++--------- mosquitto_message.c | 278 ++++++++--- php_mosquitto.h | 84 +++- tests/Client/connect.phpt | 4 +- tests/Client/onConnect.phpt | 7 +- tests/Client/onDisconnect.phpt | 7 +- tests/Client/onLog.phpt | 7 +- tests/Client/onMessage.phpt | 9 +- tests/Client/onSubscribe.phpt | 7 +- tests/Client/onUnsubscribe.phpt | 7 +- tests/Client/publish.phpt | 2 +- tests/Client/setMaxInFlightMessages.phpt | 4 +- tests/Client/setMessageRetry.phpt | 4 +- tests/Client/setReconnectDelay.phpt | 4 +- tests/Client/setTlsOptions.phpt | 2 +- tests/Client/subscribe.phpt | 2 +- tests/Message/__construct.phpt | 6 +- tests/setup.php | 5 + 18 files changed, 685 insertions(+), 330 deletions(-) diff --git a/mosquitto.c b/mosquitto.c index be64b47..5b8ce48 100644 --- a/mosquitto.c +++ b/mosquitto.c @@ -17,7 +17,56 @@ zend_object_handlers mosquitto_std_object_handlers; ZEND_DECLARE_MODULE_GLOBALS(mosquitto) -static inline mosquitto_client_object *mosquitto_client_object_get(zval *zobj TSRMLS_DC); +#ifdef ZEND_ENGINE_3 +# ifndef Z_BVAL +# define Z_BVAL(zv) (Z_TYPE(zv) == IS_TRUE) +# define Z_BVAL_P(pzv) Z_BVAL(*pzv) +# endif +# define ZO_HANDLE_DC +typedef size_t mosquitto_strlen_type; +#else /* ZEND_ENGINE_2 */ +# ifndef Z_OBJ_P +# define Z_OBJ_P(pzv) ((zend_object*)zend_object_store_get_object(pzv TSRMLS_CC)) +# endif +# define ZO_HANDLE_DC , zend_object_handle handle +typedef int mosquitto_strlen_type; +typedef long zend_long; +#endif + +static inline mosquitto_client_object *mosquitto_client_object_get(zval *zobj TSRMLS_DC) { + // TODO: ZEND_ASSERT()s + mosquitto_client_object *obj = mosquitto_client_object_from_zend_object(Z_OBJ_P(zobj)); + if (!obj->client) { + php_error(E_ERROR, "Internal surface object missing in %s wrapper, " + "you must call parent::__construct in extended classes", Z_OBJCE_P(zobj)->name); + } + return obj; +} + +static inline void mosquitto_callback_addref(zend_fcall_info *finfo) { +#ifdef ZEND_ENGINE_3 + zval tmp; + Z_TRY_ADDREF(finfo->function_name); + if (finfo->object) { + ZVAL_OBJ(&tmp, finfo->object); + Z_TRY_ADDREF(tmp); + } +#else + Z_ADDREF_P(finfo->function_name); + if (finfo->object_ptr) { + Z_ADDREF_P(finfo->object_ptr); + } +#endif +} + +static inline const char *mosquitto_finfo_name(zend_fcall_info *info) { +#ifdef ZEND_ENGINE_3 + return Z_STRVAL(info->function_name); +#else + return Z_STRVAL_P(info->function_name); +#endif +} + static int php_mosquitto_pw_callback(char *buf, int size, int rwflag, void *userdata); /* {{{ Arginfo */ @@ -99,9 +148,9 @@ ZEND_END_ARG_INFO() /* {{{ Mosquitto\Client::__construct() */ PHP_METHOD(Mosquitto_Client, __construct) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); char *id = NULL; - int id_len = 0; + mosquitto_strlen_type id_len = 0; zend_bool clean_session = 1; PHP_MOSQUITTO_ERROR_HANDLING(); @@ -111,17 +160,13 @@ PHP_METHOD(Mosquitto_Client, __construct) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) zend_object_store_get_object(getThis() TSRMLS_CC); object->client = mosquitto_new(id, clean_session, object); - if (!object->client) { char *message = php_mosquitto_strerror_wrapper(errno); zend_throw_exception(mosquitto_ce_exception, message, 1 TSRMLS_CC); -#ifndef STRERROR_R_CHAR_P - if (message != NULL) { + if (message) { efree(message); } -#endif } } /* }}} */ @@ -129,9 +174,10 @@ PHP_METHOD(Mosquitto_Client, __construct) /* {{{ Mosquitto\Client::setTlsCertificates() */ PHP_METHOD(Mosquitto_Client, setTlsCertificates) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); char *ca_path = NULL, *cert_path = NULL, *key_path = NULL, *key_pw = NULL; - int ca_path_len = 0, cert_path_len = 0, key_path_len = 0, key_pw_len, retval = 0; + mosquitto_strlen_type ca_path_len = 0, cert_path_len = 0, key_path_len = 0, key_pw_len; + int retval = 0; zval stat; zend_bool is_dir = 0; int (*pw_callback)(char *, int, int, void *) = NULL; @@ -156,8 +202,6 @@ PHP_METHOD(Mosquitto_Client, setTlsCertificates) PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) zend_object_store_get_object(getThis() TSRMLS_CC); - php_stat(ca_path, ca_path_len, FS_IS_DIR, &stat TSRMLS_CC); is_dir = Z_BVAL(stat); @@ -181,7 +225,7 @@ PHP_METHOD(Mosquitto_Client, setTlsCertificates) /* {{{ Mosquitto\Client::setTlsInsecure() */ PHP_METHOD(Mosquitto_Client, setTlsInsecure) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); zend_bool value = 0; int retval = 0; @@ -192,8 +236,6 @@ PHP_METHOD(Mosquitto_Client, setTlsInsecure) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) zend_object_store_get_object(getThis() TSRMLS_CC); - retval = mosquitto_tls_insecure_set(object->client, value); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -203,10 +245,10 @@ PHP_METHOD(Mosquitto_Client, setTlsInsecure) /* {{{ Mosquitto\Client::setTlsOptions() */ PHP_METHOD(Mosquitto_Client, setTlsOptions) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); char *tls_version = NULL, *ciphers = NULL; - int tls_version_len = 0, ciphers_len = 0, retval = 0; - int verify_peer = 0; + mosquitto_strlen_type tls_version_len = 0, ciphers_len = 0; + int retval = 0, verify_peer = 0; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s!s!", @@ -219,8 +261,6 @@ PHP_METHOD(Mosquitto_Client, setTlsOptions) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) zend_object_store_get_object(getThis() TSRMLS_CC); - retval = mosquitto_tls_opts_set(object->client, verify_peer, tls_version, ciphers); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -231,9 +271,10 @@ PHP_METHOD(Mosquitto_Client, setTlsOptions) /* {{{ Mosquitto\Client::setTlsPSK() */ PHP_METHOD(Mosquitto_Client, setTlsPSK) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); char *psk = NULL, *identity = NULL, *ciphers = NULL; - int psk_len = 0, identity_len = 0, ciphers_len = 0, retval = 0; + mosquitto_strlen_type psk_len = 0, identity_len = 0, ciphers_len = 0; + int retval = 0; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!s!|s!", @@ -244,8 +285,6 @@ PHP_METHOD(Mosquitto_Client, setTlsPSK) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) zend_object_store_get_object(getThis() TSRMLS_CC); - retval = mosquitto_tls_psk_set(object->client, psk, identity, ciphers); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -256,9 +295,10 @@ PHP_METHOD(Mosquitto_Client, setTlsPSK) /* {{{ Mosquitto\Client::setCredentials() */ PHP_METHOD(Mosquitto_Client, setCredentials) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); char *username = NULL, *password = NULL; - int username_len, password_len, retval; + mosquitto_strlen_type username_len, password_len; + int retval; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &username, &username_len, &password, &password_len) == FAILURE) { @@ -267,7 +307,6 @@ PHP_METHOD(Mosquitto_Client, setCredentials) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_username_pw_set(object->client, username, password); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); } @@ -276,9 +315,10 @@ PHP_METHOD(Mosquitto_Client, setCredentials) /* {{{ Mosquitto\Client::setWill() */ PHP_METHOD(Mosquitto_Client, setWill) { - mosquitto_client_object *object; - int topic_len, payload_len, retval; - long qos; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); + mosquitto_strlen_type topic_len, payload_len; + int retval; + zend_long qos; zend_bool retain; char *topic, *payload; @@ -290,7 +330,6 @@ PHP_METHOD(Mosquitto_Client, setWill) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_will_set(object->client, topic, payload_len, (void *) payload, qos, retain); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -300,7 +339,7 @@ PHP_METHOD(Mosquitto_Client, setWill) /* {{{ Mosquitto\Client::clearWill() */ PHP_METHOD(Mosquitto_Client, clearWill) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); int retval; PHP_MOSQUITTO_ERROR_HANDLING(); @@ -310,7 +349,6 @@ PHP_METHOD(Mosquitto_Client, clearWill) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_will_clear(object->client); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -320,9 +358,9 @@ PHP_METHOD(Mosquitto_Client, clearWill) /* {{{ Mosquitto\Client::setReconnectDelay() */ PHP_METHOD(Mosquitto_Client, setReconnectDelay) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); int retval; - long reconnect_delay = 0, reconnect_delay_max = 0; + zend_long reconnect_delay = 0, reconnect_delay_max = 0; zend_bool exponential_backoff = 0; PHP_MOSQUITTO_ERROR_HANDLING(); @@ -333,7 +371,6 @@ PHP_METHOD(Mosquitto_Client, setReconnectDelay) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_reconnect_delay_set(object->client, reconnect_delay, reconnect_delay_max, exponential_backoff); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -343,11 +380,12 @@ PHP_METHOD(Mosquitto_Client, setReconnectDelay) /* {{{ Mosquitto\Client::connect() */ PHP_METHOD(Mosquitto_Client, connect) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); char *host = NULL, *interface = NULL; - int host_len, interface_len, retval; - long port = 1883; - long keepalive = 0; + mosquitto_strlen_type host_len, interface_len; + int retval; + zend_long port = 1883; + zend_long keepalive = 0; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lls!", @@ -359,8 +397,6 @@ PHP_METHOD(Mosquitto_Client, connect) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - if (interface == NULL) { retval = mosquitto_connect(object->client, host, port, keepalive); } else { @@ -375,7 +411,7 @@ PHP_METHOD(Mosquitto_Client, connect) /* {{{ Mosquitto\Client::disconnect() */ PHP_METHOD(Mosquitto_Client, disconnect) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); int retval; PHP_MOSQUITTO_ERROR_HANDLING(); @@ -385,8 +421,6 @@ PHP_METHOD(Mosquitto_Client, disconnect) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - retval = mosquitto_disconnect(object->client); php_mosquitto_exit_loop(object); @@ -397,7 +431,7 @@ PHP_METHOD(Mosquitto_Client, disconnect) /* {{{ Mosquitto\Client::onConnect() */ PHP_METHOD(Mosquitto_Client, onConnect) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); zend_fcall_info connect_callback = empty_fcall_info; zend_fcall_info_cache connect_callback_cache = empty_fcall_info_cache; @@ -410,19 +444,14 @@ PHP_METHOD(Mosquitto_Client, onConnect) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - if (!ZEND_FCI_INITIALIZED(connect_callback)) { zend_throw_exception(mosquitto_ce_exception, "Need a valid callback", 0 TSRMLS_CC); } + PHP_MOSQUITTO_FREE_CALLBACK(object, connect); object->connect_callback = connect_callback; object->connect_callback_cache = connect_callback_cache; - Z_ADDREF_P(connect_callback.function_name); - - if (connect_callback.object_ptr != NULL) { - Z_ADDREF_P(connect_callback.object_ptr); - } + mosquitto_callback_addref(&(object->connect_callback)); mosquitto_connect_callback_set(object->client, php_mosquitto_connect_callback); } @@ -431,7 +460,7 @@ PHP_METHOD(Mosquitto_Client, onConnect) /* {{{ Mosquitto\Client::onDisconnect() */ PHP_METHOD(Mosquitto_Client, onDisconnect) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); zend_fcall_info disconnect_callback = empty_fcall_info; zend_fcall_info_cache disconnect_callback_cache = empty_fcall_info_cache; @@ -444,19 +473,14 @@ PHP_METHOD(Mosquitto_Client, onDisconnect) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - if (!ZEND_FCI_INITIALIZED(disconnect_callback)) { zend_throw_exception(mosquitto_ce_exception, "Need a valid callback", 0 TSRMLS_CC); } + PHP_MOSQUITTO_FREE_CALLBACK(object, disconnect); object->disconnect_callback = disconnect_callback; object->disconnect_callback_cache = disconnect_callback_cache; - Z_ADDREF_P(disconnect_callback.function_name); - - if (disconnect_callback.object_ptr != NULL) { - Z_ADDREF_P(disconnect_callback.object_ptr); - } + mosquitto_callback_addref(&(object->disconnect_callback)); mosquitto_disconnect_callback_set(object->client, php_mosquitto_disconnect_callback); } @@ -465,7 +489,7 @@ PHP_METHOD(Mosquitto_Client, onDisconnect) /* {{{ Mosquitto\Client::onLog() */ PHP_METHOD(Mosquitto_Client, onLog) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); zend_fcall_info log_callback = empty_fcall_info; zend_fcall_info_cache log_callback_cache = empty_fcall_info_cache; @@ -478,19 +502,14 @@ PHP_METHOD(Mosquitto_Client, onLog) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - if (!ZEND_FCI_INITIALIZED(log_callback)) { zend_throw_exception(mosquitto_ce_exception, "Need a valid callback", 0 TSRMLS_CC); } + PHP_MOSQUITTO_FREE_CALLBACK(object, log); object->log_callback = log_callback; object->log_callback_cache = log_callback_cache; - Z_ADDREF_P(log_callback.function_name); - - if (log_callback.object_ptr != NULL) { - Z_ADDREF_P(log_callback.object_ptr); - } + mosquitto_callback_addref(&(object->log_callback)); mosquitto_log_callback_set(object->client, php_mosquitto_log_callback); } @@ -499,7 +518,7 @@ PHP_METHOD(Mosquitto_Client, onLog) /* {{{ Mosquitto\Client::onSubscribe() */ PHP_METHOD(Mosquitto_Client, onSubscribe) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); zend_fcall_info subscribe_callback = empty_fcall_info; zend_fcall_info_cache subscribe_callback_cache = empty_fcall_info_cache; @@ -512,19 +531,14 @@ PHP_METHOD(Mosquitto_Client, onSubscribe) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - if (!ZEND_FCI_INITIALIZED(subscribe_callback)) { zend_throw_exception(mosquitto_ce_exception, "Need a valid callback", 0 TSRMLS_CC); } + PHP_MOSQUITTO_FREE_CALLBACK(object, subscribe); object->subscribe_callback = subscribe_callback; object->subscribe_callback_cache = subscribe_callback_cache; - Z_ADDREF_P(subscribe_callback.function_name); - - if (subscribe_callback.object_ptr != NULL) { - Z_ADDREF_P(subscribe_callback.object_ptr); - } + mosquitto_callback_addref(&(object->subscribe_callback)); mosquitto_subscribe_callback_set(object->client, php_mosquitto_subscribe_callback); } @@ -533,7 +547,7 @@ PHP_METHOD(Mosquitto_Client, onSubscribe) /* {{{ Mosquitto\Client::onUnsubscribe() */ PHP_METHOD(Mosquitto_Client, onUnsubscribe) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); zend_fcall_info unsubscribe_callback = empty_fcall_info; zend_fcall_info_cache unsubscribe_callback_cache = empty_fcall_info_cache; @@ -546,19 +560,14 @@ PHP_METHOD(Mosquitto_Client, onUnsubscribe) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - if (!ZEND_FCI_INITIALIZED(unsubscribe_callback)) { zend_throw_exception(mosquitto_ce_exception, "Need a valid callback", 0 TSRMLS_CC); } + PHP_MOSQUITTO_FREE_CALLBACK(object, unsubscribe); object->unsubscribe_callback = unsubscribe_callback; object->unsubscribe_callback_cache = unsubscribe_callback_cache; - Z_ADDREF_P(unsubscribe_callback.function_name); - - if (unsubscribe_callback.object_ptr != NULL) { - Z_ADDREF_P(unsubscribe_callback.object_ptr); - } + mosquitto_callback_addref(&(object->unsubscribe_callback)); mosquitto_unsubscribe_callback_set(object->client, php_mosquitto_unsubscribe_callback); } @@ -567,7 +576,7 @@ PHP_METHOD(Mosquitto_Client, onUnsubscribe) /* {{{ Mosquitto\Client::onMessage() */ PHP_METHOD(Mosquitto_Client, onMessage) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); zend_fcall_info message_callback = empty_fcall_info; zend_fcall_info_cache message_callback_cache = empty_fcall_info_cache; @@ -580,19 +589,14 @@ PHP_METHOD(Mosquitto_Client, onMessage) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - if (!ZEND_FCI_INITIALIZED(message_callback)) { zend_throw_exception(mosquitto_ce_exception, "Need a valid callback", 0 TSRMLS_CC); } + PHP_MOSQUITTO_FREE_CALLBACK(object, message); object->message_callback = message_callback; object->message_callback_cache = message_callback_cache; - Z_ADDREF_P(message_callback.function_name); - - if (message_callback.object_ptr != NULL) { - Z_ADDREF_P(message_callback.object_ptr); - } + mosquitto_callback_addref(&(object->message_callback)); mosquitto_message_callback_set(object->client, php_mosquitto_message_callback); } @@ -601,7 +605,7 @@ PHP_METHOD(Mosquitto_Client, onMessage) /* {{{ Mosquitto\Client::onPublish() */ PHP_METHOD(Mosquitto_Client, onPublish) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); zend_fcall_info publish_callback = empty_fcall_info; zend_fcall_info_cache publish_callback_cache = empty_fcall_info_cache; @@ -614,19 +618,14 @@ PHP_METHOD(Mosquitto_Client, onPublish) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); - if (!ZEND_FCI_INITIALIZED(publish_callback)) { zend_throw_exception(mosquitto_ce_exception, "Need a valid callback", 0 TSRMLS_CC); } + PHP_MOSQUITTO_FREE_CALLBACK(object, publish); object->publish_callback = publish_callback; object->publish_callback_cache = publish_callback_cache; - Z_ADDREF_P(publish_callback.function_name); - - if (publish_callback.object_ptr != NULL) { - Z_ADDREF_P(publish_callback.object_ptr); - } + mosquitto_callback_addref(&(object->publish_callback)); mosquitto_publish_callback_set(object->client, php_mosquitto_publish_callback); } @@ -635,7 +634,7 @@ PHP_METHOD(Mosquitto_Client, onPublish) /* {{{ Mosquitto\Client::getSocket() */ PHP_METHOD(Mosquitto_Client, getSocket) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters_none() == FAILURE) { @@ -644,7 +643,6 @@ PHP_METHOD(Mosquitto_Client, getSocket) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); RETURN_LONG(mosquitto_socket(object->client)); } /* }}} */ @@ -652,9 +650,9 @@ PHP_METHOD(Mosquitto_Client, getSocket) /* {{{ Mosquitto\Client::setMaxInFlightMessages() */ PHP_METHOD(Mosquitto_Client, setMaxInFlightMessages) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); int retval; - long max = 0; + zend_long max = 0; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &max) == FAILURE) { @@ -663,7 +661,6 @@ PHP_METHOD(Mosquitto_Client, setMaxInFlightMessages) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_max_inflight_messages_set(object->client, max); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -673,8 +670,8 @@ PHP_METHOD(Mosquitto_Client, setMaxInFlightMessages) /* {{{ Mosquitto\Client::setMessageRetry() */ PHP_METHOD(Mosquitto_Client, setMessageRetry) { - mosquitto_client_object *object; - long retry = 0; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); + zend_long retry = 0; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &retry) == FAILURE) { @@ -683,7 +680,6 @@ PHP_METHOD(Mosquitto_Client, setMessageRetry) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); mosquitto_message_retry_set(object->client, retry); } /* }}} */ @@ -691,9 +687,10 @@ PHP_METHOD(Mosquitto_Client, setMessageRetry) /* {{{ Mosquitto\Client::publish() */ PHP_METHOD(Mosquitto_Client, publish) { - mosquitto_client_object *object; - int mid, topic_len, payload_len, retval; - long qos = 0; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); + int mid, retval; + mosquitto_strlen_type topic_len, payload_len; + zend_long qos = 0; zend_bool retain = 0; char *topic, *payload; @@ -705,7 +702,6 @@ PHP_METHOD(Mosquitto_Client, publish) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_publish(object->client, &mid, topic, payload_len, (void *) payload, qos, retain); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -717,10 +713,11 @@ PHP_METHOD(Mosquitto_Client, publish) /* {{{ Mosquitto\Client::subscribe() */ PHP_METHOD(Mosquitto_Client, subscribe) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); char *sub; - int sub_len, retval, mid; - long qos; + mosquitto_strlen_type sub_len; + int retval, mid; + zend_long qos; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", @@ -730,7 +727,6 @@ PHP_METHOD(Mosquitto_Client, subscribe) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_subscribe(object->client, &mid, sub, qos); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -742,9 +738,10 @@ PHP_METHOD(Mosquitto_Client, subscribe) /* {{{ Mosquitto\Client::unsubscribe() */ PHP_METHOD(Mosquitto_Client, unsubscribe) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); char *sub; - int sub_len, retval, mid; + mosquitto_strlen_type sub_len; + int retval, mid; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", @@ -754,7 +751,6 @@ PHP_METHOD(Mosquitto_Client, unsubscribe) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_unsubscribe(object->client, &mid, sub); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); @@ -766,8 +762,9 @@ PHP_METHOD(Mosquitto_Client, unsubscribe) /* {{{ Mosquitto\Client::loop() */ PHP_METHOD(Mosquitto_Client, loop) { - mosquitto_client_object *object; - long timeout = 1000, max_packets = 1, retval = 0; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); + zend_long timeout = 1000, max_packets = 1; + long retval = 0; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", @@ -777,7 +774,6 @@ PHP_METHOD(Mosquitto_Client, loop) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); retval = mosquitto_loop(object->client, timeout, max_packets); php_mosquitto_handle_errno(retval, errno TSRMLS_CC); } @@ -786,8 +782,9 @@ PHP_METHOD(Mosquitto_Client, loop) /* {{{ Mosquitto\Client::loopForever() */ PHP_METHOD(Mosquitto_Client, loopForever) { - mosquitto_client_object *object; - long timeout = 1000, max_packets = 1, retval = 0; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); + zend_long timeout = 1000, max_packets = 1; + long retval = 0; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", @@ -797,7 +794,6 @@ PHP_METHOD(Mosquitto_Client, loopForever) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); object->looping = 1; while (object->looping) { @@ -814,7 +810,7 @@ PHP_METHOD(Mosquitto_Client, loopForever) /* {{{ Mosquitto\Client::exitLoop() */ PHP_METHOD(Mosquitto_Client, exitLoop) { - mosquitto_client_object *object; + mosquitto_client_object *object = mosquitto_client_object_from_zend_object(Z_OBJ_P(getThis())); PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters_none() == FAILURE) { @@ -823,7 +819,6 @@ PHP_METHOD(Mosquitto_Client, exitLoop) } PHP_MOSQUITTO_RESTORE_ERRORS(); - object = (mosquitto_client_object *) mosquitto_client_object_get(getThis() TSRMLS_CC); php_mosquitto_exit_loop(object); } /* }}} */ @@ -839,17 +834,13 @@ static int strerror_r(int errnum, char *buf, size_t buf_len) PHP_MOSQUITTO_API char *php_mosquitto_strerror_wrapper(int err) { - char *buf; -#ifdef STRERROR_R_CHAR_P - return strerror_r(err, buf, 256); -#else - buf = ecalloc(256, sizeof(char)); - if (!strerror_r(err, buf, 256)) { - return buf; + char *buf = ecalloc(256, sizeof(char)); + strerror_r(err, buf, 256); + if (!buf[0]) { + efree(buf); + return NULL; } - efree(buf); - return NULL; -#endif + return buf; } PHP_MOSQUITTO_API void php_mosquitto_exit_loop(mosquitto_client_object *object) @@ -857,46 +848,60 @@ PHP_MOSQUITTO_API void php_mosquitto_exit_loop(mosquitto_client_object *object) object->looping = 0; } -static inline mosquitto_client_object *mosquitto_client_object_get(zval *zobj TSRMLS_DC) +static void mosquitto_client_object_destroy(zend_object *object ZO_HANDLE_DC TSRMLS_DC) { - mosquitto_client_object *pobj = zend_object_store_get_object(zobj TSRMLS_CC); - - if (pobj->client == NULL) { - php_error(E_ERROR, "Internal surface object missing in %s wrapper, you must call parent::__construct in extended classes", Z_OBJCE_P(zobj)->name); - } - return pobj; -} - -static void mosquitto_client_object_destroy(void *object TSRMLS_DC) -{ - mosquitto_client_object *client = (mosquitto_client_object *) object; + mosquitto_client_object *client = mosquitto_client_object_from_zend_object(object); /* Disconnect cleanly, but disregard an error if it wasn't connected */ /* We must loop here so that the disconnect packet is sent and acknowledged */ mosquitto_disconnect(client->client); mosquitto_loop(client->client, 100, 1); mosquitto_destroy(client->client); + client->client = NULL; if (MQTTG(client_key_len) > 0) { efree(MQTTG(client_key)); + MQTTG(client_key) = NULL; } - PHP_MOSQUITTO_FREE_CALLBACK(connect); - PHP_MOSQUITTO_FREE_CALLBACK(subscribe); - PHP_MOSQUITTO_FREE_CALLBACK(unsubscribe); - PHP_MOSQUITTO_FREE_CALLBACK(publish); - PHP_MOSQUITTO_FREE_CALLBACK(message); - PHP_MOSQUITTO_FREE_CALLBACK(disconnect); - PHP_MOSQUITTO_FREE_CALLBACK(log); + PHP_MOSQUITTO_FREE_CALLBACK(client, connect); + PHP_MOSQUITTO_FREE_CALLBACK(client, subscribe); + PHP_MOSQUITTO_FREE_CALLBACK(client, unsubscribe); + PHP_MOSQUITTO_FREE_CALLBACK(client, publish); + PHP_MOSQUITTO_FREE_CALLBACK(client, message); + PHP_MOSQUITTO_FREE_CALLBACK(client, disconnect); + PHP_MOSQUITTO_FREE_CALLBACK(client, log); +} + +static void mosquitto_client_object_free(zend_object *object TSRMLS_DC) { + mosquitto_client_object *client = mosquitto_client_object_from_zend_object(object); - if (client->std.properties) { - zend_hash_destroy(client->std.properties); - FREE_HASHTABLE(client->std.properties); +#ifdef ZEND_ENGINE_3 + zend_object_std_dtor(object); +#else + if (object->properties) { + zend_hash_destroy(object->properties); + FREE_HASHTABLE(object->properties); } - efree(object); +#endif } +#ifdef ZEND_ENGINE_3 +static zend_object *mosquitto_client_object_new(zend_class_entry *ce) { + mosquitto_client_object *client = ecalloc(1, sizeof(mosquitto_client_object) + zend_object_properties_size(ce)); + zend_object *ret = mosquitto_client_object_to_zend_object(client); + +#ifdef MOSQUITTO_NEED_TSRMLS + client->TSRMLS_C = TSRMLS_C; +#endif + + zend_object_std_init(ret, ce); + ret->handlers = &mosquitto_std_object_handlers; + + return ret; +} +#else static zend_object_value mosquitto_client_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; @@ -909,7 +914,7 @@ static zend_object_value mosquitto_client_object_new(zend_class_entry *ce TSRMLS client->std.ce = ce; client->client = NULL; -#ifdef ZTS +#ifdef MOSQUITTO_NEED_TSRMLS client->TSRMLS_C = TSRMLS_C; #endif @@ -920,37 +925,40 @@ static zend_object_value mosquitto_client_object_new(zend_class_entry *ce TSRMLS #else object_properties_init(&client->std, ce); #endif - retval.handle = zend_objects_store_put(client, NULL, (zend_objects_free_object_storage_t) mosquitto_client_object_destroy, NULL TSRMLS_CC); + retval.handle = zend_objects_store_put(client, + (zend_objects_store_dtor_t)mosquitto_client_object_destroy, + (zend_objects_free_object_storage_t)mosquitto_client_object_free, NULL TSRMLS_CC); retval.handlers = &mosquitto_std_object_handlers; return retval; } +#endif void php_mosquitto_handle_errno(int retval, int err TSRMLS_DC) { - const char *message; - - switch (retval) { - case MOSQ_ERR_SUCCESS: - return; - - case MOSQ_ERR_ERRNO: - message = php_mosquitto_strerror_wrapper(errno); - break; - - default: - message = mosquitto_strerror(retval); - break; + if (retval == MOSQ_ERR_ERRNO) { + char *message = php_mosquitto_strerror_wrapper(errno); + if (message) { + zend_throw_exception(mosquitto_ce_exception, message, 0 TSRMLS_CC); + efree(message); + } + } else if (retval != MOSQ_ERR_SUCCESS) { + const char *message = mosquitto_strerror(retval); + if (message && *message) { + zend_throw_exception(mosquitto_ce_exception, message, 0 TSRMLS_CC); + } } - - zend_throw_exception(mosquitto_ce_exception, (char *) message, 0 TSRMLS_CC); } PHP_MOSQUITTO_API void php_mosquitto_connect_callback(struct mosquitto *mosq, void *obj, int rc) { - mosquitto_client_object *object = (mosquitto_client_object *) obj; + mosquitto_client_object *object = (mosquitto_client_object*)obj; +#ifdef ZEND_ENGINE_3 + zval params[2], retval; +#else zval *retval_ptr = NULL, *rc_zval = NULL, *message_zval = NULL; zval **params[2]; +#endif const char *message; -#ifdef ZTS +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D = object->TSRMLS_C; #endif @@ -958,39 +966,58 @@ PHP_MOSQUITTO_API void php_mosquitto_connect_callback(struct mosquitto *mosq, vo return; } + message = mosquitto_connack_string(rc); +#ifdef ZEND_ENGINE_3 + ZVAL_LONG(¶ms[0], rc); + ZVAL_STRING(¶ms[1], message); + + ZVAL_UNDEF(&retval); + object->connect_callback.retval = &retval; +#else MAKE_STD_ZVAL(rc_zval); ZVAL_LONG(rc_zval, rc); params[0] = &rc_zval; - message = mosquitto_connack_string(rc); MAKE_STD_ZVAL(message_zval); - ZVAL_STRINGL(message_zval, message, strlen(message), 1); + ZVAL_STRING(message_zval, message, 1); params[1] = &message_zval; + object->connect_callback.retval_ptr_ptr = &retval_ptr; +#endif + object->connect_callback.params = params; object->connect_callback.param_count = 2; - object->connect_callback.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&object->connect_callback, &object->connect_callback_cache TSRMLS_CC) == FAILURE) { if (!EG(exception)) { - zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke connect callback %s()", Z_STRVAL_P(object->connect_callback.function_name)); + zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke connect callback %s()", mosquitto_finfo_name(&object->connect_callback)); } } +#ifdef ZEND_ENGINE_3 + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&retval); +#else zval_ptr_dtor(&rc_zval); zval_ptr_dtor(&message_zval); if (retval_ptr != NULL) { zval_ptr_dtor(&retval_ptr); } +#endif } PHP_MOSQUITTO_API void php_mosquitto_disconnect_callback(struct mosquitto *mosq, void *obj, int rc) { - mosquitto_client_object *object = (mosquitto_client_object *) obj; + mosquitto_client_object *object = (mosquitto_client_object*)obj; +#ifdef ZEND_ENGINE_3 + zval params[1], retval; +#else zval *retval_ptr = NULL, *rc_zval = NULL; zval **params[1]; -#ifdef ZTS +#endif +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D = object->TSRMLS_C; #endif @@ -998,34 +1025,50 @@ PHP_MOSQUITTO_API void php_mosquitto_disconnect_callback(struct mosquitto *mosq, return; } +#ifdef ZEND_ENGINE_3 + ZVAL_LONG(¶ms[0], rc); + ZVAL_UNDEF(&retval); + + object->disconnect_callback.retval = &retval; +#else MAKE_STD_ZVAL(rc_zval); ZVAL_LONG(rc_zval, rc); params[0] = &rc_zval; + object->disconnect_callback.retval_ptr_ptr = &retval_ptr; +#endif + object->disconnect_callback.params = params; object->disconnect_callback.param_count = 1; - object->disconnect_callback.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&object->disconnect_callback, &object->disconnect_callback_cache TSRMLS_CC) == FAILURE) { if (!EG(exception)) { - zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke disconnect callback %s()", Z_STRVAL_P(object->disconnect_callback.function_name)); + zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke disconnect callback %s()", mosquitto_finfo_name(&object->disconnect_callback)); } } +#ifdef ZEND_ENGINE_3 + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(&retval); +#else zval_ptr_dtor(&rc_zval); if (retval_ptr != NULL) { zval_ptr_dtor(&retval_ptr); } +#endif } PHP_MOSQUITTO_API void php_mosquitto_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str) { - mosquitto_client_object *object = (mosquitto_client_object *) obj; - zval *retval_ptr = NULL; - zval *level_zval = NULL, *str_zval = NULL; + mosquitto_client_object *object = (mosquitto_client_object*)obj; +#ifdef ZEND_ENGINE_3 + zval params[2], retval; +#else + zval *retval_ptr = NULL, *level_zval = NULL, *str_zval = NULL; zval **params[2]; -#ifdef ZTS +#endif +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D = object->TSRMLS_C; #endif @@ -1033,39 +1076,58 @@ PHP_MOSQUITTO_API void php_mosquitto_log_callback(struct mosquitto *mosq, void * return; } +#ifdef ZEND_ENGINE_3 + ZVAL_LONG(¶ms[0], level); + ZVAL_STRING(¶ms[1], str); + ZVAL_UNDEF(&retval); + + object->log_callback.retval = &retval; +#else MAKE_STD_ZVAL(level_zval); ZVAL_LONG(level_zval, level); MAKE_STD_ZVAL(str_zval); - ZVAL_STRINGL(str_zval, str, strlen(str), 1); + ZVAL_STRING(str_zval, str, 1); params[0] = &level_zval; params[1] = &str_zval; + object->log_callback.retval_ptr_ptr = &retval_ptr; +#endif + object->log_callback.params = params; object->log_callback.param_count = 2; - object->log_callback.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&object->log_callback, &object->log_callback_cache TSRMLS_CC) == FAILURE) { if (!EG(exception)) { - zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke log callback %s()", Z_STRVAL_P(object->log_callback.function_name)); + zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke log callback %s()", mosquitto_finfo_name(&object->log_callback)); } } +#ifdef ZEND_ENGINE_3 + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&retval); +#else zval_ptr_dtor(params[0]); zval_ptr_dtor(params[1]); if (retval_ptr != NULL) { zval_ptr_dtor(&retval_ptr); } +#endif } PHP_MOSQUITTO_API void php_mosquitto_message_callback(struct mosquitto *mosq, void *client_obj, const struct mosquitto_message *message) { - mosquitto_client_object *object = (mosquitto_client_object *) client_obj; + mosquitto_client_object *object = (mosquitto_client_object*)client_obj; mosquitto_message_object *message_object; +#ifdef ZEND_ENGINE_3 + zval params[1], retval, *message_zval; +#else zval *retval_ptr = NULL, *message_zval = NULL; zval **params[1]; -#ifdef ZTS +#endif +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D = object->TSRMLS_C; #endif @@ -1073,37 +1135,52 @@ PHP_MOSQUITTO_API void php_mosquitto_message_callback(struct mosquitto *mosq, vo return; } +#ifdef ZEND_ENGINE_3 + message_zval = ¶ms[0]; + ZVAL_UNDEF(&retval); + object->message_callback.retval = &retval; +#else MAKE_STD_ZVAL(message_zval); + params[0] = &message_zval; + object->message_callback.retval_ptr_ptr = &retval_ptr; +#endif + object_init_ex(message_zval, mosquitto_ce_message); - message_object = (mosquitto_message_object *) zend_object_store_get_object(message_zval TSRMLS_CC); + message_object = mosquitto_message_object_from_zend_object(Z_OBJ_P(message_zval)); mosquitto_message_copy(&message_object->message, message); - params[0] = &message_zval; object->message_callback.params = params; object->message_callback.param_count = 1; - object->message_callback.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&object->message_callback, &object->message_callback_cache TSRMLS_CC) == FAILURE) { if (!EG(exception)) { - zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke message callback %s()", Z_STRVAL_P(object->message_callback.function_name)); + zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke message callback %s()", mosquitto_finfo_name(&object->message_callback)); } } +#ifdef ZEND_ENGINE_3 + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(&retval); +#else zval_ptr_dtor(&message_zval); if (retval_ptr != NULL) { zval_ptr_dtor(&retval_ptr); } +#endif } PHP_MOSQUITTO_API void php_mosquitto_publish_callback(struct mosquitto *mosq, void *client_obj, int mid) { - mosquitto_client_object *object = (mosquitto_client_object *) client_obj; - zval *retval_ptr = NULL; - zval *mid_zval; + mosquitto_client_object *object = (mosquitto_client_object*)client_obj; +#ifdef ZEND_ENGINE_3 + zval params[1], retval; +#else + zval *retval_ptr = NULL, *mid_zval; zval **params[1]; -#ifdef ZTS +#endif +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D = object->TSRMLS_C; #endif @@ -1111,34 +1188,48 @@ PHP_MOSQUITTO_API void php_mosquitto_publish_callback(struct mosquitto *mosq, vo return; } +#ifdef ZEND_ENGINE_3 + ZVAL_LONG(¶ms[0], mid); + ZVAL_UNDEF(&retval); + object->publish_callback.retval = &retval; +#else MAKE_STD_ZVAL(mid_zval); ZVAL_LONG(mid_zval, mid); params[0] = &mid_zval; + object->publish_callback.retval_ptr_ptr = &retval_ptr; +#endif object->publish_callback.params = params; object->publish_callback.param_count = 1; - object->publish_callback.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&object->publish_callback, &object->publish_callback_cache TSRMLS_CC) == FAILURE) { if (!EG(exception)) { - zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke publish callback %s()", Z_STRVAL_P(object->publish_callback.function_name)); + zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke publish callback %s()", mosquitto_finfo_name(&object->publish_callback)); } } +#ifdef ZEND_ENGINE_3 + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(&retval); +#else zval_ptr_dtor(params[0]); if (retval_ptr != NULL) { zval_ptr_dtor(&retval_ptr); } +#endif } PHP_MOSQUITTO_API void php_mosquitto_subscribe_callback(struct mosquitto *mosq, void *client_obj, int mid, int qos_count, const int *granted_qos) { - mosquitto_client_object *object = (mosquitto_client_object *) client_obj; - zval *retval_ptr = NULL; - zval *mid_zval, *qos_count_zval, *granted_qos_zval; + mosquitto_client_object *object = (mosquitto_client_object*)client_obj; +#ifdef ZEND_ENGINE_3 + zval params[3], retval; +#else + zval *retval_ptr = NULL, *mid_zval, *qos_count_zval, *granted_qos_zval; zval **params[3]; -#ifdef ZTS +#endif +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D = object->TSRMLS_C; #endif @@ -1148,6 +1239,14 @@ PHP_MOSQUITTO_API void php_mosquitto_subscribe_callback(struct mosquitto *mosq, /* Since we can only subscribe to one topic per message, it seems reasonable to * take just the first entry from granted_qos as the granted QoS value */ +#ifdef ZEND_ENGINE_3 + ZVAL_LONG(¶ms[0], mid); + ZVAL_LONG(¶ms[1], qos_count); + ZVAL_LONG(¶ms[2], *granted_qos); + ZVAL_UNDEF(&retval); + + object->subscribe_callback.retval = &retval; +#else MAKE_STD_ZVAL(mid_zval); MAKE_STD_ZVAL(qos_count_zval); MAKE_STD_ZVAL(granted_qos_zval); @@ -1158,16 +1257,24 @@ PHP_MOSQUITTO_API void php_mosquitto_subscribe_callback(struct mosquitto *mosq, params[1] = &qos_count_zval; params[2] = &granted_qos_zval; + object->subscribe_callback.retval_ptr_ptr = &retval_ptr; +#endif + object->subscribe_callback.params = params; object->subscribe_callback.param_count = 3; - object->subscribe_callback.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&object->subscribe_callback, &object->subscribe_callback_cache TSRMLS_CC) == FAILURE) { if (!EG(exception)) { - zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke subscribe callback %s()", Z_STRVAL_P(object->subscribe_callback.function_name)); + zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke subscribe callback %s()", mosquitto_finfo_name(&object->subscribe_callback)); } } +#ifdef ZEND_ENGINE_3 + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(&retval); +#else zval_ptr_dtor(params[0]); zval_ptr_dtor(params[1]); zval_ptr_dtor(params[2]); @@ -1175,15 +1282,19 @@ PHP_MOSQUITTO_API void php_mosquitto_subscribe_callback(struct mosquitto *mosq, if (retval_ptr != NULL) { zval_ptr_dtor(&retval_ptr); } +#endif } PHP_MOSQUITTO_API void php_mosquitto_unsubscribe_callback(struct mosquitto *mosq, void *client_obj, int mid) { - mosquitto_client_object *object = (mosquitto_client_object *) client_obj; - zval *retval_ptr = NULL; - zval *mid_zval; + mosquitto_client_object *object = (mosquitto_client_object*)client_obj; +#ifdef ZEND_ENGINE_3 + zval params[1], retval; +#else + zval *retval_ptr = NULL, *mid_zval; zval **params[1]; -#ifdef ZTS +#endif +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D = object->TSRMLS_C; #endif @@ -1191,25 +1302,38 @@ PHP_MOSQUITTO_API void php_mosquitto_unsubscribe_callback(struct mosquitto *mosq return; } +#ifdef ZEND_ENGINE_3 + ZVAL_LONG(¶ms[0], mid); + ZVAL_UNDEF(&retval); + + object->unsubscribe_callback.retval = &retval; +#else MAKE_STD_ZVAL(mid_zval); ZVAL_LONG(mid_zval, mid); params[0] = &mid_zval; + object->unsubscribe_callback.retval_ptr_ptr = &retval_ptr; +#endif + object->unsubscribe_callback.params = params; object->unsubscribe_callback.param_count = 1; - object->unsubscribe_callback.retval_ptr_ptr = &retval_ptr; if (zend_call_function(&object->unsubscribe_callback, &object->unsubscribe_callback_cache TSRMLS_CC) == FAILURE) { if (!EG(exception)) { - zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke unsubscribe callback %s()", Z_STRVAL_P(object->unsubscribe_callback.function_name)); + zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to invoke unsubscribe callback %s()", mosquitto_finfo_name(&object->unsubscribe_callback)); } } +#ifdef ZEND_ENGINE_3 + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(&retval); +#else zval_ptr_dtor(params[0]); if (retval_ptr != NULL) { zval_ptr_dtor(&retval_ptr); } +#endif } static int php_mosquitto_pw_callback(char *buf, int size, int rwflag, void *userdata) { @@ -1297,14 +1421,22 @@ PHP_MINIT_FUNCTION(mosquitto) memcpy(&mosquitto_std_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mosquitto_std_object_handlers.clone_obj = NULL; +#ifdef ZEND_ENGINE_3 + mosquitto_std_object_handlers.offset = XtOffsetOf(mosquitto_client_object, std); + mosquitto_std_object_handlers.free_obj = mosquitto_client_object_free; + mosquitto_std_object_handlers.dtor_obj = mosquitto_client_object_destroy; +#endif INIT_NS_CLASS_ENTRY(client_ce, "Mosquitto", "Client", mosquitto_client_methods); - mosquitto_ce_client = zend_register_internal_class_ex(&client_ce, NULL, NULL TSRMLS_CC); + mosquitto_ce_client = zend_register_internal_class(&client_ce TSRMLS_CC); mosquitto_ce_client->create_object = mosquitto_client_object_new; INIT_NS_CLASS_ENTRY(exception_ce, "Mosquitto", "Exception", NULL); - mosquitto_ce_exception = zend_register_internal_class_ex(&exception_ce, - zend_exception_get_default(TSRMLS_C), "Exception" TSRMLS_CC); + mosquitto_ce_exception = zend_register_internal_class_ex(&exception_ce, zend_exception_get_default(TSRMLS_C) +#ifndef ZEND_ENGINE_3 + , "Exception" TSRMLS_CC +#endif + ); #define REGISTER_MOSQUITTO_LONG_CONST(const_name, value) \ zend_declare_class_constant_long(mosquitto_ce_client, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC); \ diff --git a/mosquitto_message.c b/mosquitto_message.c index 509708d..9c43a68 100644 --- a/mosquitto_message.c +++ b/mosquitto_message.c @@ -14,6 +14,15 @@ zend_class_entry *mosquitto_ce_message; static zend_object_handlers mosquitto_message_object_handlers; static HashTable php_mosquitto_message_properties; +#ifdef ZEND_ENGINE_3 +typedef size_t mosquitto_strlen_type; +#else +# ifndef Z_OBJ_P +# define Z_OBJ_P(pzv) ((zend_object*)zend_object_store_get_object(pzv TSRMLS_CC)) +# endif +typedef int mosquitto_strlen_type; +#endif + /* {{{ Arginfo */ ZEND_BEGIN_ARG_INFO(Mosquitto_Message_topicMatchesSub_args, ZEND_SEND_BY_VAL) @@ -41,7 +50,7 @@ PHP_METHOD(Mosquitto_Message, __construct) PHP_METHOD(Mosquitto_Message, topicMatchesSub) { char *topic = NULL, *subscription = NULL; - int topic_len, subscription_len; + mosquitto_strlen_type topic_len, subscription_len; zend_bool result; PHP_MOSQUITTO_ERROR_HANDLING(); @@ -61,7 +70,7 @@ PHP_METHOD(Mosquitto_Message, topicMatchesSub) PHP_METHOD(Mosquitto_Message, tokeniseTopic) { char *topic = NULL, **topics = NULL; - int topic_len = 0, retval = 0, count = 0, i = 0; + mosquitto_strlen_type topic_len = 0, retval = 0, count = 0, i = 0; PHP_MOSQUITTO_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &topic, &topic_len) == FAILURE) { @@ -70,7 +79,7 @@ PHP_METHOD(Mosquitto_Message, tokeniseTopic) } PHP_MOSQUITTO_RESTORE_ERRORS(); - retval = mosquitto_sub_topic_tokenise(topic, &topics, &count); + retval = mosquitto_sub_topic_tokenise(topic, &topics, (int*)&count); if (retval == MOSQ_ERR_NOMEM) { zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to tokenise topic"); @@ -82,7 +91,11 @@ PHP_METHOD(Mosquitto_Message, tokeniseTopic) if (topics[i] == NULL) { add_next_index_null(return_value); } else { +#ifdef ZEND_ENGINE_3 + add_next_index_string(return_value, topics[i]); +#else add_next_index_string(return_value, topics[i], 1); +#endif } } @@ -93,6 +106,30 @@ PHP_METHOD(Mosquitto_Message, tokeniseTopic) PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_READER_FUNCTION(mid); PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_READER_FUNCTION(qos); +#ifdef ZEND_ENGINE_3 +static int php_mosquitto_message_read_retain(mosquitto_message_object *mosquitto_object, zval *retval) +{ + ZVAL_BOOL(retval, mosquitto_object->message.retain); + return SUCCESS; +} + +static int php_mosquitto_message_read_topic(mosquitto_message_object *mosquitto_object, zval *retval) +{ + if (mosquitto_object->message.topic != NULL) { + ZVAL_STRING(retval, mosquitto_object->message.topic); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static int php_mosquitto_message_read_payload(mosquitto_message_object *mosquitto_object, zval *retval) +{ + ZVAL_STRINGL(retval, mosquitto_object->message.payload, mosquitto_object->message.payloadlen); + return SUCCESS; +} +#else static int php_mosquitto_message_read_retain(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC) { MAKE_STD_ZVAL(*retval); @@ -105,7 +142,7 @@ static int php_mosquitto_message_read_topic(mosquitto_message_object *mosquitto_ MAKE_STD_ZVAL(*retval); if (mosquitto_object->message.topic != NULL) { - ZVAL_STRINGL(*retval, mosquitto_object->message.topic, strlen(mosquitto_object->message.topic), 1); + ZVAL_STRING(*retval, mosquitto_object->message.topic, 1); } else { ZVAL_NULL(*retval); } @@ -119,25 +156,14 @@ static int php_mosquitto_message_read_payload(mosquitto_message_object *mosquitt ZVAL_STRINGL(*retval, mosquitto_object->message.payload, mosquitto_object->message.payloadlen, 1); return SUCCESS; } +#endif PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_WRITER_FUNCTION(mid); PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_WRITER_FUNCTION(qos); static int php_mosquitto_message_write_retain(mosquitto_message_object *mosquitto_object, zval *newval TSRMLS_DC) { - zval ztmp; - if (Z_TYPE_P(newval) != IS_BOOL) { - ztmp = *newval; - zval_copy_ctor(&ztmp); - convert_to_boolean(&ztmp); - newval = &ztmp; - } - - mosquitto_object->message.retain = Z_LVAL_P(newval); - - if (newval == &ztmp) { - zval_dtor(newval); - } + mosquitto_object->message.retain = zend_is_true(newval); return SUCCESS; } @@ -201,15 +227,45 @@ const php_mosquitto_prop_handler php_mosquitto_message_property_entries[] = { {NULL, 0, NULL, NULL} }; -zval *php_mosquitto_message_read_property(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC) -{ +#ifdef ZEND_ENGINE_3 +# define READ_PROPERTY_DC , void **cache_slot, zval *retval +# define READ_PROPERTY_CC , cache_slot, retval +# define WRITE_PROPERTY_DC , void **cache_slot +# define WRITE_PROPERTY_CC , cache_slot +# define HAS_PROPERTY_DC , void **cache_slot +# define HAS_PROPERTY_CC , cache_slot + +static php_mosquitto_prop_handler *mosquitto_get_prop_handler(zval *prop) { + zval *ret = zend_hash_find(&php_mosquitto_message_properties, Z_STR_P(prop)); + if (!ret || Z_TYPE_P(ret) != IS_PTR) { + return NULL; + } + return (php_mosquitto_prop_handler*)Z_PTR_P(ret); +} +#else +# define READ_PROPERTY_DC ZEND_LITERAL_KEY_DC TSRMLS_DC +# define READ_PROPERTY_CC ZEND_LITERAL_KEY_CC TSRMLS_CC +# define WRITE_PROPERTY_DC ZEND_LITERAL_KEY_DC TSRMLS_DC +# define WRITE_PROPERTY_CC ZEND_LITERAL_KEY_CC TSRMLS_CC +# define HAS_PROPERTY_DC ZEND_LITERAL_KEY_DC TSRMLS_DC +# define HAS_PROPERTY_CC ZEND_LITERAL_KEY_CC TSRMLS_CC + +static php_mosquitto_prop_handler *mosquitto_get_prop_handler(zval *prop) { + php_mosquitto_prop_handler *hnd; + if (FAILURE == zend_hash_find(&php_mosquitto_message_properties, Z_STRVAL_P(prop), Z_STRLEN_P(prop)+1, (void**) &hnd)) { + return NULL; + } + return hnd; +} +#endif + +zval *php_mosquitto_message_read_property(zval *object, zval *member, int type READ_PROPERTY_DC) { zval tmp_member; +#ifndef ZEND_ENGINE_3 zval *retval; - mosquitto_message_object *message_object; +#endif + mosquitto_message_object *message_object = mosquitto_message_object_from_zend_object(Z_OBJ_P(object)); php_mosquitto_prop_handler *hnd; - int ret; - - message_object = (mosquitto_message_object *) zend_object_store_get_object(object TSRMLS_CC); if (Z_TYPE_P(member) != IS_STRING) { tmp_member = *member; @@ -217,20 +273,24 @@ zval *php_mosquitto_message_read_property(zval *object, zval *member, int type Z convert_to_string(&tmp_member); member = &tmp_member; } + hnd = mosquitto_get_prop_handler(member); - ret = zend_hash_find(&php_mosquitto_message_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); - - if (ret == SUCCESS && hnd->read_func) { - ret = hnd->read_func(message_object, &retval TSRMLS_CC); - if (ret == SUCCESS) { + if (hnd && hnd->read_func) { +#ifdef ZEND_ENGINE_3 + if (FAILURE == hnd->read_func(message_object, retval)) { + ZVAL_NULL(retval); + } +#else + if (SUCCESS == hnd->read_func(message_object, &retval TSRMLS_CC)) { /* ensure we're creating a temporary variable */ Z_SET_REFCOUNT_P(retval, 0); } else { retval = EG(uninitialized_zval_ptr); } +#endif } else { zend_object_handlers * std_hnd = zend_get_std_object_handlers(); - retval = std_hnd->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC); + retval = std_hnd->read_property(object, member, type READ_PROPERTY_CC); } if (member == &tmp_member) { @@ -240,12 +300,11 @@ zval *php_mosquitto_message_read_property(zval *object, zval *member, int type Z return(retval); } -void php_mosquitto_message_write_property(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC) +void php_mosquitto_message_write_property(zval *object, zval *member, zval *value WRITE_PROPERTY_DC) { zval tmp_member; - mosquitto_message_object *obj; + mosquitto_message_object *obj = mosquitto_message_object_from_zend_object(Z_OBJ_P(object)); php_mosquitto_prop_handler *hnd; - int ret; if (Z_TYPE_P(member) != IS_STRING) { tmp_member = *member; @@ -254,20 +313,24 @@ void php_mosquitto_message_write_property(zval *object, zval *member, zval *valu member = &tmp_member; } - ret = FAILURE; - obj = (mosquitto_message_object *)zend_objects_get_address(object TSRMLS_CC); - - ret = zend_hash_find(&php_mosquitto_message_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &hnd); + hnd = mosquitto_get_prop_handler(member); - if (ret == SUCCESS && hnd->write_func) { + if (hnd && hnd->write_func) { hnd->write_func(obj, value TSRMLS_CC); +#ifdef ZEND_ENGINE_3 + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + zval_ptr_dtor(value); + } +#else if (! PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) == 0) { Z_ADDREF_P(value); zval_ptr_dtor(&value); } +#endif } else { zend_object_handlers * std_hnd = zend_get_std_object_handlers(); - std_hnd->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC); + std_hnd->write_property(object, member, value WRITE_PROPERTY_CC); } if (member == &tmp_member) { @@ -275,28 +338,45 @@ void php_mosquitto_message_write_property(zval *object, zval *member, zval *valu } } -static int php_mosquitto_message_has_property(zval *object, zval *member, int has_set_exists ZEND_LITERAL_KEY_DC TSRMLS_DC) +static int php_mosquitto_message_has_property(zval *object, zval *member, int has_set_exists HAS_PROPERTY_DC) { - php_mosquitto_prop_handler *hnd; + php_mosquitto_prop_handler *hnd = mosquitto_get_prop_handler(member); int ret = 0; +#ifdef ZEND_ENGINE_3 + zval rv; + zval *retval = &rv; +#endif - if (zend_hash_find(&php_mosquitto_message_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&hnd) == SUCCESS) { + if (hnd) { switch (has_set_exists) { case 2: ret = 1; break; case 0: { - zval *value = php_mosquitto_message_read_property(object, member, BP_VAR_IS ZEND_LITERAL_KEY_CC TSRMLS_CC); + zval *value = php_mosquitto_message_read_property(object, member, BP_VAR_IS READ_PROPERTY_CC); +#ifdef ZEND_ENGINE_3 + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + zval_ptr_dtor(value); + } +#else if (value != EG(uninitialized_zval_ptr)) { ret = Z_TYPE_P(value) != IS_NULL? 1:0; /* refcount is 0 */ Z_ADDREF_P(value); zval_ptr_dtor(&value); } +#endif break; } default: { - zval *value = php_mosquitto_message_read_property(object, member, BP_VAR_IS ZEND_LITERAL_KEY_CC TSRMLS_CC); + zval *value = php_mosquitto_message_read_property(object, member, BP_VAR_IS READ_PROPERTY_CC); +#ifdef ZEND_ENGINE_3 + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + zval_ptr_dtor(value); + } +#else if (value != EG(uninitialized_zval_ptr)) { convert_to_boolean(value); ret = Z_BVAL_P(value)? 1:0; @@ -304,59 +384,109 @@ static int php_mosquitto_message_has_property(zval *object, zval *member, int ha Z_ADDREF_P(value); zval_ptr_dtor(&value); } +#endif break; } } } else { zend_object_handlers * std_hnd = zend_get_std_object_handlers(); - ret = std_hnd->has_property(object, member, has_set_exists ZEND_LITERAL_KEY_CC TSRMLS_CC); + ret = std_hnd->has_property(object, member, has_set_exists HAS_PROPERTY_CC); } return ret; } +#ifndef ZEND_ENGINE_3 +# ifndef ZEND_HASH_FOREACH_PTR +# define ZEND_HASH_FOREACH_KEY_PTR(ht, idx, key, ptr) \ + { \ + HashPosition pos; \ + for (zend_hash_internal_pointer_reset_ex(ht, &pos); \ + zend_hash_get_current_data_ex(ht, (void**)&ptr, &pos) == SUCCESS; \ + zend_hash_move_forward_ex(ht, &pos)) { \ + key = NULL; \ + zend_hash_get_current_key_ex(ht, &key, &key##_len, &idx, 0, &pos); \ + { +# endif +# ifndef ZEND_HASH_FOREACH_END +# define ZEND_HASH_FOREACH_END() \ + } \ + } \ + } +# endif +#endif + static HashTable *php_mosquitto_message_get_properties(zval *object TSRMLS_DC) { - mosquitto_message_object *obj; + mosquitto_message_object *obj = mosquitto_message_object_from_zend_object(Z_OBJ_P(object)); php_mosquitto_prop_handler *hnd; HashTable *props; - zval *val; +#ifdef ZEND_ENGINE_3 + zend_string *key; + zend_long num_key; +#else char *key; uint key_len; - HashPosition pos; ulong num_key; +#endif - obj = (mosquitto_message_object *)zend_objects_get_address(object TSRMLS_CC); props = zend_std_get_properties(object TSRMLS_CC); - zend_hash_internal_pointer_reset_ex(&php_mosquitto_message_properties, &pos); - - while (zend_hash_get_current_data_ex(&php_mosquitto_message_properties, (void**)&hnd, &pos) == SUCCESS) { - zend_hash_get_current_key_ex(&php_mosquitto_message_properties, &key, &key_len, &num_key, 0, &pos); + ZEND_HASH_FOREACH_KEY_PTR(&php_mosquitto_message_properties, num_key, key, hnd) { +#ifdef ZEND_ENGINE_3 + zval val; + if (!hnd->read_func || (hnd->read_func(obj, &val) != SUCCESS)) { + ZVAL_NULL(&val); + } + if (key) { + zend_hash_update(props, key, &val); + } else { + zend_hash_index_update(props, num_key, &val); + } +#else + zval *val; if (!hnd->read_func || hnd->read_func(obj, &val TSRMLS_CC) != SUCCESS) { val = EG(uninitialized_zval_ptr); Z_ADDREF_P(val); } - zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL); - zend_hash_move_forward_ex(&php_mosquitto_message_properties, &pos); - } + if (key) { + zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval*), NULL); + } else { + zend_hash_index_update(props, num_key, (void *)&val, sizeof(zval*), NULL); + } +#endif + } ZEND_HASH_FOREACH_END(); + return obj->std.properties; } void php_mosquitto_message_add_property(HashTable *h, const char *name, size_t name_length, php_mosquitto_read_t read_func, php_mosquitto_write_t write_func TSRMLS_DC) { - php_mosquitto_prop_handler p; +#ifdef ZEND_ENGINE_3 + php_mosquitto_prop_handler *p = (php_mosquitto_prop_handler*)pemalloc(sizeof(php_mosquitto_prop_handler), 1); +#else + php_mosquitto_prop_handler val, *p = &val; +#endif - p.name = (char*) name; - p.name_length = name_length; - p.read_func = (read_func) ? read_func : NULL; - p.write_func = (write_func) ? write_func : NULL; - zend_hash_add(h, (char *)name, name_length + 1, &p, sizeof(php_mosquitto_prop_handler), NULL); + p->name = (char*) name; + p->name_length = name_length; + p->read_func = read_func; + p->write_func = write_func; +#ifdef ZEND_ENGINE_3 + { + zend_string *key = zend_string_init(name, name_length, 1); + zval hnd; + ZVAL_PTR(&hnd, p); + zend_hash_add(h, key, &hnd); + } +#else + zend_hash_add(h, (char *)name, name_length + 1, p, sizeof(php_mosquitto_prop_handler), NULL); +#endif } -static void mosquitto_message_object_destroy(void *object TSRMLS_DC) +static void mosquitto_message_object_destroy(zend_object *object TSRMLS_DC) { - mosquitto_message_object *message = (mosquitto_message_object *) object; + mosquitto_message_object *message = mosquitto_message_object_from_zend_object(object); zend_hash_destroy(message->std.properties); FREE_HASHTABLE(message->std.properties); @@ -371,6 +501,21 @@ static void mosquitto_message_object_destroy(void *object TSRMLS_DC) efree(object); } +#ifdef ZEND_ENGINE_3 +static zend_object *mosquitto_message_object_new(zend_class_entry *ce) { + mosquitto_message_object *msg = ecalloc(1, sizeof(mosquitto_message_object) + zend_object_properties_size(ce)); + zend_object *ret = mosquitto_message_object_to_zend_object(msg); + +#ifdef MOSQUITTO_NEED_TSRMLS + message_obj->TSRMLS_C = TSRMLS_C; +#endif + + zend_object_std_init(ret, ce); + ret->handlers = &mosquitto_message_object_handlers; + + return ret; +} +#else static zend_object_value mosquitto_message_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; @@ -382,7 +527,7 @@ static zend_object_value mosquitto_message_object_new(zend_class_entry *ce TSRML message_obj = ecalloc(1, sizeof(mosquitto_message_object)); message_obj->std.ce = ce; -#ifdef ZTS +#ifdef MOSQUITTO_NEED_TSRMLS message_obj->TSRMLS_C = TSRMLS_C; #endif @@ -397,6 +542,7 @@ static zend_object_value mosquitto_message_object_new(zend_class_entry *ce TSRML retval.handlers = &mosquitto_message_object_handlers; return retval; } +#endif const zend_function_entry mosquitto_message_methods[] = { PHP_ME(Mosquitto_Message, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) @@ -413,6 +559,10 @@ PHP_MINIT_FUNCTION(mosquitto_message) mosquitto_message_object_handlers.write_property = php_mosquitto_message_write_property; mosquitto_message_object_handlers.has_property = php_mosquitto_message_has_property; mosquitto_message_object_handlers.get_properties = php_mosquitto_message_get_properties; +#ifdef ZEND_ENGINE_3 + mosquitto_message_object_handlers.offset = XtOffsetOf(mosquitto_message_object, std); + mosquitto_message_object_handlers.free_obj = mosquitto_message_object_destroy; +#endif INIT_NS_CLASS_ENTRY(message_ce, "Mosquitto", "Message", mosquitto_message_methods); mosquitto_ce_message = zend_register_internal_class(&message_ce TSRMLS_CC); diff --git a/php_mosquitto.h b/php_mosquitto.h index 615e569..b73bf6d 100644 --- a/php_mosquitto.h +++ b/php_mosquitto.h @@ -36,8 +36,14 @@ extern zend_module_entry mosquitto_module_entry; #include +#if defined(ZEND_ENGINE_2) && defined(ZTS) +# define MOSQUITTO_NEED_TSRMLS +#endif + typedef struct _mosquitto_client_object { +#ifndef ZEND_ENGINE_3 zend_object std; +#endif struct mosquitto *client; zend_fcall_info connect_callback; @@ -55,24 +61,60 @@ typedef struct _mosquitto_client_object { zend_fcall_info log_callback; zend_fcall_info_cache log_callback_cache; - int looping; + int looping; -#ifdef ZTS +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D; #endif +#ifdef ZEND_ENGINE_3 + zend_object std; /* Must be last */ +#endif } mosquitto_client_object; typedef struct _mosquitto_message_object { +#ifndef ZEND_ENGINE_3 zend_object std; +#endif struct mosquitto_message message; zend_bool owned_topic; zend_bool owned_payload; -#ifdef ZTS +#ifdef MOSQUITTO_NEED_TSRMLS TSRMLS_D; #endif +#ifdef ZEND_ENGINE_3 + zend_object std; /* Must be last */ +#endif } mosquitto_message_object; +static inline +mosquitto_client_object *mosquitto_client_object_from_zend_object(zend_object* obj) { + return (mosquitto_client_object*)( + ((char*)obj) - XtOffsetOf(mosquitto_client_object, std) + ); +} + +static inline +zend_object *mosquitto_client_object_to_zend_object(mosquitto_client_object* client) { + return &(client->std); +} + +static inline +mosquitto_message_object *mosquitto_message_object_from_zend_object(zend_object* obj) { + return (mosquitto_message_object*)( + ((char*)obj) - XtOffsetOf(mosquitto_message_object, std) + ); +} + +static inline +zend_object *mosquitto_message_object_to_zend_object(mosquitto_message_object* msg) { + return &(msg->std); +} + +#ifdef ZEND_ENGINE_3 +typedef int (*php_mosquitto_read_t)(mosquitto_message_object *mosquitto_object, zval *retval); +#else typedef int (*php_mosquitto_read_t)(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC); +#endif typedef int (*php_mosquitto_write_t)(mosquitto_message_object *mosquitto_object, zval *newval TSRMLS_DC); typedef struct _php_mosquitto_prop_handler { @@ -89,16 +131,31 @@ typedef struct _php_mosquitto_prop_handler { #define PHP_MOSQUITTO_RESTORE_ERRORS() \ zend_restore_error_handling(&MQTTG(mosquitto_original_error_handling) TSRMLS_CC) - -#define PHP_MOSQUITTO_FREE_CALLBACK(CALLBACK) \ +#ifdef ZEND_ENGINE_3 +# define PHP_MOSQUITTO_FREE_CALLBACK(client, CALLBACK) \ + if (ZEND_FCI_INITIALIZED(client->CALLBACK ## _callback)) { \ + zval_ptr_dtor(&client->CALLBACK ## _callback.function_name); \ + } \ + \ + if (client->CALLBACK ## _callback.object != NULL) { \ + zval tmp_; \ + ZVAL_OBJ(&tmp_, client->CALLBACK ## _callback.object); \ + zval_ptr_dtor(&tmp_); \ + } \ + client->CALLBACK ## _callback = empty_fcall_info; \ + client->CALLBACK ## _callback_cache = empty_fcall_info_cache; +#else +# define PHP_MOSQUITTO_FREE_CALLBACK(client, CALLBACK) \ if (ZEND_FCI_INITIALIZED(client->CALLBACK ## _callback)) { \ zval_ptr_dtor(&client->CALLBACK ## _callback.function_name); \ } \ \ if (client->CALLBACK ## _callback.object_ptr != NULL) { \ zval_ptr_dtor(&client->CALLBACK ## _callback.object_ptr); \ - } - + } \ + client->CALLBACK ## _callback = empty_fcall_info; \ + client->CALLBACK ## _callback_cache = empty_fcall_info_cache; +#endif #define PHP_MOSQUITTO_MESSAGE_PROPERTY_ENTRY_RECORD(name) \ { "" #name "", sizeof("" #name "") - 1, php_mosquitto_message_read_##name, php_mosquitto_message_write_##name } @@ -113,13 +170,20 @@ typedef struct _php_mosquitto_prop_handler { } \ } -#define PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_READER_FUNCTION(name) \ - static int php_mosquitto_message_read_##name(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC) \ - { \ +#ifdef ZEND_ENGINE_3 +# define PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_READER_FUNCTION(name) \ + static int php_mosquitto_message_read_##name(mosquitto_message_object *mosquitto_object, zval *retval) { \ + ZVAL_LONG(retval, mosquitto_object->message.name); \ + return SUCCESS; \ + } +#else +# define PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_READER_FUNCTION(name) \ + static int php_mosquitto_message_read_##name(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC) { \ MAKE_STD_ZVAL(*retval); \ ZVAL_LONG(*retval, mosquitto_object->message.name); \ return SUCCESS; \ } +#endif #define PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_WRITER_FUNCTION(name) \ static int php_mosquitto_message_write_##name(mosquitto_message_object *mosquitto_object, zval *newval TSRMLS_DC) \ diff --git a/tests/Client/connect.phpt b/tests/Client/connect.phpt index 68bc3ce..e15398a 100644 --- a/tests/Client/connect.phpt +++ b/tests/Client/connect.phpt @@ -106,8 +106,8 @@ Mosquitto\Client::connect() expects at least 1 parameter, 0 given %s error. %s error. Invalid function arguments provided. -Mosquitto\Client::connect() expects parameter 2 to be long, object given -Mosquitto\Client::connect() expects parameter 3 to be long, object given +Mosquitto\Client::connect() expects parameter 2 to be %s, object given +Mosquitto\Client::connect() expects parameter 3 to be %s, object given %s error. object(Mosquitto\Client)#%d (%d) { } diff --git a/tests/Client/onConnect.phpt b/tests/Client/onConnect.phpt index ec9526e..496f91c 100644 --- a/tests/Client/onConnect.phpt +++ b/tests/Client/onConnect.phpt @@ -9,8 +9,10 @@ include(dirname(__DIR__) . '/setup.php'); try { $client = new Mosquitto\Client; $client->onConnect('foo'); -} catch (Exception $e) { +} catch (TypeError $e) { printf("Caught %s with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); +} catch (Mosquitto\Exception $e) { + printf("Caught TypeError with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); } unset($client); @@ -26,8 +28,7 @@ for ($i = 0; $i < 2; $i++) { } ?> --EXPECTF-- -Caught error 4096 (Argument 1 passed to Mosquitto\Client::onConnect() must be callable, string given) in %s on line 6 -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::onConnect() expects parameter 1 to be a valid callback, function 'foo' not found or invalid function name +%ACaught TypeError with code 0 and message: %s array(2) { [0]=> int(0) diff --git a/tests/Client/onDisconnect.phpt b/tests/Client/onDisconnect.phpt index d2c9992..10f35a3 100644 --- a/tests/Client/onDisconnect.phpt +++ b/tests/Client/onDisconnect.phpt @@ -9,8 +9,10 @@ include(dirname(__DIR__) . '/setup.php'); try { $client = new Mosquitto\Client; $client->onDisconnect('foo'); -} catch (Exception $e) { +} catch (TypeError $e) { printf("Caught %s with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); +} catch (Mosquitto\Exception $e) { + printf("Caught TypeError with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); } unset($client); @@ -47,8 +49,7 @@ for ($i = 0; $i < 5; $i++) { ?> --EXPECTF-- -Caught error 4096 (Argument 1 passed to Mosquitto\Client::onDisconnect() must be callable, string given) in %s on line 6 -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::onDisconnect() expects parameter 1 to be a valid callback, function 'foo' not found or invalid function name +%ACaught TypeError with code 0 and message: %s Triggering disconnect Disconnected Disconnected diff --git a/tests/Client/onLog.phpt b/tests/Client/onLog.phpt index 13cddca..300260e 100644 --- a/tests/Client/onLog.phpt +++ b/tests/Client/onLog.phpt @@ -13,8 +13,10 @@ function logger() { try { $client = new Mosquitto\Client; $client->onLog('foo'); -} catch (Exception $e) { +} catch (TypeError $e) { printf("Caught %s with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); +} catch (Mosquitto\Exception $e) { + printf("Caught TypeError with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); } $client = new Mosquitto\Client; @@ -26,8 +28,7 @@ $client->loop(50); $client->loop(50); ?> --EXPECTF-- -Caught error 4096 (Argument 1 passed to Mosquitto\Client::onLog() must be callable, string given) in %s on line %d -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::onLog() expects parameter 1 to be a valid callback, function 'foo' not found or invalid function name +%ACaught TypeError with code 0 and message: %s object(Mosquitto\Client)#%d (%d) { } array(2) { diff --git a/tests/Client/onMessage.phpt b/tests/Client/onMessage.phpt index 5e2374a..3749a3c 100644 --- a/tests/Client/onMessage.phpt +++ b/tests/Client/onMessage.phpt @@ -9,8 +9,10 @@ include(dirname(__DIR__) . '/setup.php'); try { $client = new Mosquitto\Client; $client->onMessage('foo'); -} catch (Exception $e) { +} catch (TypeError $e) { printf("Caught %s with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); +} catch (Mosquitto\Exception $e) { + printf("Caught TypeError with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); } unset($client); @@ -28,15 +30,14 @@ $client2 = new Mosquitto\Client; $client2->connect(TEST_MQTT_HOST); $client2->publish('test', 'test', 1); -for ($i = 0; $i < 3; $i++) { +for ($i = 0; $i < 30; $i++) { $client->loop(50); $client2->loop(50); } ?> --EXPECTF-- -Caught error 4096 (Argument 1 passed to Mosquitto\Client::onMessage() must be callable, string given) in %s on line %d -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::onMessage() expects parameter 1 to be a valid callback, function 'foo' not found or invalid function name +%ACaught TypeError with code 0 and message: %s object(Mosquitto\Client)#%d (%d) { } object(Mosquitto\Message)#%d (%d) { diff --git a/tests/Client/onSubscribe.phpt b/tests/Client/onSubscribe.phpt index 0eca345..1304ace 100644 --- a/tests/Client/onSubscribe.phpt +++ b/tests/Client/onSubscribe.phpt @@ -9,8 +9,10 @@ include(dirname(__DIR__) . '/setup.php'); try { $client = new Mosquitto\Client; $client->onSubscribe('foo'); -} catch (Exception $e) { +} catch (TypeError $e) { printf("Caught %s with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); +} catch (Mosquitto\Exception $e) { + printf("Caught TypeError with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); } unset($client); @@ -29,8 +31,7 @@ $client->loopForever(); ?> --EXPECTF-- -Caught error 4096 (Argument 1 passed to Mosquitto\Client::onSubscribe() must be callable, string given) in %s on line 6 -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::onSubscribe() expects parameter 1 to be a valid callback, function 'foo' not found or invalid function name +%ACaught TypeError with code 0 and message: %s array(3) { [0]=> int(1) diff --git a/tests/Client/onUnsubscribe.phpt b/tests/Client/onUnsubscribe.phpt index 0220bf4..085aa1a 100644 --- a/tests/Client/onUnsubscribe.phpt +++ b/tests/Client/onUnsubscribe.phpt @@ -9,8 +9,10 @@ include(dirname(__DIR__) . '/setup.php'); try { $client = new Mosquitto\Client; $client->onUnsubscribe('foo'); -} catch (Exception $e) { +} catch (TypeError $e) { printf("Caught %s with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); +} catch (Mosquitto\Exception $e) { + printf("Caught TypeError with code %d and message: %s\n", get_class($e), $e->getCode(), $e->getMessage()); } unset($client); @@ -34,8 +36,7 @@ $client->loopForever(); ?> --EXPECTF-- -Caught error 4096 (Argument 1 passed to Mosquitto\Client::onUnsubscribe() must be callable, string given) in %s on line 6 -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::onUnsubscribe() expects parameter 1 to be a valid callback, function 'foo' not found or invalid function name +%ACaught TypeError with code 0 and message: %s array(3) { [0]=> int(1) diff --git a/tests/Client/publish.phpt b/tests/Client/publish.phpt index bbadffc..3418138 100644 --- a/tests/Client/publish.phpt +++ b/tests/Client/publish.phpt @@ -114,7 +114,7 @@ Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::publish() Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::publish() expects parameter 1 to be string, object given Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::publish() expects at least 2 parameters, 1 given Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::publish() expects at least 2 parameters, 1 given -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::publish() expects parameter 3 to be long, object given +Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::publish() expects parameter 3 to be %s, object given Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::publish() expects parameter 4 to be boolean, object given Caught Mosquitto\Exception with code 0 and message: The client is not currently connected. Caught Mosquitto\Exception with code 0 and message: The client is not currently connected. diff --git a/tests/Client/setMaxInFlightMessages.phpt b/tests/Client/setMaxInFlightMessages.phpt index bbcfe2b..8eff9cc 100644 --- a/tests/Client/setMaxInFlightMessages.phpt +++ b/tests/Client/setMaxInFlightMessages.phpt @@ -37,5 +37,5 @@ object(Mosquitto\Client)#%d (0) { } object(Mosquitto\Client)#%d (0) { } -string(87) "Mosquitto\Client::setMaxInFlightMessages() expects parameter 1 to be long, string given" -string(87) "Mosquitto\Client::setMaxInFlightMessages() expects parameter 1 to be long, object given" +string(%d) "Mosquitto\Client::setMaxInFlightMessages() expects parameter 1 to be %s, string given" +string(%d) "Mosquitto\Client::setMaxInFlightMessages() expects parameter 1 to be %s, object given" diff --git a/tests/Client/setMessageRetry.phpt b/tests/Client/setMessageRetry.phpt index 2f30bb7..ed83dfe 100644 --- a/tests/Client/setMessageRetry.phpt +++ b/tests/Client/setMessageRetry.phpt @@ -37,5 +37,5 @@ object(Mosquitto\Client)#%d (0) { } object(Mosquitto\Client)#%d (0) { } -string(80) "Mosquitto\Client::setMessageRetry() expects parameter 1 to be long, string given" -string(80) "Mosquitto\Client::setMessageRetry() expects parameter 1 to be long, object given" +string(%d) "Mosquitto\Client::setMessageRetry() expects parameter 1 to be %s, string given" +string(%d) "Mosquitto\Client::setMessageRetry() expects parameter 1 to be %s, object given" diff --git a/tests/Client/setReconnectDelay.phpt b/tests/Client/setReconnectDelay.phpt index 39d2ad0..f787fbc 100644 --- a/tests/Client/setReconnectDelay.phpt +++ b/tests/Client/setReconnectDelay.phpt @@ -37,5 +37,5 @@ object(Mosquitto\Client)#%d (0) { } object(Mosquitto\Client)#%d (0) { } -string(82) "Mosquitto\Client::setReconnectDelay() expects parameter 1 to be long, string given" -string(82) "Mosquitto\Client::setReconnectDelay() expects parameter 1 to be long, object given" +string(%d) "Mosquitto\Client::setReconnectDelay() expects parameter 1 to be %s, string given" +string(%d) "Mosquitto\Client::setReconnectDelay() expects parameter 1 to be %s, object given" diff --git a/tests/Client/setTlsOptions.phpt b/tests/Client/setTlsOptions.phpt index 39209e8..74aff0e 100644 --- a/tests/Client/setTlsOptions.phpt +++ b/tests/Client/setTlsOptions.phpt @@ -38,7 +38,7 @@ $client->setTlsOptions(Mosquitto\Client::SSL_VERIFY_PEER, 'tlsv1.2', 'DEFAULT'); ?> --EXPECTF-- Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::setTlsOptions() expects at least 1 parameter, 0 given -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::setTlsOptions() expects parameter 1 to be long, object given +Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::setTlsOptions() expects parameter 1 to be %s, object given Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::setTlsOptions() expects parameter 2 to be string, object given Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::setTlsOptions() expects parameter 3 to be string, object given diff --git a/tests/Client/subscribe.phpt b/tests/Client/subscribe.phpt index 11ae014..0b7864d 100644 --- a/tests/Client/subscribe.phpt +++ b/tests/Client/subscribe.phpt @@ -73,7 +73,7 @@ Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::subscribe( Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::subscribe() expects exactly 2 parameters, 1 given Caught Mosquitto\Exception with code 0 and message: The client is not currently connected. Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::subscribe() expects parameter 1 to be string, object given -Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::subscribe() expects parameter 2 to be long, object given +Caught Mosquitto\Exception with code 0 and message: Mosquitto\Client::subscribe() expects parameter 2 to be %s, object given array(3) { [0]=> int(%d) diff --git a/tests/Message/__construct.phpt b/tests/Message/__construct.phpt index 823835a..a5dc868 100644 --- a/tests/Message/__construct.phpt +++ b/tests/Message/__construct.phpt @@ -77,8 +77,7 @@ object(Mosquitto\Message)#1 (5) { bool(false) } Caught error 4096 (Object of class stdClass could not be converted to string) in %s on line 16 -Caught error 8 (Object of class stdClass to string conversion) in %s on line 16 -object(Mosquitto\Message)#1 (5) { +%Aobject(Mosquitto\Message)#1 (5) { ["mid"]=> int(%d) ["topic"]=> @@ -103,8 +102,7 @@ object(Mosquitto\Message)#1 (5) { bool(false) } Caught error 4096 (Object of class stdClass could not be converted to string) in %s on line 22 -Caught error 8 (Object of class stdClass to string conversion) in %s on line 22 -object(Mosquitto\Message)#1 (5) { +%Aobject(Mosquitto\Message)#1 (5) { ["mid"]=> int(%d) ["topic"]=> diff --git a/tests/setup.php b/tests/setup.php index dfb8e45..c46d4dd 100644 --- a/tests/setup.php +++ b/tests/setup.php @@ -2,6 +2,11 @@ define('CERTIFICATE_DIR', __DIR__ . '/certs/'); +if (!class_exists("TypeError")) { + // Hack for PHP7 throwing type mismatches as TypeErrors rather than Mosquito\Exception + class TypeError extends Exception {} +} + $defaults = array( 'TEST_MQTT_HOST' => 'localhost', 'TEST_MQTT_PORT' => 1883,