Add missing methods in JackDebugClient(2).
[jack2.git] / posix / JackSocketServerChannel.cpp
blob195c41c40a51d819415c94174194450866fd84b4
1 /*
2 Copyright (C) 2004-2008 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "JackSocketServerChannel.h"
21 #include "JackRequest.h"
22 #include "JackServer.h"
23 #include "JackLockedEngine.h"
24 #include "JackGlobals.h"
25 #include "JackServerGlobals.h"
26 #include "JackClient.h"
27 #include "JackTools.h"
28 #include "JackNotification.h"
29 #include "JackException.h"
31 #include <assert.h>
32 #include <signal.h>
34 using namespace std;
36 namespace Jack
39 JackSocketServerChannel::JackSocketServerChannel():
40 fThread(this), fDecoder(NULL)
42 fPollTable = NULL;
43 fRebuild = true;
46 JackSocketServerChannel::~JackSocketServerChannel()
48 delete[] fPollTable;
51 int JackSocketServerChannel::Open(const char* server_name, JackServer* server)
53 jack_log("JackSocketServerChannel::Open");
55 // Prepare request socket
56 if (fRequestListenSocket.Bind(jack_server_dir, server_name, 0) < 0) {
57 jack_log("JackSocketServerChannel::Open : cannot create result listen socket");
58 return -1;
61 // Prepare for poll
62 BuildPoolTable();
64 fDecoder = new JackRequestDecoder(server, this);
65 fServer = server;
66 return 0;
69 void JackSocketServerChannel::Close()
71 fRequestListenSocket.Close();
73 // Close remaining client sockets
74 std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
76 for (it = fSocketTable.begin(); it != fSocketTable.end(); it++) {
77 pair<int, JackClientSocket*> elem = (*it).second;
78 JackClientSocket* socket = elem.second;
79 assert(socket);
80 socket->Close();
81 delete socket;
84 delete fDecoder;
85 fDecoder = NULL;
88 int JackSocketServerChannel::Start()
90 if (fThread.Start() != 0) {
91 jack_error("Cannot start Jack server listener");
92 return -1;
93 } else {
94 return 0;
98 void JackSocketServerChannel::Stop()
100 fThread.Kill();
103 void JackSocketServerChannel::ClientCreate()
105 jack_log("JackSocketServerChannel::ClientCreate socket");
106 JackClientSocket* socket = fRequestListenSocket.Accept();
107 if (socket) {
108 fSocketTable[socket->GetFd()] = make_pair(-1, socket);
109 fRebuild = true;
110 } else {
111 jack_error("Client socket cannot be created");
115 int JackSocketServerChannel::GetFd(JackClientSocket* socket_aux)
117 std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
119 for (it = fSocketTable.begin(); it != fSocketTable.end(); it++) {
120 pair<int, JackClientSocket*> elem = (*it).second;
121 JackClientSocket* socket = elem.second;
122 if (socket_aux == socket) {
123 return (*it).first;
126 return -1;
129 void JackSocketServerChannel::ClientAdd(detail::JackChannelTransactionInterface* socket_aux, JackClientOpenRequest* req, JackClientOpenResult *res)
131 int refnum = -1;
132 res->fResult = fServer->GetEngine()->ClientExternalOpen(req->fName, req->fPID, req->fUUID, &refnum, &res->fSharedEngine, &res->fSharedClient, &res->fSharedGraph);
133 if (res->fResult == 0) {
134 JackClientSocket* socket = dynamic_cast<JackClientSocket*>(socket_aux);
135 assert(socket);
136 int fd = GetFd(socket);
137 assert(fd >= 0);
138 fSocketTable[fd].first = refnum;
139 fRebuild = true;
140 jack_log("JackSocketServerChannel::ClientAdd ref = %d fd = %d", refnum, fd);
141 #ifdef __APPLE__
142 int on = 1;
143 if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) {
144 jack_log("JackSocketServerChannel::ClientAdd : setsockopt SO_NOSIGPIPE fd = %ld err = %s", fd, strerror(errno));
146 #endif
147 } else {
148 jack_error("Cannot create new client");
152 void JackSocketServerChannel::ClientRemove(detail::JackChannelTransactionInterface* socket_aux, int refnum)
154 JackClientSocket* socket = dynamic_cast<JackClientSocket*>(socket_aux);
155 assert(socket);
156 int fd = GetFd(socket);
157 assert(fd >= 0);
159 jack_log("JackSocketServerChannel::ClientRemove ref = %d fd = %d", refnum, fd);
160 fSocketTable.erase(fd);
161 socket->Close();
162 delete socket;
163 fRebuild = true;
166 void JackSocketServerChannel::ClientKill(int fd)
168 pair<int, JackClientSocket*> elem = fSocketTable[fd];
169 JackClientSocket* socket = elem.second;
170 int refnum = elem.first;
171 assert(socket);
173 if (refnum == -1) { // Should never happen... correspond to a client that started the socket but never opened...
174 jack_log("Client was not opened : probably correspond to server_check");
175 } else {
176 fServer->ClientKill(refnum);
179 jack_log("JackSocketServerChannel::ClientKill ref = %d fd = %d", refnum, fd);
180 fSocketTable.erase(fd);
181 socket->Close();
182 delete socket;
183 fRebuild = true;
186 void JackSocketServerChannel::BuildPoolTable()
188 if (fRebuild) {
189 fRebuild = false;
190 delete[] fPollTable;
191 fPollTable = new pollfd[fSocketTable.size() + 1];
193 jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable.size() + 1);
195 // First fd is the server request socket
196 fPollTable[0].fd = fRequestListenSocket.GetFd();
197 fPollTable[0].events = POLLIN | POLLERR;
199 // Next fd for clients
200 map<int, pair<int, JackClientSocket*> >::iterator it;
201 int i;
203 for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) {
204 jack_log("JackSocketServerChannel::BuildPoolTable fSocketTable i = %ld fd = %ld", i, it->first);
205 fPollTable[i].fd = it->first;
206 fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
211 bool JackSocketServerChannel::Init()
213 sigset_t set;
214 sigemptyset(&set);
215 sigaddset(&set, SIGPIPE);
216 pthread_sigmask(SIG_BLOCK, &set, 0);
217 return true;
220 bool JackSocketServerChannel::Execute()
222 try {
224 // Global poll
225 if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) {
226 jack_error("JackSocketServerChannel::Execute : engine poll failed err = %s request thread quits...", strerror(errno));
227 return false;
228 } else {
230 // Poll all clients
231 for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) {
232 int fd = fPollTable[i].fd;
233 jack_log("JackSocketServerChannel::Execute : fPollTable i = %ld fd = %ld", i, fd);
234 if (fPollTable[i].revents & ~POLLIN) {
235 jack_log("JackSocketServerChannel::Execute : poll client error err = %s", strerror(errno));
236 ClientKill(fd);
237 } else if (fPollTable[i].revents & POLLIN) {
238 JackClientSocket* socket = fSocketTable[fd].second;
239 // Decode header
240 JackRequest header;
241 if (header.Read(socket) < 0) {
242 jack_log("JackSocketServerChannel::Execute : cannot decode header");
243 ClientKill(fd);
244 // Decode request
245 } else {
246 // Result is not needed here
247 fDecoder->HandleRequest(socket, header.fType);
252 // Check the server request socket */
253 if (fPollTable[0].revents & POLLERR) {
254 jack_error("Error on server request socket err = %s", strerror(errno));
257 if (fPollTable[0].revents & POLLIN) {
258 ClientCreate();
262 BuildPoolTable();
263 return true;
265 } catch (JackQuitException& e) {
266 jack_log("JackSocketServerChannel::Execute : JackQuitException");
267 return false;
271 } // end of namespace