2 Copyright (C) 2004-2008 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "JackSocket.h"
21 #include "JackConstants.h"
22 #include "JackTools.h"
23 #include "JackError.h"
24 #include "promiscuous.h"
33 static void BuildName(const char* client_name
, char* res
, const char* dir
, int which
, int size
, bool promiscuous
)
35 char ext_client_name
[SYNC_MAX_NAME_SIZE
+ 1];
36 JackTools::RewriteName(client_name
, ext_client_name
);
38 snprintf(res
, size
, "%s/jack_%s_%d", dir
, ext_client_name
, which
);
40 snprintf(res
, size
, "%s/jack_%s_%d_%d", dir
, ext_client_name
, JackTools::GetUID(), which
);
44 JackClientSocket::JackClientSocket(): JackClientRequestInterface(), fSocket(-1), fTimeOut(0)
46 const char* promiscuous
= getenv("JACK_PROMISCUOUS_SERVER");
47 fPromiscuous
= (promiscuous
!= NULL
);
48 fPromiscuousGid
= jack_group2gid(promiscuous
);
51 JackClientSocket::JackClientSocket(int socket
): JackClientRequestInterface(), fSocket(socket
),fTimeOut(0), fPromiscuous(false), fPromiscuousGid(-1)
54 #if defined(__sun__) || defined(sun)
56 void JackClientSocket::SetReadTimeOut(long sec
)
61 if ((flags
= fcntl(fSocket
, F_GETFL
, 0)) < 0) {
62 jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_GETFL");
67 if (fcntl(fSocket
, F_SETFL
, flags
) < 0) {
68 jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_SETFL");
73 void JackClientSocket::SetWriteTimeOut(long sec
)
78 if ((flags
= fcntl(fSocket
, F_GETFL
, 0)) < 0) {
79 jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_GETFL");
84 if (fcntl(fSocket
, F_SETFL
, flags
) < 0) {
85 jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_SETFL");
92 void JackClientSocket::SetReadTimeOut(long sec
)
94 struct timeval timout
;
97 if (setsockopt(fSocket
, SOL_SOCKET
, SO_RCVTIMEO
, (const char*)&timout
, sizeof(timeval
)) < 0) {
98 jack_error("SetReadTimeOut fd = %ld err = %s", fSocket
, strerror(errno
));
102 void JackClientSocket::SetWriteTimeOut(long sec
)
104 struct timeval timout
;
105 timout
.tv_sec
= sec
;
107 if (setsockopt(fSocket
, SOL_SOCKET
, SO_SNDTIMEO
, (const char*)&timout
, sizeof(timeval
)) < 0) {
108 jack_error("SetWriteTimeOut fd = %ld err = %s", fSocket
, strerror(errno
));
114 void JackClientSocket::SetNonBlocking(bool onoff
)
118 if (fcntl(fSocket
, F_SETFL
, flags
| O_NONBLOCK
) < 0) {
119 jack_error("SetNonBlocking fd = %ld err = %s", fSocket
, strerror(errno
));
124 int JackClientSocket::Connect(const char* dir
, const char* name
, int which
) // A revoir : utilisation de "which"
126 struct sockaddr_un addr
;
128 if ((fSocket
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0) {
129 jack_error("Cannot create socket err = %s", strerror(errno
));
133 addr
.sun_family
= AF_UNIX
;
134 BuildName(name
, addr
.sun_path
, dir
, which
, sizeof(addr
.sun_path
), fPromiscuous
);
135 jack_log("JackClientSocket::Connect : addr.sun_path %s", addr
.sun_path
);
137 if (connect(fSocket
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
138 jack_error("Cannot connect to server socket err = %s", strerror(errno
));
146 if (setsockopt(fSocket
, SOL_SOCKET
, SO_NOSIGPIPE
, (const char*)&on
, sizeof(on
)) < 0) {
147 jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fSocket
, strerror(errno
));
154 int JackClientSocket::Close()
156 jack_log("JackClientSocket::Close");
158 shutdown(fSocket
, SHUT_RDWR
);
167 int JackClientSocket::Read(void* data
, int len
)
171 #if defined(__sun__) || defined(sun)
178 tv
.tv_sec
= fTimeOut
;
182 FD_SET(fSocket
, &fdset
);
185 res
= select(fSocket
+ 1, &fdset
, NULL
, NULL
, &tv
);
186 } while (res
< 0 && errno
== EINTR
);
190 } else if (res
== 0) {
196 if ((res
= read(fSocket
, data
, len
)) != len
) {
197 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
) {
198 jack_error("JackClientSocket::Read time out");
199 return 0; // For a non blocking socket, a read failure is not considered as an error
200 } else if (res
!= 0) {
201 jack_error("Cannot read socket fd = %d err = %s", fSocket
, strerror(errno
));
205 jack_error("Cannot read socket fd = %d err = %s", fSocket
, strerror(errno
));
213 int JackClientSocket::Write(void* data
, int len
)
217 #if defined(__sun__) || defined(sun)
224 tv
.tv_sec
= fTimeOut
;
228 FD_SET(fSocket
, &fdset
);
231 res
= select(fSocket
+ 1, NULL
, &fdset
, NULL
, &tv
);
232 } while (res
< 0 && errno
== EINTR
);
236 } else if (res
== 0) {
242 if ((res
= write(fSocket
, data
, len
)) != len
) {
243 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
) {
244 jack_log("JackClientSocket::Write time out");
245 return 0; // For a non blocking socket, a write failure is not considered as an error
246 } else if (res
!= 0) {
247 jack_error("Cannot write socket fd = %ld err = %s", fSocket
, strerror(errno
));
251 jack_error("Cannot write socket fd = %ld err = %s", fSocket
, strerror(errno
));
259 JackServerSocket::JackServerSocket(): fSocket( -1)
261 const char* promiscuous
= getenv("JACK_PROMISCUOUS_SERVER");
262 fPromiscuous
= (promiscuous
!= NULL
);
263 fPromiscuousGid
= jack_group2gid(promiscuous
);
266 int JackServerSocket::Bind(const char* dir
, const char* name
, int which
) // A revoir : utilisation de "which"
268 struct sockaddr_un addr
;
270 if ((fSocket
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0) {
271 jack_error("Cannot create server socket err = %s", strerror(errno
));
275 addr
.sun_family
= AF_UNIX
;
276 // Socket name has to be kept in fName to be "unlinked".
277 BuildName(name
, fName
, dir
, which
, sizeof(addr
.sun_path
), fPromiscuous
);
278 strncpy(addr
.sun_path
, fName
, sizeof(addr
.sun_path
) - 1);
280 jack_log("JackServerSocket::Bind : addr.sun_path %s", addr
.sun_path
);
281 unlink(fName
); // Security...
283 if (bind(fSocket
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
284 jack_error("Cannot bind server to socket err = %s", strerror(errno
));
288 if (listen(fSocket
, 100) < 0) {
289 jack_error("Cannot enable listen on server socket err = %s", strerror(errno
));
293 if (fPromiscuous
&& (jack_promiscuous_perms(-1, fName
, fPromiscuousGid
) < 0))
305 JackClientSocket
* JackServerSocket::Accept()
307 struct sockaddr_un client_addr
;
308 socklen_t client_addrlen
;
310 memset(&client_addr
, 0, sizeof(client_addr
));
311 client_addrlen
= sizeof(client_addr
);
313 int fd
= accept(fSocket
, (struct sockaddr
*)&client_addr
, &client_addrlen
);
315 jack_error("Cannot accept new connection err = %s", strerror(errno
));
318 return new JackClientSocket(fd
);
322 int JackServerSocket::Close()
325 jack_log("JackServerSocket::Close %s", fName
);
326 shutdown(fSocket
, SHUT_RDWR
);
336 } // end of namespace