1#include "betalk.h"
2#include "sysdepdefs.h"
3#include "rpc.h"
4
5#include "signal.h"
6
7
8int btRPCConnect(unsigned int serverIP, int port)
9{
10	struct sockaddr_in serverAddr;
11	int session;
12
13	// Initialize the server address structure.
14	memset(&serverAddr, 0, sizeof(serverAddr));
15	serverAddr.sin_port = htons(port);
16	serverAddr.sin_family = AF_INET;
17	serverAddr.sin_addr.s_addr = htonl(serverIP);
18
19	// Create a new socket to receive incoming requests.
20	session = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
21	if (session == INVALID_SOCKET)
22		return INVALID_SOCKET;
23
24	// Bind that socket to the address constructed above.
25	if (connect(session, (struct sockaddr *) &serverAddr, sizeof(serverAddr)))
26		return INVALID_SOCKET;
27
28	return session;
29}
30
31bool btRPCSend(int session, bt_outPacket *outPacket)
32{
33	// The XID will be 0.
34	btRPCPutInt32(outPacket, 0);
35	btRPCPutChar(outPacket, BT_CMD_TERMINATOR);
36
37	if (btSendMsg(session, outPacket->buffer, outPacket->length, 0) == -1)
38		return false;
39
40	return true;
41}
42
43bool btRPCCheckSignature(int session)
44{
45	char signature[20];
46	unsigned int sigLen;
47
48	sigLen = strlen(BT_RPC_SIGNATURE);
49	memset(signature, 0, sigLen);
50	if (btRecvMsg(session, signature, sigLen, 0) == -1)
51		return false;
52
53	// Check the signature's validity.
54	signature[sigLen] = 0;
55	return (strcmp(signature, BT_RPC_SIGNATURE) == 0);
56}
57
58// btRPCSimpleCall()
59//
60bt_inPacket *btRPCSimpleCall(unsigned int serverIP, int port, bt_outPacket *outPacket)
61{
62	struct timeval timeout;
63	bt_inPacket *inPacket;
64	fd_set sockSet;
65	char *buffer;
66	int session;
67	int32 xid, length;
68
69	// Establish a connection with the requested server, on the requested port.
70	// If we can't connect, abort and return a NULL packet.
71	inPacket = NULL;
72	session = btRPCConnect(serverIP, port);
73	if (session == INVALID_SOCKET)
74		return NULL;
75
76	// If we connected, send the requested RPC packet.  If the packet cannot be
77	// sent, the connection has dropped and we'll abort the call.
78	if (!btRPCSend(session, outPacket))
79	{
80		closesocket(session);
81		return NULL;
82	}
83
84	// Set a reasonable timeout period.  Select() is used in leiu of alarm() because
85	// select() also aborts on error, alarm() effects all threads in a process.
86	FD_ZERO(&sockSet);
87	timeout.tv_sec = 8;
88	timeout.tv_usec = 0;
89
90	// Block in select() waiting for activity.  This will block until data is available
91	// or until a socket error is pending.
92	FD_SET(session, &sockSet);
93	select(session + 1, &sockSet, NULL, NULL, &timeout);
94
95	// If our socket has data pending, then read the incoming RPC response packet.
96	// This should consist of a valid RPC signature, a tranaction ID (xid), the length
97	// of the variable data, and the data itself.
98	if (FD_ISSET(session, &sockSet))
99		if (btRPCCheckSignature(session))
100		{
101			if (btRecvMsg(session, &xid, sizeof(int32), 0) == -1 ||
102				btRecvMsg(session, &length, sizeof(int32), 0) == -1)
103				goto abortCall;
104
105			xid = B_LENDIAN_TO_HOST_INT32(xid);
106			length = B_LENDIAN_TO_HOST_INT32(length);
107
108			// Now allocate a buffer of the appropriate length.  If one cannot be
109			// allocated, we won't be able to store incoming information and the call
110			// must be aborted.
111			if (length > 0 && length < BT_RPC_MAX_PACKET_SIZE)
112			{
113				buffer = (char *) malloc(length + 1);
114				if (buffer)
115				{
116					// Read the remaining packet contents.  The btRecv() function takes
117					// care of restarting the recv() when signal interrupts occur.  It
118					// will always return -1 on error, even upon orderly shutdown of the peer.
119					if (btRecvMsg(session, buffer, length, 0) == -1)
120					{
121						free(buffer);
122						goto abortCall;
123					}
124
125					// Terminate the buffer.
126					buffer[length] = 0;
127
128					// Allocate a new incoming packet and set its buffer and length.
129					inPacket = (bt_inPacket *) malloc(sizeof(bt_inPacket));
130					if (inPacket)
131					{
132						inPacket->buffer = buffer;
133						inPacket->length = length;
134						inPacket->offset = 0;
135					}
136					else
137						free(buffer);
138				}
139			}
140		}
141
142	// Execution can naturally lead here or we can jump here from a failed attempt to
143	// send or receive an RPC packet.  The socket is closed and the current incoming
144	// packet returned, which will be NULL upon failure.
145abortCall:
146	shutdown(session, 2);
147	close(session);
148	return inPacket;
149}
150
151int btRecvMsg(int sock, void *data, int dataLen, int flags)
152{
153	int bytesRead = 0;
154	do
155	{
156		int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags);
157		if (bytes == -1)
158			return -1;
159
160		bytesRead += bytes;
161	} while (bytesRead < dataLen);
162
163	return bytesRead;
164}
165
166// btRecv()
167//
168int btRecv(int sock, void *data, int dataLen, int flags)
169{
170	int bytes;
171
172	for (;;)
173	{
174		bytes = recv(sock, data, dataLen, flags);
175		if (bytes == 0)
176			return -1;
177		else if (bytes == -1)
178			if (errno == EINTR)
179				continue;
180			else
181				return -1;
182		else
183			break;
184	}
185
186	return bytes;
187}
188
189int btSendMsg(int sock, void *data, int dataLen, int flags)
190{
191	int bytesSent = 0;
192	do
193	{
194		int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags);
195		if (bytes == -1)
196			return -1;
197
198		bytesSent += bytes;
199	} while (bytesSent < dataLen);
200
201	return bytesSent;
202}
203
204// btSend()
205//
206int btSend(int sock, void *data, int dataLen, int flags)
207{
208	int bytes;
209
210	for (;;)
211	{
212		bytes = send(sock, data, dataLen, flags);
213		if (bytes == -1)
214			if (errno == EINTR)
215				continue;
216			else
217				return -1;
218		else
219			break;
220	}
221
222	return bytes;
223}
224
225void btDestroyInPacket(bt_inPacket *packet)
226{
227	if (packet)
228	{
229		if (packet->buffer)
230			free(packet->buffer);
231
232		free(packet);
233	}
234}
235
236bt_outPacket *btRPCPutHeader(unsigned char command, unsigned char argc, int32 length)
237{
238	bt_outPacket *packet;
239
240	packet = (bt_outPacket *) malloc(sizeof(bt_outPacket));
241	if (!packet)
242		return NULL;
243
244	packet->size = BT_RPC_MIN_PACKET_SIZE;
245	packet->buffer = (char *) malloc(packet->size);
246	packet->length = 0;
247
248	if (!packet->buffer)
249	{
250		free(packet);
251		return NULL;
252	}
253
254	strcpy(packet->buffer, BT_RPC_SIGNATURE);
255	packet->length += strlen(BT_RPC_SIGNATURE);
256
257//	btRPCPutChar(packet, BT_RPC_VERSION_HI);
258//	btRPCPutChar(packet, BT_RPC_VERSION_LO);
259	btRPCPutInt32(packet, 7 + (8 * argc) + length);
260	btRPCPutChar(packet, command);
261	btRPCPutChar(packet, argc);
262
263	return packet;
264}
265
266void btRPCPutArg(bt_outPacket *packet, unsigned int type, void *data, int length)
267{
268	btRPCPutInt32(packet, type);
269	btRPCPutInt32(packet, length);
270	btRPCPutBinary(packet, data, length);
271}
272
273void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error, int length)
274{
275	packet->size = BT_RPC_MIN_PACKET_SIZE;
276	packet->buffer = (char *) malloc(packet->size);
277	packet->length = 0;
278
279	if (!packet->buffer)
280		return;
281
282	strcpy(packet->buffer, BT_RPC_SIGNATURE);
283	packet->length += strlen(BT_RPC_SIGNATURE);
284	btRPCPutInt32(packet, xid);
285	btRPCPutInt32(packet, 0);
286	btRPCPutInt32(packet, error);
287}
288
289void btRPCSendAck(int client, bt_outPacket *packet)
290{
291	if (packet)
292		if (packet->buffer)
293		{
294			*(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13);
295			btSendMsg(client, packet->buffer, packet->length, 0);
296			free(packet->buffer);
297		}
298}
299
300unsigned char btRPCGetChar(bt_inPacket *packet)
301{
302	unsigned char value;
303
304	if (packet->offset < packet->length)
305		value = (unsigned char) packet->buffer[packet->offset];
306	else
307		value = 0;
308
309	packet->offset += sizeof(value);
310	return value;
311}
312
313unsigned int btRPCGetInt32(bt_inPacket *packet)
314{
315	int32 value;
316
317	if (packet->offset < packet->length)
318		value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset]));
319	else
320		value = 0;
321
322	packet->offset += sizeof(value);
323	return value;
324}
325
326int64 btRPCGetInt64(bt_inPacket *packet)
327{
328	int64 value;
329
330	if (packet->offset < packet->length)
331		value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset]));
332	else
333		value = 0;
334
335	packet->offset += sizeof(value);
336	return value;
337}
338
339char *btRPCGetNewString(bt_inPacket *packet)
340{
341	char *str;
342	unsigned int bytes;
343
344	if (packet->offset >= packet->length)
345		return NULL;
346
347	bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset]));
348	packet->offset += sizeof(bytes);
349	if (bytes < 0 || bytes > BT_MAX_IO_BUFFER)
350		return NULL;
351
352	str = (char *) malloc(bytes + 1);
353	if (!str)
354		return NULL;
355
356	if (bytes > 0)
357		memcpy(str, &packet->buffer[packet->offset], bytes);
358
359	str[bytes] = 0;
360	packet->offset += bytes;
361
362	return str;
363}
364
365int btRPCGetString(bt_inPacket *packet, char *buffer, int length)
366{
367	unsigned int bytes;
368
369	if (packet->offset >= packet->length)
370		return ERANGE;
371
372	bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset]));
373	packet->offset += sizeof(bytes);
374	if (bytes < 0 || bytes > BT_MAX_IO_BUFFER)
375		return ERANGE;
376
377	if (length < bytes)
378		return ERANGE;
379
380	if (bytes > 0)
381		memcpy(buffer, &packet->buffer[packet->offset], bytes);
382
383	packet->offset += bytes;
384	return bytes;
385}
386
387void btRPCGrowPacket(bt_outPacket *packet, int bytes)
388{
389	if (packet->length + bytes > packet->size)
390	{
391		int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE;
392		packet->buffer = (char *) realloc(packet->buffer, packet->size + growth);
393		packet->size += growth;
394	}
395}
396
397void btRPCPutChar(bt_outPacket *packet, char value)
398{
399	btRPCGrowPacket(packet, sizeof(value));
400	packet->buffer[packet->length] = value;
401	packet->length += sizeof(value);
402}
403
404void btRPCPutInt32(bt_outPacket *packet, int32 value)
405{
406	btRPCGrowPacket(packet, sizeof(value));
407	*(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value);
408	packet->length += sizeof(value);
409}
410
411void btRPCPutInt64(bt_outPacket *packet, int64 value)
412{
413	btRPCGrowPacket(packet, sizeof(value));
414	*(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value);
415	packet->length += sizeof(value);
416}
417
418void btRPCPutString(bt_outPacket *packet, char *buffer, int length)
419{
420	if (packet && buffer)
421	{
422		btRPCGrowPacket(packet, sizeof(length) + length);
423		btRPCPutInt32(packet, length);
424		memcpy(&packet->buffer[packet->length], buffer, length);
425		packet->length += length;
426	}
427}
428
429void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length)
430{
431	if (packet && buffer)
432	{
433		btRPCGrowPacket(packet, length);
434		memcpy(&packet->buffer[packet->length], buffer, length);
435		packet->length += length;
436	}
437}
438
439int btRPCGetStat(bt_inPacket *packet, struct stat *st)
440{
441	st->st_dev = 0;
442	st->st_nlink = btRPCGetInt32(packet);
443	st->st_uid = btRPCGetInt32(packet);
444	st->st_gid = btRPCGetInt32(packet);
445	st->st_size = btRPCGetInt64(packet);
446	st->st_blksize = btRPCGetInt32(packet);
447	st->st_rdev = btRPCGetInt32(packet);
448	st->st_ino = btRPCGetInt64(packet);
449	st->st_mode = btRPCGetInt32(packet);
450	st->st_atime = btRPCGetInt32(packet);
451	st->st_mtime = btRPCGetInt32(packet);
452	st->st_ctime = btRPCGetInt32(packet);
453}
454
455void btRPCPutStat(bt_outPacket *packet, struct stat *st)
456{
457	if (packet && st)
458	{
459		btRPCPutInt32(packet, (int) st->st_nlink);
460		btRPCPutInt32(packet, (int) st->st_uid);
461		btRPCPutInt32(packet, (int) st->st_gid);
462		btRPCPutInt64(packet, (int64) st->st_size);
463		btRPCPutInt32(packet, (int) st->st_blksize);
464		btRPCPutInt32(packet, (int) st->st_rdev);
465		btRPCPutInt64(packet, (int64) st->st_ino);
466		btRPCPutInt32(packet, (int) st->st_mode);
467		btRPCPutInt32(packet, (int) st->st_atime);
468		btRPCPutInt32(packet, (int) st->st_mtime);
469		btRPCPutInt32(packet, (int) st->st_ctime);
470	}
471}
472