• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

src/lib/xmmsipc/msg.c

Go to the documentation of this file.
00001 /*  XMMS2 - X Music Multiplexer System
00002  *  Copyright (C) 2003-2009 XMMS2 Team
00003  *
00004  *  PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2.1 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
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  * Try to write message to transport. If full message isn't written
00166  * the message will keep track of the amount of data written and not
00167  * write already written data next time.
00168  *
00169  * @returns TRUE if full message was written, FALSE otherwise.
00170  *               disconnected is set if transport was disconnected
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  * Try to read message from transport into msg.
00214  *
00215  * @returns TRUE if message is fully read.
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         /* Realloc data portion */
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     /* return the offset that which we placed this value.
00305      * If this logic is changed, make sure to update
00306      * the return value of xmms_ipc_msg_put_value_data for
00307      * NONE xmmsv's, too.
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     /** @todo do we need to convert ? */
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     /* push type */
00399     xmms_ipc_msg_put_uint32 (msg, xmmsv_coll_get_type (coll));
00400 
00401     /* attribute counter and values */
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     /* idlist counter and content */
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     /* operands counter and objects */
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     /* FIXME: what to do if value fetching fails? */
00466     /* FIXME: return -1 unsigned int?? */
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         /* just like the other _put_* functions, we
00508          * return the offset that which we placed this value.
00509          * See xmms_ipc_msg_put_data().
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     /* store a dummy value, store the real count once it's known */
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     /* overwrite with real size */
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     /* store a dummy value, store the real count once it's known */
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     /* overwrite with real size */
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     /* currently, an error is just a string, so reuse that */
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     /** @todo do we need to convert? */
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     /* Get the type and create the collection */
00745     if (!xmms_ipc_msg_get_uint32 (msg, &type)) {
00746         return false;
00747     }
00748 
00749     *coll = xmmsv_coll_new (type);
00750 
00751     /* Get the list of attributes */
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     /* Get the idlist */
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     /* Get the operands */
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 }

Generated on Wed Feb 9 2011 for XMMS2 by  doxygen 1.7.1