• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

src/lib/xmmsipc/socket_tcp.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 <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 static void
00031 xmms_ipc_tcp_destroy (xmms_ipc_transport_t *ipct)
00032 {
00033     free (ipct->path);
00034     close (ipct->fd);
00035 }
00036 
00037 static 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 static 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 static 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 

Generated on Wed Feb 9 2011 for XMMS2 by  doxygen 1.7.1