/* Copyright (C) 2004-2006 Grame This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "JackSocketServerChannel.h" #include "JackRequest.h" #include "JackServer.h" #include "JackEngine.h" #include "JackGlobals.h" #include "JackClient.h" #include using namespace std; namespace Jack { JackSocketServerChannel::JackSocketServerChannel() { fThread = JackGlobals::MakeThread(this); fPollTable = NULL; fRebuild = true; } JackSocketServerChannel::~JackSocketServerChannel() { delete fThread; delete[] fPollTable; } int JackSocketServerChannel::Open(JackServer* server) { JackLog("JackSocketServerChannel::Open \n"); fServer = server; // Prepare request socket if (fRequestListenSocket.Bind(jack_server_dir, 0) < 0) { JackLog("JackSocketServerChannel::Open : cannot create result listen socket\n"); return -1; } // Prepare for poll BuildPoolTable(); // Start listening if (fThread->Start() != 0) { jack_error("Cannot start Jack server listener"); goto error; } return 0; error: fRequestListenSocket.Close(); return -1; } void JackSocketServerChannel::Close() { fThread->Kill(); fRequestListenSocket.Close(); } void JackSocketServerChannel::CreateClient() { JackLog("JackSocketServerChannel::CreateClient socket\n"); JackClientSocket* socket = fRequestListenSocket.Accept(); if (socket) { fSocketTable[socket->GetFd()] = make_pair( -1, socket); fRebuild = true; } else { jack_error("Client socket cannot be created"); } } void JackSocketServerChannel::AddClient(int fd, char* name, int* shared_engine, int* shared_client, int* shared_ports, int* result) { JackLog("JackSocketServerChannel::AddClient\n"); int refnum = -1; *result = fServer->GetEngine()->ClientNew(name, &refnum, shared_engine, shared_client, shared_ports); if (*result == 0) { fSocketTable[fd].first = refnum; fRebuild = true; } else { jack_error("Cannot create new client"); } } void JackSocketServerChannel::RemoveClient(int fd, int refnum) { pair elem = fSocketTable[fd]; JackClientSocket* socket = elem.second; assert(socket); JackLog("JackSocketServerChannel::RemoveClient ref = %d\n", refnum); fSocketTable.erase(fd); socket->Close(); delete socket; fRebuild = true; } void JackSocketServerChannel::KillClient(int fd) { pair elem = fSocketTable[fd]; JackClientSocket* socket = elem.second; int refnum = elem.first; assert(socket); JackLog("JackSocketServerChannel::KillClient ref = %d\n", refnum); if (refnum == -1) { // Should never happen... correspond to a client that started the socket but never opened... jack_error("Client not opened"); } else { fServer->Notify(refnum, JackNotifyChannelInterface::kDeadClient, 0); } fSocketTable.erase(fd); socket->Close(); delete socket; fRebuild = true; } int JackSocketServerChannel::HandleRequest(int fd) { pair elem = fSocketTable[fd]; JackClientSocket* socket = elem.second; assert(socket); // Read header JackRequest header; if (header.Read(socket) < 0) { jack_error("HandleRequest: cannot read header"); return -1; } // Read data switch (header.fType) { case JackRequest::kClientNew: { JackLog("JackRequest::ClientNew\n"); JackClientNewRequest req; JackClientNewResult res; req.Read(socket); AddClient(fd, req.fName, &res.fSharedEngine, &res.fSharedClient, &res.fSharedPorts, &res.fResult); res.Write(socket); break; } case JackRequest::kClientClose: { JackLog("JackRequest::ClientClose\n"); JackClientCloseRequest req; JackResult res; req.Read(socket); res.fResult = fServer->GetEngine()->ClientClose(req.fRefNum); res.Write(socket); RemoveClient(fd, req.fRefNum); break; } case JackRequest::kActivateClient: { JackActivateRequest req; JackResult res; JackLog("JackRequest::ActivateClient\n"); req.Read(socket); res.fResult = fServer->Activate(req.fRefNum); res.Write(socket); break; } case JackRequest::kDeactivateClient: { JackLog("JackRequest::DeactivateClient\n"); JackDeactivateRequest req; JackResult res; req.Read(socket); res.fResult = fServer->Deactivate(req.fRefNum); res.Write(socket); break; } case JackRequest::kRegisterPort: { JackLog("JackRequest::RegisterPort\n"); JackPortRegisterRequest req; JackPortRegisterResult res; req.Read(socket); res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fFlags, req.fBufferSize, &res.fPortIndex); res.Write(socket); break; } case JackRequest::kUnRegisterPort: { JackLog("JackRequest::UnRegisterPort\n"); JackPortUnRegisterRequest req; JackResult res; req.Read(socket); res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex); res.Write(socket); break; } case JackRequest::kConnectNamePorts: { JackLog("JackRequest::ConnectPorts\n"); JackPortConnectNameRequest req; JackResult res; req.Read(socket); res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); res.Write(socket); break; } case JackRequest::kDisconnectNamePorts: { JackLog("JackRequest::DisconnectPorts\n"); JackPortDisconnectNameRequest req; JackResult res; req.Read(socket); res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); res.Write(socket); break; } case JackRequest::kConnectPorts: { JackLog("JackRequest::ConnectPorts\n"); JackPortConnectRequest req; JackResult res; req.Read(socket); res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); res.Write(socket); break; } case JackRequest::kDisconnectPorts: { JackLog("JackRequest::DisconnectPorts\n"); JackPortDisconnectRequest req; JackResult res; req.Read(socket); res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); res.Write(socket); break; } case JackRequest::kSetBufferSize: { JackLog("JackRequest::SetBufferSize\n"); JackSetBufferSizeRequest req; JackResult res; req.Read(socket); res.fResult = fServer->SetBufferSize(req.fBufferSize); res.Write(socket); break; } case JackRequest::kSetFreeWheel: { JackLog("JackRequest::SetFreeWheel\n"); JackSetFreeWheelRequest req; JackResult res; req.Read(socket); res.fResult = fServer->SetFreewheel(req.fOnOff); res.Write(socket); break; } case JackRequest::kReleaseTimebase: { JackLog("JackRequest::kReleaseTimebase\n"); JackReleaseTimebaseRequest req; JackResult res; req.Read(socket); res.fResult = fServer->GetEngine()->ReleaseTimebase(req.fRefNum); res.Write(socket); break; } case JackRequest::kSetTimebaseCallback: { JackLog("JackRequest::kSetTimebaseCallback\n"); JackSetTimebaseCallbackRequest req; JackResult res; req.Read(socket); res.fResult = fServer->GetEngine()->SetTimebaseCallback(req.fRefNum, req.fConditionnal); res.Write(socket); break; } case JackRequest::kNotification: { JackLog("JackRequest::Notification\n"); JackClientNotificationRequest req; req.Read(socket); fServer->Notify(req.fRefNum, req.fNotify, req.fValue); break; } default: JackLog("Unknown request %ld\n", header.fType); break; } return 0; } void JackSocketServerChannel::BuildPoolTable() { if (fRebuild) { fRebuild = false; delete[] fPollTable; fPollTable = new pollfd[fSocketTable.size() + 1]; JackLog("JackSocketServerChannel::BuildPoolTable size = %d\n", fSocketTable.size() + 1); // First fd is the server request socket fPollTable[0].fd = fRequestListenSocket.GetFd(); fPollTable[0].events = POLLIN | POLLERR; // Next fd for clients map >::iterator it; int i; for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) { JackLog("fSocketTable i = %ld fd = %ld\n", i, it->first); fPollTable[i].fd = it->first; fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; } } } bool JackSocketServerChannel::Execute() { // Global poll if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) { jack_error("Engine poll failed err = %s request thread quits...", strerror(errno)); return false; } else { // Poll all clients for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) { int fd = fPollTable[i].fd; JackLog("fPollTable i = %ld fd = %ld\n", i, fd); if (fPollTable[i].revents & ~POLLIN) { jack_error("Poll client error err = %s", strerror(errno)); KillClient(fd); } else if (fPollTable[i].revents & POLLIN) { if (HandleRequest(fd) < 0) { jack_error("Could not handle external client request"); //RemoveClient(fd); TO CHECK } } } // Check the server request socket */ if (fPollTable[0].revents & POLLERR) { jack_error("Error on server request socket err = %s", strerror(errno)); //return false; TO CHECK } if (fPollTable[0].revents & POLLIN) { CreateClient(); } } BuildPoolTable(); return true; } } // end of namespace