Jack2
1.9.10
|
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