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.

300 lines
9.8KB

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