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