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.

161 lines
4.7KB

  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 General Public License as published by
  5. the Free Software Foundation; either version 2 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 General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackMachServerChannel.h"
  16. #include "JackRPCEngineServer.c"
  17. #include "JackError.h"
  18. #include "JackServer.h"
  19. #include "JackMachThread.h"
  20. #include "JackEngine.h"
  21. #include "JackNotification.h"
  22. using namespace std;
  23. namespace Jack
  24. {
  25. map<mach_port_t, JackMachServerChannel*> JackMachServerChannel::fPortTable;
  26. JackMachServerChannel::JackMachServerChannel()
  27. {
  28. fThread = new JackMachThread(this);
  29. }
  30. JackMachServerChannel::~JackMachServerChannel()
  31. {
  32. delete fThread;
  33. }
  34. int JackMachServerChannel::Open(const char* server_name, JackServer* server)
  35. {
  36. jack_log("JackMachServerChannel::Open");
  37. char jack_server_entry_name[512];
  38. snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s_%s", jack_server_entry, server_name);
  39. if (!fServerPort.AllocatePort(jack_server_entry_name, 16)) { // 16 is the max possible value
  40. jack_error("Cannot check in Jack server");
  41. return -1;
  42. }
  43. if (fThread->Start() != 0) {
  44. jack_error("Cannot start Jack server listener");
  45. return -1;
  46. }
  47. fServer = server;
  48. fPortTable[fServerPort.GetPort()] = this;
  49. return 0;
  50. }
  51. void JackMachServerChannel::Close()
  52. {
  53. jack_log("JackMachServerChannel::Close");
  54. fThread->Kill();
  55. fServerPort.DestroyPort();
  56. }
  57. JackEngine* JackMachServerChannel::GetEngine()
  58. {
  59. return fServer->GetEngine();
  60. }
  61. JackServer* JackMachServerChannel::GetServer()
  62. {
  63. return fServer;
  64. }
  65. void JackMachServerChannel::ClientCheck(char* name, char* name_res, int protocol, int options, int* status, int* result)
  66. {
  67. *result = GetEngine()->ClientCheck(name, name_res, protocol, options, status);
  68. }
  69. void JackMachServerChannel::ClientOpen(char* name, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result)
  70. {
  71. int refnum = -1;
  72. *result = GetEngine()->ClientExternalOpen(name, &refnum, shared_engine, shared_client, shared_graph);
  73. if (*result == 0) {
  74. mach_port_t port = fServerPort.AddPort();
  75. if (port != 0) {
  76. fClientTable[port] = refnum;
  77. fPortTable[port] = this;
  78. *private_port = port;
  79. } else {
  80. jack_error("Cannot create private client mach port");
  81. *result = -1;
  82. }
  83. } else {
  84. jack_error("Cannot create new client");
  85. }
  86. }
  87. void JackMachServerChannel::ClientClose(mach_port_t private_port, int refnum)
  88. {
  89. GetEngine()->ClientExternalClose(refnum);
  90. fClientTable.erase(private_port);
  91. // Hum, hum....
  92. kern_return_t res;
  93. if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
  94. jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
  95. }
  96. }
  97. void JackMachServerChannel::ClientKill(mach_port_t private_port)
  98. {
  99. jack_log("JackMachServerChannel::ClientKill");
  100. int refnum = fClientTable[private_port];
  101. assert(refnum > 0);
  102. fServer->Notify(refnum, kDeadClient, 0);
  103. fClientTable.erase(private_port);
  104. // Hum, hum....
  105. kern_return_t res;
  106. if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
  107. jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
  108. }
  109. }
  110. boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply)
  111. {
  112. if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
  113. jack_log("MACH_NOTIFY_NO_SENDERS %ld", Request->msgh_local_port);
  114. JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port];
  115. assert(channel);
  116. channel->ClientKill(Request->msgh_local_port);
  117. } else {
  118. JackRPCEngine_server(Request, Reply);
  119. }
  120. return true;
  121. }
  122. bool JackMachServerChannel::Execute()
  123. {
  124. kern_return_t res;
  125. if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
  126. jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res));
  127. }
  128. //return (res == KERN_SUCCESS); mach_msg_server can fail if the client reply port is not valid anymore (crashed client)
  129. return true;
  130. }
  131. } // end of namespace