Jack2 1.9.6

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) {
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             return -1;
00192         }
00193     } else {
00194         return 0;
00195     }
00196 }
00197 
00198 int JackClientSocket::Write(void* data, int len)
00199 {
00200     int res;
00201 
00202 #if defined(__sun__) || defined(sun)
00203     if (fTimeOut > 0) {
00204  
00205         struct timeval tv;
00206             fd_set fdset;
00207         ssize_t res;
00208     
00209         tv.tv_sec = fTimeOut;
00210             tv.tv_usec = 0;
00211     
00212             FD_ZERO(&fdset);
00213             FD_SET(fSocket, &fdset);
00214     
00215             do {
00216                     res = select(fSocket + 1, NULL, &fdset, NULL, &tv);
00217             } while (res < 0 && errno == EINTR);
00218     
00219             if (res < 0) {
00220                     return res;
00221         } else if (res == 0) {
00222                    return -1;
00223             }
00224    }
00225 #endif
00226 
00227     if ((res = write(fSocket, data, len)) != len) {
00228         if (errno == EWOULDBLOCK) {
00229             jack_log("JackClientSocket::Write time out");
00230             return 0;  // For a non blocking socket, a write failure is not considered as an error
00231         } else if (res != 0) {
00232             jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
00233             return 0;
00234         } else {
00235             return -1;
00236         }
00237     } else {
00238         return 0;
00239     }
00240 }
00241 
00242 int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which"
00243 {
00244     struct sockaddr_un addr;
00245 
00246     if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
00247         jack_error("Cannot create server socket err = %s", strerror(errno));
00248         return -1;
00249     }
00250 
00251     addr.sun_family = AF_UNIX;
00252     BuildName(name, fName, dir, which);
00253     strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1);
00254   
00255     jack_log("Bind: addr.sun_path %s", addr.sun_path);
00256     unlink(fName); // Security...
00257 
00258     if (bind(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
00259         jack_error("Cannot bind server to socket err = %s", strerror(errno));
00260         goto error;
00261     }
00262 
00263     if (listen(fSocket, 1) < 0) {
00264         jack_error("Cannot enable listen on server socket err = %s", strerror(errno));
00265         goto error;
00266     }
00267 
00268     return 0;
00269 
00270 error:
00271     unlink(fName);
00272     close(fSocket);
00273     return -1;
00274 }
00275 
00276 JackClientSocket* JackServerSocket::Accept()
00277 {
00278     struct sockaddr_un client_addr;
00279     socklen_t client_addrlen;
00280 
00281     memset(&client_addr, 0, sizeof(client_addr));
00282     client_addrlen = sizeof(client_addr);
00283 
00284     int fd = accept(fSocket, (struct sockaddr*)&client_addr, &client_addrlen);
00285     if (fd < 0) {
00286         jack_error("Cannot accept new connection err = %s", strerror(errno));
00287         return 0;
00288     } else {
00289         return new JackClientSocket(fd);
00290     }
00291 }
00292 
00293 int JackServerSocket::Close()
00294 {
00295     if (fSocket > 0) {
00296         jack_log("JackServerSocket::Close %s", fName);
00297         shutdown(fSocket, SHUT_RDWR);
00298         close(fSocket);
00299         unlink(fName);
00300         fSocket = -1;
00301         return 0;
00302     } else {
00303         return -1;
00304     }
00305 }
00306 
00307 } // end of namespace
00308 
00309