XMMS2
|
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 00018 #include <stdio.h> 00019 #include <string.h> 00020 #include <stdlib.h> 00021 #include <signal.h> 00022 #include <assert.h> 00023 00024 #include "xmmsc/xmmsc_ipc_transport.h" 00025 #include "xmmsc/xmmsc_util.h" 00026 #include "xmmsc/xmmsc_sockets.h" 00027 #include "xmmsc/xmmsc_unistd.h" 00028 #include "url.h" 00029 #include "socket_tcp.h" 00030 00031 static void 00032 xmms_ipc_tcp_destroy (xmms_ipc_transport_t *ipct) 00033 { 00034 free (ipct->path); 00035 close (ipct->fd); 00036 } 00037 00038 static int 00039 xmms_ipc_tcp_read (xmms_ipc_transport_t *ipct, char *buffer, int len) 00040 { 00041 xmms_socket_t fd; 00042 int ret; 00043 x_return_val_if_fail (ipct, -1); 00044 x_return_val_if_fail (buffer, -1); 00045 00046 fd = ipct->fd; 00047 00048 ret = recv (fd, buffer, len, 0); 00049 00050 return ret; 00051 } 00052 00053 static int 00054 xmms_ipc_tcp_write (xmms_ipc_transport_t *ipct, char *buffer, int len) 00055 { 00056 xmms_socket_t fd; 00057 x_return_val_if_fail (ipct, -1); 00058 x_return_val_if_fail (buffer, -1); 00059 00060 fd = ipct->fd; 00061 00062 return send (fd, buffer, len, 0); 00063 00064 } 00065 00066 xmms_ipc_transport_t * 00067 xmms_ipc_tcp_client_init (const xmms_url_t *url, int ipv6) 00068 { 00069 xmms_socket_t fd = -1; 00070 xmms_ipc_transport_t *ipct; 00071 struct addrinfo hints; 00072 struct addrinfo *addrinfo; 00073 struct addrinfo *addrinfos; 00074 int gai_errno; 00075 00076 if (!xmms_sockets_initialize ()) { 00077 return NULL; 00078 } 00079 00080 memset (&hints, 0, sizeof (hints)); 00081 hints.ai_flags = 0; 00082 hints.ai_family = url->host[0] ? (ipv6 ? PF_INET6 : PF_INET) : PF_UNSPEC; 00083 hints.ai_socktype = SOCK_STREAM; 00084 hints.ai_protocol = 0; 00085 00086 if ((gai_errno = xmms_getaddrinfo (url->host[0] ? url->host : NULL, url->port[0] ? url->port : XMMS_STRINGIFY (XMMS_DEFAULT_TCP_PORT), &hints, &addrinfos))) { 00087 return NULL; 00088 } 00089 00090 for (addrinfo = addrinfos; addrinfo; addrinfo = addrinfo->ai_next) { 00091 int _reuseaddr = 1; 00092 const char* reuseaddr = (const char*)&_reuseaddr; 00093 00094 fd = socket (addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); 00095 if (!xmms_socket_valid (fd)) { 00096 return NULL; 00097 } 00098 00099 setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, reuseaddr, sizeof (_reuseaddr)); 00100 00101 if (connect (fd, addrinfo->ai_addr, addrinfo->ai_addrlen) == 0) { 00102 break; 00103 } 00104 00105 close (fd); 00106 } 00107 00108 xmms_freeaddrinfo (addrinfos); 00109 00110 if (!addrinfo) { 00111 return NULL; 00112 } 00113 00114 assert (fd != -1); 00115 00116 if (!xmms_socket_set_nonblock (fd)) { 00117 close (fd); 00118 return NULL; 00119 } 00120 00121 ipct = x_new0 (xmms_ipc_transport_t, 1); 00122 ipct->fd = fd; 00123 ipct->path = strdup (url->host); 00124 ipct->read_func = xmms_ipc_tcp_read; 00125 ipct->write_func = xmms_ipc_tcp_write; 00126 ipct->destroy_func = xmms_ipc_tcp_destroy; 00127 00128 return ipct; 00129 } 00130 00131 static xmms_ipc_transport_t * 00132 xmms_ipc_tcp_accept (xmms_ipc_transport_t *transport) 00133 { 00134 xmms_socket_t fd; 00135 struct sockaddr sockaddr; 00136 socklen_t socklen; 00137 00138 x_return_val_if_fail (transport, NULL); 00139 00140 socklen = sizeof (sockaddr); 00141 00142 fd = accept (transport->fd, &sockaddr, &socklen); 00143 if (xmms_socket_valid (fd)) { 00144 int _reuseaddr = 1; 00145 int _nodelay = 1; 00146 const char* reuseaddr = (const char*)&_reuseaddr; 00147 const char* nodelay = (const char*)&_nodelay; 00148 xmms_ipc_transport_t *ret; 00149 00150 if (!xmms_socket_set_nonblock (fd)) { 00151 close (fd); 00152 return NULL; 00153 } 00154 00155 setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, reuseaddr, sizeof (_reuseaddr)); 00156 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, nodelay, sizeof (_nodelay)); 00157 00158 ret = x_new0 (xmms_ipc_transport_t, 1); 00159 ret->fd = fd; 00160 ret->read_func = xmms_ipc_tcp_read; 00161 ret->write_func = xmms_ipc_tcp_write; 00162 ret->destroy_func = xmms_ipc_tcp_destroy; 00163 00164 return ret; 00165 } 00166 00167 return NULL; 00168 } 00169 00170 xmms_ipc_transport_t * 00171 xmms_ipc_tcp_server_init (const xmms_url_t *url, int ipv6) 00172 { 00173 xmms_socket_t fd = -1; 00174 xmms_ipc_transport_t *ipct; 00175 struct addrinfo hints; 00176 struct addrinfo *addrinfo; 00177 struct addrinfo *addrinfos; 00178 int gai_errno; 00179 00180 if (!xmms_sockets_initialize ()) { 00181 return NULL; 00182 } 00183 00184 memset (&hints, 0, sizeof (hints)); 00185 hints.ai_flags = AI_PASSIVE; 00186 hints.ai_family = url->host[0] ? (ipv6 ? PF_INET6 : PF_INET) : PF_UNSPEC; 00187 hints.ai_socktype = SOCK_STREAM; 00188 hints.ai_protocol = 0; 00189 00190 if ((gai_errno = xmms_getaddrinfo (url->host[0] ? url->host : NULL, url->port[0] ? url->port : XMMS_STRINGIFY (XMMS_DEFAULT_TCP_PORT), &hints, &addrinfos))) { 00191 return NULL; 00192 } 00193 00194 for (addrinfo = addrinfos; addrinfo; addrinfo = addrinfo->ai_next) { 00195 int _reuseaddr = 1; 00196 int _nodelay = 1; 00197 const char* reuseaddr = (const char*)&_reuseaddr; 00198 const char* nodelay = (const char*)&_nodelay; 00199 00200 fd = socket (addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); 00201 if (!xmms_socket_valid (fd)) { 00202 return NULL; 00203 } 00204 00205 setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, reuseaddr, sizeof (_reuseaddr)); 00206 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, nodelay, sizeof (_nodelay)); 00207 00208 if (bind (fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != SOCKET_ERROR && 00209 listen (fd, SOMAXCONN) != SOCKET_ERROR) { 00210 break; 00211 } 00212 close (fd); 00213 } 00214 00215 xmms_freeaddrinfo (addrinfos); 00216 00217 if (!addrinfo) { 00218 return NULL; 00219 } 00220 00221 assert (fd != -1); 00222 00223 if (!xmms_socket_set_nonblock (fd)) { 00224 close (fd); 00225 return NULL; 00226 } 00227 00228 ipct = x_new0 (xmms_ipc_transport_t, 1); 00229 ipct->fd = fd; 00230 ipct->path = strdup (url->host); 00231 ipct->read_func = xmms_ipc_tcp_read; 00232 ipct->write_func = xmms_ipc_tcp_write; 00233 ipct->accept_func = xmms_ipc_tcp_accept; 00234 ipct->destroy_func = xmms_ipc_tcp_destroy; 00235 00236 return ipct; 00237 } 00238