XMMS2

src/lib/xmmsipc/socket_unix.c

Go to the documentation of this file.
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 <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