Jack2  1.9.8
JackSocketServerChannel.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 "JackSocketServerChannel.h"
21 #include "JackRequest.h"
22 #include "JackServer.h"
23 #include "JackLockedEngine.h"
24 #include "JackGlobals.h"
25 #include "JackServerGlobals.h"
26 #include "JackClient.h"
27 #include "JackTools.h"
28 #include "JackNotification.h"
29 #include "JackException.h"
30 
31 #include <assert.h>
32 #include <signal.h>
33 
34 using namespace std;
35 
36 namespace Jack
37 {
38 
39 JackSocketServerChannel::JackSocketServerChannel():
40  fThread(this)
41 {
42  fPollTable = NULL;
43  fRebuild = true;
44 }
45 
46 JackSocketServerChannel::~JackSocketServerChannel()
47 {
48  delete[] fPollTable;
49 }
50 
51 int JackSocketServerChannel::Open(const char* server_name, JackServer* server)
52 {
53  jack_log("JackSocketServerChannel::Open");
54 
55  // Prepare request socket
56  if (fRequestListenSocket.Bind(jack_server_dir, server_name, 0) < 0) {
57  jack_log("JackSocketServerChannel::Open : cannot create result listen socket");
58  return -1;
59  }
60 
61  // Prepare for poll
62  BuildPoolTable();
63  fServer = server;
64  return 0;
65 }
66 
67 void JackSocketServerChannel::Close()
68 {
69  fRequestListenSocket.Close();
70 
71  // Close remaining client sockets
72  std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
73  for (it = fSocketTable.begin(); it != fSocketTable.end(); it++) {
74  pair<int, JackClientSocket*> elem = (*it).second;
75  JackClientSocket* socket = elem.second;
76  assert(socket);
77  socket->Close();
78  delete socket;
79  }
80 }
81 
82 int JackSocketServerChannel::Start()
83 {
84  if (fThread.Start() != 0) {
85  jack_error("Cannot start Jack server listener");
86  return -1;
87  } else {
88  return 0;
89  }
90 }
91 
92 void JackSocketServerChannel::Stop()
93 {
94  fThread.Kill();
95 }
96 
97 void JackSocketServerChannel::ClientCreate()
98 {
99  jack_log("JackSocketServerChannel::ClientCreate socket");
100  JackClientSocket* socket = fRequestListenSocket.Accept();
101  if (socket) {
102  fSocketTable[socket->GetFd()] = make_pair( -1, socket);
103  fRebuild = true;
104  } else {
105  jack_error("Client socket cannot be created");
106  }
107 }
108 
109 void JackSocketServerChannel::ClientAdd(int fd, char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
110 {
111  jack_log("JackSocketServerChannel::ClientAdd");
112  int refnum = -1;
113  *result = fServer->GetEngine()->ClientExternalOpen(name, pid, uuid, &refnum, shared_engine, shared_client, shared_graph);
114  if (*result == 0) {
115  fSocketTable[fd].first = refnum;
116  fRebuild = true;
117  #ifdef __APPLE__
118  int on = 1;
119  if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) {
120  jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fd, strerror(errno));
121  }
122  #endif
123  } else {
124  jack_error("Cannot create new client");
125  }
126 }
127 
128 void JackSocketServerChannel::ClientRemove(int fd, int refnum)
129 {
130  pair<int, JackClientSocket*> elem = fSocketTable[fd];
131  JackClientSocket* socket = elem.second;
132  assert(socket);
133  jack_log("JackSocketServerChannel::ClientRemove ref = %d", refnum);
134  fSocketTable.erase(fd);
135  socket->Close();
136  delete socket;
137  fRebuild = true;
138 }
139 
140 void JackSocketServerChannel::ClientKill(int fd)
141 {
142  pair<int, JackClientSocket*> elem = fSocketTable[fd];
143  JackClientSocket* socket = elem.second;
144  int refnum = elem.first;
145 
146  assert(socket);
147  jack_log("JackSocketServerChannel::ClientKill ref = %d", refnum);
148 
149  if (refnum == -1) { // Should never happen... correspond to a client that started the socket but never opened...
150  jack_log("Client was not opened : probably correspond to server_check");
151  } else {
152  fServer->ClientKill(refnum);
153  }
154 
155  fSocketTable.erase(fd);
156  socket->Close();
157  delete socket;
158  fRebuild = true;
159 }
160 
161 bool JackSocketServerChannel::HandleRequest(int fd)
162 {
163  pair<int, JackClientSocket*> elem = fSocketTable[fd];
164  JackClientSocket* socket = elem.second;
165  assert(socket);
166 
167  // Read header
168  JackRequest header;
169  if (header.Read(socket) < 0) {
170  jack_log("HandleRequest: cannot read header");
171  ClientKill(fd);
172  return false;
173  }
174 
175  if (fd == JackServerGlobals::fRTNotificationSocket && header.fType != JackRequest::kNotification) {
176  jack_error("fRTNotificationSocket = %d", JackServerGlobals::fRTNotificationSocket);
177  jack_error("JackSocketServerChannel::HandleRequest : incorrect notification !!");
178  return true;
179  }
180 
181  // Read data
182  switch (header.fType) {
183 
184  case JackRequest::kClientCheck: {
185  jack_log("JackRequest::ClientCheck");
186  JackClientCheckRequest req;
187  JackClientCheckResult res;
188  if (req.Read(socket) == 0)
189  res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus);
190  if (res.Write(socket) < 0)
191  jack_error("JackRequest::ClientCheck write error name = %s", req.fName);
192  // Atomic ClientCheck followed by ClientOpen on same socket
193  if (req.fOpen)
194  HandleRequest(fd);
195  break;
196  }
197 
198  case JackRequest::kClientOpen: {
199  jack_log("JackRequest::ClientOpen");
200  JackClientOpenRequest req;
201  JackClientOpenResult res;
202  if (req.Read(socket) == 0)
203  ClientAdd(fd, req.fName, req.fPID, req.fUUID, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult);
204  if (res.Write(socket) < 0)
205  jack_error("JackRequest::ClientOpen write error name = %s", req.fName);
206  break;
207  }
208 
209  case JackRequest::kClientClose: {
210  jack_log("JackRequest::ClientClose");
211  JackClientCloseRequest req;
212  JackResult res;
213  if (req.Read(socket) == 0)
214  res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum);
215  if (res.Write(socket) < 0)
216  jack_error("JackRequest::ClientClose write error ref = %d", req.fRefNum);
217  ClientRemove(fd, req.fRefNum);
218  break;
219  }
220 
221  case JackRequest::kActivateClient: {
222  JackActivateRequest req;
223  JackResult res;
224  jack_log("JackRequest::ActivateClient");
225  if (req.Read(socket) == 0)
226  res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fIsRealTime);
227  if (res.Write(socket) < 0)
228  jack_error("JackRequest::ActivateClient write error ref = %d", req.fRefNum);
229  break;
230  }
231 
232  case JackRequest::kDeactivateClient: {
233  jack_log("JackRequest::DeactivateClient");
234  JackDeactivateRequest req;
235  JackResult res;
236  if (req.Read(socket) == 0)
237  res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum);
238  if (res.Write(socket) < 0)
239  jack_error("JackRequest::DeactivateClient write error ref = %d", req.fRefNum);
240  break;
241  }
242 
243  case JackRequest::kRegisterPort: {
244  jack_log("JackRequest::RegisterPort");
245  JackPortRegisterRequest req;
246  JackPortRegisterResult res;
247  if (req.Read(socket) == 0)
248  res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex);
249  if (res.Write(socket) < 0)
250  jack_error("JackRequest::RegisterPort write error ref = %d", req.fRefNum);
251  break;
252  }
253 
254  case JackRequest::kUnRegisterPort: {
255  jack_log("JackRequest::UnRegisterPort");
256  JackPortUnRegisterRequest req;
257  JackResult res;
258  if (req.Read(socket) == 0)
259  res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex);
260  if (res.Write(socket) < 0)
261  jack_error("JackRequest::UnRegisterPort write error ref = %d", req.fRefNum);
262  break;
263  }
264 
265  case JackRequest::kConnectNamePorts: {
266  jack_log("JackRequest::ConnectNamePorts");
267  JackPortConnectNameRequest req;
268  JackResult res;
269  if (req.Read(socket) == 0)
270  res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
271  if (res.Write(socket) < 0)
272  jack_error("JackRequest::ConnectNamePorts write error ref = %d", req.fRefNum);
273  break;
274  }
275 
276  case JackRequest::kDisconnectNamePorts: {
277  jack_log("JackRequest::DisconnectNamePorts");
278  JackPortDisconnectNameRequest req;
279  JackResult res;
280  if (req.Read(socket) == 0)
281  res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
282  if (res.Write(socket) < 0)
283  jack_error("JackRequest::DisconnectNamePorts write error ref = %d", req.fRefNum);
284  break;
285  }
286 
287  case JackRequest::kConnectPorts: {
288  jack_log("JackRequest::ConnectPorts");
289  JackPortConnectRequest req;
290  JackResult res;
291  if (req.Read(socket) == 0)
292  res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
293  if (res.Write(socket) < 0)
294  jack_error("JackRequest::ConnectPorts write error ref = %d", req.fRefNum);
295  break;
296  }
297 
298  case JackRequest::kDisconnectPorts: {
299  jack_log("JackRequest::DisconnectPorts");
300  JackPortDisconnectRequest req;
301  JackResult res;
302  if (req.Read(socket) == 0)
303  res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
304  if (res.Write(socket) < 0)
305  jack_error("JackRequest::DisconnectPorts write error ref = %d", req.fRefNum);
306  break;
307  }
308 
309  case JackRequest::kPortRename: {
310  jack_log("JackRequest::PortRename");
311  JackPortRenameRequest req;
312  JackResult res;
313  if (req.Read(socket) == 0)
314  res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName);
315  if (res.Write(socket) < 0)
316  jack_error("JackRequest::PortRename write error ref = %d", req.fRefNum);
317  break;
318  }
319 
320  case JackRequest::kSetBufferSize: {
321  jack_log("JackRequest::SetBufferSize");
322  JackSetBufferSizeRequest req;
323  JackResult res;
324  if (req.Read(socket) == 0)
325  res.fResult = fServer->SetBufferSize(req.fBufferSize);
326  if (res.Write(socket) < 0)
327  jack_error("JackRequest::SetBufferSize write error");
328  break;
329  }
330 
331  case JackRequest::kSetFreeWheel: {
332  jack_log("JackRequest::SetFreeWheel");
333  JackSetFreeWheelRequest req;
334  JackResult res;
335  if (req.Read(socket) == 0)
336  res.fResult = fServer->SetFreewheel(req.fOnOff);
337  if (res.Write(socket) < 0)
338  jack_error("JackRequest::SetFreeWheel write error");
339  break;
340  }
341 
342  case JackRequest::kComputeTotalLatencies: {
343  jack_log("JackRequest::ComputeTotalLatencies");
344  JackComputeTotalLatenciesRequest req;
345  JackResult res;
346  if (req.Read(socket) == 0)
347  res.fResult = fServer->GetEngine()->ComputeTotalLatencies();
348  if (res.Write(socket) < 0)
349  jack_error("JackRequest::ComputeTotalLatencies write error");
350  break;
351  }
352 
353  case JackRequest::kReleaseTimebase: {
354  jack_log("JackRequest::ReleaseTimebase");
355  JackReleaseTimebaseRequest req;
356  JackResult res;
357  if (req.Read(socket) == 0)
358  res.fResult = fServer->ReleaseTimebase(req.fRefNum);
359  if (res.Write(socket) < 0)
360  jack_error("JackRequest::ReleaseTimebase write error ref = %d", req.fRefNum);
361  break;
362  }
363 
364  case JackRequest::kSetTimebaseCallback: {
365  jack_log("JackRequest::SetTimebaseCallback");
366  JackSetTimebaseCallbackRequest req;
367  JackResult res;
368  if (req.Read(socket) == 0)
369  res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal);
370  if (res.Write(socket) < 0)
371  jack_error("JackRequest::SetTimebaseCallback write error ref = %d", req.fRefNum);
372  break;
373  }
374 
375  case JackRequest::kGetInternalClientName: {
376  jack_log("JackRequest::GetInternalClientName");
377  JackGetInternalClientNameRequest req;
378  JackGetInternalClientNameResult res;
379  if (req.Read(socket) == 0)
380  res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName);
381  if (res.Write(socket) < 0)
382  jack_error("JackRequest::GetInternalClientName write error ref = %d", req.fRefNum);
383  break;
384  }
385 
386  case JackRequest::kInternalClientHandle: {
387  jack_log("JackRequest::InternalClientHandle");
388  JackInternalClientHandleRequest req;
389  JackInternalClientHandleResult res;
390  if (req.Read(socket) == 0)
391  res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum);
392  if (res.Write(socket) < 0)
393  jack_error("JackRequest::InternalClientHandle write error ref = %d", req.fRefNum);
394  break;
395  }
396 
397  case JackRequest::kInternalClientLoad: {
398  jack_log("JackRequest::InternalClientLoad");
399  JackInternalClientLoadRequest req;
400  JackInternalClientLoadResult res;
401  if (req.Read(socket) == 0)
402  res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus);
403  if (res.Write(socket) < 0)
404  jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName);
405  break;
406  }
407 
408  case JackRequest::kInternalClientUnload: {
409  jack_log("JackRequest::InternalClientUnload");
410  JackInternalClientUnloadRequest req;
411  JackInternalClientUnloadResult res;
412  if (req.Read(socket) == 0)
413  res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus);
414  if (res.Write(socket) < 0)
415  jack_error("JackRequest::InternalClientUnload write error ref = %d", req.fRefNum);
416  break;
417  }
418 
419  case JackRequest::kNotification: {
420  jack_log("JackRequest::Notification");
421  JackClientNotificationRequest req;
422  if (req.Read(socket) == 0) {
423  if (req.fNotify == kQUIT) {
424  jack_log("JackRequest::Notification kQUIT");
425  throw JackQuitException();
426  } else {
427  fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
428  }
429  }
430  break;
431  }
432 
433  case JackRequest::kSessionNotify: {
434  jack_log("JackRequest::SessionNotify");
435  JackSessionNotifyRequest req;
436  if (req.Read(socket) == 0) {
437  fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket, NULL);
438  }
439  break;
440  }
441 
442  case JackRequest::kSessionReply: {
443  jack_log("JackRequest::SessionReply");
444  JackSessionReplyRequest req;
445  JackResult res;
446  if (req.Read(socket) == 0) {
447  fServer->GetEngine()->SessionReply(req.fRefNum);
448  res.fResult = 0;
449  }
450  if (res.Write(socket) < 0)
451  jack_error("JackRequest::SessionReply write error");
452  break;
453  }
454 
455  case JackRequest::kGetClientByUUID: {
456  jack_log("JackRequest::GetClientByUUID");
457  JackGetClientNameRequest req;
458  JackClientNameResult res;
459  if (req.Read(socket) == 0) {
460  fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName, &res.fResult);
461  }
462  if (res.Write(socket) < 0)
463  jack_error("JackRequest::GetClientByUUID write error");
464  break;
465  }
466 
467  case JackRequest::kGetUUIDByClient: {
468  jack_log("JackRequest::GetUUIDByClient");
469  JackGetUUIDRequest req;
470  JackUUIDResult res;
471  if (req.Read(socket) == 0) {
472  fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult);
473  }
474  if (res.Write(socket) < 0)
475  jack_error("JackRequest::GetUUIDByClient write error");
476  break;
477  }
478 
479  case JackRequest::kReserveClientName: {
480  jack_log("JackRequest::ReserveClientName");
481  JackReserveNameRequest req;
482  JackResult res;
483  if (req.Read(socket) == 0) {
484  fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID, &res.fResult);
485  }
486  if (res.Write(socket) < 0)
487  jack_error("JackRequest::ReserveClientName write error");
488  break;
489  }
490 
491  case JackRequest::kClientHasSessionCallback: {
492  jack_log("JackRequest::ClientHasSessionCallback");
493  JackClientHasSessionCallbackRequest req;
494  JackResult res;
495  if (req.Read(socket) == 0) {
496  fServer->GetEngine()->ClientHasSessionCallback(req.fName, &res.fResult);
497  }
498  if (res.Write(socket) < 0)
499  jack_error("JackRequest::ClientHasSessionCallback write error");
500  break;
501  }
502 
503  default:
504  jack_error("Unknown request %ld", header.fType);
505  break;
506  }
507 
508  return true;
509 }
510 
511 void JackSocketServerChannel::BuildPoolTable()
512 {
513  if (fRebuild) {
514  fRebuild = false;
515  delete[] fPollTable;
516  fPollTable = new pollfd[fSocketTable.size() + 1];
517 
518  jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable.size() + 1);
519 
520  // First fd is the server request socket
521  fPollTable[0].fd = fRequestListenSocket.GetFd();
522  fPollTable[0].events = POLLIN | POLLERR;
523 
524  // Next fd for clients
525  map<int, pair<int, JackClientSocket*> >::iterator it;
526  int i;
527 
528  for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) {
529  jack_log("fSocketTable i = %ld fd = %ld", i, it->first);
530  fPollTable[i].fd = it->first;
531  fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
532  }
533  }
534 }
535 
537 {
538  sigset_t set;
539  sigemptyset(&set);
540  sigaddset(&set, SIGPIPE);
541  pthread_sigmask(SIG_BLOCK, &set, 0);
542  return true;
543 }
544 
545 bool JackSocketServerChannel::Execute()
546 {
547  try {
548 
549  // Global poll
550  if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) {
551  jack_error("Engine poll failed err = %s request thread quits...", strerror(errno));
552  return false;
553  } else {
554 
555  // Poll all clients
556  for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) {
557  int fd = fPollTable[i].fd;
558  jack_log("fPollTable i = %ld fd = %ld", i, fd);
559  if (fPollTable[i].revents & ~POLLIN) {
560  jack_log("Poll client error err = %s", strerror(errno));
561  ClientKill(fd);
562  } else if (fPollTable[i].revents & POLLIN) {
563  if (!HandleRequest(fd))
564  jack_log("Could not handle external client request");
565  }
566  }
567 
568  // Check the server request socket */
569  if (fPollTable[0].revents & POLLERR)
570  jack_error("Error on server request socket err = %s", strerror(errno));
571 
572  if (fPollTable[0].revents & POLLIN)
573  ClientCreate();
574  }
575 
576  BuildPoolTable();
577  return true;
578 
579  } catch (JackQuitException& e) {
580  jack_log("JackSocketServerChannel::Execute JackQuitException");
581  return false;
582  }
583 }
584 
585 } // end of namespace
586 
587