00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdarg.h>
00018 #include <string.h>
00019 #include <stdlib.h>
00020
00021 #include <errno.h>
00022 #include <time.h>
00023 #include <assert.h>
00024
00025 #include "xmmspriv/xmms_list.h"
00026 #include "xmmsc/xmmsc_ipc_transport.h"
00027 #include "xmmsc/xmmsc_ipc_msg.h"
00028 #include "xmmsc/xmmsc_util.h"
00029 #include "xmmsc/xmmsc_sockets.h"
00030 #include "xmmsc/xmmsc_stdint.h"
00031 #include "xmmsc/xmmsv_coll.h"
00032
00033
00034 typedef union {
00035 struct {
00036 uint32_t object;
00037 uint32_t cmd;
00038 uint32_t cookie;
00039 uint32_t length;
00040 uint8_t data[0];
00041 } header;
00042 uint8_t rawdata[0];
00043 } xmms_ipc_msg_data_t;
00044
00045 struct xmms_ipc_msg_St {
00046 xmms_ipc_msg_data_t *data;
00047 uint32_t get_pos;
00048 uint32_t size;
00049 uint32_t xfered;
00050 };
00051
00052
00053 void
00054 xmms_ipc_append_coll_attr (const char* key, const char* value, void *userdata) {
00055 xmms_ipc_msg_t *msg = (xmms_ipc_msg_t *)userdata;
00056 xmms_ipc_msg_put_string (msg, key);
00057 xmms_ipc_msg_put_string (msg, value);
00058 }
00059
00060 void
00061 xmms_ipc_count_coll_attr (const char* key, const char* value, void *userdata) {
00062 int *n = (int *)userdata;
00063 ++(*n);
00064 }
00065
00066
00067 xmms_ipc_msg_t *
00068 xmms_ipc_msg_alloc (void)
00069 {
00070 xmms_ipc_msg_t *msg;
00071
00072 msg = x_new0 (xmms_ipc_msg_t, 1);
00073 msg->data = malloc (XMMS_IPC_MSG_DEFAULT_SIZE);
00074 memset (msg->data, 0, XMMS_IPC_MSG_HEAD_LEN);
00075 msg->size = XMMS_IPC_MSG_DEFAULT_SIZE;
00076
00077 return msg;
00078 }
00079
00080 xmms_ipc_msg_t *
00081 xmms_ipc_msg_new (uint32_t object, uint32_t cmd)
00082 {
00083 xmms_ipc_msg_t *msg;
00084
00085 msg = xmms_ipc_msg_alloc ();
00086
00087 xmms_ipc_msg_set_cmd (msg, cmd);
00088 xmms_ipc_msg_set_object (msg, object);
00089
00090 return msg;
00091 }
00092
00093 void
00094 xmms_ipc_msg_destroy (xmms_ipc_msg_t *msg)
00095 {
00096 x_return_if_fail (msg);
00097
00098 free (msg->data);
00099 free (msg);
00100 }
00101
00102 void
00103 xmms_ipc_msg_set_length (xmms_ipc_msg_t *msg, uint32_t len)
00104 {
00105 x_return_if_fail (msg);
00106
00107 msg->data->header.length = htonl (len);
00108 }
00109
00110 uint32_t
00111 xmms_ipc_msg_get_length (const xmms_ipc_msg_t *msg)
00112 {
00113 x_return_val_if_fail (msg, 0);
00114
00115 return ntohl (msg->data->header.length);
00116 }
00117
00118 uint32_t
00119 xmms_ipc_msg_get_object (const xmms_ipc_msg_t *msg)
00120 {
00121 x_return_val_if_fail (msg, 0);
00122
00123 return ntohl (msg->data->header.object);
00124 }
00125
00126 void
00127 xmms_ipc_msg_set_object (xmms_ipc_msg_t *msg, uint32_t object)
00128 {
00129 x_return_if_fail (msg);
00130
00131 msg->data->header.object = htonl (object);
00132 }
00133
00134 uint32_t
00135 xmms_ipc_msg_get_cmd (const xmms_ipc_msg_t *msg)
00136 {
00137 x_return_val_if_fail (msg, 0);
00138
00139 return ntohl (msg->data->header.cmd);
00140 }
00141
00142 void
00143 xmms_ipc_msg_set_cmd (xmms_ipc_msg_t *msg, uint32_t cmd)
00144 {
00145 x_return_if_fail (msg);
00146
00147 msg->data->header.cmd = htonl (cmd);
00148 }
00149
00150 void
00151 xmms_ipc_msg_set_cookie (xmms_ipc_msg_t *msg, uint32_t cookie)
00152 {
00153 msg->data->header.cookie = htonl (cookie);
00154 }
00155
00156 uint32_t
00157 xmms_ipc_msg_get_cookie (const xmms_ipc_msg_t *msg)
00158 {
00159 x_return_val_if_fail (msg, 0);
00160
00161 return ntohl (msg->data->header.cookie);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 bool
00173 xmms_ipc_msg_write_transport (xmms_ipc_msg_t *msg,
00174 xmms_ipc_transport_t *transport,
00175 bool *disconnected)
00176 {
00177 char *buf;
00178 unsigned int ret, len;
00179
00180 x_return_val_if_fail (msg, false);
00181 x_return_val_if_fail (msg->data, false);
00182 x_return_val_if_fail (transport, false);
00183
00184 len = xmms_ipc_msg_get_length (msg) + XMMS_IPC_MSG_HEAD_LEN;
00185
00186 x_return_val_if_fail (len > msg->xfered, true);
00187
00188 buf = (char *) (msg->data->rawdata + msg->xfered);
00189 ret = xmms_ipc_transport_write (transport, buf, len - msg->xfered);
00190
00191 if (ret == SOCKET_ERROR) {
00192 if (xmms_socket_error_recoverable ()) {
00193 return false;
00194 }
00195
00196 if (disconnected) {
00197 *disconnected = true;
00198 }
00199
00200 return false;
00201 } else if (!ret) {
00202 if (disconnected) {
00203 *disconnected = true;
00204 }
00205 } else {
00206 msg->xfered += ret;
00207 }
00208
00209 return (len == msg->xfered);
00210 }
00211
00212
00213
00214
00215
00216
00217 bool
00218 xmms_ipc_msg_read_transport (xmms_ipc_msg_t *msg,
00219 xmms_ipc_transport_t *transport,
00220 bool *disconnected)
00221 {
00222 char *buf;
00223 unsigned int ret, len;
00224
00225 x_return_val_if_fail (msg, false);
00226 x_return_val_if_fail (transport, false);
00227
00228 while (true) {
00229 len = XMMS_IPC_MSG_HEAD_LEN;
00230
00231 if (msg->xfered >= XMMS_IPC_MSG_HEAD_LEN) {
00232 len += xmms_ipc_msg_get_length (msg);
00233
00234 if (len > msg->size) {
00235 void *newbuf;
00236 newbuf = realloc (msg->data, len);
00237 if (!newbuf) {
00238 if (disconnected) {
00239 *disconnected = true;
00240 }
00241 return false;
00242 }
00243 msg->size = len;
00244 msg->data = newbuf;
00245 }
00246
00247 if (msg->xfered == len) {
00248 return true;
00249 }
00250 }
00251
00252 x_return_val_if_fail (msg->xfered < len, false);
00253
00254 buf = (char *) (msg->data->rawdata + msg->xfered);
00255 ret = xmms_ipc_transport_read (transport, buf, len - msg->xfered);
00256
00257 if (ret == SOCKET_ERROR) {
00258 if (xmms_socket_error_recoverable ()) {
00259 return false;
00260 }
00261
00262 if (disconnected) {
00263 *disconnected = true;
00264 }
00265
00266 return false;
00267 } else if (ret == 0) {
00268 if (disconnected) {
00269 *disconnected = true;
00270 }
00271
00272 return false;
00273 } else {
00274 msg->xfered += ret;
00275 }
00276 }
00277 }
00278
00279 static uint32_t
00280 xmms_ipc_msg_put_data (xmms_ipc_msg_t *msg, const void *data, unsigned int len)
00281 {
00282 uint32_t total;
00283
00284 x_return_val_if_fail (msg, -1);
00285
00286 total = xmms_ipc_msg_get_length (msg) + XMMS_IPC_MSG_HEAD_LEN + len;
00287
00288 if (total > msg->size) {
00289 int realloc_size = XMMS_IPC_MSG_DEFAULT_SIZE;
00290
00291 if (len > XMMS_IPC_MSG_DEFAULT_SIZE) {
00292 realloc_size = len;
00293 }
00294
00295
00296 msg->data = realloc (msg->data, msg->size + realloc_size);
00297 msg->size += realloc_size;
00298 }
00299
00300 total = xmms_ipc_msg_get_length (msg);
00301 memcpy (&msg->data->header.data[total], data, len);
00302 xmms_ipc_msg_set_length (msg, total + len);
00303
00304
00305
00306
00307
00308
00309 return total;
00310 }
00311
00312 uint32_t
00313 xmms_ipc_msg_put_bin (xmms_ipc_msg_t *msg,
00314 const unsigned char *data,
00315 unsigned int len)
00316 {
00317 xmms_ipc_msg_put_uint32 (msg, len);
00318 return xmms_ipc_msg_put_data (msg, data, len);
00319 }
00320
00321 uint32_t
00322 xmms_ipc_msg_put_error (xmms_ipc_msg_t *msg, const char *errmsg)
00323 {
00324 if (!msg) {
00325 return -1;
00326 }
00327
00328 if (!errmsg) {
00329 return xmms_ipc_msg_put_uint32 (msg, 0);
00330 }
00331
00332 xmms_ipc_msg_put_uint32 (msg, strlen (errmsg) + 1);
00333
00334 return xmms_ipc_msg_put_data (msg, errmsg, strlen (errmsg) + 1);
00335 }
00336
00337 uint32_t
00338 xmms_ipc_msg_put_uint32 (xmms_ipc_msg_t *msg, uint32_t v)
00339 {
00340 v = htonl (v);
00341
00342 return xmms_ipc_msg_put_data (msg, &v, sizeof (v));
00343 }
00344
00345 void
00346 xmms_ipc_msg_store_uint32 (xmms_ipc_msg_t *msg,
00347 uint32_t offset, uint32_t v)
00348 {
00349 v = htonl (v);
00350
00351 memcpy (&msg->data->header.data[offset], &v, sizeof (v));
00352 }
00353
00354 uint32_t
00355 xmms_ipc_msg_put_int32 (xmms_ipc_msg_t *msg, int32_t v)
00356 {
00357 v = htonl (v);
00358
00359 return xmms_ipc_msg_put_data (msg, &v, sizeof (v));
00360 }
00361
00362 uint32_t
00363 xmms_ipc_msg_put_float (xmms_ipc_msg_t *msg, float v)
00364 {
00365
00366 return xmms_ipc_msg_put_data (msg, &v, sizeof (v));
00367 }
00368
00369 uint32_t
00370 xmms_ipc_msg_put_string (xmms_ipc_msg_t *msg, const char *str)
00371 {
00372 if (!msg) {
00373 return -1;
00374 }
00375
00376 if (!str) {
00377 return xmms_ipc_msg_put_uint32 (msg, 0);
00378 }
00379
00380 xmms_ipc_msg_put_uint32 (msg, strlen (str) + 1);
00381
00382 return xmms_ipc_msg_put_data (msg, str, strlen (str) + 1);
00383 }
00384
00385 uint32_t
00386 xmms_ipc_msg_put_collection (xmms_ipc_msg_t *msg, xmmsv_coll_t *coll)
00387 {
00388 xmmsv_list_iter_t *it;
00389 xmmsv_t *v;
00390 int n;
00391 uint32_t ret, *idlist;
00392 xmmsv_coll_t *op;
00393
00394 if (!msg || !coll) {
00395 return -1;
00396 }
00397
00398
00399 xmms_ipc_msg_put_uint32 (msg, xmmsv_coll_get_type (coll));
00400
00401
00402 n = 0;
00403 xmmsv_coll_attribute_foreach (coll, xmms_ipc_count_coll_attr, &n);
00404 xmms_ipc_msg_put_uint32 (msg, n);
00405
00406 xmmsv_coll_attribute_foreach (coll, xmms_ipc_append_coll_attr, msg);
00407
00408
00409 idlist = xmmsv_coll_get_idlist (coll);
00410 for (n = 0; idlist[n] != 0; n++) { }
00411
00412 xmms_ipc_msg_put_uint32 (msg, n);
00413 for (n = 0; idlist[n] != 0; n++) {
00414 xmms_ipc_msg_put_uint32 (msg, idlist[n]);
00415 }
00416
00417
00418 n = 0;
00419 if (xmmsv_coll_get_type (coll) != XMMS_COLLECTION_TYPE_REFERENCE) {
00420 n = xmmsv_list_get_size (xmmsv_coll_operands_get (coll));
00421 }
00422
00423 ret = xmms_ipc_msg_put_uint32 (msg, n);
00424
00425 if (n > 0) {
00426 xmmsv_get_list_iter (xmmsv_coll_operands_get (coll), &it);
00427
00428 while (xmmsv_list_iter_entry (it, &v)) {
00429 if (!xmmsv_get_coll (v, &op)) {
00430 x_api_error ("Non collection operand", 0);
00431 }
00432 ret = xmms_ipc_msg_put_collection (msg, op);
00433 xmmsv_list_iter_next (it);
00434 }
00435 }
00436
00437 return ret;
00438 }
00439
00440 uint32_t
00441 xmms_ipc_msg_put_value (xmms_ipc_msg_t *msg, xmmsv_t *v)
00442 {
00443 xmmsv_type_t type;
00444
00445 type = xmmsv_get_type (v);
00446 xmms_ipc_msg_put_int32 (msg, type);
00447
00448 return xmms_ipc_msg_put_value_data (msg, v);
00449 }
00450
00451 uint32_t
00452 xmms_ipc_msg_put_value_data (xmms_ipc_msg_t *msg, xmmsv_t *v)
00453 {
00454 uint32_t ret;
00455 uint32_t u;
00456 int32_t i;
00457 const char *s;
00458 xmmsv_coll_t *c;
00459 const unsigned char *bc;
00460 unsigned int bl;
00461 xmmsv_type_t type;
00462
00463 type = xmmsv_get_type (v);
00464
00465
00466
00467
00468 switch (type) {
00469 case XMMSV_TYPE_ERROR:
00470 if (!xmmsv_get_error (v, &s)) {
00471 return -1;
00472 }
00473 ret = xmms_ipc_msg_put_error (msg, s);
00474 break;
00475 case XMMSV_TYPE_INT32:
00476 if (!xmmsv_get_int (v, &i)) {
00477 return -1;
00478 }
00479 ret = xmms_ipc_msg_put_int32 (msg, i);
00480 break;
00481 case XMMSV_TYPE_STRING:
00482 if (!xmmsv_get_string (v, &s)) {
00483 return -1;
00484 }
00485 ret = xmms_ipc_msg_put_string (msg, s);
00486 break;
00487 case XMMSV_TYPE_COLL:
00488 if (!xmmsv_get_coll (v, &c)) {
00489 return -1;
00490 }
00491 ret = xmms_ipc_msg_put_collection (msg, c);
00492 break;
00493 case XMMSV_TYPE_BIN:
00494 if (!xmmsv_get_bin (v, &bc, &bl)) {
00495 return -1;
00496 }
00497 ret = xmms_ipc_msg_put_bin (msg, bc, bl);
00498 break;
00499 case XMMSV_TYPE_LIST:
00500 ret = xmms_ipc_msg_put_value_list (msg, v);
00501 break;
00502 case XMMSV_TYPE_DICT:
00503 ret = xmms_ipc_msg_put_value_dict (msg, v);
00504 break;
00505
00506 case XMMSV_TYPE_NONE:
00507
00508
00509
00510
00511 ret = xmms_ipc_msg_get_length (msg);
00512 break;
00513 default:
00514 x_internal_error ("Tried to serialize value of unsupported type");
00515 return -1;
00516 }
00517
00518 return ret;
00519 }
00520
00521 uint32_t
00522 xmms_ipc_msg_put_value_list (xmms_ipc_msg_t *msg, xmmsv_t *v)
00523 {
00524 xmmsv_list_iter_t *it;
00525 xmmsv_t *entry;
00526 uint32_t ret, offset, count;
00527
00528 if (!xmmsv_get_list_iter (v, &it)) {
00529 return -1;
00530 }
00531
00532
00533 offset = xmms_ipc_msg_put_uint32 (msg, 0);
00534
00535 count = 0;
00536 while (xmmsv_list_iter_valid (it)) {
00537 xmmsv_list_iter_entry (it, &entry);
00538 ret = xmms_ipc_msg_put_value (msg, entry);
00539 xmmsv_list_iter_next (it);
00540 count++;
00541 }
00542
00543
00544 xmms_ipc_msg_store_uint32 (msg, offset, count);
00545
00546 return ret;
00547 }
00548
00549 uint32_t
00550 xmms_ipc_msg_put_value_dict (xmms_ipc_msg_t *msg, xmmsv_t *v)
00551 {
00552 xmmsv_dict_iter_t *it;
00553 const char *key;
00554 xmmsv_t *entry;
00555 uint32_t ret, offset, count;
00556
00557 if (!xmmsv_get_dict_iter (v, &it)) {
00558 return -1;
00559 }
00560
00561
00562 offset = xmms_ipc_msg_put_uint32 (msg, 0);
00563
00564 count = 0;
00565 while (xmmsv_dict_iter_valid (it)) {
00566 xmmsv_dict_iter_pair (it, &key, &entry);
00567 ret = xmms_ipc_msg_put_string (msg, key);
00568 ret = xmms_ipc_msg_put_value (msg, entry);
00569 xmmsv_dict_iter_next (it);
00570 count++;
00571 }
00572
00573
00574 xmms_ipc_msg_store_uint32 (msg, offset, count);
00575
00576 return ret;
00577 }
00578
00579
00580 static bool
00581 xmms_ipc_msg_get_data (xmms_ipc_msg_t *msg, void *buf, unsigned int len)
00582 {
00583 if (!msg)
00584 return false;
00585
00586 if (len > xmms_ipc_msg_get_length (msg) - msg->get_pos)
00587 return false;
00588
00589 if (buf) {
00590 memcpy (buf, &msg->data->header.data[msg->get_pos], len);
00591 }
00592
00593 msg->get_pos += len;
00594
00595 return true;
00596 }
00597
00598 bool
00599 xmms_ipc_msg_get_error_alloc (xmms_ipc_msg_t *msg, char **buf,
00600 unsigned int *len)
00601 {
00602
00603 return xmms_ipc_msg_get_string_alloc (msg, buf, len);
00604 }
00605
00606 bool
00607 xmms_ipc_msg_get_uint32 (xmms_ipc_msg_t *msg, uint32_t *v)
00608 {
00609 bool ret;
00610
00611 ret = xmms_ipc_msg_get_data (msg, v, sizeof (*v));
00612
00613 if (v) {
00614 *v = ntohl (*v);
00615 }
00616
00617 return ret;
00618 }
00619
00620 bool
00621 xmms_ipc_msg_get_int32 (xmms_ipc_msg_t *msg, int32_t *v)
00622 {
00623 bool ret;
00624
00625 ret = xmms_ipc_msg_get_data (msg, v, sizeof (*v));
00626
00627 if (v) {
00628 *v = ntohl (*v);
00629 }
00630
00631 return ret;
00632 }
00633
00634 bool
00635 xmms_ipc_msg_get_float (xmms_ipc_msg_t *msg, float *v)
00636 {
00637
00638 return xmms_ipc_msg_get_data (msg, v, sizeof (*v));
00639 }
00640
00641 bool
00642 xmms_ipc_msg_get_string_alloc (xmms_ipc_msg_t *msg, char **buf,
00643 unsigned int *len)
00644 {
00645 char *str;
00646 unsigned int l;
00647
00648 if (!xmms_ipc_msg_get_uint32 (msg, &l)) {
00649 return false;
00650 }
00651
00652 if (l > xmms_ipc_msg_get_length (msg) - msg->get_pos)
00653 return false;
00654
00655 str = x_malloc (l + 1);
00656 if (!str) {
00657 return false;
00658 }
00659
00660 if (!xmms_ipc_msg_get_data (msg, str, l)) {
00661 free (str);
00662 return false;
00663 }
00664
00665 str[l] = '\0';
00666
00667 *buf = str;
00668 *len = l;
00669
00670 return true;
00671 }
00672
00673 bool
00674 xmms_ipc_msg_get_bin_alloc (xmms_ipc_msg_t *msg,
00675 unsigned char **buf,
00676 unsigned int *len)
00677 {
00678 unsigned char *b;
00679 unsigned int l;
00680
00681 if (!xmms_ipc_msg_get_uint32 (msg, &l)) {
00682 return false;
00683 }
00684
00685 if (l > xmms_ipc_msg_get_length (msg) - msg->get_pos)
00686 return false;
00687
00688 b = x_malloc (l);
00689 if (!b) {
00690 return false;
00691 }
00692
00693 if (!xmms_ipc_msg_get_data (msg, b, l)) {
00694 free (b);
00695 return false;
00696 }
00697
00698 *buf = b;
00699 *len = l;
00700
00701 return true;
00702 }
00703
00704 bool
00705 xmms_ipc_msg_get_string (xmms_ipc_msg_t *msg, char *buf, unsigned int maxlen)
00706 {
00707 uint32_t len;
00708
00709 if (buf) {
00710 buf[maxlen - 1] = '\0';
00711 maxlen--;
00712 }
00713
00714 if (!xmms_ipc_msg_get_uint32 (msg, &len)) {
00715 return false;
00716 }
00717
00718 if (!len) {
00719 buf[0] = '\0';
00720 return true;
00721 }
00722
00723 if (!xmms_ipc_msg_get_data (msg, buf, MIN (maxlen, len))) {
00724 return false;
00725 }
00726
00727 if (maxlen < len) {
00728 xmms_ipc_msg_get_data (msg, NULL, len - maxlen);
00729 }
00730
00731 return true;
00732 }
00733
00734 bool
00735 xmms_ipc_msg_get_collection_alloc (xmms_ipc_msg_t *msg, xmmsv_coll_t **coll)
00736 {
00737 unsigned int i;
00738 unsigned int type;
00739 unsigned int n_items;
00740 unsigned int id;
00741 uint32_t *idlist = NULL;
00742 char *key, *val;
00743
00744
00745 if (!xmms_ipc_msg_get_uint32 (msg, &type)) {
00746 return false;
00747 }
00748
00749 *coll = xmmsv_coll_new (type);
00750
00751
00752 if (!xmms_ipc_msg_get_uint32 (msg, &n_items)) {
00753 goto err;
00754 }
00755
00756 for (i = 0; i < n_items; i++) {
00757 unsigned int len;
00758 if (!xmms_ipc_msg_get_string_alloc (msg, &key, &len)) {
00759 goto err;
00760 }
00761 if (!xmms_ipc_msg_get_string_alloc (msg, &val, &len)) {
00762 free (key);
00763 goto err;
00764 }
00765
00766 xmmsv_coll_attribute_set (*coll, key, val);
00767 free (key);
00768 free (val);
00769 }
00770
00771
00772 if (!xmms_ipc_msg_get_uint32 (msg, &n_items)) {
00773 goto err;
00774 }
00775
00776 if (!(idlist = x_new (uint32_t, n_items + 1))) {
00777 goto err;
00778 }
00779
00780 for (i = 0; i < n_items; i++) {
00781 if (!xmms_ipc_msg_get_uint32 (msg, &id)) {
00782 goto err;
00783 }
00784
00785 idlist[i] = id;
00786 }
00787
00788 idlist[i] = 0;
00789 xmmsv_coll_set_idlist (*coll, idlist);
00790 free (idlist);
00791 idlist = NULL;
00792
00793
00794 if (!xmms_ipc_msg_get_uint32 (msg, &n_items)) {
00795 goto err;
00796 }
00797
00798 for (i = 0; i < n_items; i++) {
00799 xmmsv_coll_t *operand;
00800
00801 if (!xmms_ipc_msg_get_collection_alloc (msg, &operand)) {
00802 goto err;
00803 }
00804
00805 xmmsv_coll_add_operand (*coll, operand);
00806 xmmsv_coll_unref (operand);
00807 }
00808
00809 return true;
00810
00811 err:
00812 if (idlist != NULL) {
00813 free (idlist);
00814 }
00815
00816 xmmsv_coll_unref (*coll);
00817
00818 return false;
00819 }
00820
00821
00822 static int
00823 xmmsc_deserialize_dict (xmms_ipc_msg_t *msg, xmmsv_t **val)
00824 {
00825 xmmsv_t *dict;
00826 unsigned int len, ignore;
00827 char *key;
00828
00829 dict = xmmsv_new_dict ();
00830
00831 if (!xmms_ipc_msg_get_uint32 (msg, &len)) {
00832 goto err;
00833 }
00834
00835 while (len--) {
00836 xmmsv_t *v;
00837
00838 if (!xmms_ipc_msg_get_string_alloc (msg, &key, &ignore)) {
00839 goto err;
00840 }
00841
00842 if (!xmms_ipc_msg_get_value_alloc (msg, &v)) {
00843 goto err;
00844 }
00845
00846 xmmsv_dict_set (dict, key, v);
00847 free (key);
00848 xmmsv_unref (v);
00849 }
00850
00851 *val = dict;
00852
00853 return true;
00854
00855 err:
00856 x_internal_error ("Message from server did not parse correctly!");
00857 xmmsv_unref (dict);
00858 return false;
00859 }
00860
00861 static int
00862 xmmsc_deserialize_list (xmms_ipc_msg_t *msg, xmmsv_t **val)
00863 {
00864 xmmsv_t *list;
00865 unsigned int len;
00866
00867 list = xmmsv_new_list ();
00868
00869 if (!xmms_ipc_msg_get_uint32 (msg, &len)) {
00870 goto err;
00871 }
00872
00873 while (len--) {
00874 xmmsv_t *v;
00875 if (xmms_ipc_msg_get_value_alloc (msg, &v)) {
00876 xmmsv_list_append (list, v);
00877 } else {
00878 goto err;
00879 }
00880 xmmsv_unref (v);
00881 }
00882
00883 *val = list;
00884
00885 return true;
00886
00887 err:
00888 x_internal_error ("Message from server did not parse correctly!");
00889 xmmsv_unref (list);
00890 return false;
00891 }
00892
00893
00894 bool
00895 xmms_ipc_msg_get_value_alloc (xmms_ipc_msg_t *msg, xmmsv_t **val)
00896 {
00897 int32_t type;
00898
00899 if (!xmms_ipc_msg_get_int32 (msg, (int32_t *) &type)) {
00900 return false;
00901 }
00902
00903 return xmms_ipc_msg_get_value_of_type_alloc (msg, type, val);
00904 }
00905
00906 bool
00907 xmms_ipc_msg_get_value_of_type_alloc (xmms_ipc_msg_t *msg, xmmsv_type_t type,
00908 xmmsv_t **val)
00909 {
00910 int32_t i;
00911 uint32_t len, u;
00912 char *s;
00913 xmmsv_coll_t *c;
00914 unsigned char *d;
00915
00916 switch (type) {
00917 case XMMSV_TYPE_ERROR:
00918 if (!xmms_ipc_msg_get_error_alloc (msg, &s, &len)) {
00919 return false;
00920 }
00921 *val = xmmsv_new_error (s);
00922 free (s);
00923 break;
00924 case XMMSV_TYPE_INT32:
00925 if (!xmms_ipc_msg_get_int32 (msg, &i)) {
00926 return false;
00927 }
00928 *val = xmmsv_new_int (i);
00929 break;
00930 case XMMSV_TYPE_STRING:
00931 if (!xmms_ipc_msg_get_string_alloc (msg, &s, &len)) {
00932 return false;
00933 }
00934 *val = xmmsv_new_string (s);
00935 free (s);
00936 break;
00937 case XMMSV_TYPE_DICT:
00938 if (!xmmsc_deserialize_dict (msg, val)) {
00939 return false;
00940 }
00941 break;
00942
00943 case XMMSV_TYPE_LIST :
00944 if (!xmmsc_deserialize_list (msg, val)) {
00945 return false;
00946 }
00947 break;
00948
00949 case XMMSV_TYPE_COLL:
00950 xmms_ipc_msg_get_collection_alloc (msg, &c);
00951 if (!c) {
00952 return false;
00953 }
00954 *val = xmmsv_new_coll (c);
00955 xmmsv_coll_unref (c);
00956 break;
00957
00958 case XMMSV_TYPE_BIN:
00959 if (!xmms_ipc_msg_get_bin_alloc (msg, &d, &len)) {
00960 return false;
00961 }
00962 *val = xmmsv_new_bin (d, len);
00963 free (d);
00964 break;
00965
00966 case XMMSV_TYPE_NONE:
00967 *val = xmmsv_new_none ();
00968 break;
00969 default:
00970 x_internal_error ("Got message of unknown type!");
00971 return false;
00972 }
00973
00974 return true;
00975 }