JackWinNamedPipeServerChannel.cpp

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

Generated on Thu Feb 14 11:16:02 2008 for Jackdmp by  doxygen 1.5.1