| 
							- /*
 -  Copyright (C) 2004-2008 Grame
 - 
 -  This program is free software; you can redistribute it and/or modify
 -  it under the terms of the GNU Lesser General Public License as published by
 -  the Free Software Foundation; either version 2.1 of the License, or
 -  (at your option) any later version.
 - 
 -  This program is distributed in the hope that it will be useful,
 -  but WITHOUT ANY WARRANTY; without even the implied warranty of
 -  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 -  GNU Lesser General Public License for more details.
 - 
 -  You should have received a copy of the GNU Lesser General Public License
 -  along with this program; if not, write to the Free Software
 -  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 - 
 -  */
 - 
 - 
 - #include "JackWinNamedPipeServerChannel.h"
 - #include "JackNotification.h"
 - #include "JackRequest.h"
 - #include "JackServer.h"
 - #include "JackLockedEngine.h"
 - #include "JackGlobals.h"
 - #include "JackClient.h"
 - #include "JackNotification.h"
 - #include "JackException.h"
 - #include <assert.h>
 - 
 - using namespace std;
 - 
 - namespace Jack
 - {
 - 
 - HANDLE JackClientPipeThread::fMutex = NULL;  // Never released....
 - 
 - // fRefNum = -1 correspond to already removed client
 - 
 - JackClientPipeThread::JackClientPipeThread(JackWinNamedPipeClient* pipe)
 -     :fPipe(pipe), fDecoder(NULL), fServer(NULL), fThread(this), fRefNum(0)
 - {
 -     // First one allocated the static fMutex
 -     if (fMutex == NULL) {
 -         fMutex = CreateMutex(NULL, FALSE, NULL);
 -     }
 - }
 - 
 - JackClientPipeThread::~JackClientPipeThread()
 - {
 -     jack_log("JackClientPipeThread::~JackClientPipeThread");
 -     delete fPipe;
 - }
 - 
 - int JackClientPipeThread::Open(JackServer* server)      // Open the Server/Client connection
 - {
 -     // Start listening
 -     if (fThread.Start() != 0) {
 -         jack_error("Cannot start Jack server listener\n");
 -         return -1;
 -     } else {
 -         fDecoder = new JackRequestDecoder(server, this);
 -         fServer = server;
 -         return 0;
 -     }
 - }
 - 
 - void JackClientPipeThread::Close()                                      // Close the Server/Client connection
 - {
 -     jack_log("JackClientPipeThread::Close 0 %x %ld", this, fRefNum);
 - 
 -     //fThread.Kill();
 -     fPipe->Close();
 -     fRefNum = -1;
 - 
 -     delete fDecoder;
 -     fDecoder = NULL;
 - }
 - 
 - bool JackClientPipeThread::Execute()
 - {
 -     try {
 - 
 -         jack_log("JackClientPipeThread::Execute %x", this);
 -         JackRequest header;
 -         int res = header.Read(fPipe);
 -         bool ret = true;
 - 
 -         // Lock the global mutex
 -         if (WaitForSingleObject(fMutex, INFINITE) == WAIT_FAILED) {
 -             jack_error("JackClientPipeThread::Execute : mutex wait error");
 -         }
 - 
 -         // Decode header
 -         if (res < 0) {
 -             jack_log("JackClientPipeThread::Execute : cannot decode header");
 -             ClientKill();
 -             ret = false;
 -         // Decode request
 -         } else if (fDecoder->HandleRequest(fPipe, header.fType) < 0) {
 -             ret = false;
 -         }
 - 
 -         // Unlock the global mutex
 -         if (!ReleaseMutex(fMutex)) {
 -             jack_error("JackClientPipeThread::Execute : mutex release error");
 -         }
 -         return ret;
 - 
 -     } catch (JackQuitException& e) {
 -         jack_log("JackClientPipeThread::Execute : JackQuitException");
 -         return false;
 -     }
 - }
 - 
 - void JackClientPipeThread::ClientAdd(detail::JackChannelTransactionInterface* socket, JackClientOpenRequest* req, JackClientOpenResult *res)
 - {
 -     jack_log("JackClientPipeThread::ClientAdd %x %s", this, req->fName);
 -     fRefNum = -1;
 -     res->fResult = fServer->GetEngine()->ClientExternalOpen(req->fName, req->fPID, req->fUUID, &fRefNum, &res->fSharedEngine, &res->fSharedClient, &res->fSharedGraph);
 - }
 - 
 - void JackClientPipeThread::ClientRemove(detail::JackChannelTransactionInterface* socket_aux, int refnum)
 - {
 -     jack_log("JackClientPipeThread::ClientRemove ref = %d", refnum);
 -     Close();
 - }
 - 
 - void JackClientPipeThread::ClientKill()
 - {
 -     jack_log("JackClientPipeThread::ClientKill ref = %d", fRefNum);
 - 
 -     if (fRefNum == -1) {        // Correspond to an already removed client.
 -         jack_log("Kill a closed client %x", this);
 -     } else if (fRefNum == 0) {  // Correspond to a still not opened client.
 -         jack_log("Kill a not opened client %x", this);
 -     } else {
 -         fServer->GetEngine()->ClientKill(fRefNum);
 -     }
 - 
 -     Close();
 - }
 - 
 - JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel():fThread(this)
 - {}
 - 
 - JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel()
 - {
 -     std::list<JackClientPipeThread*>::iterator it;
 - 
 -     for (it = fClientList.begin(); it !=  fClientList.end(); it++) {
 -         JackClientPipeThread* client = *it;
 -         client->Close();
 -         delete client;
 -     }
 - }
 - 
 - int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* server)
 - {
 -     jack_log("JackWinNamedPipeServerChannel::Open");
 -     snprintf(fServerName, sizeof(fServerName), server_name);
 - 
 -     // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object
 -     if (ClientListen()) {
 -         fServer = server;
 -         return 0;
 -     } else {
 -         jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
 -         return -1;
 -     }
 - }
 - 
 - void JackWinNamedPipeServerChannel::Close()
 - {
 -     /* TODO : solve WIN32 thread Kill issue
 -     This would hang the server... since we are quitting it, its not really problematic,
 -     all resources will be deallocated at the end.
 - 
 -     fRequestListenPipe.Close();
 -     fThread.Stop();
 -     */
 - 
 -     fRequestListenPipe.Close();
 - }
 - 
 - int JackWinNamedPipeServerChannel::Start()
 - {
 -     if (fThread.Start() != 0) {
 -         jack_error("Cannot start Jack server listener");
 -         return -1;
 -     } else {
 -         return 0;
 -     }
 - }
 - 
 - void JackWinNamedPipeServerChannel::Stop()
 - {
 -     fThread.Kill();
 - }
 - 
 - bool JackWinNamedPipeServerChannel::Init()
 - {
 -     jack_log("JackWinNamedPipeServerChannel::Init");
 -     // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object
 -     return ClientAccept();
 - }
 - 
 - bool JackWinNamedPipeServerChannel::ClientListen()
 - {
 -     if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) {
 -         jack_error("JackWinNamedPipeServerChannel::ClientListen : cannot create result listen pipe");
 -         return false;
 -     } else {
 -         return true;
 -     }
 - }
 - 
 - bool JackWinNamedPipeServerChannel::ClientAccept()
 - {
 -      JackWinNamedPipeClient* pipe;
 - 
 -      if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
 -         jack_error("JackWinNamedPipeServerChannel::ClientAccept : cannot connect pipe");
 -         return false;
 -     } else {
 -         ClientAdd(pipe);
 -         return true;
 -     }
 - }
 - 
 - bool JackWinNamedPipeServerChannel::Execute()
 - {
 -     if (!ClientListen()) {
 -        return false;
 -     }
 - 
 -     return ClientAccept();
 - }
 - 
 - void JackWinNamedPipeServerChannel::ClientAdd(JackWinNamedPipeClient* pipe)
 - {
 -     // Remove dead (= not running anymore) clients.
 -     std::list<JackClientPipeThread*>::iterator it = fClientList.begin();
 -     JackClientPipeThread* client;
 - 
 -     jack_log("JackWinNamedPipeServerChannel::ClientAdd size %ld", fClientList.size());
 - 
 -     while (it != fClientList.end()) {
 -         client = *it;
 -         if (client->IsRunning()) {
 -             it++;
 -         } else {
 -             it = fClientList.erase(it);
 -             delete client;
 -         }
 -     }
 - 
 -     client = new JackClientPipeThread(pipe);
 -     client->Open(fServer);
 - 
 -     // Here we are sure that the client is running (because it's thread is in "running" state).
 -     fClientList.push_back(client);
 - }
 - 
 - } // end of namespace
 - 
 
 
  |