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.
21 #include "JackWinNamedPipeServerChannel.h"
22 #include "JackNotification.h"
23 #include "JackRequest.h"
24 #include "JackServer.h"
25 #include "JackLockedEngine.h"
26 #include "JackGlobals.h"
27 #include "JackClient.h"
28 #include "JackNotification.h"
29 #include "JackException.h"
37 HANDLE
JackClientPipeThread::fMutex
= NULL
; // Never released....
39 // fRefNum = -1 correspond to already removed client
41 JackClientPipeThread::JackClientPipeThread(JackWinNamedPipeClient
* pipe
)
42 :fPipe(pipe
), fDecoder(NULL
), fServer(NULL
), fThread(this), fRefNum(0)
44 // First one allocated the static fMutex
46 fMutex
= CreateMutex(NULL
, FALSE
, NULL
);
50 JackClientPipeThread::~JackClientPipeThread()
52 jack_log("JackClientPipeThread::~JackClientPipeThread");
56 int JackClientPipeThread::Open(JackServer
* server
) // Open the Server/Client connection
59 if (fThread
.Start() != 0) {
60 jack_error("Cannot start Jack server listener\n");
63 fDecoder
= new JackRequestDecoder(server
, this);
69 void JackClientPipeThread::Close() // Close the Server/Client connection
71 jack_log("JackClientPipeThread::Close 0 %x %ld", this, fRefNum
);
81 bool JackClientPipeThread::Execute()
85 jack_log("JackClientPipeThread::Execute %x", this);
87 int res
= header
.Read(fPipe
);
90 // Lock the global mutex
91 if (WaitForSingleObject(fMutex
, INFINITE
) == WAIT_FAILED
) {
92 jack_error("JackClientPipeThread::Execute : mutex wait error");
97 jack_log("JackClientPipeThread::Execute : cannot decode header");
101 } else if (fDecoder
->HandleRequest(fPipe
, header
.fType
) < 0) {
105 // Unlock the global mutex
106 if (!ReleaseMutex(fMutex
)) {
107 jack_error("JackClientPipeThread::Execute : mutex release error");
111 } catch (JackQuitException
& e
) {
112 jack_log("JackClientPipeThread::Execute : JackQuitException");
117 void JackClientPipeThread::ClientAdd(detail::JackChannelTransactionInterface
* socket
, JackClientOpenRequest
* req
, JackClientOpenResult
*res
)
119 jack_log("JackClientPipeThread::ClientAdd %x %s", this, req
->fName
);
121 res
->fResult
= fServer
->GetEngine()->ClientExternalOpen(req
->fName
, req
->fPID
, req
->fUUID
, &fRefNum
, &res
->fSharedEngine
, &res
->fSharedClient
, &res
->fSharedGraph
);
124 void JackClientPipeThread::ClientRemove(detail::JackChannelTransactionInterface
* socket_aux
, int refnum
)
126 jack_log("JackClientPipeThread::ClientRemove ref = %d", refnum
);
130 void JackClientPipeThread::ClientKill()
132 jack_log("JackClientPipeThread::ClientKill ref = %d", fRefNum
);
134 if (fRefNum
== -1) { // Correspond to an already removed client.
135 jack_log("Kill a closed client %x", this);
136 } else if (fRefNum
== 0) { // Correspond to a still not opened client.
137 jack_log("Kill a not opened client %x", this);
139 fServer
->ClientKill(fRefNum
);
145 JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel():fThread(this)
148 JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel()
150 std::list
<JackClientPipeThread
*>::iterator it
;
152 for (it
= fClientList
.begin(); it
!= fClientList
.end(); it
++) {
153 JackClientPipeThread
* client
= *it
;
159 int JackWinNamedPipeServerChannel::Open(const char* server_name
, JackServer
* server
)
161 jack_log("JackWinNamedPipeServerChannel::Open");
162 snprintf(fServerName
, sizeof(fServerName
), server_name
);
164 // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object
165 if (ClientListen()) {
169 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
174 void JackWinNamedPipeServerChannel::Close()
176 /* TODO : solve WIN32 thread Kill issue
177 This would hang the server... since we are quitting it, its not really problematic,
178 all ressources will be deallocated at the end.
180 fRequestListenPipe.Close();
184 fRequestListenPipe
.Close();
187 int JackWinNamedPipeServerChannel::Start()
189 if (fThread
.Start() != 0) {
190 jack_error("Cannot start Jack server listener");
197 void JackWinNamedPipeServerChannel::Stop()
202 bool JackWinNamedPipeServerChannel::Init()
204 jack_log("JackWinNamedPipeServerChannel::Init");
205 // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object
206 return ClientAccept();
209 bool JackWinNamedPipeServerChannel::ClientListen()
211 if (fRequestListenPipe
.Bind(jack_server_dir
, fServerName
, 0) < 0) {
212 jack_error("JackWinNamedPipeServerChannel::ClientListen : cannot create result listen pipe");
219 bool JackWinNamedPipeServerChannel::ClientAccept()
221 JackWinNamedPipeClient
* pipe
;
223 if ((pipe
= fRequestListenPipe
.AcceptClient()) == NULL
) {
224 jack_error("JackWinNamedPipeServerChannel::ClientAccept : cannot connect pipe");
232 bool JackWinNamedPipeServerChannel::Execute()
234 if (!ClientListen()) {
238 return ClientAccept();
241 void JackWinNamedPipeServerChannel::ClientAdd(JackWinNamedPipeClient
* pipe
)
243 // Remove dead (= not running anymore) clients.
244 std::list
<JackClientPipeThread
*>::iterator it
= fClientList
.begin();
245 JackClientPipeThread
* client
;
247 jack_log("JackWinNamedPipeServerChannel::ClientAdd size %ld", fClientList
.size());
249 while (it
!= fClientList
.end()) {
251 if (client
->IsRunning()) {
254 it
= fClientList
.erase(it
);
259 client
= new JackClientPipeThread(pipe
);
260 client
->Open(fServer
);
262 // Here we are sure that the client is running (because it's thread is in "running" state).
263 fClientList
.push_back(client
);
266 } // end of namespace