14a49301eSmrg/* 24a49301eSmrg * Copyright 2009 VMware, Inc. 34a49301eSmrg * All Rights Reserved. 44a49301eSmrg * 54a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 64a49301eSmrg * copy of this software and associated documentation files (the "Software"), 74a49301eSmrg * to deal in the Software without restriction, including without limitation 84a49301eSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub 94a49301eSmrg * license, and/or sell copies of the Software, and to permit persons to whom 104a49301eSmrg * the Software is furnished to do so, subject to the following conditions: 114a49301eSmrg * 124a49301eSmrg * The above copyright notice and this permission notice (including the next 134a49301eSmrg * paragraph) shall be included in all copies or substantial portions of the 144a49301eSmrg * Software. 154a49301eSmrg * 164a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 174a49301eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 194a49301eSmrg * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 204a49301eSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 214a49301eSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 224a49301eSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 234a49301eSmrg */ 244a49301eSmrg 25af69d88dSmrg#include "rbug.h" 26af69d88dSmrg#include "rbug_internal.h" 274a49301eSmrg 284a49301eSmrg#include "util/u_network.h" 294a49301eSmrg 304a49301eSmrgstruct rbug_connection 314a49301eSmrg{ 324a49301eSmrg int socket; 334a49301eSmrg uint32_t send_serial; 344a49301eSmrg uint32_t recv_serial; 354a49301eSmrg enum rbug_opcode opcode; 364a49301eSmrg}; 374a49301eSmrg 384a49301eSmrg/** 394a49301eSmrg * Create a rbug connection from a socket created with u_socket. 404a49301eSmrg * 414a49301eSmrg * Result: 424a49301eSmrg * A new allocated connection using socket as communication path 434a49301eSmrg */ 444a49301eSmrgstruct rbug_connection * 454a49301eSmrgrbug_from_socket(int socket) 464a49301eSmrg{ 474a49301eSmrg struct rbug_connection *c = CALLOC_STRUCT(rbug_connection); 484a49301eSmrg c->socket = socket; 494a49301eSmrg return c; 504a49301eSmrg} 514a49301eSmrg 524a49301eSmrg/** 534a49301eSmrg * Free a connection, also closes socket. 544a49301eSmrg */ 554a49301eSmrgvoid 564a49301eSmrgrbug_disconnect(struct rbug_connection *c) 574a49301eSmrg{ 584a49301eSmrg u_socket_close(c->socket); 594a49301eSmrg FREE(c); 604a49301eSmrg} 614a49301eSmrg 624a49301eSmrg/** 634a49301eSmrg * Waits for a message to be fully received. 644a49301eSmrg * Also returns the serial for the message, serial is not touched for replys. 654a49301eSmrg * 664a49301eSmrg * Result: 674a49301eSmrg * demarshaled message on success, NULL on connection error 684a49301eSmrg */ 694a49301eSmrgstruct rbug_header * 704a49301eSmrgrbug_get_message(struct rbug_connection *c, uint32_t *serial) 714a49301eSmrg{ 724a49301eSmrg struct rbug_proto_header header; 734a49301eSmrg struct rbug_header *out; 744a49301eSmrg struct rbug_proto_header *data; 754a49301eSmrg size_t length = 0; 764a49301eSmrg size_t read = 0; 774a49301eSmrg int ret; 784a49301eSmrg 794a49301eSmrg 804a49301eSmrg ret = u_socket_peek(c->socket, &header, sizeof(header)); 814a49301eSmrg if (ret <= 0) { 824a49301eSmrg return NULL; 834a49301eSmrg } 844a49301eSmrg 854a49301eSmrg length = (size_t)header.length * 4; 864a49301eSmrg data = MALLOC(length); 874a49301eSmrg if (!data) { 884a49301eSmrg return NULL; 894a49301eSmrg } 904a49301eSmrg data->opcode = 0; 914a49301eSmrg 924a49301eSmrg do { 934a49301eSmrg uint8_t *ptr = ((uint8_t*)data) + read; 944a49301eSmrg ret = u_socket_recv(c->socket, ptr, length - read); 954a49301eSmrg 964a49301eSmrg if (ret <= 0) { 974a49301eSmrg FREE(data); 984a49301eSmrg return NULL; 994a49301eSmrg } 1004a49301eSmrg 1014a49301eSmrg read += ret; 1024a49301eSmrg } while(read < length); 1034a49301eSmrg 1044a49301eSmrg out = rbug_demarshal(data); 1054a49301eSmrg if (!out) 1064a49301eSmrg FREE(data); 1074a49301eSmrg else if (serial) 1084a49301eSmrg *serial = c->recv_serial++; 1094a49301eSmrg else 1104a49301eSmrg c->recv_serial++; 1114a49301eSmrg 1124a49301eSmrg return out; 1134a49301eSmrg} 1144a49301eSmrg 1154a49301eSmrg/** 1164a49301eSmrg * Frees a message and associated data. 1174a49301eSmrg */ 1184a49301eSmrgvoid 1194a49301eSmrgrbug_free_header(struct rbug_header *header) 1204a49301eSmrg{ 1214a49301eSmrg if (!header) 1224a49301eSmrg return; 1234a49301eSmrg 1244a49301eSmrg FREE(header->__message); 1254a49301eSmrg FREE(header); 1264a49301eSmrg} 1274a49301eSmrg 1284a49301eSmrg/** 1294a49301eSmrg * Internal function used by rbug_send_* functions. 1304a49301eSmrg * 1314a49301eSmrg * Start sending a message. 1324a49301eSmrg */ 1334a49301eSmrgint 1344a49301eSmrgrbug_connection_send_start(struct rbug_connection *c, enum rbug_opcode opcode, uint32_t length) 1354a49301eSmrg{ 1364a49301eSmrg c->opcode = opcode; 1374a49301eSmrg return 0; 1384a49301eSmrg} 1394a49301eSmrg 1404a49301eSmrg/** 1414a49301eSmrg * Internal function used by rbug_send_* functions. 1424a49301eSmrg * 1434a49301eSmrg * Write data to the socket. 1444a49301eSmrg */ 1454a49301eSmrgint 1464a49301eSmrgrbug_connection_write(struct rbug_connection *c, void *to, uint32_t size) 1474a49301eSmrg{ 1484a49301eSmrg int ret = u_socket_send(c->socket, to, size); 1494a49301eSmrg return ret; 1504a49301eSmrg} 1514a49301eSmrg 1524a49301eSmrg/** 1534a49301eSmrg * Internal function used by rbug_send_* functions. 1544a49301eSmrg * 15501e04c3fSmrg * Finish writing data to the socket. 1564a49301eSmrg * Ups the send_serial and sets the serial argument if supplied. 1574a49301eSmrg */ 1584a49301eSmrgint rbug_connection_send_finish(struct rbug_connection *c, uint32_t *serial) 1594a49301eSmrg{ 1604a49301eSmrg if (c->opcode < 0) 1614a49301eSmrg return 0; 1624a49301eSmrg else if (serial) 1634a49301eSmrg *serial = c->send_serial++; 1644a49301eSmrg else 1654a49301eSmrg c->send_serial++; 1664a49301eSmrg 1674a49301eSmrg return 0; 1684a49301eSmrg} 169