blob: 3b5cebf4ca3faaa3e189949e0a872dd8b522d5fd [file] [log] [blame]
// Copyright (C) 2014 BMW Group
// Author: Lutz Bichler (lutz.bichler@bmw.de)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <vsomeip/configuration.hpp>
#include <vsomeip/logger.hpp>
#include "../include/constants.hpp"
#include "../include/ipv4_option_impl.hpp"
#include "../include/ipv6_option_impl.hpp"
#include "../include/message_impl.hpp"
#include "../include/runtime.hpp"
#include "../include/service_discovery_fsm.hpp"
#include "../include/service_discovery_host.hpp"
#include "../include/service_discovery_impl.hpp"
#include "../include/serviceentry_impl.hpp"
#include "../../endpoints/include/tcp_server_endpoint_impl.hpp"
#include "../../endpoints/include/udp_server_endpoint_impl.hpp"
#include "../../routing/include/servicegroup.hpp"
#include "../../routing/include/serviceinfo.hpp"
namespace vsomeip {
namespace sd {
service_discovery_impl::service_discovery_impl(service_discovery_host *_host) :
host_(_host), io_(_host->get_io()), default_(
std::make_shared < service_discovery_fsm > ("default", this)) {
}
service_discovery_impl::~service_discovery_impl() {
}
std::shared_ptr<configuration> service_discovery_impl::get_configuration() const {
return host_->get_configuration();
}
boost::asio::io_service & service_discovery_impl::get_io() {
return io_;
}
void service_discovery_impl::init() {
std::shared_ptr<configuration> its_configuration =
host_->get_configuration();
if (its_configuration) {
std::set < std::string > its_servicegroups =
its_configuration->get_servicegroups();
for (auto its_group : its_servicegroups) {
if (its_group != "default"
&& its_configuration->is_local_servicegroup(its_group)) {
additional_[its_group] = std::make_shared
< service_discovery_fsm > (its_group, this);
}
}
} else {
VSOMEIP_ERROR << "SD: no configuration found!";
}
host_->create_service_discovery_endpoint(
its_configuration->get_service_discovery_address(),
its_configuration->get_service_discovery_port(),
its_configuration->get_service_discovery_protocol()
);
}
void service_discovery_impl::start() {
default_->start();
for (auto &its_group : additional_) {
its_group.second->start();
}
default_->process(ev_none());
for (auto &its_group : additional_) {
its_group.second->process(ev_none());
}
}
void service_discovery_impl::stop() {
}
void service_discovery_impl::offer_service(service_t _service,
instance_t _instance) {
VSOMEIP_DEBUG << "sdi::offer_service [" << std::hex << _service << "."
<< _instance << "]";
}
void service_discovery_impl::stop_offer_service(service_t _service,
instance_t _instance) {
VSOMEIP_DEBUG << "sdi::stop_offer_service [" << std::hex << _service << "."
<< _instance << "]";
}
void service_discovery_impl::request_service(service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor,
ttl_t _ttl) {
VSOMEIP_DEBUG << "sdi::request_service [" << std::hex << _service << "."
<< _instance << "]";
auto find_service = requested_.find(_service);
if (find_service != requested_.end()) {
auto find_instance = find_service->second.find(_instance);
if (find_instance != find_service->second.end()) {
// TODO: check version and report errors
} else {
find_service->second[_instance]
= std::make_shared< serviceinfo >(_major, _minor, _ttl);
}
} else {
requested_[_service][_instance]
= std::make_shared< serviceinfo >(_major, _minor, _ttl);
}
}
void service_discovery_impl::release_service(service_t _service,
instance_t _instance) {
auto find_service = requested_.find(_service);
if (find_service != requested_.end()) {
find_service->second.erase(_instance);
}
}
void service_discovery_impl::insert_service_entries(
std::shared_ptr< message_impl > &_message, service_map_t &_services,
bool _is_offer) {
for (auto its_service : _services) {
for (auto its_instance : its_service.second) {
auto its_info = its_instance.second;
std::shared_ptr< serviceentry_impl > its_entry
= _message->create_service_entry();
if (its_entry) {
its_entry->set_type((_is_offer ?
entry_type_e::OFFER_SERVICE :
entry_type_e::FIND_SERVICE));
its_entry->set_service(its_service.first);
its_entry->set_instance(its_instance.first);
its_entry->set_major_version(its_info->get_major());
its_entry->set_minor_version(its_info->get_minor());
its_entry->set_ttl(its_info->get_ttl());
std::shared_ptr< endpoint > its_endpoint
= its_info->get_reliable_endpoint();
if (its_endpoint) {
if (its_endpoint->is_v4()) {
std::shared_ptr< ipv4_option_impl > its_option
= _message->create_ipv4_option(false);
if (its_option) {
std::vector< byte_t > its_address;
if (its_endpoint->get_address(its_address)) {
its_option->set_address(its_address);
its_option->set_port(its_endpoint->get_port());
its_option->set_udp(its_endpoint->is_udp());
its_entry->assign_option(its_option, 1);
}
}
} else {
std::shared_ptr< ipv6_option_impl > its_option
= _message->create_ipv6_option(false);
if (its_option) {
std::shared_ptr< ipv4_option_impl > its_option
= _message->create_ipv4_option(false);
if (its_option) {
std::vector< byte_t > its_address;
if (its_endpoint->get_address(its_address)) {
its_option->set_address(its_address);
its_option->set_port(its_endpoint->get_port());
its_option->set_udp(its_endpoint->is_udp());
its_entry->assign_option(its_option, 1);
}
}
}
}
}
} else {
VSOMEIP_ERROR << "Failed to create service entry.";
}
}
}
}
void service_discovery_impl::send(const std::string &_name, bool _is_announcing) {
//std::unique_lock its_lock(serializer_mutex_);
std::shared_ptr< message_impl > its_message = runtime::get()->create_message();
// TODO: optimize building of SD message (common options)
// If we are the default group and not in main phase, include "FindOffer"-entries
if (_name == "default" && !_is_announcing) {
insert_service_entries(its_message, requested_, false);
}
// Always include the "OfferService"-entries for the service group
service_map_t its_offers = host_->get_offered_services(_name);
insert_service_entries(its_message, its_offers, true);
// Serialize and send
host_->send(VSOMEIP_SD_CLIENT, its_message, true, false);
}
// Interface endpoint_host
void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
endpoint *_receiver) {
VSOMEIP_DEBUG << "sdi::on_message";
}
} // namespace sd
} // namespace vsomeip