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
00028 using namespace std;
00029
00030 namespace Jack
00031 {
00032
00033 map<mach_port_t, JackMachServerChannel*> JackMachServerChannel::fPortTable;
00034
00035 JackMachServerChannel::JackMachServerChannel():fThread(this)
00036 {}
00037
00038 JackMachServerChannel::~JackMachServerChannel()
00039 {}
00040
00041 int JackMachServerChannel::Open(const char* server_name, JackServer* server)
00042 {
00043 jack_log("JackMachServerChannel::Open");
00044 char jack_server_entry_name[512];
00045 snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
00046
00047 if (!fServerPort.AllocatePort(jack_server_entry_name, 16)) {
00048 jack_error("Cannot check in Jack server");
00049 return -1;
00050 }
00051
00052 if (fThread.Start() != 0) {
00053 jack_error("Cannot start Jack server listener");
00054 return -1;
00055 }
00056
00057 fServer = server;
00058 fPortTable[fServerPort.GetPort()] = this;
00059 return 0;
00060 }
00061
00062 void JackMachServerChannel::Close()
00063 {
00064 jack_log("JackMachServerChannel::Close");
00065 fThread.Kill();
00066 fServerPort.DestroyPort();
00067 }
00068
00069 JackLockedEngine* JackMachServerChannel::GetEngine()
00070 {
00071 return fServer->GetEngine();
00072 }
00073
00074 JackServer* JackMachServerChannel::GetServer()
00075 {
00076 return fServer;
00077 }
00078
00079 void JackMachServerChannel::ClientCheck(char* name, char* name_res, int protocol, int options, int* status, int* result)
00080 {
00081 *result = GetEngine()->ClientCheck(name, name_res, protocol, options, status);
00082 }
00083
00084 void JackMachServerChannel::ClientOpen(char* name, int pid, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result)
00085 {
00086 int refnum = -1;
00087 *result = GetEngine()->ClientExternalOpen(name, pid, &refnum, shared_engine, shared_client, shared_graph);
00088
00089 if (*result == 0) {
00090 mach_port_t port = fServerPort.AddPort();
00091 if (port != 0) {
00092 fClientTable[port] = refnum;
00093 fPortTable[port] = this;
00094 *private_port = port;
00095 } else {
00096 jack_error("Cannot create private client mach port");
00097 *result = -1;
00098 }
00099 } else {
00100 jack_error("Cannot create new client");
00101 }
00102 }
00103
00104 void JackMachServerChannel::ClientClose(mach_port_t private_port, int refnum)
00105 {
00106 GetEngine()->ClientExternalClose(refnum);
00107 fClientTable.erase(private_port);
00108
00109
00110 kern_return_t res;
00111 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
00112 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
00113 }
00114 }
00115
00116 void JackMachServerChannel::ClientKill(mach_port_t private_port)
00117 {
00118 jack_log("JackMachServerChannel::ClientKill");
00119 int refnum = fClientTable[private_port];
00120 assert(refnum > 0);
00121 fServer->ClientKill(refnum);
00122 fClientTable.erase(private_port);
00123
00124
00125 kern_return_t res;
00126 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
00127 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
00128 }
00129 }
00130
00131 boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply)
00132 {
00133 if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
00134 jack_log("MACH_NOTIFY_NO_SENDERS %ld", Request->msgh_local_port);
00135 JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port];
00136 assert(channel);
00137 channel->ClientKill(Request->msgh_local_port);
00138 } else {
00139 JackRPCEngine_server(Request, Reply);
00140 }
00141 return true;
00142 }
00143
00144 bool JackMachServerChannel::Execute()
00145 {
00146 kern_return_t res;
00147 if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
00148 jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res));
00149 }
00150
00151 return true;
00152 }
00153
00154 }
00155
00156