Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * plugin_tool.cpp - Fawkes plugin tool 00004 * 00005 * Created: Mon Dec 04 14:43:23 2006 00006 * Copyright 2006 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include <tools/plugin/plugin_tool.h> 00024 00025 #include <netcomm/fawkes/client.h> 00026 #include <plugin/net/messages.h> 00027 #include <plugin/net/list_message.h> 00028 #include <utils/system/argparser.h> 00029 00030 #include <cstdio> 00031 #include <cstdlib> 00032 #include <cstring> 00033 00034 using namespace fawkes; 00035 00036 /** @class PluginTool tools/plugin/plugin_tool.h 00037 * Program to communicate with plugin manager via Fawkes network. 00038 */ 00039 00040 /** Constructor. 00041 * @param argp argument parser, three arguments are handled: 00042 * - -l plugin_name load plugin named plugin_name 00043 * - -u plugin_name unload plugin named plugin_name 00044 * - -w watch for changes 00045 * @param c FawkesNetworkClient with established connection 00046 */ 00047 PluginTool::PluginTool(ArgumentParser *argp, FawkesNetworkClient *c) 00048 { 00049 this->c = c; 00050 plugin_name = NULL; 00051 quit = false; 00052 00053 if ( argp->has_arg("l") ) { 00054 opmode = M_LOAD; 00055 plugin_name = argp->arg("l"); 00056 } else if ( argp->has_arg("u") ) { 00057 opmode = M_UNLOAD; 00058 plugin_name = argp->arg("u"); 00059 } else if ( argp->has_arg("R") ) { 00060 opmode = M_RELOAD; 00061 plugin_name = argp->arg("R"); 00062 } else if ( argp->has_arg("w") ) { 00063 opmode = M_WATCH; 00064 } else if ( argp->has_arg("a") ) { 00065 opmode = M_LIST_AVAIL; 00066 } else { 00067 opmode = M_LIST_LOADED; 00068 } 00069 00070 __program_name = argp->program_name(); 00071 00072 list_found = false; 00073 } 00074 00075 00076 /** Constructor. 00077 * This constructor just set the Fawkes network client. A run() call will 00078 * fail if not one of set_load_plugin(), set_unload_plugin(), set_watch_mode() 00079 * or set_list_mode() has been called before. 00080 * @param c Fawkes network client with established connection 00081 */ 00082 PluginTool::PluginTool(FawkesNetworkClient *c) 00083 { 00084 this->c = c; 00085 plugin_name = NULL; 00086 quit = false; 00087 opmode = M_UNKNOWN; 00088 list_found = false; 00089 } 00090 00091 /** Destructor */ 00092 PluginTool::~PluginTool() 00093 { 00094 } 00095 00096 00097 /** Print usage. 00098 * @param program_name program name 00099 */ 00100 void 00101 PluginTool::print_usage(const char *program_name) 00102 { 00103 printf("Usage: %s [-l plugin|-u plugin|-R plugin|-w|-a|-L] [-r host[:port]]\n" 00104 " -l plugin Load plugin with given name\n" 00105 " -u plugin Unload plugin with given name\n" 00106 " -R plugin Reload plugin with given name\n" 00107 " -w Watch all load/unload operations\n" 00108 " -a List available plugins\n" 00109 " -L List loaded plugins (default)\n\n" 00110 " -r host[:port] Remote host (and optionally port) to connect to\n\n" 00111 " If called without any option list currently loaded plugins\n\n", 00112 program_name); 00113 } 00114 00115 /** Load plugin on next run. 00116 * The next time run is called a LOAD_PLUGIN message is sent for the 00117 * given plugin name. 00118 * @param plugin_name name of the plugin to load 00119 */ 00120 void 00121 PluginTool::set_load_plugin(const char *plugin_name) 00122 { 00123 this->plugin_name = plugin_name; 00124 opmode = M_LOAD; 00125 } 00126 00127 00128 /** Unload plugin on next run. 00129 * The next time run is called a UNLOAD_PLUGIN message is sent for the 00130 * given plugin name. 00131 * @param plugin_name name of the plugin to unload 00132 */ 00133 void 00134 PluginTool::set_unload_plugin(const char *plugin_name) 00135 { 00136 this->plugin_name = plugin_name; 00137 opmode = M_UNLOAD; 00138 } 00139 00140 00141 /** Set watch mode. 00142 * On next run() call the client will watch for new events. 00143 */ 00144 void 00145 PluginTool::set_watch_mode() 00146 { 00147 opmode = M_WATCH; 00148 } 00149 00150 00151 /** Set list mode. 00152 * On next run() call the client will list all loaded plugins once. 00153 */ 00154 void 00155 PluginTool::set_list_mode() 00156 { 00157 opmode = M_LIST_LOADED; 00158 } 00159 00160 00161 /** Handle signals. 00162 * @param signum signal number of received signal 00163 */ 00164 void 00165 PluginTool::handle_signal(int signum) 00166 { 00167 c->wake(FAWKES_CID_PLUGINMANAGER); 00168 quit = true; 00169 } 00170 00171 00172 /** Execute load operation. */ 00173 void 00174 PluginTool::load() 00175 { 00176 printf("Requesting loading of plugin %s\n", plugin_name); 00177 plugin_load_msg_t *l = (plugin_load_msg_t *)calloc(1, sizeof(plugin_load_msg_t)); 00178 strncpy(l->name, plugin_name, PLUGIN_MSG_NAME_LENGTH); 00179 00180 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER, 00181 MSG_PLUGIN_LOAD, 00182 l, sizeof(plugin_load_msg_t)); 00183 c->enqueue(msg); 00184 00185 while ( ! quit ) { 00186 c->wait(FAWKES_CID_PLUGINMANAGER); 00187 } 00188 } 00189 00190 00191 /** Execute unload operation. */ 00192 void 00193 PluginTool::unload() 00194 { 00195 printf("Requesting unloading of plugin %s\n", plugin_name); 00196 plugin_unload_msg_t *m = (plugin_unload_msg_t *)calloc(1, sizeof(plugin_unload_msg_t)); 00197 strncpy(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH); 00198 00199 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER, 00200 MSG_PLUGIN_UNLOAD, 00201 m, sizeof(plugin_unload_msg_t)); 00202 c->enqueue(msg); 00203 00204 while ( ! quit ) { 00205 c->wait(FAWKES_CID_PLUGINMANAGER); 00206 } 00207 } 00208 00209 00210 /** Execute list available operation. */ 00211 void 00212 PluginTool::list_avail() 00213 { 00214 printf("Request the list of all available plugins\n"); 00215 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER, 00216 MSG_PLUGIN_LIST_AVAIL); 00217 c->enqueue(msg); 00218 00219 while ( ! quit ) { 00220 c->wait(FAWKES_CID_PLUGINMANAGER); 00221 } 00222 } 00223 00224 00225 /** Execute list operation. */ 00226 void 00227 PluginTool::list_loaded() 00228 { 00229 // we got a list of loaded messages during startup, show them 00230 printf("Request the list of all loaded plugins\n"); 00231 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER, 00232 MSG_PLUGIN_LIST_LOADED); 00233 c->enqueue(msg); 00234 00235 while ( ! quit ) { 00236 c->wait(FAWKES_CID_PLUGINMANAGER); 00237 } 00238 } 00239 00240 00241 /** Watch for plugin manager events. */ 00242 void 00243 PluginTool::watch() 00244 { 00245 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER, 00246 MSG_PLUGIN_SUBSCRIBE_WATCH); 00247 c->enqueue(msg); 00248 printf("Watching for plugin events\n"); 00249 printf("%-10s %-40s\n", "Event", "Plugin Name/ID"); 00250 while ( ! quit ) { 00251 c->wait(FAWKES_CID_PLUGINMANAGER); 00252 } 00253 00254 // unsubscribe 00255 msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER, MSG_PLUGIN_UNSUBSCRIBE_WATCH); 00256 c->enqueue(msg); 00257 } 00258 00259 00260 /** Handler has been deregistered. 00261 */ 00262 void 00263 PluginTool::deregistered(unsigned int id) throw() 00264 { 00265 quit = true; 00266 } 00267 00268 00269 /** Inbound message received. 00270 * @param msg message. 00271 */ 00272 void 00273 PluginTool::inbound_received(FawkesNetworkMessage *msg, 00274 unsigned int id) throw() 00275 { 00276 if (msg->cid() != FAWKES_CID_PLUGINMANAGER) return; 00277 00278 if ( msg->msgid() == MSG_PLUGIN_LOADED ) { 00279 if ( msg->payload_size() != sizeof(plugin_loaded_msg_t) ) { 00280 printf("Invalid message size (load succeeded)\n"); 00281 } else { 00282 plugin_loaded_msg_t *m = (plugin_loaded_msg_t *)msg->payload(); 00283 if ( opmode == M_WATCH ) { 00284 printf("%-10s %s\n", "loaded", m->name); 00285 } else { 00286 if ( strncmp(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH) == 0 ) { 00287 printf("Loading of %s succeeded\n", plugin_name); 00288 quit = true; 00289 } 00290 } 00291 } 00292 } else if ( msg->msgid() == MSG_PLUGIN_LOAD_FAILED) { 00293 if ( msg->payload_size() != sizeof(plugin_load_failed_msg_t) ) { 00294 printf("Invalid message size (load failed)\n"); 00295 } else { 00296 plugin_load_failed_msg_t *m = (plugin_load_failed_msg_t *)msg->payload(); 00297 if ( opmode == M_WATCH ) { 00298 printf("%-10s %s\n", "loadfail", m->name); 00299 } else { 00300 if ( strncmp(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH) == 0 ) { 00301 printf("Loading of %s failed, see log for reason\n", plugin_name); 00302 quit = true; 00303 } 00304 } 00305 } 00306 } else if ( msg->msgid() == MSG_PLUGIN_UNLOADED ) { 00307 if ( msg->payload_size() != sizeof(plugin_unloaded_msg_t) ) { 00308 printf("Invalid message size (unload succeeded)\n"); 00309 } else { 00310 plugin_unloaded_msg_t *m = (plugin_unloaded_msg_t *)msg->payload(); 00311 if ( opmode == M_WATCH ) { 00312 printf("%-10s %s\n", "unloaded", m->name); 00313 } else { 00314 if ( strncmp(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH) == 0 ) { 00315 printf("Unloading of %s succeeded\n", plugin_name); 00316 quit = true; 00317 } 00318 } 00319 } 00320 } else if ( msg->msgid() == MSG_PLUGIN_UNLOAD_FAILED) { 00321 if ( msg->payload_size() != sizeof(plugin_unload_failed_msg_t) ) { 00322 printf("Invalid message size (unload failed)\n"); 00323 } else { 00324 plugin_unload_failed_msg_t *m = (plugin_unload_failed_msg_t *)msg->payload(); 00325 if ( opmode == M_WATCH ) { 00326 printf("%-10s %s\n", "unloadfail", m->name); 00327 } else { 00328 if ( strncmp(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH) == 0 ) { 00329 printf("Unloading of %s failed, see log for reason\n", plugin_name); 00330 quit = true; 00331 } 00332 } 00333 } 00334 } else if (msg->msgid() == MSG_PLUGIN_AVAIL_LIST ) { 00335 PluginListMessage *plm = msg->msgc<PluginListMessage>(); 00336 if ( plm->has_next() ) { 00337 printf("Available plugins:\n"); 00338 while ( plm->has_next() ) { 00339 char *plugin_name = plm->next(); 00340 char *plugin_desc = NULL; 00341 if ( plm->has_next() ) { 00342 plugin_desc = plm->next(); 00343 } else { 00344 throw Exception("Invalid plugin list received"); 00345 } 00346 printf(" %-16s (%s)\n", plugin_name, plugin_desc); 00347 free(plugin_name); 00348 free(plugin_desc); 00349 } 00350 } else { 00351 printf("No plugins available\n"); 00352 } 00353 quit = true; 00354 delete plm; 00355 } else if (msg->msgid() == MSG_PLUGIN_LOADED_LIST ) { 00356 PluginListMessage *plm = msg->msgc<PluginListMessage>(); 00357 if ( plm->has_next() ) { 00358 printf("Loaded plugins:\n"); 00359 while ( plm->has_next() ) { 00360 char *p = plm->next(); 00361 printf(" %s\n", p); 00362 free(p); 00363 } 00364 } else { 00365 printf("No plugins loaded\n"); 00366 } 00367 quit = true; 00368 delete plm; 00369 } else if ( msg->msgid() == MSG_PLUGIN_AVAIL_LIST_FAILED) { 00370 printf("Obtaining list of available plugins failed\n"); 00371 } else if ( msg->msgid() == MSG_PLUGIN_LOADED_LIST_FAILED) { 00372 printf("Obtaining list of loaded plugins failed\n"); 00373 } 00374 } 00375 00376 00377 void 00378 PluginTool::connection_established(unsigned int id) throw() 00379 { 00380 // ignored, client has to be connected already 00381 } 00382 00383 00384 void 00385 PluginTool::connection_died(unsigned int id) throw() 00386 { 00387 printf("Connection died, exiting\n"); 00388 quit = true; 00389 } 00390 00391 /** Run opmode as requested determined by the arguments. */ 00392 void 00393 PluginTool:: run() 00394 { 00395 c->register_handler(this, FAWKES_CID_PLUGINMANAGER); 00396 00397 switch (opmode) { 00398 case M_LOAD: 00399 load(); 00400 break; 00401 00402 case M_UNLOAD: 00403 unload(); 00404 break; 00405 00406 case M_RELOAD: 00407 unload(); 00408 quit = false; 00409 load(); 00410 break; 00411 00412 case M_LIST_AVAIL: 00413 list_avail(); 00414 break; 00415 00416 case M_LIST_LOADED: 00417 list_loaded(); 00418 break; 00419 00420 case M_WATCH: 00421 watch(); 00422 break; 00423 00424 default: 00425 print_usage(__program_name); 00426 } 00427 00428 c->deregister_handler(FAWKES_CID_PLUGINMANAGER); 00429 }