Jack2 1.9.10

JackWinNamedPipeServerChannel.cpp

00001 /*
00002  Copyright (C) 2004-2008 Grame
00003 
00004  This program is free software; you can redistribute it and/or modify
00005  it under the terms of the GNU Lesser General Public License as published by
00006  the Free Software Foundation; either version 2.1 of the License, or
00007  (at your option) any later version.
00008 
00009  This program is distributed in the hope that it will be useful,
00010  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  GNU Lesser General Public License for more details.
00013 
00014  You should have received a copy of the GNU Lesser General Public License
00015  along with this program; if not, write to the Free Software
00016  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 
00018  */
00019 
00020 
00021 #include "JackWinNamedPipeServerChannel.h"
00022 #include "JackNotification.h"
00023 #include "JackRequest.h"
00024 #include "JackServer.h"
00025 #include "JackLockedEngine.h"
00026 #include "JackGlobals.h"
00027 #include "JackClient.h"
00028 #include "JackNotification.h"
00029 #include "JackException.h"
00030 #include <assert.h>
00031 
00032 using namespace std;
00033 
00034 namespace Jack
00035 {
00036 
00037 HANDLE JackClientPipeThread::fMutex = NULL;  // Never released....
00038 
00039 // fRefNum = -1 correspond to already removed client
00040 
00041 JackClientPipeThread::JackClientPipeThread(JackWinNamedPipeClient* pipe)
00042     :fPipe(pipe), fDecoder(NULL), fServer(NULL), fThread(this), fRefNum(0)
00043 {
00044     // First one allocated the static fMutex
00045     if (fMutex == NULL) {
00046         fMutex = CreateMutex(NULL, FALSE, NULL);
00047     }
00048 }
00049 
00050 JackClientPipeThread::~JackClientPipeThread()
00051 {
00052     jack_log("JackClientPipeThread::~JackClientPipeThread");
00053     delete fPipe;
00054 }
00055 
00056 int JackClientPipeThread::Open(JackServer* server)      // Open the Server/Client connection
00057 {
00058     // Start listening
00059     if (fThread.Start() != 0) {
00060         jack_error("Cannot start Jack server listener\n");
00061         return -1;
00062     } else {
00063         fDecoder = new JackRequestDecoder(server, this);
00064         fServer = server;
00065         return 0;
00066     }
00067 }
00068 
00069 void JackClientPipeThread::Close()                                      // Close the Server/Client connection
00070 {
00071     jack_log("JackClientPipeThread::Close 0 %x %ld", this, fRefNum);
00072 
00073     //fThread.Kill();
00074     fPipe->Close();
00075     fRefNum = -1;
00076 
00077     delete fDecoder;
00078     fDecoder = NULL;
00079 }
00080 
00081 bool JackClientPipeThread::Execute()
00082 {
00083     try {
00084 
00085         jack_log("JackClientPipeThread::Execute %x", this);
00086         JackRequest header;
00087         int res = header.Read(fPipe);
00088         bool ret = true;
00089 
00090         // Lock the global mutex
00091         if (WaitForSingleObject(fMutex, INFINITE) == WAIT_FAILED) {
00092             jack_error("JackClientPipeThread::Execute : mutex wait error");
00093         }
00094 
00095         // Decode header
00096         if (res < 0) {
00097             jack_log("JackClientPipeThread::Execute : cannot decode header");
00098             ClientKill();
00099             ret = false;
00100         // Decode request
00101         } else if (fDecoder->HandleRequest(fPipe, header.fType) < 0) {
00102             ret = false;
00103         }
00104 
00105         // Unlock the global mutex
00106         if (!ReleaseMutex(fMutex)) {
00107             jack_error("JackClientPipeThread::Execute : mutex release error");
00108         }
00109         return ret;
00110 
00111     } catch (JackQuitException& e) {
00112         jack_log("JackClientPipeThread::Execute : JackQuitException");
00113         return false;
00114     }
00115 }
00116 
00117 void JackClientPipeThread::ClientAdd(detail::JackChannelTransactionInterface* socket, JackClientOpenRequest* req, JackClientOpenResult *res)
00118 {
00119     jack_log("JackClientPipeThread::ClientAdd %x %s", this, req->fName);
00120     fRefNum = -1;
00121     res->fResult = fServer->GetEngine()->ClientExternalOpen(req->fName, req->fPID, req->fUUID, &fRefNum, &res->fSharedEngine, &res->fSharedClient, &res->fSharedGraph);
00122 }
00123 
00124 void JackClientPipeThread::ClientRemove(detail::JackChannelTransactionInterface* socket_aux, int refnum)
00125 {
00126     jack_log("JackClientPipeThread::ClientRemove ref = %d", refnum);
00127     Close();
00128 }
00129 
00130 void JackClientPipeThread::ClientKill()
00131 {
00132     jack_log("JackClientPipeThread::ClientKill ref = %d", fRefNum);
00133 
00134     if (fRefNum == -1) {        // Correspond to an already removed client.
00135         jack_log("Kill a closed client %x", this);
00136     } else if (fRefNum == 0) {  // Correspond to a still not opened client.
00137         jack_log("Kill a not opened client %x", this);
00138     } else {
00139         fServer->GetEngine()->ClientKill(fRefNum);
00140     }
00141 
00142     Close();
00143 }
00144 
00145 JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel():fThread(this)
00146 {}
00147 
00148 JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel()
00149 {
00150     std::list<JackClientPipeThread*>::iterator it;
00151 
00152     for (it = fClientList.begin(); it !=  fClientList.end(); it++) {
00153         JackClientPipeThread* client = *it;
00154         client->Close();
00155         delete client;
00156     }
00157 }
00158 
00159 int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* server)
00160 {
00161     jack_log("JackWinNamedPipeServerChannel::Open");
00162     snprintf(fServerName, sizeof(fServerName), server_name);
00163 
00164     // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object
00165     if (ClientListen()) {
00166         fServer = server;
00167         return 0;
00168     } else {
00169         jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
00170         return -1;
00171     }
00172 }
00173 
00174 void JackWinNamedPipeServerChannel::Close()
00175 {
00176     /* TODO : solve WIN32 thread Kill issue
00177     This would hang the server... since we are quitting it, its not really problematic,
00178     all ressources will be deallocated at the end.
00179 
00180     fRequestListenPipe.Close();
00181     fThread.Stop();
00182     */
00183 
00184     fRequestListenPipe.Close();
00185 }
00186 
00187 int JackWinNamedPipeServerChannel::Start()
00188 {
00189     if (fThread.Start() != 0) {
00190         jack_error("Cannot start Jack server listener");
00191         return -1;
00192     } else {
00193         return 0;
00194     }
00195 }
00196 
00197 void JackWinNamedPipeServerChannel::Stop()
00198 {
00199     fThread.Kill();
00200 }
00201 
00202 bool JackWinNamedPipeServerChannel::Init()
00203 {
00204     jack_log("JackWinNamedPipeServerChannel::Init");
00205     // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object
00206     return ClientAccept();
00207 }
00208 
00209 bool JackWinNamedPipeServerChannel::ClientListen()
00210 {
00211     if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) {
00212         jack_error("JackWinNamedPipeServerChannel::ClientListen : cannot create result listen pipe");
00213         return false;
00214     } else {
00215         return true;
00216     }
00217 }
00218 
00219 bool JackWinNamedPipeServerChannel::ClientAccept()
00220 {
00221      JackWinNamedPipeClient* pipe;
00222 
00223      if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
00224         jack_error("JackWinNamedPipeServerChannel::ClientAccept : cannot connect pipe");
00225         return false;
00226     } else {
00227         ClientAdd(pipe);
00228         return true;
00229     }
00230 }
00231 
00232 bool JackWinNamedPipeServerChannel::Execute()
00233 {
00234     if (!ClientListen()) {
00235        return false;
00236     }
00237 
00238     return ClientAccept();
00239 }
00240 
00241 void JackWinNamedPipeServerChannel::ClientAdd(JackWinNamedPipeClient* pipe)
00242 {
00243     // Remove dead (= not running anymore) clients.
00244     std::list<JackClientPipeThread*>::iterator it = fClientList.begin();
00245     JackClientPipeThread* client;
00246 
00247     jack_log("JackWinNamedPipeServerChannel::ClientAdd size %ld", fClientList.size());
00248 
00249     while (it != fClientList.end()) {
00250         client = *it;
00251         if (client->IsRunning()) {
00252             it++;
00253         } else {
00254             it = fClientList.erase(it);
00255             delete client;
00256         }
00257     }
00258 
00259     client = new JackClientPipeThread(pipe);
00260     client->Open(fServer);
00261 
00262     // Here we are sure that the client is running (because it's thread is in "running" state).
00263     fClientList.push_back(client);
00264 }
00265 
00266 } // end of namespace
00267 
00268