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/*
26 * This file holds the function implementation for one of the rbug extensions.
27 * Prototypes and declerations of functions and structs is in the same folder
28 * in the header file matching this file's name.
29 *
30 * The functions starting rbug_send_* encodes a call to the write format and
31 * sends that to the supplied connection, while functions starting with
32 * rbug_demarshal_* demarshal data in the wire protocol.
33 *
34 * Functions ending with _reply are replies to requests.
35 */
36
37#include "rbug_internal.h"
38#include "rbug_core.h"
39
40int rbug_send_noop(struct rbug_connection *__con,
41                   uint32_t *__serial)
42{
43	uint32_t __len = 0;
44	uint32_t __pos = 0;
45	uint8_t *__data = NULL;
46	int __ret = 0;
47
48	LEN(8); /* header */
49
50	/* align */
51	PAD(__len, 8);
52
53	__data = (uint8_t*)MALLOC(__len);
54	if (!__data)
55		return -ENOMEM;
56
57	WRITE(4, int32_t, ((int32_t)RBUG_OP_NOOP));
58	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
59
60	/* final pad */
61	PAD(__pos, 8);
62
63	if (__pos != __len) {
64		__ret = -EINVAL;
65	} else {
66		rbug_connection_send_start(__con, RBUG_OP_NOOP, __len);
67		rbug_connection_write(__con, __data, __len);
68		__ret = rbug_connection_send_finish(__con, __serial);
69	}
70
71	FREE(__data);
72	return __ret;
73}
74
75int rbug_send_ping(struct rbug_connection *__con,
76                   uint32_t *__serial)
77{
78	uint32_t __len = 0;
79	uint32_t __pos = 0;
80	uint8_t *__data = NULL;
81	int __ret = 0;
82
83	LEN(8); /* header */
84
85	/* align */
86	PAD(__len, 8);
87
88	__data = (uint8_t*)MALLOC(__len);
89	if (!__data)
90		return -ENOMEM;
91
92	WRITE(4, int32_t, ((int32_t)RBUG_OP_PING));
93	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
94
95	/* final pad */
96	PAD(__pos, 8);
97
98	if (__pos != __len) {
99		__ret = -EINVAL;
100	} else {
101		rbug_connection_send_start(__con, RBUG_OP_PING, __len);
102		rbug_connection_write(__con, __data, __len);
103		__ret = rbug_connection_send_finish(__con, __serial);
104	}
105
106	FREE(__data);
107	return __ret;
108}
109
110int rbug_send_error(struct rbug_connection *__con,
111                    uint32_t error,
112                    uint32_t *__serial)
113{
114	uint32_t __len = 0;
115	uint32_t __pos = 0;
116	uint8_t *__data = NULL;
117	int __ret = 0;
118
119	LEN(8); /* header */
120	LEN(4); /* error */
121
122	/* align */
123	PAD(__len, 8);
124
125	__data = (uint8_t*)MALLOC(__len);
126	if (!__data)
127		return -ENOMEM;
128
129	WRITE(4, int32_t, ((int32_t)RBUG_OP_ERROR));
130	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
131	WRITE(4, uint32_t, error); /* error */
132
133	/* final pad */
134	PAD(__pos, 8);
135
136	if (__pos != __len) {
137		__ret = -EINVAL;
138	} else {
139		rbug_connection_send_start(__con, RBUG_OP_ERROR, __len);
140		rbug_connection_write(__con, __data, __len);
141		__ret = rbug_connection_send_finish(__con, __serial);
142	}
143
144	FREE(__data);
145	return __ret;
146}
147
148int rbug_send_ping_reply(struct rbug_connection *__con,
149                         uint32_t serial,
150                         uint32_t *__serial)
151{
152	uint32_t __len = 0;
153	uint32_t __pos = 0;
154	uint8_t *__data = NULL;
155	int __ret = 0;
156
157	LEN(8); /* header */
158	LEN(4); /* serial */
159
160	/* align */
161	PAD(__len, 8);
162
163	__data = (uint8_t*)MALLOC(__len);
164	if (!__data)
165		return -ENOMEM;
166
167	WRITE(4, int32_t, ((int32_t)RBUG_OP_PING_REPLY));
168	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
169	WRITE(4, uint32_t, serial); /* serial */
170
171	/* final pad */
172	PAD(__pos, 8);
173
174	if (__pos != __len) {
175		__ret = -EINVAL;
176	} else {
177		rbug_connection_send_start(__con, RBUG_OP_PING_REPLY, __len);
178		rbug_connection_write(__con, __data, __len);
179		__ret = rbug_connection_send_finish(__con, __serial);
180	}
181
182	FREE(__data);
183	return __ret;
184}
185
186int rbug_send_error_reply(struct rbug_connection *__con,
187                          uint32_t serial,
188                          uint32_t error,
189                          uint32_t *__serial)
190{
191	uint32_t __len = 0;
192	uint32_t __pos = 0;
193	uint8_t *__data = NULL;
194	int __ret = 0;
195
196	LEN(8); /* header */
197	LEN(4); /* serial */
198	LEN(4); /* error */
199
200	/* align */
201	PAD(__len, 8);
202
203	__data = (uint8_t*)MALLOC(__len);
204	if (!__data)
205		return -ENOMEM;
206
207	WRITE(4, int32_t, ((int32_t)RBUG_OP_ERROR_REPLY));
208	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
209	WRITE(4, uint32_t, serial); /* serial */
210	WRITE(4, uint32_t, error); /* error */
211
212	/* final pad */
213	PAD(__pos, 8);
214
215	if (__pos != __len) {
216		__ret = -EINVAL;
217	} else {
218		rbug_connection_send_start(__con, RBUG_OP_ERROR_REPLY, __len);
219		rbug_connection_write(__con, __data, __len);
220		__ret = rbug_connection_send_finish(__con, __serial);
221	}
222
223	FREE(__data);
224	return __ret;
225}
226
227struct rbug_proto_noop * rbug_demarshal_noop(struct rbug_proto_header *header)
228{
229	struct rbug_proto_noop *ret;
230
231	if (!header)
232		return NULL;
233	if (header->opcode != (int32_t)RBUG_OP_NOOP)
234		return NULL;
235
236	ret = MALLOC(sizeof(*ret));
237	if (!ret)
238		return NULL;
239
240	ret->header.__message = header;
241	ret->header.opcode = header->opcode;
242
243	return ret;
244}
245
246struct rbug_proto_ping * rbug_demarshal_ping(struct rbug_proto_header *header)
247{
248	struct rbug_proto_ping *ret;
249
250	if (!header)
251		return NULL;
252	if (header->opcode != (int32_t)RBUG_OP_PING)
253		return NULL;
254
255	ret = MALLOC(sizeof(*ret));
256	if (!ret)
257		return NULL;
258
259	ret->header.__message = header;
260	ret->header.opcode = header->opcode;
261
262	return ret;
263}
264
265struct rbug_proto_error * rbug_demarshal_error(struct rbug_proto_header *header)
266{
267	uint32_t len = 0;
268	uint32_t pos = 0;
269	uint8_t *data =  NULL;
270	struct rbug_proto_error *ret;
271
272	if (!header)
273		return NULL;
274	if (header->opcode != (int32_t)RBUG_OP_ERROR)
275		return NULL;
276
277	pos = 0;
278	len = header->length * 4;
279	data = (uint8_t*)&header[1];
280	ret = MALLOC(sizeof(*ret));
281	if (!ret)
282		return NULL;
283
284	ret->header.__message = header;
285	ret->header.opcode = header->opcode;
286
287	READ(4, uint32_t, error); /* error */
288
289	return ret;
290}
291
292struct rbug_proto_ping_reply * rbug_demarshal_ping_reply(struct rbug_proto_header *header)
293{
294	uint32_t len = 0;
295	uint32_t pos = 0;
296	uint8_t *data =  NULL;
297	struct rbug_proto_ping_reply *ret;
298
299	if (!header)
300		return NULL;
301	if (header->opcode != (int32_t)RBUG_OP_PING_REPLY)
302		return NULL;
303
304	pos = 0;
305	len = header->length * 4;
306	data = (uint8_t*)&header[1];
307	ret = MALLOC(sizeof(*ret));
308	if (!ret)
309		return NULL;
310
311	ret->header.__message = header;
312	ret->header.opcode = header->opcode;
313
314	READ(4, uint32_t, serial); /* serial */
315
316	return ret;
317}
318
319struct rbug_proto_error_reply * rbug_demarshal_error_reply(struct rbug_proto_header *header)
320{
321	uint32_t len = 0;
322	uint32_t pos = 0;
323	uint8_t *data =  NULL;
324	struct rbug_proto_error_reply *ret;
325
326	if (!header)
327		return NULL;
328	if (header->opcode != (int32_t)RBUG_OP_ERROR_REPLY)
329		return NULL;
330
331	pos = 0;
332	len = header->length * 4;
333	data = (uint8_t*)&header[1];
334	ret = MALLOC(sizeof(*ret));
335	if (!ret)
336		return NULL;
337
338	ret->header.__message = header;
339	ret->header.opcode = header->opcode;
340
341	READ(4, uint32_t, serial); /* serial */
342	READ(4, uint32_t, error); /* error */
343
344	return ret;
345}
346