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 | +[![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 | ... | ... |
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__ */ | ... | ... |