00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "JackTools.h"
00021 #include "JackMachServerChannel.h"
00022 #include "JackRPCEngineServer.c"
00023 #include "JackError.h"
00024 #include "JackServer.h"
00025 #include "JackLockedEngine.h"
00026 #include "JackNotification.h"
00027 #include "JackServerGlobals.h"
00028
00029 using namespace std;
00030
00031 namespace Jack
00032 {
00033
00034 map<mach_port_t, JackMachServerChannel*> JackMachServerChannel::fPortTable;
00035
00036 JackMachServerChannel::JackMachServerChannel():fThread(this)
00037 {}
00038
00039 JackMachServerChannel::~JackMachServerChannel()
00040 {}
00041
00042 int JackMachServerChannel::Open(const char* server_name, JackServer* server)
00043 {
00044 jack_log("JackMachServerChannel::Open");
00045 char jack_server_entry_name[512];
00046 snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
00047
00048 if (!fServerPort.AllocatePort(jack_server_entry_name, 16)) {
00049 jack_error("Cannot check in Jack server");
00050 return -1;
00051 }
00052
00053 fServer = server;
00054 fPortTable[fServerPort.GetPort()] = this;
00055 return 0;
00056 }
00057
00058 void JackMachServerChannel::Close()
00059 {
00060 jack_log("JackMachServerChannel::Close");
00061 #ifdef MAC_OS_X_VERSION_10_5
00062
00063 fThread.Kill();
00064 #else
00065 fThread.Stop();
00066 #endif
00067 fServerPort.DestroyPort();
00068 }
00069
00070 int JackMachServerChannel::Start()
00071 {
00072 if (fThread.Start() != 0) {
00073 jack_error("Cannot start Jack server listener");
00074 return -1;
00075 }
00076
00077 return 0;
00078 }
00079
00080 JackLockedEngine* JackMachServerChannel::GetEngine()
00081 {
00082 return fServer->GetEngine();
00083 }
00084
00085 JackServer* JackMachServerChannel::GetServer()
00086 {
00087 return fServer;
00088 }
00089
00090 void JackMachServerChannel::ClientCheck(char* name, char* name_res, int protocol, int options, int* status, int* result)
00091 {
00092 *result = GetEngine()->ClientCheck(name, name_res, protocol, options, status);
00093 }
00094
00095 void JackMachServerChannel::ClientOpen(char* name, int pid, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result)
00096 {
00097 int refnum = -1;
00098 *result = GetEngine()->ClientExternalOpen(name, pid, &refnum, shared_engine, shared_client, shared_graph);
00099
00100 if (*result == 0) {
00101 mach_port_t port = fServerPort.AddPort();
00102 if (port != 0) {
00103 fClientTable[port] = refnum;
00104 fPortTable[port] = this;
00105 *private_port = port;
00106 } else {
00107 jack_error("Cannot create private client mach port");
00108 *result = -1;
00109 }
00110 } else {
00111 jack_error("Cannot create new client");
00112 }
00113 }
00114
00115 void JackMachServerChannel::ClientClose(mach_port_t private_port, int refnum)
00116 {
00117 GetEngine()->ClientExternalClose(refnum);
00118 fClientTable.erase(private_port);
00119
00120
00121 kern_return_t res;
00122 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
00123 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
00124 }
00125 }
00126
00127 void JackMachServerChannel::ClientKill(mach_port_t private_port)
00128 {
00129 jack_log("JackMachServerChannel::ClientKill");
00130 int refnum = fClientTable[private_port];
00131 assert(refnum > 0);
00132 fServer->ClientKill(refnum);
00133 fClientTable.erase(private_port);
00134
00135
00136 kern_return_t res;
00137 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
00138 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
00139 }
00140 }
00141
00142 boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply)
00143 {
00144 if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
00145 jack_log("MACH_NOTIFY_NO_SENDERS %ld", Request->msgh_local_port);
00146 JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port];
00147 assert(channel);
00148 channel->ClientKill(Request->msgh_local_port);
00149 } else {
00150 JackRPCEngine_server(Request, Reply);
00151 }
00152 return true;
00153 }
00154
00155 bool JackMachServerChannel::Execute()
00156 {
00157 try {
00158
00159 kern_return_t res;
00160 if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
00161 jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res));
00162
00163 }
00164 return true;
00165
00166 } catch (JackQuitException& e) {
00167 jack_log("JackMachServerChannel::Execute JackQuitException");
00168 return false;
00169 }
00170 }
00171
00172 }
00173
00174