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