Jack2
1.9.10
|
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