File: rpc.c

package info (click to toggle)
php3 3%3A3.0.18-0potato1.1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 17,736 kB
  • ctags: 11,198
  • sloc: ansic: 108,120; sh: 2,512; php: 2,024; yacc: 1,887; makefile: 1,038; perl: 537; pascal: 238; awk: 90; cpp: 28; sql: 11
file content (289 lines) | stat: -rw-r--r-- 8,064 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/*
   +----------------------------------------------------------------------+
   | PHP HTML Embedded Scripting Language Version 3.0                     |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997,1998 PHP Development Team (See Credits file)      |
   +----------------------------------------------------------------------+
   | This program is free software; you can redistribute it and/or modify |
   | it under the terms of one of the following licenses:                 |
   |                                                                      |
   |  A) the GNU General Public License as published by the Free Software |
   |     Foundation; either version 2 of the License, or (at your option) |
   |     any later version.                                               |
   |                                                                      |
   |  B) the PHP License as published by the PHP Development Team and     |
   |     included in the distribution in the file: LICENSE                |
   |                                                                      |
   | This program is distributed in the hope that it will be useful,      |
   | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
   | GNU General Public License for more details.                         |
   |                                                                      |
   | You should have received a copy of both licenses referred to here.   |
   | If you did not, or have any questions about PHP licensing, please    |
   | contact core@php.net.                                                |
   +----------------------------------------------------------------------+
   | Authors: Stig Sther Bakken <ssb@fast.no>                            |
   +----------------------------------------------------------------------+
 */

/* $Id: rpc.c,v 1.3 1999/12/26 18:44:48 rasmus Exp $ */
#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"
#include "rpc_protocol.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.
 *
 */

#define RPC_GLOBAL(a) a
#define RPC_TLS_VARS

rpc_module php3_rpc_module;

/* {{{ dynamic loading stuff */

#if COMPILE_DL

php3_module_entry *get_module() { return &rpc_module_entry; };

#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);


function_entry rpc_functions[] = {
	{ "rpc_call",     php3_rpc_call,    NULL },
	{ NULL,           NULL,             NULL }
};

php3_module_entry rpc_module_entry = {
    "PHP 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).host = "localhost";
	RPC_GLOBAL(php3_rpc_module).port = 1200; /* -1 means unix domain socket */

	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)
{
	struct sockaddr_un saddr;
	int fd;

	saddr.sun_family = AF_UNIX;
	strncpy(saddr.sun_path, path, sizeof(saddr.sun_path));
	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;
}


/* 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, readlen, writelen, pos;
	char *buf, readbuf[1024]; /* XXX FIXME hardcoded limit! */
	rpc_opcode_t opcode;
	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_put_opcode(&buf, &len, &size, RPC_FUNCTION_CALL);
	rpc_put_pval(&buf, &len, &size, argv[0]);
	rpc_put_opcode(&buf, &len, &size, RPC_FUNCTION_NPARAMS);
	rpc_put_short(&buf, &len, &size, argc - 1);
	for (i = 1; i < argc; i++) {
		rpc_put_opcode(&buf, &len, &size, RPC_FUNCTION_PARAMETER);
		rpc_put_pval(&buf, &len, &size, argv[i]);
	}
	writelen = write(sock, buf, len);
	if (writelen != len) {
		php3_error(E_WARNING, "XXX FIXME have to make a write loop");
		RETURN_FALSE;
	}
	/* XXX FIXME not efficient use of read() here */
	readlen = read(sock, (char *)&opcode, sizeof(opcode));
	if (readlen != sizeof(opcode)) {
		php3_error(E_WARNING, "malformed RPC response");
		RETURN_FALSE;
	}
	php3_printf("opcode=%d\n", opcode);
	switch (opcode) {
		case RPC_RETURN_VALUE: {
			pval *val;

			val = rpc_get_pval(readbuf, &pos, readlen);
			if (val == NULL) {
				RETVAL_FALSE;
			} else {
				memcpy(return_value, val, sizeof(pval));
			}
			break;
		}
		case RPC_ERROR: {
			rpc_error_t error;

			error = rpc_get_opcode(readbuf, &pos, readlen);
			php3_error(E_WARNING, "RPC error %d", error);
			RETVAL_FALSE;
			break;
		}
		default: {
			php3_error(E_WARNING, "malformed RPC response");
			RETVAL_FALSE;
			break;
		}
	}
}

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 */