|
Urbi SDK Remote for C++
2.7.5
|
00001 /* 00002 * Copyright (C) 2008-2011, Gostai S.A.S. 00003 * 00004 * This software is provided "as is" without warranty of any kind, 00005 * either expressed or implied, including but not limited to the 00006 * implied warranties of fitness for a particular purpose. 00007 * 00008 * See the LICENSE file for more information. 00009 */ 00010 00011 #include <string> 00012 #include <libport/cassert> 00013 #include <cstdarg> 00014 #include <libport/cstdlib> 00015 #include <iostream> 00016 #include <stdexcept> 00017 00018 #include <boost/assign/list_of.hpp> 00019 using namespace boost::assign; 00020 00021 #include <libport/cli.hh> 00022 #include <libport/containers.hh> 00023 #include <libport/debug.hh> 00024 #include <libport/file-system.hh> 00025 #include <libport/foreach.hh> 00026 #include <libport/path.hh> 00027 #include <libport/package-info.hh> 00028 #include <libport/program-name.hh> 00029 #include <libport/sysexits.hh> 00030 #include <libport/unistd.h> 00031 #include <libport/windows.hh> 00032 #include <libport/option-parser.hh> 00033 #include <libport/xltdl.hh> 00034 00035 #include <urbi/exit.hh> 00036 #include <urbi/package-info.hh> 00037 #include <urbi/uclient.hh> 00038 #include <urbi/urbi-root.hh> 00039 00040 GD_CATEGORY(Urbi.UrbiLaunch); 00041 00042 using namespace urbi; 00043 using libport::program_name; 00044 00045 static UCallbackAction 00046 onError(const UMessage& msg) 00047 { 00048 LIBPORT_USE(msg); 00049 GD_FERROR("%s: load module error: %s", program_name(), msg.message); 00050 return URBI_CONTINUE; 00051 } 00052 00053 static UCallbackAction 00054 onDone(const UMessage&) 00055 { 00056 ::exit(0); 00057 } 00058 00059 static int 00060 connect_plugin(const std::string& host, int port, 00061 const libport::cli_args_type& modules) 00062 { 00063 UClient cl(host, port); 00064 if (cl.error()) 00065 // UClient already displayed an error message. 00066 ::exit(1); 00067 cl.setErrorCallback(callback(&onError)); 00068 cl.setCallback(callback(&onDone), "output"); 00069 foreach (const std::string& m, modules) 00070 cl << "loadModule(\"" << m << "\");"; 00071 cl << "output << 1;"; 00072 while (true) 00073 sleep(1); 00074 return 0; 00075 } 00076 00077 static void 00078 usage(libport::OptionParser& parser) 00079 { 00080 std::cout << 00081 "usage: " << program_name() << 00082 " [OPTIONS] MODULE_NAMES ... [-- UOPTIONS...]\n" 00083 "Start an UObject in either remote or plugin mode.\n" 00084 << parser << 00085 "MODULE_NAMES is a list of modules.\n" 00086 "UOPTIONS are passed to urbi::main in remote and start modes.\n" 00087 "\n" 00088 "Exit values:\n" 00089 " 0 success\n" 00090 " " << EX_NOINPUT << " some of the MODULES are missing\n" 00091 " " << EX_OSFILE << " libuobject is missing\n" 00092 " * other kinds of errors\n" 00093 ; 00094 ::exit(EX_OK); 00095 } 00096 00097 00098 static 00099 void 00100 version() 00101 { 00102 std::cout << urbi::package_info() << std::endl 00103 << libport::exit(EX_OK); 00104 } 00105 00106 00107 static 00108 int 00109 urbi_launch_(int argc, const char* argv[], UrbiRoot& urbi_root) 00110 { 00111 libport::program_initialize(argc, argv); 00112 00113 // The options passed to urbi::main. 00114 libport::cli_args_type args; 00115 00116 args << argv[0]; 00117 00118 libport::OptionValue 00119 arg_custom("start using the shared library FILE", "custom", 'c', "FILE"), 00120 arg_pfile("file containing the port to listen to", "port-file", 0, "FILE"); 00121 libport::OptionFlag 00122 arg_plugin("start as a plugin uobject on a running server", "plugin", 'p'), 00123 arg_remote("start as a remote uobject", "remote", 'r'), 00124 arg_root("output Urbi root and exit", "print-root"), 00125 arg_start("start an urbi server and connect as plugin", "start", 's'); 00126 libport::OptionsEnd arg_end; 00127 00128 libport::OptionParser opt_parser; 00129 opt_parser << "Options:" 00130 << libport::opts::help 00131 << libport::opts::version 00132 << arg_root 00133 << arg_custom 00134 #ifndef LIBPORT_DEBUG_DISABLE 00135 << libport::opts::debug 00136 #endif 00137 << "Mode selection:" 00138 << arg_plugin 00139 << arg_remote 00140 << arg_start 00141 << "Networking:" 00142 << libport::opts::host 00143 << libport::opts::port 00144 << arg_pfile 00145 << arg_end; 00146 00147 // The list of modules. 00148 libport::cli_args_type modules; 00149 try 00150 { 00151 modules = opt_parser(libport::program_arguments()); 00152 } 00153 catch (const libport::Error& e) 00154 { 00155 const libport::Error::errors_type& err = e.errors(); 00156 foreach (std::string wrong_arg, err) 00157 libport::invalid_option(wrong_arg); 00158 } 00159 00160 if (libport::opts::version.get()) 00161 version(); 00162 if (libport::opts::help.get()) 00163 usage(opt_parser); 00164 if (arg_root.get()) 00165 std::cout << urbi_root.root() << std::endl << libport::exit(0); 00166 00167 // Connection mode. 00168 enum ConnectMode 00169 { 00171 MODE_PLUGIN_START, 00173 MODE_PLUGIN_LOAD, 00175 MODE_REMOTE 00176 }; 00177 ConnectMode connect_mode = MODE_REMOTE; 00178 00179 if (arg_plugin.get()) 00180 connect_mode = MODE_PLUGIN_LOAD; 00181 if (arg_remote.get()) 00182 connect_mode = MODE_REMOTE; 00183 if (arg_start.get()) 00184 connect_mode = MODE_PLUGIN_START; 00185 00187 std::string host = libport::opts::host.value(UClient::default_host()); 00188 if (libport::opts::host.filled()) 00189 args << "--host" << host; 00190 00192 int port = libport::opts::port.get<int>(urbi::UClient::URBI_PORT); 00193 if (libport::opts::port.filled()) 00194 args << "--port" << libport::opts::port.value(); 00195 00196 if (arg_pfile.filled()) 00197 { 00198 std::string file = arg_pfile.value(); 00199 if (connect_mode == MODE_PLUGIN_LOAD) 00200 port = libport::file_contents_get<int>(file); 00201 args << "--port-file" << file; 00202 } 00203 args.insert(args.end(), arg_end.get().begin(), arg_end.get().end()); 00204 00205 if (connect_mode == MODE_PLUGIN_LOAD) 00206 return connect_plugin(host, port, modules); 00207 00208 // Open the right core library. 00209 if (arg_custom.filled()) 00210 urbi_root.load_custom(arg_custom.value()); 00211 else if (connect_mode == MODE_REMOTE) 00212 urbi_root.load_remote(); 00213 else 00214 urbi_root.load_plugin(); 00215 00216 // If URBI_UOBJECT_PATH is not defined, first look in ., then in the 00217 // stdlib. 00218 std::string uobject_path = libport::xgetenv("URBI_UOBJECT_PATH", ".:"); 00219 00220 // Load the modules using our uobject library path. 00221 libport::xlt_advise dl; 00222 dl.ext().path().push_back(uobject_path, ":"); 00223 foreach(const std::string& s, urbi_root.uobjects_path()) 00224 dl.path().push_back(s); 00225 foreach (const std::string& s, modules) 00226 dl.open(s); 00227 00228 return urbi_root.urbi_main(args, true, true); 00229 } 00230 00231 extern "C" 00232 { 00233 int 00234 URBI_SDK_API 00235 urbi_launch(int argc, const char* argv[], UrbiRoot& root) 00236 try 00237 { 00238 return urbi_launch_(argc, argv, root); 00239 } 00240 catch (const std::exception& e) 00241 { 00242 std::cerr << argv[0] << ": " << e.what() << std::endl 00243 << libport::exit(EX_FAIL); 00244 } 00245 }