Add innosetup files
[jack2.git] / posix / JackSocket.cpp
blobbe43d0116c84938ee0dbbb0e96ebffbb54b1f57c
1 /*
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"
25 #include <string.h>
26 #include <stdio.h>
27 #include <pthread.h>
28 #include <fcntl.h>
30 namespace Jack
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);
37 if (promiscuous) {
38 snprintf(res, size, "%s/jack_%s_%d", dir, ext_client_name, which);
39 } else {
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)
58 int flags;
59 fTimeOut = sec;
61 if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) {
62 jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_GETFL");
63 return;
66 flags |= O_NONBLOCK;
67 if (fcntl(fSocket, F_SETFL, flags) < 0) {
68 jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_SETFL");
69 return;
73 void JackClientSocket::SetWriteTimeOut(long sec)
75 int flags;
76 fTimeOut = sec;
78 if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) {
79 jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_GETFL");
80 return;
83 flags |= O_NONBLOCK;
84 if (fcntl(fSocket, F_SETFL, flags) < 0) {
85 jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_SETFL");
86 return;
90 #else
92 void JackClientSocket::SetReadTimeOut(long sec)
94 struct timeval timout;
95 timout.tv_sec = sec;
96 timout.tv_usec = 0;
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 ;
106 timout.tv_usec = 0;
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));
112 #endif
114 void JackClientSocket::SetNonBlocking(bool onoff)
116 if (onoff) {
117 long flags = 0;
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));
130 return -1;
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));
139 close(fSocket);
140 fSocket = -1;
141 return -1;
144 #ifdef __APPLE__
145 int on = 1;
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));
149 #endif
151 return 0;
154 int JackClientSocket::Close()
156 jack_log("JackClientSocket::Close");
157 if (fSocket > 0) {
158 shutdown(fSocket, SHUT_RDWR);
159 close(fSocket);
160 fSocket = -1;
161 return 0;
162 } else {
163 return -1;
167 int JackClientSocket::Read(void* data, int len)
169 int res;
171 #if defined(__sun__) || defined(sun)
172 if (fTimeOut > 0) {
174 struct timeval tv;
175 fd_set fdset;
176 ssize_t res;
178 tv.tv_sec = fTimeOut;
179 tv.tv_usec = 0;
181 FD_ZERO(&fdset);
182 FD_SET(fSocket, &fdset);
184 do {
185 res = select(fSocket + 1, &fdset, NULL, NULL, &tv);
186 } while (res < 0 && errno == EINTR);
188 if (res < 0) {
189 return res;
190 } else if (res == 0) {
191 return -1;
194 #endif
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));
202 //return 0;
203 return -1;
204 } else {
205 jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
206 return -1;
208 } else {
209 return 0;
213 int JackClientSocket::Write(void* data, int len)
215 int res;
217 #if defined(__sun__) || defined(sun)
218 if (fTimeOut > 0) {
220 struct timeval tv;
221 fd_set fdset;
222 ssize_t res;
224 tv.tv_sec = fTimeOut;
225 tv.tv_usec = 0;
227 FD_ZERO(&fdset);
228 FD_SET(fSocket, &fdset);
230 do {
231 res = select(fSocket + 1, NULL, &fdset, NULL, &tv);
232 } while (res < 0 && errno == EINTR);
234 if (res < 0) {
235 return res;
236 } else if (res == 0) {
237 return -1;
240 #endif
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));
248 //return 0;
249 return -1;
250 } else {
251 jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
252 return -1;
254 } else {
255 return 0;
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));
272 return -1;
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));
285 goto error;
288 if (listen(fSocket, 100) < 0) {
289 jack_error("Cannot enable listen on server socket err = %s", strerror(errno));
290 goto error;
293 if (fPromiscuous && (jack_promiscuous_perms(-1, fName, fPromiscuousGid) < 0))
294 goto error;
296 return 0;
298 error:
299 unlink(fName);
300 close(fSocket);
301 fSocket = -1;
302 return -1;
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);
314 if (fd < 0) {
315 jack_error("Cannot accept new connection err = %s", strerror(errno));
316 return 0;
317 } else {
318 return new JackClientSocket(fd);
322 int JackServerSocket::Close()
324 if (fSocket > 0) {
325 jack_log("JackServerSocket::Close %s", fName);
326 shutdown(fSocket, SHUT_RDWR);
327 close(fSocket);
328 unlink(fName);
329 fSocket = -1;
330 return 0;
331 } else {
332 return -1;
336 } // end of namespace