jack: remove unnecessary GPL include from LGPL code
[jack2.git] / windows / JackWinNamedPipeServerChannel.cpp
blob954fae2acfb585963e76034784475f5204b80983
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.
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"
30 #include <assert.h>
32 using namespace std;
34 namespace Jack
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
45 if (fMutex == NULL) {
46 fMutex = CreateMutex(NULL, FALSE, NULL);
50 JackClientPipeThread::~JackClientPipeThread()
52 jack_log("JackClientPipeThread::~JackClientPipeThread");
53 delete fPipe;
56 int JackClientPipeThread::Open(JackServer* server) // Open the Server/Client connection
58 // Start listening
59 if (fThread.Start() != 0) {
60 jack_error("Cannot start Jack server listener\n");
61 return -1;
62 } else {
63 fDecoder = new JackRequestDecoder(server, this);
64 fServer = server;
65 return 0;
69 void JackClientPipeThread::Close() // Close the Server/Client connection
71 jack_log("JackClientPipeThread::Close 0 %x %ld", this, fRefNum);
73 //fThread.Kill();
74 fPipe->Close();
75 fRefNum = -1;
77 delete fDecoder;
78 fDecoder = NULL;
81 bool JackClientPipeThread::Execute()
83 try {
85 jack_log("JackClientPipeThread::Execute %x", this);
86 JackRequest header;
87 int res = header.Read(fPipe);
88 bool ret = true;
90 // Lock the global mutex
91 if (WaitForSingleObject(fMutex, INFINITE) == WAIT_FAILED) {
92 jack_error("JackClientPipeThread::Execute : mutex wait error");
95 // Decode header
96 if (res < 0) {
97 jack_log("JackClientPipeThread::Execute : cannot decode header");
98 ClientKill();
99 ret = false;
100 // Decode request
101 } else if (fDecoder->HandleRequest(fPipe, header.fType) < 0) {
102 ret = false;
105 // Unlock the global mutex
106 if (!ReleaseMutex(fMutex)) {
107 jack_error("JackClientPipeThread::Execute : mutex release error");
109 return ret;
111 } catch (JackQuitException& e) {
112 jack_log("JackClientPipeThread::Execute : JackQuitException");
113 return false;
117 void JackClientPipeThread::ClientAdd(detail::JackChannelTransactionInterface* socket, JackClientOpenRequest* req, JackClientOpenResult *res)
119 jack_log("JackClientPipeThread::ClientAdd %x %s", this, req->fName);
120 fRefNum = -1;
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);
127 Close();
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);
138 } else {
139 fServer->GetEngine()->ClientKill(fRefNum);
142 Close();
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;
154 client->Close();
155 delete client;
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()) {
166 fServer = server;
167 return 0;
168 } else {
169 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
170 return -1;
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 resources will be deallocated at the end.
180 fRequestListenPipe.Close();
181 fThread.Stop();
184 fRequestListenPipe.Close();
187 int JackWinNamedPipeServerChannel::Start()
189 if (fThread.Start() != 0) {
190 jack_error("Cannot start Jack server listener");
191 return -1;
192 } else {
193 return 0;
197 void JackWinNamedPipeServerChannel::Stop()
199 fThread.Kill();
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");
213 return false;
214 } else {
215 return true;
219 bool JackWinNamedPipeServerChannel::ClientAccept()
221 JackWinNamedPipeClient* pipe;
223 if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
224 jack_error("JackWinNamedPipeServerChannel::ClientAccept : cannot connect pipe");
225 return false;
226 } else {
227 ClientAdd(pipe);
228 return true;
232 bool JackWinNamedPipeServerChannel::Execute()
234 if (!ClientListen()) {
235 return false;
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()) {
250 client = *it;
251 if (client->IsRunning()) {
252 it++;
253 } else {
254 it = fClientList.erase(it);
255 delete client;
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