Jack2  1.9.10
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, int size)
00033 {
00034     char ext_client_name[SYNC_MAX_NAME_SIZE + 1];
00035     JackTools::RewriteName(client_name, ext_client_name);
00036     if (getenv("JACK_PROMISCUOUS_SERVER")) {
00037             snprintf(res, size, "%s/jack_%s_%d", dir, ext_client_name, which);
00038     } else {
00039             snprintf(res, size, "%s/jack_%s_%d_%d", dir, ext_client_name, JackTools::GetUID(), which);
00040     }
00041 }
00042 
00043 JackClientSocket::JackClientSocket(int socket): JackClientRequestInterface(), fSocket(socket),fTimeOut(0)
00044 {}
00045 
00046 #if defined(__sun__) || defined(sun)
00047 
00048 void JackClientSocket::SetReadTimeOut(long sec)
00049 {
00050     int flags;
00051     fTimeOut = sec;
00052 
00053     if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) {
00054                 jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_GETFL");
00055                 return;
00056         }
00057 
00058         flags |= O_NONBLOCK;
00059         if (fcntl(fSocket, F_SETFL, flags) < 0) {
00060                 jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_SETFL");
00061                 return;
00062         }
00063 }
00064 
00065 void JackClientSocket::SetWriteTimeOut(long sec)
00066 {
00067     int flags;
00068     fTimeOut = sec;
00069 
00070     if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) {
00071                 jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_GETFL");
00072                 return;
00073         }
00074 
00075         flags |= O_NONBLOCK;
00076         if (fcntl(fSocket, F_SETFL, flags) < 0) {
00077                 jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_SETFL");
00078                 return;
00079         }
00080 }
00081 
00082 #else
00083 
00084 void JackClientSocket::SetReadTimeOut(long sec)
00085 {
00086     struct timeval timout;
00087     timout.tv_sec = sec;
00088     timout.tv_usec = 0;
00089     if (setsockopt(fSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timout, sizeof(timeval)) < 0) {
00090         jack_error("SetReadTimeOut fd = %ld err = %s", fSocket, strerror(errno));
00091     }
00092 }
00093 
00094 void JackClientSocket::SetWriteTimeOut(long sec)
00095 {
00096     struct timeval timout;
00097     timout.tv_sec = sec ;
00098     timout.tv_usec = 0;
00099     if (setsockopt(fSocket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timout, sizeof(timeval)) < 0) {
00100         jack_error("SetWriteTimeOut fd = %ld err = %s", fSocket, strerror(errno));
00101     }
00102 }
00103 
00104 #endif
00105 
00106 void JackClientSocket::SetNonBlocking(bool onoff)
00107 {
00108     if (onoff) {
00109         long flags = 0;
00110         if (fcntl(fSocket, F_SETFL, flags | O_NONBLOCK) < 0) {
00111             jack_error("SetNonBlocking fd = %ld err = %s", fSocket, strerror(errno));
00112         }
00113     }
00114 }
00115 
00116 int JackClientSocket::Connect(const char* dir, const char* name, int which) // A revoir : utilisation de "which"
00117 {
00118     struct sockaddr_un addr;
00119 
00120     if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
00121         jack_error("Cannot create socket err = %s", strerror(errno));
00122         return -1;
00123     }
00124 
00125     addr.sun_family = AF_UNIX;
00126     BuildName(name, addr.sun_path, dir, which, sizeof(addr.sun_path));
00127     jack_log("JackClientSocket::Connect : addr.sun_path %s", addr.sun_path);
00128 
00129     if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
00130         jack_error("Cannot connect to server socket err = %s", strerror(errno));
00131         close(fSocket);
00132         return -1;
00133     }
00134 
00135 #ifdef __APPLE__
00136     int on = 1;
00137     if (setsockopt(fSocket, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) {
00138         jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fSocket, strerror(errno));
00139     }
00140 #endif
00141 
00142     return 0;
00143 }
00144 
00145 int JackClientSocket::Close()
00146 {
00147     jack_log("JackClientSocket::Close");
00148     if (fSocket > 0) {
00149         shutdown(fSocket, SHUT_RDWR);
00150         close(fSocket);
00151         fSocket = -1;
00152         return 0;
00153     } else {
00154         return -1;
00155     }
00156 }
00157 
00158 int JackClientSocket::Read(void* data, int len)
00159 {
00160     int res;
00161 
00162 #if defined(__sun__) || defined(sun)
00163     if (fTimeOut > 0) {
00164 
00165         struct timeval tv;
00166             fd_set fdset;
00167         ssize_t res;
00168 
00169         tv.tv_sec = fTimeOut;
00170             tv.tv_usec = 0;
00171 
00172             FD_ZERO(&fdset);
00173             FD_SET(fSocket, &fdset);
00174 
00175             do {
00176                     res = select(fSocket + 1, &fdset, NULL, NULL, &tv);
00177             } while (res < 0 && errno == EINTR);
00178 
00179             if (res < 0) {
00180                     return res;
00181         } else if (res == 0) {
00182                     return -1;
00183             }
00184     }
00185 #endif
00186 
00187     if ((res = read(fSocket, data, len)) != len) {
00188         if (errno == EWOULDBLOCK || errno == EAGAIN) {
00189             jack_error("JackClientSocket::Read time out");
00190             return 0;  // For a non blocking socket, a read failure is not considered as an error
00191         } else if (res != 0) {
00192             jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
00193             //return 0;
00194             return -1;
00195         } else {
00196             jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
00197             return -1;
00198         }
00199     } else {
00200         return 0;
00201     }
00202 }
00203 
00204 int JackClientSocket::Write(void* data, int len)
00205 {
00206     int res;
00207 
00208 #if defined(__sun__) || defined(sun)
00209     if (fTimeOut > 0) {
00210 
00211         struct timeval tv;
00212             fd_set fdset;
00213         ssize_t res;
00214 
00215         tv.tv_sec = fTimeOut;
00216             tv.tv_usec = 0;
00217 
00218             FD_ZERO(&fdset);
00219             FD_SET(fSocket, &fdset);
00220 
00221             do {
00222                     res = select(fSocket + 1, NULL, &fdset, NULL, &tv);
00223             } while (res < 0 && errno == EINTR);
00224 
00225             if (res < 0) {
00226                     return res;
00227         } else if (res == 0) {
00228                    return -1;
00229             }
00230    }
00231 #endif
00232 
00233     if ((res = write(fSocket, data, len)) != len) {
00234         if (errno == EWOULDBLOCK || errno == EAGAIN) {
00235             jack_log("JackClientSocket::Write time out");
00236             return 0;  // For a non blocking socket, a write failure is not considered as an error
00237         } else if (res != 0) {
00238             jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
00239             //return 0;
00240             return -1;
00241         } else {
00242             jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
00243             return -1;
00244         }
00245     } else {
00246         return 0;
00247     }
00248 }
00249 
00250 int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which"
00251 {
00252     struct sockaddr_un addr;
00253 
00254     if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
00255         jack_error("Cannot create server socket err = %s", strerror(errno));
00256         return -1;
00257     }
00258 
00259     addr.sun_family = AF_UNIX;
00260     // Socket name has to be kept in fName to be "unlinked".
00261     BuildName(name, fName, dir, which, sizeof(addr.sun_path));
00262     strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1);
00263    
00264     jack_log("JackServerSocket::Bind : addr.sun_path %s", addr.sun_path);
00265     unlink(fName); // Security...
00266 
00267     if (bind(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
00268         jack_error("Cannot bind server to socket err = %s", strerror(errno));
00269         goto error;
00270     }
00271 
00272     if (listen(fSocket, 100) < 0) {
00273         jack_error("Cannot enable listen on server socket err = %s", strerror(errno));
00274         goto error;
00275     }
00276 
00277     return 0;
00278 
00279 error:
00280     unlink(fName);
00281     close(fSocket);
00282     return -1;
00283 }
00284 
00285 JackClientSocket* JackServerSocket::Accept()
00286 {
00287     struct sockaddr_un client_addr;
00288     socklen_t client_addrlen;
00289 
00290     memset(&client_addr, 0, sizeof(client_addr));
00291     client_addrlen = sizeof(client_addr);
00292 
00293     int fd = accept(fSocket, (struct sockaddr*)&client_addr, &client_addrlen);
00294     if (fd < 0) {
00295         jack_error("Cannot accept new connection err = %s", strerror(errno));
00296         return 0;
00297     } else {
00298         return new JackClientSocket(fd);
00299     }
00300 }
00301 
00302 int JackServerSocket::Close()
00303 {
00304     if (fSocket > 0) {
00305         jack_log("JackServerSocket::Close %s", fName);
00306         shutdown(fSocket, SHUT_RDWR);
00307         close(fSocket);
00308         unlink(fName);
00309         fSocket = -1;
00310         return 0;
00311     } else {
00312         return -1;
00313     }
00314 }
00315 
00316 } // end of namespace
00317 
00318