Jack2 1.9.6

JackMachPort.cpp

00001 /*
00002 Copyright (C) 2004-2008 Grame
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as published by
00006 the Free Software Foundation; either version 2.1 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public License
00015 along with this program; if not, write to the Free Software 
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 
00018 */
00019 
00020 #include "JackMachPort.h"
00021 #include "JackError.h"
00022 
00023 namespace Jack
00024 {
00025 
00026 // Server side : port is published to be accessible from other processes (clients)
00027 
00028 bool JackMachPort::AllocatePort(const char* name, int queue)
00029 {
00030     mach_port_t task = mach_task_self();
00031     kern_return_t res;
00032 
00033     if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) {
00034         jack_error("AllocatePort: Can't find bootstrap mach port err = %s", mach_error_string(res));
00035         return false;
00036     }
00037 
00038     if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &fServerPort)) != KERN_SUCCESS) {
00039         jack_error("AllocatePort: can't allocate mach port err = %s", mach_error_string(res));
00040         return false;
00041     }
00042 
00043     if ((res = mach_port_insert_right(task, fServerPort, fServerPort, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) {
00044         jack_error("AllocatePort: error inserting mach rights err = %s", mach_error_string(res));
00045         return false;
00046     }
00047 
00048     if ((res = bootstrap_register(fBootPort, (char*)name, fServerPort)) != KERN_SUCCESS) {
00049         jack_error("Allocate: can't check in mach port name = %s err = %s", name, mach_error_string(res));
00050         return false;
00051     }
00052 
00053     mach_port_limits_t qlimits;
00054     mach_msg_type_number_t info_cnt = MACH_PORT_LIMITS_INFO_COUNT;
00055     if ((res = mach_port_get_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, &info_cnt)) != KERN_SUCCESS) {
00056         jack_error("Allocate: mach_port_get_attributes error err = %s", name, mach_error_string(res));
00057     }
00058 
00059     jack_log("AllocatePort: queue limit %ld", qlimits.mpl_qlimit);
00060 
00061     if (queue > 0) {
00062         qlimits.mpl_qlimit = queue;
00063         if ((res = mach_port_set_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, MACH_PORT_LIMITS_INFO_COUNT)) != KERN_SUCCESS) {
00064             jack_error("Allocate: mach_port_set_attributes error name = %s err = %s", name, mach_error_string(res));
00065         }
00066     }
00067 
00068     return true;
00069 }
00070 
00071 // Server side : port is published to be accessible from other processes (clients)
00072 
00073 bool JackMachPort::AllocatePort(const char* name)
00074 {
00075     return AllocatePort(name, -1);
00076 }
00077 
00078 // Client side : get the published port from server
00079 
00080 bool JackMachPort::ConnectPort(const char* name)
00081 {
00082     kern_return_t res;
00083 
00084     jack_log("JackMachPort::ConnectPort %s", name);
00085 
00086     if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) {
00087         jack_error("ConnectPort: can't find bootstrap port err = %s", mach_error_string(res));
00088         return false;
00089     }
00090 
00091     if ((res = bootstrap_look_up(fBootPort, (char*)name, &fServerPort)) != KERN_SUCCESS) {
00092         jack_error("ConnectPort: can't find mach server port name = %s err = %s", name, mach_error_string(res));
00093         return false;
00094     }
00095 
00096     return true;
00097 }
00098 
00099 bool JackMachPort::DisconnectPort()
00100 {
00101     jack_log("JackMacRPC::DisconnectPort");
00102     kern_return_t res;
00103     mach_port_t task = mach_task_self();
00104 
00105     if (fBootPort != 0) {
00106         if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
00107             jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
00108         }
00109     }
00110 
00111     if (fServerPort != 0) {
00112         if ((res = mach_port_deallocate(task, fServerPort)) != KERN_SUCCESS) {
00113             jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fServerPort err = %s", mach_error_string(res));
00114         }
00115     }
00116     
00117     return true;
00118 }
00119 
00120 bool JackMachPort::DestroyPort()
00121 {
00122     jack_log("JackMacRPC::DisconnectPort");
00123     kern_return_t res;
00124     mach_port_t task = mach_task_self();
00125 
00126     if (fBootPort != 0) {
00127         if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
00128             jack_error("JackMacRPC::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
00129         }
00130     }
00131 
00132     if (fServerPort != 0) {
00133         if ((res = mach_port_destroy(task, fServerPort)) != KERN_SUCCESS) {
00134             jack_error("JackMacRPC::DisconnectPort mach_port_destroy fServerPort err = %s", mach_error_string(res));
00135         }
00136     }
00137 
00138     return true;
00139 }
00140 
00141 mach_port_t JackMachPort::GetPort()
00142 {
00143     return fServerPort;
00144 }
00145 
00146 bool JackMachPortSet::AllocatePort(const char* name, int queue)
00147 {
00148     kern_return_t res;
00149     mach_port_t task = mach_task_self();
00150 
00151     jack_log("JackMachPortSet::AllocatePort");
00152 
00153     if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) {
00154         jack_error("AllocatePort: Can't find bootstrap mach port err = %s", mach_error_string(res));
00155         return false;
00156     }
00157 
00158     if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &fServerPort)) != KERN_SUCCESS) {
00159         jack_error("AllocatePort: can't allocate mach port err = %s", mach_error_string(res));
00160         return false;
00161     }
00162 
00163     if ((res = mach_port_insert_right(task, fServerPort, fServerPort, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) {
00164         jack_error("AllocatePort: error inserting mach rights err = %s", mach_error_string(res));
00165         return false;
00166     }
00167 
00168     if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_PORT_SET, &fPortSet)) != KERN_SUCCESS) {
00169         jack_error("AllocatePort: can't allocate mach port err = %s", mach_error_string(res));
00170         return false;
00171     }
00172 
00173     if ((res = mach_port_move_member(task, fServerPort, fPortSet)) != KERN_SUCCESS) {
00174         jack_error("AllocatePort: error in mach_port_move_member err = %s", mach_error_string(res));
00175         return false;
00176     }
00177 
00178     if ((res = bootstrap_register(fBootPort, (char*)name, fServerPort)) != KERN_SUCCESS) {
00179         jack_error("Allocate: can't check in mach port name = %s err = %s", name, mach_error_string(res));
00180         return false;
00181     }
00182 
00183     mach_port_limits_t qlimits;
00184     mach_msg_type_number_t info_cnt = MACH_PORT_LIMITS_INFO_COUNT;
00185     if ((res = mach_port_get_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, &info_cnt)) != KERN_SUCCESS) {
00186         jack_error("Allocate: mach_port_get_attributes error name = %s err = %s", name, mach_error_string(res));
00187     }
00188 
00189     jack_log("AllocatePort: queue limit = %ld", qlimits.mpl_qlimit);
00190 
00191     if (queue > 0) {
00192         qlimits.mpl_qlimit = queue;
00193 
00194         if ((res = mach_port_set_attributes(task, fServerPort, MACH_PORT_LIMITS_INFO, (mach_port_info_t) & qlimits, MACH_PORT_LIMITS_INFO_COUNT)) != KERN_SUCCESS) {
00195             jack_error("Allocate: mach_port_set_attributes error name = %s err = %s", name, mach_error_string(res));
00196         }
00197     }
00198 
00199     return true;
00200 }
00201 
00202 // Server side : port is published to be accessible from other processes (clients)
00203 
00204 bool JackMachPortSet::AllocatePort(const char* name)
00205 {
00206     return AllocatePort(name, -1);
00207 }
00208 
00209 bool JackMachPortSet::DisconnectPort()
00210 {
00211     kern_return_t res;
00212     mach_port_t task = mach_task_self();
00213 
00214     jack_log("JackMachPortSet::DisconnectPort");
00215 
00216     if (fBootPort != 0) {
00217         if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
00218             jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate fBootPort err = %s", mach_error_string(res));
00219         }
00220     }
00221 
00222     if (fServerPort != 0) {
00223         if ((res = mach_port_deallocate(task, fServerPort)) != KERN_SUCCESS) {
00224             jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate fServerPort err = %s", mach_error_string(res));
00225         }
00226     }
00227 
00228     return true;
00229 }
00230 
00231 bool JackMachPortSet::DestroyPort()
00232 {
00233     kern_return_t res;
00234     mach_port_t task = mach_task_self();
00235 
00236     jack_log("JackMachPortSet::DisconnectPort");
00237 
00238     if (fBootPort != 0) {
00239         if ((res = mach_port_deallocate(task, fBootPort)) != KERN_SUCCESS) {
00240             jack_error("JackMachPortSet::DisconnectPort mach_port_deallocate err = %s", mach_error_string(res));
00241         }
00242     }
00243 
00244     if (fServerPort != 0) {
00245         if ((res = mach_port_destroy(task, fServerPort)) != KERN_SUCCESS) {
00246             jack_error("JackMachPortSet::DisconnectPort mach_port_destroy fServerPort err = %s", mach_error_string(res));
00247         }
00248     }
00249 
00250     return true;
00251 }
00252 
00253 mach_port_t JackMachPortSet::GetPortSet()
00254 {
00255     return fPortSet;
00256 }
00257 
00258 mach_port_t JackMachPortSet::AddPort()
00259 {
00260     kern_return_t res;
00261     mach_port_t task = mach_task_self();
00262     mach_port_t old_port, result = 0;
00263 
00264     jack_log("JackMachPortSet::AddPort");
00265 
00266     if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &result)) != KERN_SUCCESS) {
00267         jack_error("AddPort: can't allocate mach port err = %s", mach_error_string(res));
00268         goto error;
00269     }
00270 
00271     if ((res = mach_port_request_notification(task, result, MACH_NOTIFY_NO_SENDERS,
00272                1, result, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_port)) != KERN_SUCCESS) {
00273         jack_error("AddPort: error in mach_port_request_notification err = %s", mach_error_string(res));
00274         goto error;
00275     }
00276 
00277     if ((res = mach_port_move_member(task, result, fPortSet)) != KERN_SUCCESS) {
00278         jack_error("AddPort: error in mach_port_move_member err = %s", mach_error_string(res));
00279         goto error;
00280     }
00281 
00282     return result;
00283 
00284 error:
00285     if (result) {
00286         if ((res = mach_port_destroy(task, result)) != KERN_SUCCESS) {
00287             jack_error("JackMacRPC::DisconnectPort mach_port_destroy err = %s", mach_error_string(res));
00288         }
00289     }
00290     return 0;
00291 }
00292 
00293 
00294 } // end of namespace
00295