00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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