Jack2  1.9.7
JackSocketServerChannel.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 #include "JackSocketServerChannel.h"
00021 #include "JackRequest.h"
00022 #include "JackServer.h"
00023 #include "JackLockedEngine.h"
00024 #include "JackGlobals.h"
00025 #include "JackServerGlobals.h"
00026 #include "JackClient.h"
00027 #include "JackTools.h"
00028 #include "JackNotification.h"
00029 #include "JackException.h"
00030 
00031 #include <assert.h>
00032 #include <signal.h>
00033 
00034 using namespace std;
00035 
00036 namespace Jack
00037 {
00038 
00039 JackSocketServerChannel::JackSocketServerChannel():
00040     fThread(this)
00041 {
00042     fPollTable = NULL;
00043     fRebuild = true;
00044 }
00045 
00046 JackSocketServerChannel::~JackSocketServerChannel()
00047 {
00048     delete[] fPollTable;
00049 }
00050 
00051 int JackSocketServerChannel::Open(const char* server_name, JackServer* server)
00052 {
00053     jack_log("JackSocketServerChannel::Open");
00054 
00055     // Prepare request socket
00056     if (fRequestListenSocket.Bind(jack_server_dir, server_name, 0) < 0) {
00057         jack_log("JackSocketServerChannel::Open : cannot create result listen socket");
00058         return -1;
00059     }
00060 
00061     // Prepare for poll
00062     BuildPoolTable();
00063     fServer = server;
00064     return 0;
00065 }
00066 
00067 void JackSocketServerChannel::Close()
00068 {
00069     fThread.Stop();
00070     fRequestListenSocket.Close();
00071 
00072     // Close remaining client sockets
00073     std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
00074     for (it = fSocketTable.begin(); it != fSocketTable.end(); it++) {
00075         pair<int, JackClientSocket*> elem = (*it).second;
00076         JackClientSocket* socket = elem.second;
00077         assert(socket);
00078         socket->Close();
00079         delete socket;
00080     }
00081 }
00082 
00083 int JackSocketServerChannel::Start()
00084 {
00085     if (fThread.Start() != 0) {
00086         jack_error("Cannot start Jack server listener");
00087         return -1;
00088     }
00089 
00090     return 0;
00091 }
00092 
00093 void JackSocketServerChannel::ClientCreate()
00094 {
00095     jack_log("JackSocketServerChannel::ClientCreate socket");
00096     JackClientSocket* socket = fRequestListenSocket.Accept();
00097     if (socket) {
00098         fSocketTable[socket->GetFd()] = make_pair( -1, socket);
00099         fRebuild = true;
00100     } else {
00101         jack_error("Client socket cannot be created");
00102     }
00103 }
00104 
00105 void JackSocketServerChannel::ClientAdd(int fd, char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
00106 {
00107     jack_log("JackSocketServerChannel::ClientAdd");
00108     int refnum = -1;
00109     *result = fServer->GetEngine()->ClientExternalOpen(name, pid, uuid, &refnum, shared_engine, shared_client, shared_graph);
00110     if (*result == 0) {
00111         fSocketTable[fd].first = refnum;
00112         fRebuild = true;
00113     #ifdef __APPLE__
00114         int on = 1;
00115         if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) {
00116             jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fd, strerror(errno));
00117         }
00118     #endif
00119     } else {
00120         jack_error("Cannot create new client");
00121     }
00122 }
00123 
00124 void JackSocketServerChannel::ClientRemove(int fd, int refnum)
00125 {
00126     pair<int, JackClientSocket*> elem = fSocketTable[fd];
00127     JackClientSocket* socket = elem.second;
00128     assert(socket);
00129     jack_log("JackSocketServerChannel::ClientRemove ref = %d", refnum);
00130     fSocketTable.erase(fd);
00131     socket->Close();
00132     delete socket;
00133     fRebuild = true;
00134 }
00135 
00136 void JackSocketServerChannel::ClientKill(int fd)
00137 {
00138     pair<int, JackClientSocket*> elem = fSocketTable[fd];
00139     JackClientSocket* socket = elem.second;
00140     int refnum = elem.first;
00141 
00142     assert(socket);
00143     jack_log("JackSocketServerChannel::ClientKill ref = %d", refnum);
00144 
00145     if (refnum == -1) {  // Should never happen... correspond to a client that started the socket but never opened...
00146         jack_log("Client was not opened : probably correspond to server_check");
00147     } else {
00148         fServer->ClientKill(refnum);
00149     }
00150 
00151     fSocketTable.erase(fd);
00152     socket->Close();
00153     delete socket;
00154     fRebuild = true;
00155 }
00156 
00157 bool JackSocketServerChannel::HandleRequest(int fd)
00158 {
00159     pair<int, JackClientSocket*> elem = fSocketTable[fd];
00160     JackClientSocket* socket = elem.second;
00161     assert(socket);
00162 
00163     // Read header
00164     JackRequest header;
00165     if (header.Read(socket) < 0) {
00166         jack_log("HandleRequest: cannot read header");
00167         ClientKill(fd);  // TO CHECK SOLARIS
00168         return false;
00169     }
00170 
00171     if (fd == JackServerGlobals::fRTNotificationSocket && header.fType != JackRequest::kNotification) {
00172         jack_error("fRTNotificationSocket = %d", JackServerGlobals::fRTNotificationSocket);
00173         jack_error("JackSocketServerChannel::HandleRequest : incorrect notification !!");
00174         return true;
00175     }
00176 
00177     // Read data
00178     switch (header.fType) {
00179 
00180         case JackRequest::kClientCheck: {
00181             jack_log("JackRequest::ClientCheck");
00182             JackClientCheckRequest req;
00183             JackClientCheckResult res;
00184             if (req.Read(socket) == 0)
00185                 res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus);
00186             if (res.Write(socket) < 0)
00187                 jack_error("JackRequest::ClientCheck write error name = %s", req.fName);
00188             break;
00189         }
00190 
00191         case JackRequest::kClientOpen: {
00192             jack_log("JackRequest::ClientOpen");
00193             JackClientOpenRequest req;
00194             JackClientOpenResult res;
00195             if (req.Read(socket) == 0)
00196                 ClientAdd(fd, req.fName, req.fPID, req.fUUID, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult);
00197             if (res.Write(socket) < 0)
00198                 jack_error("JackRequest::ClientOpen write error name = %s", req.fName);
00199             break;
00200         }
00201 
00202         case JackRequest::kClientClose: {
00203             jack_log("JackRequest::ClientClose");
00204             JackClientCloseRequest req;
00205             JackResult res;
00206             if (req.Read(socket) == 0)
00207                 res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum);
00208             if (res.Write(socket) < 0)
00209                 jack_error("JackRequest::ClientClose write error ref = %d", req.fRefNum);
00210             ClientRemove(fd, req.fRefNum);
00211             break;
00212         }
00213 
00214         case JackRequest::kActivateClient: {
00215             JackActivateRequest req;
00216             JackResult res;
00217             jack_log("JackRequest::ActivateClient");
00218             if (req.Read(socket) == 0)
00219                 res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fIsRealTime);
00220             if (res.Write(socket) < 0)
00221                 jack_error("JackRequest::ActivateClient write error ref = %d", req.fRefNum);
00222             break;
00223         }
00224 
00225         case JackRequest::kDeactivateClient: {
00226             jack_log("JackRequest::DeactivateClient");
00227             JackDeactivateRequest req;
00228             JackResult res;
00229             if (req.Read(socket) == 0)
00230                 res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum);
00231             if (res.Write(socket) < 0)
00232                 jack_error("JackRequest::DeactivateClient write error ref = %d", req.fRefNum);
00233             break;
00234         }
00235 
00236         case JackRequest::kRegisterPort: {
00237             jack_log("JackRequest::RegisterPort");
00238             JackPortRegisterRequest req;
00239             JackPortRegisterResult res;
00240             if (req.Read(socket) == 0)
00241                 res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex);
00242             if (res.Write(socket) < 0)
00243                 jack_error("JackRequest::RegisterPort write error ref = %d", req.fRefNum);
00244             break;
00245         }
00246 
00247         case JackRequest::kUnRegisterPort: {
00248             jack_log("JackRequest::UnRegisterPort");
00249             JackPortUnRegisterRequest req;
00250             JackResult res;
00251             if (req.Read(socket) == 0)
00252                 res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex);
00253             if (res.Write(socket) < 0)
00254                 jack_error("JackRequest::UnRegisterPort write error ref = %d", req.fRefNum);
00255             break;
00256         }
00257 
00258         case JackRequest::kConnectNamePorts: {
00259             jack_log("JackRequest::ConnectNamePorts");
00260             JackPortConnectNameRequest req;
00261             JackResult res;
00262             if (req.Read(socket) == 0)
00263                 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
00264             if (res.Write(socket) < 0)
00265                 jack_error("JackRequest::ConnectNamePorts write error ref = %d", req.fRefNum);
00266             break;
00267         }
00268 
00269         case JackRequest::kDisconnectNamePorts: {
00270             jack_log("JackRequest::DisconnectNamePorts");
00271             JackPortDisconnectNameRequest req;
00272             JackResult res;
00273             if (req.Read(socket) == 0)
00274                 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
00275             if (res.Write(socket) < 0)
00276                 jack_error("JackRequest::DisconnectNamePorts write error ref = %d", req.fRefNum);
00277             break;
00278         }
00279 
00280         case JackRequest::kConnectPorts: {
00281             jack_log("JackRequest::ConnectPorts");
00282             JackPortConnectRequest req;
00283             JackResult res;
00284             if (req.Read(socket) == 0)
00285                 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
00286             if (res.Write(socket) < 0)
00287                 jack_error("JackRequest::ConnectPorts write error ref = %d", req.fRefNum);
00288             break;
00289         }
00290 
00291         case JackRequest::kDisconnectPorts: {
00292             jack_log("JackRequest::DisconnectPorts");
00293             JackPortDisconnectRequest req;
00294             JackResult res;
00295             if (req.Read(socket) == 0)
00296                 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
00297             if (res.Write(socket) < 0)
00298                 jack_error("JackRequest::DisconnectPorts write error ref = %d", req.fRefNum);
00299             break;
00300         }
00301 
00302         case JackRequest::kPortRename: {
00303             jack_log("JackRequest::PortRename");
00304             JackPortRenameRequest req;
00305             JackResult res;
00306             if (req.Read(socket) == 0)
00307                 res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName);
00308             if (res.Write(socket) < 0)
00309                 jack_error("JackRequest::PortRename write error ref = %d", req.fRefNum);
00310             break;
00311         }
00312 
00313         case JackRequest::kSetBufferSize: {
00314             jack_log("JackRequest::SetBufferSize");
00315             JackSetBufferSizeRequest req;
00316             JackResult res;
00317             if (req.Read(socket) == 0)
00318                 res.fResult = fServer->SetBufferSize(req.fBufferSize);
00319             if (res.Write(socket) < 0)
00320                 jack_error("JackRequest::SetBufferSize write error");
00321             break;
00322         }
00323 
00324         case JackRequest::kSetFreeWheel: {
00325             jack_log("JackRequest::SetFreeWheel");
00326             JackSetFreeWheelRequest req;
00327             JackResult res;
00328             if (req.Read(socket) == 0)
00329                 res.fResult = fServer->SetFreewheel(req.fOnOff);
00330             if (res.Write(socket) < 0)
00331                 jack_error("JackRequest::SetFreeWheel write error");
00332             break;
00333         }
00334 
00335          case JackRequest::kComputeTotalLatencies: {
00336             jack_log("JackRequest::ComputeTotalLatencies");
00337             JackComputeTotalLatenciesRequest req;
00338             JackResult res;
00339             if (req.Read(socket) == 0)
00340                 res.fResult = fServer->GetEngine()->ComputeTotalLatencies();
00341             if (res.Write(socket) < 0)
00342                 jack_error("JackRequest::ComputeTotalLatencies write error");
00343             break;
00344         }
00345 
00346         case JackRequest::kReleaseTimebase: {
00347             jack_log("JackRequest::ReleaseTimebase");
00348             JackReleaseTimebaseRequest req;
00349             JackResult res;
00350             if (req.Read(socket) == 0)
00351                 res.fResult = fServer->ReleaseTimebase(req.fRefNum);
00352             if (res.Write(socket) < 0)
00353                 jack_error("JackRequest::ReleaseTimebase write error ref = %d", req.fRefNum);
00354             break;
00355         }
00356 
00357         case JackRequest::kSetTimebaseCallback: {
00358             jack_log("JackRequest::SetTimebaseCallback");
00359             JackSetTimebaseCallbackRequest req;
00360             JackResult res;
00361             if (req.Read(socket) == 0)
00362                 res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal);
00363             if (res.Write(socket) < 0)
00364                 jack_error("JackRequest::SetTimebaseCallback write error ref = %d", req.fRefNum);
00365             break;
00366         }
00367 
00368         case JackRequest::kGetInternalClientName: {
00369             jack_log("JackRequest::GetInternalClientName");
00370             JackGetInternalClientNameRequest req;
00371             JackGetInternalClientNameResult res;
00372             if (req.Read(socket) == 0)
00373                 res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName);
00374             if (res.Write(socket) < 0)
00375                 jack_error("JackRequest::GetInternalClientName write error ref = %d", req.fRefNum);
00376             break;
00377         }
00378 
00379         case JackRequest::kInternalClientHandle: {
00380             jack_log("JackRequest::InternalClientHandle");
00381             JackInternalClientHandleRequest req;
00382             JackInternalClientHandleResult res;
00383             if (req.Read(socket) == 0)
00384                 res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum);
00385             if (res.Write(socket) < 0)
00386                 jack_error("JackRequest::InternalClientHandle write error ref = %d", req.fRefNum);
00387             break;
00388         }
00389 
00390         case JackRequest::kInternalClientLoad: {
00391             jack_log("JackRequest::InternalClientLoad");
00392             JackInternalClientLoadRequest req;
00393             JackInternalClientLoadResult res;
00394             if (req.Read(socket) == 0)
00395                 res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus);
00396             if (res.Write(socket) < 0)
00397                 jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName);
00398             break;
00399         }
00400 
00401         case JackRequest::kInternalClientUnload: {
00402             jack_log("JackRequest::InternalClientUnload");
00403             JackInternalClientUnloadRequest req;
00404             JackInternalClientUnloadResult res;
00405             if (req.Read(socket) == 0)
00406                 res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus);
00407             if (res.Write(socket) < 0)
00408                 jack_error("JackRequest::InternalClientUnload write error ref = %d", req.fRefNum);
00409             break;
00410         }
00411 
00412         case JackRequest::kNotification: {
00413             jack_log("JackRequest::Notification");
00414             JackClientNotificationRequest req;
00415             if (req.Read(socket) == 0) {
00416                 if (req.fNotify == kQUIT) {
00417                     jack_log("JackRequest::Notification kQUIT");
00418                     throw JackQuitException();
00419                 } else {
00420                     fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
00421                 }
00422             }
00423             break;
00424         }
00425 
00426         case JackRequest::kSessionNotify: {
00427             jack_log("JackRequest::SessionNotify");
00428             JackSessionNotifyRequest req;
00429             JackSessionNotifyResult res;
00430             if (req.Read(socket) == 0) {
00431                 fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket);
00432             }
00433             break;
00434         }
00435 
00436         case JackRequest::kSessionReply: {
00437             jack_log("JackRequest::SessionReply");
00438             JackSessionReplyRequest req;
00439             JackResult res;
00440             if (req.Read(socket) == 0) {
00441                 fServer->GetEngine()->SessionReply(req.fRefNum);
00442                 res.fResult = 0;
00443             }
00444             if (res.Write(socket) < 0)
00445                 jack_error("JackRequest::SessionReply write error");
00446             break;
00447         }
00448 
00449         case JackRequest::kGetClientByUUID: {
00450             jack_log("JackRequest::GetClientByUUID");
00451             JackGetClientNameRequest req;
00452             JackClientNameResult res;
00453             if (req.Read(socket) == 0) {
00454                 fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName, &res.fResult);
00455             }
00456             if (res.Write(socket) < 0)
00457                 jack_error("JackRequest::GetClientByUUID write error");
00458             break;
00459         }
00460 
00461         case JackRequest::kGetUUIDByClient: {
00462             jack_log("JackRequest::GetUUIDByClient");
00463             JackGetUUIDRequest req;
00464             JackUUIDResult res;
00465             if (req.Read(socket) == 0) {
00466                 fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult);
00467             }
00468             if (res.Write(socket) < 0)
00469                 jack_error("JackRequest::GetUUIDByClient write error");
00470             break;
00471         }
00472 
00473         case JackRequest::kReserveClientName: {
00474             jack_log("JackRequest::ReserveClientName");
00475             JackReserveNameRequest req;
00476             JackResult res;
00477             if (req.Read(socket) == 0) {
00478                 fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID, &res.fResult);
00479             }
00480             if (res.Write(socket) < 0)
00481                 jack_error("JackRequest::ReserveClientName write error");
00482             break;
00483         }
00484 
00485         case JackRequest::kClientHasSessionCallback: {
00486             jack_log("JackRequest::ClientHasSessionCallback");
00487             JackClientHasSessionCallbackRequest req;
00488             JackResult res;
00489             if (req.Read(socket) == 0) {
00490                 fServer->GetEngine()->ClientHasSessionCallbackRequest(req.fName, &res.fResult);
00491             }
00492             if (res.Write(socket) < 0)
00493                 jack_error("JackRequest::ClientHasSessionCallback write error");
00494             break;
00495         }
00496 
00497         default:
00498             jack_error("Unknown request %ld", header.fType);
00499             break;
00500     }
00501 
00502     return true;
00503 }
00504 
00505 void JackSocketServerChannel::BuildPoolTable()
00506 {
00507     if (fRebuild) {
00508         fRebuild = false;
00509         delete[] fPollTable;
00510         fPollTable = new pollfd[fSocketTable.size() + 1];
00511 
00512         jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable.size() + 1);
00513 
00514         // First fd is the server request socket
00515         fPollTable[0].fd = fRequestListenSocket.GetFd();
00516         fPollTable[0].events = POLLIN | POLLERR;
00517 
00518         // Next fd for clients
00519         map<int, pair<int, JackClientSocket*> >::iterator it;
00520         int i;
00521 
00522         for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) {
00523             jack_log("fSocketTable i = %ld fd = %ld", i, it->first);
00524             fPollTable[i].fd = it->first;
00525             fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
00526         }
00527     }
00528 }
00529 
00530 bool JackSocketServerChannel::Init()
00531 {
00532     sigset_t set;
00533     sigemptyset(&set);
00534     sigaddset(&set, SIGPIPE);
00535     pthread_sigmask(SIG_BLOCK, &set, 0);
00536     return true;
00537 }
00538 
00539 bool JackSocketServerChannel::Execute()
00540 {
00541     try {
00542 
00543         // Global poll
00544         if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) {
00545             jack_error("Engine poll failed err = %s request thread quits...", strerror(errno));
00546             return false;
00547         } else {
00548 
00549             // Poll all clients
00550             for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) {
00551                 int fd = fPollTable[i].fd;
00552                 jack_log("fPollTable i = %ld fd = %ld", i, fd);
00553                 if (fPollTable[i].revents & ~POLLIN) {
00554                     jack_log("Poll client error err = %s", strerror(errno));
00555                     ClientKill(fd);
00556                 } else if (fPollTable[i].revents & POLLIN) {
00557                     if (!HandleRequest(fd))
00558                         jack_log("Could not handle external client request");
00559                 }
00560             }
00561 
00562             // Check the server request socket */
00563             if (fPollTable[0].revents & POLLERR)
00564                 jack_error("Error on server request socket err = %s", strerror(errno));
00565 
00566             if (fPollTable[0].revents & POLLIN)
00567                 ClientCreate();
00568         }
00569 
00570         BuildPoolTable();
00571         return true;
00572 
00573     } catch (JackQuitException& e) {
00574         jack_log("JackMachServerChannel::Execute JackQuitException");
00575         return false;
00576     }
00577 }
00578 
00579 } // end of namespace
00580 
00581