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"
39 JackSocketServerChannel::JackSocketServerChannel():
46 JackSocketServerChannel::~JackSocketServerChannel()
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");
67 void JackSocketServerChannel::Close()
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
;
83 int JackSocketServerChannel::Start()
85 if (fThread
.Start() != 0) {
86 jack_error("Cannot start Jack server listener");
93 void JackSocketServerChannel::ClientCreate()
95 jack_log("JackSocketServerChannel::ClientCreate socket");
96 JackClientSocket
* socket
= fRequestListenSocket
.Accept();
98 fSocketTable
[socket
->GetFd()] = make_pair( -1, socket
);
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");
109 *result
= fServer
->GetEngine()->ClientExternalOpen(name
, pid
, uuid
, &refnum
, shared_engine
, shared_client
, shared_graph
);
111 fSocketTable
[fd
].first
= refnum
;
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
));
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
;
129 jack_log("JackSocketServerChannel::ClientRemove ref = %d", refnum
);
130 fSocketTable
.erase(fd
);
136 void JackSocketServerChannel::ClientKill(int fd
)
138 pair
<int, JackClientSocket
*> elem
= fSocketTable
[fd
];
139 JackClientSocket
* socket
= elem
.second
;
140 int refnum
= elem
.first
;
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");
148 fServer
->ClientKill(refnum
);
151 fSocketTable
.erase(fd
);
157 bool JackSocketServerChannel::HandleRequest(int fd
)
159 pair
<int, JackClientSocket
*> elem
= fSocketTable
[fd
];
160 JackClientSocket
* socket
= elem
.second
;
165 if (header
.Read(socket
) < 0) {
166 jack_log("HandleRequest: cannot read header");
171 if (fd
== JackServerGlobals::fRTNotificationSocket
&& header
.fType
!= JackRequest::kNotification
) {
172 jack_error("fRTNotificationSocket = %d", JackServerGlobals::fRTNotificationSocket
);
173 jack_error("JackSocketServerChannel::HandleRequest : incorrect notification !!");
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
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
);
205 case JackRequest::kClientClose
: {
206 jack_log("JackRequest::ClientClose");
207 JackClientCloseRequest req
;
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
);
217 case JackRequest::kActivateClient
: {
218 JackActivateRequest req
;
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
);
228 case JackRequest::kDeactivateClient
: {
229 jack_log("JackRequest::DeactivateClient");
230 JackDeactivateRequest req
;
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
);
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
);
250 case JackRequest::kUnRegisterPort
: {
251 jack_log("JackRequest::UnRegisterPort");
252 JackPortUnRegisterRequest req
;
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
);
261 case JackRequest::kConnectNamePorts
: {
262 jack_log("JackRequest::ConnectNamePorts");
263 JackPortConnectNameRequest req
;
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
);
272 case JackRequest::kDisconnectNamePorts
: {
273 jack_log("JackRequest::DisconnectNamePorts");
274 JackPortDisconnectNameRequest req
;
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
);
283 case JackRequest::kConnectPorts
: {
284 jack_log("JackRequest::ConnectPorts");
285 JackPortConnectRequest req
;
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
);
294 case JackRequest::kDisconnectPorts
: {
295 jack_log("JackRequest::DisconnectPorts");
296 JackPortDisconnectRequest req
;
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
);
305 case JackRequest::kPortRename
: {
306 jack_log("JackRequest::PortRename");
307 JackPortRenameRequest req
;
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
);
316 case JackRequest::kSetBufferSize
: {
317 jack_log("JackRequest::SetBufferSize");
318 JackSetBufferSizeRequest req
;
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");
327 case JackRequest::kSetFreeWheel
: {
328 jack_log("JackRequest::SetFreeWheel");
329 JackSetFreeWheelRequest req
;
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");
338 case JackRequest::kComputeTotalLatencies
: {
339 jack_log("JackRequest::ComputeTotalLatencies");
340 JackComputeTotalLatenciesRequest req
;
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");
349 case JackRequest::kReleaseTimebase
: {
350 jack_log("JackRequest::ReleaseTimebase");
351 JackReleaseTimebaseRequest req
;
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
);
360 case JackRequest::kSetTimebaseCallback
: {
361 jack_log("JackRequest::SetTimebaseCallback");
362 JackSetTimebaseCallbackRequest req
;
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
);
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
);
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
);
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
);
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
);
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();
423 fServer
->Notify(req
.fRefNum
, req
.fNotify
, req
.fValue
);
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
);
438 case JackRequest::kSessionReply
: {
439 jack_log("JackRequest::SessionReply");
440 JackSessionReplyRequest req
;
442 if (req
.Read(socket
) == 0) {
443 fServer
->GetEngine()->SessionReply(req
.fRefNum
);
446 if (res
.Write(socket
) < 0)
447 jack_error("JackRequest::SessionReply write error");
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");
463 case JackRequest::kGetUUIDByClient
: {
464 jack_log("JackRequest::GetUUIDByClient");
465 JackGetUUIDRequest req
;
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");
475 case JackRequest::kReserveClientName
: {
476 jack_log("JackRequest::ReserveClientName");
477 JackReserveNameRequest req
;
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");
487 case JackRequest::kClientHasSessionCallback
: {
488 jack_log("JackRequest::ClientHasSessionCallback");
489 JackClientHasSessionCallbackRequest req
;
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");
500 jack_error("Unknown request %ld", header
.fType
);
507 void JackSocketServerChannel::BuildPoolTable()
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
;
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()
536 sigaddset(&set
, SIGPIPE
);
537 pthread_sigmask(SIG_BLOCK
, &set
, 0);
541 bool JackSocketServerChannel::Execute()
546 if ((poll(fPollTable
, fSocketTable
.size() + 1, 10000) < 0) && (errno
!= EINTR
)) {
547 jack_error("Engine poll failed err = %s request thread quits...", strerror(errno
));
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
));
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
)
575 } catch (JackQuitException
& e
) {
576 jack_log("JackSocketServerChannel::Execute JackQuitException");
581 } // end of namespace