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

Generated on Wed Jan 10 11:42:47 2007 for Jackdmp by  doxygen 1.4.5