1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc. 3bf215546Sopenharmony_ci * All Rights Reserved. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "rbug.h" 26bf215546Sopenharmony_ci#include "rbug_internal.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "util/u_network.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_cistruct rbug_connection 31bf215546Sopenharmony_ci{ 32bf215546Sopenharmony_ci int socket; 33bf215546Sopenharmony_ci uint32_t send_serial; 34bf215546Sopenharmony_ci uint32_t recv_serial; 35bf215546Sopenharmony_ci enum rbug_opcode opcode; 36bf215546Sopenharmony_ci}; 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci/** 39bf215546Sopenharmony_ci * Create a rbug connection from a socket created with u_socket. 40bf215546Sopenharmony_ci * 41bf215546Sopenharmony_ci * Result: 42bf215546Sopenharmony_ci * A new allocated connection using socket as communication path 43bf215546Sopenharmony_ci */ 44bf215546Sopenharmony_cistruct rbug_connection * 45bf215546Sopenharmony_cirbug_from_socket(int socket) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci struct rbug_connection *c = CALLOC_STRUCT(rbug_connection); 48bf215546Sopenharmony_ci c->socket = socket; 49bf215546Sopenharmony_ci return c; 50bf215546Sopenharmony_ci} 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci/** 53bf215546Sopenharmony_ci * Free a connection, also closes socket. 54bf215546Sopenharmony_ci */ 55bf215546Sopenharmony_civoid 56bf215546Sopenharmony_cirbug_disconnect(struct rbug_connection *c) 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci u_socket_close(c->socket); 59bf215546Sopenharmony_ci FREE(c); 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci/** 63bf215546Sopenharmony_ci * Waits for a message to be fully received. 64bf215546Sopenharmony_ci * Also returns the serial for the message, serial is not touched for replys. 65bf215546Sopenharmony_ci * 66bf215546Sopenharmony_ci * Result: 67bf215546Sopenharmony_ci * demarshaled message on success, NULL on connection error 68bf215546Sopenharmony_ci */ 69bf215546Sopenharmony_cistruct rbug_header * 70bf215546Sopenharmony_cirbug_get_message(struct rbug_connection *c, uint32_t *serial) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci struct rbug_proto_header header; 73bf215546Sopenharmony_ci struct rbug_header *out; 74bf215546Sopenharmony_ci struct rbug_proto_header *data; 75bf215546Sopenharmony_ci size_t length = 0; 76bf215546Sopenharmony_ci size_t read = 0; 77bf215546Sopenharmony_ci int ret; 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci ret = u_socket_peek(c->socket, &header, sizeof(header)); 81bf215546Sopenharmony_ci if (ret <= 0) { 82bf215546Sopenharmony_ci return NULL; 83bf215546Sopenharmony_ci } 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci length = (size_t)header.length * 4; 86bf215546Sopenharmony_ci data = MALLOC(length); 87bf215546Sopenharmony_ci if (!data) { 88bf215546Sopenharmony_ci return NULL; 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci data->opcode = 0; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci do { 93bf215546Sopenharmony_ci uint8_t *ptr = ((uint8_t*)data) + read; 94bf215546Sopenharmony_ci ret = u_socket_recv(c->socket, ptr, length - read); 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci if (ret <= 0) { 97bf215546Sopenharmony_ci FREE(data); 98bf215546Sopenharmony_ci return NULL; 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci read += ret; 102bf215546Sopenharmony_ci } while(read < length); 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci out = rbug_demarshal(data); 105bf215546Sopenharmony_ci if (!out) 106bf215546Sopenharmony_ci FREE(data); 107bf215546Sopenharmony_ci else if (serial) 108bf215546Sopenharmony_ci *serial = c->recv_serial++; 109bf215546Sopenharmony_ci else 110bf215546Sopenharmony_ci c->recv_serial++; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci return out; 113bf215546Sopenharmony_ci} 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci/** 116bf215546Sopenharmony_ci * Frees a message and associated data. 117bf215546Sopenharmony_ci */ 118bf215546Sopenharmony_civoid 119bf215546Sopenharmony_cirbug_free_header(struct rbug_header *header) 120bf215546Sopenharmony_ci{ 121bf215546Sopenharmony_ci if (!header) 122bf215546Sopenharmony_ci return; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci FREE(header->__message); 125bf215546Sopenharmony_ci FREE(header); 126bf215546Sopenharmony_ci} 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci/** 129bf215546Sopenharmony_ci * Internal function used by rbug_send_* functions. 130bf215546Sopenharmony_ci * 131bf215546Sopenharmony_ci * Start sending a message. 132bf215546Sopenharmony_ci */ 133bf215546Sopenharmony_ciint 134bf215546Sopenharmony_cirbug_connection_send_start(struct rbug_connection *c, enum rbug_opcode opcode, uint32_t length) 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci c->opcode = opcode; 137bf215546Sopenharmony_ci return 0; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci/** 141bf215546Sopenharmony_ci * Internal function used by rbug_send_* functions. 142bf215546Sopenharmony_ci * 143bf215546Sopenharmony_ci * Write data to the socket. 144bf215546Sopenharmony_ci */ 145bf215546Sopenharmony_ciint 146bf215546Sopenharmony_cirbug_connection_write(struct rbug_connection *c, void *to, uint32_t size) 147bf215546Sopenharmony_ci{ 148bf215546Sopenharmony_ci int ret = u_socket_send(c->socket, to, size); 149bf215546Sopenharmony_ci return ret; 150bf215546Sopenharmony_ci} 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci/** 153bf215546Sopenharmony_ci * Internal function used by rbug_send_* functions. 154bf215546Sopenharmony_ci * 155bf215546Sopenharmony_ci * Finish writing data to the socket. 156bf215546Sopenharmony_ci * Ups the send_serial and sets the serial argument if supplied. 157bf215546Sopenharmony_ci */ 158bf215546Sopenharmony_ciint rbug_connection_send_finish(struct rbug_connection *c, uint32_t *serial) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci if (c->opcode < 0) 161bf215546Sopenharmony_ci return 0; 162bf215546Sopenharmony_ci else if (serial) 163bf215546Sopenharmony_ci *serial = c->send_serial++; 164bf215546Sopenharmony_ci else 165bf215546Sopenharmony_ci c->send_serial++; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci return 0; 168bf215546Sopenharmony_ci} 169