File: piond.cpp

package info (click to toggle)
pion 5.0.7%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 3,048 kB
  • ctags: 3,122
  • sloc: cpp: 14,237; perl: 269; pascal: 152; makefile: 145; sh: 70
file content (181 lines) | stat: -rw-r--r-- 7,142 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// ---------------------------------------------------------------------
// pion:  a Boost C++ framework for building lightweight HTTP interfaces
// ---------------------------------------------------------------------
// Copyright (C) 2007-2014 Splunk Inc.  (https://github.com/splunk/pion)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#include <vector>
#include <iostream>
#include <boost/asio.hpp>
#include <pion/error.hpp>
#include <pion/plugin.hpp>
#include <pion/process.hpp>
#include <pion/http/plugin_server.hpp>

// these are used only when linking to static web service libraries
// #ifdef PION_STATIC_LINKING
PION_DECLARE_PLUGIN(EchoService)
PION_DECLARE_PLUGIN(FileService)
PION_DECLARE_PLUGIN(HelloService)
PION_DECLARE_PLUGIN(LogService)
PION_DECLARE_PLUGIN(CookieService)

using namespace std;
using namespace pion;


/// displays an error message if the arguments are invalid
void argument_error(void)
{
    std::cerr << "usage:   piond [OPTIONS] RESOURCE WEBSERVICE" << std::endl
              << "         piond [OPTIONS] -c SERVICE_CONFIG_FILE" << std::endl
              << "options: [-ssl PEM_FILE] [-i IP] [-p PORT] [-d PLUGINS_DIR] [-o OPTION=VALUE] [-v]" << std::endl;
}


/// main control function
int main (int argc, char *argv[])
{
    static const unsigned int DEFAULT_PORT = 8080;

    // used to keep track of web service name=value options
    typedef std::vector<std::pair<std::string, std::string> >   ServiceOptionsType;
    ServiceOptionsType service_options;
    
    // parse command line: determine port number, RESOURCE and WEBSERVICE
    boost::asio::ip::tcp::endpoint cfg_endpoint(boost::asio::ip::tcp::v4(), DEFAULT_PORT);
    std::string service_config_file;
    std::string resource_name;
    std::string service_name;
    std::string ssl_pem_file;
    bool ssl_flag = false;
    bool verbose_flag = false;
    
    for (int argnum=1; argnum < argc; ++argnum) {
        if (argv[argnum][0] == '-') {
            if (argv[argnum][1] == 'p' && argv[argnum][2] == '\0' && argnum+1 < argc) {
                // set port number
                ++argnum;
                cfg_endpoint.port(strtoul(argv[argnum], 0, 10));
                if (cfg_endpoint.port() == 0) cfg_endpoint.port(DEFAULT_PORT);
            } else if (argv[argnum][1] == 'i' && argv[argnum][2] == '\0' && argnum+1 < argc) {
                // set ip address
                cfg_endpoint.address(boost::asio::ip::address::from_string(argv[++argnum]));
            } else if (argv[argnum][1] == 'c' && argv[argnum][2] == '\0' && argnum+1 < argc) {
                service_config_file = argv[++argnum];
            } else if (argv[argnum][1] == 'd' && argv[argnum][2] == '\0' && argnum+1 < argc) {
                // add the service plug-ins directory to the search path
                try { plugin::add_plugin_directory(argv[++argnum]); }
                catch (error::directory_not_found&) {
                    std::cerr << "piond: Web service plug-ins directory does not exist: "
                        << argv[argnum] << std::endl;
                    return 1;
                }
            } else if (argv[argnum][1] == 'o' && argv[argnum][2] == '\0' && argnum+1 < argc) {
                std::string option_name(argv[++argnum]);
                std::string::size_type pos = option_name.find('=');
                if (pos == std::string::npos) {
                    argument_error();
                    return 1;
                }
                std::string option_value(option_name, pos + 1);
                option_name.resize(pos);
                service_options.push_back( std::make_pair(option_name, option_value) );
            } else if (argv[argnum][1] == 's' && argv[argnum][2] == 's' &&
                       argv[argnum][3] == 'l' && argv[argnum][4] == '\0' && argnum+1 < argc) {
                ssl_flag = true;
                ssl_pem_file = argv[++argnum];
            } else if (argv[argnum][1] == 'v' && argv[argnum][2] == '\0') {
                verbose_flag = true;
            } else {
                argument_error();
                return 1;
            }
        } else if (argnum+2 == argc) {
            // second to last argument = RESOURCE
            resource_name = argv[argnum];
        } else if (argnum+1 == argc) {
            // last argument = WEBSERVICE
            service_name = argv[argnum];
        } else {
            argument_error();
            return 1;
        }
    }
    
    if (service_config_file.empty() && (resource_name.empty() || service_name.empty())) {
        argument_error();
        return 1;
    }
    
    // initialize signal handlers, etc.
    process::initialize();
    
    // initialize log system (use simple configuration)
    logger main_log(PION_GET_LOGGER("piond"));
    logger pion_log(PION_GET_LOGGER("pion"));
    if (verbose_flag) {
        PION_LOG_SETLEVEL_DEBUG(main_log);
        PION_LOG_SETLEVEL_DEBUG(pion_log);
    } else {
        PION_LOG_SETLEVEL_INFO(main_log);
        PION_LOG_SETLEVEL_INFO(pion_log);
    }
    PION_LOG_CONFIG_BASIC;
    
    try {
        // add the Pion plug-ins installation directory to our path
        try { plugin::add_plugin_directory(PION_PLUGINS_DIRECTORY); }
        catch (error::directory_not_found&) {
            PION_LOG_WARN(main_log, "Default plug-ins directory does not exist: "
                << PION_PLUGINS_DIRECTORY);
        }

        // add the directory of the program we're running to our path
        try { plugin::add_plugin_directory(boost::filesystem::path(argv[0]).branch_path().string()); }
        catch (error::directory_not_found&) {
            PION_LOG_WARN(main_log, "Directory of current executable does not exist: "
                << boost::filesystem::path(argv[0]).branch_path());
        }

        // create a server for HTTP & add the Hello Service
        http::plugin_server  web_server(cfg_endpoint);

        if (ssl_flag) {
#ifdef PION_HAVE_SSL
            // configure server for SSL
            web_server.set_ssl_key_file(ssl_pem_file);
            PION_LOG_INFO(main_log, "SSL support enabled using key file: " << ssl_pem_file);
#else
            PION_LOG_ERROR(main_log, "SSL support is not enabled");
#endif
        }
        
        if (service_config_file.empty()) {
            // load a single web service using the command line arguments
            web_server.load_service(resource_name, service_name);

            // set web service options if any are defined
            for (ServiceOptionsType::iterator i = service_options.begin();
                 i != service_options.end(); ++i)
            {
                web_server.set_service_option(resource_name, i->first, i->second);
            }
        } else {
            // load services using the configuration file
            web_server.load_service_config(service_config_file);
        }

        // startup the server
        web_server.start();
        process::wait_for_shutdown();
        
    } catch (std::exception& e) {
        PION_LOG_FATAL(main_log, pion::diagnostic_information(e));
    }

    return 0;
}