Simplify server temporary mode : now use a JackTemporaryException.
[jack2.git] / macosx / JackMachServerChannel.cpp
blob19295f796978485ee7f710e35bec589c6f794761
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"
27 #include "JackServerGlobals.h"
29 using namespace std;
31 namespace Jack
34 map<mach_port_t, JackMachServerChannel*> JackMachServerChannel::fPortTable;
36 JackMachServerChannel::JackMachServerChannel():fThread(this)
39 JackMachServerChannel::~JackMachServerChannel()
42 int JackMachServerChannel::Open(const char* server_name, JackServer* server)
44 jack_log("JackMachServerChannel::Open");
45 char jack_server_entry_name[512];
46 snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
48 if (!fServerPort.AllocatePort(jack_server_entry_name, 16)) { // 16 is the max possible value
49 jack_error("Cannot check in Jack server");
50 return -1;
53 fServer = server;
54 fPortTable[fServerPort.GetPort()] = this;
55 return 0;
58 void JackMachServerChannel::Close()
60 jack_log("JackMachServerChannel::Close");
61 fThread.Kill();
62 fServerPort.DestroyPort();
65 int JackMachServerChannel::Start()
67 if (fThread.Start() != 0) {
68 jack_error("Cannot start Jack server listener");
69 return -1;
72 return 0;
75 JackLockedEngine* JackMachServerChannel::GetEngine()
77 return fServer->GetEngine();
80 JackServer* JackMachServerChannel::GetServer()
82 return fServer;
85 void JackMachServerChannel::ClientCheck(char* name, char* name_res, int protocol, int options, int* status, int* result)
87 *result = GetEngine()->ClientCheck(name, name_res, protocol, options, status);
90 void JackMachServerChannel::ClientOpen(char* name, int pid, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result)
92 int refnum = -1;
93 *result = GetEngine()->ClientExternalOpen(name, pid, &refnum, shared_engine, shared_client, shared_graph);
95 if (*result == 0) {
96 mach_port_t port = fServerPort.AddPort();
97 if (port != 0) {
98 fClientTable[port] = refnum;
99 fPortTable[port] = this;
100 *private_port = port;
101 } else {
102 jack_error("Cannot create private client mach port");
103 *result = -1;
105 } else {
106 jack_error("Cannot create new client");
110 void JackMachServerChannel::ClientClose(mach_port_t private_port, int refnum)
112 GetEngine()->ClientExternalClose(refnum);
113 fClientTable.erase(private_port);
115 // Hum, hum....
116 kern_return_t res;
117 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
118 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
122 void JackMachServerChannel::ClientKill(mach_port_t private_port)
124 jack_log("JackMachServerChannel::ClientKill");
125 int refnum = fClientTable[private_port];
126 assert(refnum > 0);
127 fServer->ClientKill(refnum);
128 fClientTable.erase(private_port);
130 // Hum, hum....
131 kern_return_t res;
132 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) {
133 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res));
137 boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply)
139 if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
140 jack_log("MACH_NOTIFY_NO_SENDERS %ld", Request->msgh_local_port);
141 JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port];
142 assert(channel);
143 channel->ClientKill(Request->msgh_local_port);
144 } else {
145 JackRPCEngine_server(Request, Reply);
147 return true;
150 bool JackMachServerChannel::Execute()
152 kern_return_t res;
153 if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
154 jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res));
156 //return (res == KERN_SUCCESS); mach_msg_server can fail if the client reply port is not valid anymore (crashed client)
157 return true;
160 } // end of namespace