pion
5.0.6
|
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 }