JackMachServerChannel.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 General Public License as published by
00006   the Free Software Foundation; either version 2 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 General Public License for more details.
00013 
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #include "JackMachServerChannel.h"
00021 #include "JackRPCEngineServer.c"
00022 #include "JackError.h"
00023 #include "JackServer.h"
00024 #include "JackMachThread.h"
00025 #include "JackEngine.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()
00036 {
00037     fThread = new JackMachThread(this);
00038 }
00039 
00040 JackMachServerChannel::~JackMachServerChannel()
00041 {
00042     delete fThread;
00043 }
00044 
00045 int JackMachServerChannel::Open(const char* server_name, JackServer* server)
00046 {
00047     JackLog("JackMachServerChannel::Open\n");
00048         char jack_server_entry_name[512];
00049         snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s_%s", jack_server_entry, server_name);
00050 
00051     if (!fServerPort.AllocatePort(jack_server_entry_name, 16)) { // 16 is the max possible value
00052         jack_error("Cannot check in Jack server");
00053         return -1;
00054     }
00055 
00056     if (fThread->Start() != 0) {
00057         jack_error("Cannot start Jack server listener");
00058         return -1;
00059     }
00060 
00061     fServer = server;
00062     fPortTable[fServerPort.GetPort()] = this;
00063     return 0;
00064 }
00065 
00066 void JackMachServerChannel::Close()
00067 {
00068     JackLog("JackMachServerChannel::Close\n");
00069     fThread->Kill();
00070     fServerPort.DestroyPort();
00071 }
00072 
00073 JackEngine* JackMachServerChannel::GetEngine()
00074 {
00075     return fServer->GetEngine();
00076 }
00077 
00078 JackServer* JackMachServerChannel::GetServer()
00079 {
00080     return fServer;
00081 }
00082 
00083 void JackMachServerChannel::ClientCheck(char* name, char* name_res, int protocol, int options, int* status, int* result)
00084 {
00085         *result = GetEngine()->ClientCheck(name, name_res, protocol, options, status);
00086 }
00087 
00088 void JackMachServerChannel::ClientOpen(char* name, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result)
00089 {
00090     int refnum = -1;
00091         *result = GetEngine()->ClientExternalOpen(name, &refnum, shared_engine, shared_client, shared_graph);
00092 
00093     if (*result == 0) {
00094         mach_port_t port = fServerPort.AddPort();
00095         if (port != 0) {
00096             fClientTable[port] = refnum;
00097             fPortTable[port] = this;
00098             *private_port = port;
00099         } else {
00100             jack_error("Cannot create private client mach port");
00101             *result = -1;
00102         }
00103     } else {
00104         jack_error("Cannot create new client");
00105     }
00106 }
00107 
00108 void JackMachServerChannel::ClientClose(mach_port_t private_port, int refnum)
00109 {
00110         GetEngine()->ClientExternalClose(refnum);
00111     fClientTable.erase(private_port);
00112 
00113     // Hum, hum....
00114     kern_return_t res;
00115     if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
00116         jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
00117     }
00118 }
00119 
00120 void JackMachServerChannel::ClientKill(mach_port_t private_port)
00121 {
00122     JackLog("JackMachServerChannel::ClientKill\n");
00123     int refnum = fClientTable[private_port];
00124     assert(refnum > 0);
00125     fServer->Notify(refnum, kDeadClient, 0);
00126     fClientTable.erase(private_port);
00127 
00128     // Hum, hum....
00129     kern_return_t res;
00130     if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
00131         jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
00132     }
00133 }
00134 
00135 boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply)
00136 {
00137     if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
00138         JackLog("MACH_NOTIFY_NO_SENDERS %ld\n", Request->msgh_local_port);
00139         JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port];
00140         assert(channel);
00141         channel->ClientKill(Request->msgh_local_port);
00142     } else {
00143         JackRPCEngine_server(Request, Reply);
00144     }
00145     return true;
00146 }
00147 
00148 bool JackMachServerChannel::Execute()
00149 {
00150     kern_return_t res;
00151     if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
00152         JackLog("JackMachServerChannel::Execute: err = %s\n", mach_error_string(res));
00153     }
00154     //return (res == KERN_SUCCESS);  mach_msg_server can fail if the client reply port is not valid anymore (crashed client)
00155     return true;
00156 }
00157 
00158 } // end of namespace
00159 
00160 

Generated on Thu Feb 14 11:16:02 2008 for Jackdmp by  doxygen 1.5.1