Jack2: JackSocketServerChannel.cpp Source File

Jack2 1.9.12

JackSocketServerChannel.cpp
1 /*
2 Copyright (C) 2004-2008 Grame
3
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.
8
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.
13
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.
17
18 */
19
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"
30
31 #include <assert.h>
32 #include <signal.h>
33
34 using namespace std;
35
36 namespace Jack
37 {
38
39 JackSocketServerChannel::JackSocketServerChannel():
40 fThread(this), fDecoder(NULL)
41 {
42 fPollTable = NULL;
43 fRebuild = true;
44 }
45
46 JackSocketServerChannel::~JackSocketServerChannel()
47 {
48 delete[] fPollTable;
49 }
50
51 int JackSocketServerChannel::Open(const char* server_name, JackServer* server)
52 {
53 jack_log("JackSocketServerChannel::Open");
54
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;
59 }
60
61 // Prepare for poll
62 BuildPoolTable();
63
64 fDecoder = new JackRequestDecoder(server, this);
65 fServer = server;
66 return 0;
67 }
68
69 void JackSocketServerChannel::Close()
70 {
71 fRequestListenSocket.Close();
72
73 // Close remaining client sockets
74 std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
75
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;
82 }
83
84 delete fDecoder;
85 fDecoder = NULL;
86 }
87
88 int JackSocketServerChannel::Start()
89 {
90 if (fThread.Start() != 0) {
91 jack_error("Cannot start Jack server listener");
92 return -1;
93 } else {
94 return 0;
95 }
96 }
97
98 void JackSocketServerChannel::Stop()
99 {
100 fThread.Stop();
101 }
102
103 void JackSocketServerChannel::ClientCreate()
104 {
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");
112 }
113 }
114
115 int JackSocketServerChannel::GetFd(JackClientSocket* socket_aux)
116 {
117 std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
118
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;
124 }
125 }
126 return -1;
127 }
128
129 void JackSocketServerChannel::ClientAdd(detail::JackChannelTransactionInterface* socket_aux, JackClientOpenRequest* req, JackClientOpenResult *res)
130 {
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));
145 }
146 #endif
147 } else {
148 jack_error("Cannot create new client");
149 }
150 }
151
152 void JackSocketServerChannel::ClientRemove(detail::JackChannelTransactionInterface* socket_aux, int refnum)
153 {
154 JackClientSocket* socket = dynamic_cast<JackClientSocket*>(socket_aux);
155 assert(socket);
156 int fd = GetFd(socket);
157 assert(fd >= 0);
158
159 jack_log("JackSocketServerChannel::ClientRemove ref = %d fd = %d", refnum, fd);
160 fSocketTable.erase(fd);
161 socket->Close();
162 delete socket;
163 fRebuild = true;
164 }
165
166 void JackSocketServerChannel::ClientKill(int fd)
167 {
168 pair<int, JackClientSocket*> elem = fSocketTable[fd];
169 JackClientSocket* socket = elem.second;
170 int refnum = elem.first;
171 assert(socket);
172
173 jack_log("JackSocketServerChannel::ClientKill ref = %d fd = %d", refnum, fd);
174 if (refnum == -1) { // Should never happen... correspond to a client that started the socket but never opened...
175 jack_log("Client was not opened : probably correspond to server_check");
176 } else {
177 fServer->GetEngine()->ClientKill(refnum);
178 }
179
180 fSocketTable.erase(fd);
181 socket->Close();
182 delete socket;
183 fRebuild = true;
184 }
185
186 void JackSocketServerChannel::BuildPoolTable()
187 {
188 if (fRebuild) {
189 fRebuild = false;
190 delete[] fPollTable;
191 fPollTable = new pollfd[fSocketTable.size() + 1];
192
193 jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable.size() + 1);
194
195 // First fd is the server request socket
196 fPollTable[0].fd = fRequestListenSocket.GetFd();
197 fPollTable[0].events = POLLIN | POLLERR;
198
199 // Next fd for clients
200 map<int, pair<int, JackClientSocket*> >::iterator it;
201 int i;
202
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;
207 }
208 }
209 }
210
211 bool JackSocketServerChannel::Init()
212 {
213 sigset_t set;
214 sigemptyset(&set);
215 sigaddset(&set, SIGPIPE);
216 pthread_sigmask(SIG_BLOCK, &set, 0);
217 return true;
218 }
219
220 bool JackSocketServerChannel::Execute()
221 {
222 try {
223
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 {
229
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);
248 }
249 }
250 }
251
252 // Check the server request socket */
253 if (fPollTable[0].revents & POLLERR) {
254 jack_error("Error on server request socket err = %s", strerror(errno));
255 }
256
257 if (fPollTable[0].revents & POLLIN) {
258 ClientCreate();
259 }
260 }
261
262 BuildPoolTable();
263 return true;
264
265 } catch (JackQuitException& e) {
266 jack_log("JackSocketServerChannel::Execute : JackQuitException");
267 return false;
268 }
269 }
270
271 } // end of namespace
272
273
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
Jack::JackSocketServerChannel::Init
bool Init()
Definition: JackSocketServerChannel.cpp:211
jack_log
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108