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");
167 ClientKill(fd
); // TO CHECK SOLARIS
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
);
191 case JackRequest::kClientOpen
: {
192 jack_log("JackRequest::ClientOpen");
193 JackClientOpenRequest req
;
194 JackClientOpenResult res
;
195 if (req
.Read(socket
) == 0)
196 ClientAdd(fd
, req
.fName
, req
.fPID
, req
.fUUID
, &res
.fSharedEngine
, &res
.fSharedClient
, &res
.fSharedGraph
, &res
.fResult
);
197 if (res
.Write(socket
) < 0)
198 jack_error("JackRequest::ClientOpen write error name = %s", req
.fName
);
202 case JackRequest::kClientClose
: {
203 jack_log("JackRequest::ClientClose");
204 JackClientCloseRequest req
;
206 if (req
.Read(socket
) == 0)
207 res
.fResult
= fServer
->GetEngine()->ClientExternalClose(req
.fRefNum
);
208 if (res
.Write(socket
) < 0)
209 jack_error("JackRequest::ClientClose write error ref = %d", req
.fRefNum
);
210 ClientRemove(fd
, req
.fRefNum
);
214 case JackRequest::kActivateClient
: {
215 JackActivateRequest req
;
217 jack_log("JackRequest::ActivateClient");
218 if (req
.Read(socket
) == 0)
219 res
.fResult
= fServer
->GetEngine()->ClientActivate(req
.fRefNum
, req
.fIsRealTime
);
220 if (res
.Write(socket
) < 0)
221 jack_error("JackRequest::ActivateClient write error ref = %d", req
.fRefNum
);
225 case JackRequest::kDeactivateClient
: {
226 jack_log("JackRequest::DeactivateClient");
227 JackDeactivateRequest req
;
229 if (req
.Read(socket
) == 0)
230 res
.fResult
= fServer
->GetEngine()->ClientDeactivate(req
.fRefNum
);
231 if (res
.Write(socket
) < 0)
232 jack_error("JackRequest::DeactivateClient write error ref = %d", req
.fRefNum
);
236 case JackRequest::kRegisterPort
: {
237 jack_log("JackRequest::RegisterPort");
238 JackPortRegisterRequest req
;
239 JackPortRegisterResult res
;
240 if (req
.Read(socket
) == 0)
241 res
.fResult
= fServer
->GetEngine()->PortRegister(req
.fRefNum
, req
.fName
, req
.fPortType
, req
.fFlags
, req
.fBufferSize
, &res
.fPortIndex
);
242 if (res
.Write(socket
) < 0)
243 jack_error("JackRequest::RegisterPort write error ref = %d", req
.fRefNum
);
247 case JackRequest::kUnRegisterPort
: {
248 jack_log("JackRequest::UnRegisterPort");
249 JackPortUnRegisterRequest req
;
251 if (req
.Read(socket
) == 0)
252 res
.fResult
= fServer
->GetEngine()->PortUnRegister(req
.fRefNum
, req
.fPortIndex
);
253 if (res
.Write(socket
) < 0)
254 jack_error("JackRequest::UnRegisterPort write error ref = %d", req
.fRefNum
);
258 case JackRequest::kConnectNamePorts
: {
259 jack_log("JackRequest::ConnectNamePorts");
260 JackPortConnectNameRequest req
;
262 if (req
.Read(socket
) == 0)
263 res
.fResult
= fServer
->GetEngine()->PortConnect(req
.fRefNum
, req
.fSrc
, req
.fDst
);
264 if (res
.Write(socket
) < 0)
265 jack_error("JackRequest::ConnectNamePorts write error ref = %d", req
.fRefNum
);
269 case JackRequest::kDisconnectNamePorts
: {
270 jack_log("JackRequest::DisconnectNamePorts");
271 JackPortDisconnectNameRequest req
;
273 if (req
.Read(socket
) == 0)
274 res
.fResult
= fServer
->GetEngine()->PortDisconnect(req
.fRefNum
, req
.fSrc
, req
.fDst
);
275 if (res
.Write(socket
) < 0)
276 jack_error("JackRequest::DisconnectNamePorts write error ref = %d", req
.fRefNum
);
280 case JackRequest::kConnectPorts
: {
281 jack_log("JackRequest::ConnectPorts");
282 JackPortConnectRequest req
;
284 if (req
.Read(socket
) == 0)
285 res
.fResult
= fServer
->GetEngine()->PortConnect(req
.fRefNum
, req
.fSrc
, req
.fDst
);
286 if (res
.Write(socket
) < 0)
287 jack_error("JackRequest::ConnectPorts write error ref = %d", req
.fRefNum
);
291 case JackRequest::kDisconnectPorts
: {
292 jack_log("JackRequest::DisconnectPorts");
293 JackPortDisconnectRequest req
;
295 if (req
.Read(socket
) == 0)
296 res
.fResult
= fServer
->GetEngine()->PortDisconnect(req
.fRefNum
, req
.fSrc
, req
.fDst
);
297 if (res
.Write(socket
) < 0)
298 jack_error("JackRequest::DisconnectPorts write error ref = %d", req
.fRefNum
);
302 case JackRequest::kPortRename
: {
303 jack_log("JackRequest::PortRename");
304 JackPortRenameRequest req
;
306 if (req
.Read(socket
) == 0)
307 res
.fResult
= fServer
->GetEngine()->PortRename(req
.fRefNum
, req
.fPort
, req
.fName
);
308 if (res
.Write(socket
) < 0)
309 jack_error("JackRequest::PortRename write error ref = %d", req
.fRefNum
);
313 case JackRequest::kSetBufferSize
: {
314 jack_log("JackRequest::SetBufferSize");
315 JackSetBufferSizeRequest req
;
317 if (req
.Read(socket
) == 0)
318 res
.fResult
= fServer
->SetBufferSize(req
.fBufferSize
);
319 if (res
.Write(socket
) < 0)
320 jack_error("JackRequest::SetBufferSize write error");
324 case JackRequest::kSetFreeWheel
: {
325 jack_log("JackRequest::SetFreeWheel");
326 JackSetFreeWheelRequest req
;
328 if (req
.Read(socket
) == 0)
329 res
.fResult
= fServer
->SetFreewheel(req
.fOnOff
);
330 if (res
.Write(socket
) < 0)
331 jack_error("JackRequest::SetFreeWheel write error");
335 case JackRequest::kComputeTotalLatencies
: {
336 jack_log("JackRequest::ComputeTotalLatencies");
337 JackComputeTotalLatenciesRequest req
;
339 if (req
.Read(socket
) == 0)
340 res
.fResult
= fServer
->GetEngine()->ComputeTotalLatencies();
341 if (res
.Write(socket
) < 0)
342 jack_error("JackRequest::ComputeTotalLatencies write error");
346 case JackRequest::kReleaseTimebase
: {
347 jack_log("JackRequest::ReleaseTimebase");
348 JackReleaseTimebaseRequest req
;
350 if (req
.Read(socket
) == 0)
351 res
.fResult
= fServer
->ReleaseTimebase(req
.fRefNum
);
352 if (res
.Write(socket
) < 0)
353 jack_error("JackRequest::ReleaseTimebase write error ref = %d", req
.fRefNum
);
357 case JackRequest::kSetTimebaseCallback
: {
358 jack_log("JackRequest::SetTimebaseCallback");
359 JackSetTimebaseCallbackRequest req
;
361 if (req
.Read(socket
) == 0)
362 res
.fResult
= fServer
->SetTimebaseCallback(req
.fRefNum
, req
.fConditionnal
);
363 if (res
.Write(socket
) < 0)
364 jack_error("JackRequest::SetTimebaseCallback write error ref = %d", req
.fRefNum
);
368 case JackRequest::kGetInternalClientName
: {
369 jack_log("JackRequest::GetInternalClientName");
370 JackGetInternalClientNameRequest req
;
371 JackGetInternalClientNameResult res
;
372 if (req
.Read(socket
) == 0)
373 res
.fResult
= fServer
->GetEngine()->GetInternalClientName(req
.fIntRefNum
, res
.fName
);
374 if (res
.Write(socket
) < 0)
375 jack_error("JackRequest::GetInternalClientName write error ref = %d", req
.fRefNum
);
379 case JackRequest::kInternalClientHandle
: {
380 jack_log("JackRequest::InternalClientHandle");
381 JackInternalClientHandleRequest req
;
382 JackInternalClientHandleResult res
;
383 if (req
.Read(socket
) == 0)
384 res
.fResult
= fServer
->GetEngine()->InternalClientHandle(req
.fName
, &res
.fStatus
, &res
.fIntRefNum
);
385 if (res
.Write(socket
) < 0)
386 jack_error("JackRequest::InternalClientHandle write error ref = %d", req
.fRefNum
);
390 case JackRequest::kInternalClientLoad
: {
391 jack_log("JackRequest::InternalClientLoad");
392 JackInternalClientLoadRequest req
;
393 JackInternalClientLoadResult res
;
394 if (req
.Read(socket
) == 0)
395 res
.fResult
= fServer
->InternalClientLoad1(req
.fName
, req
.fDllName
, req
.fLoadInitName
, req
.fOptions
, &res
.fIntRefNum
, req
.fUUID
, &res
.fStatus
);
396 if (res
.Write(socket
) < 0)
397 jack_error("JackRequest::InternalClientLoad write error name = %s", req
.fName
);
401 case JackRequest::kInternalClientUnload
: {
402 jack_log("JackRequest::InternalClientUnload");
403 JackInternalClientUnloadRequest req
;
404 JackInternalClientUnloadResult res
;
405 if (req
.Read(socket
) == 0)
406 res
.fResult
= fServer
->GetEngine()->InternalClientUnload(req
.fIntRefNum
, &res
.fStatus
);
407 if (res
.Write(socket
) < 0)
408 jack_error("JackRequest::InternalClientUnload write error ref = %d", req
.fRefNum
);
412 case JackRequest::kNotification
: {
413 jack_log("JackRequest::Notification");
414 JackClientNotificationRequest req
;
415 if (req
.Read(socket
) == 0) {
416 if (req
.fNotify
== kQUIT
) {
417 jack_log("JackRequest::Notification kQUIT");
418 throw JackQuitException();
420 fServer
->Notify(req
.fRefNum
, req
.fNotify
, req
.fValue
);
426 case JackRequest::kSessionNotify
: {
427 jack_log("JackRequest::SessionNotify");
428 JackSessionNotifyRequest req
;
429 JackSessionNotifyResult res
;
430 if (req
.Read(socket
) == 0) {
431 fServer
->GetEngine()->SessionNotify(req
.fRefNum
, req
.fDst
, req
.fEventType
, req
.fPath
, socket
);
436 case JackRequest::kSessionReply
: {
437 jack_log("JackRequest::SessionReply");
438 JackSessionReplyRequest req
;
440 if (req
.Read(socket
) == 0) {
441 fServer
->GetEngine()->SessionReply(req
.fRefNum
);
444 if (res
.Write(socket
) < 0)
445 jack_error("JackRequest::SessionReply write error");
449 case JackRequest::kGetClientByUUID
: {
450 jack_log("JackRequest::GetClientByUUID");
451 JackGetClientNameRequest req
;
452 JackClientNameResult res
;
453 if (req
.Read(socket
) == 0) {
454 fServer
->GetEngine()->GetClientNameForUUID(req
.fUUID
, res
.fName
, &res
.fResult
);
456 if (res
.Write(socket
) < 0)
457 jack_error("JackRequest::GetClientByUUID write error");
461 case JackRequest::kGetUUIDByClient
: {
462 jack_log("JackRequest::GetUUIDByClient");
463 JackGetUUIDRequest req
;
465 if (req
.Read(socket
) == 0) {
466 fServer
->GetEngine()->GetUUIDForClientName(req
.fName
, res
.fUUID
, &res
.fResult
);
468 if (res
.Write(socket
) < 0)
469 jack_error("JackRequest::GetUUIDByClient write error");
473 case JackRequest::kReserveClientName
: {
474 jack_log("JackRequest::ReserveClientName");
475 JackReserveNameRequest req
;
477 if (req
.Read(socket
) == 0) {
478 fServer
->GetEngine()->ReserveClientName(req
.fName
, req
.fUUID
, &res
.fResult
);
480 if (res
.Write(socket
) < 0)
481 jack_error("JackRequest::ReserveClientName write error");
485 case JackRequest::kClientHasSessionCallback
: {
486 jack_log("JackRequest::ClientHasSessionCallback");
487 JackClientHasSessionCallbackRequest req
;
489 if (req
.Read(socket
) == 0) {
490 fServer
->GetEngine()->ClientHasSessionCallbackRequest(req
.fName
, &res
.fResult
);
492 if (res
.Write(socket
) < 0)
493 jack_error("JackRequest::ClientHasSessionCallback write error");
498 jack_error("Unknown request %ld", header
.fType
);
505 void JackSocketServerChannel::BuildPoolTable()
510 fPollTable
= new pollfd
[fSocketTable
.size() + 1];
512 jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable
.size() + 1);
514 // First fd is the server request socket
515 fPollTable
[0].fd
= fRequestListenSocket
.GetFd();
516 fPollTable
[0].events
= POLLIN
| POLLERR
;
518 // Next fd for clients
519 map
<int, pair
<int, JackClientSocket
*> >::iterator it
;
522 for (i
= 1, it
= fSocketTable
.begin(); it
!= fSocketTable
.end(); it
++, i
++) {
523 jack_log("fSocketTable i = %ld fd = %ld", i
, it
->first
);
524 fPollTable
[i
].fd
= it
->first
;
525 fPollTable
[i
].events
= POLLIN
| POLLPRI
| POLLERR
| POLLHUP
| POLLNVAL
;
530 bool JackSocketServerChannel::Init()
534 sigaddset(&set
, SIGPIPE
);
535 pthread_sigmask(SIG_BLOCK
, &set
, 0);
539 bool JackSocketServerChannel::Execute()
544 if ((poll(fPollTable
, fSocketTable
.size() + 1, 10000) < 0) && (errno
!= EINTR
)) {
545 jack_error("Engine poll failed err = %s request thread quits...", strerror(errno
));
550 for (unsigned int i
= 1; i
< fSocketTable
.size() + 1; i
++) {
551 int fd
= fPollTable
[i
].fd
;
552 jack_log("fPollTable i = %ld fd = %ld", i
, fd
);
553 if (fPollTable
[i
].revents
& ~POLLIN
) {
554 jack_log("Poll client error err = %s", strerror(errno
));
556 } else if (fPollTable
[i
].revents
& POLLIN
) {
557 if (!HandleRequest(fd
))
558 jack_log("Could not handle external client request");
562 // Check the server request socket */
563 if (fPollTable
[0].revents
& POLLERR
)
564 jack_error("Error on server request socket err = %s", strerror(errno
));
566 if (fPollTable
[0].revents
& POLLIN
)
573 } catch (JackQuitException
& e
) {
574 jack_log("JackMachServerChannel::Execute JackQuitException");
579 } // end of namespace