pion  5.0.6
utils/piond.cpp
00001 // ---------------------------------------------------------------------
00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
00003 // ---------------------------------------------------------------------
00004 // Copyright (C) 2007-2014 Splunk Inc.  (https://github.com/splunk/pion)
00005 //
00006 // Distributed under the Boost Software License, Version 1.0.
00007 // See http://www.boost.org/LICENSE_1_0.txt
00008 //
00009 
00010 #include <vector>
00011 #include <iostream>
00012 #include <boost/asio.hpp>
00013 #include <pion/error.hpp>
00014 #include <pion/plugin.hpp>
00015 #include <pion/process.hpp>
00016 #include <pion/http/plugin_server.hpp>
00017 
00018 // these are used only when linking to static web service libraries
00019 // #ifdef PION_STATIC_LINKING
00020 PION_DECLARE_PLUGIN(EchoService)
00021 PION_DECLARE_PLUGIN(FileService)
00022 PION_DECLARE_PLUGIN(HelloService)
00023 PION_DECLARE_PLUGIN(LogService)
00024 PION_DECLARE_PLUGIN(CookieService)
00025 
00026 using namespace std;
00027 using namespace pion;
00028 
00029 
00031 void argument_error(void)
00032 {
00033     std::cerr << "usage:   piond [OPTIONS] RESOURCE WEBSERVICE" << std::endl
00034               << "         piond [OPTIONS] -c SERVICE_CONFIG_FILE" << std::endl
00035               << "options: [-ssl PEM_FILE] [-i IP] [-p PORT] [-d PLUGINS_DIR] [-o OPTION=VALUE] [-v]" << std::endl;
00036 }
00037 
00038 
00040 int main (int argc, char *argv[])
00041 {
00042     static const unsigned int DEFAULT_PORT = 8080;
00043 
00044     // used to keep track of web service name=value options
00045     typedef std::vector<std::pair<std::string, std::string> >   ServiceOptionsType;
00046     ServiceOptionsType service_options;
00047     
00048     // parse command line: determine port number, RESOURCE and WEBSERVICE
00049     boost::asio::ip::tcp::endpoint cfg_endpoint(boost::asio::ip::tcp::v4(), DEFAULT_PORT);
00050     std::string service_config_file;
00051     std::string resource_name;
00052     std::string service_name;
00053     std::string ssl_pem_file;
00054     bool ssl_flag = false;
00055     bool verbose_flag = false;
00056     
00057     for (int argnum=1; argnum < argc; ++argnum) {
00058         if (argv[argnum][0] == '-') {
00059             if (argv[argnum][1] == 'p' && argv[argnum][2] == '\0' && argnum+1 < argc) {
00060                 // set port number
00061                 ++argnum;
00062                 cfg_endpoint.port(strtoul(argv[argnum], 0, 10));
00063                 if (cfg_endpoint.port() == 0) cfg_endpoint.port(DEFAULT_PORT);
00064             } else if (argv[argnum][1] == 'i' && argv[argnum][2] == '\0' && argnum+1 < argc) {
00065                 // set ip address
00066                 cfg_endpoint.address(boost::asio::ip::address::from_string(argv[++argnum]));
00067             } else if (argv[argnum][1] == 'c' && argv[argnum][2] == '\0' && argnum+1 < argc) {
00068                 service_config_file = argv[++argnum];
00069             } else if (argv[argnum][1] == 'd' && argv[argnum][2] == '\0' && argnum+1 < argc) {
00070                 // add the service plug-ins directory to the search path
00071                 try { plugin::add_plugin_directory(argv[++argnum]); }
00072                 catch (error::directory_not_found&) {
00073                     std::cerr << "piond: Web service plug-ins directory does not exist: "
00074                         << argv[argnum] << std::endl;
00075                     return 1;
00076                 }
00077             } else if (argv[argnum][1] == 'o' && argv[argnum][2] == '\0' && argnum+1 < argc) {
00078                 std::string option_name(argv[++argnum]);
00079                 std::string::size_type pos = option_name.find('=');
00080                 if (pos == std::string::npos) {
00081                     argument_error();
00082                     return 1;
00083                 }
00084                 std::string option_value(option_name, pos + 1);
00085                 option_name.resize(pos);
00086                 service_options.push_back( std::make_pair(option_name, option_value) );
00087             } else if (argv[argnum][1] == 's' && argv[argnum][2] == 's' &&
00088                        argv[argnum][3] == 'l' && argv[argnum][4] == '\0' && argnum+1 < argc) {
00089                 ssl_flag = true;
00090                 ssl_pem_file = argv[++argnum];
00091             } else if (argv[argnum][1] == 'v' && argv[argnum][2] == '\0') {
00092                 verbose_flag = true;
00093             } else {
00094                 argument_error();
00095                 return 1;
00096             }
00097         } else if (argnum+2 == argc) {
00098             // second to last argument = RESOURCE
00099             resource_name = argv[argnum];
00100         } else if (argnum+1 == argc) {
00101             // last argument = WEBSERVICE
00102             service_name = argv[argnum];
00103         } else {
00104             argument_error();
00105             return 1;
00106         }
00107     }
00108     
00109     if (service_config_file.empty() && (resource_name.empty() || service_name.empty())) {
00110         argument_error();
00111         return 1;
00112     }
00113     
00114     // initialize signal handlers, etc.
00115     process::initialize();
00116     
00117     // initialize log system (use simple configuration)
00118     logger main_log(PION_GET_LOGGER("piond"));
00119     logger pion_log(PION_GET_LOGGER("pion"));
00120     if (verbose_flag) {
00121         PION_LOG_SETLEVEL_DEBUG(main_log);
00122         PION_LOG_SETLEVEL_DEBUG(pion_log);
00123     } else {
00124         PION_LOG_SETLEVEL_INFO(main_log);
00125         PION_LOG_SETLEVEL_INFO(pion_log);
00126     }
00127     PION_LOG_CONFIG_BASIC;
00128     
00129     try {
00130         // add the Pion plug-ins installation directory to our path
00131         try { plugin::add_plugin_directory(PION_PLUGINS_DIRECTORY); }
00132         catch (error::directory_not_found&) {
00133             PION_LOG_WARN(main_log, "Default plug-ins directory does not exist: "
00134                 << PION_PLUGINS_DIRECTORY);
00135         }
00136 
00137         // add the directory of the program we're running to our path
00138         try { plugin::add_plugin_directory(boost::filesystem::path(argv[0]).branch_path().string()); }
00139         catch (error::directory_not_found&) {
00140             PION_LOG_WARN(main_log, "Directory of current executable does not exist: "
00141                 << boost::filesystem::path(argv[0]).branch_path());
00142         }
00143 
00144         // create a server for HTTP & add the Hello Service
00145         http::plugin_server  web_server(cfg_endpoint);
00146 
00147         if (ssl_flag) {
00148 #ifdef PION_HAVE_SSL
00149             // configure server for SSL
00150             web_server.set_ssl_key_file(ssl_pem_file);
00151             PION_LOG_INFO(main_log, "SSL support enabled using key file: " << ssl_pem_file);
00152 #else
00153             PION_LOG_ERROR(main_log, "SSL support is not enabled");
00154 #endif
00155         }
00156         
00157         if (service_config_file.empty()) {
00158             // load a single web service using the command line arguments
00159             web_server.load_service(resource_name, service_name);
00160 
00161             // set web service options if any are defined
00162             for (ServiceOptionsType::iterator i = service_options.begin();
00163                  i != service_options.end(); ++i)
00164             {
00165                 web_server.set_service_option(resource_name, i->first, i->second);
00166             }
00167         } else {
00168             // load services using the configuration file
00169             web_server.load_service_config(service_config_file);
00170         }
00171 
00172         // startup the server
00173         web_server.start();
00174         process::wait_for_shutdown();
00175         
00176     } catch (std::exception& e) {
00177         PION_LOG_FATAL(main_log, pion::diagnostic_information(e));
00178     }
00179 
00180     return 0;
00181 }