0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 12:12:15 +02:00

Updated OMI to support server-side usage.

This commit is contained in:
James Yonan 2016-05-05 16:11:53 -06:00 committed by Lev Stipakov
parent 061daa8e3c
commit 4a45609b29
No known key found for this signature in database
GPG Key ID: 88670BE258B9C258

View File

@ -30,6 +30,7 @@
#include <utility>
#include <algorithm>
#include <openvpn/common/size.hpp>
#include <openvpn/common/platform.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/rc.hpp>
@ -60,6 +61,24 @@ namespace openvpn {
public:
OPENVPN_EXCEPTION(omi_error);
struct LogFn
{
LogFn(const OptionList& opt)
{
fn = opt.get_optional("log", 1, 256);
if (fn.empty())
{
fn = opt.get_optional("log-append", 1, 256);
append = true;
}
errors_to_stderr = opt.exists("errors-to-stderr");
}
std::string fn;
bool append = false;
bool errors_to_stderr = false;
};
void stop()
{
if (stop_called)
@ -204,39 +223,38 @@ namespace openvpn {
std::deque<std::string> hist;
};
OMICore(asio::io_context& io_context_arg,
OptionList opt_arg)
OMICore(asio::io_context& io_context_arg)
: io_context(io_context_arg),
opt(std::move(opt_arg)),
stop_timer(io_context_arg)
{
}
void open_log()
void log_setup(const LogFn& log)
{
// open log file
bool append = false;
std::string log_fn = opt.get_optional("log", 1, 256);
if (log_fn.empty())
if (!log.fn.empty())
{
log_fn = opt.get_optional("log-append", 1, 256);
append = true;
#if defined(OPENVPN_PLATFORM_WIN)
log_handle = Win::LogUtil::create_file(log.fn, "", log.append);
#else
RedirectStd redir("",
log.fn,
log.append ? RedirectStd::FLAGS_APPEND : RedirectStd::FLAGS_OVERWRITE,
RedirectStd::MODE_ALL,
false);
redir.redirect();
#endif
}
if (!log_fn.empty())
log_setup(log_fn, append);
// other log-related options
errors_to_stderr = opt.exists("errors-to-stderr");
errors_to_stderr = log.errors_to_stderr;
}
std::string get_config() const
static std::string get_config(const OptionList& opt)
{
// get config file
const std::string config_fn = opt.get("config", 1, 256);
return read_config(config_fn);
}
void start()
void start(const OptionList& opt)
{
const Option& o = opt.get("management");
const std::string addr = o.get(1, 256);
@ -244,6 +262,17 @@ namespace openvpn {
hold_flag = opt.exists("management-hold");
// management-queue-limit low_water high_water
{
const Option* o = opt.get_ptr("management-queue-limit");
if (o)
{
const size_t low_water = o->get_num<size_t>(1, 0, 0, 1000000);
const size_t high_water = o->get_num<size_t>(2, 0, 0, 1000000);
content_out_throttle.reset(new BufferThrottle(low_water, high_water));
}
}
// management-client-user root
{
const Option* o = opt.get_ptr("management-client-user");
@ -260,12 +289,12 @@ namespace openvpn {
{
if (port == "unix")
{
OPENVPN_LOG("Connecting to " << addr << " [unix]");
OPENVPN_LOG("OMI Connecting to " << addr << " [unix]");
connect_unix(addr);
}
else
{
OPENVPN_LOG("Connecting to [" << addr << "]:" << port << " [tcp]");
OPENVPN_LOG("OMI Connecting to [" << addr << "]:" << port << " [tcp]");
connect_tcp(addr, port);
}
}
@ -273,22 +302,30 @@ namespace openvpn {
{
if (port == "unix")
{
OPENVPN_LOG("Listening on " << addr << " [unix]");
OPENVPN_LOG("OMI Listening on " << addr << " [unix]");
listen_unix(addr);
}
else
{
OPENVPN_LOG("Listening on [" << addr << "]:" << port << " [tcp]");
OPENVPN_LOG("OMI Listening on [" << addr << "]:" << port << " [tcp]");
listen_tcp(addr, port);
}
}
}
void start_connection_if_not_hold()
{
if (!hold_flag)
omi_start_connection();
}
void send(BufferPtr buf)
{
if (!is_sock_open())
return;
content_out.push_back(std::move(buf));
if (content_out_throttle)
content_out_throttle->size_change(content_out.size());
if (content_out.size() == 1) // send operation not currently active?
queue_send();
}
@ -299,6 +336,14 @@ namespace openvpn {
send(buf_from_string(str));
}
bool send_ready() const
{
if (content_out_throttle)
return content_out_throttle->ready();
else
return true;
}
void log_full(const std::string& text) // logs to OMI buffer and log file
{
const time_t now = ::time(NULL);
@ -312,6 +357,12 @@ namespace openvpn {
std::cout << date_time(now) << ' ' << text << std::flush;
}
void log_timestamp(const time_t timestamp, const std::string& text) // logs to OMI buffer only
{
const std::string textcrlf = string::unix2dos(text, true);
log_line(openvpn::to_string(timestamp) + ",," + textcrlf);
}
void log_line(const std::string& line) // logs to OMI buffer only
{
if (!stop_called)
@ -350,15 +401,59 @@ namespace openvpn {
virtual void omi_start_connection() = 0;
virtual void omi_done(const bool eof) = 0;
virtual void omi_sigterm() = 0;
virtual void omi_sighup() = 0;
virtual bool omi_stop() = 0;
virtual bool omi_is_sighup_implemented()
{
return false;
}
virtual void omi_sighup()
{
}
asio::io_context& io_context;
const OptionList opt;
private:
typedef RCPtr<OMICore> Ptr;
class BufferThrottle
{
public:
BufferThrottle(const size_t low_water_arg,
const size_t high_water_arg)
: low_water(low_water_arg),
high_water(high_water_arg)
{
if (low_water > high_water)
throw Exception("bad management-queue-limit values");
}
void size_change(const size_t size)
{
if (ready_)
{
if (size > high_water)
ready_ = false;
}
else
{
if (size <= low_water)
ready_ = true;
}
}
bool ready() const
{
return ready_;
}
private:
const size_t low_water;
const size_t high_water;
volatile bool ready_ = true;
};
void command_in(std::unique_ptr<Command> cmd)
{
try {
@ -518,7 +613,7 @@ namespace openvpn {
send("SUCCESS: signal SIGTERM thrown\r\n");
omi_sigterm();
}
else if (type == "SIGHUP")
else if (type == "SIGHUP" && omi_is_sighup_implemented())
{
send("SUCCESS: signal SIGHUP thrown\r\n");
omi_sighup();
@ -565,6 +660,8 @@ namespace openvpn {
if (is_open)
socket->close();
content_out.clear();
if (content_out_throttle)
content_out_throttle->size_change(content_out.size());
in_partial.clear();
if (is_open)
omi_done(eof);
@ -618,20 +715,6 @@ namespace openvpn {
return read_text_utf8(fn);
}
void log_setup(const std::string& log_fn, const bool append)
{
#if defined(OPENVPN_PLATFORM_WIN)
log_handle = Win::LogUtil::create_file(log_fn, "", append);
#else
RedirectStd redir("",
log_fn,
append ? RedirectStd::FLAGS_APPEND : RedirectStd::FLAGS_OVERWRITE,
RedirectStd::MODE_ALL,
false);
redir.redirect();
#endif
}
void listen_tcp(const std::string& addr, const std::string& port)
{
// init TCP acceptor
@ -848,7 +931,11 @@ namespace openvpn {
BufferPtr buf = content_out.front();
if (bytes_sent == buf->size())
content_out.pop_front();
{
content_out.pop_front();
if (content_out_throttle)
content_out_throttle->size_change(content_out.size());
}
else if (bytes_sent < buf->size())
buf->advance(bytes_sent);
else
@ -875,7 +962,7 @@ namespace openvpn {
bool errors_to_stderr = false;
// stopping
bool stop_called = false;
volatile bool stop_called = false;
AsioTimer stop_timer;
// hold
@ -890,6 +977,9 @@ namespace openvpn {
History hist_state {"state", 100};
History hist_echo {"echo", 100};
// throttling
std::unique_ptr<BufferThrottle> content_out_throttle;
#if defined(OPENVPN_PLATFORM_WIN)
Win::ScopedHANDLE log_handle;
#endif