Jack2 1.9.7

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, req.fUUID, 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, req.fUUID, &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::kComputeTotalLatencies: {
00256                 jack_log("JackRequest::ComputeTotalLatencies");
00257                 JackComputeTotalLatenciesRequest req;
00258                 JackResult res;
00259                 if (req.Read(fPipe) == 0)
00260                     res.fResult = fServer->GetEngine()->ComputeTotalLatencies();
00261                 res.Write(fPipe);
00262                 break;
00263             }
00264 
00265             case JackRequest::kReleaseTimebase: {
00266                 jack_log("JackRequest::ReleaseTimebase");
00267                 JackReleaseTimebaseRequest req;
00268                 JackResult res;
00269                 if (req.Read(fPipe) == 0)
00270                     res.fResult = fServer->ReleaseTimebase(req.fRefNum);
00271                 res.Write(fPipe);
00272                 break;
00273             }
00274 
00275             case JackRequest::kSetTimebaseCallback: {
00276                 jack_log("JackRequest::SetTimebaseCallback");
00277                 JackSetTimebaseCallbackRequest req;
00278                 JackResult res;
00279                 if (req.Read(fPipe) == 0)
00280                     res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal);
00281                 res.Write(fPipe);
00282                 break;
00283             }
00284 
00285             case JackRequest::kGetInternalClientName: {
00286                 jack_log("JackRequest::GetInternalClientName");
00287                 JackGetInternalClientNameRequest req;
00288                 JackGetInternalClientNameResult res;
00289                 if (req.Read(fPipe) == 0)
00290                     res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName);
00291                 res.Write(fPipe);
00292                 break;
00293             }
00294 
00295             case JackRequest::kInternalClientHandle: {
00296                 jack_log("JackRequest::InternalClientHandle");
00297                 JackInternalClientHandleRequest req;
00298                 JackInternalClientHandleResult res;
00299                 if (req.Read(fPipe) == 0)
00300                     res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum);
00301                 res.Write(fPipe);
00302                 break;
00303             }
00304 
00305             case JackRequest::kInternalClientLoad: {
00306                 jack_log("JackRequest::InternalClientLoad");
00307                 JackInternalClientLoadRequest req;
00308                 JackInternalClientLoadResult res;
00309                 if (req.Read(fPipe) == 0)
00310                     res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus);
00311                 res.Write(fPipe);
00312                 break;
00313             }
00314 
00315             case JackRequest::kInternalClientUnload: {
00316                 jack_log("JackRequest::InternalClientUnload");
00317                 JackInternalClientUnloadRequest req;
00318                 JackInternalClientUnloadResult res;
00319                 if (req.Read(fPipe) == 0)
00320                     res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus);
00321                 res.Write(fPipe);
00322                 break;
00323             }
00324 
00325             case JackRequest::kNotification: {
00326                 jack_log("JackRequest::Notification");
00327                 JackClientNotificationRequest req;
00328                 if (req.Read(fPipe) == 0) {
00329                     if (req.fNotify == kQUIT) {
00330                         jack_log("JackRequest::Notification kQUIT");
00331                         throw JackQuitException();
00332                     } else {
00333                         fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
00334                     }
00335                 }
00336                 break;
00337             }
00338 
00339             case JackRequest::kSessionNotify: {
00340                 jack_log("JackRequest::SessionNotify");
00341                 JackSessionNotifyRequest req;
00342                 JackSessionNotifyResult res;
00343                 if (req.Read(fPipe) == 0) {
00344                     fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, fPipe);
00345                 }
00346                 res.Write(fPipe);
00347                 break;
00348             }
00349 
00350             case JackRequest::kSessionReply: {
00351                 jack_log("JackRequest::SessionReply");
00352                 JackSessionReplyRequest req;
00353                 JackResult res;
00354                 if (req.Read(fPipe) == 0) {
00355                     fServer->GetEngine()->SessionReply(req.fRefNum);
00356                     res.fResult = 0;
00357                 }
00358                 res.Write(fPipe);
00359                 break;
00360             }
00361 
00362             case JackRequest::kGetClientByUUID: {
00363                 jack_log("JackRequest::GetClientByUUID");
00364                 JackGetClientNameRequest req;
00365                 JackClientNameResult res;
00366                 if (req.Read(fPipe) == 0) {
00367                     fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName, &res.fResult);
00368                 }
00369                 res.Write(fPipe);
00370                 break;
00371             }
00372 
00373             case JackRequest::kGetUUIDByClient: {
00374                 jack_log("JackRequest::GetUUIDByClient");
00375                 JackGetUUIDRequest req;
00376                 JackUUIDResult res;
00377                 if (req.Read(fPipe) == 0) {
00378                     fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult);
00379                 }
00380                 res.Write(fPipe);
00381                 break;
00382             }
00383 
00384             case JackRequest::kReserveClientName: {
00385                 jack_log("JackRequest::ReserveClientName");
00386                 JackReserveNameRequest req;
00387                 JackResult res;
00388                 if (req.Read(fPipe) == 0) {
00389                     fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID, &res.fResult);
00390                 }
00391                 res.Write(fPipe);
00392                 break;
00393             }
00394 
00395             case JackRequest::kClientHasSessionCallback: {
00396                 jack_log("JackRequest::ClientHasSessionCallback");
00397                 JackClientHasSessionCallbackRequest req;
00398                 JackResult res;
00399                 if (req.Read(fPipe) == 0) {
00400                     fServer->GetEngine()->ClientHasSessionCallbackRequest(req.fName, &res.fResult);
00401                 }
00402                 res.Write(fPipe);
00403                 break;
00404             }
00405 
00406             default:
00407                 jack_log("Unknown request %ld", header.fType);
00408                 break;
00409         }
00410     }
00411 
00412     // Unlock the global mutex
00413     ReleaseMutex(fMutex);
00414     return ret;
00415 }
00416 
00417 void JackClientPipeThread::ClientAdd(char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
00418 {
00419     jack_log("JackClientPipeThread::ClientAdd %s", name);
00420     fRefNum = -1;
00421     *result = fServer->GetEngine()->ClientExternalOpen(name, pid, uuid, &fRefNum, shared_engine, shared_client, shared_graph);
00422 }
00423 
00424 void JackClientPipeThread::ClientRemove()
00425 {
00426     jack_log("JackClientPipeThread::ClientRemove ref = %d", fRefNum);
00427     /* TODO : solve WIN32 thread Kill issue
00428     Close();
00429     */
00430     fRefNum = -1;
00431     fPipe->Close();
00432 }
00433 
00434 void JackClientPipeThread::ClientKill()
00435 {
00436     jack_log("JackClientPipeThread::ClientKill ref = %d", fRefNum);
00437 
00438     if (fRefNum == -1) {                // Correspond to an already removed client.
00439         jack_log("Kill a closed client");
00440     } else if (fRefNum == 0) {  // Correspond to a still not opened client.
00441         jack_log("Kill a not opened client");
00442     } else {
00443         fServer->ClientKill(fRefNum);
00444     }
00445 
00446     Close();
00447 }
00448 
00449 JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel():fThread(this)
00450 {}
00451 
00452 JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel()
00453 {
00454     std::list<JackClientPipeThread*>::iterator it;
00455 
00456     for (it = fClientList.begin(); it !=  fClientList.end(); it++) {
00457         JackClientPipeThread* client = *it;
00458         client->Close();
00459         delete client;
00460     }
00461 }
00462 
00463 int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* server)
00464 {
00465     jack_log("JackWinNamedPipeServerChannel::Open ");
00466     snprintf(fServerName, sizeof(fServerName), server_name);
00467 
00468     // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object
00469     if (fRequestListenPipe.Bind(jack_server_dir, server_name, 0) < 0) {
00470         jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
00471         return -1;
00472     }
00473 
00474     fServer = server;
00475     return 0;
00476 }
00477 
00478 void JackWinNamedPipeServerChannel::Close()
00479 {
00480     /* TODO : solve WIN32 thread Kill issue
00481         This would hang the server... since we are quitting it, its not really problematic,
00482         all ressources will be desallocated at the end.
00483 
00484         fRequestListenPipe.Close();
00485         fThread.Stop();
00486     */
00487 
00488     fThread.Kill();
00489     fRequestListenPipe.Close();
00490 }
00491 
00492 int JackWinNamedPipeServerChannel::Start()
00493 {
00494     if (fThread.Start() != 0) {
00495         jack_error("Cannot start Jack server listener");
00496         return -1;
00497     }
00498 
00499     return 0;
00500 }
00501 
00502 bool JackWinNamedPipeServerChannel::Init()
00503 {
00504     jack_log("JackWinNamedPipeServerChannel::Init ");
00505     JackWinNamedPipeClient* pipe;
00506 
00507     // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object
00508     if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
00509         jack_error("JackWinNamedPipeServerChannel::Init : cannot connect pipe");
00510         return false;
00511     } else {
00512         ClientAdd(pipe);
00513         return true;
00514     }
00515 }
00516 
00517 bool JackWinNamedPipeServerChannel::Execute()
00518 {
00519     JackWinNamedPipeClient* pipe;
00520 
00521     if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) {
00522         jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
00523         return false;
00524     }
00525 
00526     if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
00527         jack_error("JackWinNamedPipeServerChannel::Open : cannot connect pipe");
00528         return false;
00529     }
00530 
00531     ClientAdd(pipe);
00532     return true;
00533 }
00534 
00535 void JackWinNamedPipeServerChannel::ClientAdd(JackWinNamedPipeClient* pipe)
00536 {
00537     // Remove dead (= not running anymore) clients.
00538     std::list<JackClientPipeThread*>::iterator it = fClientList.begin();
00539     JackClientPipeThread* client;
00540 
00541     jack_log("ClientAdd size  %ld", fClientList.size());
00542 
00543     while (it != fClientList.end()) {
00544         client = *it;
00545         jack_log("Remove dead client = %x running =  %ld", client, client->IsRunning());
00546         if (client->IsRunning()) {
00547             it++;
00548         } else {
00549             it = fClientList.erase(it);
00550             delete client;
00551         }
00552     }
00553 
00554     client = new JackClientPipeThread(pipe);
00555     client->Open(fServer);
00556     // Here we are sure that the client is running (because it's thread is in "running" state).
00557     fClientList.push_back(client);
00558 }
00559 
00560 } // end of namespace
00561 
00562 

Generated for Jack2 by doxygen 1.7.3