mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 04:02:15 +02:00
Completed client refactoring to make polymorphic abstraction
layer for transport and tun objects.
This commit is contained in:
parent
d7039586dd
commit
648298d17a
@ -2,6 +2,7 @@
|
||||
#define OPENVPN_COMMON_DISPATCH_H
|
||||
|
||||
#include <openvpn/common/types.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
// Dispatcher for asio async_read
|
||||
@ -15,12 +16,12 @@ namespace openvpn {
|
||||
|
||||
void operator()(const boost::system::error_code& error, const size_t bytes_recvd)
|
||||
{
|
||||
(obj_->*handle_read_)(data_, error, bytes_recvd);
|
||||
(obj_.get()->*handle_read_)(data_, error, bytes_recvd);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handle_read_;
|
||||
C* obj_;
|
||||
boost::intrusive_ptr<C> obj_;
|
||||
Data data_;
|
||||
};
|
||||
|
||||
@ -41,12 +42,12 @@ namespace openvpn {
|
||||
|
||||
void operator()(const boost::system::error_code& error)
|
||||
{
|
||||
(obj_->*handler_)(data_, error);
|
||||
(obj_.get()->*handler_)(data_, error);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
C* obj_;
|
||||
boost::intrusive_ptr<C> obj_;
|
||||
Data data_;
|
||||
};
|
||||
|
||||
@ -67,12 +68,12 @@ namespace openvpn {
|
||||
|
||||
void operator()(const boost::system::error_code& error)
|
||||
{
|
||||
(obj_->*handler_)(error);
|
||||
(obj_.get()->*handler_)(error);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
C* obj_;
|
||||
boost::intrusive_ptr<C> obj_;
|
||||
};
|
||||
|
||||
template <typename C, typename Handler>
|
||||
@ -92,14 +93,39 @@ namespace openvpn {
|
||||
|
||||
void operator()(const boost::system::error_code& error, EndpointIterator iter)
|
||||
{
|
||||
(obj_->*handler_)(error, iter);
|
||||
(obj_.get()->*handler_)(error, iter);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
C* obj_;
|
||||
boost::intrusive_ptr<C> obj_;
|
||||
};
|
||||
|
||||
// Dispatcher for asio signal
|
||||
|
||||
template <typename C, typename Handler>
|
||||
class AsioDispatchSignal
|
||||
{
|
||||
public:
|
||||
AsioDispatchSignal(Handler handler, C* obj)
|
||||
: handler_(handler), obj_(obj) {}
|
||||
|
||||
void operator()(const boost::system::error_code& error, int signal_number)
|
||||
{
|
||||
(obj_.get()->*handler_)(error, signal_number);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
boost::intrusive_ptr<C> obj_;
|
||||
};
|
||||
|
||||
template <typename C, typename Handler>
|
||||
AsioDispatchSignal<C, Handler> asio_dispatch_signal(Handler handler, C* obj)
|
||||
{
|
||||
return AsioDispatchSignal<C, Handler>(handler, obj);
|
||||
}
|
||||
|
||||
// General purpose dispatcher with data
|
||||
|
||||
template <typename C, typename Handler, typename Data>
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
@ -10,7 +11,6 @@
|
||||
#include <openvpn/common/thread.hpp>
|
||||
#include <openvpn/log/log.hpp>
|
||||
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
class ASIOThreadPool
|
||||
|
@ -24,6 +24,7 @@ namespace openvpn {
|
||||
// error stats
|
||||
NETWORK_ERROR, // errors on network socket
|
||||
RESOLVE_ERROR, // DNS resolution error
|
||||
BAD_SRC_ADDR, // packet from unknown source address
|
||||
TUN_ERROR, // errors on tun/tap interface
|
||||
HMAC_ERROR, // HMAC verification failure
|
||||
REPLAY_ERROR, // error from PacketIDReceive
|
||||
@ -82,6 +83,7 @@ namespace openvpn {
|
||||
"TUN_BYTES_OUT",
|
||||
"NETWORK_ERROR",
|
||||
"RESOLVE_ERROR",
|
||||
"BAD_SRC_ADDR",
|
||||
"TUN_ERROR",
|
||||
"HMAC_ERROR",
|
||||
"REPLAY_ERROR",
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/options.hpp>
|
||||
#include <openvpn/common/process.hpp>
|
||||
#include <openvpn/common/file.hpp>
|
||||
|
@ -1,10 +1,11 @@
|
||||
#ifndef OPENVPN_TRANSPORT_TRANSBASE_H
|
||||
#define OPENVPN_TRANSPORT_TRANSBASE_H
|
||||
#ifndef OPENVPN_TRANSPORT_CLIENT_TRANSBASE_H
|
||||
#define OPENVPN_TRANSPORT_CLIENT_TRANSBASE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
@ -25,7 +26,7 @@ namespace openvpn {
|
||||
{
|
||||
virtual void transport_recv(BufferAllocated& buf) = 0;
|
||||
virtual void transport_connected() {}
|
||||
virtual void transport_error(const std::string) {}
|
||||
virtual void transport_error(const std::exception&) {}
|
||||
};
|
||||
|
||||
struct TransportClientFactory : public RC<thread_unsafe_refcount>
|
||||
@ -38,4 +39,4 @@ namespace openvpn {
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_TRANSPORT_TRANSBASE_H
|
||||
#endif // OPENVPN_TRANSPORT_CLIENT_TRANSBASE_H
|
@ -1,16 +1,18 @@
|
||||
#ifndef OPENVPN_TRANSPORT_UDPCLI_H
|
||||
#define OPENVPN_TRANSPORT_UDPCLI_H
|
||||
#ifndef OPENVPN_TRANSPORT_CLIENT_UDPCLI_H
|
||||
#define OPENVPN_TRANSPORT_CLIENT_UDPCLI_H
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <openvpn/transport/udplink.hpp>
|
||||
#include <openvpn/transport/transbase.hpp>
|
||||
#include <openvpn/transport/client/transbase.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace UDPTransport {
|
||||
|
||||
OPENVPN_EXCEPTION(udp_transport_resolve_error);
|
||||
|
||||
class ClientConfig : public TransportClientFactory
|
||||
{
|
||||
public:
|
||||
@ -18,6 +20,7 @@ namespace openvpn {
|
||||
|
||||
std::string server_host;
|
||||
std::string server_port;
|
||||
bool server_addr_float;
|
||||
int n_parallel;
|
||||
Frame::Ptr frame;
|
||||
ProtoStats::Ptr stats;
|
||||
@ -30,7 +33,8 @@ namespace openvpn {
|
||||
virtual TransportClient::Ptr new_client_obj(boost::asio::io_service& io_service,
|
||||
TransportClientParent& parent);
|
||||
private:
|
||||
ClientConfig() {}
|
||||
ClientConfig()
|
||||
: server_addr_float(false), n_parallel(8) {}
|
||||
};
|
||||
|
||||
class Client : public TransportClient
|
||||
@ -88,7 +92,6 @@ namespace openvpn {
|
||||
: io_service(io_service_arg),
|
||||
config(config_arg),
|
||||
parent(parent_arg),
|
||||
impl(NULL),
|
||||
resolver(io_service_arg),
|
||||
halt(false)
|
||||
{
|
||||
@ -104,7 +107,10 @@ namespace openvpn {
|
||||
|
||||
void udp_read_handler(PacketFrom::SPtr& pfp) // called by LinkImpl
|
||||
{
|
||||
parent.transport_recv(pfp->buf);
|
||||
if (config->server_addr_float || pfp->sender_endpoint == server_endpoint)
|
||||
parent.transport_recv(pfp->buf);
|
||||
else
|
||||
config->stats->error(ProtoStats::BAD_SRC_ADDR);
|
||||
}
|
||||
|
||||
void stop_()
|
||||
@ -112,9 +118,9 @@ namespace openvpn {
|
||||
if (impl)
|
||||
{
|
||||
impl->stop();
|
||||
delete impl;
|
||||
impl = NULL;
|
||||
impl.reset();
|
||||
}
|
||||
resolver.cancel();
|
||||
halt = true;
|
||||
}
|
||||
|
||||
@ -128,13 +134,13 @@ namespace openvpn {
|
||||
// get resolved endpoint
|
||||
server_endpoint = *endpoint_iterator;
|
||||
|
||||
impl = new LinkImpl(io_service,
|
||||
this,
|
||||
server_endpoint,
|
||||
REMOTE_CONNECT,
|
||||
false,
|
||||
config->frame,
|
||||
config->stats);
|
||||
impl.reset(new LinkImpl(io_service,
|
||||
this,
|
||||
server_endpoint,
|
||||
REMOTE_CONNECT,
|
||||
false,
|
||||
config->frame,
|
||||
config->stats));
|
||||
impl->start(config->n_parallel);
|
||||
parent.transport_connected();
|
||||
}
|
||||
@ -144,7 +150,8 @@ namespace openvpn {
|
||||
os << "DNS resolve error on '" << config->server_host << "' for UDP session: " << error;
|
||||
config->stats->error(ProtoStats::RESOLVE_ERROR);
|
||||
stop();
|
||||
parent.transport_error(os.str());
|
||||
udp_transport_resolve_error err(os.str());
|
||||
parent.transport_error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,7 +159,7 @@ namespace openvpn {
|
||||
boost::asio::io_service& io_service;
|
||||
ClientConfig::Ptr config;
|
||||
TransportClientParent& parent;
|
||||
LinkImpl* impl;
|
||||
LinkImpl::Ptr impl;
|
||||
boost::asio::ip::udp::resolver resolver;
|
||||
UDPTransport::Endpoint server_endpoint;
|
||||
bool halt;
|
@ -1,12 +1,12 @@
|
||||
#ifndef OPENVPN_TRANSPORT_UDPLINK_H
|
||||
#define OPENVPN_TRANSPORT_UDPLINK_H
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <openvpn/common/types.hpp>
|
||||
#include <openvpn/common/scoped_ptr.hpp>
|
||||
#include <openvpn/common/dispatch.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/frame/frame.hpp>
|
||||
#include <openvpn/log/log.hpp>
|
||||
#include <openvpn/log/protostats.hpp>
|
||||
@ -41,9 +41,11 @@ namespace openvpn {
|
||||
};
|
||||
|
||||
template <typename ReadHandler>
|
||||
class Link : boost::noncopyable
|
||||
class Link : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef boost::intrusive_ptr<Link> Ptr;
|
||||
|
||||
Link(boost::asio::io_service& io_service,
|
||||
ReadHandler read_handler_arg,
|
||||
const Endpoint& endpoint,
|
||||
@ -73,39 +75,52 @@ namespace openvpn {
|
||||
|
||||
bool send(const Buffer& buf, Endpoint* endpoint)
|
||||
{
|
||||
try {
|
||||
const size_t wrote = endpoint
|
||||
? socket.send_to(buf.const_buffers_1(), *endpoint)
|
||||
: socket.send(buf.const_buffers_1());
|
||||
stats->inc_stat(ProtoStats::BYTES_OUT, wrote);
|
||||
if (wrote == buf.size())
|
||||
return true;
|
||||
else
|
||||
{
|
||||
OPENVPN_LOG_UDPLINK_ERROR("UDP partial send error");
|
||||
stats->error(ProtoStats::NETWORK_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (boost::system::system_error& e)
|
||||
if (!halt)
|
||||
{
|
||||
OPENVPN_LOG_UDPLINK_ERROR("UDP send error: " << e.what());
|
||||
stats->error(ProtoStats::NETWORK_ERROR);
|
||||
return false;
|
||||
try {
|
||||
const size_t wrote = endpoint
|
||||
? socket.send_to(buf.const_buffers_1(), *endpoint)
|
||||
: socket.send(buf.const_buffers_1());
|
||||
stats->inc_stat(ProtoStats::BYTES_OUT, wrote);
|
||||
if (wrote == buf.size())
|
||||
return true;
|
||||
else
|
||||
{
|
||||
OPENVPN_LOG_UDPLINK_ERROR("UDP partial send error");
|
||||
stats->error(ProtoStats::NETWORK_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (boost::system::system_error& e)
|
||||
{
|
||||
OPENVPN_LOG_UDPLINK_ERROR("UDP send error: " << e.what());
|
||||
stats->error(ProtoStats::NETWORK_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void start(const int n_parallel)
|
||||
{
|
||||
for (int i = 0; i < n_parallel; i++)
|
||||
queue_read(NULL);
|
||||
if (!halt)
|
||||
{
|
||||
for (int i = 0; i < n_parallel; i++)
|
||||
queue_read(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void stop() {
|
||||
halt = true;
|
||||
socket.close();
|
||||
if (!halt)
|
||||
{
|
||||
halt = true;
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
|
||||
~Link() { stop(); }
|
||||
|
||||
private:
|
||||
void queue_read(PacketFrom *udpfrom)
|
||||
{
|
||||
|
41
openvpn/tun/client/tunbase.hpp
Normal file
41
openvpn/tun/client/tunbase.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef OPENVPN_TUN_CLIENT_TUNBASE_H
|
||||
#define OPENVPN_TUN_CLIENT_TUNBASE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/common/options.hpp>
|
||||
#include <openvpn/transport/client/transbase.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
struct TunClient : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
typedef boost::intrusive_ptr<TunClient> Ptr;
|
||||
|
||||
virtual void client_start(const OptionList&, TransportClient&) = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual bool tun_send(BufferAllocated& buf) = 0;
|
||||
virtual std::string tun_name() const = 0;
|
||||
};
|
||||
|
||||
struct TunClientParent
|
||||
{
|
||||
virtual void tun_recv(BufferAllocated& buf) = 0;
|
||||
virtual void tun_connected() {}
|
||||
virtual void tun_error(const std::exception&) {}
|
||||
};
|
||||
|
||||
struct TunClientFactory : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
typedef boost::intrusive_ptr<TunClientFactory> Ptr;
|
||||
|
||||
virtual TunClient::Ptr new_client_obj(boost::asio::io_service& io_service,
|
||||
TunClientParent& parent) = 0;
|
||||
};
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_TUN_CLIENT_TUNBASE_H
|
157
openvpn/tun/linux/client/tuncli.hpp
Normal file
157
openvpn/tun/linux/client/tuncli.hpp
Normal file
@ -0,0 +1,157 @@
|
||||
#ifndef OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H
|
||||
#define OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H
|
||||
|
||||
#include <openvpn/tun/linux/tun.hpp>
|
||||
#include <openvpn/tun/client/tunbase.hpp>
|
||||
#include <openvpn/netconf/linux/route.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace TunLinux {
|
||||
|
||||
class ClientConfig : public TunClientFactory
|
||||
{
|
||||
public:
|
||||
typedef boost::intrusive_ptr<ClientConfig> Ptr;
|
||||
|
||||
std::string name;
|
||||
bool ipv6;
|
||||
bool tap;
|
||||
int txqueuelen;
|
||||
unsigned int mtu;
|
||||
|
||||
int n_parallel;
|
||||
Frame::Ptr frame;
|
||||
ProtoStats::Ptr stats;
|
||||
|
||||
static Ptr new_obj()
|
||||
{
|
||||
return new ClientConfig;
|
||||
}
|
||||
|
||||
virtual TunClient::Ptr new_client_obj(boost::asio::io_service& io_service,
|
||||
TunClientParent& parent);
|
||||
private:
|
||||
ClientConfig()
|
||||
: ipv6(false), tap(false), txqueuelen(200), mtu(1500), n_parallel(8) {}
|
||||
};
|
||||
|
||||
class Client : public TunClient
|
||||
{
|
||||
friend class ClientConfig; // calls constructor
|
||||
friend class Tun<Client*>; // calls tun_read_handler
|
||||
|
||||
typedef Tun<Client*> TunImpl;
|
||||
|
||||
public:
|
||||
virtual void client_start(const OptionList& opt, TransportClient& transcli)
|
||||
{
|
||||
if (!impl)
|
||||
{
|
||||
halt = false;
|
||||
try {
|
||||
// start tun
|
||||
impl.reset(new TunImpl(io_service,
|
||||
this,
|
||||
config->frame,
|
||||
config->stats,
|
||||
config->name,
|
||||
config->ipv6,
|
||||
config->tap,
|
||||
config->txqueuelen
|
||||
));
|
||||
impl->start(config->n_parallel);
|
||||
|
||||
// do ifconfig
|
||||
impl->ifconfig(opt, config->mtu);
|
||||
|
||||
// add routes
|
||||
route_list.reset(new RouteListLinux(opt, transcli.server_endpoint_addr()));
|
||||
|
||||
// signal that we are connected
|
||||
parent.tun_connected();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
config->stats->error(ProtoStats::TUN_ERROR);
|
||||
stop();
|
||||
parent.tun_error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool tun_send(BufferAllocated& buf)
|
||||
{
|
||||
return send(buf);
|
||||
}
|
||||
|
||||
virtual std::string tun_name() const
|
||||
{
|
||||
if (impl)
|
||||
return impl->name();
|
||||
else
|
||||
return "UNDEF_TUN";
|
||||
}
|
||||
|
||||
virtual void stop() { stop_(); }
|
||||
virtual ~Client() { stop_(); }
|
||||
|
||||
private:
|
||||
Client(boost::asio::io_service& io_service_arg,
|
||||
ClientConfig* config_arg,
|
||||
TunClientParent& parent_arg)
|
||||
: io_service(io_service_arg),
|
||||
config(config_arg),
|
||||
parent(parent_arg),
|
||||
halt(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool send(const Buffer& buf)
|
||||
{
|
||||
if (impl)
|
||||
return impl->write(buf);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void tun_read_handler(PacketFrom::SPtr& pfp) // called by TunImpl
|
||||
{
|
||||
parent.tun_recv(pfp->buf);
|
||||
}
|
||||
|
||||
void stop_()
|
||||
{
|
||||
// remove added routes
|
||||
if (route_list)
|
||||
{
|
||||
route_list->stop();
|
||||
route_list.reset();
|
||||
}
|
||||
|
||||
// stop tun
|
||||
if (impl)
|
||||
{
|
||||
impl->stop();
|
||||
impl.reset();
|
||||
}
|
||||
halt = true;
|
||||
}
|
||||
|
||||
boost::asio::io_service& io_service;
|
||||
ClientConfig::Ptr config;
|
||||
TunClientParent& parent;
|
||||
TunImpl::Ptr impl;
|
||||
RouteListLinux::Ptr route_list;
|
||||
bool halt;
|
||||
};
|
||||
|
||||
inline TunClient::Ptr ClientConfig::new_client_obj(boost::asio::io_service& io_service,
|
||||
TunClientParent& parent)
|
||||
{
|
||||
return TunClient::Ptr(new Client(io_service, this, parent));
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H
|
@ -1,5 +1,5 @@
|
||||
#ifndef OPENVPN_TUN_LINUX_TUNLINUX_H
|
||||
#define OPENVPN_TUN_LINUX_TUNLINUX_H
|
||||
#ifndef OPENVPN_TUN_LINUX_TUN_H
|
||||
#define OPENVPN_TUN_LINUX_TUN_H
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
@ -10,12 +10,11 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
#include <openvpn/common/types.hpp>
|
||||
#include <openvpn/common/rc.hpp> // fixme
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/common/scoped_ptr.hpp>
|
||||
#include <openvpn/common/scoped_fd.hpp>
|
||||
#include <openvpn/common/dispatch.hpp>
|
||||
@ -45,24 +44,24 @@ namespace openvpn {
|
||||
OPENVPN_EXCEPTION(tun_tx_queue_len_error);
|
||||
|
||||
template <typename ReadHandler>
|
||||
class Tun : public RC<thread_unsafe_refcount> // boost::noncopyable (fixme)
|
||||
class Tun : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef boost::intrusive_ptr<Tun> Ptr;
|
||||
|
||||
Tun(boost::asio::io_service& io_service,
|
||||
ReadHandler read_handler,
|
||||
const Frame::Ptr& frame,
|
||||
const ProtoStats::Ptr& stats,
|
||||
const char *name=NULL,
|
||||
const bool ipv6=false,
|
||||
const bool tap=false,
|
||||
const int txqueuelen=200)
|
||||
ReadHandler read_handler_arg,
|
||||
const Frame::Ptr& frame_arg,
|
||||
const ProtoStats::Ptr& stats_arg,
|
||||
const std::string name,
|
||||
const bool ipv6,
|
||||
const bool tap,
|
||||
const int txqueuelen)
|
||||
|
||||
: halt_(false),
|
||||
read_handler_(read_handler),
|
||||
frame_(frame),
|
||||
stats_(stats)
|
||||
: halt(false),
|
||||
read_handler(read_handler_arg),
|
||||
frame(frame_arg),
|
||||
stats(stats_arg)
|
||||
{
|
||||
static const char node[] = "/dev/net/tun";
|
||||
ScopedFD fd(open(node, O_RDWR));
|
||||
@ -78,10 +77,10 @@ namespace openvpn {
|
||||
ifr.ifr_flags |= IFF_TAP;
|
||||
else
|
||||
ifr.ifr_flags |= IFF_TUN;
|
||||
if (name)
|
||||
if (!name.empty())
|
||||
{
|
||||
if (::strlen(name) < IFNAMSIZ)
|
||||
::strcpy (ifr.ifr_name, name);
|
||||
if (name.length() < IFNAMSIZ)
|
||||
::strcpy (ifr.ifr_name, name.c_str());
|
||||
else
|
||||
throw tun_name_error();
|
||||
}
|
||||
@ -117,35 +116,48 @@ namespace openvpn {
|
||||
|
||||
bool write(const Buffer& buf)
|
||||
{
|
||||
try {
|
||||
const size_t wrote = sd->write_some(buf.const_buffers_1());
|
||||
stats_->inc_stat(ProtoStats::TUN_BYTES_OUT, wrote);
|
||||
if (wrote == buf.size())
|
||||
return true;
|
||||
else
|
||||
{
|
||||
OPENVPN_LOG_TUN_ERROR("TUN partial write error");
|
||||
stats_->error(ProtoStats::TUN_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (boost::system::system_error& e)
|
||||
if (!halt)
|
||||
{
|
||||
OPENVPN_LOG_TUN_ERROR("TUN write error: " << e.what());
|
||||
stats_->error(ProtoStats::TUN_ERROR);
|
||||
return false;
|
||||
try {
|
||||
const size_t wrote = sd->write_some(buf.const_buffers_1());
|
||||
stats->inc_stat(ProtoStats::TUN_BYTES_OUT, wrote);
|
||||
if (wrote == buf.size())
|
||||
return true;
|
||||
else
|
||||
{
|
||||
OPENVPN_LOG_TUN_ERROR("TUN partial write error");
|
||||
stats->error(ProtoStats::TUN_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (boost::system::system_error& e)
|
||||
{
|
||||
OPENVPN_LOG_TUN_ERROR("TUN write error: " << e.what());
|
||||
stats->error(ProtoStats::TUN_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void start(const int n_parallel)
|
||||
{
|
||||
for (int i = 0; i < n_parallel; i++)
|
||||
queue_read(NULL);
|
||||
if (!halt)
|
||||
{
|
||||
for (int i = 0; i < n_parallel; i++)
|
||||
queue_read(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void stop() {
|
||||
halt_ = true;
|
||||
sd->close();
|
||||
void stop()
|
||||
{
|
||||
if (!halt)
|
||||
{
|
||||
halt = true;
|
||||
sd->close();
|
||||
delete sd;
|
||||
}
|
||||
}
|
||||
|
||||
int ifconfig(const OptionList& opt, const unsigned int mtu)
|
||||
@ -172,9 +184,7 @@ namespace openvpn {
|
||||
}
|
||||
}
|
||||
|
||||
~Tun() {
|
||||
delete sd;
|
||||
}
|
||||
~Tun() { stop(); }
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
@ -187,7 +197,7 @@ namespace openvpn {
|
||||
OPENVPN_LOG_TUN_VERBOSE("TunLinux::queue_read");
|
||||
if (!tunfrom)
|
||||
tunfrom = new PacketFrom();
|
||||
frame_->prepare(Frame::READ_TUN, tunfrom->buf);
|
||||
frame->prepare(Frame::READ_TUN, tunfrom->buf);
|
||||
|
||||
sd->async_read_some(tunfrom->buf.mutable_buffers_1(),
|
||||
asio_dispatch_read(&Tun::handle_read, this, tunfrom));
|
||||
@ -197,18 +207,18 @@ namespace openvpn {
|
||||
{
|
||||
OPENVPN_LOG_TUN_VERBOSE("TunLinux::handle_read: " << error.message());
|
||||
typename PacketFrom::SPtr pfp(tunfrom);
|
||||
if (!halt_)
|
||||
if (!halt)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
pfp->buf.set_size(bytes_recvd);
|
||||
stats_->inc_stat(ProtoStats::TUN_BYTES_IN, bytes_recvd);
|
||||
read_handler_->tun_read_handler(pfp);
|
||||
stats->inc_stat(ProtoStats::TUN_BYTES_IN, bytes_recvd);
|
||||
read_handler->tun_read_handler(pfp);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPENVPN_LOG_TUN_ERROR("TUN Read Error: " << error);
|
||||
stats_->error(ProtoStats::TUN_ERROR);
|
||||
stats->error(ProtoStats::TUN_ERROR);
|
||||
}
|
||||
queue_read(pfp.release()); // reuse buffer if still available
|
||||
}
|
||||
@ -216,13 +226,13 @@ namespace openvpn {
|
||||
|
||||
std::string name_;
|
||||
boost::asio::posix::stream_descriptor *sd;
|
||||
bool halt_;
|
||||
ReadHandler read_handler_;
|
||||
const Frame::Ptr frame_;
|
||||
ProtoStats::Ptr stats_;
|
||||
bool halt;
|
||||
ReadHandler read_handler;
|
||||
const Frame::Ptr frame;
|
||||
ProtoStats::Ptr stats;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_TUN_LINUX_TUNLINUX_H
|
||||
#endif // OPENVPN_TUN_LINUX_TUN_H
|
@ -1,36 +0,0 @@
|
||||
#ifndef OPENVPN_TUN_TUNBASE_H
|
||||
#define OPENVPN_TUN_TUNBASE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/rc.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
struct TunBase : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
typedef boost::intrusive_ptr<TunBase> Ptr;
|
||||
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual bool tun_send(BufferAllocated& buf) = 0;
|
||||
};
|
||||
|
||||
struct TunParent
|
||||
{
|
||||
virtual void tun_recv(BufferAllocated& buf) = 0;
|
||||
virtual void tun_connected() {}
|
||||
virtual void tun_error(const std::string) {}
|
||||
};
|
||||
|
||||
struct TunFactory : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
typedef boost::intrusive_ptr<TunFactory> Ptr;
|
||||
|
||||
virtual TunBase::Ptr new_obj(boost::asio::io_service& io_service,
|
||||
TunParent& parent) = 0;
|
||||
};
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_TUN_TUNBASE_H
|
Loading…
Reference in New Issue
Block a user