pax_global_header 0000666 0000000 0000000 00000000064 12147457105 0014520 g ustar 00root root 0000000 0000000 52 comment=432f1d361617550a2660d1b07089b971dd045a54
php-stomp-1.0.5/ 0000775 0000000 0000000 00000000000 12147457105 0013452 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/package.xml 0000664 0000000 0000000 00000024061 12147457105 0015572 0 ustar 00root root 0000000 0000000
stomp
pecl.php.net
Stomp client extension
This extension allows php applications to communicate with any Stomp compliant Message Brokers through easy object oriented and procedural interfaces.
Pierrick Charron
pierrick
pierrick@php.net
yes
2012-11-18
1.0.5
1.0.5
stable
stable
PHP License
- Fix memory leak when Stomp can't write the message on the queue. (Pierrick)
- Add a buffer for receipts. (Pierrick)
- Fixed bug #62831 (Stomp module seems not initializing SSL library first).
(Patch by lwhsu at lwhsu dot org)
- Fixed bug #59972 (Message body are not binary safe). (Pierrick)
5.2.2
1.4.0
openssl
stomp
1.0.5
1.0.5
stable
stable
PHP License
2012-11-18
- Fix memory leak when Stomp can't write the message on the queue. (Pierrick)
- Add a buffer for receipts. (Pierrick)
- Fixed bug #62831 (Stomp module seems not initializing SSL library first).
(Patch by lwhsu at lwhsu dot org)
- Fixed bug #59972 (Message body are not binary safe). (Pierrick)
1.0.4
1.0.4
stable
stable
PHP License
2012-09-17
- Fix compatibility with 5.4
1.0.3
1.0.3
stable
stable
PHP License
2010-10-12
- Fixed bug #18772 (setTimeout usecs not honored)
1.0.2
1.0.2
stable
stable
PHP License
2010-08-13
- Fixed SSL connection bug introduced in 1.0.1
1.0.1
1.0.1
stable
stable
PHP License
2010-08-03
- Add new parameter to the constructor to allow client to send extra informations
- Add zend engine runtime cache support (introduced into trunk)
- Add new details property in the StompException class
- Add new StompException::getDetails() method
- Add the frame body content in the Stomp::Error() method
- Fixed bug #17262 (Server is not responding on win32)
1.0.0
1.0.0
stable
stable
PHP License
2010-02-11
- Bump to stable
0.4.1
0.4.1
beta
beta
PHP License
2010-01-19
- Fix compilation issue on PHP5.2 branch
0.4.0
0.4.0
beta
beta
PHP License
2010-01-17
- Adds the ability to specify an alternative class for readFrame
0.3.2
0.3.2
beta
beta
PHP License
2009-11-22
- Adds alt class
- Fixed bug #16936 (Module segfaults on readFrame if Frame > STOMP_BUFSIZE)
- Fixed bug #16933 (readFrame does not notice when server shuts down)
- Fixed bug #16930 (readFrame reports error-frames as "timeout")
0.3.1
0.3.1
beta
beta
PHP License
2009-11-08
- Fix memory leak in stomp_send and in stomp_ack
- Reduced minimum php version to 5.2.2
0.3.0
0.3.0
beta
beta
PHP License
2009-11-06
- new stomp_connect_error() function (pierrick)
- stomp_begin, stomp_abort and stomp_commit now accept additional headers (pierrick)
- new connection timeout and read timeout ini configuration (pierrick)
- Fix a memory leak in stomp_read_line (pierrick)
- Better set of test (Pierrick and Anis)
0.2.0
0.2.0
beta
beta
PHP License
2009-11-01
- Windows build fix (kalle)
- Add SSL support (pierrick)
0.1.0
0.1.0
alpha
alpha
PHP License
2009-10-30
- Initial PECL release. (pierrick)
php-stomp-1.0.5/stomp-1.0.5/ 0000775 0000000 0000000 00000000000 12147457105 0015253 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/CREDITS 0000664 0000000 0000000 00000000027 12147457105 0016272 0 ustar 00root root 0000000 0000000 stomp
Pierrick Charron
php-stomp-1.0.5/stomp-1.0.5/config.m4 0000664 0000000 0000000 00000001521 12147457105 0016761 0 ustar 00root root 0000000 0000000 dnl $Id$
dnl config.m4 for extension stomp
PHP_ARG_ENABLE(stomp, whether to enable stomp support,
Make sure that the comment is aligned:
[ --enable-stomp Enable stomp support])
PHP_ARG_WITH(openssl-dir,OpenSSL dir for stomp,
[ --with-openssl-dir[=DIR] stomp: openssl install prefix], no, no)
if test "$PHP_STOMP" != "no"; then
PHP_NEW_EXTENSION(stomp, stomp.c php_stomp.c, $ext_shared)
test -z "$PHP_OPENSSL" && PHP_OPENSSL=no
if test "$PHP_OPENSSL" != "no" || test "$PHP_OPENSSL_DIR" != "no"; then
PHP_SETUP_OPENSSL(STOMP_SHARED_LIBADD,
[
AC_DEFINE(HAVE_STOMP_SSL,1,[ ])
], [
AC_MSG_ERROR([OpenSSL libraries not found.
Check the path given to --with-openssl-dir and output in config.log)
])
])
PHP_SUBST(STOMP_SHARED_LIBADD)
fi
fi
php-stomp-1.0.5/stomp-1.0.5/config.w32 0000664 0000000 0000000 00000000467 12147457105 0017064 0 ustar 00root root 0000000 0000000 // $Id$
// vim:ft=javascript
ARG_ENABLE("stomp", "enable stomp support", "no");
if (PHP_STOMP != "no") {
if (CHECK_LIB("ssleay32.lib", "stomp", PHP_STOMP) && CHECK_LIB("libeay32.lib", "stomp", PHP_STOMP)) {
ADD_FLAG("CFLAGS_STOMP", "/DHAVE_STOMP_SSL=1");
}
EXTENSION("stomp", "stomp.c php_stomp.c");
}
php-stomp-1.0.5/stomp-1.0.5/doc/ 0000775 0000000 0000000 00000000000 12147457105 0016020 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/doc/classes.php 0000664 0000000 0000000 00000010372 12147457105 0020171 0 ustar 00root root 0000000 0000000 send($queue, $msg);
$stomp->subscribe($queue);
$frame = $stomp->readFrame();
if ($frame->body === $msg) {
echo "Worked\n";
$stomp->ack($frame, array('receipt' => 'message-12345'));
} else {
echo "Failed\n";
}
$stomp->disconnect();
} catch(StompException $e) {
echo $e->getMessage();
}
php-stomp-1.0.5/stomp-1.0.5/examples/procedural.php 0000664 0000000 0000000 00000001014 12147457105 0021736 0 ustar 00root root 0000000 0000000 't1'));
stomp_commit($stomp, 't1');
stomp_subscribe($stomp, $queue);
$frame = stomp_read_frame($stomp);
if ($frame['body'] === $msg) {
echo "Worked\n";
stomp_ack($stomp, $frame['headers']['message-id']);
} else {
echo "Failed\n";
}
stomp_close($stomp);
}
php-stomp-1.0.5/stomp-1.0.5/php_stomp.c 0000775 0000000 0000000 00000110271 12147457105 0017435 0 ustar 00root root 0000000 0000000 /*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Pierrick Charron |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "zend_exceptions.h"
#include "ext/standard/info.h"
#include "ext/standard/url.h"
#include "php_stomp.h"
#include "ext/standard/php_smart_str.h"
#define FETCH_STOMP_OBJECT \
i_obj = (stomp_object_t *) zend_object_store_get_object(stomp_object TSRMLS_CC); \
if (!(stomp = i_obj->stomp)) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, PHP_STOMP_ERR_NO_CTR); \
RETURN_FALSE; \
}
#define INIT_FRAME_L(frame, cmd, l) \
frame.command = cmd; \
frame.command_length = l; \
ALLOC_HASHTABLE(frame.headers); \
zend_hash_init(frame.headers, 0, NULL, NULL, 0);
#define INIT_FRAME(frame, cmd) INIT_FRAME_L(frame, cmd, sizeof(cmd)-1)
#define FRAME_HEADER_FROM_HASHTABLE(h, p) \
HashTable *headers_ht = p; \
zval **value = NULL; \
char *string_key = NULL; \
ulong num_key; \
for (zend_hash_internal_pointer_reset(headers_ht); \
zend_hash_get_current_data(headers_ht, (void **)&value) == SUCCESS; \
zend_hash_move_forward(headers_ht)) { \
if (zend_hash_get_current_key(headers_ht, &string_key, &num_key, 1) != HASH_KEY_IS_STRING) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument or parameter array"); \
break; \
} else { \
if (Z_TYPE_PP(value) != IS_STRING) { \
SEPARATE_ZVAL(value); \
convert_to_string(*value); \
} \
zend_hash_add(h, string_key, strlen(string_key)+1, Z_STRVAL_PP(value), Z_STRLEN_PP(value)+1, NULL); \
efree(string_key); \
} \
}
#define CLEAR_FRAME(frame) \
zend_hash_destroy(frame.headers); \
efree(frame.headers);
#define STOMP_ERROR(errno, msg) \
STOMP_G(error_no) = errno; \
if (STOMP_G(error_msg)) { \
efree(STOMP_G(error_msg)); \
} \
STOMP_G(error_msg) = estrdup(msg); \
if (stomp_object) { \
zend_throw_exception_ex(stomp_ce_exception, errno TSRMLS_CC, msg); \
}
#define STOMP_ERROR_DETAILS(errno, msg, details) \
STOMP_G(error_no) = errno; \
if (STOMP_G(error_msg)) { \
efree(STOMP_G(error_msg)); \
} \
STOMP_G(error_msg) = estrdup(msg); \
if (stomp_object) { \
zval *object = zend_throw_exception_ex(stomp_ce_exception, errno TSRMLS_CC, msg); \
if (details) { \
zend_update_property_string(stomp_ce_exception, object, "details", sizeof("details")-1, (char *) details TSRMLS_CC); \
} \
}
static int le_stomp;
ZEND_DECLARE_MODULE_GLOBALS(stomp)
static PHP_GINIT_FUNCTION(stomp);
/* {{{ stomp_class_entry */
zend_class_entry *stomp_ce_stomp;
zend_class_entry *stomp_ce_exception;
zend_class_entry *stomp_ce_frame;
/* }}} */
/* {{{ arg_info */
ZEND_BEGIN_ARG_INFO_EX(stomp_no_args, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_connect_args, 0, 0, 0)
ZEND_ARG_INFO(0, broker)
ZEND_ARG_INFO(0, username)
ZEND_ARG_INFO(0, password)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_link_only, 0, 0, 1)
ZEND_ARG_INFO(0, link)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_send_args, 0, 0, 3)
ZEND_ARG_INFO(0, link)
ZEND_ARG_INFO(0, destination)
ZEND_ARG_INFO(0, msg)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_oop_send_args, 0, 0, 2)
ZEND_ARG_INFO(0, destination)
ZEND_ARG_INFO(0, msg)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_subscribe_args, 0, 0, 2)
ZEND_ARG_INFO(0, link)
ZEND_ARG_INFO(0, destination)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_oop_subscribe_args, 0, 0, 1)
ZEND_ARG_INFO(0, destination)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_readframe_args, 0, 0, 1)
ZEND_ARG_INFO(0, link)
ZEND_ARG_INFO(0, class_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_oop_readframe_args, 0, 0, 0)
ZEND_ARG_INFO(0, class_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_transaction_args, 0, 0, 2)
ZEND_ARG_INFO(0, link)
ZEND_ARG_INFO(0, transaction_id)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_oop_transaction_args, 0, 0, 1)
ZEND_ARG_INFO(0, transaction_id)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_ack_args, 0, 0, 2)
ZEND_ARG_INFO(0, link)
ZEND_ARG_INFO(0, msg)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_oop_ack_args, 0, 0, 1)
ZEND_ARG_INFO(0, msg)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_set_read_timeout_args, 0, 0, 2)
ZEND_ARG_INFO(0, link)
ZEND_ARG_INFO(0, seconds)
ZEND_ARG_INFO(0, microseconds)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_oop_set_read_timeout_args, 0, 0, 1)
ZEND_ARG_INFO(0, seconds)
ZEND_ARG_INFO(0, microseconds)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(stomp_frame_construct_args, 0, 0, 0)
ZEND_ARG_INFO(0, command)
ZEND_ARG_ARRAY_INFO(0, headers, 1)
ZEND_ARG_INFO(0, body)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ stomp_functions */
zend_function_entry stomp_functions[] = {
PHP_FE(stomp_version, stomp_no_args)
PHP_FE(stomp_connect, stomp_connect_args)
PHP_FE(stomp_connect_error, stomp_no_args)
PHP_FE(stomp_get_session_id, stomp_link_only)
PHP_FE(stomp_close, stomp_link_only)
PHP_FE(stomp_send, stomp_send_args)
PHP_FE(stomp_subscribe, stomp_subscribe_args)
PHP_FE(stomp_has_frame, stomp_link_only)
PHP_FE(stomp_read_frame, stomp_readframe_args)
PHP_FE(stomp_unsubscribe, stomp_subscribe_args)
PHP_FE(stomp_begin, stomp_transaction_args)
PHP_FE(stomp_commit, stomp_transaction_args)
PHP_FE(stomp_abort, stomp_transaction_args)
PHP_FE(stomp_ack, stomp_ack_args)
PHP_FE(stomp_error, stomp_link_only)
PHP_FE(stomp_set_read_timeout, stomp_set_read_timeout_args)
PHP_FE(stomp_get_read_timeout, stomp_link_only)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ stomp_methods[] */
static zend_function_entry stomp_methods[] = {
PHP_FALIAS(__construct, stomp_connect, stomp_connect_args)
PHP_FALIAS(getSessionId, stomp_get_session_id, stomp_no_args)
PHP_FALIAS(__destruct, stomp_close, stomp_no_args)
PHP_FALIAS(send, stomp_send, stomp_oop_send_args)
PHP_FALIAS(subscribe, stomp_subscribe, stomp_oop_subscribe_args)
PHP_FALIAS(hasFrame, stomp_has_frame, stomp_no_args)
PHP_FALIAS(readFrame, stomp_read_frame, stomp_oop_readframe_args)
PHP_FALIAS(unsubscribe, stomp_unsubscribe, stomp_oop_subscribe_args)
PHP_FALIAS(begin, stomp_begin, stomp_oop_transaction_args)
PHP_FALIAS(commit, stomp_commit, stomp_oop_transaction_args)
PHP_FALIAS(abort, stomp_abort, stomp_oop_transaction_args)
PHP_FALIAS(ack, stomp_ack, stomp_oop_ack_args)
PHP_FALIAS(error, stomp_error, stomp_no_args)
PHP_FALIAS(setReadTimeout, stomp_set_read_timeout, stomp_oop_set_read_timeout_args)
PHP_FALIAS(getReadTimeout, stomp_get_read_timeout, stomp_no_args)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ stomp_frame_methods[] */
static zend_function_entry stomp_frame_methods[] = {
PHP_ME(stompframe, __construct, stomp_frame_construct_args, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ stomp_exception_methods[] */
static zend_function_entry stomp_exception_methods[] = {
PHP_ME(stompexception, getDetails, stomp_no_args, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ stomp_module_entry */
zend_module_entry stomp_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_STOMP_EXTNAME,
stomp_functions,
PHP_MINIT(stomp),
PHP_MSHUTDOWN(stomp),
PHP_RINIT(stomp),
PHP_RSHUTDOWN(stomp),
PHP_MINFO(stomp),
#if ZEND_MODULE_API_NO >= 20010901
PHP_STOMP_VERSION,
#endif
PHP_MODULE_GLOBALS(stomp),
PHP_GINIT(stomp),
NULL,
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("stomp.default_broker", "tcp://localhost:61613", PHP_INI_ALL, OnUpdateString, default_broker, zend_stomp_globals, stomp_globals)
STD_PHP_INI_ENTRY("stomp.default_read_timeout_sec", "2", PHP_INI_ALL, OnUpdateLong, read_timeout_sec, zend_stomp_globals, stomp_globals)
STD_PHP_INI_ENTRY("stomp.default_read_timeout_usec", "0", PHP_INI_ALL, OnUpdateLong, read_timeout_usec, zend_stomp_globals, stomp_globals)
STD_PHP_INI_ENTRY("stomp.default_connection_timeout_sec", "2", PHP_INI_ALL, OnUpdateLong, connection_timeout_sec, zend_stomp_globals, stomp_globals)
STD_PHP_INI_ENTRY("stomp.default_connection_timeout_usec", "0", PHP_INI_ALL, OnUpdateLong, connection_timeout_usec, zend_stomp_globals, stomp_globals)
PHP_INI_END()
/* {{{ PHP_GINIT_FUNCTION */
static PHP_GINIT_FUNCTION(stomp)
{
stomp_globals->default_broker = NULL;
stomp_globals->read_timeout_sec = 2;
stomp_globals->read_timeout_usec = 0;
stomp_globals->connection_timeout_sec = 2;
stomp_globals->connection_timeout_usec = 0;
#if HAVE_STOMP_SSL
SSL_library_init();
#endif
}
/* }}} */
ZEND_DECLARE_MODULE_GLOBALS(stomp)
#ifdef COMPILE_DL_STOMP
ZEND_GET_MODULE(stomp)
#endif
/* {{{ constructor/destructor */
static void stomp_send_disconnect(stomp_t *stomp TSRMLS_DC)
{
stomp_frame_t frame = {0};
INIT_FRAME(frame, "DISCONNECT");
stomp_send(stomp, &frame TSRMLS_CC);
CLEAR_FRAME(frame);
}
static void php_destroy_stomp_res(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
stomp_t *stomp = (stomp_t *) rsrc->ptr;
stomp_send_disconnect(stomp TSRMLS_CC);
stomp_close(stomp);
}
static void stomp_object_free_storage(stomp_object_t *intern TSRMLS_DC)
{
zend_object_std_dtor(&intern->std TSRMLS_CC);
if (intern->stomp) {
stomp_send_disconnect(intern->stomp TSRMLS_CC);
stomp_close(intern->stomp);
}
efree(intern);
}
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
#define PHP_STOMP_RUNTIME_CACHE
#endif
static zend_object_value php_stomp_new(zend_class_entry *ce TSRMLS_DC)
{
zend_object_value retval;
stomp_object_t *intern;
#ifndef PHP_STOMP_RUNTIME_CACHE
zval *tmp;
#endif
intern = (stomp_object_t *) ecalloc(1, sizeof(stomp_object_t));
intern->stomp = NULL;
zend_object_std_init(&intern->std, ce TSRMLS_CC);
#ifdef PHP_STOMP_RUNTIME_CACHE
object_properties_init(&intern->std, ce);
#else
zend_hash_copy(intern->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
#endif
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) stomp_object_free_storage, NULL TSRMLS_CC);
retval.handlers = zend_get_std_object_handlers();
return retval;
}
/* }}} */
/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(stomp)
{
zend_class_entry ce;
/* Ressource */
le_stomp = zend_register_list_destructors_ex(php_destroy_stomp_res, NULL, PHP_STOMP_RES_NAME, module_number);
/* Register Stomp class */
INIT_CLASS_ENTRY(ce, PHP_STOMP_CLASSNAME, stomp_methods);
stomp_ce_stomp = zend_register_internal_class(&ce TSRMLS_CC);
stomp_ce_stomp->create_object = php_stomp_new;
/* Register StompFrame class */
INIT_CLASS_ENTRY(ce, PHP_STOMP_FRAME_CLASSNAME, stomp_frame_methods);
stomp_ce_frame = zend_register_internal_class(&ce TSRMLS_CC);
/* Properties */
zend_declare_property_null(stomp_ce_frame, "command", sizeof("command")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_null(stomp_ce_frame, "headers", sizeof("headers")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_null(stomp_ce_frame, "body", sizeof("body")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
/* Register StompException class */
INIT_CLASS_ENTRY(ce, PHP_STOMP_EXCEPTION_CLASSNAME, stomp_exception_methods);
stomp_ce_exception = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
/* Properties */
zend_declare_property_null(stomp_ce_exception, "details", sizeof("details")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
/** Register INI entries **/
REGISTER_INI_ENTRIES();
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(stomp)
{
/* Unregister INI entries */
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
/* }}} */
/* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(stomp)
{
STOMP_G(error_msg) = NULL;
STOMP_G(error_no) = 0;
return SUCCESS;
}
/* }}} */
/* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(stomp)
{
if (STOMP_G(error_msg)) {
efree(STOMP_G(error_msg));
}
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(stomp)
{
php_info_print_table_start();
php_info_print_table_header(2, PHP_STOMP_EXTNAME, "enabled");
php_info_print_table_row(2, "API version", PHP_STOMP_VERSION);
#if HAVE_STOMP_SSL
php_info_print_table_row(2, "SSL Support", "enabled");
#else
php_info_print_table_row(2, "SSL Support", "disabled");
#endif
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
}
/* }}} */
/* {{{ proto string stomp_version()
Get stomp extension version */
PHP_FUNCTION(stomp_version)
{
RETURN_STRINGL(PHP_STOMP_VERSION, sizeof(PHP_STOMP_VERSION)-1, 1);
}
/* }}} */
/* {{{ proto Stomp::__construct([string broker [, string username [, string password [, array headers]]]])
Connect to server */
PHP_FUNCTION(stomp_connect)
{
zval *stomp_object = getThis();
zval *headers = NULL;
stomp_t *stomp = NULL;
char *broker = NULL, *username = NULL, *password = NULL;
int broker_len = 0, username_len = 0, password_len = 0;
php_url *url_parts;
#ifdef HAVE_STOMP_SSL
int use_ssl = 0;
#endif
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sssa!", &broker, &broker_len, &username, &username_len, &password, &password_len, &headers) == FAILURE) {
return;
}
/* Verify that broker URI */
if (!broker) {
broker = STOMP_G(default_broker);
}
url_parts = php_url_parse_ex(broker, strlen(broker));
if (!url_parts || !url_parts->host) {
STOMP_ERROR(0, PHP_STOMP_ERR_INVALID_BROKER_URI);
php_url_free(url_parts);
return;
}
if (url_parts->scheme) {
if (strcmp(url_parts->scheme, "ssl") == 0) {
#if HAVE_STOMP_SSL
use_ssl = 1;
#else
STOMP_ERROR(0, "SSL DISABLED");
php_url_free(url_parts);
return;
#endif
} else if (strcmp(url_parts->scheme, "tcp") != 0) {
STOMP_ERROR(0, PHP_STOMP_ERR_INVALID_BROKER_URI_SCHEME);
php_url_free(url_parts);
return;
}
}
stomp = stomp_init();
#if HAVE_STOMP_SSL
stomp->options.use_ssl = use_ssl;
#endif
stomp->options.read_timeout_sec = STOMP_G(read_timeout_sec);
stomp->options.read_timeout_usec = STOMP_G(read_timeout_usec);
stomp->options.connect_timeout_sec = STOMP_G(connection_timeout_sec);
stomp->options.connect_timeout_usec = STOMP_G(connection_timeout_usec);
stomp->status = stomp_connect(stomp, url_parts->host, url_parts->port ? url_parts->port : 61613 TSRMLS_CC);
php_url_free(url_parts);
if (stomp->status) {
stomp_frame_t *res;
stomp_frame_t frame = {0};
INIT_FRAME(frame, "CONNECT");
if (username_len == 0) {
username = "";
}
if (password_len == 0) {
password = "";
}
zend_hash_add(frame.headers, "login", sizeof("login"), username, username_len + 1, NULL);
zend_hash_add(frame.headers, "passcode", sizeof("passcode"), password, password_len + 1, NULL);
if (NULL != headers) {
FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(headers));
}
stomp_send(stomp, &frame TSRMLS_CC);
CLEAR_FRAME(frame);
/* Retreive Response */
res = stomp_read_frame(stomp);
if (NULL == res) {
STOMP_ERROR(0, PHP_STOMP_ERR_SERVER_NOT_RESPONDING);
} else if (0 != strncmp("CONNECTED", res->command, sizeof("CONNECTED")-1)) {
if (stomp->error) {
STOMP_ERROR_DETAILS(stomp->errnum, stomp->error, stomp->error_details);
} else {
STOMP_ERROR(0, PHP_STOMP_ERR_UNKNOWN);
}
} else {
char *key = NULL;
if (zend_hash_find(res->headers, "session", sizeof("session"), (void **)&key) == SUCCESS) {
if (stomp->session) {
efree(stomp->session);
}
stomp->session = estrdup(key);
}
stomp_free_frame(res);
if (!stomp_object) {
ZEND_REGISTER_RESOURCE(return_value, stomp, le_stomp);
return;
} else {
stomp_object_t *i_obj = (stomp_object_t *) zend_object_store_get_object(stomp_object TSRMLS_CC);
if (i_obj->stomp) {
stomp_close(i_obj->stomp);
}
i_obj->stomp = stomp;
RETURN_TRUE;
}
}
} else {
STOMP_ERROR_DETAILS(0, stomp->error, stomp->error_details);
}
stomp_close(stomp);
RETURN_FALSE;
}
/* }}} */
/* {{{ proto string stomp_connect_error()
Get the last connection error */
PHP_FUNCTION(stomp_connect_error)
{
if (STOMP_G(error_msg)) {
RETURN_STRING(STOMP_G(error_msg),1);
} else {
RETURN_NULL();
}
}
/* }}} */
/* {{{ proto string Stomp::getSessionId()
Get the current stomp session ID */
PHP_FUNCTION(stomp_get_session_id)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
if (!stomp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, PHP_STOMP_ERR_NO_CTR);
RETURN_FALSE;
}
if (stomp->session) {
RETURN_STRING(stomp->session, 1);
} else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto boolean Stomp::__destruct()
Close stomp connection */
PHP_FUNCTION(stomp_close)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
FETCH_STOMP_OBJECT;
stomp_send_disconnect(stomp TSRMLS_CC);
stomp_close(stomp);
i_obj->stomp = NULL;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
zend_list_delete(Z_RESVAL_P(arg));
}
RETURN_TRUE;
}
/* }}} */
/* {{{ proto boolean Stomp::send(string destination, mixed msg [, array headers])
Sends a message to a destination in the messaging system */
PHP_FUNCTION(stomp_send)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
char *destination = NULL;
int destination_length = 0;
zval *msg = NULL, *headers = NULL;
stomp_frame_t frame = {0};
int success = 0;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|a!", &destination, &destination_length, &msg, &headers) == FAILURE) {
return;
}
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|a!", &arg, &destination, &destination_length, &msg, &headers) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
/* Verify destination */
if (0 == destination_length) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, PHP_STOMP_ERR_EMPTY_DESTINATION);
RETURN_FALSE;
}
INIT_FRAME(frame, "SEND");
/* Translate a PHP array to a stomp_header array */
if (NULL != headers) {
FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(headers));
}
/* Add the destination */
zend_hash_add(frame.headers, "destination", sizeof("destination"), destination, destination_length + 1, NULL);
if (Z_TYPE_P(msg) == IS_STRING) {
frame.body = Z_STRVAL_P(msg);
frame.body_length = Z_STRLEN_P(msg);
} else if (Z_TYPE_P(msg) == IS_OBJECT && instanceof_function(Z_OBJCE_P(msg), stomp_ce_frame TSRMLS_CC)) {
zval *frame_obj_prop = NULL;
frame_obj_prop = zend_read_property(stomp_ce_frame, msg, "command", sizeof("command")-1, 1 TSRMLS_CC);
if (Z_TYPE_P(frame_obj_prop) == IS_STRING) {
frame.command = Z_STRVAL_P(frame_obj_prop);
frame.command_length = Z_STRLEN_P(frame_obj_prop);
}
frame_obj_prop = zend_read_property(stomp_ce_frame, msg, "body", sizeof("body")-1, 1 TSRMLS_CC);
if (Z_TYPE_P(frame_obj_prop) == IS_STRING) {
frame.body = Z_STRVAL_P(frame_obj_prop);
frame.body_length = Z_STRLEN_P(frame_obj_prop);
}
frame_obj_prop = zend_read_property(stomp_ce_frame, msg, "headers", sizeof("headers")-1, 1 TSRMLS_CC);
if (Z_TYPE_P(frame_obj_prop) == IS_ARRAY) {
FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(frame_obj_prop));
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expects parameter %d to be a string or a StompFrame object.", stomp_object?2:3);
CLEAR_FRAME(frame);
RETURN_FALSE;
}
if (stomp_send(stomp, &frame TSRMLS_CC) > 0) {
success = stomp_valid_receipt(stomp, &frame);
}
CLEAR_FRAME(frame);
RETURN_BOOL(success);
}
/* }}} */
/* {{{ proto boolean Stomp::subscribe(string destination [, array headers])
Register to listen to a given destination */
PHP_FUNCTION(stomp_subscribe)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
char *destination = NULL;
int destination_length = 0;
zval *headers = NULL;
stomp_frame_t frame = {0};
int success = 0;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a!", &destination, &destination_length, &headers) == FAILURE) {
return;
}
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|a!", &arg, &destination, &destination_length, &headers) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
/* Verify destination */
if (0 == destination_length) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, PHP_STOMP_ERR_EMPTY_DESTINATION);
RETURN_FALSE;
}
INIT_FRAME(frame, "SUBSCRIBE");
/* Translate a PHP array to a stomp_header array */
if (NULL != headers) {
FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(headers));
}
/* Add the destination */
zend_hash_add(frame.headers, "ack", sizeof("ack"), "client", sizeof("client"), NULL);
zend_hash_add(frame.headers, "destination", sizeof("destination"), destination, destination_length + 1, NULL);
zend_hash_add(frame.headers, "activemq.prefetchSize", sizeof("activemq.prefetchSize"), "1", sizeof("1"), NULL);
if (stomp_send(stomp, &frame TSRMLS_CC) > 0) {
success = stomp_valid_receipt(stomp, &frame);
}
CLEAR_FRAME(frame);
RETURN_BOOL(success);
}
/* }}} */
/* {{{ proto boolean Stomp::unsubscribe(string destination [, array headers])
Remove an existing subscription */
PHP_FUNCTION(stomp_unsubscribe)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
char *destination = NULL;
int destination_length = 0;
zval *headers = NULL;
stomp_frame_t frame = {0};
int success = 0;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a!", &destination, &destination_length, &headers) == FAILURE) {
return;
}
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|a!", &arg, &destination, &destination_length, &headers) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
/* Verify destination */
if (0 == destination_length) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, PHP_STOMP_ERR_EMPTY_DESTINATION);
RETURN_FALSE;
}
INIT_FRAME(frame, "UNSUBSCRIBE");
/* Translate a PHP array to a stomp_header array */
if (NULL != headers) {
FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(headers));
}
/* Add the destination */
zend_hash_add(frame.headers, "destination", sizeof("destination"), destination, destination_length + 1, NULL);
if (stomp_send(stomp, &frame TSRMLS_CC) > 0) {
success = stomp_valid_receipt(stomp, &frame);
}
CLEAR_FRAME(frame);
RETURN_BOOL(success);
}
/* }}} */
/* {{{ proto boolean Stomp::hasFrame()
Indicate whether or not there is a frame ready to read */
PHP_FUNCTION(stomp_has_frame)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
RETURN_BOOL(stomp_select(stomp) > 0);
}
/* }}} */
/* {{{ proto StompFrame Stomp::readFrame()
Read the next frame */
PHP_FUNCTION(stomp_read_frame)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
stomp_frame_t *res = NULL;
char *class_name = NULL;
int class_name_len = 0;
zend_class_entry *ce = NULL;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &class_name, &class_name_len) == FAILURE) {
return;
}
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s", &arg, &class_name, &class_name_len) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
if (class_name_len > 0) {
ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
if (!ce) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name);
ce = stomp_ce_frame;
}
} else if (stomp_object) {
ce = stomp_ce_frame;
}
if ((res = stomp_read_frame(stomp))) {
zval *headers = NULL;
if (0 == strncmp("ERROR", res->command, sizeof("ERROR") - 1)) {
char *error_msg = NULL;
if (zend_hash_find(res->headers, "message", sizeof("message"), (void **)&error_msg) == SUCCESS) {
zval *excobj = zend_throw_exception_ex(stomp_ce_exception, 0 TSRMLS_CC, error_msg);
if (res->body) {
zend_update_property_string(stomp_ce_exception, excobj, "details", sizeof("details")-1, (char *) res->body TSRMLS_CC);
}
stomp_free_frame(res);
RETURN_FALSE;
}
}
MAKE_STD_ZVAL(headers);
array_init(headers);
if (res->headers) {
char *key;
ulong pos;
zend_hash_internal_pointer_reset(res->headers);
while (zend_hash_get_current_key(res->headers, &key, &pos, 0) == HASH_KEY_IS_STRING) {
char *value = NULL;
if (zend_hash_get_current_data(res->headers, (void **)&value) == SUCCESS) {
add_assoc_string(headers, key, value, 1);
}
zend_hash_move_forward(res->headers);
}
}
if (ce) {
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zval *retval_ptr;
object_init_ex(return_value, ce);
if (ce->constructor) {
zval *cmd = NULL, *body = NULL;
ALLOC_ZVAL(cmd);
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3) || (PHP_MAJOR_VERSION > 5)
Z_SET_REFCOUNT_P(cmd, 1);
Z_UNSET_ISREF_P(cmd);
#else
cmd->refcount = 1;
cmd->is_ref = 0;
#endif
ZVAL_STRINGL(cmd, res->command, res->command_length, 1);
ALLOC_ZVAL(body);
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3) || (PHP_MAJOR_VERSION > 5)
Z_SET_REFCOUNT_P(body, 1);
Z_UNSET_ISREF_P(body);
#else
body->refcount = 1;
body->is_ref = 0;
#endif
if (res->body) {
ZVAL_STRINGL(body, res->body, res->body_length, 1);
} else {
ZVAL_NULL(body);
}
fci.size = sizeof(fci);
fci.function_table = &ce->function_table;
fci.function_name = NULL;
fci.symbol_table = NULL;
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3) || (PHP_MAJOR_VERSION > 5)
fci.object_ptr = return_value;
#else
fci.object_pp = &return_value;
#endif
fci.retval_ptr_ptr = &retval_ptr;
// PARAMS
fci.param_count = 3;
fci.params = (zval***) safe_emalloc(sizeof(zval*), 3, 0);
fci.params[0] = &cmd;
fci.params[1] = &headers;
fci.params[2] = &body;
fci.no_separation = 1;
fcc.initialized = 1;
fcc.function_handler = ce->constructor;
fcc.calling_scope = EG(scope);
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3) || (PHP_MAJOR_VERSION > 5)
fcc.called_scope = Z_OBJCE_P(return_value);
fcc.object_ptr = return_value;
#else
fcc.object_pp = &return_value;
#endif
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
} else {
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
}
}
if (fci.params) {
efree(fci.params);
}
zval_ptr_dtor(&cmd);
zval_ptr_dtor(&body);
}
zval_ptr_dtor(&headers);
} else {
array_init(return_value);
add_assoc_string_ex(return_value, "command", sizeof("command"), res->command, 1);
if (res->body) {
add_assoc_stringl_ex(return_value, "body", sizeof("body"), res->body, res->body_length, 1);
}
add_assoc_zval_ex(return_value, "headers", sizeof("headers"), headers);
}
stomp_free_frame(res);
} else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ _php_stomp_transaction */
static void _php_stomp_transaction(INTERNAL_FUNCTION_PARAMETERS, char *cmd) {
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
char *transaction_id = NULL;
int transaction_id_length = 0;
stomp_frame_t frame = {0};
int success = 0;
zval *headers = NULL;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a", &transaction_id, &transaction_id_length, &headers) == FAILURE) {
return;
}
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|a", &arg, &transaction_id, &transaction_id_length, &headers) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
INIT_FRAME_L(frame, cmd, strlen(cmd));
if (transaction_id_length > 0) {
zend_hash_add(frame.headers, "transaction", sizeof("transaction"), transaction_id, transaction_id_length + 1, NULL);
}
/* Translate a PHP array to a stomp_header array */
if (NULL != headers) {
FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(headers));
}
if (stomp_send(stomp, &frame TSRMLS_CC) > 0) {
success = stomp_valid_receipt(stomp, &frame);
}
CLEAR_FRAME(frame);
RETURN_BOOL(success);
}
/* }}} */
/* {{{ proto boolean Stomp::begin(string transactionId [, array headers ])
Start a transaction */
PHP_FUNCTION(stomp_begin)
{
_php_stomp_transaction(INTERNAL_FUNCTION_PARAM_PASSTHRU, "BEGIN");
}
/* }}} */
/* {{{ proto boolean Stomp::commit(string transactionId [, array headers ])
Commit a transaction in progress */
PHP_FUNCTION(stomp_commit)
{
_php_stomp_transaction(INTERNAL_FUNCTION_PARAM_PASSTHRU, "COMMIT");
}
/* }}} */
/* {{{ proto boolean Stomp::abort(string transactionId [, array headers ])
Rollback a transaction in progress */
PHP_FUNCTION(stomp_abort)
{
_php_stomp_transaction(INTERNAL_FUNCTION_PARAM_PASSTHRU, "ABORT");
}
/* }}} */
/* {{{ proto boolean Stomp::ack(mixed msg [, array headers])
Acknowledge consumption of a message from a subscription using client acknowledgment */
PHP_FUNCTION(stomp_ack)
{
zval *stomp_object = getThis();
zval *msg = NULL, *headers = NULL;
stomp_t *stomp = NULL;
stomp_frame_t frame = {0};
int success = 0;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a!", &msg, &headers) == FAILURE) {
return;
}
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|a!", &arg, &msg, &headers) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
INIT_FRAME(frame, "ACK");
if (NULL != headers) {
FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(headers));
}
if (Z_TYPE_P(msg) == IS_STRING) {
zend_hash_add(frame.headers, "message-id", sizeof("message-id"), Z_STRVAL_P(msg), Z_STRLEN_P(msg) + 1, NULL);
} else if (Z_TYPE_P(msg) == IS_OBJECT && instanceof_function(Z_OBJCE_P(msg), stomp_ce_frame TSRMLS_CC)) {
zval *frame_obj_prop = zend_read_property(stomp_ce_frame, msg, "headers", sizeof("headers")-1, 1 TSRMLS_CC);
if (Z_TYPE_P(frame_obj_prop) == IS_ARRAY) {
FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(frame_obj_prop));
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expects parameter %d to be a string or a StompFrame object.", stomp_object?2:3);
CLEAR_FRAME(frame);
RETURN_FALSE;
}
if (stomp_send(stomp, &frame TSRMLS_CC) > 0) {
success = stomp_valid_receipt(stomp, &frame);
}
CLEAR_FRAME(frame);
RETURN_BOOL(success);
}
/* }}} */
/* {{{ proto string Stomp::error()
Get the last error message */
PHP_FUNCTION(stomp_error)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
if (stomp->error) {
if (stomp->error_details) {
char *error_msg = (char *) emalloc(strlen(stomp->error) + strlen(stomp->error_details) + 10);
strcpy(error_msg, stomp->error);
strcat(error_msg, "\n\n");
strcat(error_msg, stomp->error_details);
RETURN_STRING(error_msg, 0);
} else {
RETURN_STRING(stomp->error, 1);
}
} else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto void Stomp::setTimeout(int seconds [, int microseconds])
Set the timeout */
PHP_FUNCTION(stomp_set_read_timeout)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
long sec = 0, usec = 0;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &sec, &usec) == FAILURE) {
return;
}
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &arg, &sec, &usec) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
stomp->options.read_timeout_sec = sec;
stomp->options.read_timeout_usec = usec;
}
/* }}} */
/* {{{ proto array Stomp::getTimeout()
Get the timeout */
PHP_FUNCTION(stomp_get_read_timeout)
{
zval *stomp_object = getThis();
stomp_t *stomp = NULL;
if (stomp_object) {
stomp_object_t *i_obj = NULL;
FETCH_STOMP_OBJECT;
} else {
zval *arg = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(stomp, stomp_t *, &arg, -1, PHP_STOMP_RES_NAME, le_stomp);
}
array_init(return_value);
add_assoc_long_ex(return_value, "sec", sizeof("sec"), stomp->options.read_timeout_sec);
add_assoc_long_ex(return_value, "usec", sizeof("usec"), stomp->options.read_timeout_usec);
}
/* }}} */
/* {{{ proto void StompFrame::__construct([string command [, array headers [, string body]]])
Create StompFrame object */
PHP_METHOD(stompframe, __construct)
{
zval *object = getThis();
char *command = NULL, *body = NULL;
int command_length = 0, body_length = -1;
zval *headers = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!s", &command, &command_length, &headers, &body, &body_length) == FAILURE) {
return;
}
if (command_length > 0) {
zend_update_property_stringl(stomp_ce_frame, object, "command", sizeof("command")-1, command, command_length TSRMLS_CC);
}
if (headers) {
zend_update_property(stomp_ce_frame, object, "headers", sizeof("headers")-1, headers TSRMLS_CC);
}
if (body_length > 0) {
zend_update_property_stringl(stomp_ce_frame, object, "body", sizeof("body")-1, body, body_length TSRMLS_CC);
}
}
/* }}} */
/* {{{ proto string StompException::getDetails()
Get error details */
PHP_METHOD(stompexception, getDetails)
{
zval *object = getThis();
zval *details = NULL;
details = zend_read_property(stomp_ce_exception, object, "details", sizeof("details")-1, 1 TSRMLS_CC);
RETURN_STRINGL(Z_STRVAL_P(details), Z_STRLEN_P(details), 1);
}
/* }}} */
php-stomp-1.0.5/stomp-1.0.5/php_stomp.h 0000664 0000000 0000000 00000007567 12147457105 0017454 0 ustar 00root root 0000000 0000000 /*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Pierrick Charron |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef PHP_STOMP_H
#define PHP_STOMP_H
#include "stomp.h"
typedef struct _stomp_object {
zend_object std;
stomp_t *stomp;
} stomp_object_t;
#define PHP_STOMP_EXTNAME "Stomp"
#define PHP_STOMP_MAJOR_VERSION "1"
#define PHP_STOMP_MINOR_VERSION "0"
#define PHP_STOMP_PATCH_VERSION "5"
#define PHP_STOMP_VERSION_STATUS ""
#define PHP_STOMP_VERSION PHP_STOMP_MAJOR_VERSION "." PHP_STOMP_MINOR_VERSION "." PHP_STOMP_PATCH_VERSION PHP_STOMP_VERSION_STATUS
#define PHP_STOMP_RES_NAME "stomp connection"
#define PHP_STOMP_CLASSNAME "Stomp"
#define PHP_STOMP_FRAME_CLASSNAME "StompFrame"
#define PHP_STOMP_EXCEPTION_CLASSNAME "StompException"
#define PHP_STOMP_ERR_UNKNOWN "Stomp unknown error"
#define PHP_STOMP_ERR_INVALID_BROKER_URI "Invalid Broker URI"
#define PHP_STOMP_ERR_INVALID_BROKER_URI_SCHEME "Invalid Broker URI scheme"
#define PHP_STOMP_ERR_SERVER_NOT_RESPONDING "Server is not responding"
#define PHP_STOMP_ERR_EMPTY_DESTINATION "Destination can not be empty"
#define PHP_STOMP_ERR_NO_CTR "Stomp constructor was not called"
extern zend_module_entry stomp_module_entry;
#define phpext_stomp_ptr &stomp_module_entry
#ifdef PHP_WIN32
#define PHP_STOMP_API __declspec(dllexport)
#else
#define PHP_STOMP_API
#endif
#ifdef ZTS
#include "TSRM.h"
#endif
PHP_MINIT_FUNCTION(stomp);
PHP_MSHUTDOWN_FUNCTION(stomp);
PHP_RINIT_FUNCTION(stomp);
PHP_RSHUTDOWN_FUNCTION(stomp);
PHP_MINFO_FUNCTION(stomp);
/* Methods declarations */
PHP_FUNCTION(stomp_version);
PHP_FUNCTION(stomp_connect);
PHP_FUNCTION(stomp_connect_error);
PHP_FUNCTION(stomp_get_session_id);
PHP_FUNCTION(stomp_close);
PHP_FUNCTION(stomp_send);
PHP_FUNCTION(stomp_subscribe);
PHP_FUNCTION(stomp_has_frame);
PHP_FUNCTION(stomp_read_frame);
PHP_FUNCTION(stomp_unsubscribe);
PHP_FUNCTION(stomp_begin);
PHP_FUNCTION(stomp_commit);
PHP_FUNCTION(stomp_abort);
PHP_FUNCTION(stomp_ack);
PHP_FUNCTION(stomp_error);
PHP_FUNCTION(stomp_set_read_timeout);
PHP_FUNCTION(stomp_get_read_timeout);
PHP_METHOD(stompframe, __construct);
PHP_METHOD(stompexception, getDetails);
ZEND_BEGIN_MODULE_GLOBALS(stomp)
/* INI */
char *default_broker;
long read_timeout_sec;
long read_timeout_usec;
long connection_timeout_sec;
long connection_timeout_usec;
/* Others */
long error_no;
char *error_msg;
ZEND_END_MODULE_GLOBALS(stomp)
#ifdef ZTS
#define STOMP_G(v) TSRMG(stomp_globals_id, zend_stomp_globals *, v)
#else
#define STOMP_G(v) (stomp_globals.v)
#endif
#endif /* PHP_STOMP_H */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
php-stomp-1.0.5/stomp-1.0.5/stomp.c 0000664 0000000 0000000 00000033644 12147457105 0016573 0 ustar 00root root 0000000 0000000 /*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Pierrick Charron |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "zend_exceptions.h"
#include "ext/standard/php_smart_str.h"
#include "stomp.h"
#include "php_stomp.h"
#define RETURN_READ_FRAME_FAIL { stomp_free_frame(f); return NULL; }
ZEND_EXTERN_MODULE_GLOBALS(stomp);
extern zend_class_entry *stomp_ce_exception;
/* {{{ stomp_init
*/
stomp_t *stomp_init()
{
/* Memory allocation */
stomp_t *stomp = (stomp_t *) emalloc(sizeof(stomp_t));
memset(stomp, 0, sizeof(*stomp));
/* Define all values */
stomp->host = NULL;
stomp->port = 0;
stomp->status = 0;
stomp->error = NULL;
stomp->error_details = NULL;
stomp->errnum = 0;
stomp->session = NULL;
stomp->options.connect_timeout_sec = 2;
stomp->options.connect_timeout_usec = 0;
stomp->options.read_timeout_sec = 2;
stomp->options.read_timeout_usec = 0;
#if HAVE_STOMP_SSL
stomp->options.use_ssl = 0;
stomp->ssl_handle = NULL;
#endif
stomp->buffer = NULL;
return stomp;
}
/* }}} */
/* {{{ stomp_frame_buffer_push
*/
void stomp_frame_buffer_push(stomp_frame_cell_t **pcell, stomp_frame_t *frame)
{
stomp_frame_cell_t *cell = (stomp_frame_cell_t *) emalloc(sizeof(stomp_frame_cell_t));
cell->frame = frame;
cell->next = NULL;
if (!*pcell) {
*pcell = cell;
} else {
stomp_frame_cell_t *cursor = *pcell;
while (cursor->next != NULL) cursor = cursor->next;
cursor->next = cell;
}
}
/* }}} */
/* {{{ stomp_frame_buffer_shift
*/
stomp_frame_t *stomp_frame_buffer_shift(stomp_frame_cell_t **pcell) {
stomp_frame_t *frame = NULL;
if (*pcell) {
stomp_frame_cell_t *cell = *pcell;
*pcell = cell->next;
frame = cell->frame;
efree(cell);
}
return frame;
}
/* }}} */
/* {{{ stomp_frame_buffer_clear
*/
void stomp_frame_buffer_clear(stomp_frame_cell_t **pcell) {
stomp_frame_t *frame = NULL;
while (frame = stomp_frame_buffer_shift(pcell)) efree(frame);
}
/* }}} */
/* {{{ stomp_set_error
*/
void stomp_set_error(stomp_t *stomp, const char *error, int errnum, const char *details)
{
if (stomp->error != NULL) {
efree(stomp->error);
stomp->error = NULL;
}
if (stomp->error_details != NULL) {
efree(stomp->error_details);
stomp->error_details = NULL;
}
stomp->errnum = errnum;
if (error != NULL) {
stomp->error = estrdup(error);
}
if (details != NULL) {
stomp->error_details = estrdup(details);
}
}
/* }}} */
/* {{{ stomp_writeable
*/
int stomp_writeable(stomp_t *stomp)
{
int n;
n = php_pollfd_for_ms(stomp->fd, POLLOUT, 1000);
if (n < 1) {
#ifndef PHP_WIN32
if (n == 0) {
errno = ETIMEDOUT;
}
#endif
return 0;
}
return 1;
}
/* }}} */
/* {{{ stomp_connect
*/
int stomp_connect(stomp_t *stomp, const char *host, unsigned short port TSRMLS_DC)
{
char error[1024];
socklen_t size;
struct timeval tv;
if (stomp->host != NULL)
{
efree(stomp->host);
}
stomp->host = (char *) emalloc(strlen(host) + 1);
memcpy(stomp->host, host, strlen(host));
stomp->host[strlen(host)] = '\0';
stomp->port = port;
tv.tv_sec = stomp->options.connect_timeout_sec;
tv.tv_usec = stomp->options.connect_timeout_usec;
stomp->fd = php_network_connect_socket_to_host(stomp->host, stomp->port, SOCK_STREAM, 0, &tv, NULL, NULL, NULL, 0 TSRMLS_CC);
if (stomp->fd == -1) {
snprintf(error, sizeof(error), "Unable to connect to %s:%ld", stomp->host, stomp->port);
stomp_set_error(stomp, error, errno, NULL);
return 0;
}
size = sizeof(stomp->localaddr);
memset(&stomp->localaddr, 0, size);
if (getsockname(stomp->fd, (struct sockaddr*) &stomp->localaddr, &size) == -1) {
snprintf(error, sizeof(error), "getsockname failed: %s (%d)", strerror(errno), errno);
stomp_set_error(stomp, error, errno, NULL);
return 0;
}
if (stomp_writeable(stomp)) {
#if HAVE_STOMP_SSL
if (stomp->options.use_ssl) {
SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
if (NULL == ctx) {
stomp_set_error(stomp, "failed to create the SSL context", 0, NULL);
return 0;
}
SSL_CTX_set_options(ctx, SSL_OP_ALL);
stomp->ssl_handle = SSL_new(ctx);
if (stomp->ssl_handle == NULL) {
stomp_set_error(stomp, "failed to create the SSL handle", 0, NULL);
SSL_CTX_free(ctx);
return 0;
}
SSL_set_fd(stomp->ssl_handle, stomp->fd);
if (SSL_connect(stomp->ssl_handle) <= 0) {
stomp_set_error(stomp, "SSL/TLS handshake failed", 0, NULL);
SSL_shutdown(stomp->ssl_handle);
return 0;
}
}
#endif
return 1;
} else {
snprintf(error, sizeof(error), "Unable to connect to %s:%ld", stomp->host, stomp->port);
stomp_set_error(stomp, error, errno, NULL);
return 0;
}
}
/* }}} */
/* {{{ stomp_close
*/
void stomp_close(stomp_t *stomp)
{
if (NULL == stomp) {
return;
}
if (stomp->fd != -1) {
#if HAVE_STOMP_SSL
if(stomp->ssl_handle) {
SSL_shutdown(stomp->ssl_handle);
}
#endif
closesocket(stomp->fd);
}
if (stomp->host) {
efree(stomp->host);
}
if (stomp->session) {
efree(stomp->session);
}
if (stomp->error) {
efree(stomp->error);
}
if (stomp->error_details) {
efree(stomp->error_details);
}
stomp_frame_buffer_clear(&stomp->buffer);
efree(stomp);
}
/* }}} */
/* {{{ stomp_send
*/
int stomp_send(stomp_t *stomp, stomp_frame_t *frame TSRMLS_DC)
{
smart_str buf = {0};
/* Command */
smart_str_appends(&buf, frame->command);
smart_str_appendc(&buf, '\n');
/* Headers */
if (frame->headers) {
char *key;
ulong pos;
zend_hash_internal_pointer_reset(frame->headers);
while (zend_hash_get_current_key(frame->headers, &key, &pos, 0) == HASH_KEY_IS_STRING) {
char *value = NULL;
smart_str_appends(&buf, key);
smart_str_appendc(&buf, ':');
if (zend_hash_get_current_data(frame->headers, (void **)&value) == SUCCESS) {
smart_str_appends(&buf, value);
}
smart_str_appendc(&buf, '\n');
zend_hash_move_forward(frame->headers);
}
}
if (frame->body_length > 0) {
smart_str_appends(&buf, "content-length:");
smart_str_append_long(&buf, frame->body_length);
smart_str_appendc(&buf, '\n');
}
smart_str_appendc(&buf, '\n');
if (frame->body > 0) {
smart_str_appendl(&buf, frame->body, frame->body_length > 0 ? frame->body_length : strlen(frame->body));
}
if (!stomp_writeable(stomp)) {
char error[1024];
snprintf(error, sizeof(error), "Unable to send data");
stomp_set_error(stomp, error, errno, NULL);
smart_str_free(&buf);
return 0;
}
#ifdef HAVE_STOMP_SSL
if (stomp->options.use_ssl) {
if (-1 == SSL_write(stomp->ssl_handle, buf.c, buf.len) || -1 == SSL_write(stomp->ssl_handle, "\0\n", 2)) {
char error[1024];
snprintf(error, sizeof(error), "Unable to send data");
stomp_set_error(stomp, error, errno, NULL);
smart_str_free(&buf);
return 0;
}
} else {
#endif
if (-1 == send(stomp->fd, buf.c, buf.len, 0) || -1 == send(stomp->fd, "\0\n", 2, 0)) {
char error[1024];
snprintf(error, sizeof(error), "Unable to send data");
stomp_set_error(stomp, error, errno, NULL);
smart_str_free(&buf);
return 0;
}
#ifdef HAVE_STOMP_SSL
}
#endif
smart_str_free(&buf);
return 1;
}
/* }}} */
/* {{{ stomp_recv
*/
int stomp_recv(stomp_t *stomp, char *msg, size_t length)
{
int len;
#if HAVE_STOMP_SSL
if(stomp->options.use_ssl) {
len = SSL_read(stomp->ssl_handle, msg, length);
} else {
#endif
len = recv(stomp->fd, msg, length, 0);
#if HAVE_STOMP_SSL
}
#endif
if (len == 0) {
TSRMLS_FETCH();
zend_throw_exception_ex(stomp_ce_exception, errno TSRMLS_CC, "Unexpected EOF while reading from socket");
stomp->status = -1;
}
return len;
}
/* }}} */
/* {{{ stomp_read_buffer
*/
static int stomp_read_buffer(stomp_t *stomp, char **data)
{
int rc = 0;
size_t i = 0;
size_t bufsize = STOMP_BUFSIZE + 1;
char *buffer = (char *) emalloc(STOMP_BUFSIZE + 1);
while (1) {
size_t length = 1;
rc = stomp_recv(stomp, buffer + i, length);
if (rc < 1) {
efree(buffer);
return -1;
}
if (1 == length) {
i++;
if (buffer[i-1] == 0) {
char endline[1];
if (1 != stomp_recv(stomp, endline, 1) && '\n' != endline[0]) {
efree(buffer);
return 0;
}
break;
}
if (i >= bufsize) {
buffer = (char *) erealloc(buffer, bufsize + STOMP_BUFSIZE);
bufsize += STOMP_BUFSIZE;
}
}
}
if (i > 1) {
*data = (char *) emalloc(i);
if (NULL == *data) {
efree(buffer);
return -1;
}
memcpy(*data, buffer, i);
}
efree(buffer);
return i-1;
}
/* }}} */
/* {{{ stomp_read_line
*/
static int stomp_read_line(stomp_t *stomp, char **data)
{
int rc = 0;
size_t i = 0;
size_t bufsize = STOMP_BUFSIZE + 1;
char *buffer = (char *) emalloc(STOMP_BUFSIZE + 1);
while (1) {
size_t length = 1;
rc = stomp_recv(stomp, buffer + i, length);
if (rc < 1) {
efree(buffer);
return -1;
}
if (1 == length) {
i++;
if (buffer[i-1] == '\n') {
buffer[i-1] = 0;
break;
} else if (buffer[i-1] == 0) {
efree(buffer);
return 0;
}
if (i >= bufsize) {
buffer = (char *) erealloc(buffer, bufsize + STOMP_BUFSIZE);
bufsize += STOMP_BUFSIZE;
}
}
}
if (i > 1) {
*data = (char *) emalloc(i);
if (NULL == *data) {
efree(buffer);
return -1;
}
memcpy(*data, buffer, i);
}
efree(buffer);
return i-1;
}
/* }}} */
/* {{{ stomp_free_frame
*/
void stomp_free_frame(stomp_frame_t *frame)
{
if (frame) {
if (frame->command) {
efree(frame->command);
}
if (frame->body) {
efree(frame->body);
}
if (frame->headers) {
zend_hash_destroy(frame->headers);
efree(frame->headers);
}
efree(frame);
}
}
/* }}} */
/* {{{ stomp_read_frame
*/
stomp_frame_t *stomp_read_frame(stomp_t *stomp)
{
stomp_frame_t *f = NULL;
char *cmd = NULL, *length_str = NULL;
int length = 0;
if (stomp->buffer) {
return stomp_frame_buffer_shift(&stomp->buffer);
}
if (!stomp_select(stomp)) {
return NULL;
}
INIT_STOMP_FRAME(f);
if (NULL == f) {
return NULL;
}
/* Parse the command */
length = stomp_read_line(stomp, &cmd);
if (length < 1) {
RETURN_READ_FRAME_FAIL;
}
f->command = cmd;
f->command_length = length;
/* Parse the header */
while (1) {
char *p = NULL;
length = stomp_read_line(stomp, &p);
if (length < 0) {
RETURN_READ_FRAME_FAIL;
}
if (0 == length) {
break;
} else {
char *p2 = NULL;
char *key;
char *value;
p2 = strstr(p,":");
if (p2 == NULL) {
efree(p);
RETURN_READ_FRAME_FAIL;
}
/* Null terminate the key */
*p2=0;
key = p;
/* The rest is the value. */
value = p2+1;
/* Insert key/value into hash table. */
zend_hash_add(f->headers, key, strlen(key) + 1, value, strlen(value) + 1, NULL);
efree(p);
}
}
/* Check for the content length */
if (zend_hash_find(f->headers, "content-length", sizeof("content-length"), (void **)&length_str) == SUCCESS) {
char endbuffer[2];
length = 2;
f->body_length = atoi(length_str);
f->body = (char *) emalloc(f->body_length);
if (-1 == stomp_recv(stomp, f->body, f->body_length)) {
RETURN_READ_FRAME_FAIL;
}
if (length != stomp_recv(stomp, endbuffer, length) || endbuffer[0] != '\0' || endbuffer[1] != '\n') {
RETURN_READ_FRAME_FAIL;
}
} else {
f->body_length = stomp_read_buffer(stomp, &f->body);
}
return f;
}
/* }}} */
/* {{{ stomp_valid_receipt
*/
int stomp_valid_receipt(stomp_t *stomp, stomp_frame_t *frame) {
int success = 1;
char error[1024];
char *receipt = NULL;
if (zend_hash_find(frame->headers, "receipt", sizeof("receipt"), (void **)&receipt) == SUCCESS) {
stomp_frame_cell_t *buffer = NULL;
success = 0;
while (1) {
stomp_frame_t *res = stomp_read_frame(stomp);
if (res) {
if (0 == strncmp("RECEIPT", res->command, sizeof("RECEIPT") - 1)) {
char *receipt_id = NULL;
if (zend_hash_find(res->headers, "receipt-id", sizeof("receipt-id"), (void **)&receipt_id) == SUCCESS
&& strlen(receipt) == strlen(receipt_id)
&& !strcmp(receipt, receipt_id)) {
success = 1;
} else {
snprintf(error, sizeof(error), "Unexpected receipt id : %s", receipt_id);
stomp_set_error(stomp, error, 0, NULL);
}
stomp_free_frame(res);
stomp->buffer = buffer;
return success;
} else if (0 == strncmp("ERROR", res->command, sizeof("ERROR") - 1)) {
char *error_msg = NULL;
if (zend_hash_find(res->headers, "message", sizeof("message"), (void **)&error_msg) == SUCCESS) {
stomp_set_error(stomp, error_msg, 0, res->body);
}
stomp_free_frame(res);
stomp->buffer = buffer;
return success;
} else {
stomp_frame_buffer_push(&buffer, res);
}
} else {
stomp->buffer = buffer;
return success;
}
}
}
return success;
}
/* }}} */
/* {{{ stomp_select
*/
int stomp_select(stomp_t *stomp)
{
int n;
struct timeval tv;
if (stomp->buffer) {
return 1;
}
tv.tv_sec = stomp->options.read_timeout_sec;
tv.tv_usec = stomp->options.read_timeout_usec;
n = php_pollfd_for(stomp->fd, PHP_POLLREADABLE, &tv);
if (n < 1) {
#if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK))
if (n == 0) {
errno = ETIMEDOUT;
}
#endif
return 0;
}
return 1;
}
/* }}} */
php-stomp-1.0.5/stomp-1.0.5/stomp.h 0000775 0000000 0000000 00000005540 12147457105 0016575 0 ustar 00root root 0000000 0000000 /*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Pierrick Charron |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef _STOMP_H_
#define _STOMP_H_
#include "php_network.h"
#if HAVE_STOMP_SSL
#include
#endif
#define STOMP_BUFSIZE 4096
#define INIT_STOMP_FRAME(f) \
f = (stomp_frame_t *) emalloc(sizeof(stomp_frame_t)); \
f->command = NULL; f->body = NULL; \
ALLOC_HASHTABLE(f->headers); \
zend_hash_init(f->headers, 0, NULL, NULL, 0);
typedef struct _stomp_options {
long connect_timeout_sec;
long connect_timeout_usec;
long read_timeout_sec;
long read_timeout_usec;
#if HAVE_STOMP_SSL
int use_ssl;
#endif
} stomp_options_t;
typedef struct _stomp_frame {
char *command;
int command_length;
HashTable *headers;
char *body;
int body_length;
} stomp_frame_t;
typedef struct _stomp_frame_cell {
stomp_frame_t *frame;
struct _stomp_frame_cell *next;
} stomp_frame_cell_t;
typedef struct _stomp {
php_socket_t fd;
php_sockaddr_storage localaddr;
stomp_options_t options;
char *host;
unsigned short port;
int status;
char *error;
int errnum;
char *error_details;
char *session;
#if HAVE_STOMP_SSL
SSL *ssl_handle;
#endif
stomp_frame_cell_t *buffer;
} stomp_t;
stomp_t *stomp_init();
int stomp_connect(stomp_t *stomp, const char *host, unsigned short port TSRMLS_DC);
void stomp_close(stomp_t *stomp);
int stomp_send(stomp_t *connection, stomp_frame_t *frame TSRMLS_DC);
stomp_frame_t *stomp_read_frame(stomp_t *connection);
int stomp_valid_receipt(stomp_t *connection, stomp_frame_t *frame);
int stomp_select(stomp_t *connection);
void stomp_set_error(stomp_t *stomp, const char *error, int errnum, const char *details);
void stomp_free_frame(stomp_frame_t *frame);
#endif /* _STOMP_H_ */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
php-stomp-1.0.5/stomp-1.0.5/tests/ 0000775 0000000 0000000 00000000000 12147457105 0016415 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/001-stomp.phpt 0000664 0000000 0000000 00000000303 12147457105 0020746 0 ustar 00root root 0000000 0000000 --TEST--
Check for stomp presence
--SKIPIF--
--FILE--
--EXPECT--
stomp extension is available
php-stomp-1.0.5/stomp-1.0.5/tests/002-version.phpt 0000664 0000000 0000000 00000000236 12147457105 0021277 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_version()
--SKIPIF--
--FILE--
--EXPECTF--
%d.%d.%s
php-stomp-1.0.5/stomp-1.0.5/tests/003-connect/ 0000775 0000000 0000000 00000000000 12147457105 0020346 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/003-connect/001.phpt 0000664 0000000 0000000 00000001005 12147457105 0021537 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_connect() - URI validation
--SKIPIF--
--FILE--
--EXPECT--
NULL
string(18) "Invalid Broker URI"
NULL
string(18) "Invalid Broker URI"
NULL
string(18) "Invalid Broker URI"
NULL
string(25) "Invalid Broker URI scheme"
php-stomp-1.0.5/stomp-1.0.5/tests/003-connect/002.phpt 0000664 0000000 0000000 00000000373 12147457105 0021547 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_connect() - Test connection
--SKIPIF--
--FILE--
--EXPECTF--
resource(%d) of type (stomp connection)
NULL
php-stomp-1.0.5/stomp-1.0.5/tests/004-getSessionId/ 0000775 0000000 0000000 00000000000 12147457105 0021316 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/004-getSessionId/001.phpt 0000664 0000000 0000000 00000000404 12147457105 0022511 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_get_session_id()
--SKIPIF--
--FILE--
--EXPECTF--
string(%d) "%s"
php-stomp-1.0.5/stomp-1.0.5/tests/005-close/ 0000775 0000000 0000000 00000000000 12147457105 0020024 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/005-close/001.phpt 0000664 0000000 0000000 00000000400 12147457105 0021213 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_close() - tests parameters
--SKIPIF--
--FILE--
--EXPECTF--
Warning: stomp_close() expects parameter 1 to be resource, null given in %s on line %d
php-stomp-1.0.5/stomp-1.0.5/tests/005-close/002.phpt 0000664 0000000 0000000 00000000434 12147457105 0021223 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_close()
--SKIPIF--
--FILE--
--EXPECT--
success
closed
php-stomp-1.0.5/stomp-1.0.5/tests/006-send/ 0000775 0000000 0000000 00000000000 12147457105 0017651 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/006-send/001.phpt 0000664 0000000 0000000 00000001255 12147457105 0021051 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_send() - tests parameters
--SKIPIF--
--FILE--
--EXPECTF--
Warning: stomp_send(): Destination can not be empty in %s on line %d
Warning: stomp_send(): Expects parameter %d to be a string or a StompFrame object. in %s on line %d
bool(true)
bool(true)
bool(true)
php-stomp-1.0.5/stomp-1.0.5/tests/006-send/002.phpt 0000664 0000000 0000000 00000001174 12147457105 0021052 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp::send() - tests parameters
--SKIPIF--
--FILE--
send('', array());
$s->send('/queue/test-06', array());
var_dump($s->send('/queue/test-06', ''));
var_dump($s->send('/queue/test-06', 'A realMessage'));
var_dump($s->send('/queue/test-06', 'بياريك شارون'));
?>
--EXPECTF--
Warning: Stomp::send(): Destination can not be empty in %s on line %d
Warning: Stomp::send(): Expects parameter %d to be a string or a StompFrame object. in %s on line %d
bool(true)
bool(true)
bool(true)
php-stomp-1.0.5/stomp-1.0.5/tests/007-subscribe/ 0000775 0000000 0000000 00000000000 12147457105 0020702 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/007-subscribe/001.phpt 0000664 0000000 0000000 00000000701 12147457105 0022075 0 ustar 00root root 0000000 0000000 --TEST--
Test Stomp::subscribe()
--SKIPIF--
--FILE--
subscribe('', array());
$s->subscribe('/queue/test', 'string');
?>
--EXPECTF--
Warning: Stomp::subscribe(): Destination can not be empty in %s on line %d
Catchable fatal error: Argument 2 passed to Stomp::subscribe() must be %s array, string given in %s on line %d
php-stomp-1.0.5/stomp-1.0.5/tests/008-unsubscribe/ 0000775 0000000 0000000 00000000000 12147457105 0021246 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/008-unsubscribe/001.phpt 0000664 0000000 0000000 00000000713 12147457105 0022444 0 ustar 00root root 0000000 0000000 --TEST--
Test Stomp::unsubscribe()
--SKIPIF--
--FILE--
unsubscribe('', array());
$s->unsubscribe('/queue/test', 'string');
?>
--EXPECTF--
Warning: Stomp::unsubscribe(): Destination can not be empty in %s on line %d
Catchable fatal error: Argument 2 passed to Stomp::unsubscribe() must be %s array, string given in %s on line %d
php-stomp-1.0.5/stomp-1.0.5/tests/009-readFrame/ 0000775 0000000 0000000 00000000000 12147457105 0020611 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/009-readFrame/001.phpt 0000664 0000000 0000000 00000000663 12147457105 0022013 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp::readFrame() - tests functionnality and parameters
--SKIPIF--
--FILE--
send('/queue/test-09', 'A test Message');
$s->subscribe('/queue/test-09', array('ack' => 'auto'));
var_dump($s->readFrame()->body);
var_dump($s->readFrame());
?>
--EXPECTF--
string(14) "A test Message"
bool(false)
php-stomp-1.0.5/stomp-1.0.5/tests/009-readFrame/002.phpt 0000664 0000000 0000000 00000000756 12147457105 0022017 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_read_frame() - test functionnality and parameters
--SKIPIF--
--FILE--
'auto'));
$result = stomp_read_frame($link);
var_dump($result['body']);
var_dump(stomp_read_frame($link));
?>
--EXPECTF--
string(14) "A test Message"
bool(false)
php-stomp-1.0.5/stomp-1.0.5/tests/009-readFrame/003.phpt 0000664 0000000 0000000 00000001146 12147457105 0022012 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp::readFrame() - custom frame class
--SKIPIF--
--FILE--
send('/queue/test-09', 'A test Message');
$s->subscribe('/queue/test-09', array('ack' => 'auto'));
$frame = $s->readFrame('customFrame');
var_dump(get_class($frame), $frame->body);
?>
--EXPECT--
string(11) "customFrame"
string(14) "A test Message"
php-stomp-1.0.5/stomp-1.0.5/tests/009-readFrame/004.phpt 0000664 0000000 0000000 00000000615 12147457105 0022013 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp::readFrame() - Test the body binary safety
--SKIPIF--
--FILE--
send('/queue/test-09', "A test Message\0Foo");
$s->subscribe('/queue/test-09', array('ack' => 'auto'));
var_dump($s->readFrame()->body);
?>
--EXPECTF--
string(18) "A test Message Foo"
php-stomp-1.0.5/stomp-1.0.5/tests/009-readFrame/005.phpt 0000664 0000000 0000000 00000000701 12147457105 0022010 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_read_frame() - Test the body binary safety
--SKIPIF--
--FILE--
'auto'));
$result = stomp_read_frame($link);
var_dump($result['body']);
?>
--EXPECTF--
string(18) "A test Message Foo"
php-stomp-1.0.5/stomp-1.0.5/tests/010-timeout/ 0000775 0000000 0000000 00000000000 12147457105 0020401 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/010-timeout/001.phpt 0000664 0000000 0000000 00000003615 12147457105 0021603 0 ustar 00root root 0000000 0000000 --TEST--
Test Stomp::getReadTimout() and Stomp::setReadTimeout() - tests functionnality and parameters
--INI--
stomp.default_read_timeout_sec=5
stomp.default_read_timeout_usec=5
--SKIPIF--
--FILE--
getReadTimeout());
// Set read timout with an integer as seconds
var_dump($s->setReadTimeout(10));
// Second test, read supposed to return 10.0
var_dump($s->getReadTimeout());
// Set read timout with an integer as seconds
var_dump($s->setReadTimeout(10, 5));
// Third test, read supposed to return 10.5
var_dump($s->getReadTimeout());
// Set read timout with the first param as a string, supposed to trigger a warning
var_dump($s->setReadTimeout(''));
// Fourth test, read supposed to get the last value set : 10.5
var_dump($s->getReadTimeout());
// Set read timout with the second param as a string, supposed to trigger a warning
var_dump($s->setReadTimeout(10, ''));
// Fourth test, read supposed to get the last value set : 10.5
var_dump($s->getReadTimeout());
// Set read timout with the params as null
var_dump($s->setReadTimeout(null, null));
// Fifth test, read supposed to get the last value set : 0.0
var_dump($s->getReadTimeout());
unset($s);
?>
--EXPECTF--
array(2) {
["sec"]=>
int(5)
["usec"]=>
int(5)
}
NULL
array(2) {
["sec"]=>
int(10)
["usec"]=>
int(0)
}
NULL
array(2) {
["sec"]=>
int(10)
["usec"]=>
int(5)
}
Warning: Stomp::setReadTimeout() expects parameter 1 to be long, string given in %s on line %d
NULL
array(2) {
["sec"]=>
int(10)
["usec"]=>
int(5)
}
Warning: Stomp::setReadTimeout() expects parameter 2 to be long, string given in %s on line %d
NULL
array(2) {
["sec"]=>
int(10)
["usec"]=>
int(5)
}
NULL
array(2) {
["sec"]=>
int(0)
["usec"]=>
int(0)
}
php-stomp-1.0.5/stomp-1.0.5/tests/010-timeout/002.phpt 0000664 0000000 0000000 00000004005 12147457105 0021576 0 ustar 00root root 0000000 0000000 --TEST--
Test stomp_get_read_timout() and stomp_set_read_timeout() - tests functionnality and parameters
--INI--
stomp.default_read_timeout_sec=5
stomp.default_read_timeout_usec=5
--SKIPIF--
--FILE--
--EXPECTF--
array(2) {
["sec"]=>
int(5)
["usec"]=>
int(5)
}
NULL
array(2) {
["sec"]=>
int(10)
["usec"]=>
int(0)
}
NULL
array(2) {
["sec"]=>
int(10)
["usec"]=>
int(5)
}
Warning: stomp_set_read_timeout() expects parameter 2 to be long, string given in %s on line %d
NULL
array(2) {
["sec"]=>
int(10)
["usec"]=>
int(5)
}
Warning: stomp_set_read_timeout() expects parameter 3 to be long, string given in %s on line %d
NULL
array(2) {
["sec"]=>
int(10)
["usec"]=>
int(5)
}
NULL
array(2) {
["sec"]=>
int(0)
["usec"]=>
int(0)
}
php-stomp-1.0.5/stomp-1.0.5/tests/011-commit/ 0000775 0000000 0000000 00000000000 12147457105 0020204 5 ustar 00root root 0000000 0000000 php-stomp-1.0.5/stomp-1.0.5/tests/011-commit/001.phpt 0000664 0000000 0000000 00000002122 12147457105 0021376 0 ustar 00root root 0000000 0000000 --TEST--
Test Stomp::commit() - tests functionnality and parameters
--SKIPIF--
--FILE--
begin('t1'));
// sends a message to the queue and specifies a good transaction
var_dump($s->send('/queue/test-011-commit', 'bar', array('transaction' => 't1')));
// sends a message to the queue and asks for a receipt
$s->send('/queue/test-011-commit', 'bar', array('transaction' => 't2', 'receipt' => 'tptp'));
echo gettype($s->error()) . PHP_EOL;
// commits a valid transaction
var_dump($s->commit('t1'));
// commits non valid transaction (null as a parameter) and asks for a receipt
var_dump($s->commit(null, array('receipt' => 'commit-key')));
var_dump($s->commit(null));
// commits a non valid transaction (a transaction id that does not exist) and asks for a receipt
$s->commit('t2', array('receipt' => 'commit-key'));
echo gettype($s->error());
unset($s);
?>
--EXPECTF--
bool(true)
bool(true)
string
bool(true)
bool(false)
bool(true)
string