1 // Copyright (c) 2007, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 #include <mach/mach.h> 31 #include <servers/bootstrap.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <sys/stat.h> 35 #include <unistd.h> 36 37 //============================================================================== 38 // class OnDemandServer : 39 // A basic on-demand server launcher supporting a single named service port 40 // 41 // Example Usage : 42 // 43 // kern_return_t result; 44 // OnDemandServer *server = OnDemandServer::Create("/tmp/myserver", 45 // "com.MyCompany.MyServiceName", 46 // true, 47 // &result); 48 // 49 // if (server) { 50 // server->LaunchOnDemand(); 51 // mach_port_t service_port = GetServicePort(); 52 // 53 // // Send a mach message to service_port and "myserver" will be launched 54 // } 55 // 56 // 57 // ---- Now in the server code ---- 58 // 59 // // "myserver" should get the service port and read the message which 60 // // launched it: 61 // mach_port_t service_rcv_port_; 62 // kern_return_t kr = bootstrap_check_in(bootstrap_port, 63 // "com.MyCompany.MyServiceName", 64 // &service_rcv_port_); 65 // // mach_msg() read service_rcv_port_ .... 66 // 67 // .... 68 // 69 // // Later "myserver" may want to unregister the service if it doesn't 70 // // want its bootstrap service to stick around after it exits. 71 // 72 // // DO NOT use mach_port_deallocate() here -- it will fail and the 73 // // following bootstrap_register() will also fail leaving our service 74 // // name hanging around forever (until reboot) 75 // kern_return_t kr = mach_port_destroy(mach_task_self(), service_rcv_port_); 76 // 77 // kr = bootstrap_register(bootstrap_port, 78 // "com.MyCompany.MyServiceName", 79 // MACH_PORT_NULL); 80 81 class OnDemandServer { 82 public: 83 // must call Initialize() to be useful OnDemandServer()84 OnDemandServer() 85 : server_port_(MACH_PORT_NULL), 86 service_port_(MACH_PORT_NULL), 87 unregister_on_cleanup_(true) { 88 } 89 90 // Creates the bootstrap server and service 91 kern_return_t Initialize(const char *server_command, 92 const char *service_name, 93 bool unregister_on_cleanup); 94 95 // Returns an OnDemandServer object if successful, or NULL if there's 96 // an error. The error result will be returned in out_result. 97 // 98 // server_command : the full path name including optional command-line 99 // arguments to the executable representing the server 100 // 101 // service_name : represents service name 102 // something like "com.company.ServiceName" 103 // 104 // unregister_on_cleanup : if true, unregisters the service name 105 // when the OnDemandServer is deleted -- unregistering will 106 // ONLY be possible if LaunchOnDemand() has NOT been called. 107 // If false, then the service will continue to be registered 108 // even after the current process quits. 109 // 110 // out_result : if non-NULL, returns the result 111 // this value will be KERN_SUCCESS if Create() returns non-NULL 112 // 113 static OnDemandServer *Create(const char *server_command, 114 const char *service_name, 115 bool unregister_on_cleanup, 116 kern_return_t *out_result); 117 118 // Cleans up and if LaunchOnDemand() has not yet been called then 119 // the bootstrap service will be unregistered. 120 ~OnDemandServer(); 121 122 // This must be called if we intend to commit to launching the server 123 // by sending a mach message to our service port. Do not call it otherwise 124 // or it will be difficult (impossible?) to unregister the service name. 125 void LaunchOnDemand(); 126 127 // This is the port we need to send a mach message to after calling 128 // LaunchOnDemand(). Sending a message causing an immediate launch 129 // of the server GetServicePort()130 mach_port_t GetServicePort() { return service_port_; }; 131 132 private: 133 // Disallow copy constructor 134 OnDemandServer(const OnDemandServer&); 135 136 // Cleans up and if LaunchOnDemand() has not yet been called then 137 // the bootstrap service will be unregistered. 138 void Unregister(); 139 140 name_t service_name_; 141 142 mach_port_t server_port_; 143 mach_port_t service_port_; 144 bool unregister_on_cleanup_; 145 }; 146