1848b8605Smrg/* 2848b8605Smrg * Copyright 2009 VMware, Inc. 3848b8605Smrg * All Rights Reserved. 4848b8605Smrg * 5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6848b8605Smrg * copy of this software and associated documentation files (the "Software"), 7848b8605Smrg * to deal in the Software without restriction, including without limitation 8848b8605Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 9848b8605Smrg * license, and/or sell copies of the Software, and to permit persons to whom 10848b8605Smrg * the Software is furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice and this permission notice (including the next 13848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 14848b8605Smrg * Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20848b8605Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21848b8605Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22848b8605Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg#include "rbug.h" 26848b8605Smrg#include "rbug_internal.h" 27848b8605Smrg 28848b8605Smrg#include "util/u_network.h" 29848b8605Smrg 30848b8605Smrgstruct rbug_connection 31848b8605Smrg{ 32848b8605Smrg int socket; 33848b8605Smrg uint32_t send_serial; 34848b8605Smrg uint32_t recv_serial; 35848b8605Smrg enum rbug_opcode opcode; 36848b8605Smrg}; 37848b8605Smrg 38848b8605Smrg/** 39848b8605Smrg * Create a rbug connection from a socket created with u_socket. 40848b8605Smrg * 41848b8605Smrg * Result: 42848b8605Smrg * A new allocated connection using socket as communication path 43848b8605Smrg */ 44848b8605Smrgstruct rbug_connection * 45848b8605Smrgrbug_from_socket(int socket) 46848b8605Smrg{ 47848b8605Smrg struct rbug_connection *c = CALLOC_STRUCT(rbug_connection); 48848b8605Smrg c->socket = socket; 49848b8605Smrg return c; 50848b8605Smrg} 51848b8605Smrg 52848b8605Smrg/** 53848b8605Smrg * Free a connection, also closes socket. 54848b8605Smrg */ 55848b8605Smrgvoid 56848b8605Smrgrbug_disconnect(struct rbug_connection *c) 57848b8605Smrg{ 58848b8605Smrg u_socket_close(c->socket); 59848b8605Smrg FREE(c); 60848b8605Smrg} 61848b8605Smrg 62848b8605Smrg/** 63848b8605Smrg * Waits for a message to be fully received. 64848b8605Smrg * Also returns the serial for the message, serial is not touched for replys. 65848b8605Smrg * 66848b8605Smrg * Result: 67848b8605Smrg * demarshaled message on success, NULL on connection error 68848b8605Smrg */ 69848b8605Smrgstruct rbug_header * 70848b8605Smrgrbug_get_message(struct rbug_connection *c, uint32_t *serial) 71848b8605Smrg{ 72848b8605Smrg struct rbug_proto_header header; 73848b8605Smrg struct rbug_header *out; 74848b8605Smrg struct rbug_proto_header *data; 75848b8605Smrg size_t length = 0; 76848b8605Smrg size_t read = 0; 77848b8605Smrg int ret; 78848b8605Smrg 79848b8605Smrg 80848b8605Smrg ret = u_socket_peek(c->socket, &header, sizeof(header)); 81848b8605Smrg if (ret <= 0) { 82848b8605Smrg return NULL; 83848b8605Smrg } 84848b8605Smrg 85848b8605Smrg length = (size_t)header.length * 4; 86848b8605Smrg data = MALLOC(length); 87848b8605Smrg if (!data) { 88848b8605Smrg return NULL; 89848b8605Smrg } 90848b8605Smrg data->opcode = 0; 91848b8605Smrg 92848b8605Smrg do { 93848b8605Smrg uint8_t *ptr = ((uint8_t*)data) + read; 94848b8605Smrg ret = u_socket_recv(c->socket, ptr, length - read); 95848b8605Smrg 96848b8605Smrg if (ret <= 0) { 97848b8605Smrg FREE(data); 98848b8605Smrg return NULL; 99848b8605Smrg } 100848b8605Smrg 101848b8605Smrg read += ret; 102848b8605Smrg } while(read < length); 103848b8605Smrg 104848b8605Smrg out = rbug_demarshal(data); 105848b8605Smrg if (!out) 106848b8605Smrg FREE(data); 107848b8605Smrg else if (serial) 108848b8605Smrg *serial = c->recv_serial++; 109848b8605Smrg else 110848b8605Smrg c->recv_serial++; 111848b8605Smrg 112848b8605Smrg return out; 113848b8605Smrg} 114848b8605Smrg 115848b8605Smrg/** 116848b8605Smrg * Frees a message and associated data. 117848b8605Smrg */ 118848b8605Smrgvoid 119848b8605Smrgrbug_free_header(struct rbug_header *header) 120848b8605Smrg{ 121848b8605Smrg if (!header) 122848b8605Smrg return; 123848b8605Smrg 124848b8605Smrg FREE(header->__message); 125848b8605Smrg FREE(header); 126848b8605Smrg} 127848b8605Smrg 128848b8605Smrg/** 129848b8605Smrg * Internal function used by rbug_send_* functions. 130848b8605Smrg * 131848b8605Smrg * Start sending a message. 132848b8605Smrg */ 133848b8605Smrgint 134848b8605Smrgrbug_connection_send_start(struct rbug_connection *c, enum rbug_opcode opcode, uint32_t length) 135848b8605Smrg{ 136848b8605Smrg c->opcode = opcode; 137848b8605Smrg return 0; 138848b8605Smrg} 139848b8605Smrg 140848b8605Smrg/** 141848b8605Smrg * Internal function used by rbug_send_* functions. 142848b8605Smrg * 143848b8605Smrg * Write data to the socket. 144848b8605Smrg */ 145848b8605Smrgint 146848b8605Smrgrbug_connection_write(struct rbug_connection *c, void *to, uint32_t size) 147848b8605Smrg{ 148848b8605Smrg int ret = u_socket_send(c->socket, to, size); 149848b8605Smrg return ret; 150848b8605Smrg} 151848b8605Smrg 152848b8605Smrg/** 153848b8605Smrg * Internal function used by rbug_send_* functions. 154848b8605Smrg * 155b8e80941Smrg * Finish writing data to the socket. 156848b8605Smrg * Ups the send_serial and sets the serial argument if supplied. 157848b8605Smrg */ 158848b8605Smrgint rbug_connection_send_finish(struct rbug_connection *c, uint32_t *serial) 159848b8605Smrg{ 160848b8605Smrg if (c->opcode < 0) 161848b8605Smrg return 0; 162848b8605Smrg else if (serial) 163848b8605Smrg *serial = c->send_serial++; 164848b8605Smrg else 165848b8605Smrg c->send_serial++; 166848b8605Smrg 167848b8605Smrg return 0; 168848b8605Smrg} 169