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 00018 #include <stdio.h> 00019 #include <sys/types.h> 00020 #include <sys/socket.h> 00021 #include <unistd.h> 00022 #include <sys/un.h> 00023 #include <errno.h> 00024 #include <string.h> 00025 #include <fcntl.h> 00026 #include <unistd.h> 00027 #include <stdlib.h> 00028 #include <signal.h> 00029 #include <syslog.h> 00030 00031 #include "xmmsc/xmmsc_ipc_transport.h" 00032 #include "xmmsc/xmmsc_util.h" 00033 #include "url.h" 00034 #include "socket_unix.h" 00035 00036 static void 00037 xmms_ipc_usocket_destroy (xmms_ipc_transport_t *ipct) 00038 { 00039 free (ipct->path); 00040 close (ipct->fd); 00041 } 00042 00043 static int 00044 xmms_ipc_usocket_read (xmms_ipc_transport_t *ipct, char *buffer, int len) 00045 { 00046 int fd; 00047 int ret; 00048 x_return_val_if_fail (ipct, -1); 00049 x_return_val_if_fail (buffer, -1); 00050 00051 fd = ipct->fd; 00052 00053 ret = recv (fd, buffer, len, 0); 00054 00055 return ret; 00056 } 00057 00058 static int 00059 xmms_ipc_usocket_write (xmms_ipc_transport_t *ipct, char *buffer, int len) 00060 { 00061 int fd; 00062 x_return_val_if_fail (ipct, -1); 00063 x_return_val_if_fail (buffer, -1); 00064 00065 fd = ipct->fd; 00066 00067 return send (fd, buffer, len, 0); 00068 00069 } 00070 00071 xmms_ipc_transport_t * 00072 xmms_ipc_usocket_client_init (const xmms_url_t *url) 00073 { 00074 int fd; 00075 int flags; 00076 xmms_ipc_transport_t *ipct; 00077 struct sockaddr_un saddr; 00078 00079 00080 fd = socket (AF_UNIX, SOCK_STREAM, 0); 00081 if (fd == -1) { 00082 return NULL; 00083 } 00084 00085 saddr.sun_family = AF_UNIX; 00086 snprintf (saddr.sun_path, sizeof(saddr.sun_path), "/%s", url->path); 00087 00088 if (connect (fd, (struct sockaddr *) &saddr, sizeof (saddr)) == -1) { 00089 close (fd); 00090 return NULL; 00091 } 00092 00093 flags = fcntl (fd, F_GETFL, 0); 00094 00095 if (flags == -1) { 00096 close (fd); 00097 return NULL; 00098 } 00099 00100 flags |= O_NONBLOCK; 00101 00102 flags = fcntl (fd, F_SETFL, flags); 00103 if (flags == -1) { 00104 close (fd); 00105 return NULL; 00106 } 00107 00108 ipct = x_new0 (xmms_ipc_transport_t, 1); 00109 ipct->fd = fd; 00110 ipct->path = strdup (url->path); 00111 ipct->read_func = xmms_ipc_usocket_read; 00112 ipct->write_func = xmms_ipc_usocket_write; 00113 ipct->destroy_func = xmms_ipc_usocket_destroy; 00114 00115 return ipct; 00116 } 00117 00118 static xmms_ipc_transport_t * 00119 xmms_ipc_usocket_accept (xmms_ipc_transport_t *transport) 00120 { 00121 int fd; 00122 struct sockaddr_un sin; 00123 socklen_t sin_len; 00124 00125 x_return_val_if_fail (transport, NULL); 00126 00127 sin_len = sizeof (sin); 00128 00129 fd = accept (transport->fd, (struct sockaddr *)&sin, &sin_len); 00130 if (fd >= 0) { 00131 int flags; 00132 xmms_ipc_transport_t *ret; 00133 00134 flags = fcntl (fd, F_GETFL, 0); 00135 00136 if (flags == -1) { 00137 close (fd); 00138 return NULL; 00139 } 00140 00141 flags |= O_NONBLOCK; 00142 00143 flags = fcntl (fd, F_SETFL, flags); 00144 if (flags == -1) { 00145 close (fd); 00146 return NULL; 00147 } 00148 00149 00150 ret = x_new0 (xmms_ipc_transport_t, 1); 00151 ret->fd = fd; 00152 ret->read_func = xmms_ipc_usocket_read; 00153 ret->write_func = xmms_ipc_usocket_write; 00154 ret->destroy_func = xmms_ipc_usocket_destroy; 00155 00156 return ret; 00157 } 00158 00159 return NULL; 00160 } 00161 00162 xmms_ipc_transport_t * 00163 xmms_ipc_usocket_server_init (const xmms_url_t *url) 00164 { 00165 int fd; 00166 int flags; 00167 xmms_ipc_transport_t *ipct; 00168 struct sockaddr_un saddr; 00169 00170 00171 fd = socket (AF_UNIX, SOCK_STREAM, 0); 00172 if (fd == -1) { 00173 return NULL; 00174 } 00175 00176 saddr.sun_family = AF_UNIX; 00177 snprintf (saddr.sun_path, sizeof (saddr.sun_path), "/%s", url->path); 00178 00179 if (access (saddr.sun_path, F_OK) == 0) { 00180 if (connect (fd, (struct sockaddr *) &saddr, sizeof (saddr)) != -1) { 00181 /* active socket already exists! */ 00182 close (fd); 00183 return NULL; 00184 } 00185 /* remove stale socket */ 00186 unlink (saddr.sun_path); 00187 } 00188 00189 if (bind (fd, (struct sockaddr *) &saddr, sizeof (saddr)) == -1) { 00190 close (fd); 00191 return NULL; 00192 } 00193 00194 listen (fd, 5); 00195 00196 flags = fcntl (fd, F_GETFL, 0); 00197 00198 if (flags == -1) { 00199 close (fd); 00200 return NULL; 00201 } 00202 00203 flags |= O_NONBLOCK; 00204 00205 flags = fcntl (fd, F_SETFL, flags); 00206 if (flags == -1) { 00207 close (fd); 00208 return NULL; 00209 } 00210 00211 ipct = x_new0 (xmms_ipc_transport_t, 1); 00212 ipct->fd = fd; 00213 ipct->path = strdup (url->path); 00214 ipct->read_func = xmms_ipc_usocket_read; 00215 ipct->write_func = xmms_ipc_usocket_write; 00216 ipct->accept_func = xmms_ipc_usocket_accept; 00217 ipct->destroy_func = xmms_ipc_usocket_destroy; 00218 00219 return ipct; 00220 } 00221