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 
33 struct 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 
53 void
55 {
56  x_return_if_fail (msg);
57 
58  xmmsv_unref (msg->bb);
59  free (msg);
60 }
61 
62 static void
63 xmms_ipc_msg_update_length (xmmsv_t *bb)
64 {
65  int len;
66 
67  len = xmmsv_bitbuffer_len (bb);
68 
69  len /= 8;
70  len -= XMMS_IPC_MSG_HEAD_LEN;
71 
72  xmmsv_bitbuffer_goto (bb, 12*8);
73  xmmsv_bitbuffer_put_bits (bb, 32, len);
75 }
76 
77 static uint32_t
78 xmms_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 
90 uint32_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 
103 static void
104 xmms_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 
113 uint32_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 
126 static void
127 xmms_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 
136 void
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 
144 uint32_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 
158 xmms_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  */
179 bool
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  */
225 bool
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) {
237  len = XMMS_IPC_MSG_HEAD_LEN;
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 
280 uint32_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 
290 bool
292 {
293  return xmmsv_bitbuffer_deserialize_value (msg->bb, val);
294 }
int xmms_ipc_transport_read(xmms_ipc_transport_t *ipct, char *buffer, int len)
Definition: transport.c:37
#define XMMS_IPC_MSG_HEAD_LEN
Definition: xmmsc_ipc_msg.h:29
#define x_return_val_if_fail(expr, val)
Definition: xmmsc_util.h:13
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
bool xmms_socket_error_recoverable(void)
Definition: socket_common.c:9
struct xmmsv_St xmmsv_t
Definition: xmmsv_general.h:48
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
struct xmms_ipc_msg_St xmms_ipc_msg_t
Definition: xmmsc_ipc_msg.h:31
int xmmsv_bitbuffer_pos(xmmsv_t *v)
Definition: value.c:2653
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_put_bits(xmmsv_t *v, int bits, int d)
Definition: value.c:2567
void xmms_ipc_msg_destroy(xmms_ipc_msg_t *msg)
Definition: msg.c:54
int xmmsv_bitbuffer_deserialize_value(xmmsv_t *bb, xmmsv_t **val)
int xmmsv_bitbuffer_align(xmmsv_t *v)
Definition: value.c:2636
void xmms_ipc_msg_set_cookie(xmms_ipc_msg_t *msg, uint32_t cookie)
Definition: msg.c:137
int xmmsv_bitbuffer_len(xmmsv_t *v)
Definition: value.c:2671
xmms_ipc_msg_t * xmms_ipc_msg_alloc(void)
Definition: msg.c:41
int xmms_ipc_transport_write(xmms_ipc_transport_t *ipct, char *buffer, int len)
Definition: transport.c:43
#define x_new0(type, num)
Definition: xmmsc_util.h:16
uint32_t xmms_ipc_msg_get_object(const xmms_ipc_msg_t *msg)
Definition: msg.c:91
xmms_ipc_msg_t * xmms_ipc_msg_new(uint32_t object, uint32_t cmd)
Definition: msg.c:158
#define SOCKET_ERROR
Definition: xmmsc_sockets.h:17
int xmmsv_bitbuffer_serialize_value(xmmsv_t *bb, xmmsv_t *v)
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
int xmmsv_bitbuffer_put_data(xmmsv_t *v, const unsigned char *b, int len)
Definition: value.c:2622
uint32_t xmms_ipc_msg_get_cmd(const xmms_ipc_msg_t *msg)
Definition: msg.c:114
#define x_return_if_fail(expr)
Definition: xmmsc_util.h:12
int xmmsv_bitbuffer_end(xmmsv_t *v)
Definition: value.c:2665
int xmmsv_bitbuffer_get_bits(xmmsv_t *v, int bits, int *res)
Definition: value.c:2524
uint32_t xmms_ipc_msg_put_value(xmms_ipc_msg_t *msg, xmmsv_t *v)
Definition: msg.c:281
bool xmms_ipc_msg_get_value(xmms_ipc_msg_t *msg, xmmsv_t **val)
Definition: msg.c:291
xmmsv_t * xmmsv_bitbuffer_new(void)
Definition: value.c:2511
uint32_t xmms_ipc_msg_get_cookie(const xmms_ipc_msg_t *msg)
Definition: msg.c:145