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 fThread.Kill();
00062 fServerPort.DestroyPort();
00063 }
00064
00065 int JackMachServerChannel::Start()
00066 {
00067 if (fThread.Start() != 0) {
00068 jack_error("Cannot start Jack server listener");
00069 return -1;
00070 }
00071
00072 return 0;
00073 }
00074
00075 JackLockedEngine* JackMachServerChannel::GetEngine()
00076 {
00077 return fServer->GetEngine();
00078 }
00079
00080 JackServer* JackMachServerChannel::GetServer()
00081 {
00082 return fServer;
00083 }
00084
00085 void JackMachServerChannel::ClientCheck(char* name, char* name_res, int protocol, int options, int* status, int* result)
00086 {
00087 *result = GetEngine()->ClientCheck(name, name_res, protocol, options, status);
00088 }
00089
00090 void JackMachServerChannel::ClientOpen(char* name, int pid, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result)
00091 {
00092 int refnum = -1;
00093 *result = GetEngine()->ClientExternalOpen(name, pid, &refnum, shared_engine, shared_client, shared_graph);
00094
00095 if (*result == 0) {
00096 mach_port_t port = fServerPort.AddPort();
00097 if (port != 0) {
00098 fClientTable[port] = refnum;
00099 fPortTable[port] = this;
00100 *private_port = port;
00101 } else {
00102 jack_error("Cannot create private client mach port");
00103 *result = -1;
00104 }
00105 } else {
00106 jack_error("Cannot create new client");
00107 }
00108 }
00109
00110 void JackMachServerChannel::ClientClose(mach_port_t private_port, int refnum)
00111 {
00112 GetEngine()->ClientExternalClose(refnum);
00113 fClientTable.erase(private_port);
00114
00115
00116 kern_return_t res;
00117 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
00118 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
00119 }
00120 }
00121
00122 void JackMachServerChannel::ClientKill(mach_port_t private_port)
00123 {
00124 jack_log("JackMachServerChannel::ClientKill");
00125 int refnum = fClientTable[private_port];
00126 assert(refnum > 0);
00127 fServer->ClientKill(refnum);
00128 fClientTable.erase(private_port);
00129
00130
00131 kern_return_t res;
00132 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
00133 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
00134 }
00135 }
00136
00137 boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply)
00138 {
00139 if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
00140 jack_log("MACH_NOTIFY_NO_SENDERS %ld", Request->msgh_local_port);
00141 JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port];
00142 assert(channel);
00143 channel->ClientKill(Request->msgh_local_port);
00144 } else {
00145 JackRPCEngine_server(Request, Reply);
00146 }
00147 return true;
00148 }
00149
00150 bool JackMachServerChannel::Execute()
00151 {
00152 kern_return_t res;
00153 if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
00154 jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res));
00155 }
00156
00157 return true;
00158 }
00159
00160 }
00161
00162