Merge branch 'master' into no-self-connect
[jack2.git] / macosx / JackMachServerChannel.cpp
blob84d87b93f2689b235090531deedabcf21a261e40
1 /*
2 Copyright (C) 2004-2008 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "JackTools.h"
21 #include "JackMachServerChannel.h"
22 #include "JackRPCEngineServer.c"
23 #include "JackError.h"
24 #include "JackServer.h"
25 #include "JackLockedEngine.h"
26 #include "JackNotification.h"
28 using namespace std;
30 namespace Jack
33 map<mach_port_t, JackMachServerChannel*> JackMachServerChannel::fPortTable;
35 JackMachServerChannel::JackMachServerChannel():fThread(this)
38 JackMachServerChannel::~JackMachServerChannel()
41 int JackMachServerChannel::Open(const char* server_name, JackServer* server)
43 jack_log("JackMachServerChannel::Open");
44 char jack_server_entry_name[512];
45 snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
47 if (!fServerPort.AllocatePort(jack_server_entry_name, 16)) { // 16 is the max possible value
48 jack_error("Cannot check in Jack server");
49 return -1;
52 if (fThread.Start() != 0) {
53 jack_error("Cannot start Jack server listener");
54 return -1;
57 fServer = server;
58 fPortTable[fServerPort.GetPort()] = this;
59 return 0;
62 void JackMachServerChannel::Close()
64 jack_log("JackMachServerChannel::Close");
65 fThread.Kill();
66 fServerPort.DestroyPort();
69 JackLockedEngine* JackMachServerChannel::GetEngine()
71 return fServer->GetEngine();
74 JackServer* JackMachServerChannel::GetServer()
76 return fServer;
79 void JackMachServerChannel::ClientCheck(char* name, char* name_res, int protocol, int options, int* status, int* result)
81 *result = GetEngine()->ClientCheck(name, name_res, protocol, options, status);
84 void JackMachServerChannel::ClientOpen(char* name, int pid, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result)
86 int refnum = -1;
87 *result = GetEngine()->ClientExternalOpen(name, pid, &refnum, shared_engine, shared_client, shared_graph);
89 if (*result == 0) {
90 mach_port_t port = fServerPort.AddPort();
91 if (port != 0) {
92 fClientTable[port] = refnum;
93 fPortTable[port] = this;
94 *private_port = port;
95 } else {
96 jack_error("Cannot create private client mach port");
97 *result = -1;
99 } else {
100 jack_error("Cannot create new client");
104 void JackMachServerChannel::ClientClose(mach_port_t private_port, int refnum)
106 GetEngine()->ClientExternalClose(refnum);
107 fClientTable.erase(private_port);
109 // Hum, hum....
110 kern_return_t res;
111 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
112 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
116 void JackMachServerChannel::ClientKill(mach_port_t private_port)
118 jack_log("JackMachServerChannel::ClientKill");
119 int refnum = fClientTable[private_port];
120 assert(refnum > 0);
121 fServer->ClientKill(refnum);
122 fClientTable.erase(private_port);
124 // Hum, hum....
125 kern_return_t res;
126 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
127 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
131 boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply)
133 if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
134 jack_log("MACH_NOTIFY_NO_SENDERS %ld", Request->msgh_local_port);
135 JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port];
136 assert(channel);
137 channel->ClientKill(Request->msgh_local_port);
138 } else {
139 JackRPCEngine_server(Request, Reply);
141 return true;
144 bool JackMachServerChannel::Execute()
146 kern_return_t res;
147 if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
148 jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res));
150 //return (res == KERN_SUCCESS); mach_msg_server can fail if the client reply port is not valid anymore (crashed client)
151 return true;
154 } // end of namespace