Initial work
This commit is contained in:
commit
3222551702
374 changed files with 40290 additions and 0 deletions
71
src/CMakeLists.txt
Normal file
71
src/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
include_directories(
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${GLIB_INCLUDE_DIRS}
|
||||
${GIO_INCLUDE_DIRS}
|
||||
${GIO-UNIX_INCLUDE_DIRS}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/external/process-cpp-minimal/include
|
||||
${CMAKE_SOURCE_DIR}/external/android-emugl/host/include
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
anbox/logger.cpp
|
||||
anbox/utils.cpp
|
||||
anbox/cli.cpp
|
||||
anbox/runtime.cpp
|
||||
anbox/version.cpp
|
||||
anbox/daemon.cpp
|
||||
anbox/config.cpp
|
||||
anbox/pid_persister.cpp
|
||||
anbox/container.cpp
|
||||
anbox/container_connector.cpp
|
||||
|
||||
anbox/common/fd.cpp
|
||||
anbox/common/fd_sets.h
|
||||
anbox/common/variable_length_array.h
|
||||
|
||||
anbox/network/message_sender.h
|
||||
anbox/network/message_receiver.h
|
||||
anbox/network/message_processor.h
|
||||
anbox/network/connector.h
|
||||
anbox/network/connection_creator.h
|
||||
anbox/network/qemu_pipe_connection_creator.cpp
|
||||
anbox/network/published_socket_connector.cpp
|
||||
anbox/network/connections.h
|
||||
anbox/network/socket_connection.cpp
|
||||
anbox/network/socket_messenger.cpp
|
||||
anbox/network/delegate_message_processor.h
|
||||
|
||||
anbox/graphics/opengles_message_processor.cpp
|
||||
anbox/graphics/gl_renderer_server.cpp
|
||||
|
||||
anbox/support/null_message_processor.cpp
|
||||
anbox/support/boot_properties_message_processor.cpp
|
||||
anbox/support/hwcontrol_message_processor.cpp
|
||||
|
||||
anbox/cmds/version.cpp
|
||||
anbox/cmds/run.cpp
|
||||
anbox/cmds/shell.cpp
|
||||
|
||||
anbox/do_not_copy_or_move.h
|
||||
anbox/optional.h
|
||||
anbox/defer_action.h)
|
||||
|
||||
add_library(anbox-core ${SOURCES})
|
||||
target_link_libraries(anbox-core
|
||||
${Boost_LDFLAGS}
|
||||
${Boost_LIBRARIES}
|
||||
pthread
|
||||
process-cpp
|
||||
bwrap
|
||||
OpenglRender)
|
||||
|
||||
add_executable(anbox main.cpp)
|
||||
target_link_libraries(anbox
|
||||
anbox-core)
|
||||
|
||||
install(
|
||||
TARGETS anbox
|
||||
RUNTIME DESTINATION sbin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib/static)
|
||||
275
src/anbox/cli.cpp
Normal file
275
src/anbox/cli.cpp
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "anbox/cli.h"
|
||||
|
||||
namespace cli = anbox::cli;
|
||||
namespace po = boost::program_options;
|
||||
|
||||
namespace {
|
||||
namespace pattern {
|
||||
static constexpr const char* help_for_command_with_subcommands =
|
||||
"NAME:\n"
|
||||
" %1% - %2%\n"
|
||||
"\n"
|
||||
"USAGE:\n"
|
||||
" %3% [command options] [arguments...]";
|
||||
|
||||
static constexpr const char* commands = "COMMANDS:";
|
||||
static constexpr const char* command = " %1% %2%";
|
||||
|
||||
static constexpr const char* options = "OPTIONS:";
|
||||
static constexpr const char* option = " --%1% %2%";
|
||||
}
|
||||
|
||||
void add_to_desc_for_flags(po::options_description& desc, const std::set<cli::Flag::Ptr>& flags)
|
||||
{
|
||||
for (auto flag : flags)
|
||||
{
|
||||
auto v = po::value<std::string>()->notifier([flag](const std::string& s)
|
||||
{
|
||||
flag->notify(s);
|
||||
});
|
||||
desc.add_options()(flag->name().as_string().c_str(), v, flag->description().as_string().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> cli::args(int argc, char **argv)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
for (int i = 1; i < argc; i++) result.push_back(argv[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
const cli::Name& cli::Flag::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
const cli::Description& cli::Flag::description() const
|
||||
{
|
||||
return description_;
|
||||
}
|
||||
|
||||
cli::Flag::Flag(const Name& name, const Description& description)
|
||||
: name_{name},
|
||||
description_{description}
|
||||
{
|
||||
}
|
||||
|
||||
cli::Command::FlagsWithInvalidValue::FlagsWithInvalidValue() : std::runtime_error{"Flags with invalid value"}
|
||||
{
|
||||
}
|
||||
|
||||
cli::Command::FlagsMissing::FlagsMissing() : std::runtime_error{"Flags are missing in command invocation"}
|
||||
{
|
||||
}
|
||||
|
||||
cli::Name cli::Command::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
cli::Usage cli::Command::usage() const
|
||||
{
|
||||
return usage_;
|
||||
}
|
||||
|
||||
cli::Description cli::Command::description() const
|
||||
{
|
||||
return description_;
|
||||
}
|
||||
|
||||
cli::Command::Command(const cli::Name& name, const cli::Usage& usage, const cli::Description& description)
|
||||
: name_(name),
|
||||
usage_(usage),
|
||||
description_(description)
|
||||
{
|
||||
}
|
||||
|
||||
cli::CommandWithSubcommands::CommandWithSubcommands(const Name& name, const Usage& usage, const Description& description)
|
||||
: Command{name, usage, description}
|
||||
{
|
||||
command(std::make_shared<cmd::Help>(*this));
|
||||
}
|
||||
|
||||
cli::CommandWithSubcommands& cli::CommandWithSubcommands::command(const Command::Ptr& command)
|
||||
{
|
||||
commands_[command->name().as_string()] = command;
|
||||
return *this;
|
||||
}
|
||||
|
||||
cli::CommandWithSubcommands& cli::CommandWithSubcommands::flag(const Flag::Ptr& flag)
|
||||
{
|
||||
flags_.insert(flag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void cli::CommandWithSubcommands::help(std::ostream& out)
|
||||
{
|
||||
out << boost::format(pattern::help_for_command_with_subcommands)
|
||||
% name().as_string() % usage().as_string()
|
||||
% name().as_string() << std::endl;
|
||||
|
||||
if (flags_.size() > 0)
|
||||
{
|
||||
out << std::endl << pattern::options << std::endl;
|
||||
for (const auto& flag : flags_)
|
||||
out << boost::format(pattern::option) % flag->name() % flag->description() << std::endl;
|
||||
}
|
||||
|
||||
if (commands_.size() > 0)
|
||||
{
|
||||
out << std::endl << pattern::commands << std::endl;
|
||||
for (const auto& cmd : commands_)
|
||||
out << boost::format(pattern::command) % cmd.second->name() % cmd.second->description() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int cli::CommandWithSubcommands::run(const cli::Command::Context& ctxt)
|
||||
{
|
||||
po::positional_options_description pdesc;
|
||||
pdesc.add("command", 1);
|
||||
|
||||
po::options_description desc("Options");
|
||||
desc.add_options()("command", po::value<std::string>()->required(), "the command to be executed");
|
||||
|
||||
add_to_desc_for_flags(desc, flags_);
|
||||
|
||||
try
|
||||
{
|
||||
po::variables_map vm;
|
||||
auto parsed = po::command_line_parser(ctxt.args)
|
||||
.options(desc)
|
||||
.positional(pdesc)
|
||||
.style(po::command_line_style::unix_style)
|
||||
.allow_unregistered()
|
||||
.run();
|
||||
|
||||
po::store(parsed, vm);
|
||||
po::notify(vm);
|
||||
|
||||
return commands_[vm["command"].as<std::string>()]->run(cli::Command::Context
|
||||
{
|
||||
ctxt.cin,
|
||||
ctxt.cout,
|
||||
po::collect_unrecognized(parsed.options, po::include_positional)
|
||||
});
|
||||
}
|
||||
catch (const po::error& e)
|
||||
{
|
||||
ctxt.cout << e.what() << std::endl;
|
||||
help(ctxt.cout);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
cli::CommandWithFlagsAndAction::CommandWithFlagsAndAction(const Name& name, const Usage& usage, const Description& description)
|
||||
: Command{name, usage, description}
|
||||
{
|
||||
}
|
||||
|
||||
cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::flag(const Flag::Ptr& flag)
|
||||
{
|
||||
flags_.insert(flag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::action(const Action& action)
|
||||
{
|
||||
action_ = action;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int cli::CommandWithFlagsAndAction::run(const Context& ctxt)
|
||||
{
|
||||
po::options_description cd(name().as_string());
|
||||
|
||||
bool help_requested{false};
|
||||
cd.add_options()("help", po::bool_switch(&help_requested), "produces a help message");
|
||||
|
||||
add_to_desc_for_flags(cd, flags_);
|
||||
|
||||
try
|
||||
{
|
||||
po::variables_map vm;
|
||||
auto parsed = po::command_line_parser(ctxt.args).options(cd).style(po::command_line_style::unix_style).allow_unregistered().run();
|
||||
po::store(parsed, vm);
|
||||
po::notify(vm);
|
||||
|
||||
if (help_requested)
|
||||
{
|
||||
help(ctxt.cout);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return action_(cli::Command::Context
|
||||
{
|
||||
ctxt.cin,
|
||||
ctxt.cout,
|
||||
po::collect_unrecognized(parsed.options, po::exclude_positional)
|
||||
});
|
||||
}
|
||||
catch (const po::error& e)
|
||||
{
|
||||
ctxt.cout << e.what() << std::endl;
|
||||
help(ctxt.cout);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void cli::CommandWithFlagsAndAction::help(std::ostream& out)
|
||||
{
|
||||
out << boost::format(pattern::help_for_command_with_subcommands)
|
||||
% name().as_string() % description().as_string()
|
||||
% name().as_string() << std::endl;
|
||||
|
||||
if (flags_.size() > 0)
|
||||
{
|
||||
out << std::endl << boost::format(pattern::options) << std::endl;
|
||||
for (const auto& flag : flags_)
|
||||
out << boost::format(pattern::option) % flag->name() % flag->description() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
cli::cmd::Help::Help(Command& cmd)
|
||||
: Command{cli::Name{"help"}, cli::Usage{"prints a short help message"}, cli::Description{"prints a short help message"}},
|
||||
command{cmd}
|
||||
{
|
||||
}
|
||||
|
||||
// From Command
|
||||
int cli::cmd::Help::run(const Context &context)
|
||||
{
|
||||
command.help(context.cout);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void cli::cmd::Help::help(std::ostream &out)
|
||||
{
|
||||
command.help(out);
|
||||
}
|
||||
356
src/anbox/cli.h
Normal file
356
src/anbox/cli.h
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
#ifndef BIOMETRY_UTIL_CLI_H_
|
||||
#define BIOMETRY_UTIL_CLI_H_
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
#include "anbox/optional.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace cli {
|
||||
|
||||
template<std::size_t max>
|
||||
class SizeConstrainedString
|
||||
{
|
||||
public:
|
||||
SizeConstrainedString(const std::string& s) : s{s}
|
||||
{
|
||||
if(s.size() > max)
|
||||
throw std::logic_error{"Max size exceeded " + std::to_string(max)};
|
||||
}
|
||||
|
||||
const std::string& as_string() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string s;
|
||||
};
|
||||
|
||||
template<std::size_t max>
|
||||
bool operator<(const SizeConstrainedString<max>& lhs, const SizeConstrainedString<max>& rhs)
|
||||
{
|
||||
return lhs.as_string() < rhs.as_string();
|
||||
}
|
||||
|
||||
template<std::size_t max>
|
||||
bool operator==(const SizeConstrainedString<max>& lhs, const SizeConstrainedString<max>& rhs)
|
||||
{
|
||||
return lhs.as_string() == rhs.as_string();
|
||||
}
|
||||
|
||||
template<std::size_t max>
|
||||
std::ostream& operator<<(std::ostream& out, const SizeConstrainedString<max>& scs)
|
||||
{
|
||||
return out << std::setw(max) << std::left << scs.as_string();
|
||||
}
|
||||
|
||||
// We are imposing size constraints to ensure a consistent CLI layout.
|
||||
typedef SizeConstrainedString<20> Name;
|
||||
typedef SizeConstrainedString<60> Usage;
|
||||
typedef SizeConstrainedString<60> Description;
|
||||
|
||||
/// @brief Flag models an input parameter to a command.
|
||||
class Flag : public DoNotCopyOrMove
|
||||
{
|
||||
public:
|
||||
// Safe us some typing.
|
||||
typedef std::shared_ptr<Flag> Ptr;
|
||||
|
||||
/// @brief notify announces a new value to the flag.
|
||||
virtual void notify(const std::string& value) = 0;
|
||||
/// @brief name returns the name of the Flag.
|
||||
const Name& name() const;
|
||||
/// @brief description returns a human-readable description of the flag.
|
||||
const Description& description() const;
|
||||
|
||||
protected:
|
||||
/// @brief Flag creates a new instance, initializing name and description
|
||||
/// from the given values.
|
||||
Flag(const Name& name, const Description& description);
|
||||
|
||||
private:
|
||||
Name name_;
|
||||
Description description_;
|
||||
};
|
||||
|
||||
/// @brief TypedFlag implements Flag relying on operator<< and operator>> to read/write values to/from strings.
|
||||
template<typename T>
|
||||
class TypedFlag : public Flag
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr<TypedFlag<T>> Ptr;
|
||||
|
||||
TypedFlag(const Name& name, const Description& description) : Flag{name, description}
|
||||
{
|
||||
}
|
||||
|
||||
/// @brief value installs the given value in the flag.
|
||||
TypedFlag& value(const T& value)
|
||||
{
|
||||
value_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief value returns the optional value associated with the flag.
|
||||
const Optional<T>& value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
/// @brief notify tries to unwrap a value of type T from value.
|
||||
void notify(const std::string& s) override
|
||||
{
|
||||
std::stringstream ss{s};
|
||||
T value; ss >> value;
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
Optional<T> value_;
|
||||
};
|
||||
|
||||
/// @brief TypedReferenceFlag implements Flag, relying on operator<</>> to convert to/from string representations,
|
||||
/// updating the given mutable reference to a value of type T.
|
||||
template<typename T>
|
||||
class TypedReferenceFlag : public Flag
|
||||
{
|
||||
public:
|
||||
// Safe us some typing.
|
||||
typedef std::shared_ptr<TypedReferenceFlag<T>> Ptr;
|
||||
|
||||
/// @brief TypedReferenceFlag initializes a new instance with name, description and value.
|
||||
TypedReferenceFlag(const Name& name, const Description& description, T& value)
|
||||
: Flag{name, description},
|
||||
value_{value}
|
||||
{
|
||||
}
|
||||
|
||||
/// @brief notify tries to unwrap a value of type T from value,
|
||||
/// relying on operator>> to read from given string s.
|
||||
void notify(const std::string& s) override
|
||||
{
|
||||
std::stringstream ss{s};
|
||||
ss >> value_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::reference_wrapper<T> value_;
|
||||
};
|
||||
|
||||
/// @brief OptionalTypedReferenceFlag handles Optional<T> references, making sure that
|
||||
/// a value is always read on notify, even if the Optional<T> wasn't initialized previously.
|
||||
template<typename T>
|
||||
class OptionalTypedReferenceFlag : public Flag
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr<OptionalTypedReferenceFlag<T>> Ptr;
|
||||
|
||||
OptionalTypedReferenceFlag(const Name& name, const Description& description, Optional<T>& value)
|
||||
: Flag{name, description},
|
||||
value_{value}
|
||||
{
|
||||
}
|
||||
|
||||
/// @brief notify tries to unwrap a value of type T from value.
|
||||
void notify(const std::string& s) override
|
||||
{
|
||||
std::stringstream ss{s}; T value; ss >> value;
|
||||
value_.get() = value;
|
||||
}
|
||||
|
||||
private:
|
||||
std::reference_wrapper<Optional<T>> value_;
|
||||
};
|
||||
|
||||
/// @brief Command abstracts an individual command available from the daemon.
|
||||
class Command : public DoNotCopyOrMove
|
||||
{
|
||||
public:
|
||||
// Safe us some typing
|
||||
typedef std::shared_ptr<Command> Ptr;
|
||||
|
||||
/// @brief FlagsMissing is thrown if at least one required flag is missing.
|
||||
struct FlagsMissing : public std::runtime_error
|
||||
{
|
||||
/// @brief FlagsMissing initializes a new instance.
|
||||
FlagsMissing();
|
||||
};
|
||||
|
||||
/// @brief FlagsWithWrongValue is thrown if a value passed on the command line is invalid.
|
||||
struct FlagsWithInvalidValue : public std::runtime_error
|
||||
{
|
||||
/// @brief FlagsWithInvalidValue initializes a new instance.
|
||||
FlagsWithInvalidValue();
|
||||
};
|
||||
|
||||
/// @brief Context bundles information passed to Command::run invocations.
|
||||
struct Context
|
||||
{
|
||||
std::istream& cin; ///< The std::istream that should be used for reading.
|
||||
std::ostream& cout; ///< The std::ostream that should be used for writing.
|
||||
std::vector<std::string> args; ///< The command line args.
|
||||
};
|
||||
|
||||
/// @brief name returns the Name of the command.
|
||||
virtual Name name() const;
|
||||
|
||||
/// @brief usage returns a short usage string for the command.
|
||||
virtual Usage usage() const;
|
||||
|
||||
/// @brief description returns a longer string explaining the command.
|
||||
virtual Description description() const;
|
||||
|
||||
/// @brief run puts the command to execution.
|
||||
virtual int run(const Context& context) = 0;
|
||||
|
||||
/// @brief help prints information about a command to out.
|
||||
virtual void help(std::ostream& out) = 0;
|
||||
|
||||
protected:
|
||||
/// @brief Command initializes a new instance with the given name, usage and description.
|
||||
Command(const Name& name, const Usage& usage, const Description& description);
|
||||
|
||||
/// @brief name adjusts the name of the command to n.
|
||||
// virtual void name(const Name& n);
|
||||
/// @brief usage adjusts the usage string of the comand to u.
|
||||
// virtual void usage(const Usage& u);
|
||||
/// @brief description adjusts the description string of the command to d.
|
||||
// virtual void description(const Description& d);
|
||||
|
||||
private:
|
||||
Name name_;
|
||||
Usage usage_;
|
||||
Description description_;
|
||||
};
|
||||
|
||||
/// @brief CommandWithSubcommands implements Command, selecting one of a set of actions.
|
||||
class CommandWithSubcommands : public Command
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr<CommandWithSubcommands> Ptr;
|
||||
typedef std::function<int(const Context&)> Action;
|
||||
|
||||
/// @brief CommandWithSubcommands initializes a new instance with the given name, usage and description
|
||||
CommandWithSubcommands(const Name& name, const Usage& usage, const Description& description);
|
||||
|
||||
/// @brief command adds the given command to the set of known commands.
|
||||
CommandWithSubcommands& command(const Command::Ptr& command);
|
||||
|
||||
/// @brief flag adds the given flag to the set of known flags.
|
||||
CommandWithSubcommands& flag(const Flag::Ptr& flag);
|
||||
|
||||
// From Command
|
||||
int run(const Context& context) override;
|
||||
void help(std::ostream &out) override;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, Command::Ptr> commands_;
|
||||
std::set<Flag::Ptr> flags_;
|
||||
};
|
||||
|
||||
/// @brief CommandWithFlagsAction implements Command, executing an Action after handling
|
||||
class CommandWithFlagsAndAction : public Command
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr<CommandWithFlagsAndAction> Ptr;
|
||||
typedef std::function<int(const Context&)> Action;
|
||||
|
||||
/// @brief CommandWithFlagsAndAction initializes a new instance with the given name, usage and description
|
||||
CommandWithFlagsAndAction(const Name& name, const Usage& usage, const Description& description);
|
||||
|
||||
/// @brief flag adds the given flag to the set of known flags.
|
||||
CommandWithFlagsAndAction& flag(const Flag::Ptr& flag);
|
||||
|
||||
/// @brief action installs the given action.
|
||||
CommandWithFlagsAndAction& action(const Action& action);
|
||||
|
||||
// From Command
|
||||
int run(const Context& context) override;
|
||||
void help(std::ostream &out) override;
|
||||
|
||||
private:
|
||||
std::set<Flag::Ptr> flags_;
|
||||
Action action_;
|
||||
};
|
||||
|
||||
namespace cmd
|
||||
{
|
||||
/// @brief HelpFor prints a help message for the given command on execution.
|
||||
class Help : public Command
|
||||
{
|
||||
public:
|
||||
/// @brief HelpFor initializes a new instance with the given reference to a cmd.
|
||||
explicit Help(Command& cmd);
|
||||
|
||||
// From Command
|
||||
int run(const Context &context) override;
|
||||
void help(std::ostream &out) override;
|
||||
|
||||
private:
|
||||
/// @cond
|
||||
Command& command;
|
||||
/// @endcond
|
||||
};
|
||||
}
|
||||
|
||||
/// @brief args returns a vector of strings assembled from argc and argv.
|
||||
std::vector<std::string> args(int argc, char** argv);
|
||||
|
||||
/// @brief make_flag returns a flag with the given name and description.
|
||||
template<typename T>
|
||||
typename TypedFlag<T>::Ptr make_flag(const Name& name, const Description& description)
|
||||
{
|
||||
return std::make_shared<TypedFlag<T>>(name, description);
|
||||
}
|
||||
|
||||
/// @brief make_flag returns a flag with the given name and description, notifying updates to value.
|
||||
template<typename T>
|
||||
typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, T& value)
|
||||
{
|
||||
return std::make_shared<TypedReferenceFlag<T>>(name, desc, value);
|
||||
}
|
||||
|
||||
/// @brief make_flag returns a flag with the given name and description, updating the given optional value.
|
||||
template<typename T>
|
||||
typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, Optional<T>& value)
|
||||
{
|
||||
return std::make_shared<OptionalTypedReferenceFlag<T>>(name, desc, value);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
} // namespace anbox
|
||||
|
||||
|
||||
#endif
|
||||
111
src/anbox/cmds/run.cpp
Normal file
111
src/anbox/cmds/run.cpp
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "core/posix/signal.h"
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/container.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/pid_persister.h"
|
||||
#include "anbox/cmds/run.h"
|
||||
#include "anbox/network/published_socket_connector.h"
|
||||
#include "anbox/network/qemu_pipe_connection_creator.h"
|
||||
#include "anbox/graphics/gl_renderer_server.h"
|
||||
|
||||
#include <sys/prctl.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace {
|
||||
class NullConnectionCreator : public anbox::network::ConnectionCreator {
|
||||
public:
|
||||
void create_connection_for(
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) override {
|
||||
WARNING("Not implemented");
|
||||
socket->close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
anbox::cmds::Run::Run()
|
||||
: CommandWithFlagsAndAction{cli::Name{"run"}, cli::Usage{"run"}, cli::Description{"Run the the anbox system"}}
|
||||
{
|
||||
flag(cli::make_flag(cli::Name{"rootfs"}, cli::Description{"Path to Android rootfs"}, rootfs_));
|
||||
// Just for the purpose to allow QtMir (or unity8) to find this on our /proc/*/cmdline
|
||||
// for proper confinement etc.
|
||||
flag(cli::make_flag(cli::Name{"desktop_file_hint"}, cli::Description{"Desktop file hint for QtMir/Unity8"}, desktop_file_hint_));
|
||||
action([this](const cli::Command::Context &ctx) {
|
||||
if (rootfs_.empty() || !fs::is_directory(fs::path(rootfs_))) {
|
||||
ctx.cout << "Not valid rootfs path provided" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
auto trap = core::posix::trap_signals_for_process({core::posix::Signal::sig_term,
|
||||
core::posix::Signal::sig_int});
|
||||
trap->signal_raised().connect([trap](const core::posix::Signal &signal) {
|
||||
INFO("Signal %i received. Good night.", static_cast<int>(signal));
|
||||
trap->stop();
|
||||
});
|
||||
|
||||
auto rt = Runtime::create();
|
||||
|
||||
auto renderer = std::make_shared<graphics::GLRendererServer>();
|
||||
renderer->start();
|
||||
|
||||
// Socket which will be used by the qemud service inside the Android
|
||||
// container for things like sensors, vibrtator etc.
|
||||
auto qemud_connector = std::make_shared<network::PublishedSocketConnector>(
|
||||
utils::string_format("%s/qemud", config::data_path()),
|
||||
rt,
|
||||
std::make_shared<NullConnectionCreator>());
|
||||
|
||||
// The qemu pipe is used as a very fast communication channel between guest
|
||||
// and host for things like the GLES emulation/translation, the RIL or ADB.
|
||||
auto qemu_pipe_connector = std::make_shared<network::PublishedSocketConnector>(
|
||||
utils::string_format("%s/qemu_pipe", config::data_path()),
|
||||
rt,
|
||||
std::make_shared<network::QemuPipeConnectionCreator>(rt, renderer->socket_path()));
|
||||
|
||||
auto spec = Container::Spec::Default();
|
||||
spec.rootfs_path = rootfs_;
|
||||
spec.bind_paths.insert({qemud_connector->socket_file(), "/dev/qemud"});
|
||||
spec.bind_paths.insert({qemu_pipe_connector->socket_file(), "/dev/qemu_pipe"});
|
||||
spec.temporary_dirs.push_back("/data");
|
||||
// We isolate the container from accessing binder nodes of the host
|
||||
// through the IPC namespace which gets support for binder with extra
|
||||
// patches we require.
|
||||
spec.dev_bind_paths.push_back("/dev/binder");
|
||||
// Required for shared memory allocations. TODO(morphis): Letting the guest
|
||||
// access should be ok but needs more investigation.
|
||||
spec.dev_bind_paths.push_back("/dev/ashmem");
|
||||
|
||||
auto container = Container::create(spec);
|
||||
|
||||
rt->start();
|
||||
container->start();
|
||||
|
||||
trap->run();
|
||||
|
||||
container->stop();
|
||||
rt->stop();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
});
|
||||
}
|
||||
40
src/anbox/cmds/run.h
Normal file
40
src/anbox/cmds/run.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_CMDS_RUN_H_
|
||||
#define ANBOX_CMDS_RUN_H_
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "anbox/cli.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace cmds {
|
||||
class Run : public cli::CommandWithFlagsAndAction {
|
||||
public:
|
||||
Run();
|
||||
|
||||
private:
|
||||
std::string rootfs_;
|
||||
std::string desktop_file_hint_;
|
||||
};
|
||||
} // namespace cmds
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
36
src/anbox/cmds/shell.cpp
Normal file
36
src/anbox/cmds/shell.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "core/posix/signal.h"
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/container_connector.h"
|
||||
#include "anbox/cmds/shell.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
anbox::cmds::Shell::Shell()
|
||||
: CommandWithFlagsAndAction{cli::Name{"shell"}, cli::Usage{"shell"}, cli::Description{"Open a shell within the Anbox container"}}
|
||||
{
|
||||
action([this](const cli::Command::Context &ctx) {
|
||||
ContainerConnector connector;
|
||||
return connector.run("/system/bin/sh");
|
||||
});
|
||||
}
|
||||
39
src/anbox/cmds/shell.h
Normal file
39
src/anbox/cmds/shell.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_CMDS_RUN_QEMU_H_
|
||||
#define ANBOX_CMDS_RUN_QEMU_H_
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "anbox/cli.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace cmds {
|
||||
class Shell : public cli::CommandWithFlagsAndAction {
|
||||
public:
|
||||
Shell();
|
||||
|
||||
private:
|
||||
std::string rootfs_;
|
||||
};
|
||||
} // namespace cmds
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
33
src/anbox/cmds/version.cpp
Normal file
33
src/anbox/cmds/version.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/cmds/version.h"
|
||||
#include "anbox/version.h"
|
||||
|
||||
anbox::cmds::Version::Version()
|
||||
: CommandWithFlagsAndAction{cli::Name{"version"}, cli::Usage{"version"}, cli::Description{"print the version of the daemon"}}
|
||||
{
|
||||
action([](const cli::Command::Context& ctxt)
|
||||
{
|
||||
std::uint32_t major, minor, patch;
|
||||
anbox::version(major, minor, patch);
|
||||
ctxt.cout << "anbox " << major << "." << minor << "." << patch << std::endl;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
38
src/anbox/cmds/version.h
Normal file
38
src/anbox/cmds/version.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_CMDS_VERSION_H_
|
||||
#define ANBOX_CMDS_VERSION_H_
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "anbox/cli.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace cmds {
|
||||
class Version : public cli::CommandWithFlagsAndAction {
|
||||
public:
|
||||
Version();
|
||||
};
|
||||
} // namespace cmds
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
61
src/anbox/common/fd.cpp
Normal file
61
src/anbox/common/fd.cpp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright © 2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
|
||||
*/
|
||||
#include "anbox/common/fd.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace anbox {
|
||||
Fd::Fd() :
|
||||
Fd{invalid}
|
||||
{
|
||||
}
|
||||
|
||||
Fd::Fd(IntOwnedFd fd) :
|
||||
fd{std::make_shared<int>(fd.int_owned_fd)}
|
||||
{
|
||||
}
|
||||
|
||||
Fd::Fd(int raw_fd) :
|
||||
fd{new int{raw_fd},
|
||||
[](int* fd)
|
||||
{
|
||||
if (!fd) return;
|
||||
if (*fd > Fd::invalid) ::close(*fd);
|
||||
delete fd;
|
||||
}}
|
||||
{
|
||||
}
|
||||
|
||||
Fd::Fd(Fd&& other) :
|
||||
fd{std::move(other.fd)}
|
||||
{
|
||||
}
|
||||
|
||||
Fd& Fd::operator=(Fd other)
|
||||
{
|
||||
std::swap(fd, other.fd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Fd::operator int() const
|
||||
{
|
||||
if (fd) return *fd;
|
||||
return invalid;
|
||||
}
|
||||
} // namespace anbox
|
||||
50
src/anbox/common/fd.h
Normal file
50
src/anbox/common/fd.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright © 2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_COMMON_FD_H_
|
||||
#define ANBOX_COMMON_FD_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace anbox {
|
||||
struct IntOwnedFd
|
||||
{
|
||||
int int_owned_fd;
|
||||
};
|
||||
class Fd
|
||||
{
|
||||
public:
|
||||
//transfer ownership of the POD-int to the object. The int no longer needs close()ing,
|
||||
//and has the lifetime of the Fd object.
|
||||
explicit Fd(int fd);
|
||||
explicit Fd(IntOwnedFd);
|
||||
static int const invalid{-1};
|
||||
Fd(); //Initializes fd to the anbox::Fd::invalid;
|
||||
Fd(Fd&&);
|
||||
Fd(Fd const&) = default;
|
||||
Fd& operator=(Fd);
|
||||
|
||||
//bit of a convenient kludge. take care not to close or otherwise destroy the FD.
|
||||
operator int() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<int> fd;
|
||||
};
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
31
src/anbox/common/fd_sets.h
Normal file
31
src/anbox/common/fd_sets.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright © 2013 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Robert Carr <robert.carr@canonical.com>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_COMMON_FD_SETS_H_
|
||||
#define ANBOX_COMMON_FD_SETS_H_
|
||||
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "anbox/common/fd.h"
|
||||
|
||||
namespace anbox {
|
||||
typedef std::vector<std::vector<Fd>> FdSets;
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
61
src/anbox/common/variable_length_array.h
Normal file
61
src/anbox/common/variable_length_array.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright © 2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 3 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_COMMON_VARIABLE_LENGTH_ARRAY_H_
|
||||
#define ANBOX_COMMON_VARIABLE_LENGTH_ARRAY_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <memory>
|
||||
|
||||
namespace anbox {
|
||||
template <size_t BuiltInBufferSize>
|
||||
class VariableLengthArray
|
||||
{
|
||||
public:
|
||||
explicit VariableLengthArray(size_t size) : size_{size}
|
||||
{
|
||||
/* Don't call resize if the initial values of member variables are valid */
|
||||
if (size > BuiltInBufferSize) resize(size);
|
||||
}
|
||||
|
||||
void resize(size_t size)
|
||||
{
|
||||
if (size > BuiltInBufferSize)
|
||||
effective_buffer = BufferUPtr{new unsigned char[size], heap_deleter};
|
||||
else
|
||||
effective_buffer = BufferUPtr{builtin_buffer, null_deleter};
|
||||
|
||||
size_ = size;
|
||||
}
|
||||
|
||||
unsigned char* data() const { return effective_buffer.get(); }
|
||||
size_t size() const { return size_; }
|
||||
|
||||
private:
|
||||
typedef std::unique_ptr<unsigned char,void (*)(unsigned char*)> BufferUPtr;
|
||||
|
||||
static void null_deleter(unsigned char*) {}
|
||||
static void heap_deleter(unsigned char* b) { delete[] b; }
|
||||
|
||||
unsigned char builtin_buffer[BuiltInBufferSize];
|
||||
BufferUPtr effective_buffer{builtin_buffer, null_deleter};
|
||||
size_t size_;
|
||||
};
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
29
src/anbox/config.cpp
Normal file
29
src/anbox/config.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "anbox/config.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace config {
|
||||
std::string data_path() {
|
||||
// TODO(morphis): replace with proper compile time constant
|
||||
return "/home/phablet/.local/share/anbox/";
|
||||
}
|
||||
} // namespace config
|
||||
} // namespace anbox
|
||||
30
src/anbox/config.h
Normal file
30
src/anbox/config.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_CONFIG_H_
|
||||
#define ANBOX_CONFIG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
namespace config {
|
||||
std::string BubblewrapPath();
|
||||
std::string data_path();
|
||||
} // namespace config
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
123
src/anbox/container.cpp
Normal file
123
src/anbox/container.cpp
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "core/posix/fork.h"
|
||||
#include "core/posix/exec.h"
|
||||
|
||||
#include "anbox/utils.h"
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/container.h"
|
||||
#include "anbox/common/fd.h"
|
||||
|
||||
extern "C" int bwrap_main(int argc, char **argv);
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace anbox {
|
||||
|
||||
Container::Spec Container::Spec::Default() {
|
||||
Spec spec;
|
||||
spec.init_command = "/init";
|
||||
spec.environment.insert({"PATH", "/system/bin:/system/sbin:/system/xbin"});
|
||||
return spec;
|
||||
}
|
||||
std::shared_ptr<Container> Container::create(const Container::Spec &spec) {
|
||||
return std::shared_ptr<Container>(new Container{spec});
|
||||
}
|
||||
|
||||
Container::Container(const Container::Spec &spec) :
|
||||
spec_(spec),
|
||||
child_(core::posix::ChildProcess::invalid()),
|
||||
child_group_(core::posix::ProcessGroup::invalid()) {
|
||||
}
|
||||
|
||||
Container::~Container() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void Container::start() {
|
||||
std::vector<std::string> arguments = {
|
||||
"--ro-bind", spec_.rootfs_path, "/",
|
||||
"--dev", "/dev",
|
||||
"--proc", "/proc",
|
||||
"--unshare-user",
|
||||
"--unshare-ipc",
|
||||
"--unshare-pid",
|
||||
"--unshare-net",
|
||||
"--unshare-uts",
|
||||
// We will take UID 0 (root) inside the container
|
||||
"--uid", "0",
|
||||
// We will take GID 0 (root) inside the container
|
||||
"--gid", "0",
|
||||
"--chdir", "/",
|
||||
"--pid-file", utils::string_format("%s/pid", config::data_path()),
|
||||
};
|
||||
|
||||
for (const auto &dir : spec_.temporary_dirs) {
|
||||
arguments.push_back("--tmpfs");
|
||||
arguments.push_back(dir);
|
||||
}
|
||||
|
||||
for (const auto &path : spec_.dev_bind_paths) {
|
||||
arguments.push_back("--dev-bind");
|
||||
arguments.push_back(path);
|
||||
arguments.push_back(path);
|
||||
}
|
||||
|
||||
for (const auto &path : spec_.bind_paths) {
|
||||
arguments.push_back("--bind");
|
||||
arguments.push_back(path.first);
|
||||
arguments.push_back(path.second);
|
||||
}
|
||||
|
||||
for (const auto &env : spec_.environment) {
|
||||
arguments.push_back("--setenv");
|
||||
arguments.push_back(env.first);
|
||||
arguments.push_back(env.second);
|
||||
}
|
||||
|
||||
arguments.push_back(spec_.init_command);
|
||||
|
||||
child_ = core::posix::fork([&]() {
|
||||
char **it, **pargv;
|
||||
it = pargv = new char*[arguments.size() + 2];
|
||||
*it = strdup("bwrap");
|
||||
it++;
|
||||
for (auto arg : arguments) {
|
||||
*it = ::strdup(arg.c_str());
|
||||
it++;
|
||||
}
|
||||
*it = nullptr;
|
||||
|
||||
if (bwrap_main(arguments.size() + 1, pargv))
|
||||
return core::posix::exit::Status::failure;
|
||||
|
||||
return core::posix::exit::Status::success;
|
||||
}, core::posix::StandardStream::empty);
|
||||
|
||||
child_group_ = child_.process_group_or_throw();
|
||||
}
|
||||
|
||||
void Container::stop() {
|
||||
child_group_.send_signal_or_throw(core::posix::Signal::sig_kill);
|
||||
}
|
||||
|
||||
} // namespace anbox
|
||||
65
src/anbox/container.h
Normal file
65
src/anbox/container.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_CONTAINER_H_
|
||||
#define ANBOX_CONTAINER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory.h>
|
||||
|
||||
#include "core/posix/child_process.h"
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
#include "anbox/runtime.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace anbox {
|
||||
class Container : public DoNotCopyOrMove,
|
||||
public std::enable_shared_from_this<Container> {
|
||||
public:
|
||||
class Spec {
|
||||
public:
|
||||
static Spec Default();
|
||||
|
||||
std::string rootfs_path;
|
||||
std::string init_command;
|
||||
std::vector<std::string> temporary_dirs;
|
||||
std::map<std::string,std::string> bind_paths;
|
||||
std::vector<std::string> dev_bind_paths;
|
||||
std::map<std::string,std::string> environment;
|
||||
};
|
||||
|
||||
static std::shared_ptr<Container> create(const Spec &spec);
|
||||
|
||||
virtual ~Container();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
private:
|
||||
Container(const Container::Spec &spec);
|
||||
|
||||
Spec spec_;
|
||||
core::posix::ChildProcess child_;
|
||||
core::posix::ProcessGroup child_group_;
|
||||
};
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
148
src/anbox/container_connector.cpp
Normal file
148
src/anbox/container_connector.cpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/container_connector.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/utils.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include "core/posix/exec.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace {
|
||||
class NamespaceAttacher {
|
||||
public:
|
||||
enum class ns_type {
|
||||
user,
|
||||
pid,
|
||||
uts,
|
||||
mount,
|
||||
ipc,
|
||||
net,
|
||||
};
|
||||
|
||||
static std::string ns_type_to_string(ns_type type) {
|
||||
switch (type) {
|
||||
case ns_type::user:
|
||||
return "user";
|
||||
case ns_type::pid:
|
||||
return "pid";
|
||||
case ns_type::uts:
|
||||
return "uts";
|
||||
case ns_type::mount:
|
||||
return "mnt";
|
||||
case ns_type::ipc:
|
||||
return "ipc";
|
||||
case ns_type::net:
|
||||
return "net";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Unknown namespace type"));
|
||||
}
|
||||
|
||||
NamespaceAttacher(const std::vector<ns_type> &types, pid_t pid) :
|
||||
pid_(pid) {
|
||||
|
||||
attach(types);
|
||||
}
|
||||
|
||||
~NamespaceAttacher() {
|
||||
}
|
||||
|
||||
private:
|
||||
void attach(const std::vector<ns_type> &types) {
|
||||
std::vector<int> fds;
|
||||
for (const auto &type : types) {
|
||||
const auto path = anbox::utils::string_format("/proc/%lu/ns/%s", pid_, ns_type_to_string(type));
|
||||
if (!fs::exists(fs::path(path)))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to open namespace file"));
|
||||
|
||||
const auto fd = ::open(path.c_str(), O_RDONLY);
|
||||
if (fd < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to open namespace file"));
|
||||
|
||||
fds.push_back(fd);
|
||||
}
|
||||
|
||||
for (const auto &fd : fds) {
|
||||
if (::setns(fd, 0) == -1)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Could not attach to namespace"));
|
||||
|
||||
::close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
pid_t pid_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
ContainerConnector::ContainerConnector() {
|
||||
}
|
||||
|
||||
ContainerConnector::~ContainerConnector() {
|
||||
}
|
||||
|
||||
int ContainerConnector::run(const std::string &path) {
|
||||
const auto pid = std::stol(utils::read_file_if_exists_or_throw(
|
||||
utils::string_format("%s/pid", config::data_path())));
|
||||
|
||||
if (!fs::is_directory(fs::path(utils::string_format("/proc/%i", pid))))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Container isn't running"));
|
||||
|
||||
namespaces_ = std::make_shared<NamespaceAttacher>(std::vector<NamespaceAttacher::ns_type>{
|
||||
NamespaceAttacher::ns_type::user,
|
||||
NamespaceAttacher::ns_type::mount,
|
||||
NamespaceAttacher::ns_type::pid,
|
||||
NamespaceAttacher::ns_type::uts,
|
||||
NamespaceAttacher::ns_type::ipc,
|
||||
NamespaceAttacher::ns_type::net,
|
||||
}, pid);
|
||||
|
||||
// A few things we want to preset in our env within the container shell
|
||||
std::map<std::string, std::string> env = {
|
||||
{ "ANDROID_ROOT", "/" }
|
||||
};
|
||||
|
||||
auto child = core::posix::exec(path, {}, env, core::posix::StandardStream::empty, [this]() {
|
||||
// We're now in the namespace bwrap spawns up for the container which has
|
||||
// a /newroot directory pointing to the new root filesystem we get from
|
||||
// Android and is what we need to change to in order to work within
|
||||
// the Anroid system.
|
||||
if (::chroot("/newroot") != 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to enter container root filesystem"));
|
||||
|
||||
chdir("/");
|
||||
});
|
||||
|
||||
child.wait_for(core::posix::wait::Flags::untraced);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
40
src/anbox/container_connector.h
Normal file
40
src/anbox/container_connector.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_CONTAINER_CONNECTOR_H_
|
||||
#define ANBOX_CONTAINER_CONNECTOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace {
|
||||
class NamespaceAttacher;
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
class ContainerConnector {
|
||||
public:
|
||||
ContainerConnector();
|
||||
~ContainerConnector();
|
||||
|
||||
int run(const std::string &path);
|
||||
|
||||
private:
|
||||
std::shared_ptr<NamespaceAttacher> namespaces_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
55
src/anbox/daemon.cpp
Normal file
55
src/anbox/daemon.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/daemon.h"
|
||||
#include "anbox/config.h"
|
||||
|
||||
#include "anbox/cmds/version.h"
|
||||
#include "anbox/cmds/run.h"
|
||||
#include "anbox/cmds/shell.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace anbox {
|
||||
Daemon::Daemon() :
|
||||
cmd{cli::Name{"anbox"}, cli::Usage{"anbox"}, cli::Description{"The Android in a Box runtime"}} {
|
||||
|
||||
cmd.command(std::make_shared<cmds::Version>())
|
||||
.command(std::make_shared<cmds::Run>())
|
||||
.command(std::make_shared<cmds::Shell>());
|
||||
}
|
||||
|
||||
int Daemon::Run(const std::vector<std::string> &arguments)
|
||||
try {
|
||||
ensure_data_path();
|
||||
return cmd.run({std::cin, std::cout, arguments});
|
||||
}
|
||||
catch(std::exception &err) {
|
||||
ERROR("%s", err.what());
|
||||
}
|
||||
|
||||
void Daemon::ensure_data_path() {
|
||||
if (!fs::is_directory(fs::path(config::data_path())))
|
||||
fs::create_directories(fs::path(config::data_path()));
|
||||
}
|
||||
} // namespace anbox
|
||||
41
src/anbox/daemon.h
Normal file
41
src/anbox/daemon.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_DAEMON_H_
|
||||
#define ANBOX_DAEMON_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
#include "anbox/cli.h"
|
||||
|
||||
namespace anbox {
|
||||
class Daemon : public DoNotCopyOrMove {
|
||||
public:
|
||||
Daemon();
|
||||
|
||||
int Run(const std::vector<std::string> &arguments);
|
||||
|
||||
private:
|
||||
void ensure_data_path();
|
||||
|
||||
cli::CommandWithSubcommands cmd;
|
||||
};
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
44
src/anbox/defer_action.h
Normal file
44
src/anbox/defer_action.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_DEFER_ACTION_H_
|
||||
#define ANBOX_DEFER_ACTION_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
|
||||
namespace anbox {
|
||||
|
||||
class DeferAction : public DoNotCopyOrMove {
|
||||
public:
|
||||
DeferAction(const std::function<void()> action) :
|
||||
action_(action) {
|
||||
}
|
||||
|
||||
~DeferAction() {
|
||||
if (action_)
|
||||
action_();
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> action_;
|
||||
};
|
||||
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
38
src/anbox/do_not_copy_or_move.h
Normal file
38
src/anbox/do_not_copy_or_move.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_DO_NOT_COPY_OR_MOVE_H_
|
||||
#define ANBOX_DO_NOT_COPY_OR_MOVE_H_
|
||||
|
||||
namespace anbox {
|
||||
|
||||
class DoNotCopyOrMove
|
||||
{
|
||||
public:
|
||||
DoNotCopyOrMove(const DoNotCopyOrMove&) = delete;
|
||||
DoNotCopyOrMove(DoNotCopyOrMove&&) = delete;
|
||||
virtual ~DoNotCopyOrMove() = default;
|
||||
DoNotCopyOrMove& operator=(const DoNotCopyOrMove&) = delete;
|
||||
DoNotCopyOrMove& operator=(DoNotCopyOrMove&&) = delete;
|
||||
|
||||
protected:
|
||||
DoNotCopyOrMove() = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
79
src/anbox/graphics/gl_renderer_server.cpp
Normal file
79
src/anbox/graphics/gl_renderer_server.cpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/graphics/gl_renderer_server.h"
|
||||
|
||||
#include "OpenglRender/render_api.h"
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
GLRendererServer::GLRendererServer() {
|
||||
// Force the host EGL/GLES libraries as translator implementation
|
||||
::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 1);
|
||||
::setenv("ANDROID_GLESv1_LIB", "libGLESv1_CM.so.1", 1);
|
||||
::setenv("ANDROID_GLESv2_LIB", "libGLESv2.so.2", 1);
|
||||
|
||||
if (!initLibrary())
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer"));
|
||||
|
||||
setStreamMode(RENDER_API_STREAM_MODE_UNIX);
|
||||
}
|
||||
|
||||
GLRendererServer::~GLRendererServer() {
|
||||
destroyOpenGLSubwindow();
|
||||
stopOpenGLRenderer();
|
||||
}
|
||||
|
||||
void logger_write(const char *format, ...) {
|
||||
char message[2048];
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(message, sizeof(message) - 1, format, args);
|
||||
va_end(args);
|
||||
|
||||
DEBUG("%s", message);
|
||||
}
|
||||
|
||||
void GLRendererServer::start() {
|
||||
emugl_logger_struct log_funcs;
|
||||
log_funcs.coarse = logger_write;
|
||||
log_funcs.fine = logger_write;
|
||||
|
||||
char server_addr[256] = { 0 };
|
||||
if (!initOpenGLRenderer(1080, 1920, true, server_addr, sizeof(server_addr), log_funcs, logger_write))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup OpenGL renderer"));
|
||||
|
||||
socket_path_ = server_addr;
|
||||
DEBUG("socket path %s", socket_path_);
|
||||
|
||||
// Create the window we use for rendering the output we get from the
|
||||
// Android container. This will internally construct a Mir surface
|
||||
// and use the host EGL/GLES libraries for rendering.
|
||||
showOpenGLSubwindow(0, 0, 0, 1080, 1920, 1080, 1920, 1.0f, 0);
|
||||
}
|
||||
|
||||
std::string GLRendererServer::socket_path() const {
|
||||
return socket_path_;
|
||||
}
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
42
src/anbox/graphics/gl_renderer_server.h
Normal file
42
src/anbox/graphics/gl_renderer_server.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
|
||||
#define ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
|
||||
class GLRendererServer {
|
||||
public:
|
||||
GLRendererServer();
|
||||
~GLRendererServer();
|
||||
|
||||
void start();
|
||||
|
||||
std::string socket_path() const;
|
||||
|
||||
private:
|
||||
std::string socket_path_;
|
||||
};
|
||||
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
64
src/anbox/graphics/opengles_message_processor.cpp
Normal file
64
src/anbox/graphics/opengles_message_processor.cpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/graphics/opengles_message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/connections.h"
|
||||
#include "anbox/network/delegate_message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
|
||||
OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::string &renderer_socket_path,
|
||||
const std::shared_ptr<Runtime> &rt,
|
||||
const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
client_messenger_(messenger) {
|
||||
|
||||
connect_and_attach(renderer_socket_path, rt);
|
||||
}
|
||||
|
||||
OpenGlesMessageProcessor::~OpenGlesMessageProcessor() {
|
||||
}
|
||||
|
||||
void OpenGlesMessageProcessor::connect_and_attach(const std::string &socket_path,
|
||||
const std::shared_ptr<Runtime> &rt) {
|
||||
|
||||
auto socket = std::make_shared<boost::asio::local::stream_protocol::socket>(rt->service());
|
||||
socket->connect(boost::asio::local::stream_protocol::endpoint(socket_path));
|
||||
|
||||
messenger_ = std::make_shared<network::SocketMessenger>(socket);
|
||||
renderer_ = std::make_shared<network::SocketConnection>(
|
||||
messenger_,
|
||||
0,
|
||||
std::make_shared<network::Connections<network::SocketConnection>>(),
|
||||
std::make_shared<network::DelegateMessageProcessor>([&](const std::vector<std::uint8_t> &data) {
|
||||
client_messenger_->send(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
return true;
|
||||
}));
|
||||
|
||||
renderer_->read_next_message();
|
||||
}
|
||||
|
||||
bool OpenGlesMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
||||
messenger_->send(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
52
src/anbox/graphics/opengles_message_processor.h
Normal file
52
src/anbox/graphics/opengles_message_processor.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_GRAPHICS_OPENGLES_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_GRAPHICS_OPENGLES_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/socket_connection.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
class OpenGlesMessageProcessor : public network::MessageProcessor {
|
||||
public:
|
||||
OpenGlesMessageProcessor(const std::string &renderer_socket_path,
|
||||
const std::shared_ptr<Runtime> &rt,
|
||||
const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~OpenGlesMessageProcessor();
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
|
||||
private:
|
||||
void connect_and_attach(const std::string &socket_path,
|
||||
const std::shared_ptr<Runtime> &rt);
|
||||
|
||||
std::shared_ptr<network::SocketMessenger> client_messenger_;
|
||||
std::shared_ptr<network::SocketMessenger> messenger_;
|
||||
std::shared_ptr<network::SocketConnection> renderer_;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
154
src/anbox/logger.cpp
Normal file
154
src/anbox/logger.cpp
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
|
||||
#define BOOST_LOG_DYN_LINK
|
||||
#include <boost/date_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/log/expressions.hpp>
|
||||
#include <boost/log/support/date_time.hpp>
|
||||
#include <boost/log/utility/manipulators.hpp>
|
||||
#include <boost/log/utility/setup.hpp>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
|
||||
namespace {
|
||||
namespace attrs {
|
||||
BOOST_LOG_ATTRIBUTE_KEYWORD(Severity, "anbox::Severity", anbox::Logger::Severity)
|
||||
BOOST_LOG_ATTRIBUTE_KEYWORD(Location, "Location", anbox::Logger::Location)
|
||||
BOOST_LOG_ATTRIBUTE_KEYWORD(Timestamp, "Timestamp", boost::posix_time::ptime)
|
||||
}
|
||||
|
||||
struct BoostLogLogger : public anbox::Logger {
|
||||
BoostLogLogger() :
|
||||
initialized_(false) {
|
||||
}
|
||||
|
||||
void Init(const anbox::Logger::Severity &severity = anbox::Logger::Severity::kWarning) override {
|
||||
if (initialized_)
|
||||
return;
|
||||
|
||||
boost::log::formatter formatter = boost::log::expressions::stream
|
||||
<< "[" << attrs::Severity << " "
|
||||
<< boost::log::expressions::format_date_time< boost::posix_time::ptime >("Timestamp", "%Y-%m-%d %H:%M:%S")
|
||||
<< "] "
|
||||
<< boost::log::expressions::if_(boost::log::expressions::has_attr(attrs::Location))
|
||||
[
|
||||
boost::log::expressions::stream << "[" << attrs::Location << "] "
|
||||
]
|
||||
<< boost::log::expressions::smessage;
|
||||
|
||||
boost::log::core::get()->remove_all_sinks();
|
||||
auto logger = boost::log::add_console_log(std::cout);
|
||||
logger->set_formatter(formatter);
|
||||
|
||||
// FIXME need to enable this once we found how we wrap this
|
||||
// properly into our service architecture. For now left as
|
||||
// it is.
|
||||
boost::ignore_unused_variable_warning(severity);
|
||||
// logger->set_filter(attrs::Severity < severity);
|
||||
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
void Log(Severity severity, const std::string& message, const boost::optional<Location> &loc) {
|
||||
if (!initialized_)
|
||||
Init();
|
||||
|
||||
if (auto rec = boost::log::trivial::logger::get().open_record()) {
|
||||
boost::log::record_ostream out{rec};
|
||||
out << boost::log::add_value(attrs::Severity, severity)
|
||||
<< boost::log::add_value(attrs::Timestamp, boost::posix_time::microsec_clock::universal_time())
|
||||
<< message;
|
||||
|
||||
if (loc) {
|
||||
// We have to pass in a temporary as boost::log (<= 1.55) expects a
|
||||
// mutable reference to be passed to boost::log::add_value(...).
|
||||
auto tmp = *loc;
|
||||
out << boost::log::add_value(attrs::Location, tmp);
|
||||
}
|
||||
|
||||
boost::log::trivial::logger::get().push_record(std::move(rec));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool initialized_;
|
||||
};
|
||||
|
||||
std::shared_ptr<anbox::Logger>& MutableInstance() {
|
||||
static std::shared_ptr<anbox::Logger> instance{new BoostLogLogger()};
|
||||
return instance;
|
||||
}
|
||||
|
||||
void SetInstance(const std::shared_ptr<anbox::Logger>& logger) {
|
||||
MutableInstance() = logger;
|
||||
}
|
||||
}
|
||||
namespace anbox {
|
||||
|
||||
void Logger::Trace(const std::string& message, const boost::optional<Location>& location) {
|
||||
Log(Severity::kTrace, message, location);
|
||||
}
|
||||
|
||||
void Logger::Debug(const std::string& message, const boost::optional<Location>& location) {
|
||||
Log(Severity::kDebug, message, location);
|
||||
}
|
||||
|
||||
void Logger::Info(const std::string& message, const boost::optional<Location>& location) {
|
||||
Log(Severity::kInfo, message, location);
|
||||
}
|
||||
|
||||
void Logger::Warning(const std::string& message, const boost::optional<Location>& location) {
|
||||
Log(Severity::kWarning, message, location);
|
||||
}
|
||||
|
||||
void Logger::Error(const std::string& message, const boost::optional<Location>& location) {
|
||||
Log(Severity::kError, message, location);
|
||||
}
|
||||
|
||||
void Logger::Fatal(const std::string& message, const boost::optional<Location>& location) {
|
||||
Log(Severity::kFatal, message, location);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& strm, anbox::Logger::Severity severity) {
|
||||
switch (severity) {
|
||||
case anbox::Logger::Severity::kTrace: return strm << "TT";
|
||||
case anbox::Logger::Severity::kDebug: return strm << "DD";
|
||||
case anbox::Logger::Severity::kInfo: return strm << "II";
|
||||
case anbox::Logger::Severity::kWarning: return strm << "WW";
|
||||
case anbox::Logger::Severity::kError: return strm << "EE";
|
||||
case anbox::Logger::Severity::kFatal: return strm << "FF";
|
||||
default: return strm << static_cast<uint>(severity);
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Logger::Location &location) {
|
||||
return out << utils::string_format("%s:%d@%s", boost::filesystem::path(location.file).filename().string(), location.line, location.function);
|
||||
}
|
||||
|
||||
Logger& Log() {
|
||||
return *MutableInstance();
|
||||
}
|
||||
|
||||
void SetLogger(const std::shared_ptr<Logger>& logger) {
|
||||
SetInstance(logger);
|
||||
}
|
||||
|
||||
} // namespace anbox
|
||||
118
src/anbox/logger.h
Normal file
118
src/anbox/logger.h
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_LOGGER_H_
|
||||
#define ANBOX_LOGGER_H_
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <memory.h>
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
#include "anbox/utils.h"
|
||||
|
||||
namespace anbox {
|
||||
// A Logger enables persisting of messages describing & explaining the
|
||||
// state of the system.
|
||||
class Logger : public DoNotCopyOrMove {
|
||||
public:
|
||||
// Severity enumerates all known severity levels
|
||||
// applicable to log messages.
|
||||
enum class Severity {
|
||||
kTrace,
|
||||
kDebug,
|
||||
kInfo,
|
||||
kWarning,
|
||||
kError,
|
||||
kFatal
|
||||
};
|
||||
|
||||
// A Location describes the origin of a log message.
|
||||
struct Location {
|
||||
std::string file; // The name of the file that contains the log message.
|
||||
std::string function; // The function that contains the log message.
|
||||
std::uint32_t line; // The line in file that resulted in the log message.
|
||||
};
|
||||
|
||||
virtual void Init(const Severity &severity = Severity::kWarning) = 0;
|
||||
|
||||
virtual void Log(Severity severity, const std::string &message, const boost::optional<Location>& location) = 0;
|
||||
|
||||
virtual void Trace(const std::string& message, const boost::optional<Location>& location = boost::optional<Location>{});
|
||||
virtual void Debug(const std::string& message, const boost::optional<Location>& location = boost::optional<Location>{});
|
||||
virtual void Info(const std::string& message, const boost::optional<Location>& location = boost::optional<Location>{});
|
||||
virtual void Warning(const std::string& message, const boost::optional<Location>& location = boost::optional<Location>{});
|
||||
virtual void Error(const std::string& message, const boost::optional<Location>& location = boost::optional<Location>{});
|
||||
virtual void Fatal(const std::string& message, const boost::optional<Location>& location = boost::optional<Location>{});
|
||||
|
||||
|
||||
template<typename... T>
|
||||
void Tracef(const boost::optional<Location>& location, const std::string& pattern, T&&...args) {
|
||||
Trace(utils::string_format(pattern, std::forward<T>(args)...), location);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
void Debugf(const boost::optional<Location>& location, const std::string& pattern, T&&...args) {
|
||||
Debug(utils::string_format(pattern, std::forward<T>(args)...), location);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
void Infof(const boost::optional<Location>& location, const std::string& pattern, T&&...args) {
|
||||
Info(utils::string_format(pattern, std::forward<T>(args)...), location);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
void Warningf(const boost::optional<Location>& location, const std::string& pattern, T&&...args) {
|
||||
Warning(utils::string_format(pattern, std::forward<T>(args)...), location);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
void Errorf(const boost::optional<Location>& location, const std::string& pattern, T&&...args) {
|
||||
Error(utils::string_format(pattern, std::forward<T>(args)...), location);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
void Fatalf(const boost::optional<Location>& location, const std::string& pattern, T&&...args) {
|
||||
Fatal(utils::string_format(pattern, std::forward<T>(args)...), location);
|
||||
}
|
||||
|
||||
protected:
|
||||
Logger() = default;
|
||||
};
|
||||
|
||||
// operator<< inserts severity into out.
|
||||
std::ostream& operator<<(std::ostream& out, Logger::Severity severity);
|
||||
|
||||
// operator<< inserts location into out.
|
||||
std::ostream& operator<<(std::ostream& out, const Logger::Location &location);
|
||||
|
||||
// Log returns the mcs-wide configured logger instance.
|
||||
// Save to call before/after main.
|
||||
Logger& Log();
|
||||
// SetLog installs the given logger as mcs-wide default logger.
|
||||
void SetLogger(const std::shared_ptr<Logger>& logger);
|
||||
}
|
||||
|
||||
#define TRACE(...) anbox::Log().Tracef(anbox::Logger::Location{__FILE__, __FUNCTION__, __LINE__}, __VA_ARGS__)
|
||||
#define DEBUG(...) anbox::Log().Debugf(anbox::Logger::Location{__FILE__, __FUNCTION__, __LINE__}, __VA_ARGS__)
|
||||
#define INFO(...) anbox::Log().Infof(anbox::Logger::Location{__FILE__, __FUNCTION__, __LINE__}, __VA_ARGS__)
|
||||
#define WARNING(...) anbox::Log().Warningf(anbox::Logger::Location{__FILE__, __FUNCTION__, __LINE__}, __VA_ARGS__)
|
||||
#define ERROR(...) anbox::Log().Errorf(anbox::Logger::Location{__FILE__, __FUNCTION__, __LINE__}, __VA_ARGS__)
|
||||
#define FATAL(...) anbox::Log().Fatalf(anbox::Logger::Location{__FILE__, __FUNCTION__, __LINE__}, __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
31
src/anbox/network/connection_context.cpp
Normal file
31
src/anbox/network/connection_context.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/network/connection_context.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
|
||||
ConnectionContext::ConnectionContext(
|
||||
std::function<void()> const connect_handler,
|
||||
Connector const* connector) :
|
||||
connect_handler(connect_handler),
|
||||
connector(connector) {
|
||||
}
|
||||
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
48
src/anbox/network/connection_context.h
Normal file
48
src/anbox/network/connection_context.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright © 2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Alan Griffiths <alan@octopull.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_CONNECTION_CONTEXT_H_
|
||||
#define ANBOX_NETWORK_CONNECTION_CONTEXT_H_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class Connector;
|
||||
|
||||
class ConnectionContext
|
||||
{
|
||||
public:
|
||||
ConnectionContext(Connector const* connector) :
|
||||
ConnectionContext([](){}, connector) {}
|
||||
ConnectionContext(
|
||||
std::function<void()> const connect_handler,
|
||||
Connector const* connector);
|
||||
|
||||
int fd_for_new_client(std::function<void()> const& connect_handler) const;
|
||||
void handle_client_connect() const { connect_handler(); }
|
||||
|
||||
private:
|
||||
std::function<void()> const connect_handler;
|
||||
Connector const* const connector;
|
||||
};
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
|
||||
#endif
|
||||
16
src/anbox/network/connection_creator.cpp
Normal file
16
src/anbox/network/connection_creator.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
35
src/anbox/network/connection_creator.h
Normal file
35
src/anbox/network/connection_creator.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_CONNECTION_CREATOR_H_
|
||||
#define ANBOX_NETWORK_CONNECTION_CREATOR_H_
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class ConnectionCreator : public DoNotCopyOrMove {
|
||||
public:
|
||||
virtual void create_connection_for(
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) = 0;
|
||||
};
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
#endif
|
||||
71
src/anbox/network/connections.h
Normal file
71
src/anbox/network/connections.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright © 2012-2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Alan Griffiths <alan@octopull.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_CONNECTIONS_H_
|
||||
#define ANBOX_NETWORK_CONNECTIONS_H_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <map>
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
template<class Connection>
|
||||
class Connections
|
||||
{
|
||||
public:
|
||||
Connections() {}
|
||||
~Connections() { clear(); }
|
||||
|
||||
void add(std::shared_ptr<Connection> const& connection)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
connections[connection->id()] = connection;
|
||||
}
|
||||
|
||||
void remove(int id)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
connections.erase(id);
|
||||
}
|
||||
|
||||
bool includes(int id) const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return connections.find(id) != connections.end();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
connections.clear();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Connections(Connections const&) = delete;
|
||||
Connections& operator =(Connections const&) = delete;
|
||||
|
||||
std::mutex mutex;
|
||||
std::map<int, std::shared_ptr<Connection>> connections;
|
||||
};
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
|
||||
|
||||
#endif
|
||||
29
src/anbox/network/connector.h
Normal file
29
src/anbox/network/connector.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_CONNECTOR_H
|
||||
#define ANBOX_NETWORK_CONNECTOR_H
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class Connector {
|
||||
public:
|
||||
};
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
48
src/anbox/network/delegate_message_processor.h
Normal file
48
src/anbox/network/delegate_message_processor.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_DELEGATE_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_NETWORK_DELEGATE_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include "anbox/network/message_processor.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
|
||||
class DelegateMessageProcessor : public MessageProcessor {
|
||||
public:
|
||||
DelegateMessageProcessor(std::function<bool(const std::vector<std::uint8_t>&)> delegate) :
|
||||
delegate_(delegate) {
|
||||
}
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override {
|
||||
if (!delegate_)
|
||||
return false;
|
||||
|
||||
return delegate_(data);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<bool(const std::vector<std::uint8_t>&)> delegate_;
|
||||
};
|
||||
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
192
src/anbox/network/fd_socket_transmission.cpp
Normal file
192
src/anbox/network/fd_socket_transmission.cpp
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright © 2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
|
||||
*/
|
||||
|
||||
#include "anbox/network/fd_socket_transmission.h"
|
||||
#include "anbox/common/variable_length_array.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/exception/errinfo_errno.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace anbox {
|
||||
socket_error::socket_error(std::string const& message) :
|
||||
std::system_error(errno, std::system_category(), message)
|
||||
{
|
||||
}
|
||||
|
||||
socket_disconnected_error::socket_disconnected_error(std::string const& message) :
|
||||
std::system_error(errno, std::system_category(), message)
|
||||
{
|
||||
}
|
||||
|
||||
fd_reception_error::fd_reception_error(std::string const& message) :
|
||||
std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
|
||||
void send_fds(
|
||||
Fd const& socket,
|
||||
std::vector<Fd> const& fds)
|
||||
{
|
||||
if (fds.size() > 0)
|
||||
{
|
||||
// We send dummy data
|
||||
struct iovec iov;
|
||||
char dummy_iov_data = 'M';
|
||||
iov.iov_base = &dummy_iov_data;
|
||||
iov.iov_len = 1;
|
||||
|
||||
// Allocate space for control message
|
||||
static auto const builtin_n_fds = 5;
|
||||
static auto const builtin_cmsg_space = CMSG_SPACE(builtin_n_fds * sizeof(int));
|
||||
auto const fds_bytes = fds.size() * sizeof(int);
|
||||
VariableLengthArray<builtin_cmsg_space> control{CMSG_SPACE(fds_bytes)};
|
||||
// Silence valgrind uninitialized memory complaint
|
||||
memset(control.data(), 0, control.size());
|
||||
|
||||
// Message to send
|
||||
struct msghdr header;
|
||||
header.msg_name = NULL;
|
||||
header.msg_namelen = 0;
|
||||
header.msg_iov = &iov;
|
||||
header.msg_iovlen = 1;
|
||||
header.msg_controllen = control.size();
|
||||
header.msg_control = control.data();
|
||||
header.msg_flags = 0;
|
||||
|
||||
// Control message contains file descriptors
|
||||
struct cmsghdr *message = CMSG_FIRSTHDR(&header);
|
||||
message->cmsg_len = CMSG_LEN(fds_bytes);
|
||||
message->cmsg_level = SOL_SOCKET;
|
||||
message->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
int* const data = reinterpret_cast<int*>(CMSG_DATA(message));
|
||||
int i = 0;
|
||||
for (auto& fd : fds)
|
||||
data[i++] = fd;
|
||||
|
||||
auto const sent = sendmsg(socket, &header, MSG_NOSIGNAL);
|
||||
if (sent < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to send fds: " + std::string(strerror(errno))));
|
||||
}
|
||||
}
|
||||
|
||||
bool socket_error_is_transient(int error_code)
|
||||
{
|
||||
return (error_code == EINTR);
|
||||
}
|
||||
|
||||
void receive_data(Fd const& socket, void* buffer, size_t bytes_requested, std::vector<Fd>& fds)
|
||||
{
|
||||
if (bytes_requested == 0)
|
||||
BOOST_THROW_EXCEPTION(std::logic_error("Attempted to receive 0 bytes"));
|
||||
|
||||
size_t bytes_read{0};
|
||||
unsigned fds_read{0};
|
||||
while (bytes_read < bytes_requested)
|
||||
{
|
||||
// Store the data in the buffer requested
|
||||
struct iovec iov;
|
||||
iov.iov_base = static_cast<uint8_t*>(buffer) + bytes_read;
|
||||
iov.iov_len = bytes_requested - bytes_read;
|
||||
|
||||
// Allocate space for control message
|
||||
static auto const builtin_n_fds = 5;
|
||||
static auto const builtin_cmsg_space = CMSG_SPACE(builtin_n_fds * sizeof(int));
|
||||
auto const fds_bytes = (fds.size() - fds_read) * sizeof(int);
|
||||
VariableLengthArray<builtin_cmsg_space> control{CMSG_SPACE(fds_bytes)};
|
||||
|
||||
// Message to read
|
||||
struct msghdr header;
|
||||
header.msg_name = NULL;
|
||||
header.msg_namelen = 0;
|
||||
header.msg_iov = &iov;
|
||||
header.msg_iovlen = 1;
|
||||
header.msg_controllen = control.size();
|
||||
header.msg_control = control.data();
|
||||
header.msg_flags = 0;
|
||||
|
||||
ssize_t const result = recvmsg(socket, &header, MSG_NOSIGNAL | MSG_WAITALL);
|
||||
if (result == 0)
|
||||
BOOST_THROW_EXCEPTION(socket_disconnected_error("Failed to read message from server: server has shutdown"));
|
||||
if (result < 0)
|
||||
{
|
||||
if (socket_error_is_transient(errno))
|
||||
continue;
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
if (errno == EPIPE)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
boost::enable_error_info(socket_disconnected_error("Failed to read message from server"))
|
||||
<< boost::errinfo_errno(errno));
|
||||
|
||||
BOOST_THROW_EXCEPTION(
|
||||
boost::enable_error_info(socket_error("Failed to read message from server"))
|
||||
<< boost::errinfo_errno(errno));
|
||||
}
|
||||
|
||||
bytes_read += result;
|
||||
|
||||
// If we get a proper control message, copy the received
|
||||
// file descriptors back to the caller
|
||||
struct cmsghdr const* const cmsg = CMSG_FIRSTHDR(&header);
|
||||
if (cmsg)
|
||||
{
|
||||
if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_CREDENTIALS))
|
||||
BOOST_THROW_EXCEPTION(fd_reception_error("received SCM_CREDENTIALS when expecting fd"));
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
|
||||
BOOST_THROW_EXCEPTION(fd_reception_error("Invalid control message for receiving file descriptors"));
|
||||
|
||||
int const* const data = reinterpret_cast<int const*>CMSG_DATA(cmsg);
|
||||
ptrdiff_t const header_size = reinterpret_cast<char const*>(data) - reinterpret_cast<char const*>(cmsg);
|
||||
int const nfds = (cmsg->cmsg_len - header_size) / sizeof(int);
|
||||
|
||||
// NOTE: This relies on the file descriptor cmsg being read
|
||||
// (and written) atomically.
|
||||
if (cmsg->cmsg_len > CMSG_LEN(fds_bytes) || (header.msg_flags & MSG_CTRUNC))
|
||||
{
|
||||
for (int i = 0; i < nfds; i++)
|
||||
::close(data[i]);
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Received more fds than expected"));
|
||||
}
|
||||
|
||||
// We can't properly pass Fds through google::protobuf::Message,
|
||||
// which is where these get shoved.
|
||||
//
|
||||
// When we have our own RPC generator plugin and aren't using deprecated
|
||||
// Protobuf features this can go away.
|
||||
for (int i = 0; i < nfds; i++)
|
||||
fds[fds_read + i] = Fd{IntOwnedFd{data[i]}};
|
||||
|
||||
fds_read += nfds;
|
||||
}
|
||||
}
|
||||
|
||||
if (fds_read < fds.size())
|
||||
{
|
||||
for (auto fd : fds)
|
||||
if (fd >= 0)
|
||||
::close(fd);
|
||||
fds.clear();
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Received fewer fds than expected"));
|
||||
}
|
||||
}
|
||||
} // namespace anbox
|
||||
50
src/anbox/network/fd_socket_transmission.h
Normal file
50
src/anbox/network/fd_socket_transmission.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright © 2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_FD_SOCKET_TRANSMISSION_H_
|
||||
#define ANBOX_NETWORK_FD_SOCKET_TRANSMISSION_H_
|
||||
|
||||
#include "anbox/common/fd.h"
|
||||
|
||||
#include <vector>
|
||||
#include <system_error>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace anbox
|
||||
{
|
||||
struct socket_error : std::system_error
|
||||
{
|
||||
socket_error(std::string const& message);
|
||||
};
|
||||
|
||||
struct socket_disconnected_error : std::system_error
|
||||
{
|
||||
socket_disconnected_error(std::string const& message);
|
||||
};
|
||||
|
||||
struct fd_reception_error : std::runtime_error
|
||||
{
|
||||
fd_reception_error(std::string const& message);
|
||||
};
|
||||
|
||||
bool socket_error_is_transient(int error_code);
|
||||
void send_fds(Fd const& socket, std::vector<Fd> const& fd);
|
||||
void receive_data(Fd const& socket, void* buffer, size_t bytes_requested, std::vector<Fd>& fds);
|
||||
}
|
||||
|
||||
#endif
|
||||
34
src/anbox/network/message_processor.h
Normal file
34
src/anbox/network/message_processor.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_MESSAGE_PROCESSOR_H
|
||||
#define ANBOX_NETWORK_MESSAGE_PROCESSOR_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class MessageProcessor {
|
||||
public:
|
||||
virtual ~MessageProcessor() { }
|
||||
virtual bool process_data(const std::vector<std::uint8_t> &data) = 0;
|
||||
};
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
48
src/anbox/network/message_receiver.h
Normal file
48
src/anbox/network/message_receiver.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright © 2013-2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_MESSAGE_RECEIVER_H_
|
||||
#define ANBOX_NETWORK_MESSAGE_RECEIVER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/common/fd.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class MessageReceiver
|
||||
{
|
||||
public:
|
||||
//receive message from the socket. 'handler' will be called when 'buffer' has been filled with exactly 'size'
|
||||
typedef std::function<void(boost::system::error_code const&, size_t)> AnboxReadHandler;
|
||||
virtual void async_receive_msg(AnboxReadHandler const& handler, boost::asio::mutable_buffers_1 const& buffer) = 0;
|
||||
virtual boost::system::error_code receive_msg(boost::asio::mutable_buffers_1 const& buffer) = 0;
|
||||
virtual size_t available_bytes() = 0;
|
||||
|
||||
protected:
|
||||
MessageReceiver() = default;
|
||||
virtual ~MessageReceiver() = default;
|
||||
MessageReceiver(MessageReceiver const&) = delete;
|
||||
MessageReceiver& operator=(MessageReceiver const&) = delete;
|
||||
};
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
40
src/anbox/network/message_sender.h
Normal file
40
src/anbox/network/message_sender.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright © 2012 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Alan Griffiths <alan@octopull.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_MESSAGE_SENDER_H_
|
||||
#define ANBOX_NETWORK_MESSAGE_SENDER_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class MessageSender
|
||||
{
|
||||
public:
|
||||
virtual void send(char const* data, size_t length) = 0;
|
||||
|
||||
protected:
|
||||
MessageSender() = default;
|
||||
virtual ~MessageSender() = default;
|
||||
MessageSender(MessageSender const&) = delete;
|
||||
MessageSender& operator=(MessageSender const&) = delete;
|
||||
};
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
|
||||
#endif
|
||||
124
src/anbox/network/published_socket_connector.cpp
Normal file
124
src/anbox/network/published_socket_connector.cpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
|
||||
#include <boost/exception/errinfo_errno.hpp>
|
||||
|
||||
#include "anbox/network/published_socket_connector.h"
|
||||
#include "anbox/network/connection_context.h"
|
||||
|
||||
namespace {
|
||||
bool socket_file_exists(std::string const& filename)
|
||||
{
|
||||
struct stat statbuf;
|
||||
bool exists = (0 == stat(filename.c_str(), &statbuf));
|
||||
/* Avoid removing non-socket files */
|
||||
bool is_socket_type = (statbuf.st_mode & S_IFMT) == S_IFSOCK;
|
||||
return exists && is_socket_type;
|
||||
}
|
||||
|
||||
bool socket_exists(std::string const& socket_name)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string socket_path{socket_name};
|
||||
|
||||
/* In case an abstract socket name exists with the same name*/
|
||||
socket_path.insert(std::begin(socket_path), ' ');
|
||||
|
||||
/* If the name is contained in this table, it signifies
|
||||
* a process is truly using that socket connection
|
||||
*/
|
||||
std::ifstream socket_names_file("/proc/net/unix");
|
||||
std::string line;
|
||||
while (std::getline(socket_names_file, line))
|
||||
{
|
||||
auto index = line.find(socket_path);
|
||||
/* check for complete match */
|
||||
if (index != std::string::npos &&
|
||||
(index + socket_path.length()) == line.length())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
/* Assume the socket exists */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string remove_if_stale(std::string const& socket_name)
|
||||
{
|
||||
if (socket_file_exists(socket_name) && !socket_exists(socket_name))
|
||||
{
|
||||
if (std::remove(socket_name.c_str()) != 0)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
boost::enable_error_info(
|
||||
std::runtime_error("Failed removing stale socket file")) << boost::errinfo_errno(errno));
|
||||
}
|
||||
}
|
||||
return socket_name;
|
||||
}
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
PublishedSocketConnector::PublishedSocketConnector(
|
||||
const std::string& socket_file,
|
||||
const std::shared_ptr<Runtime> &rt,
|
||||
const std::shared_ptr<ConnectionCreator> &connection_creator) :
|
||||
socket_file_(remove_if_stale(socket_file)),
|
||||
runtime_(rt),
|
||||
connection_creator_(connection_creator),
|
||||
acceptor_(rt->service(), socket_file_) {
|
||||
|
||||
start_accept();
|
||||
}
|
||||
|
||||
PublishedSocketConnector::~PublishedSocketConnector() {
|
||||
}
|
||||
|
||||
void PublishedSocketConnector::start_accept() {
|
||||
auto socket = std::make_shared<boost::asio::local::stream_protocol::socket>(runtime_->service());
|
||||
|
||||
acceptor_.async_accept(
|
||||
*socket,
|
||||
[this, socket](boost::system::error_code const& err) {
|
||||
on_new_connection(socket, err);
|
||||
});
|
||||
}
|
||||
|
||||
void PublishedSocketConnector::on_new_connection(
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket,
|
||||
boost::system::error_code const& err) {
|
||||
|
||||
if (!err)
|
||||
connection_creator_->create_connection_for(socket);
|
||||
|
||||
start_accept();
|
||||
}
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
56
src/anbox/network/published_socket_connector.h
Normal file
56
src/anbox/network/published_socket_connector.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_PUBLISHEDSOCKETCONNECTOR_H
|
||||
#define ANBOX_PUBLISHEDSOCKETCONNECTOR_H
|
||||
|
||||
#include <boost/asio/local/stream_protocol.hpp>
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
#include "anbox/runtime.h"
|
||||
|
||||
#include "anbox/network/connector.h"
|
||||
#include "anbox/network/connection_creator.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class PublishedSocketConnector : public DoNotCopyOrMove,
|
||||
public Connector {
|
||||
public:
|
||||
explicit PublishedSocketConnector(
|
||||
const std::string& socket_file,
|
||||
const std::shared_ptr<Runtime> &rt,
|
||||
const std::shared_ptr<ConnectionCreator> &connection_creator);
|
||||
~PublishedSocketConnector() noexcept;
|
||||
|
||||
std::string socket_file() const { return socket_file_; }
|
||||
|
||||
private:
|
||||
void start_accept();
|
||||
void on_new_connection(
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket,
|
||||
boost::system::error_code const& err);
|
||||
|
||||
const std::string socket_file_;
|
||||
std::shared_ptr<Runtime> runtime_;
|
||||
std::shared_ptr<ConnectionCreator> connection_creator_;
|
||||
boost::asio::local::stream_protocol::acceptor acceptor_;
|
||||
};
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
103
src/anbox/network/qemu_pipe_connection_creator.cpp
Normal file
103
src/anbox/network/qemu_pipe_connection_creator.cpp
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/network/qemu_pipe_connection_creator.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/graphics/opengles_message_processor.h"
|
||||
#include "anbox/support/boot_properties_message_processor.h"
|
||||
#include "anbox/support/null_message_processor.h"
|
||||
|
||||
namespace ba = boost::asio;
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
QemuPipeConnectionCreator::QemuPipeConnectionCreator(const std::shared_ptr<Runtime> &rt,
|
||||
const std::string &renderer_socket_path) :
|
||||
runtime_(rt),
|
||||
next_connection_id_(0),
|
||||
connections_(std::make_shared<Connections<SocketConnection>>()),
|
||||
renderer_socket_path_(renderer_socket_path) {
|
||||
}
|
||||
|
||||
QemuPipeConnectionCreator::~QemuPipeConnectionCreator() {
|
||||
}
|
||||
|
||||
void QemuPipeConnectionCreator::create_connection_for(
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) {
|
||||
|
||||
auto const messenger = std::make_shared<SocketMessenger>(socket);
|
||||
const auto type = identify_client(messenger);
|
||||
auto const processor = create_processor(type, messenger);
|
||||
if (!processor)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Unhandled client type"));
|
||||
|
||||
auto const& connection = std::make_shared<SocketConnection>(messenger, next_id(), connections_, processor);
|
||||
connections_->add(connection);
|
||||
connection->read_next_message();
|
||||
|
||||
DEBUG("id %i", connection->id());
|
||||
}
|
||||
|
||||
QemuPipeConnectionCreator::client_type QemuPipeConnectionCreator::identify_client(
|
||||
std::shared_ptr<SocketMessenger> const& messenger) {
|
||||
|
||||
// The client will identify itself as first thing by writing a string
|
||||
// in the format 'pipe:<name>[:<arguments>]\0' to the channel.
|
||||
std::vector<char> buffer;
|
||||
for (;;) {
|
||||
unsigned char byte[1] = { 0 };
|
||||
const auto err = messenger->receive_msg(ba::buffer(byte, 1));
|
||||
if (err)
|
||||
break;
|
||||
buffer.push_back(byte[0]);
|
||||
if (byte[0] == 0x0)
|
||||
break;
|
||||
}
|
||||
|
||||
std::string identifier_and_args = buffer.data();
|
||||
|
||||
DEBUG("identifier %s", identifier_and_args);
|
||||
|
||||
if (utils::string_starts_with(identifier_and_args, "pipe:opengles"))
|
||||
return client_type::opengles;
|
||||
// Even if 'boot-properties' is an argument to the service 'qemud' here we
|
||||
// take this as a own service instance as that is what it is.
|
||||
else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:boot-properties"))
|
||||
return client_type::qemud_boot_properties;
|
||||
|
||||
return client_type::invalid;
|
||||
}
|
||||
|
||||
std::shared_ptr<MessageProcessor> QemuPipeConnectionCreator::create_processor(const client_type &type, const std::shared_ptr<SocketMessenger> &messenger) {
|
||||
if (type == client_type::opengles)
|
||||
return std::make_shared<graphics::OpenGlesMessageProcessor>(renderer_socket_path_, runtime_, messenger);
|
||||
else if (type == client_type::qemud_boot_properties)
|
||||
return std::make_shared<support::BootPropertiesMessageProcessor>(messenger);
|
||||
|
||||
return std::make_shared<support::NullMessageProcessor>();
|
||||
}
|
||||
|
||||
int QemuPipeConnectionCreator::next_id()
|
||||
{
|
||||
return next_connection_id_.fetch_add(1);
|
||||
}
|
||||
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
67
src/anbox/network/qemu_pipe_connection_creator.h
Normal file
67
src/anbox/network/qemu_pipe_connection_creator.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_QEMU_PIPE_CONNECTION_CREATOR_H_
|
||||
#define ANBOX_NETWORK_QEMU_PIPE_CONNECTION_CREATOR_H_
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/connections.h"
|
||||
#include "anbox/network/socket_connection.h"
|
||||
#include "anbox/network/connection_creator.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
|
||||
class QemuPipeConnectionCreator : public ConnectionCreator {
|
||||
public:
|
||||
QemuPipeConnectionCreator(
|
||||
const std::shared_ptr<Runtime> &rt,
|
||||
const std::string &renderer_socket_path);
|
||||
~QemuPipeConnectionCreator() noexcept;
|
||||
|
||||
void create_connection_for(
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) override;
|
||||
|
||||
enum class client_type {
|
||||
invalid,
|
||||
opengles,
|
||||
qemud_boot_properties,
|
||||
};
|
||||
|
||||
private:
|
||||
int next_id();
|
||||
|
||||
client_type identify_client(std::shared_ptr<SocketMessenger> const& messenger);
|
||||
std::shared_ptr<MessageProcessor> create_processor(
|
||||
const client_type &type, const std::shared_ptr<SocketMessenger> &messenger);
|
||||
|
||||
std::shared_ptr<Runtime> runtime_;
|
||||
std::atomic<int> next_connection_id_;
|
||||
std::shared_ptr<Connections<SocketConnection>> const connections_;
|
||||
|
||||
std::string renderer_socket_path_;
|
||||
};
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
|
||||
#endif
|
||||
88
src/anbox/network/socket_connection.cpp
Normal file
88
src/anbox/network/socket_connection.cpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright © 2012 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Alan Griffiths <alan@octopull.co.uk>
|
||||
*/
|
||||
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include "anbox/network/socket_connection.h"
|
||||
#include "anbox/network/message_sender.h"
|
||||
#include "anbox/network/message_receiver.h"
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
namespace ba = boost::asio;
|
||||
namespace bs = boost::system;
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
SocketConnection::SocketConnection(
|
||||
std::shared_ptr<MessageReceiver> const& message_receiver,
|
||||
int id_,
|
||||
std::shared_ptr<Connections<SocketConnection>> const& connections,
|
||||
std::shared_ptr<MessageProcessor> const& processor)
|
||||
: message_receiver_(message_receiver),
|
||||
id_(id_),
|
||||
connections_(connections),
|
||||
processor_(processor)
|
||||
{
|
||||
}
|
||||
|
||||
SocketConnection::~SocketConnection() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void SocketConnection::read_next_message()
|
||||
{
|
||||
auto callback = std::bind(&SocketConnection::on_read_size,
|
||||
this, std::placeholders::_1, std::placeholders::_2);
|
||||
message_receiver_->async_receive_msg(callback, ba::buffer(buffer_));
|
||||
}
|
||||
|
||||
void SocketConnection::on_read_size(const boost::system::error_code& error, std::size_t bytes_read)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
connections_->remove(id());
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(error.message()));
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> data(bytes_read);
|
||||
std::copy(buffer_.data(), buffer_.data() + bytes_read, data.data());
|
||||
|
||||
if (processor_->process_data(data))
|
||||
read_next_message();
|
||||
else
|
||||
connections_->remove(id());
|
||||
}
|
||||
|
||||
void SocketConnection::on_response_sent(bs::error_code const& error, std::size_t)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
connections_->remove(id());
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(error.message()));
|
||||
}
|
||||
}
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
|
||||
60
src/anbox/network/socket_connection.h
Normal file
60
src/anbox/network/socket_connection.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright © 2012-2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Alan Griffiths <alan@octopull.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_SOCKET_CONNECTION_H_
|
||||
#define ANBOX_NETWORK_SOCKET_CONNECTION_H_
|
||||
|
||||
#include "anbox/network/connections.h"
|
||||
#include "anbox/network/message_receiver.h"
|
||||
#include "anbox/network/message_processor.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class SocketConnection
|
||||
{
|
||||
public:
|
||||
SocketConnection(
|
||||
std::shared_ptr<MessageReceiver> const& message_receiver,
|
||||
int id,
|
||||
std::shared_ptr<Connections<SocketConnection>> const& connections,
|
||||
std::shared_ptr<MessageProcessor> const& processor);
|
||||
|
||||
~SocketConnection() noexcept;
|
||||
|
||||
int id() const { return id_; }
|
||||
|
||||
void read_next_message();
|
||||
|
||||
private:
|
||||
void on_response_sent(boost::system::error_code const& error, std::size_t);
|
||||
void on_read_size(const boost::system::error_code& ec, std::size_t bytes_read);
|
||||
|
||||
std::shared_ptr<MessageReceiver> const message_receiver_;
|
||||
int const id_;
|
||||
std::shared_ptr<Connections<SocketConnection>> const connections_;
|
||||
std::shared_ptr<MessageProcessor> const processor_;
|
||||
std::array<std::uint8_t, 8192> buffer_;
|
||||
};
|
||||
} // namespace anbox
|
||||
} // namespace network
|
||||
|
||||
#endif
|
||||
99
src/anbox/network/socket_messenger.cpp
Normal file
99
src/anbox/network/socket_messenger.cpp
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright © 2013-2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
|
||||
*/
|
||||
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/common/variable_length_array.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace bs = boost::system;
|
||||
namespace ba = boost::asio;
|
||||
|
||||
namespace {
|
||||
/// Buffers need to be big enough to support messages
|
||||
unsigned int const serialization_buffer_size = 2048;
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
SocketMessenger::SocketMessenger(std::shared_ptr<ba::local::stream_protocol::socket> const& socket)
|
||||
: socket(socket),
|
||||
socket_fd{IntOwnedFd{socket->native_handle()}}
|
||||
{
|
||||
socket->non_blocking(true);
|
||||
boost::asio::socket_base::send_buffer_size option(64*1024);
|
||||
socket->set_option(option);
|
||||
}
|
||||
|
||||
void SocketMessenger::send(char const* data, size_t length)
|
||||
{
|
||||
VariableLengthArray<serialization_buffer_size> whole_message{length};
|
||||
std::copy(data, data + length, whole_message.data());
|
||||
|
||||
try {
|
||||
std::unique_lock<std::mutex> lg(message_lock);
|
||||
ba::write(*socket,
|
||||
ba::buffer(whole_message.data(), whole_message.size()),
|
||||
boost::asio::transfer_all());
|
||||
}
|
||||
catch (std::exception &err) {
|
||||
ERROR("Failed to write message: %s", err.what());
|
||||
}
|
||||
}
|
||||
|
||||
void SocketMessenger::async_receive_msg(
|
||||
AnboxReadHandler const& handler,
|
||||
ba::mutable_buffers_1 const& buffer)
|
||||
{
|
||||
socket->async_read_some(buffer, handler);
|
||||
}
|
||||
|
||||
bs::error_code SocketMessenger::receive_msg(
|
||||
ba::mutable_buffers_1 const& buffer)
|
||||
{
|
||||
bs::error_code e;
|
||||
size_t nread = 0;
|
||||
|
||||
while (nread < ba::buffer_size(buffer))
|
||||
{
|
||||
nread += boost::asio::read(
|
||||
*socket,
|
||||
ba::mutable_buffers_1{buffer + nread},
|
||||
e);
|
||||
|
||||
if (e && e != ba::error::would_block)
|
||||
break;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
size_t SocketMessenger::available_bytes()
|
||||
{
|
||||
boost::asio::socket_base::bytes_readable command{true};
|
||||
socket->io_control(command);
|
||||
return command.get();
|
||||
}
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
51
src/anbox/network/socket_messenger.h
Normal file
51
src/anbox/network/socket_messenger.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright © 2013-2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_NETWORK_SOCKET_MESSENGER_H_
|
||||
#define ANBOX_NETWORK_SOCKET_MESSENGER_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "anbox/common/fd_sets.h"
|
||||
#include "anbox/network/message_sender.h"
|
||||
#include "anbox/network/message_receiver.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class SocketMessenger : public MessageSender,
|
||||
public MessageReceiver {
|
||||
public:
|
||||
SocketMessenger(std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket);
|
||||
|
||||
void send(char const* data, size_t length);
|
||||
|
||||
void async_receive_msg(AnboxReadHandler const& handle, boost::asio::mutable_buffers_1 const &buffer) override;
|
||||
boost::system::error_code receive_msg(boost::asio::mutable_buffers_1 const& buffer) override;
|
||||
size_t available_bytes() override;
|
||||
|
||||
|
||||
private:
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> socket;
|
||||
anbox::Fd socket_fd;
|
||||
|
||||
std::mutex message_lock;
|
||||
};
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
74
src/anbox/network/stream_socket_transport.cpp
Normal file
74
src/anbox/network/stream_socket_transport.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/common/variable_length_array.h"
|
||||
#include "anbox/network/stream_socket_transport.h"
|
||||
#include "anbox/network/fd_socket_transmission.h"
|
||||
|
||||
#include <system_error>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <boost/exception/errinfo_errno.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
|
||||
StreamSocketTransport::StreamSocketTransport(const std::string &socket_path,
|
||||
const std::shared_ptr<Runtime> &rt) :
|
||||
socket_(std::make_shared<boost::asio::local::stream_protocol::socket>(rt->service())),
|
||||
{
|
||||
socket_.connect(boost::asio::local::stream_protocol::endpoint(socket_path));
|
||||
read_next_message();
|
||||
}
|
||||
|
||||
void StreamSocketTransport::register_observer(std::shared_ptr<Observer> const& observer)
|
||||
{
|
||||
this->observer_ = observer;
|
||||
}
|
||||
|
||||
void StreamSocketTransport::unregister_observer(std::shared_ptr<Observer> const& observer)
|
||||
{
|
||||
if (this->observer_ != observer)
|
||||
return;
|
||||
|
||||
this->observer_.reset();
|
||||
}
|
||||
|
||||
void StreamSocketTransport::send_message(std::vector<uint8_t> const& buffer)
|
||||
{
|
||||
}
|
||||
|
||||
void StreamSocketTransport::read_next_message() {
|
||||
auto callback = std::bind(&StreamSocketTransport::on_read_size,
|
||||
this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2);
|
||||
|
||||
}
|
||||
|
||||
void StreamSocketTransport::on_read_size(const boost::system::error_code& ec, std::size_t bytes_read) {
|
||||
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
66
src/anbox/network/stream_socket_transport.h
Normal file
66
src/anbox/network/stream_socket_transport.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_STREAM_SOCKET_TRANSPORT_H_
|
||||
#define ANBOX_STREAM_SOCKET_TRANSPORT_H_
|
||||
|
||||
#include "anbox/common/fd.h"
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
namespace anbox {
|
||||
namespace network {
|
||||
class StreamSocketTransport
|
||||
{
|
||||
public:
|
||||
class Observer {
|
||||
public:
|
||||
Observer() = default;
|
||||
virtual ~Observer() = default;
|
||||
|
||||
virtual void on_data_available() = 0;
|
||||
virtual void on_disconnected() = 0;
|
||||
|
||||
Observer(Observer const&) = delete;
|
||||
Observer& operator=(Observer const&) = delete;
|
||||
};
|
||||
|
||||
StreamSocketTransport(const std::string &socket_path,
|
||||
const std::shared_ptr<Runtime> &rt);
|
||||
|
||||
void register_observer(std::shared_ptr<Observer> const& observer_);
|
||||
void unregister_observer(std::shared_ptr<Observer> const& observer_);
|
||||
|
||||
void send_message(std::vector<uint8_t> const& buffer);
|
||||
void read_next_message();
|
||||
|
||||
private:
|
||||
void on_read_size(const boost::system::error_code& ec, std::size_t bytes_read);
|
||||
|
||||
std::shared_ptr<Observer> observer_;
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> socket_;
|
||||
SocketMessenger messenger_;
|
||||
};
|
||||
} // namespace network
|
||||
} // namespace anbox
|
||||
|
||||
|
||||
#endif // STREAM_SOCKET_TRANSPORT_H_
|
||||
32
src/anbox/optional.h
Normal file
32
src/anbox/optional.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_OPTIONAL_H_
|
||||
#define ANBOX_OPTIONAL_H_
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
|
||||
namespace anbox
|
||||
{
|
||||
template<typename T>
|
||||
using Optional = boost::optional<T>;
|
||||
}
|
||||
|
||||
#endif
|
||||
45
src/anbox/pid_persister.cpp
Normal file
45
src/anbox/pid_persister.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/utils.h"
|
||||
#include "anbox/pid_persister.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace anbox {
|
||||
|
||||
PidPersister::PidPersister() :
|
||||
path_(utils::string_format("%s/pid", config::data_path())) {
|
||||
if (fs::exists(fs::path(path_)))
|
||||
std::remove(path_.c_str());
|
||||
|
||||
std::ofstream file;
|
||||
file.open(path_);
|
||||
file << getpid();
|
||||
file.close();
|
||||
}
|
||||
|
||||
PidPersister::~PidPersister() {
|
||||
std::remove(path_.c_str());
|
||||
}
|
||||
|
||||
} // namespace anbox
|
||||
34
src/anbox/pid_persister.h
Normal file
34
src/anbox/pid_persister.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_PID_PERSISTER_H_
|
||||
#define ANBOX_PID_PERSISTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
class PidPersister {
|
||||
public:
|
||||
PidPersister();
|
||||
~PidPersister();
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
};
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
100
src/anbox/runtime.cpp
Normal file
100
src/anbox/runtime.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/runtime.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
// exception_safe_run runs service, catching all exceptions and
|
||||
// restarting operation until an explicit shutdown has been requested.
|
||||
//
|
||||
// TODO(tvoss): Catching all exceptions is risky as they might signal unrecoverable
|
||||
// errors. We should enable calling code to decide whether an exception should be considered
|
||||
// fatal or not.
|
||||
void exception_safe_run(boost::asio::io_service& service) {
|
||||
while (true) {
|
||||
try {
|
||||
service.run();
|
||||
// a clean return from run only happens in case of
|
||||
// stop() being called (we are keeping the service alive with
|
||||
// a service::work instance).
|
||||
break;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "test" << e.what();
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Unknown exception caught while executing boost::asio::io_service";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace anbox {
|
||||
|
||||
std::shared_ptr<Runtime> Runtime::create(std::uint32_t pool_size) {
|
||||
return std::shared_ptr<Runtime>(new Runtime(pool_size));
|
||||
}
|
||||
|
||||
Runtime::Runtime(std::uint32_t pool_size) :
|
||||
pool_size_{pool_size},
|
||||
service_{pool_size_},
|
||||
strand_{service_},
|
||||
keep_alive_{service_} {
|
||||
}
|
||||
|
||||
Runtime::~Runtime() {
|
||||
try {
|
||||
stop();
|
||||
}
|
||||
catch(...) {
|
||||
// Dropping all exceptions to satisfy the nothrow guarantee.
|
||||
}
|
||||
}
|
||||
|
||||
void Runtime::start() {
|
||||
for (unsigned int i = 0; i < pool_size_; i++)
|
||||
workers_.push_back(std::thread{exception_safe_run, std::ref(service_)});
|
||||
}
|
||||
|
||||
void Runtime::stop() {
|
||||
service_.stop();
|
||||
|
||||
for (auto& worker : workers_)
|
||||
if (worker.joinable())
|
||||
worker.join();
|
||||
}
|
||||
|
||||
std::function<void(std::function<void()>)> Runtime::to_dispatcher_functional()
|
||||
{
|
||||
// We have to make sure that we stay alive for as long as
|
||||
// calling code requires the dispatcher to work.
|
||||
auto sp = shared_from_this();
|
||||
return [sp](std::function<void()> task)
|
||||
{
|
||||
sp->strand_.post(task);
|
||||
};
|
||||
}
|
||||
|
||||
boost::asio::io_service& Runtime::service() {
|
||||
return service_;
|
||||
}
|
||||
|
||||
|
||||
} // namespace anbox
|
||||
77
src/anbox/runtime.h
Normal file
77
src/anbox/runtime.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_RUNTIME_H_
|
||||
#define ANBOX_RUNTIME_H_
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory.h>
|
||||
#include <thread>
|
||||
|
||||
#include "anbox/do_not_copy_or_move.h"
|
||||
|
||||
namespace anbox {
|
||||
|
||||
// We bundle our "global" runtime dependencies here, specifically
|
||||
// a dispatcher to decouple multiple in-process providers from one
|
||||
// another , forcing execution to a well known set of threads.
|
||||
class Runtime : public DoNotCopyOrMove,
|
||||
public std::enable_shared_from_this<Runtime> {
|
||||
public:
|
||||
// Our default concurrency setup.
|
||||
static constexpr const std::uint32_t worker_threads = 2;
|
||||
|
||||
// create returns a Runtime instance with pool_size worker threads
|
||||
// executing the underlying service.
|
||||
static std::shared_ptr<Runtime> create(std::uint32_t pool_size = worker_threads);
|
||||
|
||||
// Tears down the runtime, stopping all worker threads.
|
||||
~Runtime() noexcept(true);
|
||||
|
||||
// start executes the underlying io_service on a thread pool with
|
||||
// the size configured at creation time.
|
||||
void start();
|
||||
|
||||
// stop cleanly shuts down a Runtime instance,
|
||||
// joining all worker threads.
|
||||
void stop();
|
||||
|
||||
// to_dispatcher_functional returns a function for integration
|
||||
// with components that expect a dispatcher for operation.
|
||||
std::function<void(std::function<void()>)> to_dispatcher_functional();
|
||||
|
||||
// service returns the underlying boost::asio::io_service that is executed
|
||||
// by the Runtime.
|
||||
boost::asio::io_service& service();
|
||||
|
||||
private:
|
||||
// Runtime constructs a new instance, firing up pool_size
|
||||
// worker threads.
|
||||
Runtime(std::uint32_t pool_size);
|
||||
|
||||
std::uint32_t pool_size_;
|
||||
boost::asio::io_service service_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::io_service::work keep_alive_;
|
||||
std::vector<std::thread> workers_;
|
||||
};
|
||||
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
113
src/anbox/support/boot_properties_message_processor.cpp
Normal file
113
src/anbox/support/boot_properties_message_processor.cpp
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/support/boot_properties_message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/connections.h"
|
||||
#include "anbox/network/delegate_message_processor.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace ba = boost::asio;
|
||||
|
||||
namespace {
|
||||
static constexpr const long header_size{4};
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
BootPropertiesMessageProcessor::BootPropertiesMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
messenger_(messenger) {
|
||||
}
|
||||
|
||||
BootPropertiesMessageProcessor::~BootPropertiesMessageProcessor() {
|
||||
}
|
||||
|
||||
bool BootPropertiesMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
||||
for (const auto &byte : data)
|
||||
buffer_.push_back(byte);
|
||||
|
||||
process_commands();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BootPropertiesMessageProcessor::process_commands() {
|
||||
while (true) {
|
||||
if (buffer_.size() < header_size)
|
||||
break;
|
||||
|
||||
char header[header_size] = { 0 };
|
||||
::memcpy(header, buffer_.data(), header_size);
|
||||
|
||||
unsigned int body_size = 0;
|
||||
::sscanf(header, "%04x", &body_size);
|
||||
if (body_size != buffer_.size() - header_size)
|
||||
break;
|
||||
|
||||
std::string command;
|
||||
// Make sure we only copy as much bytes as we have to and not more
|
||||
command.insert(0, reinterpret_cast<const char*>(buffer_.data()) + header_size, body_size);
|
||||
|
||||
if (command == "list")
|
||||
list_properties();
|
||||
else
|
||||
DEBUG("Unknown command '%s'", command);
|
||||
|
||||
const auto consumed = header_size + body_size;
|
||||
buffer_.erase(buffer_.begin(), buffer_.begin() + consumed);
|
||||
|
||||
const auto remaining = buffer_.size() - consumed;
|
||||
if (remaining <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BootPropertiesMessageProcessor::list_properties() {
|
||||
std::vector<std::string> properties = {
|
||||
// Simple indicator to say we're anbox and if needed things in the container
|
||||
// can adjust to this. Normally everything should detect we're qemu which
|
||||
// should be enough for the simple cases.
|
||||
"ro.anbox=1",
|
||||
|
||||
"ro.hardware=goldfish",
|
||||
|
||||
// Needed to let the gralloc HAL load the right implementation
|
||||
"ro.kernel.qemu.gles=1",
|
||||
|
||||
// Needed from different parts of the system in order to load
|
||||
// the right implementation for qemu
|
||||
"ro.kernel.qemu=1",
|
||||
|
||||
// TODO(morphis): Using HDPI here for now but should be adjusted to the device
|
||||
// we're running on.
|
||||
"qemu.sf.lcd_density=240"
|
||||
};
|
||||
|
||||
for (const auto &prop : properties) {
|
||||
char header[header_size + 1];
|
||||
std::snprintf(header, header_size + 1, "%04x", prop.length());
|
||||
messenger_->send(header, header_size);
|
||||
messenger_->send(prop.c_str(), prop.length());
|
||||
}
|
||||
|
||||
// Send terminating NULL byte
|
||||
messenger_->send(static_cast<const char*>(""), 1);
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
49
src/anbox/support/boot_properties_message_processor.h
Normal file
49
src/anbox/support/boot_properties_message_processor.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_SUPPORT_BOOT_PROPERTIES_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_BOOT_PROPERTIES_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/socket_connection.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class BootPropertiesMessageProcessor : public network::MessageProcessor {
|
||||
public:
|
||||
BootPropertiesMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~BootPropertiesMessageProcessor();
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
|
||||
private:
|
||||
void process_commands();
|
||||
void list_properties();
|
||||
|
||||
std::shared_ptr<network::SocketMessenger> messenger_;
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
82
src/anbox/support/hwcontrol_message_processor.cpp
Normal file
82
src/anbox/support/hwcontrol_message_processor.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/support/hwcontrol_message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/connections.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace ba = boost::asio;
|
||||
|
||||
namespace {
|
||||
static constexpr const long header_size{4};
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
HwControlMessageProcessor::HwControlMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
messenger_(messenger) {
|
||||
}
|
||||
|
||||
HwControlMessageProcessor::~HwControlMessageProcessor() {
|
||||
}
|
||||
|
||||
bool HwControlMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
||||
for (const auto &byte : data)
|
||||
buffer_.push_back(byte);
|
||||
|
||||
process_commands();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HwControlMessageProcessor::process_commands() {
|
||||
while (true) {
|
||||
if (buffer_.size() < header_size)
|
||||
break;
|
||||
|
||||
char header[header_size] = { 0 };
|
||||
::memcpy(header, buffer_.data(), header_size);
|
||||
|
||||
unsigned int body_size = 0;
|
||||
::sscanf(header, "%04x", &body_size);
|
||||
if (body_size != buffer_.size() - header_size)
|
||||
break;
|
||||
|
||||
std::string command;
|
||||
// Make sure we only copy as much bytes as we have to and not more
|
||||
command.insert(0, reinterpret_cast<const char*>(buffer_.data()) + header_size, body_size);
|
||||
|
||||
if (command == "power:screen_state:wake")
|
||||
DEBUG("Got screen wake command");
|
||||
else if (command == "power:screen_state:standby")
|
||||
DEBUG("Got screen standby command");
|
||||
else
|
||||
DEBUG("Unknown command '%s'", command);
|
||||
|
||||
const auto consumed = header_size + body_size;
|
||||
buffer_.erase(buffer_.begin(), buffer_.begin() + consumed);
|
||||
|
||||
const auto remaining = buffer_.size() - consumed;
|
||||
if (remaining <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
48
src/anbox/support/hwcontrol_message_processor.h
Normal file
48
src/anbox/support/hwcontrol_message_processor.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_SUPPORT_HWCONTROL_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_HWCONTROL_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/socket_connection.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class HwControlMessageProcessor : public network::MessageProcessor {
|
||||
public:
|
||||
HwControlMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~HwControlMessageProcessor();
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
|
||||
private:
|
||||
void process_commands();
|
||||
|
||||
std::shared_ptr<network::SocketMessenger> messenger_;
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
34
src/anbox/support/null_message_processor.cpp
Normal file
34
src/anbox/support/null_message_processor.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/support/null_message_processor.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
NullMessageProcessor::NullMessageProcessor() {
|
||||
}
|
||||
|
||||
NullMessageProcessor::~NullMessageProcessor() {
|
||||
}
|
||||
|
||||
bool NullMessageProcessor::process_data(const std::vector<std::uint8_t>&) {
|
||||
return true;
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
40
src/anbox/support/null_message_processor.h
Normal file
40
src/anbox/support/null_message_processor.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_SUPPORT_NULL_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_NULL_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class NullMessageProcessor : public network::MessageProcessor {
|
||||
public:
|
||||
NullMessageProcessor();
|
||||
~NullMessageProcessor();
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
136
src/anbox/utils.cpp
Normal file
136
src/anbox/utils.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "anbox/utils.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace utils {
|
||||
|
||||
std::vector<std::string> collect_arguments(int argc, char **argv) {
|
||||
std::vector<std::string> result;
|
||||
for (int i = 1; i < argc; i++) result.push_back(argv[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string read_file_if_exists_or_throw(const std::string &file_path) {
|
||||
if (!boost::filesystem::is_regular(boost::filesystem::path(file_path)))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("File does not exist"));
|
||||
|
||||
std::ifstream file;
|
||||
file.open(file_path, std::ifstream::in);
|
||||
std::string content;
|
||||
file >> content;
|
||||
file.close();
|
||||
return content;
|
||||
}
|
||||
|
||||
bool write_to_file(const std::string &file_path, const std::string &content) {
|
||||
std::ofstream of;
|
||||
of.open(file_path, std::ofstream::out);
|
||||
of << content;
|
||||
of.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
int write_to_fd(int fd, const char *content, ssize_t len) {
|
||||
while (len > 0) {
|
||||
const auto res = write (fd, content, len);
|
||||
if (res < 0 && errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (res <= 0) {
|
||||
if (res == 0) /* Unexpected short write, should not happen when writing to a file */
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len -= res;
|
||||
content += res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_file_at(int dirfd, const char *path, const char *content) {
|
||||
const auto fd = openat (dirfd, path, O_RDWR | O_CLOEXEC, 0);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
auto res = 0;
|
||||
if (content)
|
||||
res = write_to_fd (fd, content, strlen (content));
|
||||
|
||||
const auto errsv = errno;
|
||||
close (fd);
|
||||
errno = errsv;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool string_starts_with(const std::string &text, const std::string &prefix) {
|
||||
return text.compare(0, prefix.size(), prefix) == 0;
|
||||
}
|
||||
|
||||
std::string hex_dump(const uint8_t *data, uint32_t size) {
|
||||
unsigned char buff[17];
|
||||
const uint8_t *pc = data;
|
||||
std::stringstream buffer;
|
||||
|
||||
if (size == 0) {
|
||||
buffer << "NULL" << std::endl;
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
if ((i % 16) == 0) {
|
||||
if (i != 0)
|
||||
buffer << string_format(" %s", buff) << std::endl;
|
||||
|
||||
buffer << string_format("%02x ", i);
|
||||
}
|
||||
|
||||
buffer << string_format(" %02x", static_cast<int>(pc[i]));
|
||||
|
||||
if ((pc[i] < 0x20) || (pc[i] > 0x7e))
|
||||
buff[i % 16] = '.';
|
||||
else
|
||||
buff[i % 16] = pc[i];
|
||||
buff[(i % 16) + 1] = '\0';
|
||||
}
|
||||
|
||||
while ((i % 16) != 0) {
|
||||
buffer << " ";
|
||||
i++;
|
||||
}
|
||||
|
||||
buffer << string_format(" %s", buff) << std::endl;
|
||||
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace anbox
|
||||
66
src/anbox/utils.h
Normal file
66
src/anbox/utils.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_UTILS_H_
|
||||
#define ANBOX_UTILS_H_
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
namespace utils {
|
||||
|
||||
std::vector<std::string> collect_arguments(int argc, char **argv);
|
||||
|
||||
std::string read_file_if_exists_or_throw(const std::string &file_path);
|
||||
|
||||
bool write_to_file(const std::string &file_path, const std::string &content = "");
|
||||
int write_to_fd(int fd, const char *content, ssize_t len);
|
||||
int write_file_at(int dirfd, const char *path, const char *content);
|
||||
|
||||
bool string_starts_with(const std::string &text, const std::string &prefix);
|
||||
|
||||
std::string hex_dump(const uint8_t *data, uint32_t size);
|
||||
|
||||
template<typename... Types>
|
||||
static std::string string_format(const std::string& fmt_str, Types&&... args);
|
||||
} // namespace utils
|
||||
} // namespace anbox
|
||||
|
||||
namespace impl {
|
||||
// Base case, just return the passed in boost::format instance.
|
||||
inline boost::format& string_format(boost::format& f)
|
||||
{
|
||||
return f;
|
||||
}
|
||||
// Sprintf recursively walks the parameter pack at compile time.
|
||||
template <typename Head, typename... Tail>
|
||||
inline boost::format& string_format(boost::format& f, Head const& head, Tail&&... tail) {
|
||||
return string_format(f % head, std::forward<Tail>(tail)...);
|
||||
}
|
||||
} // namespace impl
|
||||
|
||||
template <typename... Types>
|
||||
inline std::string anbox::utils::string_format(const std::string& format, Types&&... args) {
|
||||
boost::format f(format);
|
||||
return impl::string_format(f, std::forward<Types>(args)...).str();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
27
src/anbox/version.cpp
Normal file
27
src/anbox/version.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/version.h"
|
||||
|
||||
void anbox::version(std::uint32_t& major, std::uint32_t& minor, std::uint32_t& patch)
|
||||
{
|
||||
major = anbox::build::version_major;
|
||||
minor = anbox::build::version_minor;
|
||||
patch = anbox::build::version_patch;
|
||||
}
|
||||
42
src/anbox/version.h
Normal file
42
src/anbox/version.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Canonical, Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_VERSION_H_
|
||||
#define ANBOX_VERSION_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace anbox {
|
||||
namespace build {
|
||||
/// @brief version_major marks the major version of the library. The constant is meant to be used
|
||||
/// by client code both at build and runtime, enabling version checks.
|
||||
static constexpr const std::uint32_t version_major{1};
|
||||
/// @brief version_major marks the minor version of the library. The constant is meant to be used
|
||||
/// by client code both at build and runtime, enabling version checks.
|
||||
static constexpr const std::uint32_t version_minor{0};
|
||||
/// @brief version_patch marks the major version of the library. The constant is meant to be used
|
||||
/// by client code both at build and runtime, enabling version checks.
|
||||
static constexpr const std::uint32_t version_patch{1};
|
||||
} // namespace build
|
||||
|
||||
/// @brief version queries the version of the library, placing the result in major, minor and patch.
|
||||
void version(std::uint32_t& major, std::uint32_t& minor, std::uint32_t& patch);
|
||||
} // namespace build
|
||||
|
||||
#endif // ANBOX_VERSION_H_
|
||||
24
src/main.cpp
Normal file
24
src/main.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/daemon.h"
|
||||
#include "anbox/utils.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
anbox::Daemon daemon;
|
||||
return daemon.Run(anbox::utils::collect_arguments(argc, argv));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue