Jack2 1.9.6

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), 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     }
00063 
00064     fServer = server;
00065     return 0;
00066 }
00067 
00068 void JackClientPipeThread::Close()                                      // Close the Server/Client connection
00069 {
00070     jack_log("JackClientPipeThread::Close %x %ld", this, fRefNum);
00071     /*
00072         TODO : solve WIN32 thread Kill issue
00073         This would hang.. since Close will be followed by a delete,
00074         all ressources will be desallocated at the end.
00075     */
00076 
00077     fThread.Kill();
00078     fPipe->Close();
00079     fRefNum = -1;
00080 }
00081 
00082 bool JackClientPipeThread::Execute()
00083 {
00084     try{
00085         jack_log("JackClientPipeThread::Execute");
00086         return (HandleRequest());
00087     } catch (JackQuitException& e) {
00088         jack_log("JackMachServerChannel::Execute JackQuitException");
00089         return false;
00090     }
00091 }
00092 
00093 bool JackClientPipeThread::HandleRequest()
00094 {
00095     // Read header
00096     JackRequest header;
00097     int res = header.Read(fPipe);
00098     bool ret = true;
00099 
00100     // Lock the global mutex
00101     if (WaitForSingleObject(fMutex, INFINITE) == WAIT_FAILED)
00102         jack_error("JackClientPipeThread::HandleRequest: mutex wait error");
00103 
00104     if (res < 0) {
00105         jack_error("HandleRequest: cannot read header");
00106         ClientKill();
00107         ret = false;
00108     } else {
00109 
00110         // Read data
00111         switch (header.fType) {
00112 
00113             case JackRequest::kClientCheck: {
00114                 jack_log("JackRequest::ClientCheck");
00115                 JackClientCheckRequest req;
00116                 JackClientCheckResult res;
00117                 if (req.Read(fPipe) == 0)
00118                     res.fResult = fServer->GetEngine()->ClientCheck(req.fName, res.fName, req.fProtocol, req.fOptions, &res.fStatus);
00119                 res.Write(fPipe);
00120                 break;
00121             }
00122 
00123             case JackRequest::kClientOpen: {
00124                 jack_log("JackRequest::ClientOpen");
00125                 JackClientOpenRequest req;
00126                 JackClientOpenResult res;
00127                 if (req.Read(fPipe) == 0)
00128                     ClientAdd(req.fName, req.fPID, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult);
00129                 res.Write(fPipe);
00130                 break;
00131             }
00132 
00133             case JackRequest::kClientClose: {
00134                 jack_log("JackRequest::ClientClose");
00135                 JackClientCloseRequest req;
00136                 JackResult res;
00137                 if (req.Read(fPipe) == 0)
00138                     res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum);
00139                 res.Write(fPipe);
00140                 ClientRemove();
00141                 ret = false;
00142                 break;
00143             }
00144 
00145             case JackRequest::kActivateClient: {
00146                 JackActivateRequest req;
00147                 JackResult res;
00148                 jack_log("JackRequest::ActivateClient");
00149                 if (req.Read(fPipe) == 0)
00150                     res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fIsRealTime);
00151                 res.Write(fPipe);
00152                 break;
00153             }
00154 
00155             case JackRequest::kDeactivateClient: {
00156                 jack_log("JackRequest::DeactivateClient");
00157                 JackDeactivateRequest req;
00158                 JackResult res;
00159                 if (req.Read(fPipe) == 0)
00160                     res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum);
00161                 res.Write(fPipe);
00162                 break;
00163             }
00164 
00165             case JackRequest::kRegisterPort: {
00166                 jack_log("JackRequest::RegisterPort");
00167                 JackPortRegisterRequest req;
00168                 JackPortRegisterResult res;
00169                 if (req.Read(fPipe) == 0)
00170                     res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex);
00171                 res.Write(fPipe);
00172                 break;
00173             }
00174 
00175             case JackRequest::kUnRegisterPort: {
00176                 jack_log("JackRequest::UnRegisterPort");
00177                 JackPortUnRegisterRequest req;
00178                 JackResult res;
00179                 if (req.Read(fPipe) == 0)
00180                     res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex);
00181                 res.Write(fPipe);
00182                 break;
00183             }
00184 
00185             case JackRequest::kConnectNamePorts: {
00186                 jack_log("JackRequest::ConnectNamePorts");
00187                 JackPortConnectNameRequest req;
00188                 JackResult res;
00189                 if (req.Read(fPipe) == 0)
00190                     res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
00191                 res.Write(fPipe);
00192                 break;
00193             }
00194 
00195             case JackRequest::kDisconnectNamePorts: {
00196                 jack_log("JackRequest::DisconnectNamePorts");
00197                 JackPortDisconnectNameRequest req;
00198                 JackResult res;
00199                 if (req.Read(fPipe) == 0)
00200                     res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
00201                 res.Write(fPipe);
00202                 break;
00203             }
00204 
00205             case JackRequest::kConnectPorts: {
00206                 jack_log("JackRequest::ConnectPorts");
00207                 JackPortConnectRequest req;
00208                 JackResult res;
00209                 if (req.Read(fPipe) == 0)
00210                     res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
00211                 res.Write(fPipe);
00212                 break;
00213             }
00214 
00215             case JackRequest::kDisconnectPorts: {
00216                 jack_log("JackRequest::DisconnectPorts");
00217                 JackPortDisconnectRequest req;
00218                 JackResult res;
00219                 if (req.Read(fPipe) == 0)
00220                     res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
00221                 res.Write(fPipe);
00222                 break;
00223             }
00224 
00225             case JackRequest::kPortRename: {
00226                 jack_log("JackRequest::PortRename");
00227                 JackPortRenameRequest req;
00228                 JackResult res;
00229                 if (req.Read(fPipe) == 0)
00230                     res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName);
00231                 res.Write(fPipe);
00232                 break;
00233             }
00234 
00235             case JackRequest::kSetBufferSize: {
00236                 jack_log("JackRequest::SetBufferSize");
00237                 JackSetBufferSizeRequest req;
00238                 JackResult res;
00239                 if (req.Read(fPipe) == 0)
00240                     res.fResult = fServer->SetBufferSize(req.fBufferSize);
00241                 res.Write(fPipe);
00242                 break;
00243             }
00244 
00245             case JackRequest::kSetFreeWheel: {
00246                 jack_log("JackRequest::SetFreeWheel");
00247                 JackSetFreeWheelRequest req;
00248                 JackResult res;
00249                 if (req.Read(fPipe) == 0)
00250                     res.fResult = fServer->SetFreewheel(req.fOnOff);
00251                 res.Write(fPipe);
00252                 break;
00253             }
00254 
00255             case JackRequest::kReleaseTimebase: {
00256                 jack_log("JackRequest::ReleaseTimebase");
00257                 JackReleaseTimebaseRequest req;
00258                 JackResult res;
00259                 if (req.Read(fPipe) == 0)
00260                     res.fResult = fServer->ReleaseTimebase(req.fRefNum);
00261                 res.Write(fPipe);
00262                 break;
00263             }
00264 
00265             case JackRequest::kSetTimebaseCallback: {
00266                 jack_log("JackRequest::SetTimebaseCallback");
00267                 JackSetTimebaseCallbackRequest req;
00268                 JackResult res;
00269                 if (req.Read(fPipe) == 0)
00270                     res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal);
00271                 res.Write(fPipe);
00272                 break;
00273             }
00274 
00275             case JackRequest::kGetInternalClientName: {
00276                 jack_log("JackRequest::GetInternalClientName");
00277                 JackGetInternalClientNameRequest req;
00278                 JackGetInternalClientNameResult res;
00279                 if (req.Read(fPipe) == 0)
00280                     res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName);
00281                 res.Write(fPipe);
00282                 break;
00283             }
00284 
00285             case JackRequest::kInternalClientHandle: {
00286                 jack_log("JackRequest::InternalClientHandle");
00287                 JackInternalClientHandleRequest req;
00288                 JackInternalClientHandleResult res;
00289                 if (req.Read(fPipe) == 0)
00290                     res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum);
00291                 res.Write(fPipe);
00292                 break;
00293             }
00294 
00295             case JackRequest::kInternalClientLoad: {
00296                 jack_log("JackRequest::InternalClientLoad");
00297                 JackInternalClientLoadRequest req;
00298                 JackInternalClientLoadResult res;
00299                 if (req.Read(fPipe) == 0)
00300                     res.fResult = fServer->InternalClientLoad(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, &res.fStatus);
00301                 res.Write(fPipe);
00302                 break;
00303             }
00304 
00305             case JackRequest::kInternalClientUnload: {
00306                 jack_log("JackRequest::InternalClientUnload");
00307                 JackInternalClientUnloadRequest req;
00308                 JackInternalClientUnloadResult res;
00309                 if (req.Read(fPipe) == 0)
00310                     res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus);
00311                 res.Write(fPipe);
00312                 break;
00313             }
00314 
00315             case JackRequest::kNotification: {
00316                 jack_log("JackRequest::Notification");
00317                 JackClientNotificationRequest req;
00318                 if (req.Read(fPipe) == 0) {
00319                     if (req.fNotify == kQUIT) {
00320                         jack_log("JackRequest::Notification kQUIT");
00321                         throw JackQuitException();
00322                     } else {
00323                         fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
00324                     }
00325                 }
00326                 break;
00327             }
00328 
00329             default:
00330                 jack_log("Unknown request %ld", header.fType);
00331                 break;
00332         }
00333     }
00334 
00335     // Unlock the global mutex
00336     ReleaseMutex(fMutex);
00337     return ret;
00338 }
00339 
00340 void JackClientPipeThread::ClientAdd(char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
00341 {
00342     jack_log("JackClientPipeThread::ClientAdd %s", name);
00343     fRefNum = -1;
00344     *result = fServer->GetEngine()->ClientExternalOpen(name, pid, &fRefNum, shared_engine, shared_client, shared_graph);
00345 }
00346 
00347 void JackClientPipeThread::ClientRemove()
00348 {
00349     jack_log("JackClientPipeThread::ClientRemove ref = %d", fRefNum);
00350     /* TODO : solve WIN32 thread Kill issue
00351     Close();
00352     */
00353     fRefNum = -1;
00354     fPipe->Close();
00355 }
00356 
00357 void JackClientPipeThread::ClientKill()
00358 {
00359     jack_log("JackClientPipeThread::ClientKill ref = %d", fRefNum);
00360 
00361     if (fRefNum == -1) {                // Correspond to an already removed client.
00362         jack_log("Kill a closed client");
00363     } else if (fRefNum == 0) {  // Correspond to a still not opened client.
00364         jack_log("Kill a not opened client");
00365     } else {
00366         fServer->ClientKill(fRefNum);
00367     }
00368 
00369     Close();
00370 }
00371 
00372 JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel():fThread(this)
00373 {}
00374 
00375 JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel()
00376 {
00377     std::list<JackClientPipeThread*>::iterator it;
00378 
00379     for (it = fClientList.begin(); it !=  fClientList.end(); it++) {
00380         JackClientPipeThread* client = *it;
00381         client->Close();
00382         delete client;
00383     }
00384 }
00385 
00386 int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* server)
00387 {
00388     jack_log("JackWinNamedPipeServerChannel::Open ");
00389     snprintf(fServerName, sizeof(fServerName), server_name);
00390 
00391     // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object
00392     if (fRequestListenPipe.Bind(jack_server_dir, server_name, 0) < 0) {
00393         jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
00394         return -1;
00395     }
00396 
00397     fServer = server;
00398     return 0;
00399 }
00400 
00401 void JackWinNamedPipeServerChannel::Close()
00402 {
00403     /* TODO : solve WIN32 thread Kill issue
00404         This would hang the server... since we are quitting it, its not really problematic,
00405         all ressources will be desallocated at the end.
00406 
00407         fRequestListenPipe.Close();
00408         fThread.Stop();
00409     */
00410 
00411     fThread.Kill();
00412     fRequestListenPipe.Close();
00413 }
00414 
00415 int JackWinNamedPipeServerChannel::Start()
00416 {
00417     if (fThread.Start() != 0) {
00418         jack_error("Cannot start Jack server listener");
00419         return -1;
00420     }
00421 
00422     return 0;
00423 }
00424 
00425 bool JackWinNamedPipeServerChannel::Init()
00426 {
00427     jack_log("JackWinNamedPipeServerChannel::Init ");
00428     JackWinNamedPipeClient* pipe;
00429 
00430     // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object
00431     if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
00432         jack_error("JackWinNamedPipeServerChannel::Init : cannot connect pipe");
00433         return false;
00434     } else {
00435         ClientAdd(pipe);
00436         return true;
00437     }
00438 }
00439 
00440 bool JackWinNamedPipeServerChannel::Execute()
00441 {
00442     JackWinNamedPipeClient* pipe;
00443 
00444     if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) {
00445         jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
00446         return false;
00447     }
00448 
00449     if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
00450         jack_error("JackWinNamedPipeServerChannel::Open : cannot connect pipe");
00451         return false;
00452     }
00453 
00454     ClientAdd(pipe);
00455     return true;
00456 }
00457 
00458 void JackWinNamedPipeServerChannel::ClientAdd(JackWinNamedPipeClient* pipe)
00459 {
00460     // Remove dead (= not running anymore) clients.
00461     std::list<JackClientPipeThread*>::iterator it = fClientList.begin();
00462     JackClientPipeThread* client;
00463 
00464     jack_log("ClientAdd size  %ld", fClientList.size());
00465 
00466     while (it != fClientList.end()) {
00467         client = *it;
00468         jack_log("Remove dead client = %x running =  %ld", client, client->IsRunning());
00469         if (client->IsRunning()) {
00470             it++;
00471         } else {
00472             it = fClientList.erase(it);
00473             delete client;
00474         }
00475     }
00476 
00477     client = new JackClientPipeThread(pipe);
00478     client->Open(fServer);
00479     // Here we are sure that the client is running (because it's thread is in "running" state).
00480     fClientList.push_back(client);
00481 }
00482 
00483 } // end of namespace
00484 
00485