pion  5.0.6
piond.cpp
1 // ---------------------------------------------------------------------
2 // pion: a Boost C++ framework for building lightweight HTTP interfaces
3 // ---------------------------------------------------------------------
4 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion)
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8 //
9 
10 #include <vector>
11 #include <iostream>
12 #include <boost/asio.hpp>
13 #include <pion/error.hpp>
14 #include <pion/plugin.hpp>
15 #include <pion/process.hpp>
16 #include <pion/http/plugin_server.hpp>
17 
18 // these are used only when linking to static web service libraries
19 // #ifdef PION_STATIC_LINKING
20 PION_DECLARE_PLUGIN(EchoService)
21 PION_DECLARE_PLUGIN(FileService)
22 PION_DECLARE_PLUGIN(HelloService)
23 PION_DECLARE_PLUGIN(LogService)
24 PION_DECLARE_PLUGIN(CookieService)
25 
26 using namespace std;
27 using namespace pion;
28 
29 
31 void argument_error(void)
32 {
33  std::cerr << "usage: piond [OPTIONS] RESOURCE WEBSERVICE" << std::endl
34  << " piond [OPTIONS] -c SERVICE_CONFIG_FILE" << std::endl
35  << "options: [-ssl PEM_FILE] [-i IP] [-p PORT] [-d PLUGINS_DIR] [-o OPTION=VALUE] [-v]" << std::endl;
36 }
37 
38 
40 int main (int argc, char *argv[])
41 {
42  static const unsigned int DEFAULT_PORT = 8080;
43 
44  // used to keep track of web service name=value options
45  typedef std::vector<std::pair<std::string, std::string> > ServiceOptionsType;
46  ServiceOptionsType service_options;
47 
48  // parse command line: determine port number, RESOURCE and WEBSERVICE
49  boost::asio::ip::tcp::endpoint cfg_endpoint(boost::asio::ip::tcp::v4(), DEFAULT_PORT);
50  std::string service_config_file;
51  std::string resource_name;
52  std::string service_name;
53  std::string ssl_pem_file;
54  bool ssl_flag = false;
55  bool verbose_flag = false;
56 
57  for (int argnum=1; argnum < argc; ++argnum) {
58  if (argv[argnum][0] == '-') {
59  if (argv[argnum][1] == 'p' && argv[argnum][2] == '\0' && argnum+1 < argc) {
60  // set port number
61  ++argnum;
62  cfg_endpoint.port(strtoul(argv[argnum], 0, 10));
63  if (cfg_endpoint.port() == 0) cfg_endpoint.port(DEFAULT_PORT);
64  } else if (argv[argnum][1] == 'i' && argv[argnum][2] == '\0' && argnum+1 < argc) {
65  // set ip address
66  cfg_endpoint.address(boost::asio::ip::address::from_string(argv[++argnum]));
67  } else if (argv[argnum][1] == 'c' && argv[argnum][2] == '\0' && argnum+1 < argc) {
68  service_config_file = argv[++argnum];
69  } else if (argv[argnum][1] == 'd' && argv[argnum][2] == '\0' && argnum+1 < argc) {
70  // add the service plug-ins directory to the search path
71  try { plugin::add_plugin_directory(argv[++argnum]); }
73  std::cerr << "piond: Web service plug-ins directory does not exist: "
74  << argv[argnum] << std::endl;
75  return 1;
76  }
77  } else if (argv[argnum][1] == 'o' && argv[argnum][2] == '\0' && argnum+1 < argc) {
78  std::string option_name(argv[++argnum]);
79  std::string::size_type pos = option_name.find('=');
80  if (pos == std::string::npos) {
81  argument_error();
82  return 1;
83  }
84  std::string option_value(option_name, pos + 1);
85  option_name.resize(pos);
86  service_options.push_back( std::make_pair(option_name, option_value) );
87  } else if (argv[argnum][1] == 's' && argv[argnum][2] == 's' &&
88  argv[argnum][3] == 'l' && argv[argnum][4] == '\0' && argnum+1 < argc) {
89  ssl_flag = true;
90  ssl_pem_file = argv[++argnum];
91  } else if (argv[argnum][1] == 'v' && argv[argnum][2] == '\0') {
92  verbose_flag = true;
93  } else {
94  argument_error();
95  return 1;
96  }
97  } else if (argnum+2 == argc) {
98  // second to last argument = RESOURCE
99  resource_name = argv[argnum];
100  } else if (argnum+1 == argc) {
101  // last argument = WEBSERVICE
102  service_name = argv[argnum];
103  } else {
104  argument_error();
105  return 1;
106  }
107  }
108 
109  if (service_config_file.empty() && (resource_name.empty() || service_name.empty())) {
110  argument_error();
111  return 1;
112  }
113 
114  // initialize signal handlers, etc.
115  process::initialize();
116 
117  // initialize log system (use simple configuration)
118  logger main_log(PION_GET_LOGGER("piond"));
119  logger pion_log(PION_GET_LOGGER("pion"));
120  if (verbose_flag) {
121  PION_LOG_SETLEVEL_DEBUG(main_log);
122  PION_LOG_SETLEVEL_DEBUG(pion_log);
123  } else {
124  PION_LOG_SETLEVEL_INFO(main_log);
125  PION_LOG_SETLEVEL_INFO(pion_log);
126  }
127  PION_LOG_CONFIG_BASIC;
128 
129  try {
130  // add the Pion plug-ins installation directory to our path
131  try { plugin::add_plugin_directory(PION_PLUGINS_DIRECTORY); }
132  catch (error::directory_not_found&) {
133  PION_LOG_WARN(main_log, "Default plug-ins directory does not exist: "
134  << PION_PLUGINS_DIRECTORY);
135  }
136 
137  // add the directory of the program we're running to our path
138  try { plugin::add_plugin_directory(boost::filesystem::path(argv[0]).branch_path().string()); }
139  catch (error::directory_not_found&) {
140  PION_LOG_WARN(main_log, "Directory of current executable does not exist: "
141  << boost::filesystem::path(argv[0]).branch_path());
142  }
143 
144  // create a server for HTTP & add the Hello Service
145  http::plugin_server web_server(cfg_endpoint);
146 
147  if (ssl_flag) {
148 #ifdef PION_HAVE_SSL
149  // configure server for SSL
150  web_server.set_ssl_key_file(ssl_pem_file);
151  PION_LOG_INFO(main_log, "SSL support enabled using key file: " << ssl_pem_file);
152 #else
153  PION_LOG_ERROR(main_log, "SSL support is not enabled");
154 #endif
155  }
156 
157  if (service_config_file.empty()) {
158  // load a single web service using the command line arguments
159  web_server.load_service(resource_name, service_name);
160 
161  // set web service options if any are defined
162  for (ServiceOptionsType::iterator i = service_options.begin();
163  i != service_options.end(); ++i)
164  {
165  web_server.set_service_option(resource_name, i->first, i->second);
166  }
167  } else {
168  // load services using the configuration file
169  web_server.load_service_config(service_config_file);
170  }
171 
172  // startup the server
173  web_server.start();
174  process::wait_for_shutdown();
175 
176  } catch (std::exception& e) {
177  PION_LOG_FATAL(main_log, pion::diagnostic_information(e));
178  }
179 
180  return 0;
181 }
STL namespace.
exception thrown if a required directory is not found
Definition: error.hpp:174