pion-net
4.0.9
|
00001 // ------------------------------------------------------------------ 00002 // pion-net: a C++ framework for building lightweight HTTP interfaces 00003 // ------------------------------------------------------------------ 00004 // Copyright (C) 2007-2008 Atomic Labs, Inc. (http://www.atomiclabs.com) 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/PionPlugin.hpp> 00014 #include <pion/net/WebServer.hpp> 00015 #include "ShutdownManager.hpp" 00016 00017 // these are used only when linking to static web service libraries 00018 // #ifdef PION_STATIC_LINKING 00019 PION_DECLARE_PLUGIN(EchoService) 00020 PION_DECLARE_PLUGIN(FileService) 00021 PION_DECLARE_PLUGIN(HelloService) 00022 PION_DECLARE_PLUGIN(LogService) 00023 PION_DECLARE_PLUGIN(CookieService) 00024 00025 using namespace std; 00026 using namespace pion; 00027 using namespace pion::net; 00028 00029 00031 void argument_error(void) 00032 { 00033 std::cerr << "usage: PionWebServer [OPTIONS] RESOURCE WEBSERVICE" << std::endl 00034 << " PionWebServer [OPTIONS] -c SERVICE_CONFIG_FILE" << std::endl 00035 << "options: [-ssl PEM_FILE] [-i IP] [-p PORT] [-d PLUGINS_DIR] [-o OPTION=VALUE]" << 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 00056 for (int argnum=1; argnum < argc; ++argnum) { 00057 if (argv[argnum][0] == '-') { 00058 if (argv[argnum][1] == 'p' && argv[argnum][2] == '\0' && argnum+1 < argc) { 00059 // set port number 00060 ++argnum; 00061 cfg_endpoint.port(strtoul(argv[argnum], 0, 10)); 00062 if (cfg_endpoint.port() == 0) cfg_endpoint.port(DEFAULT_PORT); 00063 } else if (argv[argnum][1] == 'i' && argv[argnum][2] == '\0' && argnum+1 < argc) { 00064 // set ip address 00065 cfg_endpoint.address(boost::asio::ip::address::from_string(argv[++argnum])); 00066 } else if (argv[argnum][1] == 'c' && argv[argnum][2] == '\0' && argnum+1 < argc) { 00067 service_config_file = argv[++argnum]; 00068 } else if (argv[argnum][1] == 'd' && argv[argnum][2] == '\0' && argnum+1 < argc) { 00069 // add the service plug-ins directory to the search path 00070 try { PionPlugin::addPluginDirectory(argv[++argnum]); } 00071 catch (PionPlugin::DirectoryNotFoundException&) { 00072 std::cerr << "PionWebServer: Web service plug-ins directory does not exist: " 00073 << argv[argnum] << std::endl; 00074 return 1; 00075 } 00076 } else if (argv[argnum][1] == 'o' && argv[argnum][2] == '\0' && argnum+1 < argc) { 00077 std::string option_name(argv[++argnum]); 00078 std::string::size_type pos = option_name.find('='); 00079 if (pos == std::string::npos) { 00080 argument_error(); 00081 return 1; 00082 } 00083 std::string option_value(option_name, pos + 1); 00084 option_name.resize(pos); 00085 service_options.push_back( std::make_pair(option_name, option_value) ); 00086 } else if (argv[argnum][1] == 's' && argv[argnum][2] == 's' && 00087 argv[argnum][3] == 'l' && argv[argnum][4] == '\0' && argnum+1 < argc) { 00088 ssl_flag = true; 00089 ssl_pem_file = argv[++argnum]; 00090 } else { 00091 argument_error(); 00092 return 1; 00093 } 00094 } else if (argnum+2 == argc) { 00095 // second to last argument = RESOURCE 00096 resource_name = argv[argnum]; 00097 } else if (argnum+1 == argc) { 00098 // last argument = WEBSERVICE 00099 service_name = argv[argnum]; 00100 } else { 00101 argument_error(); 00102 return 1; 00103 } 00104 } 00105 00106 if (service_config_file.empty() && (resource_name.empty() || service_name.empty())) { 00107 argument_error(); 00108 return 1; 00109 } 00110 00111 // setup signal handler 00112 #ifdef PION_WIN32 00113 SetConsoleCtrlHandler(console_ctrl_handler, TRUE); 00114 #else 00115 signal(SIGINT, handle_signal); 00116 #endif 00117 00118 // initialize log system (use simple configuration) 00119 PionLogger main_log(PION_GET_LOGGER("PionWebServer")); 00120 PionLogger pion_log(PION_GET_LOGGER("pion")); 00121 PION_LOG_SETLEVEL_INFO(main_log); 00122 PION_LOG_SETLEVEL_INFO(pion_log); 00123 PION_LOG_CONFIG_BASIC; 00124 00125 try { 00126 // add the Pion plug-ins installation directory to our path 00127 try { PionPlugin::addPluginDirectory(PION_PLUGINS_DIRECTORY); } 00128 catch (PionPlugin::DirectoryNotFoundException&) { 00129 PION_LOG_WARN(main_log, "Default plug-ins directory does not exist: " 00130 << PION_PLUGINS_DIRECTORY); 00131 } 00132 00133 // add the directory of the program we're running to our path 00134 try { PionPlugin::addPluginDirectory(boost::filesystem::path(argv[0]).branch_path().string()); } 00135 catch (PionPlugin::DirectoryNotFoundException&) { 00136 PION_LOG_WARN(main_log, "Directory of current executable does not exist: " 00137 << boost::filesystem::path(argv[0]).branch_path()); 00138 } 00139 00140 // create a server for HTTP & add the Hello Service 00141 WebServer web_server(cfg_endpoint); 00142 00143 if (ssl_flag) { 00144 #ifdef PION_HAVE_SSL 00145 // configure server for SSL 00146 web_server.setSSLKeyFile(ssl_pem_file); 00147 PION_LOG_INFO(main_log, "SSL support enabled using key file: " << ssl_pem_file); 00148 #else 00149 PION_LOG_ERROR(main_log, "SSL support is not enabled"); 00150 #endif 00151 } 00152 00153 if (service_config_file.empty()) { 00154 // load a single web service using the command line arguments 00155 web_server.loadService(resource_name, service_name); 00156 00157 // set web service options if any are defined 00158 for (ServiceOptionsType::iterator i = service_options.begin(); 00159 i != service_options.end(); ++i) 00160 { 00161 web_server.setServiceOption(resource_name, i->first, i->second); 00162 } 00163 } else { 00164 // load services using the configuration file 00165 web_server.loadServiceConfig(service_config_file); 00166 } 00167 00168 // startup the server 00169 web_server.start(); 00170 main_shutdown_manager.wait(); 00171 00172 } catch (std::exception& e) { 00173 PION_LOG_FATAL(main_log, e.what()); 00174 } 00175 00176 return 0; 00177 }