Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / auxiliary / rbug / rbug_connection.c
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/rbug.h"
26 #include "rbug/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 }