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