CVS update: php31/ext/rpc
| From: | ssb | Date: | Wed, 16 Sep 1998 23:11:05 +0000 |
| Subject: | CVS update: php31/ext/rpc | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-1187@lists.php.net to get a copy of this message | ||
Date: Wednesday September 16, 1998 @ 19:11
Author: ssb
Update of /repository/php31/ext/rpc
In directory asf:/u2/tmp/cvs-serv22334
Modified Files:
php3_rpc.h rpc.c test.php3
Added Files:
.cvsignore
Log Message:
Implemented rpc_call(). Usage: rpc_call(function[, parameters...]).
Index: php31/ext/rpc/php3_rpc.h
diff -c php31/ext/rpc/php3_rpc.h:1.1 php31/ext/rpc/php3_rpc.h:1.2
*** php31/ext/rpc/php3_rpc.h:1.1 Tue Sep 15 19:37:27 1998
--- php31/ext/rpc/php3_rpc.h Wed Sep 16 19:11:03 1998
***************
*** 27,40 ****
+----------------------------------------------------------------------+
*/
! /* $Id: php3_rpc.h,v 1.1 1998/09/15 23:37:27 ssb Exp $ */
#define rpc_module_ptr &rpc_module_entry
extern php3_module_entry rpc_module_entry;
void php3_serialize(INTERNAL_FUNCTION_PARAMETERS);
void php3_unserialize(INTERNAL_FUNCTION_PARAMETERS);
/*
* Local variables:
--- 27,62 ----
+----------------------------------------------------------------------+
*/
! /* $Id: php3_rpc.h,v 1.2 1998/09/16 23:11:03 ssb Exp $ */
+ #define RPC_NOP 0
+
+ /* function calling opcodes */
+ #define RPC_FUNCTION_CALL 1
+ #define RPC_FUNCTION_NPARAMS 2
+ #define RPC_FUNCTION_PARAMETER 3
+ #define RPC_RETURN_VALUE 4
+
+ /* value passing opcodes */
+ #define RPC_TYPE_LONG 10
+ #define RPC_TYPE_STRING 11
+ #define RPC_TYPE_DOUBLE 12
+ #define RPC_TYPE_ARRAY 13
+
#define rpc_module_ptr &rpc_module_entry
extern php3_module_entry rpc_module_entry;
void php3_serialize(INTERNAL_FUNCTION_PARAMETERS);
void php3_unserialize(INTERNAL_FUNCTION_PARAMETERS);
+ void php3_rpc_call(INTERNAL_FUNCTION_PARAMETERS);
+
+ typedef struct {
+ char enabled;
+ char *host;
+ long port;
+ int socket;
+ } rpc_module;
/*
* Local variables:
Index: php31/ext/rpc/rpc.c
diff -c php31/ext/rpc/rpc.c:1.1 php31/ext/rpc/rpc.c:1.2
*** php31/ext/rpc/rpc.c:1.1 Tue Sep 15 19:37:28 1998
--- php31/ext/rpc/rpc.c Wed Sep 16 19:11:04 1998
***************
*** 27,62 ****
+----------------------------------------------------------------------+
*/
! /* $Id: rpc.c,v 1.1 1998/09/15 23:37:28 ssb Exp $ */
#include "php.h"
#include "internal_functions.h"
#include <sys/types.h>
#include <sys/socket.h>
! #include <sys/un.h>
#include <stdio.h>
#include "php3_rpc.h"
function_entry rpc_functions[] = {
{ "serialize", php3_serialize, first_arg_allow_ref },
{ "unserialize", php3_unserialize, first_arg_allow_ref },
{ NULL, NULL, NULL }
};
php3_module_entry rpc_module_entry = {
! "RPC",
! rpc_functions,
! NULL,
! NULL,
! NULL,
! NULL,
! NULL,
! STANDARD_MODULE_PROPERTIES
};
static int
rpc_connect_unix(char *path)
{
--- 27,226 ----
+----------------------------------------------------------------------+
*/
! /* $Id: rpc.c,v 1.2 1998/09/16 23:11:04 ssb Exp $ */
+ #ifdef THREAD_SAFE
+ # include "tls.h"
+ #endif
+ #define IS_EXT_MODULE
+
#include "php.h"
#include "internal_functions.h"
#include <sys/types.h>
#include <sys/socket.h>
! #ifdef HAVE_SYS_UN_H
! # include <sys/un.h>
! #endif
! #include <netinet/in.h>
#include <stdio.h>
+ #ifdef HAVE_UNISTD_H
+ # include <unistd.h>
+ #endif
#include "php3_rpc.h"
+ /* TODO:
+ *
+ * - Should drop htons() and similar functions in favor of
+ * of own data types with well-defined size in octets.
+ * The current version will not work between machines with
+ * different "unsigned short" and "unsigned long" sizes.
+ *
+ */
+
+ /* {{{ thread safety stuff */
+
+ #ifdef THREAD_SAFE
+ # define RPC_GLOBAL(a) rpc_globals->a
+ # define RPC_TLS_VARS \
+ rpc_global_struct *rpc_globals = TlsGetValue(RPCTls);
+
+ void *rpc_mutex;
+ DWORD RPCTls;
+ static int numthreads=0;
+
+ typedef struct rpc_global_struct {
+ rpc_module php3_rpc_module;
+ } rpc_global_struct;
+
+ #else /* !defined(THREAD_SAFE) */
+ # define RPC_GLOBAL(a) a
+ # define RPC_TLS_VARS
+
+ rpc_module php3_rpc_module;
+
+ #endif /* defined(THREAD_SAFE) */
+
+ /* }}} */
+ /* {{{ dynamic loading stuff */
+
+ #if COMPILE_DL
+
+ php3_module_entry *get_module() { return &rpc_module_entry; };
+
+ # if (WIN32|WINNT) && defined(THREAD_SAFE)
+
+ /* NOTE: You should have an rpc.def file where you export DllMain */
+ BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call,
+ LPVOID lpReserved)
+ {
+ switch (ul_reason_for_call) {
+ case DLL_PROCESS_ATTACH:
+ if ((RPCTls = TlsAlloc()) == 0xFFFFFFFF){
+ return 0;
+ }
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ if (!TlsFree(RPCTls)) {
+ return 0;
+ }
+ break;
+ }
+ return 1;
+ }
+
+ # endif /* thread safe on Windows */
+ #endif /* COMPILE_DL */
+
+ /* }}} */
+
+ int php3_minit_rpc(INIT_FUNC_ARGS);
+ int php3_mshutdown_rpc(void);
+ void php3_info_rpc(void);
+ #ifdef HAVE_SYS_UN_H
+ static int rpc_connect_unix(char *);
+ #endif
+ static int rpc_connect_tcp(char *, int);
+ static void rpc_msg_opcode(char **, int *, int *, unsigned short);
+ static void rpc_msg_pval(char **, int *, int *, pval *);
+ static void rpc_msg_raw(char **, int *, int *, char *, int);
+ static void rpc_msg_long(char **, int *, int *, long);
+
+
function_entry rpc_functions[] = {
{ "serialize", php3_serialize, first_arg_allow_ref },
{ "unserialize", php3_unserialize, first_arg_allow_ref },
+ { "rpc_call", php3_rpc_call, NULL },
{ NULL, NULL, NULL }
};
php3_module_entry rpc_module_entry = {
! "RPC", /* extension name */
! rpc_functions, /* extension function list */
! php3_minit_rpc, /* extension-wide startup function */
! php3_mshutdown_rpc, /* extension-wide shutdown function */
! NULL, /* per-request startup function */
! NULL, /* per-request shutdown function */
! php3_info_rpc, /* information function */
! STANDARD_MODULE_PROPERTIES
};
+ int
+ php3_minit_rpc(INIT_FUNC_ARGS)
+ {
+ RPC_TLS_VARS;
+
+ RPC_GLOBAL(php3_rpc_module).enabled = 1;
+ RPC_GLOBAL(php3_rpc_module).host = "/tmp/prc.sock";
+ RPC_GLOBAL(php3_rpc_module).port = -1;
+
+ if (RPC_GLOBAL(php3_rpc_module).enabled) {
+ int sock;
+
+ #ifdef HAVE_SYS_UN_H
+ if (RPC_GLOBAL(php3_rpc_module).port == -1) {
+ sock = rpc_connect_unix(RPC_GLOBAL(php3_rpc_module).host);
+ } else {
+ sock = rpc_connect_tcp(RPC_GLOBAL(php3_rpc_module).host,
+ RPC_GLOBAL(php3_rpc_module).port);
+ }
+ #else
+ sock = rpc_connect_tcp(RPC_GLOBAL(php3_rpc_module).host,
+ RPC_GLOBAL(php3_rpc_module).port);
+ #endif
+ if (sock != -1) {
+ RPC_GLOBAL(php3_rpc_module).socket = sock;
+ } else {
+ /* fail silently */
+ RPC_GLOBAL(php3_rpc_module).socket = -1;
+ }
+ }
+
+ return SUCCESS;
+ }
+
+
+ int
+ php3_mshutdown_rpc()
+ {
+ if (RPC_GLOBAL(php3_rpc_module).socket != -1) {
+ close(RPC_GLOBAL(php3_rpc_module).socket);
+ RPC_GLOBAL(php3_rpc_module).socket = -1;
+ }
+ return SUCCESS;
+ }
+
+
+ void php3_info_rpc()
+ {
+ if (RPC_GLOBAL(php3_rpc_module).socket == -1) {
+ PUTS("No connection");
+ } else {
+ #if HAVE_SYS_UN_H
+ if (RPC_GLOBAL(php3_rpc_module).port == -1) {
+ php3_printf("Connected to %s",
+ RPC_GLOBAL(php3_rpc_module).host);
+ } else {
+ php3_printf("Connected to %s port %d",
+ RPC_GLOBAL(php3_rpc_module).host,
+ RPC_GLOBAL(php3_rpc_module).port);
+ }
+ #else
+ php3_printf("Connected to %s port %d",
+ RPC_GLOBAL(php3_rpc_module).host,
+ RPC_GLOBAL(php3_rpc_module).port);
+ #endif
+ }
+ }
+
+
+ #ifdef HAVE_SYS_UN_H
static int
rpc_connect_unix(char *path)
{
***************
*** 68,116 ****
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
! perror("connect");
! return -1;
}
return fd;
}
! int
! php3i_serialize_string(pval *val, char **resultp, int *sizep)
{
! unsigned short type;
! unsigned long size;
! type = htons(val->type);
! size = htonl((unsigned long)val->value.str.len);
! *sizep = sizeof(type) + sizeof(size) + val->value.str.len;
! *resultp = emalloc(*sizep);
! if (*resultp == NULL) {
! return FAILURE;
}
! memcpy(*resultp, (char *)&type, sizeof(type));
! memcpy(*resultp+sizeof(type), (char *)&size, sizeof(size));
! memcpy(*resultp+sizeof(type)+sizeof(size), val->value.str.val, val->value.str.len);
! return SUCCESS;
}
int
! php3i_serialize_long(pval *val, char **resultp, int *sizep)
{
unsigned short type;
! unsigned long value;
type = htons(val->type);
! value = htonl((unsigned long)val->value.lval);
! *sizep = sizeof(type) + sizeof(value);
! *resultp = emalloc(*sizep);
! if (*resultp == NULL) {
! return FAILURE;
}
! memcpy(*resultp, (char *)&type, sizeof(type));
! memcpy(*resultp+sizeof(type), (char *)&value, sizeof(value));
! return SUCCESS;
}
--- 232,294 ----
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
! return -1;
}
return fd;
}
+ #endif
! static int
! rpc_connect_tcp(char *host, int port)
{
! struct sockaddr_in saddr;
! int fd;
! memset(&saddr, 0, sizeof(saddr));
! saddr.sin_addr.s_addr = lookup_hostname(host);
! saddr.sin_family = AF_INET;
! saddr.sin_port = htons((unsigned short)port);
! fd = socket(saddr.sin_family, SOCK_STREAM, 0);
! if (connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
! return -1;
}
! return fd;
}
int
! php3i_serialize(pval *val, char **resultp, int *sizep)
{
unsigned short type;
! unsigned long size, value;
type = htons(val->type);
! switch (val->type) {
! case IS_STRING:
! size = htonl((unsigned long)val->value.str.len);
! *sizep = sizeof(type) + sizeof(size) + val->value.str.len;
! *resultp = emalloc(*sizep);
! if (*resultp == NULL) {
! return FAILURE;
! }
! memcpy(*resultp, (char *)&type, sizeof(type));
! memcpy(*resultp+sizeof(type), (char *)&size, sizeof(size));
! memcpy(*resultp+sizeof(type)+sizeof(size), val->value.str.val,
! val->value.str.len);
! return SUCCESS;
! case IS_LONG:
! value = htonl((unsigned long)val->value.lval);
! *sizep = sizeof(type) + sizeof(value);
! *resultp = emalloc(*sizep);
! if (*resultp == NULL) {
! return FAILURE;
! }
! memcpy(*resultp, (char *)&type, sizeof(type));
! memcpy(*resultp+sizeof(type), (char *)&value, sizeof(value));
! return SUCCESS;
}
! return FAILURE; /* unknown type */
}
***************
*** 128,134 ****
pos += sizeof(ntype);
type = ntohs(ntype);
switch (type) {
! case IS_STRING: {
unsigned long nlen, len;
val->type = type;
--- 306,312 ----
pos += sizeof(ntype);
type = ntohs(ntype);
switch (type) {
! case RPC_TYPE_STRING: {
unsigned long nlen, len;
val->type = type;
***************
*** 147,153 ****
pos += len;
break;
}
! case IS_LONG: {
unsigned long nvalue, value;
val->type = type;
--- 325,331 ----
pos += len;
break;
}
! case RPC_TYPE_LONG: {
unsigned long nvalue, value;
val->type = type;
***************
*** 173,186 ****
*
* Strings:
* <type><length><data>
! * type - set to IS_STRING for strings, network byte-order short
* length - length of string (not counting terminating null), network
* byte-order long
* data - string data (without a terminating null)
*
* Longs:
* <type><value>
! * type - set to IS_LONG for integers
* value - integer value, network byte-order long
*
*/
--- 351,364 ----
*
* Strings:
* <type><length><data>
! * type - set to RPC_TYPE_STRING for strings, network byte-order short
* length - length of string (not counting terminating null), network
* byte-order long
* data - string data (without a terminating null)
*
* Longs:
* <type><value>
! * type - set to RPC_TYPE_LONG for integers
* value - integer value, network byte-order long
*
*/
***************
*** 195,214 ****
WRONG_PARAM_COUNT;
}
! switch (arg->type) {
! case IS_STRING:
! if (php3i_serialize_string(arg, &result, &size) == FAILURE) {
! RETURN_FALSE;
! }
! break;
! case IS_LONG:
! if (php3i_serialize_long(arg, &result, &size) == FAILURE) {
! RETURN_FALSE;
! }
! break;
! default:
! php3_error(E_WARNING, "unsupported data type");
! RETURN_FALSE;
}
RETVAL_STRINGL(result, size, 0);
}
--- 373,380 ----
WRONG_PARAM_COUNT;
}
! if (php3i_serialize(arg, &result, &size) == FAILURE) {
! RETURN_FALSE;
}
RETVAL_STRINGL(result, size, 0);
}
***************
*** 231,236 ****
--- 397,510 ----
if (php3i_unserialize(return_value, buffer, size) == FAILURE) {
RETURN_FALSE;
}
+ }
+
+
+ #define rpc_msg_short rpc_msg_opcode
+
+ static void
+ rpc_msg_opcode(char **buffer, /* data buffer */
+ int *pos, /* pointer to current buffer offset */
+ int *size, /* pointer to buffer size */
+ unsigned short opcode) /* opcode to append to the buffer */
+ {
+ int len = sizeof(opcode);
+ char *juks;
+
+ opcode = htons(opcode);
+ juks = (char *)&opcode;
+ rpc_msg_raw(buffer, pos, size, juks, len);
+ }
+
+
+ static void
+ rpc_msg_pval(char **buffer, /* data buffer */
+ int *pos, /* pointer to current buffer offset */
+ int *size, /* pointer to buffer size */
+ pval *val) /* pval to serialize and append */
+ {
+ int srl_size;
+ char *srl_buf;
+
+ if (php3i_serialize(val, &srl_buf, &srl_size) == FAILURE) {
+ return;
+ }
+ rpc_msg_raw(buffer, pos, size, srl_buf, srl_size);
+ efree(srl_buf);
+ }
+
+
+ static void
+ rpc_msg_long(char **buffer, /* data buffer */
+ int *pos, /* pointer to current buffer offset */
+ int *size, /* pointer to buffer size */
+ long value) /* value to append to the buffer */
+ {
+ int len = sizeof(value);
+ char *juks;
+
+ value = htonl(value);
+ juks = (char *)&value;
+ rpc_msg_raw(buffer, pos, size, juks, len);
+ }
+
+
+ static void
+ rpc_msg_raw(char **buffer, /* data buffer */
+ int *pos, /* pointer to current buffer offset */
+ int *size, /* pointer to buffer size */
+ char *data, /* data to append to the buffer */
+ int len) /* number of bytes to append */
+ {
+ if ((*pos + len) >= *size) {
+ while ((*pos + len) >= *size) {
+ *size *= 2;
+ }
+ *buffer = erealloc(*buffer, *size);
+ }
+ memcpy(&(*buffer)[*pos], data, len);
+ *pos += len;
+ }
+
+
+ /* TODO:
+ * - check for references and use placeholders for those parameters
+ */
+ void
+ php3_rpc_call(INTERNAL_FUNCTION_PARAMETERS)
+ {
+ pval **argv;
+ int argc, i, size, len, sock;
+ unsigned short opcode;
+ char *buf;
+ RPC_TLS_VARS;
+
+ argc = ARG_COUNT(ht);
+ if (argc < 1) {
+ WRONG_PARAM_COUNT;
+ }
+ argv = emalloc(argc * sizeof(pval *));
+ if (getParametersArray(ht, argc, argv) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ sock = RPC_GLOBAL(php3_rpc_module).socket;
+ if (sock == -1) {
+ php3_error(E_WARNING, "no RPC server connection");
+ RETURN_FALSE;
+ }
+ convert_to_string(argv[0]);
+ size = 50; /* size will be doubled every time the buffer is too small */
+ buf = emalloc(size);
+ len = 0;
+ rpc_msg_opcode(&buf, &len, &size, RPC_FUNCTION_CALL);
+ rpc_msg_pval(&buf, &len, &size, argv[0]);
+ rpc_msg_opcode(&buf, &len, &size, RPC_FUNCTION_NPARAMS);
+ rpc_msg_short(&buf, &len, &size, argc - 1);
+ for (i = 1; i < argc; i++) {
+ rpc_msg_opcode(&buf, &len, &size, RPC_FUNCTION_PARAMETER);
+ rpc_msg_pval(&buf, &len, &size, argv[i]);
+ }
+ write(sock, buf, len);
}
/*
Index: php31/ext/rpc/test.php3
diff -c php31/ext/rpc/test.php3:1.1 php31/ext/rpc/test.php3:1.2
*** php31/ext/rpc/test.php3:1.1 Tue Sep 15 19:37:28 1998
--- php31/ext/rpc/test.php3 Wed Sep 16 19:11:04 1998
***************
*** 11,14 ****
--- 11,16 ----
printf("serialized: `%s' (%s)\n", rawurlencode($ser), gettype($ser));
printf("unserialized: `%s' (%s)\n", $uns, gettype($uns));
+ rpc_call("testFunc", 2, 3, "bing");
+
?>
--
PHP Development Mailing List http://www.php.net/
To unsubscribe send an empty message to php-dev-unsubscribe@lists.php.net
For help: php-dev-help@lists.php.net