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
File was created | 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 | [![Build Status](https://travis-ci.org/mgdm/Mosquitto-PHP.svg?branch=master)](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 | ||
428 |
mosquitto_message.c
File was created | 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 | } | ||
426 |
package.xml
File was created | 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 | --> | ||
62 |
php_mosquitto.h
File was created | 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__ */ | ||
180 |