summaryrefslogtreecommitdiff
path: root/implementation/service_discovery
diff options
context:
space:
mode:
authorJürgen Gehring <Juergen.Gehring@bmw.de>2016-09-20 03:59:53 -0700
committerJürgen Gehring <Juergen.Gehring@bmw.de>2016-09-20 03:59:53 -0700
commit273814c76be4a8f906dc053492529b8d53b9e807 (patch)
treee7160dc68fe3f478a0c5c86aaccaeb620d528b63 /implementation/service_discovery
parent4c5d160362d8693aed8abd642212e68c9778bbda (diff)
downloadvSomeIP-273814c76be4a8f906dc053492529b8d53b9e807.tar.gz
vSomeIP 2.2.42.2.4
Diffstat (limited to 'implementation/service_discovery')
-rw-r--r--implementation/service_discovery/include/configuration_option_impl.hpp2
-rw-r--r--implementation/service_discovery/include/constants.hpp2
-rw-r--r--implementation/service_discovery/include/defines.hpp16
-rwxr-xr-ximplementation/service_discovery/include/deserializer.hpp2
-rwxr-xr-ximplementation/service_discovery/include/entry_impl.hpp5
-rw-r--r--implementation/service_discovery/include/enumeration_types.hpp2
-rwxr-xr-ximplementation/service_discovery/include/eventgroupentry_impl.hpp13
-rw-r--r--implementation/service_discovery/include/fsm_base.hpp12
-rw-r--r--implementation/service_discovery/include/fsm_events.hpp21
-rw-r--r--implementation/service_discovery/include/ip_option_impl.hpp2
-rw-r--r--implementation/service_discovery/include/ipv4_option_impl.hpp2
-rw-r--r--implementation/service_discovery/include/ipv6_option_impl.hpp2
-rwxr-xr-ximplementation/service_discovery/include/load_balancing_option_impl.hpp2
-rwxr-xr-ximplementation/service_discovery/include/message_element_impl.hpp2
-rwxr-xr-ximplementation/service_discovery/include/message_impl.hpp12
-rw-r--r--implementation/service_discovery/include/option_impl.hpp2
-rw-r--r--implementation/service_discovery/include/primitive_types.hpp2
-rwxr-xr-ximplementation/service_discovery/include/protection_option_impl.hpp2
-rw-r--r--implementation/service_discovery/include/request.hpp7
-rw-r--r--implementation/service_discovery/include/runtime.hpp2
-rw-r--r--implementation/service_discovery/include/runtime_impl.hpp2
-rw-r--r--implementation/service_discovery/include/service_discovery.hpp24
-rw-r--r--implementation/service_discovery/include/service_discovery_fsm.hpp74
-rw-r--r--implementation/service_discovery/include/service_discovery_host.hpp30
-rw-r--r--implementation/service_discovery/include/service_discovery_impl.hpp157
-rw-r--r--implementation/service_discovery/include/serviceentry_impl.hpp2
-rw-r--r--implementation/service_discovery/include/subscription.hpp20
-rwxr-xr-ximplementation/service_discovery/src/configuration_option_impl.cpp50
-rw-r--r--implementation/service_discovery/src/deserializer.cpp2
-rwxr-xr-ximplementation/service_discovery/src/entry_impl.cpp31
-rwxr-xr-ximplementation/service_discovery/src/eventgroupentry_impl.cpp53
-rw-r--r--implementation/service_discovery/src/fsm_base.cpp40
-rw-r--r--implementation/service_discovery/src/ip_option_impl.cpp2
-rw-r--r--implementation/service_discovery/src/ipv4_option_impl.cpp6
-rwxr-xr-ximplementation/service_discovery/src/ipv6_option_impl.cpp6
-rwxr-xr-ximplementation/service_discovery/src/load_balancing_option_impl.cpp2
-rwxr-xr-ximplementation/service_discovery/src/message_element_impl.cpp2
-rwxr-xr-ximplementation/service_discovery/src/message_impl.cpp9
-rwxr-xr-ximplementation/service_discovery/src/option_impl.cpp2
-rwxr-xr-ximplementation/service_discovery/src/protection_option_impl.cpp2
-rw-r--r--implementation/service_discovery/src/request.cpp13
-rw-r--r--implementation/service_discovery/src/runtime.cpp2
-rw-r--r--implementation/service_discovery/src/runtime_impl.cpp2
-rw-r--r--implementation/service_discovery/src/service_discovery_fsm.cpp205
-rw-r--r--implementation/service_discovery/src/service_discovery_impl.cpp1536
-rwxr-xr-ximplementation/service_discovery/src/serviceentry_impl.cpp2
-rw-r--r--implementation/service_discovery/src/subscription.cpp30
47 files changed, 1836 insertions, 582 deletions
diff --git a/implementation/service_discovery/include/configuration_option_impl.hpp b/implementation/service_discovery/include/configuration_option_impl.hpp
index de8a97f..d2351bc 100644
--- a/implementation/service_discovery/include/configuration_option_impl.hpp
+++ b/implementation/service_discovery/include/configuration_option_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/constants.hpp b/implementation/service_discovery/include/constants.hpp
index cc476a7..01c55cb 100644
--- a/implementation/service_discovery/include/constants.hpp
+++ b/implementation/service_discovery/include/constants.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/defines.hpp b/implementation/service_discovery/include/defines.hpp
index 2d23c3c..52c7216 100644
--- a/implementation/service_discovery/include/defines.hpp
+++ b/implementation/service_discovery/include/defines.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -6,14 +6,24 @@
#ifndef VSOMEIP_SD_DEFINES_HPP
#define VSOMEIP_SD_DEFINES_HPP
+#include "../../configuration/include/internal.hpp"
+
+#define VSOMEIP_MAX_TCP_SD_PAYLOAD 4075 // Available for entries & options
+#define VSOMEIP_MAX_UDP_SD_PAYLOAD 1380
+
#define VSOMEIP_SOMEIP_SD_DATA_SIZE 12
#define VSOMEIP_SOMEIP_SD_ENTRY_SIZE 16
+#define VSOMEIP_SOMEIP_SD_IPV4_OPTION_SIZE 12
+#define VSOMEIP_SOMEIP_SD_IPV6_OPTION_SIZE 24
#define VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE 3
+#define VSOMEIP_SD_IPV4_OPTION_LENGTH 0x0009
+#define VSOMEIP_SD_IPV6_OPTION_LENGTH 0x0015
+
#define VSOMEIP_SD_SERVICE 0xFFFF
#define VSOMEIP_SD_INSTANCE 0x0000
#define VSOMEIP_SD_METHOD 0x8100
-#define VSOMEIP_SD_CLIENT 0x0000
+#define VSOMEIP_SD_CLIENT (VSOMEIP_DIAGNOSIS_ADDRESS << 8) // SIP_SD_1139
#define VSOMEIP_SD_DEFAULT_ENABLED true
@@ -25,7 +35,7 @@
#define VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX 3000
#define VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY 10
#define VSOMEIP_SD_DEFAULT_REPETITIONS_MAX 3
-#define VSOMEIP_SD_DEFAULT_TTL 5
+#define VSOMEIP_SD_DEFAULT_TTL DEFAULT_TTL
#define VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY 1000
#define VSOMEIP_SD_DEFAULT_REQUEST_RESPONSE_DELAY 2000
diff --git a/implementation/service_discovery/include/deserializer.hpp b/implementation/service_discovery/include/deserializer.hpp
index 1625e80..085bc7c 100755
--- a/implementation/service_discovery/include/deserializer.hpp
+++ b/implementation/service_discovery/include/deserializer.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/entry_impl.hpp b/implementation/service_discovery/include/entry_impl.hpp
index fde425c..25f08d2 100755
--- a/implementation/service_discovery/include/entry_impl.hpp
+++ b/implementation/service_discovery/include/entry_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -46,8 +46,7 @@ public:
void set_ttl(ttl_t _ttl);
const std::vector<uint8_t> & get_options(uint8_t _run) const;
- void assign_option(const std::shared_ptr<option_impl> &_option,
- uint8_t _run);
+ void assign_option(const std::shared_ptr<option_impl> &_option);
bool is_service_entry() const;
bool is_eventgroup_entry() const;
diff --git a/implementation/service_discovery/include/enumeration_types.hpp b/implementation/service_discovery/include/enumeration_types.hpp
index 016fdae..6fb66f2 100644
--- a/implementation/service_discovery/include/enumeration_types.hpp
+++ b/implementation/service_discovery/include/enumeration_types.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/eventgroupentry_impl.hpp b/implementation/service_discovery/include/eventgroupentry_impl.hpp
index cde7497..0eb8893 100755
--- a/implementation/service_discovery/include/eventgroupentry_impl.hpp
+++ b/implementation/service_discovery/include/eventgroupentry_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -20,11 +20,22 @@ public:
eventgroup_t get_eventgroup() const;
void set_eventgroup(eventgroup_t _eventgroup);
+ uint16_t get_reserved() const;
+ void set_reserved(uint16_t _reserved);
+
+ uint8_t get_counter() const;
+ void set_counter(uint8_t _counter);
+
bool serialize(vsomeip::serializer *_to) const;
bool deserialize(vsomeip::deserializer *_from);
private:
eventgroup_t eventgroup_;
+ uint16_t reserved_;
+
+ // counter field to differentiate parallel subscriptions on same event group
+ // 4Bit only (max 16. parralel subscriptions)
+ uint8_t counter_;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/fsm_base.hpp b/implementation/service_discovery/include/fsm_base.hpp
index 13b7158..ede92d3 100644
--- a/implementation/service_discovery/include/fsm_base.hpp
+++ b/implementation/service_discovery/include/fsm_base.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -19,15 +19,17 @@ public:
fsm_base(boost::asio::io_service &_io);
virtual ~fsm_base();
- void start_timer(uint32_t _ms);
- void stop_timer();
+ void start_timer(uint32_t _ms, bool _use_alt_timer = false);
+ void stop_timer(bool _use_alt_timer = false);
- uint32_t expired_from_now();
+ uint32_t expired_from_now(bool _use_alt_timer = false);
- virtual void timer_expired(const boost::system::error_code &_error) = 0;
+ virtual void timer_expired(const boost::system::error_code &_error,
+ bool _use_alt_timer) = 0;
private:
boost::asio::system_timer timer_;
+ boost::asio::system_timer alt_timer_;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/fsm_events.hpp b/implementation/service_discovery/include/fsm_events.hpp
index 1624b00..75279e2 100644
--- a/implementation/service_discovery/include/fsm_events.hpp
+++ b/implementation/service_discovery/include/fsm_events.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -9,6 +9,7 @@
#include <boost/statechart/event.hpp>
#include <vsomeip/primitive_types.hpp>
+#include "../../routing/include/serviceinfo.hpp"
namespace sc = boost::statechart;
@@ -21,6 +22,9 @@ struct ev_none: sc::event<ev_none> {
struct ev_timeout: sc::event<ev_timeout> {
};
+struct ev_alt_timeout: sc::event<ev_alt_timeout> {
+};
+
struct ev_status_change: sc::event<ev_status_change> {
ev_status_change(bool _is_up)
: is_up_(_is_up) {
@@ -31,22 +35,25 @@ struct ev_status_change: sc::event<ev_status_change> {
struct ev_find_service: sc::event<ev_find_service> {
- ev_find_service(service_t _service, instance_t _instance,
- major_version_t _major, minor_version_t _minor, ttl_t _ttl)
- : service_(_service), instance_(_instance), major_(_major), minor_(
- _minor), ttl_(_ttl) {
+ ev_find_service(const std::shared_ptr<const serviceinfo> &_info, service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor, bool _unicast_flag)
+ : info_(_info), service_(_service), instance_(_instance), major_(_major), minor_(
+ _minor), unicast_flag_(_unicast_flag) {
}
-
+ const std::shared_ptr<const serviceinfo> &info_;
service_t service_;
instance_t instance_;
major_version_t major_;
minor_version_t minor_;
- ttl_t ttl_;
+ bool unicast_flag_;
};
struct ev_offer_change: sc::event<ev_offer_change> {
};
+struct ev_request_service: sc::event<ev_request_service> {
+};
+
} // namespace sd
} // namespace vsomeip
diff --git a/implementation/service_discovery/include/ip_option_impl.hpp b/implementation/service_discovery/include/ip_option_impl.hpp
index 8fd426b..e753b4e 100644
--- a/implementation/service_discovery/include/ip_option_impl.hpp
+++ b/implementation/service_discovery/include/ip_option_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/ipv4_option_impl.hpp b/implementation/service_discovery/include/ipv4_option_impl.hpp
index b8051cc..c233f0f 100644
--- a/implementation/service_discovery/include/ipv4_option_impl.hpp
+++ b/implementation/service_discovery/include/ipv4_option_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/ipv6_option_impl.hpp b/implementation/service_discovery/include/ipv6_option_impl.hpp
index 48938b0..c2b962f 100644
--- a/implementation/service_discovery/include/ipv6_option_impl.hpp
+++ b/implementation/service_discovery/include/ipv6_option_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/load_balancing_option_impl.hpp b/implementation/service_discovery/include/load_balancing_option_impl.hpp
index 0308a06..7504657 100755
--- a/implementation/service_discovery/include/load_balancing_option_impl.hpp
+++ b/implementation/service_discovery/include/load_balancing_option_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/message_element_impl.hpp b/implementation/service_discovery/include/message_element_impl.hpp
index 39ae3a1..c05b76e 100755
--- a/implementation/service_discovery/include/message_element_impl.hpp
+++ b/implementation/service_discovery/include/message_element_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/message_impl.hpp b/implementation/service_discovery/include/message_impl.hpp
index b0702df..a8573b8 100755
--- a/implementation/service_discovery/include/message_impl.hpp
+++ b/implementation/service_discovery/include/message_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -14,6 +14,16 @@
#include "../include/primitive_types.hpp"
#include "../../message/include/message_base_impl.hpp"
+# if _MSC_VER >= 1300
+/*
+* Diamond inheritance is used for the vsomeip::message_base base class.
+* The Microsoft compiler put warning (C4250) using a desired c++ feature: "Delegating to a sister class"
+* A powerful technique that arises from using virtual inheritance is to delegate a method from a class in another class
+* by using a common abstract base class. This is also called cross delegation.
+*/
+# pragma warning( disable : 4250 )
+# endif
+
namespace vsomeip {
namespace sd {
diff --git a/implementation/service_discovery/include/option_impl.hpp b/implementation/service_discovery/include/option_impl.hpp
index 90a6a48..21e8b9c 100644
--- a/implementation/service_discovery/include/option_impl.hpp
+++ b/implementation/service_discovery/include/option_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/primitive_types.hpp b/implementation/service_discovery/include/primitive_types.hpp
index fd12698..13f4478 100644
--- a/implementation/service_discovery/include/primitive_types.hpp
+++ b/implementation/service_discovery/include/primitive_types.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/protection_option_impl.hpp b/implementation/service_discovery/include/protection_option_impl.hpp
index 565b22b..e1f8d1e 100755
--- a/implementation/service_discovery/include/protection_option_impl.hpp
+++ b/implementation/service_discovery/include/protection_option_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/request.hpp b/implementation/service_discovery/include/request.hpp
index 9e62deb..99fe507 100644
--- a/implementation/service_discovery/include/request.hpp
+++ b/implementation/service_discovery/include/request.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -29,10 +29,15 @@ public:
ttl_t get_ttl() const;
void set_ttl(ttl_t _ttl);
+ uint8_t get_sent_counter() const;
+ void set_sent_counter(uint8_t _sent_counter);
+
private:
major_version_t major_;
minor_version_t minor_;
ttl_t ttl_;
+
+ uint8_t sent_counter_;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/runtime.hpp b/implementation/service_discovery/include/runtime.hpp
index 47255a2..656e2d5 100644
--- a/implementation/service_discovery/include/runtime.hpp
+++ b/implementation/service_discovery/include/runtime.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/runtime_impl.hpp b/implementation/service_discovery/include/runtime_impl.hpp
index cc0e14e..111d56e 100644
--- a/implementation/service_discovery/include/runtime_impl.hpp
+++ b/implementation/service_discovery/include/runtime_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp
index 894de0c..ebc81fa 100644
--- a/implementation/service_discovery/include/service_discovery.hpp
+++ b/implementation/service_discovery/include/service_discovery.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -11,6 +11,8 @@
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/enumeration_types.hpp>
+#include "../../routing/include/serviceinfo.hpp"
+#include "../../endpoints/include/endpoint.hpp"
namespace vsomeip {
@@ -41,12 +43,28 @@ public:
eventgroup_t _eventgroup, client_t _client) = 0;
virtual void unsubscribe_all(service_t _service, instance_t _instance) = 0;
- virtual void send(bool _is_announcing) = 0;
+ virtual bool send(bool _is_announcing, bool _is_find = false) = 0;
virtual void on_message(const byte_t *_data, length_t _length,
- const boost::asio::ip::address &_sender) = 0;
+ const boost::asio::ip::address &_sender,
+ const boost::asio::ip::address &_destination) = 0;
virtual void on_offer_change() = 0;
+
+ virtual void send_subscriptions(service_t _service, instance_t _instance,
+ client_t _client, bool _reliable) = 0;
+
+ virtual void send_unicast_offer_service(const std::shared_ptr<const serviceinfo> &_info,
+ service_t _service, instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor) = 0;
+ virtual void send_multicast_offer_service(const std::shared_ptr<const serviceinfo>& _info,
+ service_t _service, instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor) = 0;
+ virtual void on_reliable_endpoint_connected(
+ service_t _service, instance_t _instance,
+ const std::shared_ptr<const vsomeip::endpoint> &_endpoint) = 0;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/service_discovery_fsm.hpp b/implementation/service_discovery/include/service_discovery_fsm.hpp
index f3fe7fd..915b3e3 100644
--- a/implementation/service_discovery/include/service_discovery_fsm.hpp
+++ b/implementation/service_discovery/include/service_discovery_fsm.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -14,6 +14,8 @@
#include <boost/statechart/state.hpp>
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/transition.hpp>
+#include "../../routing/include/serviceinfo.hpp"
+
#include "../include/fsm_base.hpp"
#include "../include/fsm_events.hpp"
@@ -40,7 +42,8 @@ struct fsm: sc::state_machine<fsm, inactive>, public fsm_base {
void set_fsm(std::shared_ptr<service_discovery_fsm> _fsm);
- void timer_expired(const boost::system::error_code &_error);
+ void timer_expired(const boost::system::error_code &_error,
+ bool _use_alt_timeout);
uint32_t initial_delay_;
uint32_t repetitions_base_delay_;
@@ -95,9 +98,15 @@ struct repeat: sc::state<repeat, active> {
sc::result react(const ev_find_service &_event);
};
-struct announce: sc::state<announce, active> {
+struct offer;
+struct find;
+struct main: sc::state<main, active, mpl::list<offer, find>> {
+ main(my_context _context);
+};
+
+struct offer: sc::state<offer, main::orthogonal<0> > {
- announce(my_context _context);
+ offer(my_context _context);
typedef mpl::list<sc::custom_reaction<ev_timeout>,
sc::custom_reaction<ev_find_service>,
@@ -106,9 +115,39 @@ struct announce: sc::state<announce, active> {
sc::result react(const ev_timeout &_event);
sc::result react(const ev_find_service &_event);
sc::result react(const ev_offer_change &_event);
+
+ uint8_t run_;
+};
+
+struct idle;
+struct find: sc::state<find, main::orthogonal<1>, idle> {
+
+ find(my_context _context);
+
+ uint8_t run_;
+};
+
+struct idle: sc::state<idle, find> {
+ idle(my_context _context);
+
+ typedef mpl::list<sc::custom_reaction<ev_request_service> >reactions;
+
+ sc::result react(const ev_request_service &_event);
};
-} // namespace _offer
+struct send: sc::state<send, find> {
+ send(my_context _context);
+
+ typedef mpl::list<
+ sc::custom_reaction<ev_alt_timeout>,
+ sc::custom_reaction<ev_none>
+ > reactions;
+
+ sc::result react(const ev_alt_timeout &_event);
+ sc::result react(const ev_none &_event);
+};
+
+} // namespace _sd
///////////////////////////////////////////////////////////////////////////////
// Interface
@@ -121,13 +160,36 @@ public:
void start();
void stop();
- void send(bool _is_announcing);
+ bool send(bool _is_announcing, bool _is_find = false);
+
+ void send_unicast_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info,
+ service_t _service, instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor);
+
+ void send_multicast_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info,
+ service_t _service, instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor);
inline void process(const sc::event_base &_event) {
std::lock_guard<std::mutex> its_lock(lock_);
fsm_->process_event(_event);
}
+ inline uint8_t get_repetition_max() const {
+ if (!fsm_)
+ return 0;
+
+ return fsm_->repetitions_max_;
+ }
+
+ std::chrono::milliseconds get_elapsed_offer_timer();
+
+ bool check_is_multicast_offer();
+
private:
std::weak_ptr<service_discovery> discovery_;
std::shared_ptr<_sd::fsm> fsm_;
diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp
index 27d8007..1795d89 100644
--- a/implementation/service_discovery/include/service_discovery_host.hpp
+++ b/implementation/service_discovery/include/service_discovery_host.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -41,7 +41,7 @@ public:
bool _flush) = 0;
virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size) = 0;
+ const byte_t *_data, uint32_t _size, uint16_t _sd_port) = 0;
virtual void add_routing_info(service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor, ttl_t _ttl,
@@ -53,12 +53,14 @@ public:
virtual void del_routing_info(service_t _service, instance_t _instance,
bool _has_reliable, bool _has_unreliable) = 0;
- virtual ttl_t update_routing_info(ttl_t _elapsed) = 0;
+ virtual std::chrono::milliseconds update_routing_info(
+ std::chrono::milliseconds _elapsed) = 0;
virtual void on_subscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup,
std::shared_ptr<endpoint_definition> _subscriber,
- std::shared_ptr<endpoint_definition> _target) = 0;
+ std::shared_ptr<endpoint_definition> _target,
+ const std::chrono::high_resolution_clock::time_point &_expiration) = 0;
virtual void on_unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup,
@@ -67,11 +69,27 @@ public:
virtual void on_subscribe_ack(service_t _service, instance_t _instance,
const boost::asio::ip::address &_address, uint16_t _port) = 0;
- virtual std::shared_ptr<endpoint> find_or_create_remote_client(service_t _service,
- instance_t _instance, bool _reliable, client_t _client) = 0;
+ virtual void on_subscribe_ack(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0;
+
+ virtual std::shared_ptr<endpoint> find_or_create_remote_client(
+ service_t _service, instance_t _instance,
+ bool _reliable, client_t _client) = 0;
virtual void expire_subscriptions(const boost::asio::ip::address &_address) = 0;
virtual void expire_services(const boost::asio::ip::address &_address) = 0;
+
+ virtual bool on_subscribe_accepted(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, std::shared_ptr<endpoint_definition> _target,
+ const std::chrono::high_resolution_clock::time_point &_expiration) = 0;
+
+ virtual void on_subscribe_nack(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0;
+
+ virtual bool has_identified(client_t _client, service_t _service,
+ instance_t _instance, bool _reliable) = 0;
+
+ virtual std::chrono::high_resolution_clock::time_point expire_subscriptions() = 0;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp
index 7efb6eb..4e64328 100644
--- a/implementation/service_discovery/include/service_discovery_impl.hpp
+++ b/implementation/service_discovery/include/service_discovery_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -14,8 +14,11 @@
#include <boost/asio/system_timer.hpp>
#include "service_discovery.hpp"
+#include "../../endpoints/include/endpoint_definition.hpp"
#include "../../routing/include/types.hpp"
#include "ip_option_impl.hpp"
+#include "ipv4_option_impl.hpp"
+#include "ipv6_option_impl.hpp"
namespace vsomeip {
@@ -35,6 +38,15 @@ class subscription;
typedef std::map<service_t, std::map<instance_t, std::shared_ptr<request> > > requests_t;
+struct accepted_subscriber_t {
+ std::shared_ptr < endpoint_definition > subscriber;
+ std::shared_ptr < endpoint_definition > target;
+ std::chrono::high_resolution_clock::time_point its_expiration;
+ vsomeip::service_t service_id;
+ vsomeip::instance_t instance_id;
+ vsomeip::eventgroup_t eventgroup_;
+};
+
class service_discovery_impl: public service_discovery,
public std::enable_shared_from_this<service_discovery_impl> {
public:
@@ -59,18 +71,36 @@ public:
eventgroup_t _eventgroup, client_t _client);
void unsubscribe_all(service_t _service, instance_t _instance);
- void send(bool _is_announcing);
+ bool send(bool _is_announcing, bool _is_find);
void on_message(const byte_t *_data, length_t _length,
- const boost::asio::ip::address &_sender);
+ const boost::asio::ip::address &_sender,
+ const boost::asio::ip::address &_destination);
void on_offer_change();
+ void send_unicast_offer_service(const std::shared_ptr<const serviceinfo> &_info,
+ service_t _service, instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor);
+
+ void send_multicast_offer_service(const std::shared_ptr<const serviceinfo>& _info,
+ service_t _service, instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor);
+
+ void on_reliable_endpoint_connected(
+ service_t _service, instance_t _instance,
+ const std::shared_ptr<const vsomeip::endpoint> &_endpoint);
+
private:
+
+
std::pair<session_t, bool> get_session(const boost::asio::ip::address &_address);
void increment_session(const boost::asio::ip::address &_address);
- bool is_reboot(const boost::asio::ip::address &_address,
+ bool is_reboot(const boost::asio::ip::address &_sender,
+ const boost::asio::ip::address &_destination,
bool _reboot_flag, session_t _session);
void insert_option(std::shared_ptr<message_impl> &_message,
@@ -78,24 +108,29 @@ private:
const boost::asio::ip::address &_address, uint16_t _port,
bool _is_reliable);
void insert_find_entries(std::shared_ptr<message_impl> &_message,
- requests_t &_requests);
+ requests_t &_requests, uint32_t _start, uint32_t &_size, bool &_done);
void insert_offer_entries(std::shared_ptr<message_impl> &_message,
- services_t &_services);
- void insert_offer_service(std::shared_ptr<message_impl> _message,
+ services_t &_services, uint32_t &_start, uint32_t _size, bool &_done);
+ bool insert_offer_service(std::shared_ptr<message_impl> _message,
service_t _service, instance_t _instance,
- const std::shared_ptr<const serviceinfo> &_info);
+ const std::shared_ptr<const serviceinfo> &_info,
+ uint32_t &_size);
void insert_subscription(std::shared_ptr<message_impl> &_message,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ std::shared_ptr<subscription> &_subscription, bool _insert_reliable, bool _insert_unreliable);
+ void insert_nack_subscription_on_resubscribe(std::shared_ptr<message_impl> &_message,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
std::shared_ptr<subscription> &_subscription);
void insert_subscription_ack(std::shared_ptr<message_impl> &_message,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl);
+ std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl, uint8_t _counter, major_version_t _major, uint16_t _reserved);
void insert_subscription_nack(std::shared_ptr<message_impl> &_message, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<eventgroupinfo> &_info);
+ uint8_t _counter, major_version_t _major, uint16_t _reserved);
void process_serviceentry(std::shared_ptr<serviceentry_impl> &_entry,
- const std::vector<std::shared_ptr<option_impl> > &_options);
+ const std::vector<std::shared_ptr<option_impl> > &_options,
+ bool _unicast_flag);
void process_offerservice_serviceentry(
service_t _service, instance_t _instance, major_version_t _major,
minor_version_t _minor, ttl_t _ttl,
@@ -103,39 +138,63 @@ private:
uint16_t _reliable_port,
const boost::asio::ip::address &_unreliable_address,
uint16_t _unreliable_port);
- void send_unicast_offer_service(const std::shared_ptr<const serviceinfo>& _info,
- service_t _service, instance_t _instance,
- major_version_t _major,
- minor_version_t _minor);
- void process_findservice_serviceentry(service_t _service,
- instance_t _instance,
- major_version_t _major,
- minor_version_t _minor);
- void process_eventgroupentry(std::shared_ptr<eventgroupentry_impl> &_entry,
- const std::vector<std::shared_ptr<option_impl> > &_options);
+ void send_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info, service_t _service,
+ instance_t _instance, major_version_t _major, minor_version_t _minor,
+ bool _unicast_flag);
+ void process_findservice_serviceentry(service_t _service,
+ instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor,
+ bool _unicast_flag);
+ void process_eventgroupentry(
+ std::shared_ptr<eventgroupentry_impl> &_entry,
+ const std::vector<std::shared_ptr<option_impl> > &_options,
+ std::shared_ptr < message_impl > &its_message_response,
+ std::vector <accepted_subscriber_t> &accepted_subscribers);
void handle_eventgroup_subscription(service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, ttl_t _ttl,
- const boost::asio::ip::address &_reliable_address,
- uint16_t _reliable_port, uint16_t _unreliable_port);
+ major_version_t _major, ttl_t _ttl, uint8_t _counter, uint16_t _reserved,
+ const boost::asio::ip::address &_first_address, uint16_t _first_port,
+ bool _is_first_reliable,
+ const boost::asio::ip::address &_second_address, uint16_t _second_port,
+ bool _is_second_reliable,
+ std::shared_ptr < message_impl > &its_message,
+ std::vector <accepted_subscriber_t> &accepted_subscribers);
void handle_eventgroup_subscription_ack(service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, ttl_t _ttl,
+ major_version_t _major, ttl_t _ttl, uint8_t _counter,
const boost::asio::ip::address &_address, uint16_t _port);
+ void handle_eventgroup_subscription_nack(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, uint8_t _counter);
void serialize_and_send(std::shared_ptr<message_impl> _message,
const boost::asio::ip::address &_address);
+ bool is_tcp_connected(service_t _service,
+ instance_t _instance,
+ std::shared_ptr<vsomeip::endpoint_definition> its_endpoint);
+
void start_ttl_timer();
- ttl_t stop_ttl_timer();
+ std::chrono::milliseconds stop_ttl_timer();
+
void check_ttl(const boost::system::error_code &_error);
boost::asio::ip::address get_current_remote_address() const;
+
+ void start_subscription_expiration_timer();
+ void stop_subscription_expiration_timer();
+ void expire_subscriptions(const boost::system::error_code &_error);
+
+ bool check_ipv4_address(boost::asio::ip::address its_address);
+
bool check_static_header_fields(
const std::shared_ptr<const message> &_message) const;
void send_eventgroup_subscription_nack(service_t _service,
instance_t _instance,
eventgroup_t _eventgroup,
- major_version_t _major);
+ major_version_t _major,
+ uint8_t _counter,
+ uint16_t _reserved);
bool check_layer_four_protocol(
const std::shared_ptr<const ip_option_impl> _ip_option) const;
void get_subscription_endpoints(subscription_type_e _subscription_type,
@@ -146,6 +205,28 @@ private:
service_t _service, instance_t _instance,
client_t _client) const;
+ void send_subscriptions(service_t _service, instance_t _instance, client_t _client, bool _reliable);
+
+ template<class Option, typename AddressType>
+ std::shared_ptr<option_impl> find_existing_option(
+ std::shared_ptr<message_impl> &_message,
+ AddressType _address, uint16_t _port,
+ layer_four_protocol_e _protocol,
+ option_type_e _option_type);
+ template<class Option, typename AddressType>
+ bool check_message_for_ip_option_and_assign_existing(
+ std::shared_ptr<message_impl> &_message,
+ std::shared_ptr<entry_impl> _entry, AddressType _address,
+ uint16_t _port, layer_four_protocol_e _protocol,
+ option_type_e _option_type);
+ template<class Option, typename AddressType>
+ void assign_ip_option_to_entry(std::shared_ptr<Option> _option,
+ AddressType _address, uint16_t _port,
+ layer_four_protocol_e _protocol,
+ std::shared_ptr<entry_impl> _entry);
+
+ std::shared_ptr<request> find_request(service_t _service, instance_t _instance);
+
private:
boost::asio::io_service &io_;
service_discovery_host *host_;
@@ -165,25 +246,31 @@ private:
std::mutex requested_mutex_;
std::map<service_t,
std::map<instance_t,
- std::map<eventgroup_t, std::map<client_t, std::shared_ptr<subscription> > > > > subscribed_;
+ std::map<eventgroup_t,
+ std::map<client_t,
+ std::shared_ptr<subscription> > > > > subscribed_;
std::mutex subscribed_mutex_;
std::mutex serialize_mutex_;
// Sessions
- std::map<boost::asio::ip::address, std::pair<session_t, bool> > sessions_;
- std::map<boost::asio::ip::address, session_t > sessions_receiving_;
-
- // Reboots
- std::set<boost::asio::ip::address> reboots_;
+ std::map<boost::asio::ip::address, std::pair<session_t, bool> > sessions_sent_;
+ std::map<boost::asio::ip::address,
+ std::tuple<session_t, session_t, bool> > sessions_received_;
// Runtime
std::weak_ptr<runtime> runtime_;
- // TTL handling
+ // TTL handling for services offered by other hosts
boost::asio::system_timer ttl_timer_;
- ttl_t smallest_ttl_;
+ std::chrono::milliseconds smallest_ttl_;
ttl_t ttl_;
+
+ // TTL handling for subscriptions done by other hosts
+ boost::asio::system_timer subscription_expiration_timer_;
+ std::chrono::high_resolution_clock::time_point next_subscription_expiration_;
+
+ uint32_t max_message_size_;
};
} // namespace sd
diff --git a/implementation/service_discovery/include/serviceentry_impl.hpp b/implementation/service_discovery/include/serviceentry_impl.hpp
index f83e62a..1385f84 100644
--- a/implementation/service_discovery/include/serviceentry_impl.hpp
+++ b/implementation/service_discovery/include/serviceentry_impl.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/include/subscription.hpp b/implementation/service_discovery/include/subscription.hpp
index 25df7b3..eb2fb66 100644
--- a/implementation/service_discovery/include/subscription.hpp
+++ b/implementation/service_discovery/include/subscription.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -6,6 +6,7 @@
#ifndef VSOMEIP_SD_SUBSCRIPTION_HPP
#define VSOMEIP_SD_SUBSCRIPTION_HPP
+#include <chrono>
#include <memory>
#include <vsomeip/primitive_types.hpp>
@@ -22,7 +23,9 @@ public:
subscription(major_version_t _major, ttl_t _ttl,
std::shared_ptr<endpoint> _reliable,
std::shared_ptr<endpoint> _unreliable,
- subscription_type_e _subscription_type);
+ subscription_type_e _subscription_type,
+ uint8_t _counter,
+ std::chrono::high_resolution_clock::time_point _expiration);
~subscription();
major_version_t get_major() const;
@@ -34,8 +37,16 @@ public:
bool is_acknowledged() const;
void set_acknowledged(bool _is_acknowledged);
+ bool is_tcp_connection_established() const;
+ void set_tcp_connection_established(bool _is_established);
+
subscription_type_e get_subscription_type() const;
+ uint8_t get_counter() const;
+
+ std::chrono::high_resolution_clock::time_point get_expiration() const;
+ void set_expiration(std::chrono::high_resolution_clock::time_point _expiration);
+
private:
major_version_t major_;
ttl_t ttl_;
@@ -44,8 +55,13 @@ private:
std::shared_ptr<endpoint> unreliable_;
bool is_acknowledged_;
+ bool tcp_connection_established_;
subscription_type_e subscription_type_;
+
+ uint8_t counter_;
+
+ std::chrono::high_resolution_clock::time_point expiration_;
};
} // namespace sd
diff --git a/implementation/service_discovery/src/configuration_option_impl.cpp b/implementation/service_discovery/src/configuration_option_impl.cpp
index 793ec95..933f7b1 100755
--- a/implementation/service_discovery/src/configuration_option_impl.cpp
+++ b/implementation/service_discovery/src/configuration_option_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -92,38 +92,36 @@ bool configuration_option_impl::serialize(vsomeip::serializer *_to) const {
bool configuration_option_impl::deserialize(vsomeip::deserializer *_from) {
bool is_successful = option_impl::deserialize(_from);
- uint16_t l_length = 0;
- uint8_t l_itemLength;
+ uint8_t l_itemLength = 0;
std::string l_item(256, 0), l_key, l_value;
- is_successful = is_successful && _from->deserialize(l_length);
- if (l_length > _from->get_remaining()) {
- _from->set_remaining(0);
- return false;
- }
-
- if (l_length > 0) {
- do {
- is_successful = is_successful && _from->deserialize(l_itemLength);
- if (l_itemLength == 0)
- break;
-
- l_length = uint16_t(l_length - l_itemLength);
+ do {
+ l_itemLength = 0;
+ l_key.clear();
+ l_value.clear();
+ l_item.assign(256, '\0');
+ is_successful = is_successful && _from->deserialize(l_itemLength);
+ if (l_itemLength > 0) {
is_successful = is_successful
&& _from->deserialize((uint8_t*) &l_item[0], l_itemLength);
- size_t l_eqPos = l_item.find('=');
- l_key = l_item.substr(0, l_eqPos);
- l_value = l_item.substr(l_eqPos + 1);
-
- if (configuration_.end() == configuration_.find(l_key)) {
- configuration_[l_key] = l_value;
- } else {
- is_successful = false;
+ if (is_successful) {
+ size_t l_eqPos = l_item.find('='); //SWS_SD_00292
+ l_key = l_item.substr(0, l_eqPos);
+
+ //if no "=" is found, no value is present for key (SWS_SD_00466)
+ if( l_eqPos != std::string::npos )
+ l_value = l_item.substr(l_eqPos + 1);
+ if (configuration_.end() == configuration_.find(l_key)) {
+ configuration_[l_key] = l_value;
+ } else {
+ // TODO: log reason for failing deserialization
+ is_successful = false;
+ }
}
- } while (l_length > 0);
- }
+ }
+ } while (is_successful && _from->get_remaining() > 0);
return is_successful;
}
diff --git a/implementation/service_discovery/src/deserializer.cpp b/implementation/service_discovery/src/deserializer.cpp
index cb86c52..744c463 100644
--- a/implementation/service_discovery/src/deserializer.cpp
+++ b/implementation/service_discovery/src/deserializer.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/entry_impl.cpp b/implementation/service_discovery/src/entry_impl.cpp
index ea7a511..efff9da 100755
--- a/implementation/service_discovery/src/entry_impl.cpp
+++ b/implementation/service_discovery/src/entry_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -85,20 +85,27 @@ const std::vector<uint8_t> & entry_impl::get_options(uint8_t _run) const {
return invalid_options;
}
-void entry_impl::assign_option(const std::shared_ptr<option_impl> &_option,
- uint8_t _run) {
- if (_run > 0 && _run <= VSOMEIP_MAX_OPTION_RUN) {
- _run--; // Index = Run-1
-
- uint8_t option_index = uint8_t(get_owning_message()->get_option_index(_option));
- if (0x10 > option_index) { // as we have only a nibble for the option counter
- options_[_run].push_back(option_index);
- std::sort(options_[_run].begin(), options_[_run].end());
+void entry_impl::assign_option(const std::shared_ptr<option_impl> &_option) {
+ uint8_t option_index = uint8_t(get_owning_message()->get_option_index(_option));
+ if (0x10 > option_index) { // as we have only a nibble for the option counter
+ if (options_[0].empty() ||
+ options_[0][0] == option_index + 1 ||
+ options_[0][options_[0].size() - 1] + 1 == option_index) {
+ options_[0].push_back(option_index);
+ std::sort(options_[0].begin(), options_[0].end());
+ num_options_[0]++;
+ } else
+ if (options_[1].empty() ||
+ options_[1][0] == option_index + 1 ||
+ options_[1][options_[1].size() - 1] + 1 == option_index) {
+ options_[1].push_back(option_index);
+ std::sort(options_[1].begin(), options_[1].end());
+ num_options_[1]++;
} else {
- // TODO: decide what to do if option does not belong to the message.
+ // TODO: copy data
}
} else {
- // TODO: decide what to do if an illegal index for the option run is provided
+ // TODO: decide what to do if option does not belong to the message.
}
}
diff --git a/implementation/service_discovery/src/eventgroupentry_impl.cpp b/implementation/service_discovery/src/eventgroupentry_impl.cpp
index 024756d..220fc47 100755
--- a/implementation/service_discovery/src/eventgroupentry_impl.cpp
+++ b/implementation/service_discovery/src/eventgroupentry_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -13,11 +13,13 @@ namespace sd {
eventgroupentry_impl::eventgroupentry_impl() {
eventgroup_ = 0xFFFF;
+ counter_ = 0;
}
eventgroupentry_impl::eventgroupentry_impl(const eventgroupentry_impl &_entry)
: entry_impl(_entry) {
eventgroup_ = _entry.eventgroup_;
+ counter_ = _entry.counter_;
}
eventgroupentry_impl::~eventgroupentry_impl() {
@@ -31,6 +33,22 @@ void eventgroupentry_impl::set_eventgroup(eventgroup_t _eventgroup) {
eventgroup_ = _eventgroup;
}
+uint16_t eventgroupentry_impl::get_reserved() const {
+ return reserved_;
+}
+
+void eventgroupentry_impl::set_reserved(uint16_t _reserved) {
+ reserved_ = _reserved;
+}
+
+uint8_t eventgroupentry_impl::get_counter() const {
+ return counter_;
+}
+
+void eventgroupentry_impl::set_counter(uint8_t _counter) {
+ counter_ = _counter;
+}
+
bool eventgroupentry_impl::serialize(vsomeip::serializer *_to) const {
bool is_successful = entry_impl::serialize(_to);
@@ -39,9 +57,25 @@ bool eventgroupentry_impl::serialize(vsomeip::serializer *_to) const {
is_successful = is_successful
&& _to->serialize(static_cast<uint32_t>(ttl_), true);
- is_successful = is_successful && _to->serialize(protocol::reserved_word);
+ // 4Bit only for counter field
+ if (counter_ >= 16) {
+ is_successful = false;
+ }
+ uint16_t counter_and_reserved = protocol::reserved_word;
+ if (!reserved_ ) {
+ //reserved was not set -> just store counter as uint16
+ counter_and_reserved = static_cast<uint16_t>(counter_);
+ }
+ else {
+ //reserved contains values -> put reserved and counter into 16 bit variable
+ counter_and_reserved = (uint16_t) (((uint16_t) reserved_ << 4) | counter_);
+ }
is_successful = is_successful
+ && _to->serialize((uint8_t)(counter_and_reserved >> 8)); // serialize reserved part 1
+ is_successful = is_successful
+ && _to->serialize((uint8_t)counter_and_reserved); // serialize reserved part 2 and counter
+ is_successful = is_successful
&& _to->serialize(static_cast<uint16_t>(eventgroup_));
return is_successful;
@@ -58,9 +92,20 @@ bool eventgroupentry_impl::deserialize(vsomeip::deserializer *_from) {
is_successful = is_successful && _from->deserialize(its_ttl, true);
ttl_ = static_cast<ttl_t>(its_ttl);
- uint16_t its_reserved1;
- is_successful = is_successful && _from->deserialize(its_reserved1);
+ uint8_t reserved1, reserved2;
+ is_successful = is_successful && _from->deserialize(reserved1); // deserialize reserved part 1
+ is_successful = is_successful && _from->deserialize(reserved2); // deserialize reserved part 2 and counter
+
+ reserved_ = (uint16_t) (((uint16_t)reserved1 << 8) | reserved2); // combine reserved parts and counter
+ reserved_ = (uint16_t) (reserved_ >> 4); //remove counter from reserved field
+
+ //set 4 bits of reserved part 2 field to zero
+ counter_ = (uint8_t) (reserved2 & (~(0xF0)));
+ // 4Bit only for counter field
+ if (counter_ >= 16) {
+ is_successful = false;
+ }
uint16_t its_eventgroup = 0;
is_successful = is_successful && _from->deserialize(its_eventgroup);
eventgroup_ = static_cast<eventgroup_t>(its_eventgroup);
diff --git a/implementation/service_discovery/src/fsm_base.cpp b/implementation/service_discovery/src/fsm_base.cpp
index 07a0def..e3c234b 100644
--- a/implementation/service_discovery/src/fsm_base.cpp
+++ b/implementation/service_discovery/src/fsm_base.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -9,26 +9,42 @@ namespace vsomeip {
namespace sd {
fsm_base::fsm_base(boost::asio::io_service &_io)
- : timer_(_io) {
+ : timer_(_io), alt_timer_(_io) {
}
fsm_base::~fsm_base() {
}
-void fsm_base::start_timer(uint32_t _milliseconds) {
- timer_.expires_from_now(std::chrono::milliseconds(_milliseconds));
- timer_.async_wait(
- std::bind(&fsm_base::timer_expired, shared_from_this(),
- std::placeholders::_1));
+void fsm_base::start_timer(uint32_t _milliseconds, bool _use_alt_timer) {
+ if (_use_alt_timer) {
+ alt_timer_.expires_from_now(std::chrono::milliseconds(_milliseconds));
+ alt_timer_.async_wait(
+ std::bind(&fsm_base::timer_expired, shared_from_this(),
+ std::placeholders::_1, true));
+ } else {
+ timer_.expires_from_now(std::chrono::milliseconds(_milliseconds));
+ timer_.async_wait(
+ std::bind(&fsm_base::timer_expired, shared_from_this(),
+ std::placeholders::_1, false));
+ }
}
-void fsm_base::stop_timer() {
- timer_.cancel();
+void fsm_base::stop_timer(bool _use_alt_timer) {
+ if (_use_alt_timer) {
+ alt_timer_.cancel();
+ } else {
+ timer_.cancel();
+ }
}
-uint32_t fsm_base::expired_from_now() {
- return (uint32_t) std::chrono::duration_cast < std::chrono::milliseconds
- > (timer_.expires_from_now()).count();
+uint32_t fsm_base::expired_from_now(bool _use_alt_timer) {
+ if (_use_alt_timer) {
+ return (uint32_t) std::chrono::duration_cast < std::chrono::milliseconds
+ > (alt_timer_.expires_from_now()).count();
+ } else {
+ return (uint32_t) std::chrono::duration_cast < std::chrono::milliseconds
+ > (timer_.expires_from_now()).count();
+ }
}
} // namespace sd
diff --git a/implementation/service_discovery/src/ip_option_impl.cpp b/implementation/service_discovery/src/ip_option_impl.cpp
index 3fcffac..08f78b9 100644
--- a/implementation/service_discovery/src/ip_option_impl.cpp
+++ b/implementation/service_discovery/src/ip_option_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/ipv4_option_impl.cpp b/implementation/service_discovery/src/ipv4_option_impl.cpp
index ca5a2c5..9f2cec4 100644
--- a/implementation/service_discovery/src/ipv4_option_impl.cpp
+++ b/implementation/service_discovery/src/ipv4_option_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -6,6 +6,7 @@
#include <vsomeip/constants.hpp>
#include "../include/constants.hpp"
+#include "../include/defines.hpp"
#include "../include/ipv4_option_impl.hpp"
#include "../../message/include/deserializer.hpp"
#include "../../message/include/serializer.hpp"
@@ -42,7 +43,8 @@ bool ipv4_option_impl::serialize(vsomeip::serializer *_to) const {
}
bool ipv4_option_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = option_impl::deserialize(_from);
+ bool is_successful = option_impl::deserialize(_from)
+ && length_ == VSOMEIP_SD_IPV4_OPTION_LENGTH;
uint8_t its_reserved;
_from->deserialize(address_.data(), 4);
_from->deserialize(its_reserved);
diff --git a/implementation/service_discovery/src/ipv6_option_impl.cpp b/implementation/service_discovery/src/ipv6_option_impl.cpp
index 1aa2570..089b509 100755
--- a/implementation/service_discovery/src/ipv6_option_impl.cpp
+++ b/implementation/service_discovery/src/ipv6_option_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -6,6 +6,7 @@
#include <cstring>
#include "../include/constants.hpp"
+#include "../include/defines.hpp"
#include "../include/ipv6_option_impl.hpp"
#include "../../message/include/deserializer.hpp"
#include "../../message/include/serializer.hpp"
@@ -42,7 +43,8 @@ bool ipv6_option_impl::serialize(vsomeip::serializer *_to) const {
}
bool ipv6_option_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = option_impl::deserialize(_from);
+ bool is_successful = option_impl::deserialize(_from)
+ && length_ == VSOMEIP_SD_IPV6_OPTION_LENGTH;;
uint8_t its_reserved;
_from->deserialize(address_.data(), 16);
_from->deserialize(its_reserved);
diff --git a/implementation/service_discovery/src/load_balancing_option_impl.cpp b/implementation/service_discovery/src/load_balancing_option_impl.cpp
index 47a5b70..5c12c39 100755
--- a/implementation/service_discovery/src/load_balancing_option_impl.cpp
+++ b/implementation/service_discovery/src/load_balancing_option_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/message_element_impl.cpp b/implementation/service_discovery/src/message_element_impl.cpp
index 6577115..4c1a683 100755
--- a/implementation/service_discovery/src/message_element_impl.cpp
+++ b/implementation/service_discovery/src/message_element_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/message_impl.cpp b/implementation/service_discovery/src/message_impl.cpp
index 3130dda..8159bd4 100755
--- a/implementation/service_discovery/src/message_impl.cpp
+++ b/implementation/service_discovery/src/message_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -204,6 +204,7 @@ bool message_impl::serialize(vsomeip::serializer *_to) const {
bool message_impl::deserialize(vsomeip::deserializer *_from) {
bool is_successful;
+ bool option_is_successful(true);
// header
is_successful = header_.deserialize(_from);
@@ -251,12 +252,12 @@ bool message_impl::deserialize(vsomeip::deserializer *_from) {
_from->set_remaining(options_length_);
}
- while (is_successful && _from->get_remaining()) {
+ while (option_is_successful && _from->get_remaining()) {
std::shared_ptr < option_impl > its_option(deserialize_option(_from));
if (its_option) {
options_.push_back(its_option);
- } else {
- is_successful = false;
+ } else {
+ option_is_successful = false;
}
}
diff --git a/implementation/service_discovery/src/option_impl.cpp b/implementation/service_discovery/src/option_impl.cpp
index cff6d61..71aa085 100755
--- a/implementation/service_discovery/src/option_impl.cpp
+++ b/implementation/service_discovery/src/option_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/protection_option_impl.cpp b/implementation/service_discovery/src/protection_option_impl.cpp
index 7197565..366f531 100755
--- a/implementation/service_discovery/src/protection_option_impl.cpp
+++ b/implementation/service_discovery/src/protection_option_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/request.cpp b/implementation/service_discovery/src/request.cpp
index 8673822..6ed2d66 100644
--- a/implementation/service_discovery/src/request.cpp
+++ b/implementation/service_discovery/src/request.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -9,8 +9,7 @@ namespace vsomeip {
namespace sd {
request::request(major_version_t _major, minor_version_t _minor, ttl_t _ttl)
- : major_(_major), minor_(_minor), ttl_(_ttl) {
-
+ : major_(_major), minor_(_minor), ttl_(_ttl), sent_counter_(0) {
}
major_version_t request::get_major() const {
@@ -37,5 +36,13 @@ void request::set_ttl(ttl_t _ttl) {
ttl_ = _ttl;
}
+uint8_t request::get_sent_counter() const {
+ return sent_counter_;
+}
+
+void request::set_sent_counter(uint8_t _sent_counter) {
+ sent_counter_ = _sent_counter;
+}
+
} // namespace sd
} // namespace vsomeip
diff --git a/implementation/service_discovery/src/runtime.cpp b/implementation/service_discovery/src/runtime.cpp
index f7d1a4f..be68d24 100644
--- a/implementation/service_discovery/src/runtime.cpp
+++ b/implementation/service_discovery/src/runtime.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/runtime_impl.cpp b/implementation/service_discovery/src/runtime_impl.cpp
index 2cc25d2..187b5bc 100644
--- a/implementation/service_discovery/src/runtime_impl.cpp
+++ b/implementation/service_discovery/src/runtime_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/service_discovery_fsm.cpp b/implementation/service_discovery/src/service_discovery_fsm.cpp
index d2428dd..a4ede7b 100644
--- a/implementation/service_discovery/src/service_discovery_fsm.cpp
+++ b/implementation/service_discovery/src/service_discovery_fsm.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -9,6 +9,8 @@
#include "../include/defines.hpp"
#include "../include/service_discovery.hpp"
#include "../include/service_discovery_fsm.hpp"
+#include "../../routing/include/serviceinfo.hpp"
+
#include "../../configuration/include/configuration.hpp"
#include "../../logging/include/logger.hpp"
@@ -31,11 +33,17 @@ void fsm::set_fsm(std::shared_ptr<service_discovery_fsm> _fsm) {
fsm_ = _fsm;
}
-void fsm::timer_expired(const boost::system::error_code &_error) {
+void fsm::timer_expired(const boost::system::error_code &_error,
+ bool _use_alt_timeout) {
if (!_error) {
std::shared_ptr<service_discovery_fsm> its_fsm = fsm_.lock();
- if (its_fsm)
- its_fsm->process(ev_timeout());
+ if (its_fsm) {
+ if (_use_alt_timeout) {
+ its_fsm->process(ev_alt_timeout());
+ } else {
+ its_fsm->process(ev_timeout());
+ }
+ }
}
}
@@ -96,7 +104,7 @@ sc::result active::react(const ev_status_change &_event) {
if (!outermost_context().is_up_)
return transit<inactive>();
- return discard_event();
+ return forward_event();
}
///////////////////////////////////////////////////////////////////////////////
@@ -129,53 +137,142 @@ repeat::repeat(my_context _context)
uint32_t its_timeout = (outermost_context().repetitions_base_delay_
<< outermost_context().run_);
outermost_context().run_++;
- fsm->send(false);
+ (void)fsm->send(false);
outermost_context().start_timer(its_timeout);
}
}
sc::result repeat::react(const ev_timeout &_event) {
(void)_event;
-
- if (outermost_context().run_ < outermost_context().repetitions_max_)
+ if (outermost_context().run_ < outermost_context().repetitions_max_) {
return transit<repeat>();
-
- return transit<announce>();
+ }
+ return transit<main>();
}
sc::result repeat::react(const ev_find_service &_event) {
- (void)_event;
- return discard_event();
+ VSOMEIP_TRACE << "sd::active.repeat.react.find";
+ std::shared_ptr < service_discovery_fsm > fsm =
+ outermost_context().fsm_.lock();
+ // Answer Find Service messages with unicast offer in repetition phase
+ if (fsm) {
+ fsm->send_unicast_offer_service(_event.info_, _event.service_, _event.instance_,
+ _event.major_, _event.minor_);
+ }
+ return forward_event();
}
///////////////////////////////////////////////////////////////////////////////
-// State "Active.Announce"
+// State "Active.Main"
///////////////////////////////////////////////////////////////////////////////
-announce::announce(my_context _context)
- : sc::state<announce, active>(_context) {
+main::main(my_context _context)
+ : sc::state<main, active, mpl::list<offer, find> >(_context) {
+ VSOMEIP_TRACE << "sd::active.main";
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// State "Active.Main.Offer"
+///////////////////////////////////////////////////////////////////////////////
+offer::offer(my_context _context)
+ : sc::state<offer, main::orthogonal<0> >(_context) {
std::shared_ptr < service_discovery_fsm > fsm =
outermost_context().fsm_.lock();
if (fsm) {
- VSOMEIP_TRACE << "sd::active.announce";
+ VSOMEIP_TRACE << "sd::active.main.offer";
outermost_context().start_timer(
outermost_context().cyclic_offer_delay_);
- fsm->send(true);
+ (void)fsm->send(true);
}
}
-sc::result announce::react(const ev_timeout &_event) {
+sc::result offer::react(const ev_timeout &_event) {
(void)_event;
- return transit<announce>();
+ return transit<offer>();
}
-sc::result announce::react(const ev_find_service &_event) {
+sc::result offer::react(const ev_find_service &_event) {
+ VSOMEIP_TRACE << "sd::active.main.react.find";
+ std::shared_ptr < service_discovery_fsm > fsm =
+ outermost_context().fsm_.lock();
+ if (fsm) {
+ if(_event.unicast_flag_) {
+ if( !fsm->check_is_multicast_offer()) { // SIP_SD_89
+ fsm->send_unicast_offer_service(_event.info_, _event.service_, _event.instance_,
+ _event.major_, _event.minor_);
+ } else { // SIP_SD_90
+ fsm->send_multicast_offer_service(_event.info_, _event.service_, _event.instance_,
+ _event.major_, _event.minor_);
+ }
+ } else { // SIP_SD_91
+ fsm->send_multicast_offer_service(_event.info_, _event.service_, _event.instance_,
+ _event.major_, _event.minor_);
+ }
+ }
+ return forward_event();
+}
+
+sc::result offer::react(const ev_offer_change &_event) {
(void)_event;
- return discard_event();
+ return transit<offer>();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// State "Active.Announce.Main.Find"
+///////////////////////////////////////////////////////////////////////////////
+find::find(my_context _context)
+ : sc::state<find, main::orthogonal<1>, idle>(_context) {
+ VSOMEIP_TRACE << "sd::active.main.find";
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// State "Active.Announce.Idle"
+///////////////////////////////////////////////////////////////////////////////
+idle::idle(my_context _context)
+ : sc::state<idle, find>(_context) {
+ VSOMEIP_TRACE << "sd::active.main.find.idle";
+ context<find>().run_ = 0;
+}
+
+sc::result idle::react(const ev_request_service &_event) {
+ (void)_event;
+ return transit<send>();
}
-sc::result announce::react(const ev_offer_change &_event) {
+///////////////////////////////////////////////////////////////////////////////
+// State "Active.Announce.Main.Find.Send"
+///////////////////////////////////////////////////////////////////////////////
+send::send(my_context _context)
+ : sc::state<send, find>(_context) {
+ std::shared_ptr < service_discovery_fsm > fsm =
+ outermost_context().fsm_.lock();
+ if (fsm) {
+ VSOMEIP_TRACE << "sd::active.main.find.send";
+ // Increment to the maximum run value (which is repetition_max-1)
+ // As new request might be added in the meantime, this will be
+ // used to calculate the maximum cycle time.
+ if (context<find>().run_ < fsm->get_repetition_max()) {
+ context<find>().run_++;
+ uint32_t its_timeout = (outermost_context().repetitions_base_delay_
+ << context<find>().run_);
+ if (fsm->send(true, true))
+ outermost_context().start_timer(its_timeout, true);
+ }
+ else {
+ post_event(ev_none());
+ }
+ } else {
+ post_event(ev_none());
+ }
+}
+
+sc::result send::react(const ev_alt_timeout &_event) {
+ (void)_event;
+ return transit<send>();
+}
+
+sc::result send::react(const ev_none &_event) {
(void)_event;
- return transit<announce>();
+ return transit<idle>();
}
} // namespace _sd
@@ -187,7 +284,6 @@ service_discovery_fsm::service_discovery_fsm(
std::shared_ptr<service_discovery> _discovery)
: discovery_(_discovery), fsm_(
std::make_shared < _sd::fsm > (_discovery->get_io())) {
-
std::shared_ptr < service_discovery > discovery = discovery_.lock();
if (discovery) {
std::shared_ptr < configuration > its_configuration =
@@ -232,10 +328,10 @@ service_discovery_fsm::service_discovery_fsm(
if (fsm_->cyclic_offer_delay_ <= 0)
fsm_->cyclic_offer_delay_ = VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY;
- VSOMEIP_INFO << "SD configuration [" << fsm_->initial_delay_ << ":"
- << fsm_->repetitions_base_delay_ << ":"
- << (int) fsm_->repetitions_max_ << ":"
- << fsm_->cyclic_offer_delay_ << "]";
+ VSOMEIP_INFO << "SD configuration [" << std::dec << fsm_->initial_delay_ << ":"
+ << std::dec << fsm_->repetitions_base_delay_ << ":"
+ << std::dec << (int) fsm_->repetitions_max_ << ":"
+ << std::dec << fsm_->cyclic_offer_delay_ << "]";
} else {
VSOMEIP_ERROR << "SD initialization failed";
}
@@ -249,10 +345,57 @@ void service_discovery_fsm::start() {
void service_discovery_fsm::stop() {
}
-void service_discovery_fsm::send(bool _is_announcing) {
+bool service_discovery_fsm::send(bool _is_announcing, bool _is_find) {
std::shared_ptr < service_discovery > discovery = discovery_.lock();
- if (discovery)
- discovery->send(_is_announcing);
+ if (discovery) {
+ return discovery->send(_is_announcing, _is_find);
+ }
+ return false;
+}
+
+void service_discovery_fsm::send_unicast_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info,
+ service_t _service, instance_t _instance,
+ major_version_t _major,
+ minor_version_t _minor) {
+ std::shared_ptr < service_discovery > discovery = discovery_.lock();
+ if (discovery) {
+ discovery->send_unicast_offer_service(_info, _service,
+ _instance, _major, _minor );
+ }
+}
+
+void service_discovery_fsm::send_multicast_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info, service_t _service,
+ instance_t _instance, major_version_t _major, minor_version_t _minor) {
+ std::shared_ptr < service_discovery > discovery = discovery_.lock();
+ if (discovery) {
+ discovery->send_multicast_offer_service(_info, _service,
+ _instance, _major, _minor );
+ }
+}
+
+std::chrono::milliseconds service_discovery_fsm::get_elapsed_offer_timer() {
+ //get remaining time to next offer since last offer
+ std::chrono::milliseconds remaining =
+ std::chrono::milliseconds(fsm_->expired_from_now(false));
+
+ if( std::chrono::milliseconds(0) > remaining) {
+ remaining = std::chrono::milliseconds(fsm_->cyclic_offer_delay_);
+ }
+ return std::chrono::milliseconds(fsm_->cyclic_offer_delay_) - remaining;
+}
+
+bool service_discovery_fsm::check_is_multicast_offer() {
+ bool is_multicast(false);
+ std::chrono::milliseconds elapsed_ = get_elapsed_offer_timer();
+ uint32_t half_cyclic_offer_delay_ = fsm_->cyclic_offer_delay_ / 2;
+
+ if( elapsed_ >= std::chrono::milliseconds(half_cyclic_offer_delay_)) {
+ // Response must be a multicast offer (SIP_SD_90)
+ is_multicast = true;
+ }
+ return is_multicast;
}
} // namespace sd
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index b5493b8..10c6c96 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -40,7 +40,13 @@ service_discovery_impl::service_discovery_impl(service_discovery_host *_host)
serializer_(std::make_shared<serializer>()),
deserializer_(std::make_shared<deserializer>()),
ttl_timer_(_host->get_io()),
- smallest_ttl_(DEFAULT_TTL) {
+ smallest_ttl_(DEFAULT_TTL),
+ subscription_expiration_timer_(_host->get_io()) {
+ std::chrono::seconds smallest_ttl(DEFAULT_TTL);
+ smallest_ttl_ = std::chrono::duration_cast<std::chrono::milliseconds>(smallest_ttl);
+
+ // TODO: cleanup start condition!
+ next_subscription_expiration_ = std::chrono::high_resolution_clock::now() + std::chrono::hours(24);
}
service_discovery_impl::~service_discovery_impl() {
@@ -66,6 +72,8 @@ void service_discovery_impl::init() {
port_ = its_configuration->get_sd_port();
reliable_ = (its_configuration->get_sd_protocol()
== "tcp");
+ max_message_size_ = (reliable_ ? VSOMEIP_MAX_TCP_SD_PAYLOAD :
+ VSOMEIP_MAX_UDP_SD_PAYLOAD);
serializer_->create_data(
reliable_ ?
@@ -99,19 +107,26 @@ void service_discovery_impl::stop() {
void service_discovery_impl::request_service(service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor,
ttl_t _ttl) {
- std::lock_guard<std::mutex> its_lock(requested_mutex_);
- 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
+ bool is_new_request(true);
+ {
+ std::lock_guard<std::mutex> its_lock(requested_mutex_);
+ 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()) {
+ is_new_request = false;
+ // TODO: check version and report errors
+ } else {
+ find_service->second[_instance] = std::make_shared < request
+ > (_major, _minor, _ttl);
+ }
} else {
- find_service->second[_instance] = std::make_shared < request
+ requested_[_service][_instance] = std::make_shared < request
> (_major, _minor, _ttl);
}
- } else {
- requested_[_service][_instance] = std::make_shared < request
- > (_major, _minor, _ttl);
+ }
+ if (is_new_request) {
+ default_->process(ev_request_service());
}
}
@@ -123,11 +138,22 @@ void service_discovery_impl::release_service(service_t _service,
}
}
+std::shared_ptr<request>
+service_discovery_impl::find_request(service_t _service, instance_t _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()) {
+ return find_instance->second;
+ }
+ }
+ return nullptr;
+}
+
void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client,
subscription_type_e _subscription_type) {
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
-
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
auto found_instance = found_service->second.find(_instance);
@@ -138,6 +164,8 @@ void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
if (found_client != found_eventgroup->second.end()) {
if (found_client->second->get_major() == _major) {
found_client->second->set_ttl(_ttl);
+ found_client->second->set_expiration(std::chrono::high_resolution_clock::now()
+ + std::chrono::seconds(_ttl));
} else {
VSOMEIP_ERROR
<< "Subscriptions to different versions of the same "
@@ -157,25 +185,57 @@ void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
get_subscription_endpoints(_subscription_type, its_unreliable, its_reliable,
&its_address, &has_address, _service, _instance, _client);
+ const uint8_t max_parallel_subscriptions = 16; // 4Bit Counter field
+ uint8_t subscribe_count = static_cast<uint8_t>(subscribed_[_service][_instance][_eventgroup].size());
+ if (subscribe_count >= max_parallel_subscriptions) {
+ VSOMEIP_WARNING << "Too many parallel subscriptions (max.16) on same event group: "
+ << std::hex << _eventgroup << std::dec;
+ return;
+ }
+
// New subscription
std::shared_ptr < subscription > its_subscription = std::make_shared
- < subscription > (_major, _ttl, its_reliable, its_unreliable, _subscription_type);
+ < subscription > (_major, _ttl, its_reliable, its_unreliable,
+ _subscription_type, subscribe_count,
+ std::chrono::high_resolution_clock::time_point() + std::chrono::seconds(_ttl));
subscribed_[_service][_instance][_eventgroup][_client] = its_subscription;
-
if (has_address) {
std::shared_ptr<runtime> its_runtime = runtime_.lock();
if (!its_runtime)
return;
+ if (_client != VSOMEIP_ROUTING_CLIENT) {
+ if (its_subscription->get_endpoint(true) &&
+ !host_->has_identified(_client, _service, _instance, true)) {
+ return;
+ }
+ if (its_subscription->get_endpoint(false) &&
+ !host_->has_identified(_client, _service, _instance, false)) {
+ return;
+ }
+ }
+
std::shared_ptr<message_impl> its_message
= its_runtime->create_message();
-
- // TODO: consume major & ttl
- insert_subscription(its_message, _service, _instance, _eventgroup,
- its_subscription);
- serialize_and_send(its_message, its_address);
-
- its_subscription->set_acknowledged(false);
+ if (its_subscription->get_endpoint(true)
+ && its_subscription->get_endpoint(true)->is_connected()) {
+ insert_subscription(its_message,
+ _service, _instance,
+ _eventgroup,
+ its_subscription, true, true);
+ } else {
+ // don't insert reliable endpoint option if the
+ // TCP client endpoint is not yet connected
+ insert_subscription(its_message,
+ _service, _instance,
+ _eventgroup,
+ its_subscription, false, true);
+ its_subscription->set_tcp_connection_established(false);
+ }
+ if(0 < its_message->get_entries().size()) {
+ serialize_and_send(its_message, its_address);
+ its_subscription->set_acknowledged(false);
+ }
}
}
@@ -246,7 +306,7 @@ void service_discovery_impl::unsubscribe(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, client_t _client) {
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
-
+ std::shared_ptr < subscription > its_subscription;
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
auto found_instance = found_service->second.find(_instance);
@@ -255,42 +315,33 @@ void service_discovery_impl::unsubscribe(service_t _service,
if (found_eventgroup != found_instance->second.end()) {
auto found_client = found_eventgroup->second.find(_client);
if (found_client != found_eventgroup->second.end()) {
- found_client->second->set_ttl(0);
+ its_subscription = found_client->second;
+ its_subscription->set_ttl(0);
+ std::shared_ptr < runtime > its_runtime = runtime_.lock();
+ if (its_runtime) {
+ boost::asio::ip::address its_address;
+ auto endpoint = its_subscription->get_endpoint(false);
+ if (endpoint) {
+ endpoint->get_remote_address(its_address);
+ } else {
+ endpoint = its_subscription->get_endpoint(true);
+ if (endpoint) {
+ endpoint->get_remote_address(its_address);
+ } else {
+ return;
+ }
+ }
+ std::shared_ptr < message_impl > its_message = its_runtime->create_message();
+ insert_subscription(its_message, _service, _instance, _eventgroup,
+ its_subscription, true, true);
+ serialize_and_send(its_message, its_address);
+
+ found_eventgroup->second.erase(_client);
+ }
}
}
}
}
-
- boost::asio::ip::address its_address;
-
- std::shared_ptr < runtime > its_runtime = runtime_.lock();
- if (!its_runtime)
- return;
-
- std::shared_ptr < subscription > its_subscription =
- subscribed_[_service][_instance][_eventgroup][_client];
-
- auto endpoint = its_subscription->get_endpoint(false);
- if (endpoint) {
- endpoint->get_remote_address(its_address);
- } else {
- endpoint = its_subscription->get_endpoint(true);
- if (endpoint) {
- endpoint->get_remote_address(its_address);
- }
- }
-
- std::shared_ptr < message_impl > its_message
- = its_runtime->create_message();
-
- insert_subscription(its_message, _service, _instance, _eventgroup,
- its_subscription);
-
- std::pair<session_t, bool> its_session = get_session(its_address);
- its_message->set_session(its_session.first);
- its_message->set_reboot_flag(its_session.second);
-
- serialize_and_send(its_message, its_address);
}
void service_discovery_impl::unsubscribe_all(service_t _service, instance_t _instance) {
@@ -313,9 +364,9 @@ void service_discovery_impl::unsubscribe_all(service_t _service, instance_t _ins
std::pair<session_t, bool> service_discovery_impl::get_session(
const boost::asio::ip::address &_address) {
std::pair<session_t, bool> its_session;
- auto found_session = sessions_.find(_address);
- if (found_session == sessions_.end()) {
- its_session = sessions_[_address] = { 1, true };
+ auto found_session = sessions_sent_.find(_address);
+ if (found_session == sessions_sent_.end()) {
+ its_session = sessions_sent_[_address] = { 1, true };
} else {
its_session = found_session->second;
}
@@ -324,174 +375,363 @@ std::pair<session_t, bool> service_discovery_impl::get_session(
void service_discovery_impl::increment_session(
const boost::asio::ip::address &_address) {
- auto found_session = sessions_.find(_address);
- if (found_session != sessions_.end()) {
+ auto found_session = sessions_sent_.find(_address);
+ if (found_session != sessions_sent_.end()) {
found_session->second.first++;
- if (found_session->second.first == 0) { // Wrap
- found_session->second = { 1, false };
+ if (found_session->second.first == 0) { // Wrap --> change the reboot flag!
+ found_session->second = { 1, !found_session->second.second };
}
}
}
bool service_discovery_impl::is_reboot(
- const boost::asio::ip::address &_address,
+ const boost::asio::ip::address &_sender,
+ const boost::asio::ip::address &_destination,
bool _reboot_flag, session_t _session) {
-
bool result(false);
-#ifdef VSOMEIP_TODO
- // Reboot detection: Either the flag has changed from false to true,
- // or the session identifier overrun while the flag is true
- if (reboots_.find(_address) == reboots_.end()) {
- if (_reboot_flag) {
- reboots_.insert(_address);
- result = true;
- }
+
+ auto its_last_session = sessions_received_.find(_sender);
+ bool is_multicast = _destination.is_multicast();
+
+ session_t its_unicast_id = (is_multicast ? 0 : _session);
+ session_t its_multicast_id = (is_multicast ? _session : 0);
+
+ if (its_last_session == sessions_received_.end()) {
+ sessions_received_[_sender]
+ = std::make_tuple(its_multicast_id, its_unicast_id, _reboot_flag);
} else {
- auto its_last_session = sessions_receiving_.find(_address);
- if(its_last_session != sessions_receiving_.end()) {
- if (_reboot_flag && its_last_session->second >= _session) {
+ // Reboot detection: Either the flag has changed from false to true,
+ // or the session identifier overrun while the flag is true
+ if (its_last_session != sessions_received_.end()) {
+ if (!std::get<2>(its_last_session->second) && _reboot_flag) {
result = true;
+ } else {
+ session_t its_last_id = (is_multicast ?
+ std::get<0>(its_last_session->second) :
+ std::get<1>(its_last_session->second));
+
+ if (std::get<2>(its_last_session->second) && _reboot_flag &&
+ its_last_id >= _session) {
+ result = true;
+ }
}
}
+
+ if (result == false) {
+ // no reboot -> update session
+ if (is_multicast) {
+ std::get<0>(its_last_session->second) = its_multicast_id;
+ } else {
+ std::get<1>(its_last_session->second) = its_unicast_id;
+ }
+ } else {
+ // reboot -> reset the session
+ sessions_received_.erase(_sender);
+ }
}
- sessions_receiving_[_address] = _session;
-#else
- (void)_address;
- (void)_reboot_flag;
- (void)_session;
-#endif
return result;
}
+template<class Option, typename AddressType>
+std::shared_ptr<option_impl> service_discovery_impl::find_existing_option(
+ std::shared_ptr<message_impl> &_message,
+ AddressType _address,
+ uint16_t _port, layer_four_protocol_e _protocol,
+ option_type_e _option_type) {
+ if (_message->get_options().size() > 0) {
+ std::uint16_t option_length(0x0);
+ if(_option_type == option_type_e::IP4_ENDPOINT ||
+ _option_type == option_type_e::IP4_MULTICAST) {
+ option_length = 0x9;
+ } else if(_option_type == option_type_e::IP6_ENDPOINT ||
+ _option_type == option_type_e::IP6_MULTICAST) {
+ option_length = 0x15;
+ } else { // unsupported option type
+ return nullptr;
+ }
+
+ bool is_multicast(false);
+ if(_option_type == option_type_e::IP4_MULTICAST ||
+ _option_type == option_type_e::IP6_MULTICAST) {
+ is_multicast = true;
+ }
+
+ std::vector<std::shared_ptr<option_impl>> its_options =
+ _message->get_options();
+ for (const std::shared_ptr<option_impl>& opt : its_options) {
+ if (opt->get_length() == option_length &&
+ opt->get_type() == _option_type &&
+ std::static_pointer_cast<ip_option_impl>(opt)->get_layer_four_protocol() == _protocol &&
+ std::static_pointer_cast<ip_option_impl>(opt)->get_port() == _port &&
+ std::static_pointer_cast<ip_option_impl>(opt)->is_multicast() == is_multicast &&
+ std::static_pointer_cast<Option>(opt)->get_address() == _address) {
+ return opt;
+ }
+ }
+ }
+ return nullptr;
+}
+template<class Option, typename AddressType>
+bool service_discovery_impl::check_message_for_ip_option_and_assign_existing(
+ std::shared_ptr<message_impl> &_message,
+ std::shared_ptr<entry_impl> _entry, AddressType _address,
+ uint16_t _port, layer_four_protocol_e _protocol,
+ option_type_e _option_type) {
+
+ std::shared_ptr<option_impl> its_option
+ = find_existing_option<Option, AddressType>(_message, _address, _port, _protocol, _option_type);
+ if (its_option) {
+ _entry->assign_option(its_option);
+ return true;
+ }
+ return false;
+}
+
+template<class Option, typename AddressType>
+void service_discovery_impl::assign_ip_option_to_entry(
+ std::shared_ptr<Option> _option, AddressType _address,
+ uint16_t _port, layer_four_protocol_e _protocol,
+ std::shared_ptr<entry_impl> _entry) {
+ if (_option) {
+ _option->set_address(_address);
+ _option->set_port(_port);
+ _option->set_layer_four_protocol(_protocol);
+ _entry->assign_option(_option);
+ }
+}
+
void service_discovery_impl::insert_option(
std::shared_ptr<message_impl> &_message,
std::shared_ptr<entry_impl> _entry,
const boost::asio::ip::address &_address, uint16_t _port,
bool _is_reliable) {
+ layer_four_protocol_e its_protocol =
+ _is_reliable ? layer_four_protocol_e::TCP :
+ layer_four_protocol_e::UDP;
+ bool entry_assigned(false);
+
if (unicast_ == _address) {
if (unicast_.is_v4()) {
ipv4_address_t its_address = unicast_.to_v4().to_bytes();
- std::shared_ptr < ipv4_option_impl > its_option =
- _message->create_ipv4_option(false);
- if (its_option) {
- its_option->set_address(its_address);
- its_option->set_port(_port);
- its_option->set_layer_four_protocol(
- _is_reliable ? layer_four_protocol_e::TCP :
- layer_four_protocol_e::UDP);
- _entry->assign_option(its_option, 1);
+ entry_assigned = check_message_for_ip_option_and_assign_existing<
+ ipv4_option_impl, ipv4_address_t>(_message, _entry,
+ its_address, _port, its_protocol,
+ option_type_e::IP4_ENDPOINT);
+ if(!entry_assigned) {
+ std::shared_ptr < ipv4_option_impl > its_option =
+ _message->create_ipv4_option(false);
+ assign_ip_option_to_entry<ipv4_option_impl, ipv4_address_t>(
+ its_option, its_address, _port, its_protocol, _entry);
}
} else {
ipv6_address_t its_address = unicast_.to_v6().to_bytes();
- std::shared_ptr < ipv6_option_impl > its_option =
- _message->create_ipv6_option(false);
- if (its_option) {
- its_option->set_address(its_address);
- its_option->set_port(_port);
- its_option->set_layer_four_protocol(
- _is_reliable ? layer_four_protocol_e::TCP :
- layer_four_protocol_e::UDP);
- _entry->assign_option(its_option, 1);
+ entry_assigned = check_message_for_ip_option_and_assign_existing<
+ ipv6_option_impl, ipv6_address_t>(_message, _entry,
+ its_address, _port, its_protocol,
+ option_type_e::IP6_ENDPOINT);
+ if(!entry_assigned) {
+ std::shared_ptr < ipv6_option_impl > its_option =
+ _message->create_ipv6_option(false);
+ assign_ip_option_to_entry<ipv6_option_impl, ipv6_address_t>(
+ its_option, its_address, _port, its_protocol, _entry);
}
}
} else {
if (_address.is_v4()) {
ipv4_address_t its_address = _address.to_v4().to_bytes();
- std::shared_ptr < ipv4_option_impl > its_option =
- _message->create_ipv4_option(true);
- if (its_option) {
- its_option->set_address(its_address);
- its_option->set_port(_port);
- its_option->set_layer_four_protocol(
- _is_reliable ? layer_four_protocol_e::TCP :
- layer_four_protocol_e::UDP);
- _entry->assign_option(its_option, 1);
+ entry_assigned = check_message_for_ip_option_and_assign_existing<
+ ipv4_option_impl, ipv4_address_t>(_message, _entry,
+ its_address, _port, its_protocol,
+ option_type_e::IP4_MULTICAST);
+ if(!entry_assigned) {
+ std::shared_ptr < ipv4_option_impl > its_option =
+ _message->create_ipv4_option(true);
+ assign_ip_option_to_entry<ipv4_option_impl, ipv4_address_t>(
+ its_option, its_address, _port, its_protocol, _entry);
}
} else {
ipv6_address_t its_address = _address.to_v6().to_bytes();
- std::shared_ptr < ipv6_option_impl > its_option =
- _message->create_ipv6_option(true);
- if (its_option) {
- its_option->set_address(its_address);
- its_option->set_port(_port);
- its_option->set_layer_four_protocol(
- _is_reliable ? layer_four_protocol_e::TCP :
- layer_four_protocol_e::UDP);
- _entry->assign_option(its_option, 1);
+ entry_assigned = check_message_for_ip_option_and_assign_existing<
+ ipv6_option_impl, ipv6_address_t>(_message, _entry,
+ its_address, _port, its_protocol,
+ option_type_e::IP6_MULTICAST);
+ if(!entry_assigned) {
+ std::shared_ptr < ipv6_option_impl > its_option =
+ _message->create_ipv6_option(true);
+ assign_ip_option_to_entry<ipv6_option_impl, ipv6_address_t>(
+ its_option, its_address, _port, its_protocol, _entry);
}
}
}
}
void service_discovery_impl::insert_find_entries(
- std::shared_ptr<message_impl> &_message, requests_t &_requests) {
+ std::shared_ptr<message_impl> &_message, requests_t &_requests,
+ uint32_t _start, uint32_t &_size, bool &_done) {
std::lock_guard<std::mutex> its_lock(requested_mutex_);
+ uint32_t its_size(0);
+ uint32_t i = 0;
+
+ _done = true;
for (auto its_service : _requests) {
for (auto its_instance : its_service.second) {
auto its_request = its_instance.second;
- std::shared_ptr < serviceentry_impl > its_entry =
- _message->create_service_entry();
- if (its_entry) {
- its_entry->set_type(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_request->get_major());
- its_entry->set_minor_version(its_request->get_minor());
- its_entry->set_ttl(its_request->get_ttl());
- } else {
- VSOMEIP_ERROR << "Failed to create service entry!";
+ uint8_t its_sent_counter = its_request->get_sent_counter();
+ if (its_sent_counter != default_->get_repetition_max()) {
+ if (i >= _start) {
+ if (its_size + VSOMEIP_SOMEIP_SD_ENTRY_SIZE <= max_message_size_) {
+ std::shared_ptr < serviceentry_impl > its_entry =
+ _message->create_service_entry();
+ if (its_entry) {
+ its_entry->set_type(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_request->get_major());
+ its_entry->set_minor_version(its_request->get_minor());
+ its_entry->set_ttl(its_request->get_ttl());
+ its_size += VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
+
+ its_sent_counter++;
+ its_request->set_sent_counter(its_sent_counter);
+ } else {
+ VSOMEIP_ERROR << "Failed to create service entry!";
+ }
+ } else {
+ _done = false;
+ _size = its_size;
+ return;
+ }
+ }
}
+ i++;
}
}
+ _size = its_size;
}
void service_discovery_impl::insert_offer_entries(
- std::shared_ptr<message_impl> &_message, services_t &_services) {
+ std::shared_ptr<message_impl> &_message, services_t &_services,
+ uint32_t &_start, uint32_t _size, bool &_done) {
+ uint32_t i = 0;
+ uint32_t its_size(_size);
for (auto its_service : _services) {
for (auto its_instance : its_service.second) {
- insert_offer_service(_message, its_service.first,
- its_instance.first, its_instance.second);
+ // Only insert services with configured endpoint(s)
+ if (its_instance.second->get_endpoint(false)
+ || its_instance.second->get_endpoint(true)) {
+ if (i >= _start) {
+ if (!insert_offer_service(_message, its_service.first,
+ its_instance.first, its_instance.second, its_size)) {
+ _start = i;
+ _done = false;
+ return;
+ }
+ }
+ }
+ i++;
}
}
+ _start = i;
+ _done = true;
}
void service_discovery_impl::insert_subscription(
std::shared_ptr<message_impl> &_message, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<subscription> &_subscription) {
+ std::shared_ptr<subscription> &_subscription,
+ bool _insert_reliable, bool _insert_unreliable) {
+ if((_insert_reliable && !_insert_unreliable && !_subscription->get_endpoint(true)) ||
+ (_insert_unreliable && !_insert_reliable && !_subscription->get_endpoint(false))) {
+ // don't create an eventgroup entry if there isn't an endpoint option
+ // to insert
+ return;
+ }
std::shared_ptr < eventgroupentry_impl > its_entry =
_message->create_eventgroup_entry();
its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP);
its_entry->set_service(_service);
its_entry->set_instance(_instance);
its_entry->set_eventgroup(_eventgroup);
+ its_entry->set_counter(_subscription->get_counter());
its_entry->set_major_version(_subscription->get_major());
its_entry->set_ttl(_subscription->get_ttl());
- std::shared_ptr < endpoint > its_endpoint = _subscription->get_endpoint(
- true);
+ std::shared_ptr < endpoint > its_endpoint;
+ if (_insert_reliable) {
+ its_endpoint = _subscription->get_endpoint(true);
+ if (its_endpoint) {
+ insert_option(_message, its_entry, unicast_,
+ its_endpoint->get_local_port(), true);
+ }
+ }
+ if (_insert_unreliable) {
+ its_endpoint = _subscription->get_endpoint(false);
+ if (its_endpoint) {
+ insert_option(_message, its_entry, unicast_,
+ its_endpoint->get_local_port(), false);
+ }
+ }
+}
+
+void service_discovery_impl::insert_nack_subscription_on_resubscribe(std::shared_ptr<message_impl> &_message,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ std::shared_ptr<subscription> &_subscription) {
+
+ // SIP_SD_844:
+ // This method is used for not acknowledged subscriptions on renew subscription
+ // Two entries: Stop subscribe & subscribe within one SD-Message
+ // One option: Both entries reference it
+
+ std::shared_ptr < eventgroupentry_impl > its_stop_entry =
+ _message->create_eventgroup_entry();
+ its_stop_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP);
+ its_stop_entry->set_service(_service);
+ its_stop_entry->set_instance(_instance);
+ its_stop_entry->set_eventgroup(_eventgroup);
+ its_stop_entry->set_counter(_subscription->get_counter());
+ its_stop_entry->set_major_version(_subscription->get_major());
+ its_stop_entry->set_ttl(0);
+
+ std::shared_ptr < eventgroupentry_impl > its_entry =
+ _message->create_eventgroup_entry();
+ its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP);
+ its_entry->set_service(_service);
+ its_entry->set_instance(_instance);
+ its_entry->set_eventgroup(_eventgroup);
+ its_entry->set_counter(_subscription->get_counter());
+ its_entry->set_major_version(_subscription->get_major());
+ its_entry->set_ttl(_subscription->get_ttl());
+
+ std::shared_ptr < endpoint > its_endpoint;
+ its_endpoint = _subscription->get_endpoint(true);
if (its_endpoint) {
- insert_option(_message, its_entry, unicast_, its_endpoint->get_local_port(),
- true);
+ insert_option(_message, its_stop_entry, unicast_,
+ its_endpoint->get_local_port(), true);
+ insert_option(_message, its_entry, unicast_,
+ its_endpoint->get_local_port(), true);
}
its_endpoint = _subscription->get_endpoint(false);
if (its_endpoint) {
- insert_option(_message, its_entry, unicast_, its_endpoint->get_local_port(),
- false);
+ insert_option(_message, its_stop_entry, unicast_,
+ its_endpoint->get_local_port(), false);
+ insert_option(_message, its_entry, unicast_,
+ its_endpoint->get_local_port(), false);
}
}
void service_discovery_impl::insert_subscription_ack(
std::shared_ptr<message_impl> &_message, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl) {
+ std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl, uint8_t _counter, major_version_t _major, uint16_t _reserved) {
std::shared_ptr < eventgroupentry_impl > its_entry =
_message->create_eventgroup_entry();
its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP_ACK);
its_entry->set_service(_service);
its_entry->set_instance(_instance);
its_entry->set_eventgroup(_eventgroup);
- its_entry->set_major_version(_info->get_major());
+ its_entry->set_major_version(_major);
+ its_entry->set_reserved(_reserved);
+ its_entry->set_counter(_counter);
// SWS_SD_00315
its_entry->set_ttl(_ttl);
@@ -505,7 +745,7 @@ void service_discovery_impl::insert_subscription_ack(
void service_discovery_impl::insert_subscription_nack(
std::shared_ptr<message_impl> &_message, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<eventgroupinfo> &_info) {
+ uint8_t _counter, major_version_t _major, uint16_t _reserved) {
std::shared_ptr < eventgroupentry_impl > its_entry =
_message->create_eventgroup_entry();
// SWS_SD_00316 and SWS_SD_00385
@@ -513,51 +753,75 @@ void service_discovery_impl::insert_subscription_nack(
its_entry->set_service(_service);
its_entry->set_instance(_instance);
its_entry->set_eventgroup(_eventgroup);
- its_entry->set_major_version(_info->get_major());
+ its_entry->set_major_version(_major);
+ its_entry->set_reserved(_reserved);
+ its_entry->set_counter(_counter);
// SWS_SD_00432
its_entry->set_ttl(0x0);
-
- boost::asio::ip::address its_address;
- uint16_t its_port;
- if (_info->get_multicast(its_address, its_port)) {
- insert_option(_message, its_entry, its_address, its_port, false);
- }
}
-void service_discovery_impl::send(bool _is_announcing) {
-
+bool service_discovery_impl::send(bool _is_announcing, bool _is_find) {
std::shared_ptr < runtime > its_runtime = runtime_.lock();
- if (!its_runtime)
- return;
-
- std::shared_ptr < message_impl > its_message =
- its_runtime->create_message();
-
- // TODO: optimize building of SD message (common options, utilize the two runs)
-
- // If we are not in main phase, include "FindOffer"-entries
- if (!_is_announcing) {
- insert_find_entries(its_message, requested_);
- }
+ if (its_runtime) {
+ std::vector< std::shared_ptr< message_impl > > its_messages;
+ std::shared_ptr < message_impl > its_message;
+
+ uint32_t its_remaining(max_message_size_);
+
+ if (_is_find || !_is_announcing) {
+ uint32_t its_start(0);
+ uint32_t its_size(0);
+ bool is_done(false);
+ while (!is_done) {
+ its_message = its_runtime->create_message();
+ its_messages.push_back(its_message);
+
+ insert_find_entries(its_message, requested_, its_start, its_size, is_done);
+ its_start += its_size / VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
+ };
+ its_remaining -= its_size;
+ } else {
+ its_message = its_runtime->create_message();
+ its_messages.push_back(its_message);
+ }
- // Always include the "OfferService"-entries for the service group
- services_t its_offers = host_->get_offered_services();
- insert_offer_entries(its_message, its_offers);
+ if (!_is_find) {
+ services_t its_offers = host_->get_offered_services();
+
+ uint32_t its_start(0);
+ bool is_done(false);
+ while (!is_done) {
+ insert_offer_entries(its_message, its_offers, its_start, its_remaining, is_done);
+ if (!is_done) {
+ its_remaining = max_message_size_;
+ its_message = its_runtime->create_message();
+ its_messages.push_back(its_message);
+ }
+ }
+ }
- // Serialize and send
- if (its_message->get_entries().size() > 0) {
- std::pair<session_t, bool> its_session = get_session(unicast_);
- its_message->set_session(its_session.first);
- its_message->set_reboot_flag(its_session.second);
- if (host_->send(VSOMEIP_SD_CLIENT, its_message, true)) {
- increment_session (unicast_);
+ // Serialize and send
+ bool has_sent(false);
+ for (auto m : its_messages) {
+ if (m->get_entries().size() > 0) {
+ std::pair<session_t, bool> its_session = get_session(unicast_);
+ m->set_session(its_session.first);
+ m->set_reboot_flag(its_session.second);
+ if (host_->send(VSOMEIP_SD_CLIENT, m, true)) {
+ increment_session(unicast_);
+ }
+ has_sent = true;
+ }
}
+ return has_sent;
}
+ return false;
}
// Interface endpoint_host
void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
- const boost::asio::ip::address &_sender) {
+ const boost::asio::ip::address &_sender,
+ const boost::asio::ip::address &_destination) {
#if 0
std::stringstream msg;
msg << "sdi::on_message: ";
@@ -574,30 +838,51 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
return;
}
// Expire all subscriptions / services in case of reboot
- if (is_reboot(_sender,
+ if (is_reboot(_sender, _destination,
its_message->get_reboot_flag(), its_message->get_session())) {
host_->expire_subscriptions(_sender);
host_->expire_services(_sender);
}
- ttl_t expired = stop_ttl_timer();
+ std::chrono::milliseconds expired = stop_ttl_timer();
smallest_ttl_ = host_->update_routing_info(expired);
std::vector < std::shared_ptr<option_impl> > its_options =
its_message->get_options();
+
+ std::shared_ptr<runtime> its_runtime = runtime_.lock();
+ if (!its_runtime) {
+ return;
+ }
+
+ std::shared_ptr < message_impl > its_message_response
+ = its_runtime->create_message();
+ std::vector <accepted_subscriber_t> accepted_subscribers;
+
for (auto its_entry : its_message->get_entries()) {
if (its_entry->is_service_entry()) {
std::shared_ptr < serviceentry_impl > its_service_entry =
std::dynamic_pointer_cast < serviceentry_impl
> (its_entry);
- process_serviceentry(its_service_entry, its_options);
+ bool its_unicast_flag = its_message->get_unicast_flag();
+ process_serviceentry(its_service_entry, its_options, its_unicast_flag );
} else {
std::shared_ptr < eventgroupentry_impl > its_eventgroup_entry =
std::dynamic_pointer_cast < eventgroupentry_impl
> (its_entry);
- process_eventgroupentry(its_eventgroup_entry, its_options);
+ process_eventgroupentry( its_eventgroup_entry, its_options, its_message_response, accepted_subscribers);
}
}
+
+ //send ACK / NACK if present
+ if( 0 < its_message_response->get_entries().size() && its_message_response ) {
+ serialize_and_send(its_message_response, _sender);
+ }
+
+ for( const auto &a : accepted_subscribers) {
+ host_->on_subscribe(a.service_id, a.instance_id, a.eventgroup_, a.subscriber, a.target, a.its_expiration);
+ }
+ accepted_subscribers.clear();
start_ttl_timer();
} else {
VSOMEIP_ERROR << "service_discovery_impl::on_message: deserialization error.";
@@ -612,7 +897,8 @@ void service_discovery_impl::on_offer_change() {
// Entry processing
void service_discovery_impl::process_serviceentry(
std::shared_ptr<serviceentry_impl> &_entry,
- const std::vector<std::shared_ptr<option_impl> > &_options) {
+ const std::vector<std::shared_ptr<option_impl> > &_options,
+ bool _unicast_flag) {
// Read service info from entry
entry_type_e its_type = _entry->get_type();
@@ -629,56 +915,60 @@ void service_discovery_impl::process_serviceentry(
boost::asio::ip::address its_unreliable_address;
uint16_t its_unreliable_port(ILLEGAL_PORT);
-
for (auto i : { 1, 2 }) {
for (auto its_index : _entry->get_options(uint8_t(i))) {
- std::shared_ptr < option_impl > its_option = _options[its_index];
+ if( _options.size() > its_index ) {
+ std::shared_ptr < option_impl > its_option = _options[its_index];
- switch (its_option->get_type()) {
- case option_type_e::IP4_ENDPOINT: {
- std::shared_ptr < ipv4_option_impl > its_ipv4_option =
- std::dynamic_pointer_cast < ipv4_option_impl
- > (its_option);
+ switch (its_option->get_type()) {
+ case option_type_e::IP4_ENDPOINT: {
+ std::shared_ptr < ipv4_option_impl > its_ipv4_option =
+ std::dynamic_pointer_cast < ipv4_option_impl
+ > (its_option);
- boost::asio::ip::address_v4 its_ipv4_address(
- its_ipv4_option->get_address());
+ boost::asio::ip::address_v4 its_ipv4_address(
+ its_ipv4_option->get_address());
- if (its_ipv4_option->get_layer_four_protocol()
- == layer_four_protocol_e::UDP) {
- its_unreliable_address = its_ipv4_address;
- its_unreliable_port = its_ipv4_option->get_port();
- } else {
- its_reliable_address = its_ipv4_address;
- its_reliable_port = its_ipv4_option->get_port();
+ if (its_ipv4_option->get_layer_four_protocol()
+ == layer_four_protocol_e::UDP) {
+
+
+ its_unreliable_address = its_ipv4_address;
+ its_unreliable_port = its_ipv4_option->get_port();
+ } else {
+ its_reliable_address = its_ipv4_address;
+ its_reliable_port = its_ipv4_option->get_port();
+ }
+ break;
}
- break;
- }
- case option_type_e::IP6_ENDPOINT: {
- std::shared_ptr < ipv6_option_impl > its_ipv6_option =
- std::dynamic_pointer_cast < ipv6_option_impl
- > (its_option);
+ case option_type_e::IP6_ENDPOINT: {
+ std::shared_ptr < ipv6_option_impl > its_ipv6_option =
+ std::dynamic_pointer_cast < ipv6_option_impl
+ > (its_option);
- boost::asio::ip::address_v6 its_ipv6_address(
- its_ipv6_option->get_address());
+ boost::asio::ip::address_v6 its_ipv6_address(
+ its_ipv6_option->get_address());
- if (its_ipv6_option->get_layer_four_protocol()
- == layer_four_protocol_e::UDP) {
- its_unreliable_address = its_ipv6_address;
- its_unreliable_port = its_ipv6_option->get_port();
- } else {
- its_reliable_address = its_ipv6_address;
- its_reliable_port = its_ipv6_option->get_port();
+ if (its_ipv6_option->get_layer_four_protocol()
+ == layer_four_protocol_e::UDP) {
+ its_unreliable_address = its_ipv6_address;
+ its_unreliable_port = its_ipv6_option->get_port();
+ } else {
+ its_reliable_address = its_ipv6_address;
+ its_reliable_port = its_ipv6_option->get_port();
+ }
+ break;
+ }
+ case option_type_e::IP4_MULTICAST:
+ case option_type_e::IP6_MULTICAST:
+ break;
+ case option_type_e::CONFIGURATION:
+ break;
+ case option_type_e::UNKNOWN:
+ default:
+ VSOMEIP_ERROR << "Unsupported service option";
+ break;
}
- break;
- }
- case option_type_e::IP4_MULTICAST:
- case option_type_e::IP6_MULTICAST:
- VSOMEIP_ERROR << "Invalid service option (Multicast)";
- break;
- case option_type_e::UNKNOWN:
- default:
- VSOMEIP_ERROR << "Unsupported service option";
- break;
}
}
}
@@ -687,7 +977,7 @@ void service_discovery_impl::process_serviceentry(
switch(its_type) {
case entry_type_e::FIND_SERVICE:
process_findservice_serviceentry(its_service, its_instance,
- its_major, its_minor);
+ its_major, its_minor, _unicast_flag);
break;
case entry_type_e::OFFER_SERVICE:
process_offerservice_serviceentry(its_service, its_instance,
@@ -701,6 +991,10 @@ void service_discovery_impl::process_serviceentry(
}
} else {
+ std::shared_ptr<request> its_request = find_request(its_service, its_instance);
+ if (its_request)
+ its_request->set_sent_counter(default_->get_repetition_max());
+
unsubscribe_all(its_service, its_instance);
host_->del_routing_info(its_service, its_instance,
(its_reliable_port != ILLEGAL_PORT),
@@ -719,6 +1013,10 @@ void service_discovery_impl::process_offerservice_serviceentry(
if (!its_runtime)
return;
+ std::shared_ptr<request> its_request = find_request(_service, _instance);
+ if (its_request)
+ its_request->set_sent_counter(default_->get_repetition_max());
+
host_->add_routing_info(_service, _instance,
_major, _minor, _ttl,
_reliable_address, _reliable_port,
@@ -732,31 +1030,54 @@ void service_discovery_impl::process_offerservice_serviceentry(
if (0 < found_instance->second.size()) {
std::shared_ptr<message_impl> its_message
= its_runtime->create_message();
-
for (auto its_eventgroup : found_instance->second) {
for (auto its_client : its_eventgroup.second) {
+ if (its_client.first != VSOMEIP_ROUTING_CLIENT) {
+ if (its_client.second->get_endpoint(true) &&
+ !host_->has_identified(its_client.first, _service,
+ _instance, true)) {
+ continue;
+ }
+ if (its_client.second->get_endpoint(false) &&
+ !host_->has_identified(its_client.first, _service,
+ _instance, false)) {
+ continue;
+ }
+ }
std::shared_ptr<subscription> its_subscription(its_client.second);
+ std::shared_ptr<endpoint> its_unreliable;
+ std::shared_ptr<endpoint> its_reliable;
+ bool has_address(false);
+ boost::asio::ip::address its_address;
+ get_subscription_endpoints(
+ its_client.second->get_subscription_type(),
+ its_unreliable, its_reliable, &its_address,
+ &has_address, _service, _instance,
+ its_client.first);
+ its_subscription->set_endpoint(its_reliable, true);
+ its_subscription->set_endpoint(its_unreliable, false);
if (its_subscription->is_acknowledged()) {
- std::shared_ptr<endpoint> its_unreliable;
- std::shared_ptr<endpoint> its_reliable;
- bool has_address(false);
- boost::asio::ip::address its_address;
- get_subscription_endpoints(
- its_client.second->get_subscription_type(),
- its_unreliable, its_reliable, &its_address,
- &has_address, _service, _instance,
- its_client.first);
- its_subscription->set_endpoint(its_reliable, true);
- its_subscription->set_endpoint(its_unreliable,
- false);
-
- // TODO: consume major & ttl
- insert_subscription(its_message,
- _service, _instance,
- its_eventgroup.first,
- its_subscription);
+ if (its_subscription->get_endpoint(true)
+ && its_subscription->get_endpoint(true)->is_connected()) {
+ insert_subscription(its_message,
+ _service, _instance,
+ its_eventgroup.first,
+ its_subscription, true, true);
+ } else {
+ // don't insert reliable endpoint option if the
+ // TCP client endpoint is not yet connected
+ insert_subscription(its_message,
+ _service, _instance,
+ its_eventgroup.first,
+ its_subscription, false, true);
+ its_client.second->set_tcp_connection_established(false);
+ }
its_subscription->set_acknowledged(false);
+ } else {
+ insert_nack_subscription_on_resubscribe(its_message,
+ _service, _instance, its_eventgroup.first,
+ its_subscription);
}
}
}
@@ -780,7 +1101,7 @@ void service_discovery_impl::process_offerservice_serviceentry(
serializer_->serialize(its_message.get());
if (host_->send_to(its_target,
serializer_->get_data(),
- serializer_->get_size())) {
+ serializer_->get_size(), port_)) {
increment_session(its_target->get_address());
}
serializer_->reset();
@@ -793,7 +1114,7 @@ void service_discovery_impl::process_offerservice_serviceentry(
void service_discovery_impl::process_findservice_serviceentry(
service_t _service, instance_t _instance, major_version_t _major,
- minor_version_t _minor) {
+ minor_version_t _minor, bool _unicast_flag) {
services_t offered_services = host_->get_offered_services();
auto found_service = offered_services.find(_service);
if (found_service != offered_services.end()) {
@@ -801,14 +1122,18 @@ void service_discovery_impl::process_findservice_serviceentry(
auto found_instance = found_service->second.find(_instance);
if (found_instance != found_service->second.end()) {
std::shared_ptr<serviceinfo> its_info = found_instance->second;
- send_unicast_offer_service(its_info, _service, _instance,
- _major, _minor);
+
+ ev_find_service find_event(its_info, _service,
+ _instance, _major, _minor, _unicast_flag );
+ default_->process(find_event);
}
} else {
// send back all available instances
for (const auto &found_instance : found_service->second) {
- send_unicast_offer_service(found_instance.second, _service,
- _instance, _major, _minor);
+
+ ev_find_service find_event(found_instance.second, _service,
+ _instance, _major, _minor, _unicast_flag );
+ default_->process(find_event);
}
}
}
@@ -818,76 +1143,224 @@ void service_discovery_impl::send_unicast_offer_service(
const std::shared_ptr<const serviceinfo> &_info, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor) {
if (_major == ANY_MAJOR || _major == _info->get_major()) {
- if (_minor == 0xFFFFFFFF || _minor == _info->get_minor()) {
+ if (_minor == 0xFFFFFFFF || _minor <= _info->get_minor()) {
std::shared_ptr<runtime> its_runtime = runtime_.lock();
if (!its_runtime) {
return;
}
std::shared_ptr<message_impl> its_message =
its_runtime->create_message();
- insert_offer_service(its_message, _service, _instance, _info);
+
+ uint32_t its_size(max_message_size_);
+ insert_offer_service(its_message, _service, _instance, _info, its_size);
serialize_and_send(its_message, get_current_remote_address());
}
}
}
-void service_discovery_impl::insert_offer_service(
+void service_discovery_impl::send_multicast_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info, service_t _service,
+ instance_t _instance, major_version_t _major, minor_version_t _minor) {
+ if (_major == ANY_MAJOR || _major == _info->get_major()) {
+ if (_minor == 0xFFFFFFFF || _minor <= _info->get_minor()) {
+ std::shared_ptr<runtime> its_runtime = runtime_.lock();
+ if (!its_runtime) {
+ return;
+ }
+ std::shared_ptr<message_impl> its_message =
+ its_runtime->create_message();
+
+ uint32_t its_size(max_message_size_);
+ insert_offer_service(its_message, _service, _instance, _info, its_size);
+
+ if (its_message->get_entries().size() > 0) {
+ std::pair<session_t, bool> its_session = get_session(unicast_);
+ its_message->set_session(its_session.first);
+ its_message->set_reboot_flag(its_session.second);
+ if (host_->send(VSOMEIP_SD_CLIENT, its_message, true)) {
+ increment_session(unicast_);
+ }
+ }
+ }
+ }
+}
+
+void service_discovery_impl::on_reliable_endpoint_connected(
+ service_t _service, instance_t _instance,
+ const std::shared_ptr<const vsomeip::endpoint> &_endpoint) {
+ std::shared_ptr<runtime> its_runtime = runtime_.lock();
+ if (!its_runtime) {
+ return;
+ }
+
+ // send out subscriptions for services where the tcp connection
+ // wasn't established at time of subscription
+
+ std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
+
+ auto found_service = subscribed_.find(_service);
+ if (found_service != subscribed_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ if(0 < found_instance->second.size()) {
+ std::shared_ptr<message_impl> its_message(its_runtime->create_message());
+ bool has_address(false);
+ boost::asio::ip::address its_address;
+
+ for(const auto &its_eventgroup : found_instance->second) {
+ for(const auto &its_client : its_eventgroup.second) {
+ if (its_client.first != VSOMEIP_ROUTING_CLIENT) {
+ if (its_client.second->get_endpoint(true) &&
+ !host_->has_identified(its_client.first, _service,
+ _instance, true)) {
+ continue;
+ }
+ }
+ std::shared_ptr<subscription> its_subscription(its_client.second);
+ if(its_subscription && !its_subscription->is_tcp_connection_established()) {
+ const std::shared_ptr<const endpoint> its_endpoint(
+ its_subscription->get_endpoint(true));
+ if(its_endpoint && its_endpoint->is_connected()) {
+ if(its_endpoint.get() == _endpoint.get()) {
+ // mark as established
+ its_subscription->set_tcp_connection_established(true);
+
+ std::shared_ptr<endpoint> its_unreliable;
+ std::shared_ptr<endpoint> its_reliable;
+ get_subscription_endpoints(
+ its_subscription->get_subscription_type(),
+ its_unreliable, its_reliable, &its_address,
+ &has_address, _service, _instance,
+ its_client.first);
+ its_subscription->set_endpoint(its_reliable, true);
+ its_subscription->set_endpoint(its_unreliable, false);
+ // only insert reliable subscriptions as unreliable
+ // ones are immediately sent out
+ insert_subscription(its_message, _service,
+ _instance, its_eventgroup.first,
+ its_subscription, true, false);
+ its_subscription->set_acknowledged(false);
+ }
+ }
+ }
+ }
+ }
+ if (0 < its_message->get_entries().size() && has_address) {
+ serialize_and_send(its_message, its_address);
+ }
+ }
+ }
+ }
+}
+
+bool service_discovery_impl::insert_offer_service(
std::shared_ptr < message_impl > _message, service_t _service,
- instance_t _instance, const std::shared_ptr<const serviceinfo> &_info) {
- std::shared_ptr < serviceentry_impl > its_entry =
- _message->create_service_entry();
- if (its_entry) {
- its_entry->set_type(entry_type_e::OFFER_SERVICE);
- its_entry->set_service(_service);
- its_entry->set_instance(_instance);
- its_entry->set_major_version(_info->get_major());
- its_entry->set_minor_version(_info->get_minor());
-
- ttl_t its_ttl = _info->get_ttl();
- if (its_ttl > 0)
- its_ttl = ttl_;
- its_entry->set_ttl(its_ttl);
-
- std::shared_ptr < endpoint > its_endpoint =
- _info->get_endpoint(true);
- if (its_endpoint) {
- insert_option(_message, its_entry, unicast_,
- its_endpoint->get_local_port(), true);
- if (0 == _info->get_ttl()) {
- host_->del_routing_info(_service,
- _instance, true, false);
+ instance_t _instance, const std::shared_ptr<const serviceinfo> &_info,
+ uint32_t &_size) {
+
+ std::shared_ptr < endpoint > its_reliable = _info->get_endpoint(true);
+ std::shared_ptr < endpoint > its_unreliable = _info->get_endpoint(false);
+
+ uint32_t its_size = VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
+ if (its_reliable) {
+ uint32_t its_endpoint_size(0);
+ if (unicast_.is_v4()) {
+ if (!find_existing_option<ipv4_option_impl, ipv4_address_t>(_message,
+ unicast_.to_v4().to_bytes(), its_reliable->get_local_port(),
+ layer_four_protocol_e::TCP, option_type_e::IP4_ENDPOINT)) {
+ its_endpoint_size = VSOMEIP_SOMEIP_SD_IPV4_OPTION_SIZE;
+ }
+ } else {
+ if (!find_existing_option<ipv6_option_impl, ipv6_address_t>(_message,
+ unicast_.to_v6().to_bytes(), its_reliable->get_local_port(),
+ layer_four_protocol_e::TCP, option_type_e::IP6_ENDPOINT)) {
+ its_endpoint_size = VSOMEIP_SOMEIP_SD_IPV6_OPTION_SIZE;
}
}
+ its_size += its_endpoint_size;
+ }
+ if (its_unreliable) {
+ uint32_t its_endpoint_size(0);
+ if (unicast_.is_v4()) {
+ if (!find_existing_option<ipv4_option_impl, ipv4_address_t>(_message,
+ unicast_.to_v4().to_bytes(), its_unreliable->get_local_port(),
+ layer_four_protocol_e::UDP, option_type_e::IP4_ENDPOINT)) {
+ its_endpoint_size = VSOMEIP_SOMEIP_SD_IPV4_OPTION_SIZE;
+ }
+ } else {
+ if (!find_existing_option<ipv6_option_impl, ipv6_address_t>(_message,
+ unicast_.to_v6().to_bytes(), its_reliable->get_local_port(),
+ layer_four_protocol_e::UDP, option_type_e::IP6_ENDPOINT)) {
+ its_endpoint_size = VSOMEIP_SOMEIP_SD_IPV6_OPTION_SIZE;
+ }
+ }
+ its_size += its_endpoint_size;
+ }
- its_endpoint = _info->get_endpoint(false);
- if (its_endpoint) {
- insert_option(_message, its_entry, unicast_,
- its_endpoint->get_local_port(), false);
- if (0 == _info->get_ttl()) {
- host_->del_routing_info(_service,
- _instance, false, true);
+ if (its_size <= _size) {
+ _size -= its_size;
+
+ std::shared_ptr < serviceentry_impl > its_entry =
+ _message->create_service_entry();
+ if (its_entry) {
+ its_entry->set_type(entry_type_e::OFFER_SERVICE);
+ its_entry->set_service(_service);
+ its_entry->set_instance(_instance);
+ its_entry->set_major_version(_info->get_major());
+ its_entry->set_minor_version(_info->get_minor());
+
+ ttl_t its_ttl = _info->get_ttl();
+ if (its_ttl > 0)
+ its_ttl = ttl_;
+ its_entry->set_ttl(its_ttl);
+
+ if (its_reliable) {
+ insert_option(_message, its_entry, unicast_,
+ its_reliable->get_local_port(), true);
+ if (0 == _info->get_ttl()) {
+ host_->del_routing_info(_service,
+ _instance, true, false);
+ }
+ }
+
+ if (its_unreliable) {
+ insert_option(_message, its_entry, unicast_,
+ its_unreliable->get_local_port(), false);
+ if (0 == _info->get_ttl()) {
+ host_->del_routing_info(_service,
+ _instance, false, true);
+ }
}
+ // This would be a clean solution but does _not_ work with the ANDi tool
+ //unsubscribe_all(_service, _instance);
+ } else {
+ VSOMEIP_ERROR << "Failed to create service entry.";
}
- } else {
- VSOMEIP_ERROR << "Failed to create service entry.";
+ return true;
}
+
+ return false;
}
void service_discovery_impl::process_eventgroupentry(
std::shared_ptr<eventgroupentry_impl> &_entry,
- const std::vector<std::shared_ptr<option_impl> > &_options) {
+ const std::vector<std::shared_ptr<option_impl> > &_options,
+ std::shared_ptr < message_impl > &its_message_response,
+ std::vector <accepted_subscriber_t> &accepted_subscribers) {
service_t its_service = _entry->get_service();
instance_t its_instance = _entry->get_instance();
eventgroup_t its_eventgroup = _entry->get_eventgroup();
entry_type_e its_type = _entry->get_type();
major_version_t its_major = _entry->get_major_version();
ttl_t its_ttl = _entry->get_ttl();
+ uint16_t its_reserved = _entry->get_reserved();
+ uint8_t its_counter = _entry->get_counter();
if (_entry->get_owning_message()->get_return_code() != return_code) {
VSOMEIP_ERROR << "Invalid return code in SD header";
- send_eventgroup_subscription_nack(its_service, its_instance,
- its_eventgroup, its_major);
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
return;
}
@@ -895,30 +1368,35 @@ void service_discovery_impl::process_eventgroupentry(
if (_entry->get_num_options(1) == 0
&& _entry->get_num_options(2) == 0) {
VSOMEIP_ERROR << "Invalid number of options in SubscribeEventGroup entry";
- send_eventgroup_subscription_nack(its_service, its_instance,
- its_eventgroup, its_major);
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
return;
}
if(_entry->get_owning_message()->get_options_length() < 12) {
VSOMEIP_ERROR << "Invalid options length in SD message";
- send_eventgroup_subscription_nack(its_service, its_instance,
- its_eventgroup, its_major);
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
return;
}
if (_options.size()
- < (_entry->get_num_options(1) + _entry->get_num_options(2))) {
+ // cast is needed in order to get unsigned type since int will be promoted
+ // by the + operator on 16 bit or higher machines.
+ < static_cast<std::vector<std::shared_ptr<option_impl>>::size_type>(
+ (_entry->get_num_options(1)) + (_entry->get_num_options(2)))) {
VSOMEIP_ERROR << "Fewer options in SD message than "
- "referenced in EventGroup entry";
- send_eventgroup_subscription_nack(its_service, its_instance,
- its_eventgroup, its_major);
+ "referenced in EventGroup entry or malformed option received";
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
return;
}
}
- boost::asio::ip::address its_reliable_address;
- uint16_t its_reliable_port(ILLEGAL_PORT);
- boost::asio::ip::address its_unreliable_address;
- uint16_t its_unreliable_port(ILLEGAL_PORT);
+ boost::asio::ip::address its_first_address;
+ uint16_t its_first_port(ILLEGAL_PORT);
+ bool is_first_reliable(false);
+ boost::asio::ip::address its_second_address;
+ uint16_t its_second_port(ILLEGAL_PORT);
+ bool is_second_reliable(false);
for (auto i : { 1, 2 }) {
for (auto its_index : _entry->get_options(uint8_t(i))) {
@@ -926,12 +1404,15 @@ void service_discovery_impl::process_eventgroupentry(
try {
its_option = _options.at(its_index);
} catch(const std::out_of_range& e) {
+#ifdef WIN32
+ e; // silence MSVC warining C4101
+#endif
VSOMEIP_ERROR << "Fewer options in SD message than "
"referenced in EventGroup entry for "
"option run number: " << i;
if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) {
- send_eventgroup_subscription_nack(its_service, its_instance,
- its_eventgroup, its_major);
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
}
return;
}
@@ -945,18 +1426,40 @@ void service_discovery_impl::process_eventgroupentry(
boost::asio::ip::address_v4 its_ipv4_address(
its_ipv4_option->get_address());
if (!check_layer_four_protocol(its_ipv4_option)) {
- send_eventgroup_subscription_nack(its_service,
- its_instance, its_eventgroup, its_major);
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
return;
}
- // TODO: add error handling (port already set) here
- if (its_ipv4_option->get_layer_four_protocol()
- == layer_four_protocol_e::UDP) {
- its_unreliable_address = its_ipv4_address;
- its_unreliable_port = its_ipv4_option->get_port();
+
+ if (its_first_port == ILLEGAL_PORT) {
+ its_first_address = its_ipv4_address;
+ its_first_port = its_ipv4_option->get_port();
+ is_first_reliable = (its_ipv4_option->get_layer_four_protocol()
+ == layer_four_protocol_e::TCP);
+
+ if(!check_ipv4_address(its_first_address)
+ || 0 == its_first_port) {
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
+ VSOMEIP_ERROR << "Invalid port or IP address in first endpoint option specified!";
+ return;
+ }
+ } else
+ if (its_second_port == ILLEGAL_PORT) {
+ its_second_address = its_ipv4_address;
+ its_second_port = its_ipv4_option->get_port();
+ is_second_reliable = (its_ipv4_option->get_layer_four_protocol()
+ == layer_four_protocol_e::TCP);
+
+ if(!check_ipv4_address(its_second_address)
+ || 0 == its_second_port) {
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
+ VSOMEIP_ERROR << "Invalid port or IP address in second endpoint option specified!";
+ return;
+ }
} else {
- its_reliable_address = its_ipv4_address;
- its_reliable_port = its_ipv4_option->get_port();
+ // TODO: error message, too many endpoint options!
}
} else {
VSOMEIP_ERROR
@@ -973,18 +1476,24 @@ void service_discovery_impl::process_eventgroupentry(
boost::asio::ip::address_v6 its_ipv6_address(
its_ipv6_option->get_address());
if (!check_layer_four_protocol(its_ipv6_option)) {
- send_eventgroup_subscription_nack(its_service,
- its_instance, its_eventgroup, its_major);
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
return;
}
- // TODO: add error handling (port already set) here
- if (its_ipv6_option->get_layer_four_protocol()
- == layer_four_protocol_e::UDP) {
- its_unreliable_address = its_ipv6_address;
- its_unreliable_port = its_ipv6_option->get_port();
+
+ if (its_first_port == ILLEGAL_PORT) {
+ its_first_address = its_ipv6_address;
+ its_first_port = its_ipv6_option->get_port();
+ is_first_reliable = (its_ipv6_option->get_layer_four_protocol()
+ == layer_four_protocol_e::TCP);
+ } else
+ if (its_second_port == ILLEGAL_PORT) {
+ its_second_address = its_ipv6_address;
+ its_second_port = its_ipv6_option->get_port();
+ is_second_reliable = (its_ipv6_option->get_layer_four_protocol()
+ == layer_four_protocol_e::TCP);
} else {
- its_reliable_address = its_ipv6_address;
- its_reliable_port = its_ipv6_option->get_port();
+ // TODO: error message, too many endpoint options!
}
} else {
VSOMEIP_ERROR
@@ -1001,8 +1510,16 @@ void service_discovery_impl::process_eventgroupentry(
boost::asio::ip::address_v4 its_ipv4_address(
its_ipv4_option->get_address());
- its_unreliable_address = its_ipv4_address;
- its_unreliable_port = its_ipv4_option->get_port();
+ if (its_first_port == ILLEGAL_PORT) {
+ its_first_address = its_ipv4_address;
+ its_first_port = its_ipv4_option->get_port();
+ } else
+ if (its_second_port == ILLEGAL_PORT) {
+ its_second_address = its_ipv4_address;
+ its_second_port = its_ipv4_option->get_port();
+ } else {
+ // TODO: error message, too many endpoint options!
+ }
} else {
VSOMEIP_ERROR
<< "Invalid eventgroup option (IPv4 Multicast)";
@@ -1017,18 +1534,32 @@ void service_discovery_impl::process_eventgroupentry(
boost::asio::ip::address_v6 its_ipv6_address(
its_ipv6_option->get_address());
- its_unreliable_address = its_ipv6_address;
- its_unreliable_port = its_ipv6_option->get_port();
+ if (its_first_port == ILLEGAL_PORT) {
+ its_first_address = its_ipv6_address;
+ its_first_port = its_ipv6_option->get_port();
+ } else
+ if (its_second_port == ILLEGAL_PORT) {
+ its_second_address = its_ipv6_address;
+ its_second_port = its_ipv6_option->get_port();
+ } else {
+ // TODO: error message, too many endpoint options!
+ }
} else {
VSOMEIP_ERROR
<< "Invalid eventgroup option (IPv6 Multicast)";
}
break;
+ case option_type_e::CONFIGURATION: {
+ if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) {
+ }
+ break;
+ }
case option_type_e::UNKNOWN:
default:
VSOMEIP_WARNING << "Unsupported eventgroup option";
- send_eventgroup_subscription_nack(its_service, its_instance,
- its_eventgroup, its_major);
+ insert_subscription_nack(its_message_response, its_service, its_instance,
+ its_eventgroup, its_counter, its_major, its_reserved);
+
break;
}
}
@@ -1036,93 +1567,180 @@ void service_discovery_impl::process_eventgroupentry(
if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) {
handle_eventgroup_subscription(its_service, its_instance,
- its_eventgroup, its_major, its_ttl,
- (its_reliable_port != ILLEGAL_PORT ?
- its_reliable_address : its_unreliable_address),
- its_reliable_port, its_unreliable_port);
+ its_eventgroup, its_major, its_ttl, its_counter, its_reserved,
+ its_first_address, its_first_port, is_first_reliable,
+ its_second_address, its_second_port, is_second_reliable, its_message_response, accepted_subscribers);
} else {
- handle_eventgroup_subscription_ack(its_service, its_instance,
- its_eventgroup, its_major, its_ttl, its_unreliable_address,
- its_unreliable_port);
+ if( entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == its_type) { //this type is used for ACK and NACK messages
+ if(its_ttl > 0) {
+ handle_eventgroup_subscription_ack(its_service, its_instance,
+ its_eventgroup, its_major, its_ttl, its_counter,
+ its_first_address, its_first_port);
+ } else {
+ handle_eventgroup_subscription_nack(its_service, its_instance, its_eventgroup, its_counter);
+ }
+ }
}
}
void service_discovery_impl::handle_eventgroup_subscription(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
- ttl_t _ttl, const boost::asio::ip::address &_address,
- uint16_t _reliable_port, uint16_t _unreliable_port) {
+ ttl_t _ttl, uint8_t _counter, uint16_t _reserved,
+ const boost::asio::ip::address &_first_address, uint16_t _first_port, bool _is_first_reliable,
+ const boost::asio::ip::address &_second_address, uint16_t _second_port, bool _is_second_reliable,
+ std::shared_ptr < message_impl > &its_message,
+ std::vector <accepted_subscriber_t> &accepted_subscribers) {
- std::shared_ptr < runtime > its_runtime = runtime_.lock();
- if (!its_runtime)
- return;
-
- std::shared_ptr < message_impl > its_message =
- its_runtime->create_message();
if (its_message) {
std::shared_ptr < eventgroupinfo > its_info = host_->find_eventgroup(
_service, _instance, _eventgroup);
bool is_nack(false);
- std::shared_ptr < endpoint_definition > its_reliable_subscriber,
- its_unreliable_subscriber;
- std::shared_ptr < endpoint_definition > its_reliable_target,
- its_unreliable_target;
+ std::shared_ptr < endpoint_definition > its_first_subscriber,
+ its_second_subscriber;
+ std::shared_ptr < endpoint_definition > its_first_target,
+ its_second_target;
// Could not find eventgroup or wrong version
if (!its_info || _major != its_info->get_major()) {
// Create a temporary info object with TTL=0 --> send NACK
its_info = std::make_shared < eventgroupinfo > (_major, 0);
is_nack = true;
- insert_subscription_nack(its_message, _service, _instance, _eventgroup,
- its_info);
- serialize_and_send(its_message, _address);
- //TODO add check if required tcp connection is open
+ insert_subscription_nack(its_message, _service, _instance,
+ _eventgroup, _counter, _major, _reserved);
return;
} else {
- boost::asio::ip::address its_target_address;
- uint16_t its_target_port;
- if (ILLEGAL_PORT != _unreliable_port) {
- its_unreliable_subscriber = endpoint_definition::get(
- _address, _unreliable_port, false);
- if (its_info->get_multicast(its_target_address,
- its_target_port)) {
- its_unreliable_target = endpoint_definition::get(
- its_target_address, its_target_port, false);
- } else {
- its_unreliable_target = its_unreliable_subscriber;
+ boost::asio::ip::address its_first_address, its_second_address;
+ uint16_t its_first_port, its_second_port;
+ if (ILLEGAL_PORT != _first_port) {
+ its_first_subscriber = endpoint_definition::get(
+ _first_address, _first_port, _is_first_reliable);
+ if (!_is_first_reliable &&
+ its_info->get_multicast(its_first_address, its_first_port)) { // udp multicast
+ its_first_target = endpoint_definition::get(
+ its_first_address, its_first_port, false);
+ } else if(_is_first_reliable) { // tcp unicast
+ its_first_target = its_first_subscriber;
+ // check if TCP connection is established by client
+ if( !is_tcp_connected(_service, _instance, its_first_target) ) {
+ is_nack = true;
+ insert_subscription_nack(its_message, _service, _instance,
+ _eventgroup, _counter, _major, _reserved);
+ return;
+ }
+ } else { // udp unicast
+ its_first_target = its_first_subscriber;
}
}
- if (ILLEGAL_PORT != _reliable_port) {
- its_reliable_subscriber = endpoint_definition::get(
- _address, _reliable_port, true);
- its_reliable_target = its_reliable_subscriber;
+ if (ILLEGAL_PORT != _second_port) {
+ its_second_subscriber = endpoint_definition::get(
+ _second_address, _second_port, _is_second_reliable);
+ if (!_is_second_reliable &&
+ its_info->get_multicast(its_second_address, its_second_port)) { // udp multicast
+ its_second_target = endpoint_definition::get(
+ its_second_address, its_second_port, false);
+ } else if (_is_second_reliable) { // tcp unicast
+ its_second_target = its_second_subscriber;
+ // check if TCP connection is established by client
+ if( !is_tcp_connected(_service, _instance, its_second_target) ) {
+ is_nack = true;
+ insert_subscription_nack(its_message, _service, _instance,
+ _eventgroup, _counter, _major, _reserved);
+ return;
+ }
+ } else { // udp unicast
+ its_second_target = its_second_subscriber;
+ }
}
}
if (_ttl == 0) { // --> unsubscribe
- if (its_unreliable_target) {
- host_->on_unsubscribe(_service, _instance, _eventgroup, its_unreliable_target);
+ if (its_first_subscriber) {
+ host_->on_unsubscribe(_service, _instance, _eventgroup, its_first_subscriber);
}
- if (its_reliable_target) {
- host_->on_unsubscribe(_service, _instance, _eventgroup, its_reliable_target);
+ if (its_second_subscriber) {
+ host_->on_unsubscribe(_service, _instance, _eventgroup, its_second_subscriber);
}
return;
}
- insert_subscription_ack(its_message, _service, _instance, _eventgroup,
- its_info, _ttl);
+ std::chrono::high_resolution_clock::time_point its_expiration
+ = std::chrono::high_resolution_clock::now() + std::chrono::seconds(_ttl);
+
+ if (its_first_target) {
+ if(!host_->on_subscribe_accepted(_service, _instance, _eventgroup,
+ its_first_subscriber, its_expiration)) {
+ is_nack = true;
+ insert_subscription_nack(its_message, _service, _instance, _eventgroup,
+ _counter, _major, _reserved);
+ }
+ }
+ if (its_second_subscriber) {
+ if(!host_->on_subscribe_accepted(_service, _instance, _eventgroup,
+ its_second_subscriber, its_expiration)) {
+ is_nack = true;
+ insert_subscription_nack(its_message, _service, _instance, _eventgroup,
+ _counter, _major, _reserved);
+ }
+ }
+
+ if (!is_nack)
+ {
+ insert_subscription_ack(its_message, _service, _instance, _eventgroup,
+ its_info, _ttl, _counter, _major, _reserved);
+
+ if (its_expiration < next_subscription_expiration_) {
+ stop_subscription_expiration_timer();
+ next_subscription_expiration_ = its_expiration;
+ start_subscription_expiration_timer();
+ }
- serialize_and_send(its_message, _address);
+ if (its_first_target && its_first_subscriber) {
+ accepted_subscriber_t subscriber_;
+ subscriber_.service_id = _service;
+ subscriber_.instance_id = _instance;
+ subscriber_.eventgroup_ = _eventgroup;
+ subscriber_.subscriber = its_first_subscriber;
+ subscriber_.target = its_first_target;
+ subscriber_.its_expiration = its_expiration;
- // Finally register the new subscriber and send him all the fields(!)
- if (!is_nack) {
- if (its_unreliable_target && its_unreliable_subscriber) {
- host_->on_subscribe(_service, _instance, _eventgroup,
- its_unreliable_subscriber, its_unreliable_target);
+ accepted_subscribers.push_back(subscriber_);
+ }
+ if (its_second_target && its_second_subscriber) {
+ accepted_subscriber_t subscriber_;
+ subscriber_.service_id = _service;
+ subscriber_.instance_id = _instance;
+ subscriber_.eventgroup_ = _eventgroup;
+ subscriber_.subscriber = its_second_subscriber;
+ subscriber_.target = its_second_target;
+ subscriber_.its_expiration = its_expiration;
+
+ accepted_subscribers.push_back(subscriber_);
}
- if (its_reliable_target && its_reliable_subscriber) {
- host_->on_subscribe(_service, _instance, _eventgroup,
- its_reliable_subscriber, its_reliable_target);
+ }
+ }
+}
+
+void service_discovery_impl::handle_eventgroup_subscription_nack(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, uint8_t _counter) {
+ client_t nackedClient = 0;
+ std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
+ auto found_service = subscribed_.find(_service);
+ if (found_service != subscribed_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_eventgroup = found_instance->second.find(_eventgroup);
+ if (found_eventgroup != found_instance->second.end()) {
+ for (auto client : found_eventgroup->second) {
+ if (client.second->get_counter() == _counter) {
+ // Deliver nack
+ nackedClient = client.first;
+ host_->on_subscribe_nack(client.first, _service, _instance, _eventgroup);
+ break;
+ }
+ }
+ // Remove nacked subscription
+ found_eventgroup->second.erase(nackedClient);
}
}
}
@@ -1130,11 +1748,11 @@ void service_discovery_impl::handle_eventgroup_subscription(service_t _service,
void service_discovery_impl::handle_eventgroup_subscription_ack(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, ttl_t _ttl,
+ major_version_t _major, ttl_t _ttl, uint8_t _counter,
const boost::asio::ip::address &_address, uint16_t _port) {
(void)_major;
(void)_ttl;
-
+ std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
auto found_instance = found_service->second.find(_instance);
@@ -1142,16 +1760,48 @@ void service_discovery_impl::handle_eventgroup_subscription_ack(
auto found_eventgroup = found_instance->second.find(_eventgroup);
if (found_eventgroup != found_instance->second.end()) {
for (auto its_client : found_eventgroup->second) {
- its_client.second->set_acknowledged(true);
+ if (its_client.second->get_counter() == _counter) {
+ its_client.second->set_acknowledged(true);
+ }
if (_address.is_multicast()) {
host_->on_subscribe_ack(_service, _instance, _address,
_port);
}
+ host_->on_subscribe_ack(its_client.first, _service,
+ _instance, _eventgroup);
}
+ }
+ }
+ }
+}
+bool service_discovery_impl::is_tcp_connected(service_t _service,
+ instance_t _instance,
+ std::shared_ptr<vsomeip::endpoint_definition> its_endpoint) {
+ bool is_connected = false;
+ services_t offered_services = host_->get_offered_services();
+ auto found_service = offered_services.find(_service);
+ if (found_service != offered_services.end()) {
+ if (_instance != ANY_INSTANCE) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ std::shared_ptr<serviceinfo> its_info = found_instance->second;
+ if(its_info) {
+ //get reliable server endpoint
+ auto its_reliable_endpoint = its_info->get_endpoint(true);
+ if(its_reliable_endpoint) {
+ std::shared_ptr<tcp_server_endpoint_impl> its_ptr(std::static_pointer_cast<tcp_server_endpoint_impl>(its_reliable_endpoint));
+ if( !its_ptr->is_established(its_endpoint)) {
+ }
+ else {
+ is_connected = true;
+ }
+ }
+ }
}
}
}
+ return is_connected;
}
void service_discovery_impl::serialize_and_send(
@@ -1165,23 +1815,23 @@ void service_discovery_impl::serialize_and_send(
return;
}
if (host_->send_to(endpoint_definition::get(_address, port_, reliable_),
- serializer_->get_data(), serializer_->get_size())) {
+ serializer_->get_data(), serializer_->get_size(), port_)) {
increment_session(_address);
}
serializer_->reset();
}
void service_discovery_impl::start_ttl_timer() {
- ttl_timer_.expires_from_now(std::chrono::seconds(smallest_ttl_));
+ ttl_timer_.expires_from_now(std::chrono::milliseconds(smallest_ttl_));
ttl_timer_.async_wait(
std::bind(&service_discovery_impl::check_ttl, shared_from_this(),
std::placeholders::_1));
}
-ttl_t service_discovery_impl::stop_ttl_timer() {
- ttl_t remaining = ttl_t(std::chrono::duration_cast<
- std::chrono::seconds
- >(ttl_timer_.expires_from_now()).count());
+std::chrono::milliseconds service_discovery_impl::stop_ttl_timer() {
+ std::chrono::milliseconds remaining = std::chrono::duration_cast<
+ std::chrono::milliseconds
+ >(ttl_timer_.expires_from_now());
ttl_timer_.cancel();
return (smallest_ttl_ - remaining);
}
@@ -1215,11 +1865,17 @@ bool service_discovery_impl::check_static_header_fields(
VSOMEIP_ERROR << "Invalid message type in SD header";
return false;
}
+ if(_message->get_return_code() > return_code_e::E_OK
+ && _message->get_return_code()< return_code_e::E_UNKNOWN) {
+ VSOMEIP_ERROR << "Invalid return code in SD header";
+ return false;
+ }
return true;
}
void service_discovery_impl::send_eventgroup_subscription_nack(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major) {
+ service_t _service, instance_t _instance,eventgroup_t _eventgroup,
+ major_version_t _major, uint8_t _counter, uint16_t _reserved) {
std::shared_ptr<runtime> its_runtime = runtime_.lock();
if (!its_runtime) {
return;
@@ -1233,7 +1889,7 @@ void service_discovery_impl::send_eventgroup_subscription_nack(
its_info = std::make_shared < eventgroupinfo > (_major, 0);
}
insert_subscription_nack(its_message, _service, _instance, _eventgroup,
- its_info);
+ _counter, _major, _reserved);
serialize_and_send(its_message, get_current_remote_address());
}
}
@@ -1247,5 +1903,113 @@ bool service_discovery_impl::check_layer_four_protocol(
return true;
}
+void service_discovery_impl::send_subscriptions(service_t _service, instance_t _instance,
+ client_t _client, bool _reliable) {
+ std::shared_ptr<runtime> its_runtime = runtime_.lock();
+ if (!its_runtime) {
+ return;
+ }
+ std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
+ auto found_service = subscribed_.find(_service);
+ if (found_service != subscribed_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ for (auto found_eventgroup : found_instance->second) {
+ auto found_client = found_eventgroup.second.find(_client);
+ if (found_client != found_eventgroup.second.end()) {
+ boost::asio::ip::address its_address;
+ auto endpoint = found_client->second->get_endpoint(_reliable);
+ if (endpoint) {
+ endpoint->get_remote_address(its_address);
+ std::shared_ptr<message_impl> its_message
+ = its_runtime->create_message();
+
+ if(_reliable) {
+ if(endpoint->is_connected()) {
+ insert_subscription(its_message, _service,
+ _instance, found_eventgroup.first,
+ found_client->second, _reliable, !_reliable);
+ found_client->second->set_tcp_connection_established(true);
+ } else {
+ // don't insert reliable endpoint option if the
+ // TCP client endpoint is not yet connected
+ found_client->second->set_tcp_connection_established(false);
+ }
+ } else {
+ insert_subscription(its_message, _service,
+ _instance, found_eventgroup.first,
+ found_client->second, _reliable, !_reliable);
+ }
+ if(0 < its_message->get_entries().size()) {
+ serialize_and_send(its_message, its_address);
+ found_client->second->set_acknowledged(false);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void service_discovery_impl::start_subscription_expiration_timer() {
+ subscription_expiration_timer_.expires_at(next_subscription_expiration_);
+ subscription_expiration_timer_.async_wait(
+ std::bind(&service_discovery_impl::expire_subscriptions,
+ shared_from_this(),
+ std::placeholders::_1));
+}
+
+void service_discovery_impl::stop_subscription_expiration_timer() {
+ subscription_expiration_timer_.cancel();
+}
+
+void service_discovery_impl::expire_subscriptions(const boost::system::error_code &_error) {
+ if (!_error) {
+ next_subscription_expiration_ = host_->expire_subscriptions();
+ start_subscription_expiration_timer();
+ }
+}
+
+bool service_discovery_impl::check_ipv4_address(
+ boost::asio::ip::address its_address) {
+ //Check unallowed ipv4 address
+ bool is_valid = true;
+ std::shared_ptr<configuration> its_configuration =
+ host_->get_configuration();
+
+ if(its_configuration) {
+ boost::asio::ip::address_v4::bytes_type its_unicast_address =
+ its_configuration.get()->get_unicast_address().to_v4().to_bytes();
+ boost::asio::ip::address_v4::bytes_type endpoint_address =
+ its_address.to_v4().to_bytes();
+
+ //same address as unicast address of DUT not allowed
+ if(its_unicast_address
+ == endpoint_address) {
+ VSOMEIP_ERROR << "Subscribers endpoint IP address is same as DUT's address! : "
+ << its_address.to_string();
+ is_valid = false;
+ }
+
+ // first 3 triples must match
+ its_unicast_address[3] = 0x00;
+ endpoint_address[3] = 0x00;
+
+ if(its_unicast_address
+ != endpoint_address) {
+#if 1
+ VSOMEIP_ERROR<< "First 3 triples of subscribers endpoint IP address are not valid!";
+#endif
+ is_valid = false;
+
+ } else {
+#if 0
+ VSOMEIP_DEBUG << "First 3 triples of subscribers endpoint IP address are valid!";
+#endif
+ }
+ }
+ return is_valid;
+}
+
} // namespace sd
} // namespace vsomeip
diff --git a/implementation/service_discovery/src/serviceentry_impl.cpp b/implementation/service_discovery/src/serviceentry_impl.cpp
index fe31703..9f82b83 100755
--- a/implementation/service_discovery/src/serviceentry_impl.cpp
+++ b/implementation/service_discovery/src/serviceentry_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
diff --git a/implementation/service_discovery/src/subscription.cpp b/implementation/service_discovery/src/subscription.cpp
index dcb2461..402304c 100644
--- a/implementation/service_discovery/src/subscription.cpp
+++ b/implementation/service_discovery/src/subscription.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2016 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
@@ -11,11 +11,16 @@ namespace sd {
subscription::subscription(major_version_t _major, ttl_t _ttl,
std::shared_ptr<endpoint> _reliable,
std::shared_ptr<endpoint> _unreliable,
- subscription_type_e _subscription_type)
+ subscription_type_e _subscription_type,
+ uint8_t _counter,
+ std::chrono::high_resolution_clock::time_point _expiration)
: major_(_major), ttl_(_ttl),
reliable_(_reliable), unreliable_(_unreliable),
is_acknowledged_(true),
- subscription_type_(_subscription_type) {
+ tcp_connection_established_(false),
+ subscription_type_(_subscription_type),
+ counter_(_counter),
+ expiration_(_expiration) {
}
subscription::~subscription() {
@@ -53,9 +58,28 @@ void subscription::set_acknowledged(bool _is_acknowledged) {
is_acknowledged_ = _is_acknowledged;
}
+bool subscription::is_tcp_connection_established() const {
+ return tcp_connection_established_;
+}
+void subscription::set_tcp_connection_established(bool _is_established) {
+ tcp_connection_established_ = _is_established;
+}
+
subscription_type_e subscription::get_subscription_type() const {
return subscription_type_;
}
+uint8_t subscription::get_counter() const {
+ return counter_;
+}
+
+std::chrono::high_resolution_clock::time_point subscription::get_expiration() const {
+ return expiration_;
+}
+
+void subscription::set_expiration(std::chrono::high_resolution_clock::time_point _expiration) {
+ expiration_ = _expiration;
+}
+
} // namespace sd
} // namespace vsomeip