jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

571 lines
20KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "JackSocketServerChannel.h"
  16. #include "JackRequest.h"
  17. #include "JackServer.h"
  18. #include "JackLockedEngine.h"
  19. #include "JackGlobals.h"
  20. #include "JackServerGlobals.h"
  21. #include "JackClient.h"
  22. #include "JackTools.h"
  23. #include "JackNotification.h"
  24. #include "JackException.h"
  25. #include <assert.h>
  26. #include <signal.h>
  27. using namespace std;
  28. namespace Jack
  29. {
  30. JackSocketServerChannel::JackSocketServerChannel():
  31. fThread(this)
  32. {
  33. fPollTable = NULL;
  34. fRebuild = true;
  35. }
  36. JackSocketServerChannel::~JackSocketServerChannel()
  37. {
  38. delete[] fPollTable;
  39. }
  40. int JackSocketServerChannel::Open(const char* server_name, JackServer* server)
  41. {
  42. jack_log("JackSocketServerChannel::Open");
  43. // Prepare request socket
  44. if (fRequestListenSocket.Bind(jack_server_dir, server_name, 0) < 0) {
  45. jack_log("JackSocketServerChannel::Open : cannot create result listen socket");
  46. return -1;
  47. }
  48. // Prepare for poll
  49. BuildPoolTable();
  50. fServer = server;
  51. return 0;
  52. }
  53. void JackSocketServerChannel::Close()
  54. {
  55. fThread.Stop();
  56. fRequestListenSocket.Close();
  57. // Close remaining client sockets
  58. std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
  59. for (it = fSocketTable.begin(); it != fSocketTable.end(); it++) {
  60. pair<int, JackClientSocket*> elem = (*it).second;
  61. JackClientSocket* socket = elem.second;
  62. assert(socket);
  63. socket->Close();
  64. delete socket;
  65. }
  66. }
  67. int JackSocketServerChannel::Start()
  68. {
  69. if (fThread.Start() != 0) {
  70. jack_error("Cannot start Jack server listener");
  71. return -1;
  72. }
  73. return 0;
  74. }
  75. void JackSocketServerChannel::ClientCreate()
  76. {
  77. jack_log("JackSocketServerChannel::ClientCreate socket");
  78. JackClientSocket* socket = fRequestListenSocket.Accept();
  79. if (socket) {
  80. fSocketTable[socket->GetFd()] = make_pair( -1, socket);
  81. fRebuild = true;
  82. } else {
  83. jack_error("Client socket cannot be created");
  84. }
  85. }
  86. void JackSocketServerChannel::ClientAdd(int fd, char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
  87. {
  88. jack_log("JackSocketServerChannel::ClientAdd");
  89. int refnum = -1;
  90. *result = fServer->GetEngine()->ClientExternalOpen(name, pid, uuid, &refnum, shared_engine, shared_client, shared_graph);
  91. if (*result == 0) {
  92. fSocketTable[fd].first = refnum;
  93. fRebuild = true;
  94. #ifdef __APPLE__
  95. int on = 1;
  96. if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) {
  97. jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fd, strerror(errno));
  98. }
  99. #endif
  100. } else {
  101. jack_error("Cannot create new client");
  102. }
  103. }
  104. void JackSocketServerChannel::ClientRemove(int fd, int refnum)
  105. {
  106. pair<int, JackClientSocket*> elem = fSocketTable[fd];
  107. JackClientSocket* socket = elem.second;
  108. assert(socket);
  109. jack_log("JackSocketServerChannel::ClientRemove ref = %d", refnum);
  110. fSocketTable.erase(fd);
  111. socket->Close();
  112. delete socket;
  113. fRebuild = true;
  114. }
  115. void JackSocketServerChannel::ClientKill(int fd)
  116. {
  117. pair<int, JackClientSocket*> elem = fSocketTable[fd];
  118. JackClientSocket* socket = elem.second;
  119. int refnum = elem.first;
  120. assert(socket);
  121. jack_log("JackSocketServerChannel::ClientKill ref = %d", refnum);
  122. if (refnum == -1) { // Should never happen... correspond to a client that started the socket but never opened...
  123. jack_log("Client was not opened : probably correspond to server_check");
  124. } else {
  125. fServer->ClientKill(refnum);
  126. }
  127. fSocketTable.erase(fd);
  128. socket->Close();
  129. delete socket;
  130. fRebuild = true;
  131. }
  132. bool JackSocketServerChannel::HandleRequest(int fd)
  133. {
  134. pair<int, JackClientSocket*> elem = fSocketTable[fd];
  135. JackClientSocket* socket = elem.second;
  136. assert(socket);
  137. // Read header
  138. JackRequest header;
  139. if (header.Read(socket) < 0) {
  140. jack_log("HandleRequest: cannot read header");
  141. ClientKill(fd); // TO CHECK SOLARIS
  142. return false;
  143. }
  144. if (fd == JackServerGlobals::fRTNotificationSocket && header.fType != JackRequest::kNotification) {
  145. jack_error("fRTNotificationSocket = %d", JackServerGlobals::fRTNotificationSocket);
  146. jack_error("JackSocketServerChannel::HandleRequest : incorrect notification !!");
  147. return true;
  148. }
  149. // Read data
  150. switch (header.fType) {
  151. case JackRequest::kClientCheck: {
  152. jack_log("JackRequest::ClientCheck");
  153. JackClientCheckRequest req;
  154. JackClientCheckResult res;
  155. if (req.Read(socket) == 0)
  156. res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus);
  157. if (res.Write(socket) < 0)
  158. jack_error("JackRequest::ClientCheck write error name = %s", req.fName);
  159. break;
  160. }
  161. case JackRequest::kClientOpen: {
  162. jack_log("JackRequest::ClientOpen");
  163. JackClientOpenRequest req;
  164. JackClientOpenResult res;
  165. if (req.Read(socket) == 0)
  166. ClientAdd(fd, req.fName, req.fPID, req.fUUID, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult);
  167. if (res.Write(socket) < 0)
  168. jack_error("JackRequest::ClientOpen write error name = %s", req.fName);
  169. break;
  170. }
  171. case JackRequest::kClientClose: {
  172. jack_log("JackRequest::ClientClose");
  173. JackClientCloseRequest req;
  174. JackResult res;
  175. if (req.Read(socket) == 0)
  176. res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum);
  177. if (res.Write(socket) < 0)
  178. jack_error("JackRequest::ClientClose write error ref = %d", req.fRefNum);
  179. ClientRemove(fd, req.fRefNum);
  180. break;
  181. }
  182. case JackRequest::kActivateClient: {
  183. JackActivateRequest req;
  184. JackResult res;
  185. jack_log("JackRequest::ActivateClient");
  186. if (req.Read(socket) == 0)
  187. res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fIsRealTime);
  188. if (res.Write(socket) < 0)
  189. jack_error("JackRequest::ActivateClient write error ref = %d", req.fRefNum);
  190. break;
  191. }
  192. case JackRequest::kDeactivateClient: {
  193. jack_log("JackRequest::DeactivateClient");
  194. JackDeactivateRequest req;
  195. JackResult res;
  196. if (req.Read(socket) == 0)
  197. res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum);
  198. if (res.Write(socket) < 0)
  199. jack_error("JackRequest::DeactivateClient write error ref = %d", req.fRefNum);
  200. break;
  201. }
  202. case JackRequest::kRegisterPort: {
  203. jack_log("JackRequest::RegisterPort");
  204. JackPortRegisterRequest req;
  205. JackPortRegisterResult res;
  206. if (req.Read(socket) == 0)
  207. res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex);
  208. if (res.Write(socket) < 0)
  209. jack_error("JackRequest::RegisterPort write error ref = %d", req.fRefNum);
  210. break;
  211. }
  212. case JackRequest::kUnRegisterPort: {
  213. jack_log("JackRequest::UnRegisterPort");
  214. JackPortUnRegisterRequest req;
  215. JackResult res;
  216. if (req.Read(socket) == 0)
  217. res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex);
  218. if (res.Write(socket) < 0)
  219. jack_error("JackRequest::UnRegisterPort write error ref = %d", req.fRefNum);
  220. break;
  221. }
  222. case JackRequest::kConnectNamePorts: {
  223. jack_log("JackRequest::ConnectNamePorts");
  224. JackPortConnectNameRequest req;
  225. JackResult res;
  226. if (req.Read(socket) == 0)
  227. res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
  228. if (res.Write(socket) < 0)
  229. jack_error("JackRequest::ConnectNamePorts write error ref = %d", req.fRefNum);
  230. break;
  231. }
  232. case JackRequest::kDisconnectNamePorts: {
  233. jack_log("JackRequest::DisconnectNamePorts");
  234. JackPortDisconnectNameRequest req;
  235. JackResult res;
  236. if (req.Read(socket) == 0)
  237. res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
  238. if (res.Write(socket) < 0)
  239. jack_error("JackRequest::DisconnectNamePorts write error ref = %d", req.fRefNum);
  240. break;
  241. }
  242. case JackRequest::kConnectPorts: {
  243. jack_log("JackRequest::ConnectPorts");
  244. JackPortConnectRequest req;
  245. JackResult res;
  246. if (req.Read(socket) == 0)
  247. res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
  248. if (res.Write(socket) < 0)
  249. jack_error("JackRequest::ConnectPorts write error ref = %d", req.fRefNum);
  250. break;
  251. }
  252. case JackRequest::kDisconnectPorts: {
  253. jack_log("JackRequest::DisconnectPorts");
  254. JackPortDisconnectRequest req;
  255. JackResult res;
  256. if (req.Read(socket) == 0)
  257. res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
  258. if (res.Write(socket) < 0)
  259. jack_error("JackRequest::DisconnectPorts write error ref = %d", req.fRefNum);
  260. break;
  261. }
  262. case JackRequest::kPortRename: {
  263. jack_log("JackRequest::PortRename");
  264. JackPortRenameRequest req;
  265. JackResult res;
  266. if (req.Read(socket) == 0)
  267. res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName);
  268. if (res.Write(socket) < 0)
  269. jack_error("JackRequest::PortRename write error ref = %d", req.fRefNum);
  270. break;
  271. }
  272. case JackRequest::kSetBufferSize: {
  273. jack_log("JackRequest::SetBufferSize");
  274. JackSetBufferSizeRequest req;
  275. JackResult res;
  276. if (req.Read(socket) == 0)
  277. res.fResult = fServer->SetBufferSize(req.fBufferSize);
  278. if (res.Write(socket) < 0)
  279. jack_error("JackRequest::SetBufferSize write error");
  280. break;
  281. }
  282. case JackRequest::kSetFreeWheel: {
  283. jack_log("JackRequest::SetFreeWheel");
  284. JackSetFreeWheelRequest req;
  285. JackResult res;
  286. if (req.Read(socket) == 0)
  287. res.fResult = fServer->SetFreewheel(req.fOnOff);
  288. if (res.Write(socket) < 0)
  289. jack_error("JackRequest::SetFreeWheel write error");
  290. break;
  291. }
  292. case JackRequest::kComputeTotalLatencies: {
  293. jack_log("JackRequest::ComputeTotalLatencies");
  294. JackComputeTotalLatenciesRequest req;
  295. JackResult res;
  296. if (req.Read(socket) == 0)
  297. res.fResult = fServer->GetEngine()->ComputeTotalLatencies();
  298. if (res.Write(socket) < 0)
  299. jack_error("JackRequest::ComputeTotalLatencies write error");
  300. break;
  301. }
  302. case JackRequest::kReleaseTimebase: {
  303. jack_log("JackRequest::ReleaseTimebase");
  304. JackReleaseTimebaseRequest req;
  305. JackResult res;
  306. if (req.Read(socket) == 0)
  307. res.fResult = fServer->ReleaseTimebase(req.fRefNum);
  308. if (res.Write(socket) < 0)
  309. jack_error("JackRequest::ReleaseTimebase write error ref = %d", req.fRefNum);
  310. break;
  311. }
  312. case JackRequest::kSetTimebaseCallback: {
  313. jack_log("JackRequest::SetTimebaseCallback");
  314. JackSetTimebaseCallbackRequest req;
  315. JackResult res;
  316. if (req.Read(socket) == 0)
  317. res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal);
  318. if (res.Write(socket) < 0)
  319. jack_error("JackRequest::SetTimebaseCallback write error ref = %d", req.fRefNum);
  320. break;
  321. }
  322. case JackRequest::kGetInternalClientName: {
  323. jack_log("JackRequest::GetInternalClientName");
  324. JackGetInternalClientNameRequest req;
  325. JackGetInternalClientNameResult res;
  326. if (req.Read(socket) == 0)
  327. res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName);
  328. if (res.Write(socket) < 0)
  329. jack_error("JackRequest::GetInternalClientName write error ref = %d", req.fRefNum);
  330. break;
  331. }
  332. case JackRequest::kInternalClientHandle: {
  333. jack_log("JackRequest::InternalClientHandle");
  334. JackInternalClientHandleRequest req;
  335. JackInternalClientHandleResult res;
  336. if (req.Read(socket) == 0)
  337. res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum);
  338. if (res.Write(socket) < 0)
  339. jack_error("JackRequest::InternalClientHandle write error ref = %d", req.fRefNum);
  340. break;
  341. }
  342. case JackRequest::kInternalClientLoad: {
  343. jack_log("JackRequest::InternalClientLoad");
  344. JackInternalClientLoadRequest req;
  345. JackInternalClientLoadResult res;
  346. if (req.Read(socket) == 0)
  347. res.fResult = fServer->InternalClientLoad(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus);
  348. if (res.Write(socket) < 0)
  349. jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName);
  350. break;
  351. }
  352. case JackRequest::kInternalClientUnload: {
  353. jack_log("JackRequest::InternalClientUnload");
  354. JackInternalClientUnloadRequest req;
  355. JackInternalClientUnloadResult res;
  356. if (req.Read(socket) == 0)
  357. res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus);
  358. if (res.Write(socket) < 0)
  359. jack_error("JackRequest::InternalClientUnload write error ref = %d", req.fRefNum);
  360. break;
  361. }
  362. case JackRequest::kNotification: {
  363. jack_log("JackRequest::Notification");
  364. JackClientNotificationRequest req;
  365. if (req.Read(socket) == 0) {
  366. if (req.fNotify == kQUIT) {
  367. jack_log("JackRequest::Notification kQUIT");
  368. throw JackQuitException();
  369. } else {
  370. fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
  371. }
  372. }
  373. break;
  374. }
  375. case JackRequest::kSessionNotify: {
  376. jack_log("JackRequest::SessionNotify");
  377. JackSessionNotifyRequest req;
  378. JackSessionNotifyResult res;
  379. if (req.Read(socket) == 0) {
  380. fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket);
  381. }
  382. break;
  383. }
  384. case JackRequest::kSessionReply: {
  385. jack_log("JackRequest::SessionReply");
  386. JackSessionReplyRequest req;
  387. JackResult res;
  388. if (req.Read(socket) == 0) {
  389. fServer->GetEngine()->SessionReply(req.fRefNum);
  390. res.fResult = 0;
  391. }
  392. if (res.Write(socket) < 0)
  393. jack_error("JackRequest::SessionReply write error");
  394. break;
  395. }
  396. case JackRequest::kGetClientByUUID: {
  397. jack_log("JackRequest::GetClientNameForUUID");
  398. JackGetClientNameRequest req;
  399. JackClientNameResult res;
  400. if (req.Read(socket) == 0) {
  401. fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName, &res.fResult);
  402. }
  403. if (res.Write(socket) < 0)
  404. jack_error("JackRequest::GetClientNameForUUID write error");
  405. break;
  406. }
  407. case JackRequest::kGetUUIDByClient: {
  408. jack_log("JackRequest::GetUUIDForClientName");
  409. JackGetUUIDRequest req;
  410. JackUUIDResult res;
  411. if (req.Read(socket) == 0) {
  412. fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult);
  413. res.fResult = 0;
  414. }
  415. if (res.Write(socket) < 0)
  416. jack_error("JackRequest::GetUUIDForClientName write error");
  417. break;
  418. }
  419. case JackRequest::kReserveClientName: {
  420. jack_log("JackRequest::ReserveClientName");
  421. JackReserveNameRequest req;
  422. JackResult res;
  423. if (req.Read(socket) == 0) {
  424. fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID, &res.fResult);
  425. }
  426. if (res.Write(socket) < 0)
  427. jack_error("JackRequest::ReserveClientName write error");
  428. break;
  429. }
  430. default:
  431. jack_error("Unknown request %ld", header.fType);
  432. break;
  433. }
  434. return true;
  435. }
  436. void JackSocketServerChannel::BuildPoolTable()
  437. {
  438. if (fRebuild) {
  439. fRebuild = false;
  440. delete[] fPollTable;
  441. fPollTable = new pollfd[fSocketTable.size() + 1];
  442. jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable.size() + 1);
  443. // First fd is the server request socket
  444. fPollTable[0].fd = fRequestListenSocket.GetFd();
  445. fPollTable[0].events = POLLIN | POLLERR;
  446. // Next fd for clients
  447. map<int, pair<int, JackClientSocket*> >::iterator it;
  448. int i;
  449. for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) {
  450. jack_log("fSocketTable i = %ld fd = %ld", i, it->first);
  451. fPollTable[i].fd = it->first;
  452. fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
  453. }
  454. }
  455. }
  456. bool JackSocketServerChannel::Init()
  457. {
  458. sigset_t set;
  459. sigemptyset(&set);
  460. sigaddset(&set, SIGPIPE);
  461. pthread_sigmask(SIG_BLOCK, &set, 0);
  462. return true;
  463. }
  464. bool JackSocketServerChannel::Execute()
  465. {
  466. try {
  467. // Global poll
  468. if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) {
  469. jack_error("Engine poll failed err = %s request thread quits...", strerror(errno));
  470. return false;
  471. } else {
  472. // Poll all clients
  473. for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) {
  474. int fd = fPollTable[i].fd;
  475. jack_log("fPollTable i = %ld fd = %ld", i, fd);
  476. if (fPollTable[i].revents & ~POLLIN) {
  477. jack_log("Poll client error err = %s", strerror(errno));
  478. ClientKill(fd);
  479. } else if (fPollTable[i].revents & POLLIN) {
  480. if (!HandleRequest(fd))
  481. jack_log("Could not handle external client request");
  482. }
  483. }
  484. // Check the server request socket */
  485. if (fPollTable[0].revents & POLLERR)
  486. jack_error("Error on server request socket err = %s", strerror(errno));
  487. if (fPollTable[0].revents & POLLIN)
  488. ClientCreate();
  489. }
  490. BuildPoolTable();
  491. return true;
  492. } catch (JackQuitException& e) {
  493. jack_log("JackMachServerChannel::Execute JackQuitException");
  494. return false;
  495. }
  496. }
  497. } // end of namespace