Implement session api for internal clients
[jack2.git] / posix / JackSocketServerChannel.cpp
blob50480ee75f1258f05db307faabd74a94e6889d2e
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 "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"
31 #include <assert.h>
32 #include <signal.h>
34 using namespace std;
36 namespace Jack
39 JackSocketServerChannel::JackSocketServerChannel():
40 fThread(this)
42 fPollTable = NULL;
43 fRebuild = true;
46 JackSocketServerChannel::~JackSocketServerChannel()
48 delete[] fPollTable;
51 int JackSocketServerChannel::Open(const char* server_name, JackServer* server)
53 jack_log("JackSocketServerChannel::Open");
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;
61 // Prepare for poll
62 BuildPoolTable();
63 fServer = server;
64 return 0;
67 void JackSocketServerChannel::Close()
69 fThread.Stop();
70 fRequestListenSocket.Close();
72 // Close remaining client sockets
73 std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
74 for (it = fSocketTable.begin(); it != fSocketTable.end(); it++) {
75 pair<int, JackClientSocket*> elem = (*it).second;
76 JackClientSocket* socket = elem.second;
77 assert(socket);
78 socket->Close();
79 delete socket;
83 int JackSocketServerChannel::Start()
85 if (fThread.Start() != 0) {
86 jack_error("Cannot start Jack server listener");
87 return -1;
90 return 0;
93 void JackSocketServerChannel::ClientCreate()
95 jack_log("JackSocketServerChannel::ClientCreate socket");
96 JackClientSocket* socket = fRequestListenSocket.Accept();
97 if (socket) {
98 fSocketTable[socket->GetFd()] = make_pair( -1, socket);
99 fRebuild = true;
100 } else {
101 jack_error("Client socket cannot be created");
105 void JackSocketServerChannel::ClientAdd(int fd, char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
107 jack_log("JackSocketServerChannel::ClientAdd");
108 int refnum = -1;
109 *result = fServer->GetEngine()->ClientExternalOpen(name, pid, uuid, &refnum, shared_engine, shared_client, shared_graph);
110 if (*result == 0) {
111 fSocketTable[fd].first = refnum;
112 fRebuild = true;
113 #ifdef __APPLE__
114 int on = 1;
115 if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) {
116 jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fd, strerror(errno));
118 #endif
119 } else {
120 jack_error("Cannot create new client");
124 void JackSocketServerChannel::ClientRemove(int fd, int refnum)
126 pair<int, JackClientSocket*> elem = fSocketTable[fd];
127 JackClientSocket* socket = elem.second;
128 assert(socket);
129 jack_log("JackSocketServerChannel::ClientRemove ref = %d", refnum);
130 fSocketTable.erase(fd);
131 socket->Close();
132 delete socket;
133 fRebuild = true;
136 void JackSocketServerChannel::ClientKill(int fd)
138 pair<int, JackClientSocket*> elem = fSocketTable[fd];
139 JackClientSocket* socket = elem.second;
140 int refnum = elem.first;
142 assert(socket);
143 jack_log("JackSocketServerChannel::ClientKill ref = %d", refnum);
145 if (refnum == -1) { // Should never happen... correspond to a client that started the socket but never opened...
146 jack_log("Client was not opened : probably correspond to server_check");
147 } else {
148 fServer->ClientKill(refnum);
151 fSocketTable.erase(fd);
152 socket->Close();
153 delete socket;
154 fRebuild = true;
157 bool JackSocketServerChannel::HandleRequest(int fd)
159 pair<int, JackClientSocket*> elem = fSocketTable[fd];
160 JackClientSocket* socket = elem.second;
161 assert(socket);
163 // Read header
164 JackRequest header;
165 if (header.Read(socket) < 0) {
166 jack_log("HandleRequest: cannot read header");
167 ClientKill(fd);
168 return false;
171 if (fd == JackServerGlobals::fRTNotificationSocket && header.fType != JackRequest::kNotification) {
172 jack_error("fRTNotificationSocket = %d", JackServerGlobals::fRTNotificationSocket);
173 jack_error("JackSocketServerChannel::HandleRequest : incorrect notification !!");
174 return true;
177 // Read data
178 switch (header.fType) {
180 case JackRequest::kClientCheck: {
181 jack_log("JackRequest::ClientCheck");
182 JackClientCheckRequest req;
183 JackClientCheckResult res;
184 if (req.Read(socket) == 0)
185 res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus);
186 if (res.Write(socket) < 0)
187 jack_error("JackRequest::ClientCheck write error name = %s", req.fName);
188 // Atomic ClientCheck followed by ClientOpen on same socket
189 if (req.fOpen)
190 HandleRequest(fd);
191 break;
194 case JackRequest::kClientOpen: {
195 jack_log("JackRequest::ClientOpen");
196 JackClientOpenRequest req;
197 JackClientOpenResult res;
198 if (req.Read(socket) == 0)
199 ClientAdd(fd, req.fName, req.fPID, req.fUUID, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult);
200 if (res.Write(socket) < 0)
201 jack_error("JackRequest::ClientOpen write error name = %s", req.fName);
202 break;
205 case JackRequest::kClientClose: {
206 jack_log("JackRequest::ClientClose");
207 JackClientCloseRequest req;
208 JackResult res;
209 if (req.Read(socket) == 0)
210 res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum);
211 if (res.Write(socket) < 0)
212 jack_error("JackRequest::ClientClose write error ref = %d", req.fRefNum);
213 ClientRemove(fd, req.fRefNum);
214 break;
217 case JackRequest::kActivateClient: {
218 JackActivateRequest req;
219 JackResult res;
220 jack_log("JackRequest::ActivateClient");
221 if (req.Read(socket) == 0)
222 res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fIsRealTime);
223 if (res.Write(socket) < 0)
224 jack_error("JackRequest::ActivateClient write error ref = %d", req.fRefNum);
225 break;
228 case JackRequest::kDeactivateClient: {
229 jack_log("JackRequest::DeactivateClient");
230 JackDeactivateRequest req;
231 JackResult res;
232 if (req.Read(socket) == 0)
233 res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum);
234 if (res.Write(socket) < 0)
235 jack_error("JackRequest::DeactivateClient write error ref = %d", req.fRefNum);
236 break;
239 case JackRequest::kRegisterPort: {
240 jack_log("JackRequest::RegisterPort");
241 JackPortRegisterRequest req;
242 JackPortRegisterResult res;
243 if (req.Read(socket) == 0)
244 res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex);
245 if (res.Write(socket) < 0)
246 jack_error("JackRequest::RegisterPort write error ref = %d", req.fRefNum);
247 break;
250 case JackRequest::kUnRegisterPort: {
251 jack_log("JackRequest::UnRegisterPort");
252 JackPortUnRegisterRequest req;
253 JackResult res;
254 if (req.Read(socket) == 0)
255 res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex);
256 if (res.Write(socket) < 0)
257 jack_error("JackRequest::UnRegisterPort write error ref = %d", req.fRefNum);
258 break;
261 case JackRequest::kConnectNamePorts: {
262 jack_log("JackRequest::ConnectNamePorts");
263 JackPortConnectNameRequest req;
264 JackResult res;
265 if (req.Read(socket) == 0)
266 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
267 if (res.Write(socket) < 0)
268 jack_error("JackRequest::ConnectNamePorts write error ref = %d", req.fRefNum);
269 break;
272 case JackRequest::kDisconnectNamePorts: {
273 jack_log("JackRequest::DisconnectNamePorts");
274 JackPortDisconnectNameRequest req;
275 JackResult res;
276 if (req.Read(socket) == 0)
277 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
278 if (res.Write(socket) < 0)
279 jack_error("JackRequest::DisconnectNamePorts write error ref = %d", req.fRefNum);
280 break;
283 case JackRequest::kConnectPorts: {
284 jack_log("JackRequest::ConnectPorts");
285 JackPortConnectRequest req;
286 JackResult res;
287 if (req.Read(socket) == 0)
288 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
289 if (res.Write(socket) < 0)
290 jack_error("JackRequest::ConnectPorts write error ref = %d", req.fRefNum);
291 break;
294 case JackRequest::kDisconnectPorts: {
295 jack_log("JackRequest::DisconnectPorts");
296 JackPortDisconnectRequest req;
297 JackResult res;
298 if (req.Read(socket) == 0)
299 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
300 if (res.Write(socket) < 0)
301 jack_error("JackRequest::DisconnectPorts write error ref = %d", req.fRefNum);
302 break;
305 case JackRequest::kPortRename: {
306 jack_log("JackRequest::PortRename");
307 JackPortRenameRequest req;
308 JackResult res;
309 if (req.Read(socket) == 0)
310 res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName);
311 if (res.Write(socket) < 0)
312 jack_error("JackRequest::PortRename write error ref = %d", req.fRefNum);
313 break;
316 case JackRequest::kSetBufferSize: {
317 jack_log("JackRequest::SetBufferSize");
318 JackSetBufferSizeRequest req;
319 JackResult res;
320 if (req.Read(socket) == 0)
321 res.fResult = fServer->SetBufferSize(req.fBufferSize);
322 if (res.Write(socket) < 0)
323 jack_error("JackRequest::SetBufferSize write error");
324 break;
327 case JackRequest::kSetFreeWheel: {
328 jack_log("JackRequest::SetFreeWheel");
329 JackSetFreeWheelRequest req;
330 JackResult res;
331 if (req.Read(socket) == 0)
332 res.fResult = fServer->SetFreewheel(req.fOnOff);
333 if (res.Write(socket) < 0)
334 jack_error("JackRequest::SetFreeWheel write error");
335 break;
338 case JackRequest::kComputeTotalLatencies: {
339 jack_log("JackRequest::ComputeTotalLatencies");
340 JackComputeTotalLatenciesRequest req;
341 JackResult res;
342 if (req.Read(socket) == 0)
343 res.fResult = fServer->GetEngine()->ComputeTotalLatencies();
344 if (res.Write(socket) < 0)
345 jack_error("JackRequest::ComputeTotalLatencies write error");
346 break;
349 case JackRequest::kReleaseTimebase: {
350 jack_log("JackRequest::ReleaseTimebase");
351 JackReleaseTimebaseRequest req;
352 JackResult res;
353 if (req.Read(socket) == 0)
354 res.fResult = fServer->ReleaseTimebase(req.fRefNum);
355 if (res.Write(socket) < 0)
356 jack_error("JackRequest::ReleaseTimebase write error ref = %d", req.fRefNum);
357 break;
360 case JackRequest::kSetTimebaseCallback: {
361 jack_log("JackRequest::SetTimebaseCallback");
362 JackSetTimebaseCallbackRequest req;
363 JackResult res;
364 if (req.Read(socket) == 0)
365 res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal);
366 if (res.Write(socket) < 0)
367 jack_error("JackRequest::SetTimebaseCallback write error ref = %d", req.fRefNum);
368 break;
371 case JackRequest::kGetInternalClientName: {
372 jack_log("JackRequest::GetInternalClientName");
373 JackGetInternalClientNameRequest req;
374 JackGetInternalClientNameResult res;
375 if (req.Read(socket) == 0)
376 res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName);
377 if (res.Write(socket) < 0)
378 jack_error("JackRequest::GetInternalClientName write error ref = %d", req.fRefNum);
379 break;
382 case JackRequest::kInternalClientHandle: {
383 jack_log("JackRequest::InternalClientHandle");
384 JackInternalClientHandleRequest req;
385 JackInternalClientHandleResult res;
386 if (req.Read(socket) == 0)
387 res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum);
388 if (res.Write(socket) < 0)
389 jack_error("JackRequest::InternalClientHandle write error ref = %d", req.fRefNum);
390 break;
393 case JackRequest::kInternalClientLoad: {
394 jack_log("JackRequest::InternalClientLoad");
395 JackInternalClientLoadRequest req;
396 JackInternalClientLoadResult res;
397 if (req.Read(socket) == 0)
398 res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus);
399 if (res.Write(socket) < 0)
400 jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName);
401 break;
404 case JackRequest::kInternalClientUnload: {
405 jack_log("JackRequest::InternalClientUnload");
406 JackInternalClientUnloadRequest req;
407 JackInternalClientUnloadResult res;
408 if (req.Read(socket) == 0)
409 res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus);
410 if (res.Write(socket) < 0)
411 jack_error("JackRequest::InternalClientUnload write error ref = %d", req.fRefNum);
412 break;
415 case JackRequest::kNotification: {
416 jack_log("JackRequest::Notification");
417 JackClientNotificationRequest req;
418 if (req.Read(socket) == 0) {
419 if (req.fNotify == kQUIT) {
420 jack_log("JackRequest::Notification kQUIT");
421 throw JackQuitException();
422 } else {
423 fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
426 break;
429 case JackRequest::kSessionNotify: {
430 jack_log("JackRequest::SessionNotify");
431 JackSessionNotifyRequest req;
432 if (req.Read(socket) == 0) {
433 fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket, NULL);
435 break;
438 case JackRequest::kSessionReply: {
439 jack_log("JackRequest::SessionReply");
440 JackSessionReplyRequest req;
441 JackResult res;
442 if (req.Read(socket) == 0) {
443 fServer->GetEngine()->SessionReply(req.fRefNum);
444 res.fResult = 0;
446 if (res.Write(socket) < 0)
447 jack_error("JackRequest::SessionReply write error");
448 break;
451 case JackRequest::kGetClientByUUID: {
452 jack_log("JackRequest::GetClientByUUID");
453 JackGetClientNameRequest req;
454 JackClientNameResult res;
455 if (req.Read(socket) == 0) {
456 fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName, &res.fResult);
458 if (res.Write(socket) < 0)
459 jack_error("JackRequest::GetClientByUUID write error");
460 break;
463 case JackRequest::kGetUUIDByClient: {
464 jack_log("JackRequest::GetUUIDByClient");
465 JackGetUUIDRequest req;
466 JackUUIDResult res;
467 if (req.Read(socket) == 0) {
468 fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult);
470 if (res.Write(socket) < 0)
471 jack_error("JackRequest::GetUUIDByClient write error");
472 break;
475 case JackRequest::kReserveClientName: {
476 jack_log("JackRequest::ReserveClientName");
477 JackReserveNameRequest req;
478 JackResult res;
479 if (req.Read(socket) == 0) {
480 fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID, &res.fResult);
482 if (res.Write(socket) < 0)
483 jack_error("JackRequest::ReserveClientName write error");
484 break;
487 case JackRequest::kClientHasSessionCallback: {
488 jack_log("JackRequest::ClientHasSessionCallback");
489 JackClientHasSessionCallbackRequest req;
490 JackResult res;
491 if (req.Read(socket) == 0) {
492 fServer->GetEngine()->ClientHasSessionCallback(req.fName, &res.fResult);
494 if (res.Write(socket) < 0)
495 jack_error("JackRequest::ClientHasSessionCallback write error");
496 break;
499 default:
500 jack_error("Unknown request %ld", header.fType);
501 break;
504 return true;
507 void JackSocketServerChannel::BuildPoolTable()
509 if (fRebuild) {
510 fRebuild = false;
511 delete[] fPollTable;
512 fPollTable = new pollfd[fSocketTable.size() + 1];
514 jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable.size() + 1);
516 // First fd is the server request socket
517 fPollTable[0].fd = fRequestListenSocket.GetFd();
518 fPollTable[0].events = POLLIN | POLLERR;
520 // Next fd for clients
521 map<int, pair<int, JackClientSocket*> >::iterator it;
522 int i;
524 for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) {
525 jack_log("fSocketTable i = %ld fd = %ld", i, it->first);
526 fPollTable[i].fd = it->first;
527 fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
532 bool JackSocketServerChannel::Init()
534 sigset_t set;
535 sigemptyset(&set);
536 sigaddset(&set, SIGPIPE);
537 pthread_sigmask(SIG_BLOCK, &set, 0);
538 return true;
541 bool JackSocketServerChannel::Execute()
543 try {
545 // Global poll
546 if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) {
547 jack_error("Engine poll failed err = %s request thread quits...", strerror(errno));
548 return false;
549 } else {
551 // Poll all clients
552 for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) {
553 int fd = fPollTable[i].fd;
554 jack_log("fPollTable i = %ld fd = %ld", i, fd);
555 if (fPollTable[i].revents & ~POLLIN) {
556 jack_log("Poll client error err = %s", strerror(errno));
557 ClientKill(fd);
558 } else if (fPollTable[i].revents & POLLIN) {
559 if (!HandleRequest(fd))
560 jack_log("Could not handle external client request");
564 // Check the server request socket */
565 if (fPollTable[0].revents & POLLERR)
566 jack_error("Error on server request socket err = %s", strerror(errno));
568 if (fPollTable[0].revents & POLLIN)
569 ClientCreate();
572 BuildPoolTable();
573 return true;
575 } catch (JackQuitException& e) {
576 jack_log("JackSocketServerChannel::Execute JackQuitException");
577 return false;
581 } // end of namespace