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