XMMS2
msg.c
Go to the documentation of this file.
1/* XMMS2 - X Music Multiplexer System
2 * Copyright (C) 2003-2011 XMMS2 Team
3 *
4 * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 */
16
17#include <stdarg.h>
18#include <string.h>
19#include <stdlib.h>
20
21#include <errno.h>
22#include <time.h>
23#include <assert.h>
24
25#include "xmmspriv/xmms_list.h"
27#include "xmmsc/xmmsc_ipc_msg.h"
28#include "xmmsc/xmmsc_util.h"
29#include "xmmsc/xmmsc_sockets.h"
30#include "xmmsc/xmmsc_stdint.h"
31#include "xmmsc/xmmsv_coll.h"
32
33struct xmms_ipc_msg_St {
34 xmmsv_t *bb;
35 uint32_t xfered;
36};
37
38
39
42{
43 xmms_ipc_msg_t *msg;
44 static unsigned char empty[16] = {0,};
45
46 msg = x_new0 (xmms_ipc_msg_t, 1);
47 msg->bb = xmmsv_bitbuffer_new ();
48 xmmsv_bitbuffer_put_data (msg->bb, empty, 16);
49
50 return msg;
51}
52
53void
55{
56 x_return_if_fail (msg);
57
58 xmmsv_unref (msg->bb);
59 free (msg);
60}
61
62static void
63xmms_ipc_msg_update_length (xmmsv_t *bb)
64{
65 int len;
66
67 len = xmmsv_bitbuffer_len (bb);
68
69 len /= 8;
71
72 xmmsv_bitbuffer_goto (bb, 12*8);
73 xmmsv_bitbuffer_put_bits (bb, 32, len);
75}
76
77static uint32_t
78xmms_ipc_msg_get_length (const xmms_ipc_msg_t *msg)
79{
80 int len, p;
81 x_return_val_if_fail (msg, 0);
82
83 p = xmmsv_bitbuffer_pos (msg->bb);
84 xmmsv_bitbuffer_goto (msg->bb, 12*8);
85 xmmsv_bitbuffer_get_bits (msg->bb, 32, &len);
86 xmmsv_bitbuffer_goto (msg->bb, p);
87 return len;
88}
89
90uint32_t
92{
93 int obj, p;
94 x_return_val_if_fail (msg, 0);
95
96 p = xmmsv_bitbuffer_pos (msg->bb);
97 xmmsv_bitbuffer_goto (msg->bb, 0);
98 xmmsv_bitbuffer_get_bits (msg->bb, 32, &obj);
99 xmmsv_bitbuffer_goto (msg->bb, p);
100 return obj;
101}
102
103static void
104xmms_ipc_msg_set_object (xmms_ipc_msg_t *msg, uint32_t object)
105{
106 x_return_if_fail (msg);
107
108 xmmsv_bitbuffer_goto (msg->bb, 0);
109 xmmsv_bitbuffer_put_bits (msg->bb, 32, object);
110 xmmsv_bitbuffer_end (msg->bb);
111}
112
113uint32_t
115{
116 int cmd, p;
117 x_return_val_if_fail (msg, 0);
118
119 p = xmmsv_bitbuffer_pos (msg->bb);
120 xmmsv_bitbuffer_goto (msg->bb, 4 * 8);
121 xmmsv_bitbuffer_get_bits (msg->bb, 32, &cmd);
122 xmmsv_bitbuffer_goto (msg->bb, p);
123 return cmd;
124}
125
126static void
127xmms_ipc_msg_set_cmd (xmms_ipc_msg_t *msg, uint32_t cmd)
128{
129 x_return_if_fail (msg);
130
131 xmmsv_bitbuffer_goto (msg->bb, 4 * 8);
132 xmmsv_bitbuffer_put_bits (msg->bb, 32, cmd);
133 xmmsv_bitbuffer_end (msg->bb);
134}
135
136void
138{
139 xmmsv_bitbuffer_goto (msg->bb, 8 * 8);
140 xmmsv_bitbuffer_put_bits (msg->bb, 32, cookie);
141 xmmsv_bitbuffer_end (msg->bb);
142}
143
144uint32_t
146{
147 int cookie, p;
148 x_return_val_if_fail (msg, 0);
149
150 p = xmmsv_bitbuffer_pos (msg->bb);
151 xmmsv_bitbuffer_goto (msg->bb, 8 * 8);
152 xmmsv_bitbuffer_get_bits (msg->bb, 32, &cookie);
153 xmmsv_bitbuffer_goto (msg->bb, p);
154 return cookie;
155}
156
158xmms_ipc_msg_new (uint32_t object, uint32_t cmd)
159{
160 xmms_ipc_msg_t *msg;
161
162 msg = xmms_ipc_msg_alloc ();
163
164 xmms_ipc_msg_set_cmd (msg, cmd);
165 xmms_ipc_msg_set_object (msg, object);
166
167 return msg;
168}
169
170
171/**
172 * Try to write message to transport. If full message isn't written
173 * the message will keep track of the amount of data written and not
174 * write already written data next time.
175 *
176 * @returns TRUE if full message was written, FALSE otherwise.
177 * disconnected is set if transport was disconnected
178 */
179bool
181 xmms_ipc_transport_t *transport,
182 bool *disconnected)
183{
184 char *buf;
185 unsigned int ret, len;
186
187 x_return_val_if_fail (msg, false);
188 x_return_val_if_fail (transport, false);
189
190 xmmsv_bitbuffer_align (msg->bb);
191
192 len = xmmsv_bitbuffer_len (msg->bb) / 8;
193
194 x_return_val_if_fail (len > msg->xfered, true);
195
196 buf = (char *) (xmmsv_bitbuffer_buffer (msg->bb) + msg->xfered);
197 ret = xmms_ipc_transport_write (transport, buf, len - msg->xfered);
198
199 if (ret == SOCKET_ERROR) {
201 return false;
202 }
203
204 if (disconnected) {
205 *disconnected = true;
206 }
207
208 return false;
209 } else if (!ret) {
210 if (disconnected) {
211 *disconnected = true;
212 }
213 } else {
214 msg->xfered += ret;
215 }
216
217 return (len == msg->xfered);
218}
219
220/**
221 * Try to read message from transport into msg.
222 *
223 * @returns TRUE if message is fully read.
224 */
225bool
227 xmms_ipc_transport_t *transport,
228 bool *disconnected)
229{
230 char buf[512];
231 unsigned int ret, len, rlen;
232
233 x_return_val_if_fail (msg, false);
234 x_return_val_if_fail (transport, false);
235
236 while (true) {
238
239 if (msg->xfered >= XMMS_IPC_MSG_HEAD_LEN) {
240 len += xmms_ipc_msg_get_length (msg);
241
242 if (msg->xfered == len) {
243 return true;
244 }
245 }
246
247 x_return_val_if_fail (msg->xfered < len, false);
248
249 rlen = len - msg->xfered;
250 if (rlen > sizeof (buf))
251 rlen = sizeof (buf);
252
253 ret = xmms_ipc_transport_read (transport, buf, rlen);
254
255 if (ret == SOCKET_ERROR) {
257 return false;
258 }
259
260 if (disconnected) {
261 *disconnected = true;
262 }
263
264 return false;
265 } else if (ret == 0) {
266 if (disconnected) {
267 *disconnected = true;
268 }
269
270 return false;
271 } else {
272 xmmsv_bitbuffer_goto (msg->bb, msg->xfered * 8);
273 xmmsv_bitbuffer_put_data (msg->bb, (unsigned char *) buf, ret);
274 msg->xfered += ret;
276 }
277 }
278}
279
280uint32_t
282{
283 if (!xmmsv_bitbuffer_serialize_value (msg->bb, v))
284 return false;
285 xmms_ipc_msg_update_length (msg->bb);
286 return xmmsv_bitbuffer_pos (msg->bb);
287}
288
289
290bool
292{
293 return xmmsv_bitbuffer_deserialize_value (msg->bb, val);
294}
int xmmsv_bitbuffer_get_bits(xmmsv_t *v, int bits, int *res)
Definition value.c:2524
xmmsv_t * xmmsv_bitbuffer_new(void)
Definition value.c:2511
int xmmsv_bitbuffer_len(xmmsv_t *v)
Definition value.c:2671
int xmmsv_bitbuffer_deserialize_value(xmmsv_t *bb, xmmsv_t **val)
int xmmsv_bitbuffer_end(xmmsv_t *v)
Definition value.c:2665
int xmmsv_bitbuffer_align(xmmsv_t *v)
Definition value.c:2636
int xmmsv_bitbuffer_pos(xmmsv_t *v)
Definition value.c:2653
int xmmsv_bitbuffer_put_data(xmmsv_t *v, const unsigned char *b, int len)
Definition value.c:2622
int xmmsv_bitbuffer_goto(xmmsv_t *v, int pos)
Definition value.c:2643
const unsigned char * xmmsv_bitbuffer_buffer(xmmsv_t *v)
Definition value.c:2677
int xmmsv_bitbuffer_serialize_value(xmmsv_t *bb, xmmsv_t *v)
int xmmsv_bitbuffer_put_bits(xmmsv_t *v, int bits, int d)
Definition value.c:2567
void xmmsv_unref(xmmsv_t *val)
Decreases the references for the xmmsv_t When the number of references reaches 0 it will be freed.
Definition value.c:303
struct xmmsv_St xmmsv_t
void xmms_ipc_msg_destroy(xmms_ipc_msg_t *msg)
Definition msg.c:54
void xmms_ipc_msg_set_cookie(xmms_ipc_msg_t *msg, uint32_t cookie)
Definition msg.c:137
bool xmms_ipc_msg_get_value(xmms_ipc_msg_t *msg, xmmsv_t **val)
Definition msg.c:291
bool xmms_ipc_msg_write_transport(xmms_ipc_msg_t *msg, xmms_ipc_transport_t *transport, bool *disconnected)
Try to write message to transport.
Definition msg.c:180
uint32_t xmms_ipc_msg_get_cmd(const xmms_ipc_msg_t *msg)
Definition msg.c:114
uint32_t xmms_ipc_msg_get_object(const xmms_ipc_msg_t *msg)
Definition msg.c:91
bool xmms_ipc_msg_read_transport(xmms_ipc_msg_t *msg, xmms_ipc_transport_t *transport, bool *disconnected)
Try to read message from transport into msg.
Definition msg.c:226
uint32_t xmms_ipc_msg_put_value(xmms_ipc_msg_t *msg, xmmsv_t *v)
Definition msg.c:281
xmms_ipc_msg_t * xmms_ipc_msg_alloc(void)
Definition msg.c:41
xmms_ipc_msg_t * xmms_ipc_msg_new(uint32_t object, uint32_t cmd)
Definition msg.c:158
uint32_t xmms_ipc_msg_get_cookie(const xmms_ipc_msg_t *msg)
Definition msg.c:145
struct xmms_ipc_msg_St xmms_ipc_msg_t
#define XMMS_IPC_MSG_HEAD_LEN
int xmms_ipc_transport_read(xmms_ipc_transport_t *ipct, char *buffer, int len)
Definition transport.c:37
int xmms_ipc_transport_write(xmms_ipc_transport_t *ipct, char *buffer, int len)
Definition transport.c:43
bool xmms_socket_error_recoverable(void)
#define SOCKET_ERROR
#define x_return_val_if_fail(expr, val)
Definition xmmsc_util.h:13
#define x_return_if_fail(expr)
Definition xmmsc_util.h:12
#define x_new0(type, num)
Definition xmmsc_util.h:16