Commit 2708378d2177da44a4571168cb0f3e9783d9cb96
1 parent
294187800e
Exists in
master
start
Signed-off-by: Tom Huang <tom_huang@sanlien.com.tw>
Showing
4 changed files
with
1092 additions
and
0 deletions
Show diff stats
README.md
| ... | ... | @@ -0,0 +1,427 @@ |
| 1 | +# Mosquitto-PHP | |
| 2 | + | |
| 3 | +This is an extension to allow using the [Mosquitto MQTT library](http://mosquitto.org) with PHP. See the examples/ directory for usage. | |
| 4 | + | |
| 5 | +[](https://travis-ci.org/mgdm/Mosquitto-PHP) | |
| 6 | + | |
| 7 | +## Requirements | |
| 8 | + | |
| 9 | +* PHP 5.3+ | |
| 10 | +* libmosquitto 1.2.x | |
| 11 | +* Linux or Mac OS X. I do not have a Windows machine handy, though patches or | |
| 12 | + pull requests are of course very welcome! | |
| 13 | + | |
| 14 | +## Installation | |
| 15 | + | |
| 16 | +You may obtain this package using [PECL](http://pecl.php.net): | |
| 17 | + | |
| 18 | +```` | |
| 19 | +pecl install Mosquitto-alpha | |
| 20 | +```` | |
| 21 | + | |
| 22 | +Alternatively, you can use the normal extension build process: | |
| 23 | + | |
| 24 | +```` | |
| 25 | +phpize | |
| 26 | +./configure --with-mosquitto=/path/to/libmosquitto | |
| 27 | +make | |
| 28 | +make install | |
| 29 | +```` | |
| 30 | + | |
| 31 | +Then add `extension=mosquitto.so` to your `php.ini`. | |
| 32 | + | |
| 33 | +The `--with-mosquitto` argument is optional, and only required if your | |
| 34 | +libmosquitto install cannot be found. | |
| 35 | + | |
| 36 | +## Documentation | |
| 37 | + | |
| 38 | +The classes in this extension are namespaced. | |
| 39 | + | |
| 40 | +### Class Mosquitto\Client | |
| 41 | + | |
| 42 | +This is the actual Mosquitto client. | |
| 43 | + | |
| 44 | +1. [__construct](#__construct) - create a new client | |
| 45 | +1. [setCredentials](#setcredentials) - set the credentials to use on connection | |
| 46 | +1. [setTlsCertificates](#settlscertificates) - set the TLS certificate sources | |
| 47 | +1. [setTlsInsecure](#settlsinsecure) - Set verification of the server hostname | |
| 48 | + in TLS certificates | |
| 49 | +1. [setTlsOptions](#settlsoptions) - Set advanced TLS options | |
| 50 | +1. [setTlsPSK](#settlspsk) - Configure the client for pre-shared-key based TLS | |
| 51 | + support. | |
| 52 | +1. [setWill](#setwill) - set the client will, to be delivered if disconnected | |
| 53 | + uncleanly | |
| 54 | +1. [clearWill](#clearwill) - clear a previously-set will | |
| 55 | +1. [setReconnectDelay](#setreconnectdelay) - set the behaviour if disconnected | |
| 56 | + uncleanly | |
| 57 | +1. [connect](#connect) - connect to an MQTT broker | |
| 58 | +1. [disconnect](#disconnect) - disconnect from an MQTT broker | |
| 59 | +1. [onConnect](#onconnect) - set the connect callback | |
| 60 | +1. [onDisconnect](#ondisconnect) - set the disconnect callback | |
| 61 | +1. [onLog](#onlog) - set the logging callback | |
| 62 | +1. [onSubscribe](#onsubscribe) - set the subscribe callback | |
| 63 | +1. [onMessage](#onmessage) - set the callback fired when a message is received | |
| 64 | +1. [setMaxInFlightMessages](#setmaxinflightmessages) - set the number of QoS | |
| 65 | + 1 and 2 messages that can be "in flight" at once | |
| 66 | +1. [setMessageRetry](#setmessageretry) - set the number of seconds to wait | |
| 67 | + before retrying messages | |
| 68 | +1. [publish](#publish) - publish a message to a broker | |
| 69 | +1. [subscribe](#subscribe) - subscribe to a topic | |
| 70 | +1. [unsubscribe](#unsubscribe) - unsubscribe from a topic | |
| 71 | +1. [loop](#loop) - The main network loop | |
| 72 | +1. [loopForever](#loopforever) - run loop() in an infinite blocking loop | |
| 73 | + | |
| 74 | +#### __construct | |
| 75 | + | |
| 76 | +Creates a new Client instance. | |
| 77 | + | |
| 78 | +| Parameter | Type | Description | | |
| 79 | +| --- | --- | ---- | | |
| 80 | +| id | string | Client ID. Optional. If not supplied or NULL, one will be generated at random. | | |
| 81 | +| clean_session | boolean | Set to true to instruct the broker to clean all messages and subscriptions on disconnect. | | |
| 82 | + | |
| 83 | +#### setCredentials | |
| 84 | + | |
| 85 | +Set the username and password to use on connecting to the broker. Must be | |
| 86 | +called before connect(). | |
| 87 | + | |
| 88 | +| Parameter | Type | Description | | |
| 89 | +| --- | --- | ---- | | |
| 90 | +| Username | string | Username to supply to the broker | | |
| 91 | +| Password | string | Password to supply to the broker | | |
| 92 | + | |
| 93 | +#### setTlsCertificates | |
| 94 | + | |
| 95 | +Configure the client for certificate based SSL/TLS support. Must be called | |
| 96 | +before connect(). Cannot be used in conjunction with setTlsPSK(). | |
| 97 | + | |
| 98 | +Define the Certificate Authority certificates to be trusted (ie. the server | |
| 99 | +certificate must be signed with one of these certificates) using cafile. | |
| 100 | +If the server you are connecting to requires clients to provide a certificate, | |
| 101 | +define certfile and keyfile with your client certificate and private key. If | |
| 102 | +your private key is encrypted, provide the password as the fourth parameter, or | |
| 103 | +you will have to enter the password at the command line. | |
| 104 | + | |
| 105 | +| Parameter | Type | Description | | |
| 106 | +| --- | --- | ---- | | |
| 107 | +| capath | string | Path to the PEM encoded trusted CA certificate files, or to a directory containing them | | |
| 108 | +| certfile | string | Path to the PEM encoded certificate file for this client. Optional. | | |
| 109 | +| keyfile | string | Path to a file containing the PEM encoded private key for this client. Required if certfile is set. | | |
| 110 | +| password | string | The password for the keyfile, if it is encrypted. If null, the password will be asked for on the command line. | | |
| 111 | + | |
| 112 | +#### setTlsInsecure | |
| 113 | + | |
| 114 | +Configure verification of the server hostname in the server certificate. If | |
| 115 | +value is set to true, it is impossible to guarantee that the host you are | |
| 116 | +connecting to is not impersonating your server. Do not use this function in | |
| 117 | +a real system. Must be called before connect(). | |
| 118 | + | |
| 119 | +| Parameter | Type | Description | | |
| 120 | +| --- | --- | ---- | | |
| 121 | +| value | boolean | If set to false, the default, certificate hostname checking is performed. If set to true, no hostname checking is performed and the connection is insecure. | | |
| 122 | + | |
| 123 | +#### setTlsOptions | |
| 124 | + | |
| 125 | +Set advanced SSL/TLS options. Must be called before connect(). | |
| 126 | + | |
| 127 | +| Parameter | Type | Description | | |
| 128 | +| --- | --- | ---- | | |
| 129 | +| certReqs | int | Whether or not to verify the server. Can be Mosquitto\Client::SSL_VERIFY_NONE, to disable certificate verification, or Mosquitto\Client::SSL_VERIFY_PEER (the default), to verify the server certificate. | | |
| 130 | +| tlsVersion | string | The TLS version to use. If NULL, a default is used. The default value depends on the version of OpenSSL the library was compiled against. Available options on OpenSSL >= 1.0.1 are 'tlsv1.2', 'tlsv1.1' and 'tlsv1'. | | |
| 131 | +| cipers | string | A string describing the ciphers available for use. See the `openssl ciphers` tool for more information. If NULL, the default set will be used. | | |
| 132 | + | |
| 133 | +#### setTlsPSK | |
| 134 | + | |
| 135 | +Configure the client for pre-shared-key based TLS support. Must be called before connect(). Cannot be used in conjunction with setTlsCertificates. | |
| 136 | + | |
| 137 | +| Parameter | Type | Description | | |
| 138 | +| --- | --- | ---- | | |
| 139 | +| psk | string | The pre-shared key in hex format with no leading "0x". | |
| 140 | +| identity | string | The identity of this client. May be used as the username depending on server settings. | | |
| 141 | +| cipers | string | Optional. A string describing the ciphers available for use. See the `openssl ciphers` tool for more information. If NULL, the default set will be used. | | |
| 142 | + | |
| 143 | +#### setWill | |
| 144 | + | |
| 145 | +Set the client "last will and testament", which will be sent on an unclean | |
| 146 | +disconnection from the broker. Must be called before connect(). | |
| 147 | + | |
| 148 | +| Parameter | Type | Description | | |
| 149 | +| --- | --- | ---- | | |
| 150 | +| topic | string | The topic on which to publish the will. | | |
| 151 | +| payload | string | The data to send. | | |
| 152 | +| qos | int | Optional. Default 0. Integer 0, 1, or 2 indicating the Quality of Service to be used. | | |
| 153 | +| retain | boolean | Optional. Default false. If true, the message will be retained. | | |
| 154 | + | |
| 155 | +#### clearWill | |
| 156 | + | |
| 157 | +Remove a previously-set will. No parameters. | |
| 158 | + | |
| 159 | +#### setReconnectDelay | |
| 160 | + | |
| 161 | +Control the behaviour of the client when it has unexpectedly disconnected in | |
| 162 | +loopForever. The default behaviour if this method is not used is to | |
| 163 | +repeatedly attempt to reconnect with a delay of 1 second until the connection | |
| 164 | +succeeds. | |
| 165 | + | |
| 166 | +| Parameter | Type | Description | | |
| 167 | +| --- | --- | ---- | | |
| 168 | +| reconnect_delay | int | Set delay between successive reconnection attempts. | | |
| 169 | +| reconnect_delay | int | Set max delay between successive reconnection attempts when exponential backoff is enabled | | |
| 170 | +| exponential_backoff | bool | Enable exponential backoff | | |
| 171 | + | |
| 172 | +#### connect | |
| 173 | + | |
| 174 | +Connect to an MQTT broker. | |
| 175 | + | |
| 176 | +| Parameter | Type | Description | | |
| 177 | +| --- | --- | ---- | | |
| 178 | +| host | string | Hostname to connect to | | |
| 179 | +| port | int | Optional. Port number to connect to. Defaults to 1883. | | |
| 180 | +| keepalive | int | Optional. Number of sections after which the broker should PING the client if no messages have been recieved. | | |
| 181 | +| interface | string | Optional. The address or hostname of a local interface to bind to for this connection. | | |
| 182 | + | |
| 183 | +#### disconnect | |
| 184 | + | |
| 185 | +Disconnect from the broker. No parameters. | |
| 186 | + | |
| 187 | +#### onConnect | |
| 188 | + | |
| 189 | +Set the connect callback. This is called when the broker sends a CONNACK message in response to a connection. | |
| 190 | + | |
| 191 | +| Parameter | Type | Description | | |
| 192 | +| --- | --- | ---- | | |
| 193 | +| callback | callback | The callback | | |
| 194 | + | |
| 195 | +The callback should take parameters of the form: | |
| 196 | + | |
| 197 | +| Parameter | Type | Description | | |
| 198 | +| --- | --- | ---- | | |
| 199 | +| rc | int | Response code from the broker. | | |
| 200 | +| message | string | String description of the response code. | | |
| 201 | + | |
| 202 | +Response codes are as follows: | |
| 203 | + | |
| 204 | +| Code | Meaning | | |
| 205 | +| --- | --- | | |
| 206 | +| 0 | Success | | |
| 207 | +| 1 | Connection refused (unacceptable protocol version) | | |
| 208 | +| 2 | Connection refused (identifier rejected) | | |
| 209 | +| 3 | Connection refused (broker unavailable ) | | |
| 210 | +| 4-255 | Reserved for future use | | |
| 211 | + | |
| 212 | +#### onDisconnect | |
| 213 | + | |
| 214 | +Set the disconnect callback. This is called when the broker has received the | |
| 215 | +DISCONNECT command and has disconnected the client. | |
| 216 | + | |
| 217 | +| Parameter | Type | Description | | |
| 218 | +| --- | --- | ---- | | |
| 219 | +| callback | callback | The callback | | |
| 220 | + | |
| 221 | +The callback should take parameters of the form: | |
| 222 | + | |
| 223 | +| Parameter | Type | Description | | |
| 224 | +| --- | --- | ---- | | |
| 225 | +| rc | int | Reason for the disconnection. 0 means the client requested it. Any other value indicates an unexpected disconnection. | | |
| 226 | + | |
| 227 | +#### onLog | |
| 228 | + | |
| 229 | +Set the logging callback. | |
| 230 | + | |
| 231 | +| Parameter | Type | Description | | |
| 232 | +| --- | --- | ---- | | |
| 233 | +| callback | callback | The callback | | |
| 234 | + | |
| 235 | +The callback should take parameters of the form: | |
| 236 | + | |
| 237 | +| Parameter | Type | Description | | |
| 238 | +| --- | --- | ---- | | |
| 239 | +| level | int | The log message level from the values below | | |
| 240 | +| str | string | The message string. | |
| 241 | + | |
| 242 | +The level can be one of: | |
| 243 | + | |
| 244 | +* Mosquitto\Client::LOG_DEBUG | |
| 245 | +* Mosquitto\Client::LOG_INFO | |
| 246 | +* Mosquitto\Client::LOG_NOTICE | |
| 247 | +* Mosquitto\Client::LOG_WARNING | |
| 248 | +* Mosquitto\Client::LOG_ERR | |
| 249 | + | |
| 250 | +#### onSubscribe | |
| 251 | + | |
| 252 | +Set the subscribe callback. This is called when the broker responds to | |
| 253 | +a subscription request. | |
| 254 | + | |
| 255 | +| Parameter | Type | Description | | |
| 256 | +| --- | --- | ---- | | |
| 257 | +| callback | callback | The callback | | |
| 258 | + | |
| 259 | +The callback should take parameters of the form: | |
| 260 | + | |
| 261 | +| Parameter | Type | Description | | |
| 262 | +| --- | --- | ---- | | |
| 263 | +| mid | int | Message ID of the subscribe message | | |
| 264 | +| qos_count | int | Number of granted subscriptions | | |
| 265 | + | |
| 266 | +This function needs to return the granted QoS for each subscription, but | |
| 267 | +currently cannot. | |
| 268 | + | |
| 269 | +#### onUnsubscribe | |
| 270 | + | |
| 271 | +Set the unsubscribe callback. This is called when the broker responds to | |
| 272 | +a unsubscribe request. | |
| 273 | + | |
| 274 | +| Parameter | Type | Description | | |
| 275 | +| --- | --- | ---- | | |
| 276 | +| callback | callback | The callback | | |
| 277 | + | |
| 278 | +The callback should take parameters of the form: | |
| 279 | + | |
| 280 | +| Parameter | Type | Description | | |
| 281 | +| --- | --- | ---- | | |
| 282 | +| mid | int | Message ID of the unsubscribe message | | |
| 283 | + | |
| 284 | +#### onMessage | |
| 285 | + | |
| 286 | +Set the message callback. This is called when a message is received from the broker. | |
| 287 | + | |
| 288 | +| Parameter | Type | Description | | |
| 289 | +| --- | --- | ---- | | |
| 290 | +| callback | callback | The callback | | |
| 291 | + | |
| 292 | +The callback should take parameters of the form: | |
| 293 | + | |
| 294 | +| Parameter | Type | Description | | |
| 295 | +| --- | --- | ---- | | |
| 296 | +| message | Mosquitto\Message | A Message object containing the message data | | |
| 297 | + | |
| 298 | + | |
| 299 | +#### setMaxInFlightMessages | |
| 300 | + | |
| 301 | +Set the number of QoS 1 and 2 messages that can be โin flightโ at one time. An | |
| 302 | +in flight message is part way through its delivery flow. Attempts to send | |
| 303 | +further messages with publish() will result in the messages being queued until | |
| 304 | +the number of in flight messages reduces. | |
| 305 | + | |
| 306 | +Set to 0 for no maximum. | |
| 307 | + | |
| 308 | +| Parameter | Type | Description | | |
| 309 | +| --- | --- | ---- | | |
| 310 | +| max_inflight_messages | int | The maximum | | |
| 311 | + | |
| 312 | +#### setMessageRetry | |
| 313 | + | |
| 314 | +Set the number of seconds to wait before retrying messages. This applies to | |
| 315 | +publish messages with QoS>0. May be called at any time. | |
| 316 | + | |
| 317 | +| Parameter | Type | Description | | |
| 318 | +| --- | --- | ---- | | |
| 319 | +| message_retry | int | The retry period | | |
| 320 | + | |
| 321 | +#### publish | |
| 322 | + | |
| 323 | +Publish a message on a given topic. | |
| 324 | + | |
| 325 | +| Parameter | Type | Description | | |
| 326 | +| --- | --- | ---- | | |
| 327 | +| topic | string | The topic to publish on | | |
| 328 | +| payload | string | The message payload | | |
| 329 | +| qos | int | Integer value 0, 1 or 2 indicating the QoS for this message | | |
| 330 | +| retain | boolean | If true, make this message retained | | |
| 331 | + | |
| 332 | +#### subscribe | |
| 333 | + | |
| 334 | +Subscribe to a topic. | |
| 335 | + | |
| 336 | +| Parameter | Type | Description | | |
| 337 | +| --- | --- | ---- | | |
| 338 | +| topic | string | The topic. | | |
| 339 | +| qos | The QoS to request for this subscription | | |
| 340 | + | |
| 341 | +Returns the message ID of the subscription message, so this can be matched up | |
| 342 | +in the onSubscribe callback. | |
| 343 | + | |
| 344 | +#### unsubscribe | |
| 345 | + | |
| 346 | +Unsubscribe from a topic. | |
| 347 | + | |
| 348 | +| Parameter | Type | Description | | |
| 349 | +| --- | --- | ---- | | |
| 350 | +| topic | string | The topic. | | |
| 351 | +| qos | The QoS to request for this subscription | | |
| 352 | + | |
| 353 | +Returns the message ID of the subscription message, so this can be matched up | |
| 354 | +in the onUnsubscribe callback. | |
| 355 | + | |
| 356 | +#### loop | |
| 357 | + | |
| 358 | +The main network loop for the client. You must call this frequently in order | |
| 359 | +to keep communications between the client and broker working. If incoming data | |
| 360 | +is present it will then be processed. Outgoing commands, from e.g. publish(), | |
| 361 | +are normally sent immediately that their function is called, but this is not | |
| 362 | +always possible. loop() will also attempt to send any remaining outgoing | |
| 363 | +messages, which also includes commands that are part of the flow for messages | |
| 364 | +with QoS>0. | |
| 365 | + | |
| 366 | +| Parameter | Type | Description | | |
| 367 | +| --- | --- | ---- | | |
| 368 | +| timeout | int | Optional. Number of milliseconds to wait for network activity. Pass 0 for instant timeout. Defaults to 1000. | | |
| 369 | +| max_packets | int | Currently unused. | | |
| 370 | + | |
| 371 | +#### loopForever | |
| 372 | + | |
| 373 | +Call loop() in an infinite blocking loop. Callbacks will be called as required. | |
| 374 | +This will handle reconnecting if the connection is lost. Call disconnect() in | |
| 375 | +a callback to return from the loop. | |
| 376 | + | |
| 377 | +Note: exceptions thrown in callbacks do not currently cause the loop to exit. To work around this, use loop() and wrap your own loop structure around it such as a while(). | |
| 378 | + | |
| 379 | +| Parameter | Type | Description | | |
| 380 | +| --- | --- | ---- | | |
| 381 | +| timeout | int | Optional. Number of milliseconds to wait for network activity. Pass 0 for instant timeout. Defaults to 1000. | | |
| 382 | +| max_packets | int | Currently unused. | | |
| 383 | + | |
| 384 | +### Class Mosquitto\Message | |
| 385 | + | |
| 386 | +Represents a message received from a broker. All data is represented as | |
| 387 | +properties. | |
| 388 | + | |
| 389 | +| Property | Type | Description | | |
| 390 | +| --- | --- | --- | | |
| 391 | +| topic | string | The topic this message was delivered to. | | |
| 392 | +| payload | string | The payload of this message. | | |
| 393 | +| mid | int | The ID of this message. | | |
| 394 | +| qos | int | The QoS value applied to this message. | | |
| 395 | +| retain | bool | Whether this is a retained message or not. | | |
| 396 | + | |
| 397 | +This class has two static methods. | |
| 398 | + | |
| 399 | +#### topicMatchesSub | |
| 400 | + | |
| 401 | +Returns true if the supplied topic matches the supplied description, and | |
| 402 | +otherwise false. | |
| 403 | + | |
| 404 | +| Parameter | Type | Description | | |
| 405 | +| --- | --- | ---- | | |
| 406 | +| topic | string | The topic to match | | |
| 407 | +| subscription | string | The subscription to match | | |
| 408 | + | |
| 409 | +#### tokeniseTopic | |
| 410 | + | |
| 411 | +Tokenise a topic or subscription string into an array of strings representing the topic hierarchy. | |
| 412 | + | |
| 413 | +| Parameter | Type | Description | | |
| 414 | +| --- | --- | ---- | | |
| 415 | +| topic | string | The topic to tokenise | | |
| 416 | + | |
| 417 | +### Class Mosquitto\Exception | |
| 418 | + | |
| 419 | +This is an exception that may be thrown by many of the operations in the Client | |
| 420 | +object. | |
| 421 | + | |
| 422 | +## To do | |
| 423 | + | |
| 424 | +* Arginfo | |
| 425 | +* Logging callbacks | |
| 426 | +* TLS support | |
| 427 | +* Tests | ... | ... |
mosquitto_message.c
| ... | ... | @@ -0,0 +1,425 @@ |
| 1 | +#ifdef HAVE_CONFIG_H | |
| 2 | +#include "config.h" | |
| 3 | +#endif | |
| 4 | + | |
| 5 | +#include "php.h" | |
| 6 | +#include "php_ini.h" | |
| 7 | +#include "zend_variables.h" | |
| 8 | +#include "zend_exceptions.h" | |
| 9 | +#include "zend_API.h" | |
| 10 | +#include "ext/standard/info.h" | |
| 11 | +#include "php_mosquitto.h" | |
| 12 | + | |
| 13 | +zend_class_entry *mosquitto_ce_message; | |
| 14 | +static zend_object_handlers mosquitto_message_object_handlers; | |
| 15 | +static HashTable php_mosquitto_message_properties; | |
| 16 | + | |
| 17 | +/* {{{ Arginfo */ | |
| 18 | + | |
| 19 | +ZEND_BEGIN_ARG_INFO(Mosquitto_Message_topicMatchesSub_args, ZEND_SEND_BY_VAL) | |
| 20 | + ZEND_ARG_INFO(0, topic) | |
| 21 | + ZEND_ARG_INFO(0, subscription) | |
| 22 | +ZEND_END_ARG_INFO() | |
| 23 | + | |
| 24 | +ZEND_BEGIN_ARG_INFO(Mosquitto_Message_tokeniseTopic_args, ZEND_SEND_BY_VAL) | |
| 25 | + ZEND_ARG_INFO(0, topic) | |
| 26 | +ZEND_END_ARG_INFO() | |
| 27 | + | |
| 28 | +/* }}} */ | |
| 29 | + | |
| 30 | +PHP_METHOD(Mosquitto_Message, __construct) | |
| 31 | +{ | |
| 32 | + PHP_MOSQUITTO_ERROR_HANDLING(); | |
| 33 | + if (zend_parse_parameters_none() == FAILURE) { | |
| 34 | + PHP_MOSQUITTO_RESTORE_ERRORS(); | |
| 35 | + return; | |
| 36 | + } | |
| 37 | + PHP_MOSQUITTO_RESTORE_ERRORS(); | |
| 38 | +} | |
| 39 | + | |
| 40 | +/* {{{ Mosquitto\Message::topicMatchesSub() */ | |
| 41 | +PHP_METHOD(Mosquitto_Message, topicMatchesSub) | |
| 42 | +{ | |
| 43 | + char *topic = NULL, *subscription = NULL; | |
| 44 | + int topic_len, subscription_len; | |
| 45 | + zend_bool result; | |
| 46 | + | |
| 47 | + PHP_MOSQUITTO_ERROR_HANDLING(); | |
| 48 | + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", | |
| 49 | + &topic, &topic_len, &subscription, &subscription_len) == FAILURE) { | |
| 50 | + PHP_MOSQUITTO_RESTORE_ERRORS(); | |
| 51 | + return; | |
| 52 | + } | |
| 53 | + PHP_MOSQUITTO_RESTORE_ERRORS(); | |
| 54 | + | |
| 55 | + mosquitto_topic_matches_sub(subscription, topic, (bool *) &result); | |
| 56 | + RETURN_BOOL(result); | |
| 57 | +} | |
| 58 | +/* }}} */ | |
| 59 | + | |
| 60 | +/* {{{ Mosquitto\Message::tokeniseTopic() */ | |
| 61 | +PHP_METHOD(Mosquitto_Message, tokeniseTopic) | |
| 62 | +{ | |
| 63 | + char *topic = NULL, **topics = NULL; | |
| 64 | + int topic_len = 0, retval = 0, count = 0, i = 0; | |
| 65 | + | |
| 66 | + PHP_MOSQUITTO_ERROR_HANDLING(); | |
| 67 | + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &topic, &topic_len) == FAILURE) { | |
| 68 | + PHP_MOSQUITTO_RESTORE_ERRORS(); | |
| 69 | + return; | |
| 70 | + } | |
| 71 | + PHP_MOSQUITTO_RESTORE_ERRORS(); | |
| 72 | + | |
| 73 | + retval = mosquitto_sub_topic_tokenise(topic, &topics, &count); | |
| 74 | + | |
| 75 | + if (retval == MOSQ_ERR_NOMEM) { | |
| 76 | + zend_throw_exception_ex(mosquitto_ce_exception, 0 TSRMLS_CC, "Failed to tokenise topic"); | |
| 77 | + return; | |
| 78 | + } | |
| 79 | + | |
| 80 | + array_init(return_value); | |
| 81 | + for (i = 0; i < count; i++) { | |
| 82 | + if (topics[i] == NULL) { | |
| 83 | + add_next_index_null(return_value); | |
| 84 | + } else { | |
| 85 | + add_next_index_string(return_value, topics[i], 1); | |
| 86 | + } | |
| 87 | + } | |
| 88 | + | |
| 89 | + mosquitto_sub_topic_tokens_free(&topics, count); | |
| 90 | +} | |
| 91 | +/* }}} */ | |
| 92 | + | |
| 93 | +PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_READER_FUNCTION(mid); | |
| 94 | +PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_READER_FUNCTION(qos); | |
| 95 | + | |
| 96 | +static int php_mosquitto_message_read_retain(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC) | |
| 97 | +{ | |
| 98 | + MAKE_STD_ZVAL(*retval); | |
| 99 | + ZVAL_BOOL(*retval, mosquitto_object->message.retain); | |
| 100 | + return SUCCESS; | |
| 101 | +} | |
| 102 | + | |
| 103 | +static int php_mosquitto_message_read_topic(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC) | |
| 104 | +{ | |
| 105 | + MAKE_STD_ZVAL(*retval); | |
| 106 | + | |
| 107 | + if (mosquitto_object->message.topic != NULL) { | |
| 108 | + ZVAL_STRINGL(*retval, mosquitto_object->message.topic, strlen(mosquitto_object->message.topic), 1); | |
| 109 | + } else { | |
| 110 | + ZVAL_NULL(*retval); | |
| 111 | + } | |
| 112 | + | |
| 113 | + return SUCCESS; | |
| 114 | +} | |
| 115 | + | |
| 116 | +static int php_mosquitto_message_read_payload(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC) | |
| 117 | +{ | |
| 118 | + MAKE_STD_ZVAL(*retval); | |
| 119 | + ZVAL_STRINGL(*retval, mosquitto_object->message.payload, mosquitto_object->message.payloadlen, 1); | |
| 120 | + return SUCCESS; | |
| 121 | +} | |
| 122 | + | |
| 123 | +PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_WRITER_FUNCTION(mid); | |
| 124 | +PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_WRITER_FUNCTION(qos); | |
| 125 | + | |
| 126 | +static int php_mosquitto_message_write_retain(mosquitto_message_object *mosquitto_object, zval *newval TSRMLS_DC) | |
| 127 | +{ | |
| 128 | + zval ztmp; | |
| 129 | + if (Z_TYPE_P(newval) != IS_BOOL) { | |
| 130 | + ztmp = *newval; | |
| 131 | + zval_copy_ctor(&ztmp); | |
| 132 | + convert_to_boolean(&ztmp); | |
| 133 | + newval = &ztmp; | |
| 134 | + } | |
| 135 | + | |
| 136 | + mosquitto_object->message.retain = Z_LVAL_P(newval); | |
| 137 | + | |
| 138 | + if (newval == &ztmp) { | |
| 139 | + zval_dtor(newval); | |
| 140 | + } | |
| 141 | + | |
| 142 | + return SUCCESS; | |
| 143 | +} | |
| 144 | + | |
| 145 | +static int php_mosquitto_message_write_topic(mosquitto_message_object *mosquitto_object, zval *newval TSRMLS_DC) | |
| 146 | +{ | |
| 147 | + zval ztmp; | |
| 148 | + if (Z_TYPE_P(newval) != IS_STRING) { | |
| 149 | + ztmp = *newval; | |
| 150 | + zval_copy_ctor(&ztmp); | |
| 151 | + convert_to_string(&ztmp); | |
| 152 | + newval = &ztmp; | |
| 153 | + } | |
| 154 | + | |
| 155 | + if (mosquitto_object->message.topic && mosquitto_object->owned_topic) { | |
| 156 | + efree(mosquitto_object->message.topic); | |
| 157 | + } | |
| 158 | + | |
| 159 | + mosquitto_object->message.topic = estrdup(Z_STRVAL_P(newval)); | |
| 160 | + mosquitto_object->owned_topic = 1; | |
| 161 | + | |
| 162 | + if (newval == &ztmp) { | |
| 163 | + zval_dtor(newval); | |
| 164 | + } | |
| 165 | + | |
| 166 | + return SUCCESS; | |
| 167 | +} | |
| 168 | + | |
| 169 | +static int php_mosquitto_message_write_payload(mosquitto_message_object *mosquitto_object, zval *newval TSRMLS_DC) | |
| 170 | +{ | |
| 171 | + zval ztmp; | |
| 172 | + if (Z_TYPE_P(newval) != IS_STRING) { | |
| 173 | + ztmp = *newval; | |
| 174 | + zval_copy_ctor(&ztmp); | |
| 175 | + convert_to_string(&ztmp); | |
| 176 | + newval = &ztmp; | |
| 177 | + } | |
| 178 | + | |
| 179 | + if (mosquitto_object->message.payload && mosquitto_object->owned_payload) { | |
| 180 | + efree(mosquitto_object->message.payload); | |
| 181 | + mosquitto_object->message.payloadlen = 0; | |
| 182 | + } | |
| 183 | + | |
| 184 | + mosquitto_object->message.payload = estrdup(Z_STRVAL_P(newval)); | |
| 185 | + mosquitto_object->message.payloadlen = Z_STRLEN_P(newval); | |
| 186 | + mosquitto_object->owned_payload = 1; | |
| 187 | + | |
| 188 | + if (newval == &ztmp) { | |
| 189 | + zval_dtor(newval); | |
| 190 | + } | |
| 191 | + | |
| 192 | + return SUCCESS; | |
| 193 | +} | |
| 194 | + | |
| 195 | +const php_mosquitto_prop_handler php_mosquitto_message_property_entries[] = { | |
| 196 | + PHP_MOSQUITTO_MESSAGE_PROPERTY_ENTRY_RECORD(mid), | |
| 197 | + PHP_MOSQUITTO_MESSAGE_PROPERTY_ENTRY_RECORD(topic), | |
| 198 | + PHP_MOSQUITTO_MESSAGE_PROPERTY_ENTRY_RECORD(payload), | |
| 199 | + PHP_MOSQUITTO_MESSAGE_PROPERTY_ENTRY_RECORD(qos), | |
| 200 | + PHP_MOSQUITTO_MESSAGE_PROPERTY_ENTRY_RECORD(retain), | |
| 201 | + {NULL, 0, NULL, NULL} | |
| 202 | +}; | |
| 203 | + | |
| 204 | +zval *php_mosquitto_message_read_property(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC) | |
| 205 | +{ | |
| 206 | + zval tmp_member; | |
| 207 | + zval *retval; | |
| 208 | + mosquitto_message_object *message_object; | |
| 209 | + php_mosquitto_prop_handler *hnd; | |
| 210 | + int ret; | |
| 211 | + | |
| 212 | + message_object = (mosquitto_message_object *) zend_object_store_get_object(object TSRMLS_CC); | |
| 213 | + | |
| 214 | + if (Z_TYPE_P(member) != IS_STRING) { | |
| 215 | + tmp_member = *member; | |
| 216 | + zval_copy_ctor(&tmp_member); | |
| 217 | + convert_to_string(&tmp_member); | |
| 218 | + member = &tmp_member; | |
| 219 | + } | |
| 220 | + | |
| 221 | + ret = zend_hash_find(&php_mosquitto_message_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); | |
| 222 | + | |
| 223 | + if (ret == SUCCESS && hnd->read_func) { | |
| 224 | + ret = hnd->read_func(message_object, &retval TSRMLS_CC); | |
| 225 | + if (ret == SUCCESS) { | |
| 226 | + /* ensure we're creating a temporary variable */ | |
| 227 | + Z_SET_REFCOUNT_P(retval, 0); | |
| 228 | + } else { | |
| 229 | + retval = EG(uninitialized_zval_ptr); | |
| 230 | + } | |
| 231 | + } else { | |
| 232 | + zend_object_handlers * std_hnd = zend_get_std_object_handlers(); | |
| 233 | + retval = std_hnd->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC); | |
| 234 | + } | |
| 235 | + | |
| 236 | + if (member == &tmp_member) { | |
| 237 | + zval_dtor(member); | |
| 238 | + } | |
| 239 | + | |
| 240 | + return(retval); | |
| 241 | +} | |
| 242 | + | |
| 243 | +void php_mosquitto_message_write_property(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC) | |
| 244 | +{ | |
| 245 | + zval tmp_member; | |
| 246 | + mosquitto_message_object *obj; | |
| 247 | + php_mosquitto_prop_handler *hnd; | |
| 248 | + int ret; | |
| 249 | + | |
| 250 | + if (Z_TYPE_P(member) != IS_STRING) { | |
| 251 | + tmp_member = *member; | |
| 252 | + zval_copy_ctor(&tmp_member); | |
| 253 | + convert_to_string(&tmp_member); | |
| 254 | + member = &tmp_member; | |
| 255 | + } | |
| 256 | + | |
| 257 | + ret = FAILURE; | |
| 258 | + obj = (mosquitto_message_object *)zend_objects_get_address(object TSRMLS_CC); | |
| 259 | + | |
| 260 | + ret = zend_hash_find(&php_mosquitto_message_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &hnd); | |
| 261 | + | |
| 262 | + if (ret == SUCCESS && hnd->write_func) { | |
| 263 | + hnd->write_func(obj, value TSRMLS_CC); | |
| 264 | + if (! PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) == 0) { | |
| 265 | + Z_ADDREF_P(value); | |
| 266 | + zval_ptr_dtor(&value); | |
| 267 | + } | |
| 268 | + } else { | |
| 269 | + zend_object_handlers * std_hnd = zend_get_std_object_handlers(); | |
| 270 | + std_hnd->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC); | |
| 271 | + } | |
| 272 | + | |
| 273 | + if (member == &tmp_member) { | |
| 274 | + zval_dtor(member); | |
| 275 | + } | |
| 276 | +} | |
| 277 | + | |
| 278 | +static int php_mosquitto_message_has_property(zval *object, zval *member, int has_set_exists ZEND_LITERAL_KEY_DC TSRMLS_DC) | |
| 279 | +{ | |
| 280 | + php_mosquitto_prop_handler *hnd; | |
| 281 | + int ret = 0; | |
| 282 | + | |
| 283 | + if (zend_hash_find(&php_mosquitto_message_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&hnd) == SUCCESS) { | |
| 284 | + switch (has_set_exists) { | |
| 285 | + case 2: | |
| 286 | + ret = 1; | |
| 287 | + break; | |
| 288 | + case 0: { | |
| 289 | + zval *value = php_mosquitto_message_read_property(object, member, BP_VAR_IS ZEND_LITERAL_KEY_CC TSRMLS_CC); | |
| 290 | + if (value != EG(uninitialized_zval_ptr)) { | |
| 291 | + ret = Z_TYPE_P(value) != IS_NULL? 1:0; | |
| 292 | + /* refcount is 0 */ | |
| 293 | + Z_ADDREF_P(value); | |
| 294 | + zval_ptr_dtor(&value); | |
| 295 | + } | |
| 296 | + break; | |
| 297 | + } | |
| 298 | + default: { | |
| 299 | + zval *value = php_mosquitto_message_read_property(object, member, BP_VAR_IS ZEND_LITERAL_KEY_CC TSRMLS_CC); | |
| 300 | + if (value != EG(uninitialized_zval_ptr)) { | |
| 301 | + convert_to_boolean(value); | |
| 302 | + ret = Z_BVAL_P(value)? 1:0; | |
| 303 | + /* refcount is 0 */ | |
| 304 | + Z_ADDREF_P(value); | |
| 305 | + zval_ptr_dtor(&value); | |
| 306 | + } | |
| 307 | + break; | |
| 308 | + } | |
| 309 | + } | |
| 310 | + } else { | |
| 311 | + zend_object_handlers * std_hnd = zend_get_std_object_handlers(); | |
| 312 | + ret = std_hnd->has_property(object, member, has_set_exists ZEND_LITERAL_KEY_CC TSRMLS_CC); | |
| 313 | + } | |
| 314 | + return ret; | |
| 315 | +} | |
| 316 | + | |
| 317 | +static HashTable *php_mosquitto_message_get_properties(zval *object TSRMLS_DC) | |
| 318 | +{ | |
| 319 | + mosquitto_message_object *obj; | |
| 320 | + php_mosquitto_prop_handler *hnd; | |
| 321 | + HashTable *props; | |
| 322 | + zval *val; | |
| 323 | + char *key; | |
| 324 | + uint key_len; | |
| 325 | + HashPosition pos; | |
| 326 | + ulong num_key; | |
| 327 | + | |
| 328 | + obj = (mosquitto_message_object *)zend_objects_get_address(object TSRMLS_CC); | |
| 329 | + props = zend_std_get_properties(object TSRMLS_CC); | |
| 330 | + | |
| 331 | + zend_hash_internal_pointer_reset_ex(&php_mosquitto_message_properties, &pos); | |
| 332 | + | |
| 333 | + while (zend_hash_get_current_data_ex(&php_mosquitto_message_properties, (void**)&hnd, &pos) == SUCCESS) { | |
| 334 | + zend_hash_get_current_key_ex(&php_mosquitto_message_properties, &key, &key_len, &num_key, 0, &pos); | |
| 335 | + if (!hnd->read_func || hnd->read_func(obj, &val TSRMLS_CC) != SUCCESS) { | |
| 336 | + val = EG(uninitialized_zval_ptr); | |
| 337 | + Z_ADDREF_P(val); | |
| 338 | + } | |
| 339 | + zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL); | |
| 340 | + zend_hash_move_forward_ex(&php_mosquitto_message_properties, &pos); | |
| 341 | + } | |
| 342 | + return obj->std.properties; | |
| 343 | +} | |
| 344 | + | |
| 345 | + | |
| 346 | +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) | |
| 347 | +{ | |
| 348 | + php_mosquitto_prop_handler p; | |
| 349 | + | |
| 350 | + p.name = (char*) name; | |
| 351 | + p.name_length = name_length; | |
| 352 | + p.read_func = (read_func) ? read_func : NULL; | |
| 353 | + p.write_func = (write_func) ? write_func : NULL; | |
| 354 | + zend_hash_add(h, (char *)name, name_length + 1, &p, sizeof(php_mosquitto_prop_handler), NULL); | |
| 355 | +} | |
| 356 | + | |
| 357 | +static void mosquitto_message_object_destroy(void *object TSRMLS_DC) | |
| 358 | +{ | |
| 359 | + mosquitto_message_object *message = (mosquitto_message_object *) object; | |
| 360 | + zend_hash_destroy(message->std.properties); | |
| 361 | + FREE_HASHTABLE(message->std.properties); | |
| 362 | + | |
| 363 | + if (message->owned_topic == 1) { | |
| 364 | + efree(message->message.topic); | |
| 365 | + } | |
| 366 | + | |
| 367 | + if (message->owned_payload == 1) { | |
| 368 | + efree(message->message.payload); | |
| 369 | + } | |
| 370 | + | |
| 371 | + efree(object); | |
| 372 | +} | |
| 373 | + | |
| 374 | +static zend_object_value mosquitto_message_object_new(zend_class_entry *ce TSRMLS_DC) { | |
| 375 | + | |
| 376 | + zend_object_value retval; | |
| 377 | + mosquitto_message_object *message_obj; | |
| 378 | +#if PHP_VERSION_ID < 50399 | |
| 379 | + zval *temp; | |
| 380 | +#endif | |
| 381 | + | |
| 382 | + message_obj = ecalloc(1, sizeof(mosquitto_message_object)); | |
| 383 | + message_obj->std.ce = ce; | |
| 384 | + | |
| 385 | +#ifdef ZTS | |
| 386 | + message_obj->TSRMLS_C = TSRMLS_C; | |
| 387 | +#endif | |
| 388 | + | |
| 389 | + ALLOC_HASHTABLE(message_obj->std.properties); | |
| 390 | + zend_hash_init(message_obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); | |
| 391 | +#if PHP_VERSION_ID < 50399 | |
| 392 | + zend_hash_copy(message_obj->std.properties, &mosquitto_ce_message->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &temp, sizeof(zval *)); | |
| 393 | +#else | |
| 394 | + object_properties_init(&message_obj->std, mosquitto_ce_message); | |
| 395 | +#endif | |
| 396 | + retval.handle = zend_objects_store_put(message_obj, NULL, (zend_objects_free_object_storage_t) mosquitto_message_object_destroy, NULL TSRMLS_CC); | |
| 397 | + retval.handlers = &mosquitto_message_object_handlers; | |
| 398 | + return retval; | |
| 399 | +} | |
| 400 | + | |
| 401 | +const zend_function_entry mosquitto_message_methods[] = { | |
| 402 | + PHP_ME(Mosquitto_Message, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) | |
| 403 | + PHP_ME(Mosquitto_Message, topicMatchesSub, Mosquitto_Message_topicMatchesSub_args, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) | |
| 404 | + PHP_ME(Mosquitto_Message, tokeniseTopic, Mosquitto_Message_tokeniseTopic_args, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) | |
| 405 | + PHP_FE_END | |
| 406 | +}; | |
| 407 | + | |
| 408 | +PHP_MINIT_FUNCTION(mosquitto_message) | |
| 409 | +{ | |
| 410 | + zend_class_entry message_ce; | |
| 411 | + memcpy(&mosquitto_message_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); | |
| 412 | + mosquitto_message_object_handlers.read_property = php_mosquitto_message_read_property; | |
| 413 | + mosquitto_message_object_handlers.write_property = php_mosquitto_message_write_property; | |
| 414 | + mosquitto_message_object_handlers.has_property = php_mosquitto_message_has_property; | |
| 415 | + mosquitto_message_object_handlers.get_properties = php_mosquitto_message_get_properties; | |
| 416 | + | |
| 417 | + INIT_NS_CLASS_ENTRY(message_ce, "Mosquitto", "Message", mosquitto_message_methods); | |
| 418 | + mosquitto_ce_message = zend_register_internal_class(&message_ce TSRMLS_CC); | |
| 419 | + mosquitto_ce_message->create_object = mosquitto_message_object_new; | |
| 420 | + | |
| 421 | + zend_hash_init(&php_mosquitto_message_properties, 0, NULL, NULL, 1); | |
| 422 | + PHP_MOSQUITTO_ADD_PROPERTIES(&php_mosquitto_message_properties, php_mosquitto_message_property_entries); | |
| 423 | + | |
| 424 | + return SUCCESS; | |
| 425 | +} | ... | ... |
package.xml
| ... | ... | @@ -0,0 +1,61 @@ |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<package xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" packagerversion="1.4.7" version="2.0" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> | |
| 3 | + <name>Mosquitto</name> | |
| 4 | + <channel>pecl.mgdm.net</channel> | |
| 5 | + <summary>Extension for libmosquitto</summary> | |
| 6 | + <description>Mosquitto provides support for the MQTT protocol, including publishing, subscribing, and an event loop.</description> | |
| 7 | + <lead> | |
| 8 | + <name>Michael Maclean</name> | |
| 9 | + <user>mgdm</user> | |
| 10 | + <email>mgdm@php.net</email> | |
| 11 | + <active>yes</active> | |
| 12 | + </lead> | |
| 13 | + | |
| 14 | + <date>2014-04-28</date> | |
| 15 | + <version><release>0.2.2</release><api>0.2.0</api></version> | |
| 16 | + <stability><release>alpha</release><api>alpha</api></stability> | |
| 17 | + <license uri="http://opensource.org/licenses/BSD-3-Clause">BSD 3-Clause License</license> | |
| 18 | + <notes> | |
| 19 | + * Add missing unsubscribe method | |
| 20 | + </notes> | |
| 21 | + | |
| 22 | + <contents> | |
| 23 | + <dir name="/"> | |
| 24 | + <file role="doc" name="README.md"/> | |
| 25 | + <file role="doc" name="CREDITS"/> | |
| 26 | + <file role="doc" name="LICENSE"/> | |
| 27 | + | |
| 28 | + <file role="src" name="php_mosquitto.h"/> | |
| 29 | + | |
| 30 | + <file role="src" name="mosquitto.c"/> | |
| 31 | + <file role="src" name="mosquitto_message.c"/> | |
| 32 | + | |
| 33 | + <file role="src" name="config.m4"/> | |
| 34 | + <file role="src" name="config.w32"/> | |
| 35 | + </dir> | |
| 36 | + </contents> | |
| 37 | + | |
| 38 | + <dependencies> | |
| 39 | + <required> | |
| 40 | + <php> | |
| 41 | + <min>5.3.0</min> | |
| 42 | + </php> | |
| 43 | + <pearinstaller> | |
| 44 | + <min>1.4.0</min> | |
| 45 | + </pearinstaller> | |
| 46 | + </required> | |
| 47 | + | |
| 48 | + </dependencies> | |
| 49 | + | |
| 50 | + <providesextension>mosquitto</providesextension> | |
| 51 | + | |
| 52 | + <extsrcrelease> | |
| 53 | + <configureoption default="autodetect" name="with-mosquitto" prompt="Please provide the prefix of the libmosquitto installation" /> | |
| 54 | + </extsrcrelease> | |
| 55 | + | |
| 56 | + <changelog> | |
| 57 | + </changelog> | |
| 58 | +</package> | |
| 59 | +<!-- | |
| 60 | +vim:et:ts=1:sw=1 | |
| 61 | +--> | ... | ... |
php_mosquitto.h
| ... | ... | @@ -0,0 +1,179 @@ |
| 1 | +#ifndef PHP_MOSQUITTO_H | |
| 2 | +#define PHP_MOSQUITTO_H | |
| 3 | + | |
| 4 | +#define PHP_MOSQUITTO_VERSION "0.2.2" | |
| 5 | + | |
| 6 | +extern zend_module_entry mosquitto_module_entry; | |
| 7 | +#define phpext_mosquitto_ptr &mosquitto_module_entry | |
| 8 | + | |
| 9 | +#ifdef PHP_WIN32 | |
| 10 | +# define PHP_MOSQUITTO_API __declspec(dllexport) | |
| 11 | +#elif defined(__GNUC__) && __GNUC__ >= 4 | |
| 12 | +# define PHP_MOSQUITTO_API __attribute__ ((visibility("default"))) | |
| 13 | +#else | |
| 14 | +# define PHP_MOSQUITTO_API | |
| 15 | +#endif | |
| 16 | + | |
| 17 | +#ifdef __GLIBC__ | |
| 18 | +#define POSSIBLY_UNUSED __attribute__((unused)) | |
| 19 | +#else | |
| 20 | +#define POSSIBLY_UNUSED | |
| 21 | +#endif | |
| 22 | + | |
| 23 | +#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50399) | |
| 24 | +# define ZEND_LITERAL_KEY_DC , const zend_literal *_zend_literal_key | |
| 25 | +# define ZEND_LITERAL_KEY_CC , _zend_literal_key | |
| 26 | +# define ZEND_LITERAL_NIL_CC , NULL | |
| 27 | +#else | |
| 28 | +# define ZEND_LITERAL_KEY_DC | |
| 29 | +# define ZEND_LITERAL_KEY_CC | |
| 30 | +# define ZEND_LITERAL_NIL_CC | |
| 31 | +#endif | |
| 32 | + | |
| 33 | +#ifdef ZTS | |
| 34 | +#include "TSRM.h" | |
| 35 | +#endif | |
| 36 | + | |
| 37 | +#include <mosquitto.h> | |
| 38 | + | |
| 39 | +typedef struct _mosquitto_client_object { | |
| 40 | + zend_object std; | |
| 41 | + struct mosquitto *client; | |
| 42 | + | |
| 43 | + zend_fcall_info connect_callback; | |
| 44 | + zend_fcall_info_cache connect_callback_cache; | |
| 45 | + zend_fcall_info subscribe_callback; | |
| 46 | + zend_fcall_info_cache subscribe_callback_cache; | |
| 47 | + zend_fcall_info unsubscribe_callback; | |
| 48 | + zend_fcall_info_cache unsubscribe_callback_cache; | |
| 49 | + zend_fcall_info message_callback; | |
| 50 | + zend_fcall_info_cache message_callback_cache; | |
| 51 | + zend_fcall_info disconnect_callback; | |
| 52 | + zend_fcall_info_cache disconnect_callback_cache; | |
| 53 | + zend_fcall_info log_callback; | |
| 54 | + zend_fcall_info_cache log_callback_cache; | |
| 55 | + | |
| 56 | + int looping; | |
| 57 | + | |
| 58 | +#ifdef ZTS | |
| 59 | + TSRMLS_D; | |
| 60 | +#endif | |
| 61 | +} mosquitto_client_object; | |
| 62 | + | |
| 63 | +typedef struct _mosquitto_message_object { | |
| 64 | + zend_object std; | |
| 65 | + struct mosquitto_message message; | |
| 66 | + zend_bool owned_topic; | |
| 67 | + zend_bool owned_payload; | |
| 68 | +#ifdef ZTS | |
| 69 | + TSRMLS_D; | |
| 70 | +#endif | |
| 71 | +} mosquitto_message_object; | |
| 72 | + | |
| 73 | +typedef int (*php_mosquitto_read_t)(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC); | |
| 74 | +typedef int (*php_mosquitto_write_t)(mosquitto_message_object *mosquitto_object, zval *newval TSRMLS_DC); | |
| 75 | + | |
| 76 | +typedef struct _php_mosquitto_prop_handler { | |
| 77 | + const char *name; | |
| 78 | + size_t name_length; | |
| 79 | + php_mosquitto_read_t read_func; | |
| 80 | + php_mosquitto_write_t write_func; | |
| 81 | +} php_mosquitto_prop_handler; | |
| 82 | + | |
| 83 | + | |
| 84 | +#define PHP_MOSQUITTO_ERROR_HANDLING() \ | |
| 85 | + zend_replace_error_handling(EH_THROW, mosquitto_ce_exception, &MQTTG(mosquitto_original_error_handling) TSRMLS_CC) | |
| 86 | + | |
| 87 | +#define PHP_MOSQUITTO_RESTORE_ERRORS() \ | |
| 88 | + zend_restore_error_handling(&MQTTG(mosquitto_original_error_handling) TSRMLS_CC) | |
| 89 | + | |
| 90 | + | |
| 91 | +#define PHP_MOSQUITTO_FREE_CALLBACK(CALLBACK) \ | |
| 92 | + if (ZEND_FCI_INITIALIZED(client->CALLBACK ## _callback)) { \ | |
| 93 | + zval_ptr_dtor(&client->CALLBACK ## _callback.function_name); \ | |
| 94 | + } \ | |
| 95 | + \ | |
| 96 | + if (client->CALLBACK ## _callback.object_ptr != NULL) { \ | |
| 97 | + zval_ptr_dtor(&client->CALLBACK ## _callback.object_ptr); \ | |
| 98 | + } | |
| 99 | + | |
| 100 | + | |
| 101 | +#define PHP_MOSQUITTO_MESSAGE_PROPERTY_ENTRY_RECORD(name) \ | |
| 102 | + { "" #name "", sizeof("" #name "") - 1, php_mosquitto_message_read_##name, php_mosquitto_message_write_##name } | |
| 103 | + | |
| 104 | +#define PHP_MOSQUITTO_ADD_PROPERTIES(a, b) \ | |
| 105 | +{ \ | |
| 106 | + int i = 0; \ | |
| 107 | + while (b[i].name != NULL) { \ | |
| 108 | + php_mosquitto_message_add_property((a), (b)[i].name, (b)[i].name_length, \ | |
| 109 | + (php_mosquitto_read_t)(b)[i].read_func, (php_mosquitto_write_t)(b)[i].write_func TSRMLS_CC); \ | |
| 110 | + i++; \ | |
| 111 | + } \ | |
| 112 | +} | |
| 113 | + | |
| 114 | +#define PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_READER_FUNCTION(name) \ | |
| 115 | + static int php_mosquitto_message_read_##name(mosquitto_message_object *mosquitto_object, zval **retval TSRMLS_DC) \ | |
| 116 | + { \ | |
| 117 | + MAKE_STD_ZVAL(*retval); \ | |
| 118 | + ZVAL_LONG(*retval, mosquitto_object->message.name); \ | |
| 119 | + return SUCCESS; \ | |
| 120 | + } | |
| 121 | + | |
| 122 | +#define PHP_MOSQUITTO_MESSAGE_LONG_PROPERTY_WRITER_FUNCTION(name) \ | |
| 123 | +static int php_mosquitto_message_write_##name(mosquitto_message_object *mosquitto_object, zval *newval TSRMLS_DC) \ | |
| 124 | +{ \ | |
| 125 | + zval ztmp; \ | |
| 126 | + if (Z_TYPE_P(newval) != IS_LONG) { \ | |
| 127 | + ztmp = *newval; \ | |
| 128 | + zval_copy_ctor(&ztmp); \ | |
| 129 | + convert_to_long(&ztmp); \ | |
| 130 | + newval = &ztmp; \ | |
| 131 | + } \ | |
| 132 | +\ | |
| 133 | + mosquitto_object->message.name = Z_LVAL_P(newval); \ | |
| 134 | +\ | |
| 135 | + if (newval == &ztmp) { \ | |
| 136 | + zval_dtor(newval); \ | |
| 137 | + } \ | |
| 138 | + return SUCCESS; \ | |
| 139 | +} | |
| 140 | + | |
| 141 | +ZEND_BEGIN_MODULE_GLOBALS(mosquitto) | |
| 142 | + char *client_key; | |
| 143 | + int client_key_len; | |
| 144 | + zend_object_handlers mosquitto_std_object_handlers; | |
| 145 | + zend_error_handling mosquitto_original_error_handling; | |
| 146 | +ZEND_END_MODULE_GLOBALS(mosquitto) | |
| 147 | + | |
| 148 | +#ifdef ZTS | |
| 149 | +# define MQTTG(v) TSRMG(mosquitto_globals_id, zend_mosquitto_globals *, v) | |
| 150 | +#else | |
| 151 | +# define MQTTG(v) (mosquitto_globals.v) | |
| 152 | +#endif | |
| 153 | + | |
| 154 | +ZEND_EXTERN_MODULE_GLOBALS(mosquitto) | |
| 155 | + | |
| 156 | +extern zend_class_entry *mosquitto_ce_exception; | |
| 157 | +extern zend_class_entry *mosquitto_ce_client; | |
| 158 | +extern zend_class_entry *mosquitto_ce_message; | |
| 159 | + | |
| 160 | +PHP_MOSQUITTO_API void php_mosquitto_connect_callback(struct mosquitto *mosq, void *obj, int rc); | |
| 161 | +PHP_MOSQUITTO_API void php_mosquitto_disconnect_callback(struct mosquitto *mosq, void *obj, int rc); | |
| 162 | +PHP_MOSQUITTO_API void php_mosquitto_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str); | |
| 163 | +PHP_MOSQUITTO_API void php_mosquitto_message_callback(struct mosquitto *mosq, void *client_obj, const struct mosquitto_message *message); | |
| 164 | +PHP_MOSQUITTO_API void php_mosquitto_subscribe_callback(struct mosquitto *mosq, void *client_obj, int mid, int qos_count, const int *granted_qos); | |
| 165 | +PHP_MOSQUITTO_API void php_mosquitto_unsubscribe_callback(struct mosquitto *mosq, void *client_obj, int mid); | |
| 166 | +PHP_MOSQUITTO_API void php_mosquitto_disconnect_callback(struct mosquitto *mosq, void *obj, int rc); | |
| 167 | + | |
| 168 | +PHP_MOSQUITTO_API char *php_mosquitto_strerror_wrapper(int err); | |
| 169 | +void php_mosquitto_handle_errno(int retval, int err TSRMLS_DC); | |
| 170 | +void php_mosquitto_exit_loop(mosquitto_client_object *object); | |
| 171 | + | |
| 172 | +PHP_MINIT_FUNCTION(mosquitto); | |
| 173 | +PHP_MINIT_FUNCTION(mosquitto_message); | |
| 174 | +PHP_MSHUTDOWN_FUNCTION(mosquitto); | |
| 175 | +PHP_MINFO_FUNCTION(mosquitto); | |
| 176 | + | |
| 177 | +#endif /* PHP_MOSQUITTO_H */ | |
| 178 | + | |
| 179 | +/* __footer_here__ */ | ... | ... |