Jack2 1.9.8

JackSocket.cpp

00001 /*
00002 Copyright (C) 2004-2008 Grame
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as published by
00006 the Free Software Foundation; either version 2.1 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 
00018 */
00019 
00020 #include "JackSocket.h"
00021 #include "JackConstants.h"
00022 #include "JackTools.h"
00023 #include "JackError.h"
00024 #include <string.h>
00025 #include <stdio.h>
00026 #include <pthread.h>
00027 #include <fcntl.h>
00028 
00029 namespace Jack
00030 {
00031 
00032 static void BuildName(const char* client_name, char* res, const char* dir, int which)
00033 {
00034     char ext_client_name[JACK_CLIENT_NAME_SIZE + 1];
00035     JackTools::RewriteName(client_name, ext_client_name);
00036     sprintf(res, "%s/jack_%s_%d_%d", dir, ext_client_name, JackTools::GetUID(), which);
00037 }
00038 
00039 JackClientSocket::JackClientSocket(int socket): fSocket(socket),fTimeOut(0)
00040 {}
00041 
00042 #if defined(__sun__) || defined(sun)
00043 
00044 void JackClientSocket::SetReadTimeOut(long sec)
00045 {
00046     int flags;
00047     fTimeOut = sec;
00048 
00049     if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) {
00050                 jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_GETFL");
00051                 return;
00052         }
00053 
00054         flags |= O_NONBLOCK;
00055         if (fcntl(fSocket, F_SETFL, flags) < 0) {
00056                 jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_SETFL");
00057                 return;
00058         }
00059 }
00060 
00061 void JackClientSocket::SetWriteTimeOut(long sec)
00062 {
00063     int flags;
00064     fTimeOut = sec;
00065 
00066     if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) {
00067                 jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_GETFL");
00068                 return;
00069         }
00070 
00071         flags |= O_NONBLOCK;
00072         if (fcntl(fSocket, F_SETFL, flags) < 0) {
00073                 jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_SETFL");
00074                 return;
00075         }
00076 }
00077 
00078 #else
00079 
00080 void JackClientSocket::SetReadTimeOut(long sec)
00081 {
00082     struct timeval timout;
00083     timout.tv_sec = sec;
00084     timout.tv_usec = 0;
00085     if (setsockopt(fSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timout, sizeof(timeval)) < 0) {
00086         jack_error("SetReadTimeOut fd = %ld err = %s", fSocket, strerror(errno));
00087     }
00088 }
00089 
00090 void JackClientSocket::SetWriteTimeOut(long sec)
00091 {
00092     struct timeval timout;
00093     timout.tv_sec = sec ;
00094     timout.tv_usec = 0;
00095     if (setsockopt(fSocket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timout, sizeof(timeval)) < 0) {
00096         jack_error("SetWriteTimeOut fd = %ld err = %s", fSocket, strerror(errno));
00097     }
00098 }
00099 
00100 #endif
00101 
00102 void JackClientSocket::SetNonBlocking(bool onoff)
00103 {
00104     if (onoff) {
00105         long flags = 0;
00106         if (fcntl(fSocket, F_SETFL, flags | O_NONBLOCK) < 0) {
00107             jack_error("SetNonBlocking fd = %ld err = %s", fSocket, strerror(errno));
00108         }
00109     }
00110 }
00111 
00112 int JackClientSocket::Connect(const char* dir, const char* name, int which) // A revoir : utilisation de "which"
00113 {
00114     struct sockaddr_un addr;
00115 
00116     if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
00117         jack_error("Cannot create socket err = %s", strerror(errno));
00118         return -1;
00119     }
00120 
00121     addr.sun_family = AF_UNIX;
00122     BuildName(name, addr.sun_path, dir, which);
00123     jack_log("Connect: addr.sun_path %s", addr.sun_path);
00124 
00125     if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
00126         jack_error("Cannot connect to server socket err = %s", strerror(errno));
00127         close(fSocket);
00128         return -1;
00129     }
00130 
00131 #ifdef __APPLE__
00132     int on = 1;
00133     if (setsockopt(fSocket, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) {
00134         jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fSocket, strerror(errno));
00135     }
00136 #endif
00137 
00138     return 0;
00139 }
00140 
00141 int JackClientSocket::Close()
00142 {
00143     jack_log("JackClientSocket::Close");
00144     if (fSocket > 0) {
00145         shutdown(fSocket, SHUT_RDWR);
00146         close(fSocket);
00147         fSocket = -1;
00148         return 0;
00149     } else {
00150         return -1;
00151     }
00152 }
00153 
00154 int JackClientSocket::Read(void* data, int len)
00155 {
00156     int res;
00157 
00158 #if defined(__sun__) || defined(sun)
00159     if (fTimeOut > 0) {
00160 
00161         struct timeval tv;
00162             fd_set fdset;
00163         ssize_t res;
00164 
00165         tv.tv_sec = fTimeOut;
00166             tv.tv_usec = 0;
00167 
00168             FD_ZERO(&fdset);
00169             FD_SET(fSocket, &fdset);
00170 
00171             do {
00172                     res = select(fSocket + 1, &fdset, NULL, NULL, &tv);
00173             } while (res < 0 && errno == EINTR);
00174 
00175             if (res < 0) {
00176                     return res;
00177         } else if (res == 0) {
00178                     return -1;
00179             }
00180     }
00181 #endif
00182 
00183     if ((res = read(fSocket, data, len)) != len) {
00184         if (errno == EWOULDBLOCK || errno == EAGAIN) {
00185             jack_error("JackClientSocket::Read time out");
00186             return 0;  // For a non blocking socket, a read failure is not considered as an error
00187         } else if (res != 0) {
00188             jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
00189             return 0;
00190         } else {
00191             jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
00192             return -1;
00193         }
00194     } else {
00195         return 0;
00196     }
00197 }
00198 
00199 int JackClientSocket::Write(void* data, int len)
00200 {
00201     int res;
00202 
00203 #if defined(__sun__) || defined(sun)
00204     if (fTimeOut > 0) {
00205 
00206         struct timeval tv;
00207             fd_set fdset;
00208         ssize_t res;
00209 
00210         tv.tv_sec = fTimeOut;
00211             tv.tv_usec = 0;
00212 
00213             FD_ZERO(&fdset);
00214             FD_SET(fSocket, &fdset);
00215 
00216             do {
00217                     res = select(fSocket + 1, NULL, &fdset, NULL, &tv);
00218             } while (res < 0 && errno == EINTR);
00219 
00220             if (res < 0) {
00221                     return res;
00222         } else if (res == 0) {
00223                    return -1;
00224             }
00225    }
00226 #endif
00227 
00228     if ((res = write(fSocket, data, len)) != len) {
00229         if (errno == EWOULDBLOCK || errno == EAGAIN) {
00230             jack_log("JackClientSocket::Write time out");
00231             return 0;  // For a non blocking socket, a write failure is not considered as an error
00232         } else if (res != 0) {
00233             jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
00234             return 0;
00235         } else {
00236             jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
00237             return -1;
00238         }
00239     } else {
00240         return 0;
00241     }
00242 }
00243 
00244 int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which"
00245 {
00246     struct sockaddr_un addr;
00247 
00248     if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
00249         jack_error("Cannot create server socket err = %s", strerror(errno));
00250         return -1;
00251     }
00252 
00253     addr.sun_family = AF_UNIX;
00254     BuildName(name, fName, dir, which);
00255     strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1);
00256 
00257     jack_log("Bind: addr.sun_path %s", addr.sun_path);
00258     unlink(fName); // Security...
00259 
00260     if (bind(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
00261         jack_error("Cannot bind server to socket err = %s", strerror(errno));
00262         goto error;
00263     }
00264 
00265     if (listen(fSocket, 100) < 0) {
00266         jack_error("Cannot enable listen on server socket err = %s", strerror(errno));
00267         goto error;
00268     }
00269 
00270     return 0;
00271 
00272 error:
00273     unlink(fName);
00274     close(fSocket);
00275     return -1;
00276 }
00277 
00278 JackClientSocket* JackServerSocket::Accept()
00279 {
00280     struct sockaddr_un client_addr;
00281     socklen_t client_addrlen;
00282 
00283     memset(&client_addr, 0, sizeof(client_addr));
00284     client_addrlen = sizeof(client_addr);
00285 
00286     int fd = accept(fSocket, (struct sockaddr*)&client_addr, &client_addrlen);
00287     if (fd < 0) {
00288         jack_error("Cannot accept new connection err = %s", strerror(errno));
00289         return 0;
00290     } else {
00291         return new JackClientSocket(fd);
00292     }
00293 }
00294 
00295 int JackServerSocket::Close()
00296 {
00297     if (fSocket > 0) {
00298         jack_log("JackServerSocket::Close %s", fName);
00299         shutdown(fSocket, SHUT_RDWR);
00300         close(fSocket);
00301         unlink(fName);
00302         fSocket = -1;
00303         return 0;
00304     } else {
00305         return -1;
00306     }
00307 }
00308 
00309 } // end of namespace
00310 
00311