XMMS2
|
00001 /* XMMS2 - X Music Multiplexer System 00002 * Copyright (C) 2003-2011 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 struct xmms_ipc_msg_St { 00034 xmmsv_t *bb; 00035 uint32_t xfered; 00036 }; 00037 00038 00039 00040 xmms_ipc_msg_t * 00041 xmms_ipc_msg_alloc (void) 00042 { 00043 xmms_ipc_msg_t *msg; 00044 static unsigned char empty[16] = {0,}; 00045 00046 msg = x_new0 (xmms_ipc_msg_t, 1); 00047 msg->bb = xmmsv_bitbuffer_new (); 00048 xmmsv_bitbuffer_put_data (msg->bb, empty, 16); 00049 00050 return msg; 00051 } 00052 00053 void 00054 xmms_ipc_msg_destroy (xmms_ipc_msg_t *msg) 00055 { 00056 x_return_if_fail (msg); 00057 00058 xmmsv_unref (msg->bb); 00059 free (msg); 00060 } 00061 00062 static void 00063 xmms_ipc_msg_update_length (xmmsv_t *bb) 00064 { 00065 int len; 00066 00067 len = xmmsv_bitbuffer_len (bb); 00068 00069 len /= 8; 00070 len -= XMMS_IPC_MSG_HEAD_LEN; 00071 00072 xmmsv_bitbuffer_goto (bb, 12*8); 00073 xmmsv_bitbuffer_put_bits (bb, 32, len); 00074 xmmsv_bitbuffer_end (bb); 00075 } 00076 00077 static uint32_t 00078 xmms_ipc_msg_get_length (const xmms_ipc_msg_t *msg) 00079 { 00080 int len, p; 00081 x_return_val_if_fail (msg, 0); 00082 00083 p = xmmsv_bitbuffer_pos (msg->bb); 00084 xmmsv_bitbuffer_goto (msg->bb, 12*8); 00085 xmmsv_bitbuffer_get_bits (msg->bb, 32, &len); 00086 xmmsv_bitbuffer_goto (msg->bb, p); 00087 return len; 00088 } 00089 00090 uint32_t 00091 xmms_ipc_msg_get_object (const xmms_ipc_msg_t *msg) 00092 { 00093 int obj, p; 00094 x_return_val_if_fail (msg, 0); 00095 00096 p = xmmsv_bitbuffer_pos (msg->bb); 00097 xmmsv_bitbuffer_goto (msg->bb, 0); 00098 xmmsv_bitbuffer_get_bits (msg->bb, 32, &obj); 00099 xmmsv_bitbuffer_goto (msg->bb, p); 00100 return obj; 00101 } 00102 00103 static void 00104 xmms_ipc_msg_set_object (xmms_ipc_msg_t *msg, uint32_t object) 00105 { 00106 x_return_if_fail (msg); 00107 00108 xmmsv_bitbuffer_goto (msg->bb, 0); 00109 xmmsv_bitbuffer_put_bits (msg->bb, 32, object); 00110 xmmsv_bitbuffer_end (msg->bb); 00111 } 00112 00113 uint32_t 00114 xmms_ipc_msg_get_cmd (const xmms_ipc_msg_t *msg) 00115 { 00116 int cmd, p; 00117 x_return_val_if_fail (msg, 0); 00118 00119 p = xmmsv_bitbuffer_pos (msg->bb); 00120 xmmsv_bitbuffer_goto (msg->bb, 4 * 8); 00121 xmmsv_bitbuffer_get_bits (msg->bb, 32, &cmd); 00122 xmmsv_bitbuffer_goto (msg->bb, p); 00123 return cmd; 00124 } 00125 00126 static void 00127 xmms_ipc_msg_set_cmd (xmms_ipc_msg_t *msg, uint32_t cmd) 00128 { 00129 x_return_if_fail (msg); 00130 00131 xmmsv_bitbuffer_goto (msg->bb, 4 * 8); 00132 xmmsv_bitbuffer_put_bits (msg->bb, 32, cmd); 00133 xmmsv_bitbuffer_end (msg->bb); 00134 } 00135 00136 void 00137 xmms_ipc_msg_set_cookie (xmms_ipc_msg_t *msg, uint32_t cookie) 00138 { 00139 xmmsv_bitbuffer_goto (msg->bb, 8 * 8); 00140 xmmsv_bitbuffer_put_bits (msg->bb, 32, cookie); 00141 xmmsv_bitbuffer_end (msg->bb); 00142 } 00143 00144 uint32_t 00145 xmms_ipc_msg_get_cookie (const xmms_ipc_msg_t *msg) 00146 { 00147 int cookie, p; 00148 x_return_val_if_fail (msg, 0); 00149 00150 p = xmmsv_bitbuffer_pos (msg->bb); 00151 xmmsv_bitbuffer_goto (msg->bb, 8 * 8); 00152 xmmsv_bitbuffer_get_bits (msg->bb, 32, &cookie); 00153 xmmsv_bitbuffer_goto (msg->bb, p); 00154 return cookie; 00155 } 00156 00157 xmms_ipc_msg_t * 00158 xmms_ipc_msg_new (uint32_t object, uint32_t cmd) 00159 { 00160 xmms_ipc_msg_t *msg; 00161 00162 msg = xmms_ipc_msg_alloc (); 00163 00164 xmms_ipc_msg_set_cmd (msg, cmd); 00165 xmms_ipc_msg_set_object (msg, object); 00166 00167 return msg; 00168 } 00169 00170 00171 /** 00172 * Try to write message to transport. If full message isn't written 00173 * the message will keep track of the amount of data written and not 00174 * write already written data next time. 00175 * 00176 * @returns TRUE if full message was written, FALSE otherwise. 00177 * disconnected is set if transport was disconnected 00178 */ 00179 bool 00180 xmms_ipc_msg_write_transport (xmms_ipc_msg_t *msg, 00181 xmms_ipc_transport_t *transport, 00182 bool *disconnected) 00183 { 00184 char *buf; 00185 unsigned int ret, len; 00186 00187 x_return_val_if_fail (msg, false); 00188 x_return_val_if_fail (transport, false); 00189 00190 xmmsv_bitbuffer_align (msg->bb); 00191 00192 len = xmmsv_bitbuffer_len (msg->bb) / 8; 00193 00194 x_return_val_if_fail (len > msg->xfered, true); 00195 00196 buf = (char *) (xmmsv_bitbuffer_buffer (msg->bb) + msg->xfered); 00197 ret = xmms_ipc_transport_write (transport, buf, len - msg->xfered); 00198 00199 if (ret == SOCKET_ERROR) { 00200 if (xmms_socket_error_recoverable ()) { 00201 return false; 00202 } 00203 00204 if (disconnected) { 00205 *disconnected = true; 00206 } 00207 00208 return false; 00209 } else if (!ret) { 00210 if (disconnected) { 00211 *disconnected = true; 00212 } 00213 } else { 00214 msg->xfered += ret; 00215 } 00216 00217 return (len == msg->xfered); 00218 } 00219 00220 /** 00221 * Try to read message from transport into msg. 00222 * 00223 * @returns TRUE if message is fully read. 00224 */ 00225 bool 00226 xmms_ipc_msg_read_transport (xmms_ipc_msg_t *msg, 00227 xmms_ipc_transport_t *transport, 00228 bool *disconnected) 00229 { 00230 char buf[512]; 00231 unsigned int ret, len, rlen; 00232 00233 x_return_val_if_fail (msg, false); 00234 x_return_val_if_fail (transport, false); 00235 00236 while (true) { 00237 len = XMMS_IPC_MSG_HEAD_LEN; 00238 00239 if (msg->xfered >= XMMS_IPC_MSG_HEAD_LEN) { 00240 len += xmms_ipc_msg_get_length (msg); 00241 00242 if (msg->xfered == len) { 00243 return true; 00244 } 00245 } 00246 00247 x_return_val_if_fail (msg->xfered < len, false); 00248 00249 rlen = len - msg->xfered; 00250 if (rlen > sizeof (buf)) 00251 rlen = sizeof (buf); 00252 00253 ret = xmms_ipc_transport_read (transport, buf, rlen); 00254 00255 if (ret == SOCKET_ERROR) { 00256 if (xmms_socket_error_recoverable ()) { 00257 return false; 00258 } 00259 00260 if (disconnected) { 00261 *disconnected = true; 00262 } 00263 00264 return false; 00265 } else if (ret == 0) { 00266 if (disconnected) { 00267 *disconnected = true; 00268 } 00269 00270 return false; 00271 } else { 00272 xmmsv_bitbuffer_goto (msg->bb, msg->xfered * 8); 00273 xmmsv_bitbuffer_put_data (msg->bb, (unsigned char *) buf, ret); 00274 msg->xfered += ret; 00275 xmmsv_bitbuffer_goto (msg->bb, XMMS_IPC_MSG_HEAD_LEN * 8); 00276 } 00277 } 00278 } 00279 00280 uint32_t 00281 xmms_ipc_msg_put_value (xmms_ipc_msg_t *msg, xmmsv_t *v) 00282 { 00283 if (!xmmsv_bitbuffer_serialize_value (msg->bb, v)) 00284 return false; 00285 xmms_ipc_msg_update_length (msg->bb); 00286 return xmmsv_bitbuffer_pos (msg->bb); 00287 } 00288 00289 00290 bool 00291 xmms_ipc_msg_get_value (xmms_ipc_msg_t *msg, xmmsv_t **val) 00292 { 00293 return xmmsv_bitbuffer_deserialize_value (msg->bb, val); 00294 }