Jack2 1.9.8

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