2002-03-15 00:00:34 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "php.h"
|
|
|
|
#include "php_ini.h"
|
|
|
|
#include "ext/standard/info.h"
|
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
#include "php_rpc.h"
|
2002-03-15 13:10:35 +00:00
|
|
|
#include "rpc.h"
|
2002-03-15 00:00:34 +00:00
|
|
|
#include "layer.h"
|
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
static void rpc_instance_dtor(void *);
|
2002-03-19 03:36:16 +00:00
|
|
|
static void rpc_class_dtor(void *);
|
|
|
|
static void rpc_string_dtor(void *);
|
2002-06-09 14:51:41 +00:00
|
|
|
|
|
|
|
static zend_object_value rpc_objects_new(zend_class_entry * TSRMLS_DC);
|
|
|
|
static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC);
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
static int zend_ts_hash_remove_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData);
|
|
|
|
|
2002-03-15 00:00:34 +00:00
|
|
|
/* object handler */
|
2002-03-19 03:36:16 +00:00
|
|
|
static zval* rpc_read(zval *, zval *, int TSRMLS_DC);
|
|
|
|
static void rpc_write(zval *, zval *, zval * TSRMLS_DC);
|
|
|
|
static zval** rpc_get_property(zval *, zval * TSRMLS_DC);
|
|
|
|
static zval* rpc_get(zval * TSRMLS_DC);
|
|
|
|
static void rpc_set(zval **, zval * TSRMLS_DC);
|
|
|
|
static int rpc_has_property(zval *, zval *, int TSRMLS_DC);
|
|
|
|
static void rpc_unset_property(zval *, zval * TSRMLS_DC);
|
|
|
|
static HashTable* rpc_get_properties(zval * TSRMLS_DC);
|
|
|
|
static union _zend_function* rpc_get_method(zval *, char *, int TSRMLS_DC);
|
|
|
|
static union _zend_function* rpc_get_constructor(zval * TSRMLS_DC);
|
2002-06-09 14:51:41 +00:00
|
|
|
static zend_class_entry* rpc_get_class_entry(zval *object TSRMLS_DC);
|
2002-03-19 03:36:16 +00:00
|
|
|
static int rpc_compare(zval *, zval * TSRMLS_DC);
|
2002-03-15 00:00:34 +00:00
|
|
|
/**/
|
|
|
|
|
2002-04-22 14:25:46 +00:00
|
|
|
/* pseudo handler */
|
|
|
|
static void rpc_internal_get(rpc_internal *, char *, zend_uint, zval *);
|
|
|
|
static void rpc_internal_set(rpc_internal *, char *, zend_uint, zval *);
|
|
|
|
/**/
|
|
|
|
|
2002-04-22 19:40:01 +00:00
|
|
|
extern zend_object_handlers rpc_proxy_handlers;
|
|
|
|
|
2002-03-15 00:00:34 +00:00
|
|
|
static zend_object_handlers rpc_handlers = {
|
2002-06-09 14:51:41 +00:00
|
|
|
ZEND_OBJECTS_STORE_HANDLERS,
|
|
|
|
|
2002-03-15 00:00:34 +00:00
|
|
|
rpc_read,
|
|
|
|
rpc_write,
|
|
|
|
rpc_get_property,
|
2002-03-16 16:15:34 +00:00
|
|
|
NULL,
|
2002-03-15 00:00:34 +00:00
|
|
|
rpc_get,
|
|
|
|
rpc_set,
|
2002-06-09 14:51:41 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2002-03-15 00:00:34 +00:00
|
|
|
rpc_has_property,
|
|
|
|
rpc_unset_property,
|
|
|
|
rpc_get_properties,
|
|
|
|
rpc_get_method,
|
2002-03-19 18:46:28 +00:00
|
|
|
NULL,
|
2002-03-15 00:00:34 +00:00
|
|
|
rpc_get_constructor,
|
2002-04-22 14:25:46 +00:00
|
|
|
rpc_get_class_entry,
|
2002-06-09 14:51:41 +00:00
|
|
|
NULL,
|
2002-03-15 00:00:34 +00:00
|
|
|
rpc_compare
|
|
|
|
};
|
|
|
|
|
|
|
|
/* {{{ rpc_functions[]
|
|
|
|
*/
|
|
|
|
function_entry rpc_functions[] = {
|
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ rpc_module_entry
|
|
|
|
*/
|
|
|
|
zend_module_entry rpc_module_entry = {
|
|
|
|
STANDARD_MODULE_HEADER,
|
|
|
|
"rpc",
|
|
|
|
rpc_functions,
|
2002-03-16 16:15:34 +00:00
|
|
|
ZEND_MINIT(rpc),
|
|
|
|
ZEND_MSHUTDOWN(rpc),
|
2002-03-15 00:00:34 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2002-03-16 16:15:34 +00:00
|
|
|
ZEND_MINFO(rpc),
|
2002-03-15 00:00:34 +00:00
|
|
|
"0.1a",
|
|
|
|
STANDARD_MODULE_PROPERTIES
|
|
|
|
};
|
|
|
|
/* }}} */
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_class_entry rpc_class_entry;
|
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
static HashTable *handlers;
|
2002-06-10 21:16:25 +00:00
|
|
|
static TsHashTable *pool;
|
2002-04-22 14:25:46 +00:00
|
|
|
static TsHashTable *classes;
|
2002-03-19 23:28:52 +00:00
|
|
|
static zend_llist *classes_list;
|
2002-03-15 23:28:10 +00:00
|
|
|
|
2002-03-15 00:00:34 +00:00
|
|
|
#ifdef COMPILE_DL_RPC
|
2002-03-15 23:28:10 +00:00
|
|
|
ZEND_GET_MODULE(rpc);
|
2002-03-15 00:00:34 +00:00
|
|
|
#endif
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
ZEND_INI_BEGIN()
|
|
|
|
ZEND_INI_END()
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
/* {{{ ZEND_MINIT_FUNCTION
|
2002-03-15 00:00:34 +00:00
|
|
|
*/
|
2002-03-19 18:46:28 +00:00
|
|
|
ZEND_MINIT_FUNCTION(rpc)
|
2002-03-15 00:00:34 +00:00
|
|
|
{
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_class_entry *rpc_entry;
|
|
|
|
|
|
|
|
/* rpc base class entry */
|
|
|
|
INIT_CLASS_ENTRY(rpc_class_entry, "rpc", NULL);
|
|
|
|
rpc_entry = zend_register_internal_class(&rpc_class_entry TSRMLS_CC);
|
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
handlers = (HashTable *) pemalloc(sizeof(HashTable), TRUE);
|
2002-06-10 21:16:25 +00:00
|
|
|
pool = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE);
|
2002-04-22 14:25:46 +00:00
|
|
|
classes = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE);
|
2002-03-19 23:28:52 +00:00
|
|
|
classes_list = (zend_llist *) pemalloc(sizeof(zend_llist), TRUE);
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
zend_hash_init(handlers, 0, NULL, NULL, TRUE);
|
2002-06-10 21:16:25 +00:00
|
|
|
zend_ts_hash_init(pool, sizeof(rpc_internal **), NULL, rpc_instance_dtor, TRUE);
|
2002-04-22 14:25:46 +00:00
|
|
|
zend_ts_hash_init(classes, 0, NULL, NULL, TRUE);
|
2002-03-19 23:28:52 +00:00
|
|
|
zend_llist_init(classes_list, sizeof(rpc_class_hash **), rpc_class_dtor, TRUE);
|
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
FOREACH_HANDLER {
|
|
|
|
HANDLER.rpc_handler_init();
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
/* create a class entry for every rpc handler */
|
2002-06-09 14:51:41 +00:00
|
|
|
INIT_CLASS_ENTRY((*(HANDLER.ce)),
|
|
|
|
HANDLER.name,
|
|
|
|
HANDLER.methods);
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
HANDLER.ce->create_object = rpc_objects_new;
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
/* load all available rpc handler into a hash */
|
|
|
|
zend_hash_add(handlers, HANDLER.name, strlen(HANDLER.name) + 1, &(HANDLER.handlers), sizeof(rpc_object_handlers *), NULL);
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
/* register classes and functions */
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_register_internal_class_ex(HANDLER.ce, rpc_entry, NULL TSRMLS_CC);
|
2002-03-15 23:28:10 +00:00
|
|
|
zend_register_functions(HANDLER.functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_register_ini_entries(HANDLER.ini, module_number TSRMLS_CC);
|
2002-03-15 23:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
REGISTER_INI_ENTRIES();
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2002-03-15 00:00:34 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2002-03-16 16:15:34 +00:00
|
|
|
/* {{{ ZEND_MSHUTDOWN_FUNCTION
|
2002-03-15 00:00:34 +00:00
|
|
|
*/
|
2002-03-16 16:15:34 +00:00
|
|
|
ZEND_MSHUTDOWN_FUNCTION(rpc)
|
2002-03-15 00:00:34 +00:00
|
|
|
{
|
2002-03-19 23:28:52 +00:00
|
|
|
/* destroy instances first */
|
2002-06-10 21:16:25 +00:00
|
|
|
zend_ts_hash_destroy(pool);
|
2002-03-19 18:46:28 +00:00
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
zend_ts_hash_destroy(classes);
|
2002-03-19 23:28:52 +00:00
|
|
|
zend_llist_destroy(classes_list);
|
2002-03-19 18:46:28 +00:00
|
|
|
zend_hash_destroy(handlers);
|
|
|
|
|
|
|
|
pefree(handlers, TRUE);
|
|
|
|
pefree(classes, TRUE);
|
2002-03-15 13:10:35 +00:00
|
|
|
|
2002-03-15 00:00:34 +00:00
|
|
|
UNREGISTER_INI_ENTRIES();
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-03-16 16:15:34 +00:00
|
|
|
/* {{{ ZEND_MINFO_FUNCTION
|
2002-03-15 00:00:34 +00:00
|
|
|
*/
|
2002-03-16 16:15:34 +00:00
|
|
|
ZEND_MINFO_FUNCTION(rpc)
|
2002-03-15 00:00:34 +00:00
|
|
|
{
|
|
|
|
php_info_print_table_start();
|
|
|
|
php_info_print_table_header(2, "rpc support", "enabled");
|
|
|
|
php_info_print_table_end();
|
|
|
|
|
|
|
|
DISPLAY_INI_ENTRIES();
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-03-19 03:36:16 +00:00
|
|
|
static void rpc_class_dtor(void *pDest)
|
|
|
|
{
|
|
|
|
rpc_class_hash **hash;
|
|
|
|
|
|
|
|
hash = (rpc_class_hash **) pDest;
|
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
if ((*hash)->singleton) {
|
|
|
|
RPC_HT(*hash)->rpc_dtor((*hash)->data);
|
|
|
|
}
|
|
|
|
|
2002-04-22 14:25:46 +00:00
|
|
|
zend_ts_hash_destroy(&((*hash)->methods));
|
|
|
|
zend_ts_hash_destroy(&((*hash)->properties));
|
2002-03-19 03:36:16 +00:00
|
|
|
|
|
|
|
free((*hash)->name.str);
|
2002-03-19 23:28:52 +00:00
|
|
|
pefree((*hash), TRUE);
|
2002-03-19 03:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void rpc_string_dtor(void *pDest)
|
|
|
|
{
|
|
|
|
rpc_string **string;
|
|
|
|
|
|
|
|
string = (rpc_string **) pDest;
|
|
|
|
|
|
|
|
free((*string)->str);
|
|
|
|
pefree(*string, TRUE);
|
|
|
|
}
|
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
static void rpc_instance_dtor(void *pDest)
|
|
|
|
{
|
|
|
|
rpc_internal **intern;
|
|
|
|
|
|
|
|
intern = (rpc_internal **) pDest;
|
|
|
|
|
|
|
|
RPC_HT(*intern)->rpc_dtor((*intern)->data);
|
|
|
|
|
|
|
|
pefree(*intern, TRUE);
|
|
|
|
}
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
static zend_object_value rpc_objects_new(zend_class_entry *class_type TSRMLS_DC)
|
2002-03-15 00:00:34 +00:00
|
|
|
{
|
|
|
|
zend_object_value *zov;
|
2002-03-15 13:10:35 +00:00
|
|
|
rpc_internal *intern;
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
/* set up the object value struct */
|
2002-03-15 13:10:35 +00:00
|
|
|
zov = (zend_object_value*) pemalloc(sizeof(zend_object_value), TRUE);
|
2002-03-15 00:00:34 +00:00
|
|
|
zov->handlers = &rpc_handlers;
|
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
/* set up the internal representation of our rpc instance */
|
|
|
|
intern = (rpc_internal *) pemalloc(sizeof(rpc_internal), TRUE);
|
2002-03-19 03:36:16 +00:00
|
|
|
|
2002-03-15 13:10:35 +00:00
|
|
|
intern->ce = class_type;
|
|
|
|
intern->data = NULL;
|
2002-03-19 18:46:28 +00:00
|
|
|
intern->function_table.hash = intern->ce->function_table;
|
|
|
|
intern->function_table.reader = 0;
|
|
|
|
intern->function_table.mx_reader = tsrm_mutex_alloc();
|
|
|
|
intern->function_table.mx_writer = tsrm_mutex_alloc();
|
2002-03-19 03:36:16 +00:00
|
|
|
intern->mx_handler = tsrm_mutex_alloc();
|
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
if (zend_hash_find(handlers, class_type->name, class_type->name_length + 1, (void **) &(intern->handlers)) != SUCCESS) {
|
2002-03-15 23:28:10 +00:00
|
|
|
/* TODO: exception */
|
|
|
|
}
|
2002-03-15 13:10:35 +00:00
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
zov->handle = zend_objects_store_put(intern, rpc_objects_delete, NULL TSRMLS_CC);
|
2002-03-15 00:00:34 +00:00
|
|
|
|
|
|
|
return *zov;
|
|
|
|
}
|
|
|
|
|
2002-04-22 19:40:01 +00:00
|
|
|
static zend_object_value rpc_create_proxy(TSRMLS_D)
|
|
|
|
{
|
|
|
|
zend_object_value *zov;
|
|
|
|
rpc_proxy *proxy_intern;
|
|
|
|
|
|
|
|
/* set up the object value struct */
|
|
|
|
zov = (zend_object_value*) pemalloc(sizeof(zend_object_value), TRUE);
|
|
|
|
zov->handlers = &rpc_proxy_handlers;
|
|
|
|
|
|
|
|
/* set up the internal representation of the proxy */
|
|
|
|
proxy_intern = (rpc_proxy *) pemalloc(sizeof(rpc_proxy), TRUE);
|
|
|
|
|
|
|
|
/* store the instance in a hash and set the key as handle, thus
|
|
|
|
* we can find it later easily
|
|
|
|
*/
|
2002-06-09 14:51:41 +00:00
|
|
|
/* tsrm_mutex_lock(proxy->mx_writer);
|
2002-04-22 19:40:01 +00:00
|
|
|
{
|
2002-06-10 21:16:25 +00:00
|
|
|
zov->handle = zend_hash_next_free_element(TS_HASH(proxy));
|
2002-04-22 19:40:01 +00:00
|
|
|
zend_ts_hash_next_index_insert(proxy, &proxy_intern, sizeof(rpc_proxy *), NULL);
|
|
|
|
}
|
|
|
|
tsrm_mutex_unlock(proxy->mx_writer);
|
2002-06-09 14:51:41 +00:00
|
|
|
*/
|
2002-04-22 19:40:01 +00:00
|
|
|
return *zov;
|
|
|
|
}
|
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
/* object handler */
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC)
|
2002-03-15 00:00:34 +00:00
|
|
|
{
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_internal *intern = (rpc_internal *) object;
|
2002-06-10 21:16:25 +00:00
|
|
|
|
|
|
|
if (RPC_CLASS(intern) && RPC_CLASS(intern)->singleton) {
|
|
|
|
pefree(intern, TRUE);
|
|
|
|
} else if (RPC_CLASS(intern) && RPC_CLASS(intern)->poolable) {
|
|
|
|
if (RPC_CLASS(intern)->name.str) {
|
|
|
|
zend_ts_hash_add(pool, RPC_CLASS(intern)->name.str, RPC_CLASS(intern)->name.len + 1, &intern, sizeof(rpc_internal *), NULL);
|
|
|
|
} else {
|
|
|
|
zend_ts_hash_index_update(pool, RPC_CLASS(intern)->name.len + 1, &intern, sizeof(rpc_internal *), NULL);
|
2002-03-16 16:15:34 +00:00
|
|
|
}
|
2002-06-10 21:16:25 +00:00
|
|
|
} else {
|
|
|
|
RPC_HT(intern)->rpc_dtor(intern->data);
|
|
|
|
pefree(intern, TRUE);
|
|
|
|
}
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static zval* rpc_read(zval *object, zval *member, int type TSRMLS_DC)
|
|
|
|
{
|
2002-04-22 14:25:46 +00:00
|
|
|
zval *return_value;
|
|
|
|
GET_INTERNAL(intern);
|
2002-03-15 13:10:35 +00:00
|
|
|
|
2002-04-22 14:25:46 +00:00
|
|
|
/* seting up the return value and decrease the refcounter as we don't
|
|
|
|
* keep a reference to this zval.
|
|
|
|
*/
|
|
|
|
MAKE_STD_ZVAL(return_value);
|
|
|
|
ZVAL_DELREF(return_value);
|
|
|
|
ZVAL_NULL(return_value);
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
if (intern->hash && Z_TYPE_P(member) == IS_LONG) {
|
|
|
|
rpc_internal_get(intern, NULL, Z_LVAL_P(member), return_value);
|
2002-04-22 14:25:46 +00:00
|
|
|
} else if (Z_TYPE_P(member) == IS_STRING) {
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_internal_get(intern, Z_STRVAL_P(member), Z_STRLEN_P(member), return_value);
|
2002-04-22 14:25:46 +00:00
|
|
|
} else {
|
|
|
|
/* TODO: exception here */
|
|
|
|
}
|
|
|
|
|
|
|
|
return return_value;
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void rpc_write(zval *object, zval *member, zval *value TSRMLS_DC)
|
|
|
|
{
|
2002-04-22 14:25:46 +00:00
|
|
|
GET_INTERNAL(intern);
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
if (intern->hash && Z_TYPE_P(member) == IS_LONG) {
|
|
|
|
rpc_internal_set(intern, NULL, Z_LVAL_P(member), value);
|
2002-04-22 14:25:46 +00:00
|
|
|
} else if (Z_TYPE_P(member) == IS_STRING) {
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_internal_set(intern, Z_STRVAL_P(member), Z_STRLEN_P(member), value);
|
2002-04-22 14:25:46 +00:00
|
|
|
} else {
|
|
|
|
/* TODO: exception here */
|
|
|
|
}
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static zval** rpc_get_property(zval *object, zval *member TSRMLS_DC)
|
|
|
|
{
|
2002-04-22 19:40:01 +00:00
|
|
|
zval **return_value;
|
2002-04-22 14:25:46 +00:00
|
|
|
GET_INTERNAL(intern);
|
2002-03-15 13:10:35 +00:00
|
|
|
|
2002-04-22 19:40:01 +00:00
|
|
|
return_value = emalloc(sizeof(zval *));
|
|
|
|
MAKE_STD_ZVAL(*return_value);
|
|
|
|
Z_TYPE_P(object) = IS_OBJECT;
|
|
|
|
(*return_value)->value.obj = rpc_create_proxy(TSRMLS_C);
|
|
|
|
|
|
|
|
return return_value;
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static zval* rpc_get(zval *property TSRMLS_DC)
|
|
|
|
{
|
2002-03-19 03:36:16 +00:00
|
|
|
/* not yet implemented */
|
2002-03-15 13:10:35 +00:00
|
|
|
return NULL;
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void rpc_set(zval **property, zval *value TSRMLS_DC)
|
|
|
|
{
|
2002-03-19 03:36:16 +00:00
|
|
|
/* not yet implemented */
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int rpc_has_property(zval *object, zval *member, int check_empty TSRMLS_DC)
|
|
|
|
{
|
2002-03-15 13:10:35 +00:00
|
|
|
// GET_INTERNAL(intern);
|
|
|
|
|
|
|
|
/* FIXME */
|
|
|
|
return FAILURE;
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void rpc_unset_property(zval *object, zval *member TSRMLS_DC)
|
|
|
|
{
|
2002-03-15 13:10:35 +00:00
|
|
|
// GET_INTERNAL(intern);
|
2002-03-15 23:28:10 +00:00
|
|
|
/* FIXME */
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HashTable* rpc_get_properties(zval *object TSRMLS_DC)
|
|
|
|
{
|
2002-03-15 13:10:35 +00:00
|
|
|
// GET_INTERNAL(intern);
|
|
|
|
|
|
|
|
/* FIXME */
|
|
|
|
return NULL;
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static union _zend_function* rpc_get_method(zval *object, char *method, int method_len TSRMLS_DC)
|
|
|
|
{
|
2002-03-15 23:28:10 +00:00
|
|
|
zend_function *function;
|
2002-03-16 16:15:34 +00:00
|
|
|
GET_INTERNAL(intern);
|
2002-03-15 23:28:10 +00:00
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
if (zend_ts_hash_find(&(intern->function_table), method, method_len + 1, &function) != SUCCESS) {
|
2002-03-19 18:46:28 +00:00
|
|
|
zend_internal_function *zif;
|
2002-03-15 13:10:35 +00:00
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function));
|
|
|
|
zif->arg_types = NULL;
|
|
|
|
zif->function_name = method;
|
|
|
|
zif->handler = ZEND_FN(rpc_call);
|
|
|
|
zif->scope = NULL;
|
|
|
|
zif->type = ZEND_INTERNAL_FUNCTION;
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
/* add new method to the method table */
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_ts_hash_add(&(intern->function_table), method, method_len + 1, zif, sizeof(zend_function), &function);
|
2002-03-19 18:46:28 +00:00
|
|
|
efree(zif);
|
|
|
|
}
|
2002-03-15 13:10:35 +00:00
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
return function;
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static union _zend_function* rpc_get_constructor(zval *object TSRMLS_DC)
|
|
|
|
{
|
2002-03-19 18:46:28 +00:00
|
|
|
zend_function *rpc_ctor;
|
2002-03-15 13:10:35 +00:00
|
|
|
GET_INTERNAL(intern);
|
2002-06-09 14:51:41 +00:00
|
|
|
|
|
|
|
if (zend_ts_hash_find(&(intern->function_table), intern->ce->name, intern->ce->name_length + 1, &rpc_ctor) != SUCCESS) {
|
2002-03-19 18:46:28 +00:00
|
|
|
zend_internal_function *zif;
|
|
|
|
|
|
|
|
zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function));
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
zif->type = ZEND_INTERNAL_FUNCTION;
|
2002-06-09 14:51:41 +00:00
|
|
|
zif->function_name = intern->ce->name;
|
|
|
|
zif->scope = intern->ce;
|
2002-03-19 18:46:28 +00:00
|
|
|
zif->arg_types = NULL;
|
|
|
|
zif->handler = ZEND_FN(rpc_load);
|
2002-03-15 00:00:34 +00:00
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
/* add new constructor to the method table */
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_ts_hash_add(&(intern->function_table), intern->ce->name, intern->ce->name_length + 1, zif, sizeof(zend_function), &rpc_ctor);
|
2002-03-19 18:46:28 +00:00
|
|
|
efree(zif);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rpc_ctor;
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
static zend_class_entry* rpc_get_class_entry(zval *object TSRMLS_DC)
|
2002-04-22 14:25:46 +00:00
|
|
|
{
|
|
|
|
GET_INTERNAL(intern);
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
return intern->ce;
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int rpc_compare(zval *object1, zval *object2 TSRMLS_DC)
|
2002-03-15 13:10:35 +00:00
|
|
|
{
|
|
|
|
/* FIXME */
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2002-03-15 23:28:10 +00:00
|
|
|
/**/
|
|
|
|
|
|
|
|
/* constructor */
|
|
|
|
ZEND_FUNCTION(rpc_load)
|
2002-03-15 00:00:34 +00:00
|
|
|
{
|
2002-03-15 23:28:10 +00:00
|
|
|
zval *object = getThis();
|
2002-03-19 18:46:28 +00:00
|
|
|
zval ***args, ***args_free;
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_uint num_args = ZEND_NUM_ARGS();
|
|
|
|
zend_class_entry overloaded_class_entry;
|
2002-03-19 03:36:16 +00:00
|
|
|
rpc_class_hash *class_hash;
|
|
|
|
rpc_class_hash **class_hash_find = NULL;
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_internal *intern;
|
|
|
|
rpc_string hash_val, class_val;
|
2002-03-19 23:28:52 +00:00
|
|
|
int retval, append = 0;
|
|
|
|
char *arg_types;
|
2002-03-15 23:28:10 +00:00
|
|
|
|
|
|
|
/* check if we were called as a constructor or as a function */
|
|
|
|
if (!object) {
|
|
|
|
/* we were called as a function so we have to figure out which rpc layer was requested
|
|
|
|
* and then we have to set up a zval containing the object
|
|
|
|
*/
|
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
/* get class entry */
|
|
|
|
GET_CLASS(ce);
|
2002-03-15 23:28:10 +00:00
|
|
|
|
|
|
|
/* set up a new zval container */
|
2002-03-19 18:46:28 +00:00
|
|
|
object = return_value;
|
2002-03-15 23:28:10 +00:00
|
|
|
|
|
|
|
Z_TYPE_P(object) = IS_OBJECT;
|
|
|
|
|
|
|
|
/* create a new object */
|
2002-06-09 14:51:41 +00:00
|
|
|
object->value.obj = rpc_objects_new(*ce TSRMLS_CC);
|
2002-03-15 23:28:10 +00:00
|
|
|
|
|
|
|
/* now everything is set up the same way as if we were called as a constructor */
|
|
|
|
}
|
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
if (GET_INTERNAL_EX(intern, object) != SUCCESS) {
|
2002-03-16 16:15:34 +00:00
|
|
|
/* TODO: exception */
|
|
|
|
}
|
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
/* fetch further parameters */
|
2002-03-19 23:28:52 +00:00
|
|
|
GET_ARGS_EX(num_args, args, args_free, 1);
|
2002-03-19 18:46:28 +00:00
|
|
|
|
2002-03-19 03:36:16 +00:00
|
|
|
/* if classname != integer */
|
2002-06-09 14:51:41 +00:00
|
|
|
if ((zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "l", &class_val.str) != SUCCESS) ||
|
2002-03-19 03:36:16 +00:00
|
|
|
/* or we have no hash function */
|
2002-06-09 14:51:41 +00:00
|
|
|
!(RPC_HT(intern)->rpc_hash) ||
|
2002-03-19 03:36:16 +00:00
|
|
|
/* or integer hashing is not allowed */
|
2002-06-09 14:51:41 +00:00
|
|
|
!(RPC_HT(intern)->hash_type & HASH_AS_INT)) {
|
2002-03-19 03:36:16 +00:00
|
|
|
|
|
|
|
/* else check for string - classname */
|
2002-06-09 14:51:41 +00:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "s", &class_val.str, &class_val.len) != SUCCESS) {
|
2002-03-19 03:36:16 +00:00
|
|
|
/* none of the two possibilities */
|
2002-03-19 18:46:28 +00:00
|
|
|
/* TODO: exception */
|
2002-03-19 03:36:16 +00:00
|
|
|
php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C));
|
|
|
|
} else {
|
|
|
|
/* hash classname if hashing function exists */
|
2002-06-09 14:51:41 +00:00
|
|
|
if (RPC_HT(intern)->rpc_hash) {
|
2002-03-19 03:36:16 +00:00
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
GET_SIGNATURE(intern, class_val.str, class_val.len, hash_val, num_args, arg_types);
|
2002-03-19 23:28:52 +00:00
|
|
|
|
2002-03-19 03:36:16 +00:00
|
|
|
/* check if already hashed */
|
2002-04-22 14:25:46 +00:00
|
|
|
if (zend_ts_hash_find(classes, hash_val.str, hash_val.len + 1, (void **) &class_hash_find) != SUCCESS) {
|
2002-03-19 03:36:16 +00:00
|
|
|
class_hash = pemalloc(sizeof(rpc_class_hash), TRUE);
|
|
|
|
|
|
|
|
/* set up the cache */
|
2002-04-22 14:25:46 +00:00
|
|
|
zend_ts_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE);
|
|
|
|
zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE);
|
2002-06-10 21:16:25 +00:00
|
|
|
class_hash->handlers = intern->handlers;
|
|
|
|
class_hash->singleton = FALSE;
|
|
|
|
class_hash->poolable = FALSE;
|
|
|
|
class_hash->data = NULL;
|
2002-03-19 03:36:16 +00:00
|
|
|
|
|
|
|
/* do hashing */
|
2002-06-09 14:51:41 +00:00
|
|
|
if (RPC_HT(intern)->rpc_hash(class_val, (rpc_string *)(class_hash), num_args, arg_types, CLASS) != SUCCESS) {
|
2002-03-19 03:36:16 +00:00
|
|
|
/* TODO: exception */
|
|
|
|
}
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
/* overload class entry */
|
|
|
|
RPC_HT(intern)->rpc_name(class_val, &class_val, CLASS);
|
|
|
|
INIT_CLASS_ENTRY(overloaded_class_entry, NULL, NULL);
|
|
|
|
overloaded_class_entry.name = class_val.str;
|
|
|
|
overloaded_class_entry.name_length = class_val.len;
|
|
|
|
class_hash->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC);
|
|
|
|
intern->ce = class_hash->ce;
|
|
|
|
|
|
|
|
/* register with non-hashed key
|
2002-03-19 23:28:52 +00:00
|
|
|
* also track all instaces in a llist for destruction later on, because there might be duplicate entries in
|
|
|
|
* the hashtable and we can't determine if a pointer references to an already freed element
|
|
|
|
*/
|
2002-04-22 14:25:46 +00:00
|
|
|
zend_ts_hash_add(classes, hash_val.str, hash_val.len + 1, &class_hash, sizeof(rpc_class_hash *), (void **) &class_hash_find);
|
2002-03-19 23:28:52 +00:00
|
|
|
tsrm_mutex_lock(classes->mx_writer);
|
|
|
|
zend_llist_add_element(classes_list, class_hash_find);
|
|
|
|
tsrm_mutex_unlock(classes->mx_writer);
|
2002-03-19 03:36:16 +00:00
|
|
|
|
|
|
|
if (class_hash->name.str) {
|
|
|
|
/* register string hashcode */
|
2002-04-22 14:25:46 +00:00
|
|
|
zend_ts_hash_add(classes, class_hash->name.str, class_hash->name.len + 1, &class_hash, sizeof(rpc_class_hash *), NULL);
|
2002-06-09 14:51:41 +00:00
|
|
|
} else if (!class_hash->name.str && (RPC_HT(intern)->hash_type & HASH_AS_INT)) {
|
2002-03-19 03:36:16 +00:00
|
|
|
/* register int hashcode */
|
2002-04-22 14:25:46 +00:00
|
|
|
zend_ts_hash_index_update(classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL);
|
2002-03-19 03:36:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
class_hash = *class_hash_find;
|
2002-06-09 14:51:41 +00:00
|
|
|
intern->ce = class_hash->ce;
|
2002-03-19 03:36:16 +00:00
|
|
|
}
|
2002-03-19 23:28:52 +00:00
|
|
|
|
|
|
|
FREE_SIGNATURE(hash_val, arg_types);
|
2002-06-09 14:51:41 +00:00
|
|
|
} else {
|
2002-06-10 21:16:25 +00:00
|
|
|
/* overload class entry */
|
|
|
|
INIT_CLASS_ENTRY(overloaded_class_entry, class_val.str, NULL);
|
|
|
|
intern->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC);
|
2002-03-19 03:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* integer classname (hashcode) */
|
2002-06-09 14:51:41 +00:00
|
|
|
if (zend_ts_hash_index_find(classes, class_val.len, (void**) &class_hash_find) != SUCCESS) {
|
2002-03-19 03:36:16 +00:00
|
|
|
class_hash = pemalloc(sizeof(rpc_class_hash), TRUE);
|
|
|
|
|
|
|
|
/* set up the cache */
|
|
|
|
class_hash->name.str = NULL;
|
2002-06-09 14:51:41 +00:00
|
|
|
class_hash->name.len = class_val.len;
|
2002-06-10 21:16:25 +00:00
|
|
|
class_hash->handlers = intern->handlers;
|
|
|
|
class_hash->singleton = FALSE;
|
|
|
|
class_hash->poolable = FALSE;
|
|
|
|
class_hash->data = NULL;
|
2002-03-19 03:36:16 +00:00
|
|
|
|
2002-04-22 14:25:46 +00:00
|
|
|
zend_ts_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE);
|
|
|
|
zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE);
|
2002-03-19 03:36:16 +00:00
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
/* overload class entry */
|
|
|
|
RPC_HT(intern)->rpc_name(class_val, &class_val, CLASS);
|
|
|
|
INIT_CLASS_ENTRY(overloaded_class_entry, class_val.str, NULL);
|
|
|
|
class_hash->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC);
|
|
|
|
intern->ce = class_hash->ce;
|
|
|
|
|
2002-03-19 03:36:16 +00:00
|
|
|
/* register int hashcode, we don't know more */
|
2002-04-22 14:25:46 +00:00
|
|
|
zend_ts_hash_index_update(classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL);
|
2002-03-19 03:36:16 +00:00
|
|
|
} else {
|
|
|
|
class_hash = *class_hash_find;
|
2002-06-09 14:51:41 +00:00
|
|
|
intern->ce = class_hash->ce;
|
2002-03-19 03:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if hash function available */
|
2002-06-09 14:51:41 +00:00
|
|
|
if (RPC_HT(intern)->rpc_hash) {
|
2002-06-10 21:16:25 +00:00
|
|
|
rpc_internal *pool_intern;
|
|
|
|
|
2002-03-19 03:36:16 +00:00
|
|
|
/* assign cache structure */
|
2002-06-10 21:16:25 +00:00
|
|
|
RPC_CLASS(intern) = class_hash;
|
2002-03-19 03:36:16 +00:00
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
if (zend_ts_hash_remove_key_or_index(pool, RPC_CLASS(intern)->name.str, RPC_CLASS(intern)->name.len + 1, (void **) &pool_intern) == SUCCESS) {
|
|
|
|
intern->data = pool_intern->data;
|
|
|
|
|
|
|
|
pefree(pool_intern, TRUE);
|
|
|
|
retval = SUCCESS;
|
|
|
|
} else if (RPC_CLASS(intern)->singleton) {
|
|
|
|
/* singleton */
|
|
|
|
intern->data = RPC_CLASS(intern)->data;
|
|
|
|
retval = SUCCESS;
|
|
|
|
} else {
|
|
|
|
/* call the rpc ctor */
|
|
|
|
retval = RPC_HT(intern)->rpc_ctor(*(rpc_string *)(class_hash), &(intern->data), num_args, args);
|
|
|
|
}
|
2002-03-19 03:36:16 +00:00
|
|
|
} else {
|
|
|
|
/* disable caching from now on */
|
2002-06-09 14:51:41 +00:00
|
|
|
intern->hash = NULL;
|
2002-03-19 03:36:16 +00:00
|
|
|
|
|
|
|
/* call the rpc ctor */
|
2002-06-09 14:51:41 +00:00
|
|
|
retval = RPC_HT(intern)->rpc_ctor(class_val, &(intern->data), num_args, args);
|
2002-03-19 03:36:16 +00:00
|
|
|
}
|
|
|
|
|
2002-03-19 18:46:28 +00:00
|
|
|
efree(args_free);
|
|
|
|
|
|
|
|
if (retval != SUCCESS) {
|
|
|
|
/* TODO: exception */
|
|
|
|
}
|
2002-03-15 23:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FUNCTION(rpc_call)
|
|
|
|
{
|
2002-03-19 18:46:28 +00:00
|
|
|
zval *object = getThis();
|
|
|
|
zval ***args, ***args_free;
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_uint num_args = ZEND_NUM_ARGS();
|
2002-03-19 23:28:52 +00:00
|
|
|
char *hash = NULL, *arg_types;
|
2002-03-19 18:46:28 +00:00
|
|
|
int hash_len, retval, strip = 0;
|
|
|
|
|
|
|
|
/* check if we were called as a method or as a function */
|
|
|
|
if (!object) {
|
|
|
|
/* we were called as a function so we have to figure out which rpc layer was requested */
|
|
|
|
|
|
|
|
/* get class entry */
|
|
|
|
GET_CLASS(ce);
|
|
|
|
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "Ol", &object, *ce, &hash_len) != SUCCESS) {
|
2002-04-22 14:25:46 +00:00
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "Os", &object, *ce, &hash, &hash_len) != SUCCESS) {
|
2002-03-19 18:46:28 +00:00
|
|
|
/* none of the two possibilities */
|
|
|
|
/* TODO: exception */
|
|
|
|
php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
strip = 2;
|
|
|
|
} else {
|
|
|
|
hash = get_active_function_name(TSRMLS_C);
|
|
|
|
hash_len = strlen(hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
GET_ARGS_EX(num_args, args, args_free, strip);
|
|
|
|
|
|
|
|
/* scope for internal data */
|
|
|
|
{
|
2002-03-19 23:28:52 +00:00
|
|
|
rpc_string hash_val, *method_hash, **method_hash_find;
|
2002-03-19 18:46:28 +00:00
|
|
|
GET_INTERNAL(intern);
|
|
|
|
|
|
|
|
method_hash = (rpc_string *) pemalloc(sizeof(rpc_string), TRUE);
|
|
|
|
method_hash->str = hash;
|
|
|
|
method_hash->len = hash_len;
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
if (intern->hash) {
|
2002-03-19 18:46:28 +00:00
|
|
|
/* cache method table lookups */
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
if (!hash && !(RPC_HT(intern)->hash_type & HASH_AS_INT)) {
|
2002-03-19 18:46:28 +00:00
|
|
|
/* TODO: exception */
|
|
|
|
} else if(hash) {
|
2002-03-19 23:28:52 +00:00
|
|
|
/* string passed */
|
|
|
|
GET_METHOD_SIGNATURE(intern, method_hash, hash_val, num_args, arg_types);
|
2002-03-19 18:46:28 +00:00
|
|
|
|
|
|
|
/* check if already hashed */
|
2002-06-09 14:51:41 +00:00
|
|
|
if (zend_ts_hash_find(&(intern->hash->methods), hash_val.str, hash_val.len + 1, (void **) &method_hash_find) != SUCCESS) {
|
|
|
|
if (RPC_HT(intern)->rpc_hash(*method_hash, method_hash, num_args, arg_types, METHOD) != SUCCESS) {
|
2002-03-19 18:46:28 +00:00
|
|
|
/* TODO: exception */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* register with non-hashed key */
|
2002-06-09 14:51:41 +00:00
|
|
|
zend_ts_hash_add(&(intern->hash->methods), hash_val.str, hash_val.len + 1, &method_hash, sizeof(rpc_string *), NULL);
|
2002-03-19 18:46:28 +00:00
|
|
|
} else {
|
|
|
|
pefree(method_hash, TRUE);
|
|
|
|
method_hash = *method_hash_find;
|
|
|
|
}
|
2002-03-19 23:28:52 +00:00
|
|
|
|
|
|
|
FREE_SIGNATURE(hash_val, arg_types);
|
2002-03-19 18:46:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* actually this should not be neccesary, but who knows :)
|
|
|
|
* considering possible thread implementations in future php versions
|
|
|
|
* and srm it is better to do concurrency checks
|
|
|
|
*/
|
2002-06-09 14:51:41 +00:00
|
|
|
tsrm_mutex_lock(intern->mx_handler);
|
|
|
|
retval = RPC_HT(intern)->rpc_call(*method_hash, &(intern->data), &return_value, num_args, args);
|
|
|
|
tsrm_mutex_unlock(intern->mx_handler);
|
2002-03-19 18:46:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
efree(args_free);
|
|
|
|
|
|
|
|
if (retval != SUCCESS) {
|
|
|
|
/* TODO: exception here */
|
|
|
|
}
|
2002-03-15 23:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FUNCTION(rpc_set)
|
|
|
|
{
|
2002-04-22 14:25:46 +00:00
|
|
|
zval *object, *value;
|
|
|
|
char *property = NULL;
|
|
|
|
int property_len;
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_internal *intern;
|
2002-04-22 14:25:46 +00:00
|
|
|
/* get class entry */
|
|
|
|
GET_CLASS(ce);
|
|
|
|
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 3 TSRMLS_CC, "Olz", &object, *ce, &property_len, &value) != SUCCESS) {
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 3 TSRMLS_CC, "Osz", &object, *ce, &property, &property_len, &value) != SUCCESS) {
|
|
|
|
/* none of the two possibilities */
|
|
|
|
/* TODO: exception */
|
|
|
|
php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GET_INTERNAL_EX(intern, object);
|
2002-06-09 14:51:41 +00:00
|
|
|
if (!property && !intern->hash) {
|
2002-04-22 14:25:46 +00:00
|
|
|
/* TODO: exception here */
|
|
|
|
} else {
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_internal_set(intern, property, property_len, value);
|
2002-04-22 14:25:46 +00:00
|
|
|
}
|
2002-03-15 23:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FUNCTION(rpc_get)
|
|
|
|
{
|
2002-04-22 14:25:46 +00:00
|
|
|
zval *object;
|
|
|
|
char *property = NULL;
|
|
|
|
int property_len;
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_internal *intern;
|
2002-04-22 14:25:46 +00:00
|
|
|
/* get class entry */
|
|
|
|
GET_CLASS(ce);
|
|
|
|
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "Ol", &object, *ce, &property_len) != SUCCESS) {
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "Os", &object, *ce, &property, &property_len) != SUCCESS) {
|
|
|
|
/* none of the two possibilities */
|
|
|
|
/* TODO: exception */
|
|
|
|
php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GET_INTERNAL_EX(intern, object);
|
2002-06-09 14:51:41 +00:00
|
|
|
if (!property && !intern->hash) {
|
2002-04-22 14:25:46 +00:00
|
|
|
/* TODO: exception here */
|
|
|
|
} else {
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_internal_get(intern, property, property_len, return_value);
|
2002-04-22 14:25:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
ZEND_FUNCTION(rpc_singleton)
|
|
|
|
{
|
|
|
|
zval *object;
|
|
|
|
rpc_internal *intern;
|
|
|
|
/* get class entry */
|
|
|
|
GET_CLASS(ce);
|
|
|
|
|
|
|
|
zend_parse_parameters(1 TSRMLS_CC, "O", &object, *ce);
|
|
|
|
|
|
|
|
GET_INTERNAL_EX(intern, object);
|
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
if (!RPC_CLASS(intern)) {
|
|
|
|
/* TODO: exception here, no hashing */
|
|
|
|
} else if (!RPC_CLASS(intern)->singleton) {
|
|
|
|
RPC_CLASS(intern)->singleton = TRUE;
|
|
|
|
RPC_CLASS(intern)->data = intern->data;
|
2002-06-09 14:51:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FUNCTION(rpc_poolable)
|
|
|
|
{
|
|
|
|
zval *object;
|
|
|
|
rpc_internal *intern;
|
|
|
|
/* get class entry */
|
|
|
|
GET_CLASS(ce);
|
|
|
|
|
|
|
|
zend_parse_parameters(1 TSRMLS_CC, "O", &object, *ce);
|
|
|
|
|
|
|
|
GET_INTERNAL_EX(intern, object);
|
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
if (RPC_HT(intern)->poolable && RPC_CLASS(intern) && (RPC_HT(intern)->poolable == TRUE)) {
|
|
|
|
RPC_CLASS(intern)->poolable = TRUE;
|
|
|
|
} else {
|
|
|
|
/* TODO: exception here, no hashing */
|
2002-06-09 14:51:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************/
|
|
|
|
|
2002-04-22 14:25:46 +00:00
|
|
|
static void rpc_internal_get(rpc_internal *intern, char *property, zend_uint property_len, zval *return_value)
|
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
rpc_string *property_hash, **property_hash_find;
|
|
|
|
|
|
|
|
Z_TYPE_P(return_value) = IS_NULL;
|
|
|
|
|
|
|
|
property_hash = (rpc_string *) pemalloc(sizeof(rpc_string), TRUE);
|
|
|
|
property_hash->str = property;
|
|
|
|
property_hash->len = property_len;
|
|
|
|
|
|
|
|
if (intern->hash) {
|
|
|
|
/* cache method table lookups */
|
|
|
|
|
2002-06-09 14:51:41 +00:00
|
|
|
if (!property && !(RPC_HT(intern)->hash_type & HASH_AS_INT)) {
|
2002-04-22 14:25:46 +00:00
|
|
|
/* TODO: exception */
|
|
|
|
} else if(property) {
|
|
|
|
/* check if already hashed */
|
|
|
|
if (zend_ts_hash_find(&(intern->hash->properties), property, property_len + 1, (void **) &property_hash_find) != SUCCESS) {
|
2002-06-09 14:51:41 +00:00
|
|
|
if (RPC_HT(intern)->rpc_hash(*property_hash, property_hash, 0, NULL, PROPERTY) != SUCCESS) {
|
2002-04-22 14:25:46 +00:00
|
|
|
/* TODO: exception */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* register with non-hashed key */
|
|
|
|
zend_ts_hash_add(&(intern->hash->properties), property, property_len + 1, &property_hash, sizeof(rpc_string *), NULL);
|
|
|
|
} else {
|
|
|
|
pefree(property_hash, TRUE);
|
|
|
|
property_hash = *property_hash_find;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tsrm_mutex_lock(intern->mx_handler);
|
2002-06-09 14:51:41 +00:00
|
|
|
retval = RPC_HT(intern)->rpc_get(*property_hash, return_value, intern->data);
|
2002-04-22 14:25:46 +00:00
|
|
|
tsrm_mutex_unlock(intern->mx_handler);
|
|
|
|
|
|
|
|
if (retval != SUCCESS) {
|
|
|
|
/* TODO: exception here */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void rpc_internal_set(rpc_internal *intern, char *property, zend_uint property_len, zval *value)
|
|
|
|
{
|
|
|
|
int retval;
|
2002-06-09 14:51:41 +00:00
|
|
|
rpc_string property_name;
|
|
|
|
|
|
|
|
property_name.str = property;
|
|
|
|
property_name.len = property_len;
|
2002-04-22 14:25:46 +00:00
|
|
|
|
|
|
|
tsrm_mutex_lock(intern->mx_handler);
|
2002-06-09 14:51:41 +00:00
|
|
|
retval = RPC_HT(intern)->rpc_set(property_name, value, intern->data);
|
2002-04-22 14:25:46 +00:00
|
|
|
tsrm_mutex_unlock(intern->mx_handler);
|
|
|
|
|
|
|
|
if (retval != SUCCESS) {
|
|
|
|
/* TODO: exception here */
|
|
|
|
}
|
2002-03-15 00:00:34 +00:00
|
|
|
}
|
|
|
|
|
2002-06-10 21:16:25 +00:00
|
|
|
/***********************************/
|
|
|
|
|
|
|
|
static int zend_ts_hash_remove_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData)
|
|
|
|
{
|
|
|
|
uint nIndex;
|
|
|
|
uint h = nKeyLength;
|
|
|
|
uint result;
|
|
|
|
void **ppData;
|
|
|
|
Bucket *p;
|
|
|
|
|
|
|
|
tsrm_mutex_lock(ht->mx_writer);
|
|
|
|
|
|
|
|
if (arKey) {
|
|
|
|
result = zend_hash_find(TS_HASH(ht), arKey, nKeyLength, (void **) &ppData);
|
|
|
|
} else {
|
|
|
|
result = zend_hash_index_find(TS_HASH(ht), h, (void **) &ppData);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == SUCCESS) {
|
|
|
|
*pData = *ppData;
|
|
|
|
|
|
|
|
if (arKey) {
|
|
|
|
h = zend_inline_hash_func(arKey, nKeyLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
nIndex = h & TS_HASH(ht)->nTableMask;
|
|
|
|
|
|
|
|
p = TS_HASH(ht)->arBuckets[nIndex];
|
|
|
|
while (p != NULL) {
|
|
|
|
if ((p->h == h) && ((p->nKeyLength == 0) || /* Numeric index */
|
|
|
|
((p->nKeyLength == nKeyLength) && (!memcmp(p->arKey, arKey, nKeyLength))))) {
|
|
|
|
HANDLE_BLOCK_INTERRUPTIONS();
|
|
|
|
if (p == TS_HASH(ht)->arBuckets[nIndex]) {
|
|
|
|
TS_HASH(ht)->arBuckets[nIndex] = p->pNext;
|
|
|
|
} else {
|
|
|
|
p->pLast->pNext = p->pNext;
|
|
|
|
}
|
|
|
|
if (p->pNext) {
|
|
|
|
p->pNext->pLast = p->pLast;
|
|
|
|
}
|
|
|
|
if (p->pListLast != NULL) {
|
|
|
|
p->pListLast->pListNext = p->pListNext;
|
|
|
|
} else {
|
|
|
|
/* Deleting the head of the list */
|
|
|
|
TS_HASH(ht)->pListHead = p->pListNext;
|
|
|
|
}
|
|
|
|
if (p->pListNext != NULL) {
|
|
|
|
p->pListNext->pListLast = p->pListLast;
|
|
|
|
} else {
|
|
|
|
TS_HASH(ht)->pListTail = p->pListLast;
|
|
|
|
}
|
|
|
|
if (TS_HASH(ht)->pInternalPointer == p) {
|
|
|
|
TS_HASH(ht)->pInternalPointer = p->pListNext;
|
|
|
|
}
|
|
|
|
if (!p->pDataPtr) {
|
|
|
|
pefree(p->pData, TS_HASH(ht)->persistent);
|
|
|
|
}
|
|
|
|
pefree(p, TS_HASH(ht)->persistent);
|
|
|
|
HANDLE_UNBLOCK_INTERRUPTIONS();
|
|
|
|
TS_HASH(ht)->nNumOfElements--;
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
p = p->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tsrm_mutex_unlock(ht->mx_writer);
|
|
|
|
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-03-15 00:00:34 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|