Jack2  1.9.9
JackSocket.cpp
1 /*
2 Copyright (C) 2004-2008 Grame
3 
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.
8 
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.
13 
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.
17 
18 */
19 
20 #include "JackSocket.h"
21 #include "JackConstants.h"
22 #include "JackTools.h"
23 #include "JackError.h"
24 #include <string.h>
25 #include <stdio.h>
26 #include <pthread.h>
27 #include <fcntl.h>
28 
29 namespace Jack
30 {
31 
32 static void BuildName(const char* client_name, char* res, const char* dir, int which)
33 {
34  char ext_client_name[JACK_CLIENT_NAME_SIZE + 1];
35  JackTools::RewriteName(client_name, ext_client_name);
36  sprintf(res, "%s/jack_%s_%d_%d", dir, ext_client_name, JackTools::GetUID(), which);
37 }
38 
39 JackClientSocket::JackClientSocket(int socket): JackClientRequestInterface(), fSocket(socket),fTimeOut(0)
40 {}
41 
42 #if defined(__sun__) || defined(sun)
43 
44 void JackClientSocket::SetReadTimeOut(long sec)
45 {
46  int flags;
47  fTimeOut = sec;
48 
49  if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) {
50  jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_GETFL");
51  return;
52  }
53 
54  flags |= O_NONBLOCK;
55  if (fcntl(fSocket, F_SETFL, flags) < 0) {
56  jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_SETFL");
57  return;
58  }
59 }
60 
61 void JackClientSocket::SetWriteTimeOut(long sec)
62 {
63  int flags;
64  fTimeOut = sec;
65 
66  if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) {
67  jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_GETFL");
68  return;
69  }
70 
71  flags |= O_NONBLOCK;
72  if (fcntl(fSocket, F_SETFL, flags) < 0) {
73  jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_SETFL");
74  return;
75  }
76 }
77 
78 #else
79 
80 void JackClientSocket::SetReadTimeOut(long sec)
81 {
82  struct timeval timout;
83  timout.tv_sec = sec;
84  timout.tv_usec = 0;
85  if (setsockopt(fSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timout, sizeof(timeval)) < 0) {
86  jack_error("SetReadTimeOut fd = %ld err = %s", fSocket, strerror(errno));
87  }
88 }
89 
90 void JackClientSocket::SetWriteTimeOut(long sec)
91 {
92  struct timeval timout;
93  timout.tv_sec = sec ;
94  timout.tv_usec = 0;
95  if (setsockopt(fSocket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timout, sizeof(timeval)) < 0) {
96  jack_error("SetWriteTimeOut fd = %ld err = %s", fSocket, strerror(errno));
97  }
98 }
99 
100 #endif
101 
102 void JackClientSocket::SetNonBlocking(bool onoff)
103 {
104  if (onoff) {
105  long flags = 0;
106  if (fcntl(fSocket, F_SETFL, flags | O_NONBLOCK) < 0) {
107  jack_error("SetNonBlocking fd = %ld err = %s", fSocket, strerror(errno));
108  }
109  }
110 }
111 
112 int JackClientSocket::Connect(const char* dir, const char* name, int which) // A revoir : utilisation de "which"
113 {
114  struct sockaddr_un addr;
115 
116  if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
117  jack_error("Cannot create socket err = %s", strerror(errno));
118  return -1;
119  }
120 
121  addr.sun_family = AF_UNIX;
122  BuildName(name, addr.sun_path, dir, which);
123  jack_log("JackClientSocket::Connect : addr.sun_path %s", addr.sun_path);
124 
125  if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
126  jack_error("Cannot connect to server socket err = %s", strerror(errno));
127  close(fSocket);
128  return -1;
129  }
130 
131 #ifdef __APPLE__
132  int on = 1;
133  if (setsockopt(fSocket, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) {
134  jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fSocket, strerror(errno));
135  }
136 #endif
137 
138  return 0;
139 }
140 
141 int JackClientSocket::Close()
142 {
143  jack_log("JackClientSocket::Close");
144  if (fSocket > 0) {
145  shutdown(fSocket, SHUT_RDWR);
146  close(fSocket);
147  fSocket = -1;
148  return 0;
149  } else {
150  return -1;
151  }
152 }
153 
154 int JackClientSocket::Read(void* data, int len)
155 {
156  int res;
157 
158 #if defined(__sun__) || defined(sun)
159  if (fTimeOut > 0) {
160 
161  struct timeval tv;
162  fd_set fdset;
163  ssize_t res;
164 
165  tv.tv_sec = fTimeOut;
166  tv.tv_usec = 0;
167 
168  FD_ZERO(&fdset);
169  FD_SET(fSocket, &fdset);
170 
171  do {
172  res = select(fSocket + 1, &fdset, NULL, NULL, &tv);
173  } while (res < 0 && errno == EINTR);
174 
175  if (res < 0) {
176  return res;
177  } else if (res == 0) {
178  return -1;
179  }
180  }
181 #endif
182 
183  if ((res = read(fSocket, data, len)) != len) {
184  if (errno == EWOULDBLOCK || errno == EAGAIN) {
185  jack_error("JackClientSocket::Read time out");
186  return 0; // For a non blocking socket, a read failure is not considered as an error
187  } else if (res != 0) {
188  jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
189  //return 0;
190  return -1;
191  } else {
192  jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
193  return -1;
194  }
195  } else {
196  return 0;
197  }
198 }
199 
200 int JackClientSocket::Write(void* data, int len)
201 {
202  int res;
203 
204 #if defined(__sun__) || defined(sun)
205  if (fTimeOut > 0) {
206 
207  struct timeval tv;
208  fd_set fdset;
209  ssize_t res;
210 
211  tv.tv_sec = fTimeOut;
212  tv.tv_usec = 0;
213 
214  FD_ZERO(&fdset);
215  FD_SET(fSocket, &fdset);
216 
217  do {
218  res = select(fSocket + 1, NULL, &fdset, NULL, &tv);
219  } while (res < 0 && errno == EINTR);
220 
221  if (res < 0) {
222  return res;
223  } else if (res == 0) {
224  return -1;
225  }
226  }
227 #endif
228 
229  if ((res = write(fSocket, data, len)) != len) {
230  if (errno == EWOULDBLOCK || errno == EAGAIN) {
231  jack_log("JackClientSocket::Write time out");
232  return 0; // For a non blocking socket, a write failure is not considered as an error
233  } else if (res != 0) {
234  jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
235  //return 0;
236  return -1;
237  } else {
238  jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
239  return -1;
240  }
241  } else {
242  return 0;
243  }
244 }
245 
246 int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which"
247 {
248  struct sockaddr_un addr;
249 
250  if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
251  jack_error("Cannot create server socket err = %s", strerror(errno));
252  return -1;
253  }
254 
255  addr.sun_family = AF_UNIX;
256  BuildName(name, fName, dir, which);
257  strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1);
258 
259  jack_log("JackServerSocket::Bind : addr.sun_path %s", addr.sun_path);
260  unlink(fName); // Security...
261 
262  if (bind(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
263  jack_error("Cannot bind server to socket err = %s", strerror(errno));
264  goto error;
265  }
266 
267  if (listen(fSocket, 100) < 0) {
268  jack_error("Cannot enable listen on server socket err = %s", strerror(errno));
269  goto error;
270  }
271 
272  return 0;
273 
274 error:
275  unlink(fName);
276  close(fSocket);
277  return -1;
278 }
279 
280 JackClientSocket* JackServerSocket::Accept()
281 {
282  struct sockaddr_un client_addr;
283  socklen_t client_addrlen;
284 
285  memset(&client_addr, 0, sizeof(client_addr));
286  client_addrlen = sizeof(client_addr);
287 
288  int fd = accept(fSocket, (struct sockaddr*)&client_addr, &client_addrlen);
289  if (fd < 0) {
290  jack_error("Cannot accept new connection err = %s", strerror(errno));
291  return 0;
292  } else {
293  return new JackClientSocket(fd);
294  }
295 }
296 
297 int JackServerSocket::Close()
298 {
299  if (fSocket > 0) {
300  jack_log("JackServerSocket::Close %s", fName);
301  shutdown(fSocket, SHUT_RDWR);
302  close(fSocket);
303  unlink(fName);
304  fSocket = -1;
305  return 0;
306  } else {
307  return -1;
308  }
309 }
310 
311 } // end of namespace
312 
313 
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:91
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107