Implemented basic structure of daemon registry.
diff --git a/vsomeip/CMakeLists.txt b/vsomeip/CMakeLists.txt
index 6cb0372..fe1b80f 100644
--- a/vsomeip/CMakeLists.txt
+++ b/vsomeip/CMakeLists.txt
@@ -41,4 +41,7 @@
target_link_libraries(vsomeip-ip_threaded_client vsomeip-base boost_system boost_thread)
add_executable(vsomeip-ip_service_discovery_client src/examples/ip_service_discovery_client.cpp)
-target_link_libraries(vsomeip-ip_service_discovery_client vsomeip-service_discovery vsomeip-base boost_system boost_thread)
\ No newline at end of file
+target_link_libraries(vsomeip-ip_service_discovery_client vsomeip-service_discovery vsomeip-base boost_system boost_thread)
+
+add_executable(vsomeip-ip_service_discovery_service src/examples/ip_service_discovery_service.cpp)
+target_link_libraries(vsomeip-ip_service_discovery_service vsomeip-service_discovery vsomeip-base boost_system boost_thread)
\ No newline at end of file
diff --git a/vsomeip/include/vsomeip/service_discovery/internal/daemon-config.hpp b/vsomeip/include/vsomeip/service_discovery/internal/daemon-config.hpp
index 79317f6..5495c2a 100755
--- a/vsomeip/include/vsomeip/service_discovery/internal/daemon-config.hpp
+++ b/vsomeip/include/vsomeip/service_discovery/internal/daemon-config.hpp
@@ -15,6 +15,9 @@
#define VSOMEIP_KEY_PORT "--port"
#define VSOMEIP_VALUE_PORT_DEFAULT 30490
+#define VSOMEIP_KEY_REGISTRY_PATH "--registry-path"
+#define VSOMEIP_VALUE_REGISTRY_PATH_DEFAULT "/tmp/vsomeipd"
+
#define VSOMEIP_KEY_VIRTUALMODE "--virtual"
#define VSOMEIP_VALUE_IS_VIRTUAL_MODE_DEFAULT false
diff --git a/vsomeip/include/vsomeip/service_discovery/internal/daemon.hpp b/vsomeip/include/vsomeip/service_discovery/internal/daemon.hpp
index a467465..ad03fc0 100755
--- a/vsomeip/include/vsomeip/service_discovery/internal/daemon.hpp
+++ b/vsomeip/include/vsomeip/service_discovery/internal/daemon.hpp
@@ -13,6 +13,7 @@
#define VSOMEIP_DAEMON_DAEMON_HPP
#include <boost/asio/io_service.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
@@ -20,7 +21,8 @@
#include <vsomeip/endpoint.hpp>
#include <vsomeip/receiver.hpp>
#include <vsomeip/service_discovery/service_entry.hpp>
-#include <vsomeip/service_discovery/internal/registry.hpp>
+#include <vsomeip/service_discovery/internal/service_info.hpp>
+#include <vsomeip/service_discovery/internal/service_registry.hpp>
namespace vsomeip {
@@ -42,11 +44,13 @@
daemon();
void run_service();
void consume_request(const entry &, endpoint *);
+ void send_offer_service(service_info *, endpoint *);
- void send_offer_service(registry::service *, endpoint *);
+ void set_loggers(const std::string& _logger_configuration);
private:
- registry registry_;
+ service_registry *registry_;
+ std::string registry_path_;
vsomeip::service *tcp_daemon_;
vsomeip::service *udp_daemon_;
@@ -56,11 +60,17 @@
bool is_virtual_mode_;
bool is_running_;
+ // Loggers
+ bool use_console_;
+ bool use_file_;
+ bool use_dlt_;
+
boost::log::sources::severity_logger<
boost::log::trivial::severity_level > log_;
boost::log::trivial::severity_level loglevel_;
boost::asio::io_service is_;
+ boost::asio::local::stream_protocol::acceptor acceptor_;
};
} // namespace service_discovery
diff --git a/vsomeip/include/vsomeip/service_discovery/internal/registry.hpp b/vsomeip/include/vsomeip/service_discovery/internal/registry.hpp
deleted file mode 100755
index 77c7ca5..0000000
--- a/vsomeip/include/vsomeip/service_discovery/internal/registry.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// registry.hpp
-//
-// Author: Lutz Bichler
-//
-// This file is part of the BMW Some/IP implementation.
-//
-// Copyright © 2013, 2014 Bayerische Motoren Werke AG (BMW).
-// All rights reserved.
-//
-
-#ifndef VSOMEIP_SERVICE_DISCOVERY_INTERNAL_REGISTRY_HPP
-#define VSOMEIP_SERVICE_DISCOVERY_INTERNAL_REGISTRY_HPP
-
-#include <map>
-
-#include <vsomeip/primitive_types.hpp>
-
-namespace vsomeip {
-namespace service_discovery {
-
-class registry {
-public:
- class service {
- public:
- service_id service_id_;
- instance_id instance_id_;
- };
-
- service * add(service_id _service_id, instance_id _instance_id);
- service * search(service_id _service_id, instance_id _instance_id);
-
-private:
- std::map< service_id,
- std::map< instance_id,
- service > > data_;
-};
-
-} // namespace service_discovery
-} // namespace vsomeip
-
-#endif // VSOMEIP_SERVICE_DISCOVERY_INTERNAL_REGISTRY_HPP
diff --git a/vsomeip/include/vsomeip/service_discovery/internal/service_impl.hpp b/vsomeip/include/vsomeip/service_discovery/internal/service_impl.hpp
index 2159324..1895109 100644
--- a/vsomeip/include/vsomeip/service_discovery/internal/service_impl.hpp
+++ b/vsomeip/include/vsomeip/service_discovery/internal/service_impl.hpp
@@ -12,12 +12,19 @@
#ifndef VSOMEIP_SERVICE_DISCOVERY_INTERNAL_SERVICE_IMPL_HPP
#define VSOMEIP_SERVICE_DISCOVERY_INTERNAL_SERVICE_IMPL_HPP
+#include <deque>
+#include <map>
+#include <vector>
+
#include <boost/variant.hpp>
#include <boost/asio/io_service.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
+#include <vsomeip/internal/statistics_owner_impl.hpp>
#include <vsomeip/service_discovery/service.hpp>
#include <vsomeip/service_discovery/internal/events.hpp>
-#include <vsomeip/internal/statistics_owner_impl.hpp>
+#include <vsomeip/service_discovery/internal/service_info.hpp>
+
namespace vsomeip {
namespace service_discovery {
@@ -29,7 +36,7 @@
#endif
{
public:
- service_impl(vsomeip::service *_delegate);
+ service_impl(vsomeip::service *_delegate, boost::asio::io_service &_is);
virtual ~service_impl();
bool register_service(service_id _service, instance_id _instance);
@@ -49,14 +56,22 @@
void enable_magic_cookies();
void disable_magic_cookies();
-
-
bool send(const message_base *_message, bool _flush);
bool send(const uint8_t *_data, uint32_t _length, endpoint *_target, bool _flush);
bool flush(endpoint *_target);
private:
vsomeip::service *delegate_;
+ std::map< service_id, service_info > services_;
+ std::deque<std::vector<uint8_t>> command_queue_;
+
+ boost::asio::local::stream_protocol::socket socket_;
+
+private:
+ void connect();
+ void send_command(const uint8_t *_command, uint32_t _size);
+ void sent_command(boost::system::error_code const &_error, std::size_t _bytes);
+ void announce(service_info &_info);
};
} // namespace service_discovery
diff --git a/vsomeip/include/vsomeip/service_discovery/internal/service_info.hpp b/vsomeip/include/vsomeip/service_discovery/internal/service_info.hpp
new file mode 100644
index 0000000..10b3438
--- /dev/null
+++ b/vsomeip/include/vsomeip/service_discovery/internal/service_info.hpp
@@ -0,0 +1,41 @@
+//
+// service_info.hpp
+//
+// Author: Lutz Bichler <Lutz.Bichler@bmwgroup.com>
+//
+// This file is part of the BMW Some/IP implementation.
+//
+// Copyright © 2013, 2014 Bayerische Motoren Werke AG (BMW).
+// All rights reserved.
+//
+
+#ifndef VSOMEIP_SERVICE_DISCOVERY_INTERNAL_SERVICE_INFO_HPP
+#define VSOMEIP_SERVICE_DISCOVERY_INTERNAL_SERVICE_INFO_HPP
+
+#include <vsomeip/primitive_types.hpp>
+
+namespace vsomeip {
+namespace service_discovery {
+
+struct service_info {
+ service_id service_;
+ instance_id instance_;
+ major_version major_version_;
+ minor_version minor_version_;
+ time_to_live time_to_live_;
+
+ void print() {
+ std::cout << "[" << std::hex << service_
+ << " " << instance_
+ << " " << (int)major_version_
+ << "." << minor_version_
+ << " " << time_to_live_ << "]"
+ << std::endl;
+ }
+};
+
+} // namespace service_discovery
+} // namespace vsomeip
+
+
+#endif // VSOMEIP_SERVICE_DISCOVERY_INTERNAL_SERVICE_INFO_HPP
diff --git a/vsomeip/include/vsomeip/service_discovery/internal/service_registration.hpp b/vsomeip/include/vsomeip/service_discovery/internal/service_registration.hpp
deleted file mode 100644
index 3a962fb..0000000
--- a/vsomeip/include/vsomeip/service_discovery/internal/service_registration.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// service_registration.hpp
-//
-// Author: Lutz Bichler <Lutz.Bichler@bmwgroup.com>
-//
-// This file is part of the BMW Some/IP implementation.
-//
-// Copyright © 2013, 2014 Bayerische Motoren Werke AG (BMW).
-// All rights reserved.
-//
-
-#ifndef VSOMEIP_SERVICE_REGISTRATION_HPP
-#define VSOMEIP_SERVICE_REGISTRATION_HPP
-
-#include <boost/shared_ptr.hpp>
-
-namespace vsomeip {
-namespace service_discovery {
-
-class service_registration {
-public:
- service_registration();
-
- void start();
- void stop();
- void process();
-
-private:
- struct state_machine;
- boost::shared_ptr< state_machine > state_machine_;
-};
-
-} // namespace service_discovery
-} // namespace vsomeip
-
-#endif // VSOMEIP_SERVICE_INSTANCE_HPP
diff --git a/vsomeip/include/vsomeip/service_discovery/internal/service_registry.hpp b/vsomeip/include/vsomeip/service_discovery/internal/service_registry.hpp
new file mode 100644
index 0000000..b916975
--- /dev/null
+++ b/vsomeip/include/vsomeip/service_discovery/internal/service_registry.hpp
@@ -0,0 +1,67 @@
+//
+// service_registration.hpp
+//
+// Author: Lutz Bichler <Lutz.Bichler@bmwgroup.com>
+//
+// This file is part of the BMW Some/IP implementation.
+//
+// Copyright © 2013, 2014 Bayerische Motoren Werke AG (BMW).
+// All rights reserved.
+//
+
+#ifndef VSOMEIP_SERVICE_REGISTRATION_HPP
+#define VSOMEIP_SERVICE_REGISTRATION_HPP
+
+#include <boost/array.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#include <vsomeip/service_discovery/internal/service_info.hpp>
+
+namespace vsomeip {
+namespace service_discovery {
+
+class service_registry
+{
+public:
+ class session
+ : public boost::enable_shared_from_this<session> {
+ public:
+ session(boost::asio::io_service &_is);
+ boost::asio::local::stream_protocol::socket & get_socket();
+ void start();
+ void receive(const boost::system::error_code &_error,
+ size_t _transferred_bytes);
+ void consume_message();
+
+ private:
+ boost::asio::local::stream_protocol::socket socket_;
+ boost::array<uint8_t, 10> data_;
+ std::vector<uint8_t> message_;
+ };
+
+ typedef boost::shared_ptr<session> session_ptr;
+
+public:
+ service_registry(boost::asio::io_service &_is,
+ const std::string &_location);
+ void handle_accept(session_ptr _session,
+ const boost::system::error_code &_error);
+
+ service_info * add(service_id _service, instance_id _instance);
+ void remove(service_id _service, instance_id _instance);
+ service_info * find(service_id _service, instance_id _instance);
+
+private:
+ std::map<service_id,
+ std::map<instance_id,
+ service_info>> data_;
+
+ boost::asio::io_service &is_;
+ boost::asio::local::stream_protocol::acceptor acceptor_;
+};
+
+} // namespace service_discovery
+} // namespace vsomeip
+
+#endif // VSOMEIP_SERVICE_INSTANCE_HPP
diff --git a/vsomeip/src/daemon/daemon.cpp b/vsomeip/src/daemon/daemon.cpp
index 38845e1..ddf950b 100755
--- a/vsomeip/src/daemon/daemon.cpp
+++ b/vsomeip/src/daemon/daemon.cpp
@@ -12,6 +12,7 @@
#include <algorithm>
#include <fstream>
+#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
@@ -34,7 +35,6 @@
#include <vsomeip/service_discovery/service_entry.hpp>
#include <vsomeip/service_discovery/internal/daemon-config.hpp>
#include <vsomeip/service_discovery/internal/daemon.hpp>
-#include <vsomeip/service_discovery/internal/service_registration.hpp>
namespace options = boost::program_options;
namespace logging = boost::log;
@@ -57,41 +57,35 @@
return &daemon__;
}
-daemon::daemon() {
+daemon::daemon()
+ : acceptor_(is_) {
port_ = VSOMEIP_VALUE_PORT_DEFAULT;
+ registry_path_ = VSOMEIP_VALUE_REGISTRY_PATH_DEFAULT;
loglevel_ = info;
is_virtual_mode_ = VSOMEIP_VALUE_IS_VIRTUAL_MODE_DEFAULT;
- is_service_discovery_mode_
- = VSOMEIP_VALUE_IS_SERVICE_DISCOVERY_MODE_DEFAULT;
+ is_service_discovery_mode_ =
+ VSOMEIP_VALUE_IS_SERVICE_DISCOVERY_MODE_DEFAULT;
}
void daemon::init(int argc, char **argv) {
// logging first
logging::add_common_attributes();
- auto daemon_log_format
- = expressions::stream <<
- expressions::format_date_time< boost::posix_time::ptime >(
- "TimeStamp", "%Y-%m-%d %H:%M:%S.%f") <<
- " [" <<
- expressions::attr< severity_level >("Severity") <<
- "] " <<
- expressions::smessage;
+ auto daemon_log_format = expressions::stream
+ << expressions::format_date_time<boost::posix_time::ptime>(
+ "TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " ["
+ << expressions::attr<severity_level>("Severity") << "] "
+ << expressions::smessage;
- logging::add_console_log(
- std::clog,
- keywords::filter = severity >= loglevel_,
- keywords::format = daemon_log_format
- );
-
- logging::add_file_log(
- keywords::file_name = "vsomeipd_%N.log",
+ logging::add_console_log(std::clog,
+ keywords::filter = severity >= loglevel_, keywords::format =
+ daemon_log_format);
+ logging::add_file_log(keywords::file_name = "vsomeipd_%N.log",
keywords::rotation_size = 10 * 1024 * 1024,
- keywords::time_based_rotation
- = logging::sinks::file::rotation_at_time_point(0, 0, 0),
- keywords::filter = severity >= loglevel_,
- keywords::format = daemon_log_format
- );
+ keywords::time_based_rotation =
+ logging::sinks::file::rotation_at_time_point(0, 0, 0),
+ keywords::filter = severity >= loglevel_, keywords::format =
+ daemon_log_format);
boost::log::core::get()->set_filter(severity >= info);
@@ -110,36 +104,42 @@
"virtual_mode_enabled", options::value<bool>(),
"Enable/Disable virtual mode by vsomeip daemon");
- options::store(
- options::parse_command_line(argc, argv, valid_options),
+ options::store(options::parse_command_line(argc, argv, valid_options),
commandline_configuration);
options::notify(commandline_configuration);
}
catch (...) {
- BOOST_LOG_SEV(log_, error)
- << "Command line configuration (partly) invalid.";
+ BOOST_LOG_SEV(log_, error)<< "Command line configuration (partly) invalid.";
}
std::string configuration_path(VSOMEIP_DEFAULT_CONFIGURATION_FILE);
if (commandline_configuration.count("config")) {
- configuration_path
- = commandline_configuration["config"].as< std::string >();
+ configuration_path =
+ commandline_configuration["config"].as<std::string>();
}
- BOOST_LOG_SEV(log_, info) << "Using configuration file \""
- << configuration_path << "\"";
+ BOOST_LOG_SEV(log_, info)<< "Using configuration file \""
+ << configuration_path << "\"";
options::variables_map configuration;
options::options_description configuration_description;
- configuration_description.add_options()("someip.daemon.loglevel",
- options::value<std::string>(),
- "Log level to be used by vsomeip daemon")("someip.daemon.port",
- options::value<int>(), "IP port to be used by vsomeip daemon")(
- "someip.daemon.service_discovery_enabled", options::value<bool>(),
- "Enable service discovery by vsomeip daemon")(
- "someip.daemon.virtual_mode_enabled", options::value<bool>(),
- "Enable virtual mode by vsomeip daemon");
+ configuration_description.add_options()
+ ( "someip.daemon.loglevel",
+ options::value<std::string>(),
+ "Log level to be used by vsomeip daemon" )
+ ( "someip.daemon.logger",
+ options::value<std::string>(),
+ "Logger(s) to be used" )
+ ( "someip.daemon.port",
+ options::value<int>(),
+ "IP port to be used by vsomeip daemon" )
+ ( "someip.daemon.service_discovery_enabled",
+ options::value<bool>(),
+ "Enable service discovery by vsomeip daemon" )
+ ( "someip.daemon.virtual_mode_enabled",
+ options::value<bool>(),
+ "Enable virtual mode by vsomeip daemon" );
std::ifstream configuration_file;
@@ -147,51 +147,55 @@
if (configuration_file.is_open()) {
try {
- options::store(options::parse_config_file(
- configuration_file,
- configuration_description, true),
- configuration);
+ options::store(
+ options::parse_config_file(configuration_file,
+ configuration_description, true), configuration);
options::notify(configuration);
}
catch (...) {
BOOST_LOG_SEV(log_, error)
- << "Command line configuration (partly) invalid.";
+ << "Command line configuration (partly) invalid.";
+ }
+
+ if (configuration.count("someip.daemon.logger")) {
+ set_loggers(configuration["someip.daemon.logger"].as< std::string >());
}
if (configuration.count("someip.daemon.loglevel"))
- loglevel_ = loglevel_from_string(
- configuration["someip.daemon.loglevel"].
- as< std::string>());
+ loglevel_ = loglevel_from_string(
+ configuration["someip.daemon.loglevel"].
+ as< std::string>());
if (configuration.count("someip.daemon.port"))
- port_ = configuration["someip.daemon.port"].as< int >();
+ port_ = configuration["someip.daemon.port"].as<int>();
+
+ if (configuration.count("someip.daemon.registry"))
+ registry_path_ = configuration["someip.daemon.registry"].as<std::string>();
if (configuration.count("someip.daemon.virtual_mode_enabled"))
- is_virtual_mode_
- = configuration["someip.daemon.virtual_mode_enabled"].as< bool >();
+ is_virtual_mode_ = configuration["someip.daemon.virtual_mode_enabled"].as< bool >();
if (configuration.count("someip.daemon.service_discovery_enabled"))
- is_service_discovery_mode_
- = configuration["someip.daemon.service_discovery_enabled"].as< bool >();
+ is_service_discovery_mode_ = configuration["someip.daemon.service_discovery_enabled"].as< bool >();
} else {
BOOST_LOG_SEV(log_, error)
- << "Could not open configuration file \""
- << configuration_path << "\"";
+ << "Could not open configuration file \""
+ << configuration_path << "\"";
}
// Command line overwrites configuration file
if (commandline_configuration.count("log_level"))
- loglevel_ = loglevel_from_string(
- configuration["someip.daemon.loglevel"].
- as< std::string>());
+ loglevel_ = loglevel_from_string(
+ configuration["someip.daemon.loglevel"].as<std::string>());
if (commandline_configuration.count("port"))
port_ = commandline_configuration["port"].as<int>();
if (commandline_configuration.count("virtual_mode_enabled"))
- is_virtual_mode_ = commandline_configuration["virtual_mode_enabled"].as<bool>();
+ is_virtual_mode_ = commandline_configuration["virtual_mode_enabled"].as<
+ bool>();
if (commandline_configuration.count("service_discovery_enabled"))
is_service_discovery_mode_ =
@@ -201,9 +205,8 @@
void daemon::start() {
// Check whether the daemon makes any sense
if (!is_virtual_mode_ && !is_service_discovery_mode_) {
- BOOST_LOG_SEV(log_, error)
- << "Neither virtual mode nor service discovery "
- "mode active, exiting.";
+ BOOST_LOG_SEV(log_, error)<< "Neither virtual mode nor service discovery "
+ "mode active, exiting.";
stop();
} else {
BOOST_LOG_SEV(log_, info) << "Using port " << port_;
@@ -217,30 +220,31 @@
BOOST_LOG_SEV(log_, info) << "Service discovery mode: on";
}
+ // Enable internal registry interface
+ ::unlink(registry_path_.c_str());
+ registry_ = new service_registry(is_, registry_path_);
+
// create a UDP & a TCP service as we want to listen to a port and
// send/receive Some/IP messages
endpoint *udp_endpoint = new endpoint_impl("127.0.0.1", port_,
- ip_protocol::UDP, ip_version::V4);
+ ip_protocol::UDP, ip_version::V4);
endpoint *tcp_endpoint = new endpoint_impl("127.0.0.1", port_,
- ip_protocol::TCP, ip_version::V4);
+ ip_protocol::TCP, ip_version::V4);
factory *default_factory = factory::get_default_factory();
- // DEMO
- registry_.add(0x2233, 0x12);
-
udp_daemon_
- = new udp_service_impl(default_factory, udp_endpoint, is_);
+ = new udp_service_impl(default_factory, udp_endpoint, is_);
tcp_daemon_
- = new tcp_service_impl(default_factory, tcp_endpoint, is_);
+ = new tcp_service_impl(default_factory, tcp_endpoint, is_);
tcp_daemon_->register_for(this,
- SERVICE_DISCOVERY_SERVICE_ID,
- SERVICE_DISCOVERY_METHOD_ID);
+ SERVICE_DISCOVERY_SERVICE_ID,
+ SERVICE_DISCOVERY_METHOD_ID);
udp_daemon_->register_for(this,
- SERVICE_DISCOVERY_SERVICE_ID,
- SERVICE_DISCOVERY_METHOD_ID);
+ SERVICE_DISCOVERY_SERVICE_ID,
+ SERVICE_DISCOVERY_METHOD_ID);
udp_daemon_->start();
tcp_daemon_->start();
@@ -259,53 +263,66 @@
void daemon::run_service() {
while (is_running_) {
- BOOST_LOG_SEV(log_, info) << "(Re-)Starting service";
+ BOOST_LOG_SEV(log_, info)<< "(Re-)Starting service";
is_.run();
}
}
void daemon::receive(const message_base *_message) {
- const message *requests = dynamic_cast< const message * > (_message);
+ const message *requests = dynamic_cast<const message *>(_message);
if (0 != requests) {
const std::vector<entry *>& entries = requests->get_entries();
for (auto e : entries) {
consume_request(*e, _message->get_endpoint());
}
} else {
- BOOST_LOG_SEV(log_, warning)
- << "Received unstructued Some/IP service discovery message!";
+ BOOST_LOG_SEV(log_, warning)<< "Received unstructued Some/IP service discovery message!";
}
}
void daemon::consume_request(const entry &_entry, endpoint *_target) {
if (_entry.get_type() == entry_type::FIND_SERVICE) {
const service_entry& s = reinterpret_cast<const service_entry &>(_entry);
- registry::service *found = registry_.search(s.get_service_id(), s.get_instance_id());
+ service_info *found = registry_->find(s.get_service_id(), s.get_instance_id());
if (found) {
send_offer_service(found, _target);
} else {
- BOOST_LOG_SEV(log_, warning)
- << "Service " << std::hex
- << (int)s.get_service_id()
- << "."
- << (int)s.get_instance_id()
- << " not available!";
+ BOOST_LOG_SEV(log_, warning)<< "Service " << std::hex
+ << (int)s.get_service_id()
+ << "."
+ << (int)s.get_instance_id()
+ << " not available!";
}
}
}
-void daemon::send_offer_service(registry::service *_service, endpoint *_target) {
+void daemon::send_offer_service(service_info *_service, endpoint *_target) {
boost::shared_ptr<message> m(
- factory::get_default_factory()->create_service_discovery_message());
+ factory::get_default_factory()->create_service_discovery_message());
m->set_endpoint(_target);
service_entry& s = m->create_service_entry();
s.set_type(entry_type::OFFER_SERVICE);
- s.set_service_id(_service->service_id_);
- s.set_instance_id(_service->instance_id_);
+ s.set_service_id(_service->service_);
+ s.set_instance_id(_service->instance_);
udp_daemon_->send(m.get());
}
+void daemon::set_loggers(const std::string &_logger_configuration) {
+ std::string logger_configuration(_logger_configuration);
+ boost::algorithm::trim(logger_configuration);
+
+ std::vector<std::string> loggers;
+ boost::split(loggers, logger_configuration, boost::is_any_of("|"));
+
+ for (auto i: loggers) {
+ boost::algorithm::trim(i);
+ if ("console" == i) use_console_ = true;
+ else if ("file" == i) use_file_ = true;
+ else if ("dlt" == i) use_dlt_ = true;
+ }
+}
+
severity_level loglevel_from_string(const std::string &_loglevel) {
if (_loglevel == "info")
diff --git a/vsomeip/src/daemon/registry.cpp b/vsomeip/src/daemon/registry.cpp
deleted file mode 100755
index f3f9e8a..0000000
--- a/vsomeip/src/daemon/registry.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// registration.cpp
-//
-// Author: Lutz Bichler
-//
-// This file is part of the BMW Some/IP implementation.
-//
-// Copyright © 2013, 2014 Bayerische Motoren Werke AG (BMW).
-// All rights reserved.
-//
-
-#include <vsomeip/service_discovery/internal/registry.hpp>
-
-namespace vsomeip {
-namespace service_discovery {
-
-registry::service * registry::add(service_id _service_id, instance_id _instance_id) {
- registry::service *found_service_instance = search(_service_id, _instance_id);
- if (found_service_instance)
- return found_service_instance;
-
- registry::service s;
- s.service_id_ = _service_id;
- s.instance_id_ = _instance_id;
- std::map< instance_id, service >& found_service = data_[_service_id];
- found_service[_instance_id] = s;
-
- return &found_service[_instance_id];
-}
-
-registry::service * registry::search(service_id _service_id, instance_id _instance_id) {
- auto found_service = data_.find(_service_id);
- if (found_service == data_.end())
- return 0;
-
- if (_instance_id == 0xFFFF) {
- return &(found_service->second.begin()->second);
- }
-
- auto found_instance = found_service->second.find(_instance_id);
- if (found_instance == found_service->second.end())
- return 0;
-
- return &found_instance->second;
-}
-
-} // namespace service_discovery
-} // namespace vsomeip
diff --git a/vsomeip/src/service_discovery/service_behavior_impl.cpp b/vsomeip/src/daemon/service_behavior_impl.cpp
similarity index 100%
rename from vsomeip/src/service_discovery/service_behavior_impl.cpp
rename to vsomeip/src/daemon/service_behavior_impl.cpp
diff --git a/vsomeip/src/daemon/service_registration.cpp b/vsomeip/src/daemon/service_registration.cpp
deleted file mode 100644
index 7a61d03..0000000
--- a/vsomeip/src/daemon/service_registration.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-//
-// state_machine.cpp
-//
-// Author: Lutz Bichler <Lutz.Bichler@bmwgroup.com>
-//
-// This file is part of the BMW Some/IP implementation.
-//
-// Copyright © 2013, 2014 Bayerische Motoren Werke AG (BMW).
-// All rights reserved.
-//
-
-#include <boost/msm/front/state_machine_def.hpp>
-#include <boost/msm/back/state_machine.hpp>
-
-#include <vsomeip/service_discovery/internal/events.hpp>
-#include <vsomeip/service_discovery/internal/service_registration.hpp>
-
-namespace vsomeip {
-namespace service_discovery {
-
-namespace msm = boost::msm;
-namespace mpl = boost::mpl;
-using namespace boost::msm::front;
-
-////////////////////////////////////////////////////////
-/////////// Implementation of statechart /////////
-////////////////////////////////////////////////////////
-
-// Top-level state machine
-struct service_registration_state_machine_def
- : public msm::front::state_machine_def<service_registration_state_machine_def> {
-
- // States
- struct initial: public msm::front::entry_pseudo_state<0> {
- template <class Event, class Fsm>
- void on_entry(Event const &, Fsm &fsm)
- { std::cout << "Entering Initial" << std::endl; }
- template <class Event, class Fsm>
- void on_exit(Event const &, Fsm &fsm)
- { std::cout << "Exiting Initial" << std::endl; }
- };
- struct not_ready: public msm::front::state<> {
- template <class Event, class Fsm>
- void on_entry(Event const &, Fsm &fsm)
- { std::cout << "Entering NotReady" << std::endl; }
- template <class Event, class Fsm>
- void on_exit(Event const &, Fsm &fsm)
- { std::cout << "Exiting NotReady" << std::endl; }
- };
-
- struct ready: public msm::front::state_machine_def<ready> {
- template <class Event, class Fsm>
- void on_entry(Event const &, Fsm &fsm)
- { std::cout << "Entering Ready" << std::endl; }
- template <class Event, class Fsm>
- void on_exit(Event const &, Fsm &fsm)
- { std::cout << "Exiting Ready" << std::endl; }
-
- // States
- struct initial: public msm::front::entry_pseudo_state<0> {
- };
- struct waiting: public msm::front::state<> {
- };
- struct repeating: public msm::front::state<> {
- };
- struct announcing: public msm::front::state<> {
- };
-
- // Determine initial state
- typedef initial initial_state;
-
- // Members
- uint32_t repetitions_max_;
-
- // Guards
- bool is_repeating(ev_timer_expired const &_event) {
- return repetitions_max_ > 0;
- }
-
- bool is_not_repeating(ev_timer_expired const &_event) {
- return repetitions_max_ == 0;
- }
-
- // Actions
- void send_offer_service(ev_timer_expired const &_event) {
- // TODO: send message
- }
-
- void send_delayed_offer_service(ev_find_service const &_event) {
- // TODO: check timing and schedule sending of message
- }
-
- // Transitions
- struct transition_table: mpl::vector<
- row<waiting, ev_timer_expired, announcing,
- &ready::send_offer_service, &ready::is_not_repeating>,
- row<waiting, ev_timer_expired, repeating,
- &ready::send_offer_service, &ready::is_repeating>,
- a_row<repeating, ev_find_service, repeating,
- &ready::send_delayed_offer_service>,
- row<repeating, ev_timer_expired, repeating,
- &ready::send_offer_service, &ready::is_repeating>,
- g_row<repeating, ev_timer_expired, announcing,
- &ready::is_not_repeating>,
- a_row<announcing, ev_timer_expired, announcing,
- &ready::send_offer_service>,
- a_row<announcing, ev_find_service, announcing,
- &ready::send_delayed_offer_service> > {
- };
- };
-
- // Determine initial state
- typedef initial initial_state;
-
- // Members
- bool is_daemon_up_;
- bool is_service_up_;
- bool is_requested_;
-
- // Guards
- bool is_not_ready(none const &_no_event) {
- return (!is_daemon_up_ || !is_service_up_);
- }
-
- bool is_ready(none const &_no_event) {
- return !(is_not_ready(_no_event));
- }
-
- bool is_not_ready(ev_service_status_change const &_event) {
- is_service_up_ = _event.is_up_;
- return (!is_daemon_up_ || !is_service_up_);
- }
-
- bool is_ready(ev_service_status_change const &_event) {
- return !(is_not_ready(_event));
- }
-
- bool is_not_ready(ev_daemon_status_change const &_event) {
- is_daemon_up_ = _event.is_up_;
- return (!is_daemon_up_ || !is_service_up_);
- }
-
- bool is_ready(ev_daemon_status_change const &_event) {
- return !(is_not_ready(_event));
- }
-
- // Actions
- void handle_service_down(ev_daemon_status_change const &_event) {
- // TODO: clear_all_timers();
- }
- ;
-
- void handle_service_down(ev_service_status_change const &_event) {
- if (!is_service_up_) {
- // TODO: send "StopOfferService" message!
- }
-
- // TODO: clear_all_timers();
- };
-
- // Transitions
- struct transition_table: mpl::vector<
- g_row<initial, none, ready,
- &service_registration_state_machine_def::is_ready>,
- g_row<initial, none, not_ready,
- &service_registration_state_machine_def::is_not_ready>,
- g_row<not_ready, ev_daemon_status_change, ready,
- &service_registration_state_machine_def::is_ready>,
- g_row<not_ready, ev_service_status_change, ready,
- &service_registration_state_machine_def::is_ready>,
- row<ready, ev_daemon_status_change, not_ready,
- &service_registration_state_machine_def::handle_service_down,
- &service_registration_state_machine_def::is_not_ready>,
- row<ready, ev_service_status_change, not_ready,
- &service_registration_state_machine_def::handle_service_down,
- &service_registration_state_machine_def::is_not_ready> > {
- };
-
- template <class Fsm, class Event>
- void no_transition(Event const &_event, Fsm &_machine, int state) {
- std::cout << "No transition from state " << state << " on event " << typeid(_event).name() << std::endl;
- }
-};
-
-struct service_registration::state_machine
- : msm::back::state_machine< service_registration_state_machine_def > {
-};
-
-////////////////////////////////////////////////////////
-/////////// Implementation of member functions /////////
-////////////////////////////////////////////////////////
-service_registration::service_registration()
- : state_machine_(new state_machine) {
- state_machine_->is_daemon_up_ = false;
- state_machine_->is_service_up_ = false;
-}
-
-void service_registration::start() {
- state_machine_->start();
-}
-
-void service_registration::stop() {
- state_machine_->stop();
-}
-
-void service_registration::process() {
- state_machine_->process_event(none());
-}
-
-} // namespace service_discovery
-} // namespace vsomeip
-
diff --git a/vsomeip/src/daemon/service_registry.cpp b/vsomeip/src/daemon/service_registry.cpp
new file mode 100644
index 0000000..8ac096e
--- /dev/null
+++ b/vsomeip/src/daemon/service_registry.cpp
@@ -0,0 +1,164 @@
+//
+// service_registry.cpp
+//
+// Author: Lutz Bichler <Lutz.Bichler@bmwgroup.com>
+//
+// This file is part of the BMW Some/IP implementation.
+//
+// Copyright © 2013, 2014 Bayerische Motoren Werke AG (BMW).
+// All rights reserved.
+//
+
+#include <iomanip>
+
+#include <boost/asio/placeholders.hpp>
+#include <boost/bind.hpp>
+
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/internal/byteorder.hpp>
+#include <vsomeip/service_discovery/internal/service_registry.hpp>
+
+using boost::asio::local::stream_protocol;
+
+namespace vsomeip {
+namespace service_discovery {
+
+service_registry::session::session(boost::asio::io_service &_is)
+ : socket_(_is) {
+}
+
+stream_protocol::socket & service_registry::session::get_socket() {
+ return socket_;
+}
+
+void service_registry::session::start() {
+ socket_.async_read_some(boost::asio::buffer(data_),
+ boost::bind(&session::receive,
+ shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+}
+
+void service_registry::session::receive(
+ const boost::system::error_code &_error,
+ size_t _transferred_bytes) {
+
+ if (!_error) {
+ message_.insert(message_.end(), data_.c_array(), data_.c_array() + _transferred_bytes);
+ consume_message();
+ start();
+ } else {
+ // TODO: add log message here!
+ }
+}
+
+service_registry::service_registry(
+ boost::asio::io_service &_is, const std::string &_location)
+ : is_(_is), acceptor_(_is, stream_protocol::endpoint(_location)) {
+
+ session_ptr s(new session(is_));
+ acceptor_.async_accept(
+ s->get_socket(),
+ boost::bind(&service_registry::handle_accept,
+ this,
+ s,
+ boost::asio::placeholders::error));
+}
+
+void service_registry::handle_accept(
+ session_ptr _session,
+ const boost::system::error_code &_error) {
+ if (!_error) {
+ _session->start();
+ _session.reset(new session(is_));
+ acceptor_.async_accept(
+ _session->get_socket(),
+ boost::bind(&service_registry::handle_accept,
+ this,
+ _session,
+ boost::asio::placeholders::error));
+ }
+}
+
+void service_registry::session::consume_message() {
+ int i = 0;
+ bool is_complete = false;
+
+ // Search start tag
+ while (i+1 < message_.size()) {
+ if (message_[i] == 0xFE && message_[i+1] == 0xED) {
+ i += 2;
+ break;
+ }
+ i++;
+ }
+
+ // Read command
+ if (i+1 < message_.size()) {
+ uint8_t command = message_[i++];
+ switch (command) {
+ case 0:
+ if (i + 13 < message_.size()) {
+ service_info info;
+ info.service_ = VSOMEIP_BYTES_TO_WORD(message_[i], message_[i+1]);
+ info.instance_ = VSOMEIP_BYTES_TO_WORD(message_[i+2], message_[i+3]);
+ info.major_version_ = message_[i+4];
+ info.minor_version_ = VSOMEIP_BYTES_TO_LONG(message_[i+5], message_[i+6],
+ message_[i+7], message_[i+8]);
+ info.time_to_live_ = VSOMEIP_BYTES_TO_LONG(
+ 0, message_[i+9],
+ message_[i+10], message_[i+11]);
+
+ info.print();
+
+ i += 14;
+ is_complete = true;
+ }
+ break;
+ default:
+ // TODO: log "unknown command"
+ break;
+ }
+ }
+
+ if (is_complete)
+ message_.erase(message_.begin(), message_.begin() + i);
+}
+
+service_info * service_registry::add(service_id _service, instance_id _instance) {
+ service_info *found_service_instance = find(_service, _instance);
+ if (found_service_instance)
+ return found_service_instance;
+
+ service_info s;
+ s.service_ = _service;
+ s.instance_ = _instance;
+ std::map< instance_id, service_info >& found_service = data_[_service];
+ found_service[_instance] = s;
+
+ return &found_service[_instance];
+}
+
+void service_registry::remove(service_id _service, instance_id _instance) {
+ auto found_service = data_.find(_service);
+ data_.erase(found_service);
+}
+
+service_info * service_registry::find(service_id _service, instance_id _instance) {
+ auto found_service = data_.find(_service);
+ if (found_service == data_.end())
+ return 0;
+
+ if (_instance == 0xFFFF) {
+ return &(found_service->second.begin()->second);
+ }
+
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance == found_service->second.end())
+ return 0;
+
+ return &found_instance->second;
+}
+
+} // namespace service_discovery
+} // namespace vsomeip
diff --git a/vsomeip/src/examples/ip_service_discovery_service.cpp b/vsomeip/src/examples/ip_service_discovery_service.cpp
new file mode 100755
index 0000000..cd76972
--- /dev/null
+++ b/vsomeip/src/examples/ip_service_discovery_service.cpp
@@ -0,0 +1,47 @@
+//
+// main.cpp
+//
+// Author: Lutz Bichler
+//
+// This file is part of the BMW Some/IP implementation.
+//
+// Copyright �� 2013, 2014 Bayerische Motoren Werke AG (BMW).
+// All rights reserved.
+//
+#include <iostream>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/service_discovery/application.hpp>
+#include <vsomeip/service_discovery/factory.hpp>
+#include <vsomeip/service_discovery/service.hpp>
+
+#define REGISTER_SERVICE(S, I) \
+ std::cout << "Registered service instance (" << std::hex << S << ", " << I << ") " \
+ << (the_service->register_service(S, I) ? "succeeded." : "failed.") \
+ << std::endl;
+
+int main(int argc, char **argv) {
+
+ vsomeip::service_discovery::factory *default_factory
+ = vsomeip::service_discovery::factory::get_default_factory();
+ vsomeip::service_discovery::application *application
+ = default_factory->create_service_discovery_application();
+
+ vsomeip::endpoint *tcp_target
+ = default_factory->get_endpoint("127.0.0.1", VSOMEIP_LOWEST_VALID_PORT,
+ vsomeip::ip_protocol::TCP,
+ vsomeip::ip_version::V4);
+
+ vsomeip::service_discovery::service *the_service
+ = application->create_service_discovery_service(0x1234, 0x678, tcp_target);
+
+ REGISTER_SERVICE(0x2222, 0x3333);
+ REGISTER_SERVICE(0x2222, 0x3334);
+ REGISTER_SERVICE(0x2221, 0x3333);
+
+ the_service->start();
+ the_service->stop();
+
+ while (1) application->run();
+ return 0;
+}
diff --git a/vsomeip/src/service_discovery/application_impl.cpp b/vsomeip/src/service_discovery/application_impl.cpp
index 32e3d97..b7e1eee 100644
--- a/vsomeip/src/service_discovery/application_impl.cpp
+++ b/vsomeip/src/service_discovery/application_impl.cpp
@@ -43,18 +43,12 @@
std::map<const endpoint*, vsomeip::service*>::iterator found = services_.find(_source);
if (found == services_.end()) {
vsomeip::service * delegate = create_service(_source);
- new_service = new service_impl(delegate);
+ new_service = new service_impl(delegate, is_);
services_[_source] = new_service;
} else {
new_service = dynamic_cast<service_impl *>(found->second);
}
- if (0 != new_service) {
- new_service->register_service(_service, _instance);
- } else {
- // TODO: check for "new_service == 0" and issue an error if so
- }
-
return new_service;
}
diff --git a/vsomeip/src/service_discovery/service_impl.cpp b/vsomeip/src/service_discovery/service_impl.cpp
index 99c39fc..5558964 100644
--- a/vsomeip/src/service_discovery/service_impl.cpp
+++ b/vsomeip/src/service_discovery/service_impl.cpp
@@ -9,7 +9,11 @@
// All rights reserved.
//
+#include <boost/asio/placeholders.hpp>
+#include <boost/bind.hpp>
+
#include <vsomeip/service.hpp>
+#include <vsomeip/internal/byteorder.hpp>
#include <vsomeip/service_discovery/factory.hpp>
#include <vsomeip/service_discovery/message.hpp>
#include <vsomeip/service_discovery/service_entry.hpp>
@@ -22,8 +26,8 @@
namespace vsomeip {
namespace service_discovery {
-service_impl::service_impl(vsomeip::service *_delegate)
- : delegate_(_delegate) {
+service_impl::service_impl(vsomeip::service *_delegate, boost::asio::io_service &_is)
+ : delegate_(_delegate), socket_(_is) {
}
service_impl::~service_impl() {
@@ -31,21 +35,43 @@
}
bool service_impl::register_service(service_id _service, instance_id _instance) {
+ auto found = services_.find(_service);
+ if (found != services_.end()) {
+ return (found->second.instance_ == _instance);
+ }
+
+ struct service_info info = {
+ _service, _instance, 0xFF, 0xFFEEDDCC, 0xFFEEDD };
+ services_[_service] = info;
+
return true;
}
bool service_impl::unregister_service(service_id _service, instance_id _instance) {
+ services_.erase(_service);
return true;
}
void service_impl::start() {
delegate_->start();
+
+ connect();
+
+ // announce all the services
+ for (auto i : services_) {
+ announce(i.second);
+ }
}
void service_impl::stop() {
delegate_->stop();
}
+void service_impl::connect() {
+ boost::asio::local::stream_protocol::endpoint registry("/tmp/vsomeipd");
+ socket_.connect(registry);
+}
+
void service_impl::register_for(receiver *_receiver, service_id _service_id, method_id _method_id) {
delegate_->register_for(_receiver, _service_id, _method_id);
}
@@ -74,6 +100,52 @@
return delegate_->flush(_target);
}
+void service_impl::send_command(const uint8_t *_command, uint32_t _size) {
+ std::vector< uint8_t> command;
+ command.assign(_command, _command + _size);
+ command_queue_.push_back(command);
+ socket_.async_send(boost::asio::buffer(command_queue_.back()),
+ boost::bind(&service_impl::sent_command,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+}
+
+void service_impl::sent_command(boost::system::error_code const &_error, std::size_t _bytes) {
+ if (!_error) {
+ command_queue_.pop_front();
+ } else {
+ // TODO: log "error while sending command"
+ }
+}
+
+void service_impl::announce(service_info &_info) {
+ uint8_t command[] = { 0xFE, 0xED,
+ 0x0, // Command
+ 0x0, 0x0, // Service
+ 0x0, 0x0, // Instance
+ 0x0, // Major version
+ 0x0, 0x0, 0x0, 0x0, // Minor Version
+ 0x0, 0x0, 0x0, // Time to live
+ 0xED, 0xDA };
+
+ // On "wire" we use big endian
+ command[3] = VSOMEIP_WORD_BYTE1(_info.service_);
+ command[4] = VSOMEIP_WORD_BYTE0(_info.service_);
+ command[5] = VSOMEIP_WORD_BYTE1(_info.instance_);
+ command[6] = VSOMEIP_WORD_BYTE0(_info.instance_);
+ command[7] = _info.major_version_;
+ command[8] = VSOMEIP_LONG_BYTE3(_info.minor_version_);
+ command[9] = VSOMEIP_LONG_BYTE2(_info.minor_version_);
+ command[10] = VSOMEIP_LONG_BYTE1(_info.minor_version_);
+ command[11] = VSOMEIP_LONG_BYTE0(_info.minor_version_);
+ command[12] = VSOMEIP_LONG_BYTE2(_info.time_to_live_);
+ command[13] = VSOMEIP_LONG_BYTE1(_info.time_to_live_);
+ command[14] = VSOMEIP_LONG_BYTE0(_info.time_to_live_);
+
+ send_command(command, sizeof(command));
+}
+
} // namespace service_discovery
} // namespace vsomeip
diff --git a/vsomeip/vsomeipd.conf b/vsomeip/vsomeip.conf
similarity index 65%
rename from vsomeip/vsomeipd.conf
rename to vsomeip/vsomeip.conf
index d3d3c9c..d5afbcc 100644
--- a/vsomeip/vsomeipd.conf
+++ b/vsomeip/vsomeip.conf
@@ -3,11 +3,11 @@
###############################################################################
[someip.daemon]
-# loglevel = [fatal | error | warn | info | debug | verbose]
+# Loglevel [fatal | error | warn | info | debug | verbose]
loglevel = verbose
-# Port
-port = 38223
+# Logger [console | file | dlt]
+logger = console | file
# Service discovery?
service_discovery_enabled = true
@@ -21,12 +21,22 @@
# Maximum delay
maximum_delay = 1000
+# Port
+port = 30490
+
+# Protocol [udp.v4 | udp.v6 | tcp.v4 | tcp.v6]
+service_discovery_protocol = udp.v4
+
+# Internal registry
+registry = /tmp/vsomeipd
+
###############################################################################
# Some/IP: Client configuration
###############################################################################
[someip.client]
-service_discovery_port = 38223
+# Loglevel [fatal | error | warn | info | debug | verbose]
+loglevel = verbose
-# protocol = [udp.v4 | udp.v6 | tcp.v4 | tcp.v6]
-service_discovery_protocol = udp.v4
+# Logger [console | file | dlt]
+logger = console | file
\ No newline at end of file