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.

153 lines
4.4KB

  1. /*
  2. Copyright (C) 2004-2006 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. using namespace std;
  22. namespace Jack
  23. {
  24. map<mach_port_t, JackMachServerChannel*> JackMachServerChannel::fPortTable;
  25. JackMachServerChannel::JackMachServerChannel()
  26. {
  27. fThread = new JackMachThread(this);
  28. }
  29. JackMachServerChannel::~JackMachServerChannel()
  30. {
  31. delete fThread;
  32. }
  33. int JackMachServerChannel::Open(JackServer* server)
  34. {
  35. JackLog("JackMachServerChannel::Open\n");
  36. if (!fServerPort.AllocatePort(jack_server_entry, 16)) { // 16 is the max possible value
  37. jack_error("Cannot check in Jack server");
  38. return -1;
  39. }
  40. if (fThread->Start() != 0) {
  41. jack_error("Cannot start Jack server listener");
  42. return -1;
  43. }
  44. fServer = server;
  45. fPortTable[fServerPort.GetPort()] = this;
  46. return 0;
  47. }
  48. void JackMachServerChannel::Close()
  49. {
  50. JackLog("JackMachServerChannel::Close\n");
  51. fThread->Kill();
  52. fServerPort.DestroyPort();
  53. }
  54. JackEngine* JackMachServerChannel::GetEngine()
  55. {
  56. return fServer->GetEngine();
  57. }
  58. JackServer* JackMachServerChannel::GetServer()
  59. {
  60. return fServer;
  61. }
  62. void JackMachServerChannel::AddClient(char* name, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_ports, int* result)
  63. {
  64. int refnum = -1;
  65. *result = GetEngine()->ClientNew(name, &refnum, shared_engine, shared_client, shared_ports);
  66. if (*result == 0) {
  67. mach_port_t port = fServerPort.AddPort();
  68. if (port != 0) {
  69. fClientTable[port] = refnum;
  70. fPortTable[port] = this;
  71. *private_port = port;
  72. } else {
  73. jack_error("Cannot create private client mach port");
  74. *result = -1;
  75. }
  76. } else {
  77. jack_error("Cannot create new client");
  78. }
  79. }
  80. void JackMachServerChannel::RemoveClient(mach_port_t private_port, int refnum)
  81. {
  82. GetEngine()->ClientClose(refnum);
  83. fClientTable.erase(private_port);
  84. // Hum, hum....
  85. kern_return_t res;
  86. if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
  87. jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
  88. }
  89. }
  90. void JackMachServerChannel::KillClient(mach_port_t private_port)
  91. {
  92. JackLog("JackMachServerChannel::KillClient\n");
  93. int refnum = fClientTable[private_port];
  94. assert(refnum > 0);
  95. fServer->Notify(refnum, JackNotifyChannelInterface::kDeadClient, 0);
  96. fClientTable.erase(private_port);
  97. // Hum, hum....
  98. kern_return_t res;
  99. if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
  100. jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
  101. }
  102. }
  103. boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply)
  104. {
  105. if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
  106. JackLog("MACH_NOTIFY_NO_SENDERS %ld\n", Request->msgh_local_port);
  107. JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port];
  108. assert(channel);
  109. channel->KillClient(Request->msgh_local_port);
  110. } else {
  111. JackRPCEngine_server(Request, Reply);
  112. }
  113. return true;
  114. }
  115. bool JackMachServerChannel::Execute()
  116. {
  117. kern_return_t res;
  118. if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
  119. JackLog("JackMachServerChannel::Execute: err = %s\n", mach_error_string(res));
  120. }
  121. //return (res == KERN_SUCCESS); mach_msg_server can fail if the client reply port is not valid anymore (crashed client)
  122. return true;
  123. }
  124. } // end of namespace