|
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 00012 00013 #include <libport/cerrno> 00014 #include <libport/cstdio> 00015 #include <libport/debug.hh> 00016 #include <libport/unistd.h> 00017 00018 #include <iostream> 00019 #include <list> 00020 #include <sstream> 00021 00022 #include <libport/debug.hh> 00023 #include <libport/cli.hh> 00024 #include <libport/containers.hh> 00025 #include <libport/foreach.hh> 00026 #include <libport/lexical-cast.hh> 00027 #include <libport/package-info.hh> 00028 #include <libport/program-name.hh> 00029 #include <libport/sysexits.hh> 00030 00031 #include <urbi/package-info.hh> 00032 #include <urbi/uexternal.hh> 00033 #include <urbi/umain.hh> 00034 #include <urbi/umessage.hh> 00035 #include <urbi/uobject.hh> 00036 #include <urbi/urbi-root.hh> 00037 #include <urbi/usyncclient.hh> 00038 #include <libuobject/remote-ucontext-impl.hh> 00039 using libport::program_name; 00040 00041 GD_CATEGORY(Urbi.UrbiLaunch); 00042 00043 namespace urbi 00044 { 00045 static impl::RemoteUContextImpl* defaultContext; 00046 00047 static 00048 UCallbackAction 00049 debug(const UMessage& msg) 00050 { 00051 LIBPORT_USE(msg); 00052 GD_SWARN("unexpected message: " << msg); 00053 return URBI_CONTINUE; 00054 } 00055 00056 static 00057 UCallbackAction 00058 endProgram(const UMessage& msg) 00059 { 00060 LIBPORT_USE(msg); 00061 GD_SWARN("got a disconnection message: " << msg); 00062 exit(0); 00063 return URBI_CONTINUE; //stupid gcc 00064 } 00065 00066 static 00067 void 00068 usage() 00069 { 00070 std::cout << 00071 "usage:\n" << libport::program_name() << " [OPTION]...\n" 00072 "\n" 00073 "Options:\n" 00074 " -b, --buffer SIZE input buffer size" 00075 << " [" << UAbstractClient::URBI_BUFLEN << "]\n" 00076 " -h, --help output this message and exit successfully\n" 00077 " -H, --host ADDR server host name" 00078 << " [" << UClient::default_host() << "]\n" 00079 " --server put remote in server mode\n" 00080 " --no-sync-client use UClient instead of USyncClient\n" 00081 " -p, --port PORT tcp port to listen to" 00082 << " [" << UAbstractClient::URBI_PORT << "]\n" 00083 " -r, --port-file FILE file containing the port to listen to\n" 00084 " -V, --version print version information and exit\n" 00085 " -d, --disconnect exit program if disconnected [default]\n" 00086 " -s, --stay-alive do not exit program if disconnected\n" 00087 " --describe describe loaded UObjects and exit\n" 00088 " --describe-file FILE write the list of present UObjects to FILE\n" 00089 << libport::exit (EX_OK); 00090 } 00091 00092 static 00093 void 00094 version() 00095 { 00096 std::cout << urbi::package_info() << std::endl 00097 << libport::exit (EX_OK); 00098 } 00099 00100 typedef std::vector<std::string> files_type; 00101 int 00102 initialize(const std::string& host, int port, size_t buflen, 00103 bool exitOnDisconnect, bool server, const files_type& files, 00104 bool useSyncClient) 00105 { 00106 GD_FINFO_TRACE("this is %s", program_name()); 00107 GD_SINFO_TRACE(urbi::package_info()); 00108 GD_FINFO_TRACE("remote component running on %s:%s", host, port); 00109 if (useSyncClient) 00110 { 00111 USyncClient::options o; 00112 o.server(server); 00113 new USyncClient(host, port, buflen, o); 00114 } 00115 else 00116 { 00117 GD_WARN("the no-sync-client mode is dangerous. " 00118 "Any attempt to use synchronous operation will crash" 00119 " your program."); 00120 UClient::options o; 00121 o.server(server); 00122 setDefaultClient(new UClient(host, port, buflen, o)); 00123 } 00124 00125 if (!getDefaultClient() || getDefaultClient()->error()) 00126 std::cerr << "ERROR: failed to connect, exiting..." << std::endl 00127 << libport::exit(1); 00128 00129 if (exitOnDisconnect) 00130 getDefaultClient()->setClientErrorCallback(callback(&endProgram)); 00131 00132 #ifdef LIBURBIDEBUG 00133 getDefaultClient()->setWildcardCallback(callback(&debug)); 00134 #else 00135 getDefaultClient()->setErrorCallback(callback(&debug)); 00136 #endif 00137 00138 // Wait for client to be connected if in server mode. 00139 // Also wait for initialization exchanges. 00140 while (!getDefaultClient() 00141 || (!getDefaultClient()->isConnected() 00142 && !getDefaultClient()->error()) 00143 || getDefaultClient()->connectionID().empty()) 00144 usleep(20000); 00145 00146 defaultContext = new impl::RemoteUContextImpl( 00147 (USyncClient*)dynamic_cast<UClient*>(getDefaultClient())); 00148 00149 // Initialize in the correct thread. 00150 getDefaultClient()->notifyCallbacks 00151 (UMessage(*getDefaultClient(), 0, externalModuleTag, 00152 libport::format("[%s]", UEM_INIT))); 00153 // Load initialization files. 00154 foreach (const std::string& file, files) 00155 getDefaultClient()->sendFile(file); 00156 return 0; 00157 } 00158 00159 namespace 00160 { 00161 static 00162 void 00163 argument_with_option(const char* longopt, 00164 char shortopt, 00165 const std::string& val) 00166 { 00167 std::cerr 00168 << program_name() 00169 << ": warning: arguments without options are deprecated" 00170 << std::endl 00171 << "use `-" << shortopt << ' ' << val << '\'' 00172 << " or `--" << longopt << ' ' << val << "' instead" 00173 << std::endl 00174 << "Try `" << program_name() << " --help' for more information." 00175 << std::endl; 00176 } 00177 00178 } 00179 00180 00181 URBI_SDK_API int 00182 main(const libport::cli_args_type& args, UrbiRoot&, bool block, bool) 00183 { 00184 GD_INIT(); 00185 00186 std::string host = UClient::default_host(); 00187 bool exitOnDisconnect = true; 00188 int port = UAbstractClient::URBI_PORT; 00189 bool server = false; 00190 bool useSyncClient = true; 00191 bool describeMode = false; 00192 std::string describeFile; 00193 size_t buflen = UAbstractClient::URBI_BUFLEN; 00194 // Files to load 00195 files_type files; 00196 00197 // The number of the next (non-option) argument. 00198 unsigned argp = 1; 00199 for (unsigned i = 1; i < args.size(); ++i) 00200 { 00201 const std::string& arg = args[i]; 00202 if (arg == "--buffer" || arg == "-b") 00203 buflen = libport::convert_argument<size_t>(args, i++); 00204 else if (arg == "--disconnect" || arg == "-d") 00205 exitOnDisconnect = true; 00206 else if (arg == "--file" || arg == "-f") 00207 files.push_back(libport::convert_argument<const char*>(args, i++)); 00208 else if (arg == "--stay-alive" || arg == "-s") 00209 exitOnDisconnect = false; 00210 else if (arg == "--help" || arg == "-h") 00211 usage(); 00212 else if (arg == "--host" || arg == "-H") 00213 host = libport::convert_argument<std::string>(args, i++); 00214 else if (arg == "--no-sync-client") 00215 useSyncClient = false; 00216 else if (arg == "--port" || arg == "-p") 00217 port = libport::convert_argument<unsigned>(args, i++); 00218 else if (arg == "--port-file" || arg == "-r") 00219 port = 00220 (libport::file_contents_get<int> 00221 (libport::convert_argument<const char*>(args, i++))); 00222 else if (arg == "--server") 00223 server = true; 00224 // FIXME: Remove -v some day. 00225 else if (arg == "--version" || arg == "-V" || arg == "-v") 00226 version(); 00227 else if (arg == "--describe") 00228 describeMode = true; 00229 else if (arg == "--describe-file") 00230 describeFile = libport::convert_argument<const char*>(args, i++); 00231 else if (arg[0] == '-') 00232 libport::invalid_option(arg); 00233 else 00234 // A genuine argument. 00235 switch (argp++) 00236 { 00237 case 1: 00238 argument_with_option("host", 'H', args[i]); 00239 host = args[i]; 00240 break; 00241 case 2: 00242 argument_with_option("port", 'p', args[i]); 00243 port = libport::convert_argument<unsigned>("port", args[i]); 00244 break; 00245 default: 00246 std::cerr << "unexpected argument: " << arg << std::endl 00247 << libport::exit(EX_USAGE); 00248 } 00249 } 00250 00251 if (describeMode) 00252 { 00253 foreach(baseURBIStarter* s, baseURBIStarter::list()) 00254 std::cout << s->name << std::endl; 00255 foreach(baseURBIStarterHub* s, baseURBIStarterHub::list()) 00256 std::cout << s->name << std::endl; 00257 return 0; 00258 } 00259 if (!describeFile.empty()) 00260 { 00261 std::ofstream of(describeFile.c_str()); 00262 foreach(baseURBIStarter* s, baseURBIStarter::list()) 00263 of << s->name << std::endl; 00264 foreach(baseURBIStarterHub* s, baseURBIStarterHub::list()) 00265 of << s->name << std::endl; 00266 } 00267 initialize(host, port, buflen, exitOnDisconnect, server, files, 00268 useSyncClient); 00269 00270 if (block) 00271 while (true) 00272 usleep(30000000); 00273 return 0; 00274 } 00275 00276 }