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.

296 lines
9.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 "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 (fBootPort != 0) {
  80. if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
  81. jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
  82. }
  83. }
  84. if (fServerPort != 0) {
  85. if ((res = mach_port_deallocate(task, fServerPort)) != KERN_SUCCESS) {
  86. jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fServerPort err = %s", mach_error_string(res));
  87. }
  88. }
  89. return true;
  90. }
  91. bool JackMachPort::DestroyPort()
  92. {
  93. jack_log("JackMacRPC::DisconnectPort");
  94. kern_return_t res;
  95. mach_port_t task = mach_task_self();
  96. if (fBootPort != 0) {
  97. if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
  98. jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
  99. }
  100. }
  101. if (fServerPort != 0) {
  102. if ((res = mach_port_destroy(task, fServerPort)) != KERN_SUCCESS) {
  103. jack_error("JackMacRPC::DisconnectPort mach_port_destroy fServerPort err = %s", mach_error_string(res));
  104. }
  105. }
  106. return true;
  107. }
  108. mach_port_t JackMachPort::GetPort()
  109. {
  110. return fServerPort;
  111. }
  112. bool JackMachPortSet::AllocatePort(const char* name, int queue)
  113. {
  114. kern_return_t res;
  115. mach_port_t task = mach_task_self();
  116. jack_log("JackMachPortSet::AllocatePort");
  117. if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) {
  118. jack_error("AllocatePort: Can't find bootstrap mach port err = %s", mach_error_string(res));
  119. return false;
  120. }
  121. if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &fServerPort)) != 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_insert_right(task, fServerPort, fServerPort, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) {
  126. jack_error("AllocatePort: error inserting mach rights err = %s", mach_error_string(res));
  127. return false;
  128. }
  129. if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_PORT_SET, &fPortSet)) != KERN_SUCCESS) {
  130. jack_error("AllocatePort: can't allocate mach port err = %s", mach_error_string(res));
  131. return false;
  132. }
  133. if ((res = mach_port_move_member(task, fServerPort, fPortSet)) != KERN_SUCCESS) {
  134. jack_error("AllocatePort: error in mach_port_move_member err = %s", mach_error_string(res));
  135. return false;
  136. }
  137. if ((res = bootstrap_register(fBootPort, (char*)name, fServerPort)) != KERN_SUCCESS) {
  138. jack_error("Allocate: can't check in mach port name = %s err = %s", name, mach_error_string(res));
  139. return false;
  140. }
  141. mach_port_limits_t qlimits;
  142. mach_msg_type_number_t info_cnt = MACH_PORT_LIMITS_INFO_COUNT;
  143. if ((res = mach_port_get_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, &info_cnt)) != KERN_SUCCESS) {
  144. jack_error("Allocate: mach_port_get_attributes error name = %s err = %s", name, mach_error_string(res));
  145. }
  146. jack_log("AllocatePort: queue limit = %ld", qlimits.mpl_qlimit);
  147. if (queue > 0) {
  148. qlimits.mpl_qlimit = queue;
  149. if ((res = mach_port_set_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, MACH_PORT_LIMITS_INFO_COUNT)) != KERN_SUCCESS) {
  150. jack_error("Allocate: mach_port_set_attributes error name = %s err = %s", name, mach_error_string(res));
  151. }
  152. }
  153. return true;
  154. }
  155. // Server side : port is published to be accessible from other processes (clients)
  156. bool JackMachPortSet::AllocatePort(const char* name)
  157. {
  158. return AllocatePort(name, -1);
  159. }
  160. bool JackMachPortSet::DisconnectPort()
  161. {
  162. kern_return_t res;
  163. mach_port_t task = mach_task_self();
  164. jack_log("JackMachPortSet::DisconnectPort");
  165. if (fBootPort != 0) {
  166. if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
  167. jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
  168. }
  169. }
  170. if (fServerPort != 0) {
  171. if ((res = mach_port_deallocate(task, fServerPort)) != KERN_SUCCESS) {
  172. jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate fServerPort err = %s", mach_error_string(res));
  173. }
  174. }
  175. return true;
  176. }
  177. bool JackMachPortSet::DestroyPort()
  178. {
  179. kern_return_t res;
  180. mach_port_t task = mach_task_self();
  181. jack_log("JackMachPortSet::DisconnectPort");
  182. if (fBootPort != 0) {
  183. if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
  184. jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate err = %s", mach_error_string(res));
  185. }
  186. }
  187. if (fServerPort != 0) {
  188. if ((res = mach_port_destroy(task, fServerPort)) != KERN_SUCCESS) {
  189. jack_error("JackMachPortSet::DisconnectPort mach_port_destroy fServerPort err = %s", mach_error_string(res));
  190. }
  191. }
  192. return true;
  193. }
  194. mach_port_t JackMachPortSet::GetPortSet()
  195. {
  196. return fPortSet;
  197. }
  198. mach_port_t JackMachPortSet::AddPort()
  199. {
  200. kern_return_t res;
  201. mach_port_t task = mach_task_self();
  202. mach_port_t old_port, result = 0;
  203. jack_log("JackMachPortSet::AddPort");
  204. if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &result)) != KERN_SUCCESS) {
  205. jack_error("AddPort: can't allocate mach port err = %s", mach_error_string(res));
  206. goto error;
  207. }
  208. if ((res = mach_port_request_notification(task, result, MACH_NOTIFY_NO_SENDERS,
  209. 1, result, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_port)) != KERN_SUCCESS) {
  210. jack_error("AddPort: error in mach_port_request_notification err = %s", mach_error_string(res));
  211. goto error;
  212. }
  213. if ((res = mach_port_move_member(task, result, fPortSet)) != KERN_SUCCESS) {
  214. jack_error("AddPort: error in mach_port_move_member err = %s", mach_error_string(res));
  215. goto error;
  216. }
  217. return result;
  218. error:
  219. if (result) {
  220. if ((res = mach_port_destroy(task, result)) != KERN_SUCCESS) {
  221. jack_error("JackMacRPC::DisconnectPort mach_port_destroy err = %s", mach_error_string(res));
  222. }
  223. }
  224. return 0;
  225. }
  226. } // end of namespace