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.

280 lines
9.4KB

  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 "JackMachPort.h"
  16. #include "JackError.h"
  17. namespace Jack
  18. {
  19. // Server side : port is published to be accessible from other processes (clients)
  20. bool JackMachPort::AllocatePort(const char* name, int queue)
  21. {
  22. mach_port_t task = mach_task_self();
  23. kern_return_t res;
  24. if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) {
  25. jack_error("AllocatePort: Can't find bootstrap mach port err = %s", mach_error_string(res));
  26. return false;
  27. }
  28. if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &fServerPort)) != KERN_SUCCESS) {
  29. jack_error("AllocatePort: can't allocate mach port err = %s", mach_error_string(res));
  30. return false;
  31. }
  32. if ((res = mach_port_insert_right(task, fServerPort, fServerPort, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) {
  33. jack_error("AllocatePort: error inserting mach rights err = %s", mach_error_string(res));
  34. return false;
  35. }
  36. if ((res = bootstrap_register(fBootPort, (char*)name, fServerPort)) != KERN_SUCCESS) {
  37. jack_error("Allocate: can't check in mach port name = %s err = %s", name, mach_error_string(res));
  38. return false;
  39. }
  40. mach_port_limits_t qlimits;
  41. mach_msg_type_number_t info_cnt = MACH_PORT_LIMITS_INFO_COUNT;
  42. if ((res = mach_port_get_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, &info_cnt)) != KERN_SUCCESS) {
  43. jack_error("Allocate: mach_port_get_attributes error err = %s", name, mach_error_string(res));
  44. }
  45. jack_log("AllocatePort: queue limit %ld", qlimits.mpl_qlimit);
  46. if (queue > 0 ) {
  47. qlimits.mpl_qlimit = queue;
  48. if ((res = mach_port_set_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, MACH_PORT_LIMITS_INFO_COUNT)) != KERN_SUCCESS) {
  49. jack_error("Allocate: mach_port_set_attributes error name = %s err = %s", name, mach_error_string(res));
  50. }
  51. }
  52. return true;
  53. }
  54. // Server side : port is published to be accessible from other processes (clients)
  55. bool JackMachPort::AllocatePort(const char* name)
  56. {
  57. return AllocatePort(name, -1);
  58. }
  59. // Client side : get the published port from server
  60. bool JackMachPort::ConnectPort(const char* name)
  61. {
  62. kern_return_t res;
  63. jack_log("JackMachPort::ConnectPort %s", name);
  64. if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) {
  65. jack_error("ConnectPort: can't find bootstrap port err = %s", mach_error_string(res));
  66. return false;
  67. }
  68. if ((res = bootstrap_look_up(fBootPort, (char*)name, &fServerPort)) != KERN_SUCCESS) {
  69. jack_error("ConnectPort: can't find mach server port name = %s err = %s", name, mach_error_string(res));
  70. return false;
  71. }
  72. return true;
  73. }
  74. bool JackMachPort::DisconnectPort()
  75. {
  76. jack_log("JackMacRPC::DisconnectPort");
  77. kern_return_t res;
  78. mach_port_t task = mach_task_self();
  79. if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
  80. jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
  81. }
  82. if ((res = mach_port_deallocate(task, fServerPort)) != KERN_SUCCESS) {
  83. jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fServerPort err = %s", mach_error_string(res));
  84. }
  85. return true;
  86. }
  87. bool JackMachPort::DestroyPort()
  88. {
  89. jack_log("JackMacRPC::DisconnectPort");
  90. kern_return_t res;
  91. mach_port_t task = mach_task_self();
  92. if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
  93. jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
  94. }
  95. if ((res = mach_port_destroy(task, fServerPort)) != KERN_SUCCESS) {
  96. jack_error("JackMacRPC::DisconnectPort mach_port_destroy fServerPort err = %s", mach_error_string(res));
  97. }
  98. return true;
  99. }
  100. mach_port_t JackMachPort::GetPort()
  101. {
  102. return fServerPort;
  103. }
  104. bool JackMachPortSet::AllocatePort(const char* name, int queue)
  105. {
  106. kern_return_t res;
  107. mach_port_t task = mach_task_self();
  108. jack_log("JackMachPortSet::AllocatePort");
  109. if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) {
  110. jack_error("AllocatePort: Can't find bootstrap mach port err = %s", mach_error_string(res));
  111. return false;
  112. }
  113. if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &fServerPort)) != KERN_SUCCESS) {
  114. jack_error("AllocatePort: can't allocate mach port err = %s", mach_error_string(res));
  115. return false;
  116. }
  117. if ((res = mach_port_insert_right(task, fServerPort, fServerPort, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) {
  118. jack_error("AllocatePort: error inserting mach rights err = %s", mach_error_string(res));
  119. return false;
  120. }
  121. if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_PORT_SET, &fPortSet)) != KERN_SUCCESS) {
  122. jack_error("AllocatePort: can't allocate mach port err = %s", mach_error_string(res));
  123. return false;
  124. }
  125. if ((res = mach_port_move_member(task, fServerPort, fPortSet)) != KERN_SUCCESS) {
  126. jack_error("AllocatePort: error in mach_port_move_member err = %s", mach_error_string(res));
  127. return false;
  128. }
  129. if ((res = bootstrap_register(fBootPort, (char*)name, fServerPort)) != KERN_SUCCESS) {
  130. jack_error("Allocate: can't check in mach port name = %s err = %s", name, mach_error_string(res));
  131. return false;
  132. }
  133. mach_port_limits_t qlimits;
  134. mach_msg_type_number_t info_cnt = MACH_PORT_LIMITS_INFO_COUNT;
  135. if ((res = mach_port_get_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, &info_cnt)) != KERN_SUCCESS) {
  136. jack_error("Allocate: mach_port_get_attributes error name = %s err = %s", name, mach_error_string(res));
  137. }
  138. jack_log("AllocatePort: queue limit = %ld", qlimits.mpl_qlimit);
  139. if (queue > 0 ) {
  140. qlimits.mpl_qlimit = queue;
  141. if ((res = mach_port_set_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, MACH_PORT_LIMITS_INFO_COUNT)) != KERN_SUCCESS) {
  142. jack_error("Allocate: mach_port_set_attributes error name = %s err = %s", name, mach_error_string(res));
  143. }
  144. }
  145. return true;
  146. }
  147. // Server side : port is published to be accessible from other processes (clients)
  148. bool JackMachPortSet::AllocatePort(const char* name)
  149. {
  150. return AllocatePort(name, -1);
  151. }
  152. bool JackMachPortSet::DisconnectPort()
  153. {
  154. kern_return_t res;
  155. mach_port_t task = mach_task_self();
  156. jack_log("JackMachPortSet::DisconnectPort");
  157. if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
  158. jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
  159. }
  160. if ((res = mach_port_deallocate(task, fServerPort)) != KERN_SUCCESS) {
  161. jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate fServerPort err = %s", mach_error_string(res));
  162. }
  163. return true;
  164. }
  165. bool JackMachPortSet::DestroyPort()
  166. {
  167. kern_return_t res;
  168. mach_port_t task = mach_task_self();
  169. jack_log("JackMachPortSet::DisconnectPort");
  170. if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
  171. jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate err = %s", mach_error_string(res));
  172. }
  173. if ((res = mach_port_destroy(task, fServerPort)) != KERN_SUCCESS) {
  174. jack_error("JackMachPortSet::DisconnectPort mach_port_destroy fServerPort err = %s", mach_error_string(res));
  175. }
  176. return true;
  177. }
  178. mach_port_t JackMachPortSet::GetPortSet()
  179. {
  180. return fPortSet;
  181. }
  182. mach_port_t JackMachPortSet::AddPort()
  183. {
  184. kern_return_t res;
  185. mach_port_t task = mach_task_self();
  186. mach_port_t old_port, result = 0;
  187. jack_log("JackMachPortSet::AddPort");
  188. if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &result)) != KERN_SUCCESS) {
  189. jack_error("AddPort: can't allocate mach port err = %s", mach_error_string(res));
  190. goto error;
  191. }
  192. if ((res = mach_port_request_notification(task, result, MACH_NOTIFY_NO_SENDERS,
  193. 1, result, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_port)) != KERN_SUCCESS) {
  194. jack_error("AddPort: error in mach_port_request_notification err = %s", mach_error_string(res));
  195. goto error;
  196. }
  197. if ((res = mach_port_move_member(task, result, fPortSet)) != KERN_SUCCESS) {
  198. jack_error("AddPort: error in mach_port_move_member err = %s", mach_error_string(res));
  199. goto error;
  200. }
  201. return result;
  202. error:
  203. if (result) {
  204. if ((res = mach_port_destroy(task, result)) != KERN_SUCCESS) {
  205. jack_error("JackMacRPC::DisconnectPort mach_port_destroy err = %s", mach_error_string(res));
  206. }
  207. }
  208. return 0;
  209. }
  210. } // end of namespace