First part of event/eventgroup implementation. Subscription works.
Second part (routing) is missing.
diff --git a/config/vsomeip-tcp-client.json b/config/vsomeip-tcp-client.json
index 2a7a8c7..e0c50c9 100644
--- a/config/vsomeip-tcp-client.json
+++ b/config/vsomeip-tcp-client.json
@@ -3,7 +3,7 @@
 	"netmask" : "255.255.255.0",
 	"logging" : 
 	{
-		"level" : "debug",
+		"level" : "info",
 		"console" : "true",
 		"file" : { "enable" : "true", "path" : "/var/log/vsomeip.log" },
 		"dlt" : "true"
@@ -42,32 +42,29 @@
 					[
 						{
 							"event" : "0x0777",
-							"is_field" : true
+							"is_field" : "true"
 						},
 						{
 							"event" : "0x0778",
-							"is_field" : false
+							"is_field" : "false"
 						},
 						{
 							"event" : "0x0779",
-							"is_field" : true
+							"is_field" : "true"
 						}
 					],
 					"eventgroups" :
 					[
 						{
 							"eventgroup" : "0x4455",
-							"multicast" : "224.225.226.223",
 							"events" : [ "0x777", "0x778" ] 
 						},
 						{
 							"eventgroup" : "0x4465",
-							"multicast" : "224.225.226.228",
 							"events" : [ "0x778", "0x779" ] 
 						},
 						{
 							"eventgroup" : "0x4555",
-							"multicast" : "224.225.226.233",
 							"events" : [ "0x777", "0x779" ] 
 						}
 					]
diff --git a/config/vsomeip-tcp-service.json b/config/vsomeip-tcp-service.json
index 816c577..9e6583b 100644
--- a/config/vsomeip-tcp-service.json
+++ b/config/vsomeip-tcp-service.json
@@ -1,5 +1,5 @@
 {
-	"unicast" : "192.168.56.102",
+	"unicast" : "192.168.56.101",
 	"logging" :
 	{ 
 		"level" : "debug",
diff --git a/config/vsomeip-udp-client.json b/config/vsomeip-udp-client.json
index 544778d..1cdc55d 100644
--- a/config/vsomeip-udp-client.json
+++ b/config/vsomeip-udp-client.json
@@ -1,9 +1,9 @@
 {
-	"unicast" : "192.168.56.101",
+	"unicast" : "192.168.56.104",
 	"netmask" : "255.255.255.0",
 	"logging" : 
 	{
-		"level" : "debug",
+		"level" : "trace",
 		"console" : "true",
 		"file" : { "enable" : "true", "path" : "/var/log/vsomeip.log" },
 		"dlt" : "true"
@@ -15,15 +15,15 @@
 			"id" : "0x1343"
 		},
 		{
-			"name" : "client-sample",
+			"name" : "second-client-sample",
 			"id" : "0x1344"
 		},
 		{
-			"name" : "client-sample",
+			"name" : "third-client-sample",
 			"id" : "0x1345"
 		},
 		{
-			"name" : "client-sample",
+			"name" : "fourth-client-sample",
 			"id" : "0x1346"
 		}
 	],
@@ -31,13 +31,18 @@
 	[
 		{
 			"name" : "remote",
-			"address" : "192.168.56.102",
+			"unicast" : "192.168.56.101",
 			"services" : 
 			[
 				{
 					"service" : "0x1234",
 					"instance" : "0x5678",
 					"unreliable" : "30509",
+					"multicast" : 
+					{ 
+						"address" : "224.225.226.233",
+						"port" : "32344"
+					},
 					"events" : 
 					[
 						{
@@ -57,17 +62,15 @@
 					[
 						{
 							"eventgroup" : "0x4455",
-							"multicast" : "224.225.226.223",
 							"events" : [ "0x777", "0x778" ] 
 						},
 						{
 							"eventgroup" : "0x4465",
-							"multicast" : "224.225.226.228",
-							"events" : [ "0x778", "0x779" ] 
+							"events" : [ "0x778", "0x779" ],
+							"is_multicast" : "true"
 						},
 						{
 							"eventgroup" : "0x4555",
-							"multicast" : "224.225.226.233",
 							"events" : [ "0x777", "0x779" ] 
 						}
 					]
@@ -79,7 +82,7 @@
 	"service-discovery" :
 	{
 		"enable" : "true",
-		"multicast" : "224.244.224.224",
+		"multicast" : "224.244.224.245",
 		"port" : "30490",
 		"protocol" : "udp"
 	}
diff --git a/config/vsomeip-udp-service.json b/config/vsomeip-udp-service.json
index cba6b6e..406f2f3 100644
--- a/config/vsomeip-udp-service.json
+++ b/config/vsomeip-udp-service.json
@@ -1,12 +1,12 @@
 {
-	"unicast" : "192.168.56.102",
+	"unicast" : "192.168.56.101",
 	"logging" :
 	{ 
-		"level" : "debug",
+		"level" : "trace",
 		"console" : "true",
 		"file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
-		"dlt" : "false",
-	}
+		"dlt" : "false"
+	},
 	"applications" : 
 	[
 		{
@@ -18,9 +18,14 @@
 	[
 		{ 
 			"name" : "default",
+			"unicast" : "local",
 			"delays" :
 			{
-				"initial" : { "minimum" : "10", "maximum" : 100 },
+				"initial" : 
+				{ 
+					"minimum" : "10", 
+					"maximum" : 100 
+				},
 				"repetition-base" : "200",
 				"repetition-max" : "3",
 				"cyclic-offer" : "2000",
@@ -30,12 +35,50 @@
 			[
 				{
 					"service" : "0x1234",
-					"instance" : "0x5678"
+					"instance" : "0x5678",
 					"unreliable" : "30509",
+					"multicast" : 
+					{ 
+						"address" : "224.225.226.233", 
+						"port" : "32344"
+					},
+					"events" : 
+					[
+						{
+							"event" : "0x0777",
+							"is_field" : "true",
+							"update-cycle" : 2000
+						},
+						{
+							"event" : "0x0778",
+							"is_field" : "false",
+							"update-cycle" : 0
+						},
+						{
+							"event" : "0x0779",
+							"is_field" : "true"
+						}
+					],
+					"eventgroups" :
+					[
+						{
+							"eventgroup" : "0x4455",
+							"events" : [ "0x777", "0x778" ] 
+						},
+						{
+							"eventgroup" : "0x4465",
+							"events" : [ "0x778", "0x779" ], 
+							"is_multicast" : "true"
+						},
+						{
+							"eventgroup" : "0x4555",
+							"events" : [ "0x777", "0x779" ] 
+						}
+					]
 				}
 			]
 		}
-	]
+	],
 	"routing" : "service-sample",
 	"service-discovery" :
 	{
diff --git a/documentation/readme.txt b/documentation/readme.txt
new file mode 100644
index 0000000..4d1376a
--- /dev/null
+++ b/documentation/readme.txt
@@ -0,0 +1,3 @@
+To use IP multicast, the route must be added. In Linux this can be done
+by "route add -net 224.0.0.0/4 dev eth0".
+
diff --git a/examples/client-sample.cpp b/examples/client-sample.cpp
index 7d27222..c500d77 100644
--- a/examples/client-sample.cpp
+++ b/examples/client-sample.cpp
@@ -55,6 +55,9 @@
 						  this,
 						  std::placeholders::_1));
 
+		app_->subscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENTGROUP_ID,
+				vsomeip::ANY_MAJOR, vsomeip::ANY_TTL);
+
 		request_->set_service(SAMPLE_SERVICE_ID);
 		request_->set_instance(SAMPLE_INSTANCE_ID);
 		request_->set_method(SAMPLE_METHOD_ID);
diff --git a/examples/sample-ids.hpp b/examples/sample-ids.hpp
index 3fc097f..45a6f85 100644
--- a/examples/sample-ids.hpp
+++ b/examples/sample-ids.hpp
@@ -9,7 +9,10 @@
 
 #define SAMPLE_SERVICE_ID	0x1234
 #define SAMPLE_INSTANCE_ID	0x5678
-#define SAMPLE_METHOD_ID	0x0421
+#define SAMPLE_METHOD_ID	0x8421
+#define SAMPLE_EVENT_ID		0x0778
+
+#define SAMPLE_EVENTGROUP_ID	0x4465
 
 #define OTHER_SAMPLE_SERVICE_ID	0x0248
 #define OTHER_SAMPLE_INSTANCE_ID 0x5422
diff --git a/examples/service-sample.cpp b/examples/service-sample.cpp
index 13f134b..98b8c66 100644
--- a/examples/service-sample.cpp
+++ b/examples/service-sample.cpp
@@ -16,120 +16,165 @@
 #include "sample-ids.hpp"
 
 class service_sample {
-public:
-	service_sample(bool _use_tcp)
-		: app_(vsomeip::runtime::get()->create_application()),
-		  is_registered_(false),
-		  use_tcp_(_use_tcp),
-		  offer_thread_(std::bind(&service_sample::run, this)) {
-	}
+ public:
+  service_sample(bool _use_tcp)
+      : app_(vsomeip::runtime::get()->create_application()),
+        is_registered_(false),
+        use_tcp_(_use_tcp),
+        offer_thread_(std::bind(&service_sample::run, this)),
+        notification_thread_(std::bind(&service_sample::notify, this)) {
+  }
 
-	void init() {
-		std::lock_guard< std::mutex > its_lock(mutex_);
+  void init() {
+    std::lock_guard < std::mutex > its_lock(mutex_);
 
-		app_->init();
-		app_->register_message_handler(
-					SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID,
-					std::bind(&service_sample::on_message,
-					this,
-					std::placeholders::_1)
-				);
+    app_->init();
+    app_->register_message_handler(
+        SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID,
+        std::bind(&service_sample::on_message, this, std::placeholders::_1));
 
-		app_->register_event_handler(
-				std::bind(&service_sample::on_event, this, std::placeholders::_1));
+    app_->register_event_handler(
+        std::bind(&service_sample::on_event, this, std::placeholders::_1));
 
-		blocked_ = true;
-		condition_.notify_one();
-	}
+    blocked_ = true;
+    condition_.notify_one();
+  }
 
-	void start() {
-		app_->start();
-	}
+  void start() {
+    app_->start();
+  }
 
-	void offer() {
-		app_->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
-	}
+  void offer() {
+    VSOMEIP_INFO << "Offering service.";
+    //std::lock_guard < std::mutex > its_lock(notification_mutex_);
+    app_->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
 
-	void stop_offer() {
-		app_->stop_offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
-	}
+    notification_blocked_ = true;
+    //condition_.notify_one();
+  }
 
-	void on_event(vsomeip::event_type_e _event) {
-		VSOMEIP_INFO << "Application " << app_->get_name()
-					 << " is "
-				     << (_event == vsomeip::event_type_e::REGISTERED ? "registered." : "deregistered.");
+  void stop_offer() {
+    VSOMEIP_INFO << "Stop offering service.";
+    app_->stop_offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
+    notification_blocked_ = false;
+  }
 
-		if (_event == vsomeip::event_type_e::REGISTERED) {
-			if (!is_registered_) {
-				is_registered_= true;
-			}
-		} else {
-			is_registered_ = false;
-		}
-	}
+  void update() {
+    static std::shared_ptr<vsomeip::payload> its_payload =
+        vsomeip::runtime::get()->create_payload();
 
-	void on_message(std::shared_ptr< vsomeip::message > &_request) {
-		VSOMEIP_INFO << "Received a message with Client/Session ["
-				  << std::setw(4) << std::setfill('0') << std::hex << _request->get_client()
-				  << "/"
-				  << std::setw(4) << std::setfill('0') << std::hex << _request->get_session()
-				  << "]";
+    static vsomeip::byte_t its_data[1000];
+    static uint32_t its_size = 0;
 
-		std::shared_ptr< vsomeip::message > its_response
-			= vsomeip::runtime::get()->create_response(_request);
+    its_size++;
+    for (uint32_t i = 0; i < its_size; ++i)
+      its_data[i] = (i % 256);
 
-		std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload();
-		std::vector< vsomeip::byte_t > its_payload_data;
-		for (std::size_t i = 0; i < 120; ++i) its_payload_data.push_back(i % 256);
-		its_payload->set_data(its_payload_data);
-		its_response->set_payload(its_payload);
+    its_payload->set_data(its_data, its_size);
 
-		app_->send(its_response, true, use_tcp_);
-	}
+    VSOMEIP_INFO << "Updating event to " << its_size << " bytes.";
+    app_->set(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID,
+              its_payload);
+  }
 
-	void run() {
-		std::unique_lock< std::mutex > its_lock(mutex_);
-		while (!blocked_) condition_.wait(its_lock);
+  void on_event(vsomeip::event_type_e _event) {
+    VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+        << (_event == vsomeip::event_type_e::REGISTERED ?
+            "registered." : "deregistered.");
 
-		bool is_offer(true);
-		while (true) {
-			if (is_offer) offer();
-			else stop_offer();
-			std::this_thread::sleep_for(std::chrono::milliseconds(10000));
-			is_offer = !is_offer;
-		}
-	}
+    if (_event == vsomeip::event_type_e::REGISTERED) {
+      if (!is_registered_) {
+        is_registered_ = true;
+      }
+    } else {
+      is_registered_ = false;
+    }
+  }
 
-private:
-	std::shared_ptr< vsomeip::application > app_;
-	bool is_registered_;
-	bool use_tcp_;
-	std::thread offer_thread_;
-	std::mutex mutex_;
-	std::condition_variable condition_;
-	bool blocked_;
+  void on_message(std::shared_ptr<vsomeip::message> &_request) {
+    VSOMEIP_INFO << "Received a message with Client/Session [" << std::setw(4)
+        << std::setfill('0') << std::hex << _request->get_client() << "/"
+        << std::setw(4) << std::setfill('0') << std::hex
+        << _request->get_session() << "]";
+
+    std::shared_ptr<vsomeip::message> its_response = vsomeip::runtime::get()
+        ->create_response(_request);
+
+    std::shared_ptr<vsomeip::payload> its_payload = vsomeip::runtime::get()
+        ->create_payload();
+    std::vector<vsomeip::byte_t> its_payload_data;
+    for (std::size_t i = 0; i < 120; ++i)
+      its_payload_data.push_back(i % 256);
+    its_payload->set_data(its_payload_data);
+    its_response->set_payload(its_payload);
+
+    app_->send(its_response, true, use_tcp_);
+  }
+
+  void run() {
+    std::unique_lock < std::mutex > its_lock(mutex_);
+    while (!blocked_)
+      condition_.wait(its_lock);
+
+    bool is_offer(true);
+    while (true) {
+      if (is_offer)
+        offer();
+      else
+        stop_offer();
+      std::this_thread::sleep_for(std::chrono::milliseconds(10000));
+      is_offer = !is_offer;
+    }
+  }
+
+  void notify() {
+    while (true) {
+      //std::unique_lock < std::mutex > its_lock(notification_mutex_);
+      //while (!notification_blocked_)
+      //  notification_condition_.wait(its_lock);
+      //while (notification_blocked_) {
+        std::this_thread::sleep_for(std::chrono::milliseconds(500));
+        if (notification_blocked_) update();
+      //}
+    }
+  }
+
+ private:
+  std::shared_ptr<vsomeip::application> app_;
+  bool is_registered_;
+  bool use_tcp_;
+
+  std::thread offer_thread_;
+  std::mutex mutex_;
+  std::condition_variable condition_;
+  bool blocked_;
+
+  std::thread notification_thread_;
+  std::mutex notification_mutex_;
+  std::condition_variable notification_condition_;
+  bool notification_blocked_;
 };
 
 int main(int argc, char **argv) {
-	bool use_tcp = false;
+  bool use_tcp = false;
 
-	std::string tcp_enable("--tcp");
-	std::string udp_enable("--udp");
+  std::string tcp_enable("--tcp");
+  std::string udp_enable("--udp");
 
-	for (int i = 1; i < argc; i++) {
-		if (tcp_enable == argv[i]) {
-			use_tcp = true;
-			break;
-		}
-		if (udp_enable == argv[i]) {
-			use_tcp = false;
-			break;
-		}
-	}
+  for (int i = 1; i < argc; i++) {
+    if (tcp_enable == argv[i]) {
+      use_tcp = true;
+      break;
+    }
+    if (udp_enable == argv[i]) {
+      use_tcp = false;
+      break;
+    }
+  }
 
-	service_sample its_sample(use_tcp);
-	its_sample.init();
-	its_sample.start();
+  service_sample its_sample(use_tcp);
+  its_sample.init();
+  its_sample.start();
 
-	return 0;
+  return 0;
 }
diff --git a/exportmap.gcc b/exportmap.gcc
index 92cc98c..a86d0e4 100644
--- a/exportmap.gcc
+++ b/exportmap.gcc
@@ -21,6 +21,8 @@
 		vsomeip::runtime::get*;
 		*vsomeip::application_impl;
 		vsomeip::application_impl*;
+		*vsomeip::eventgroupinfo;
+		vsomeip::eventgroupinfo::*;
 		*vsomeip::servicegroup;
 		vsomeip::servicegroup::*;
 		*vsomeip::serviceinfo;
diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp
index 612bc4d..15c1680 100644
--- a/implementation/configuration/include/configuration_impl.hpp
+++ b/implementation/configuration/include/configuration_impl.hpp
@@ -51,7 +51,11 @@
 	int32_t get_cyclic_offer_delay(const std::string &_name) const;
 	int32_t get_cyclic_request_delay(const std::string &_name) const;
 
-	std::string get_address(service_t _service, instance_t _instance) const;
+	std::string get_unicast(service_t _service, instance_t _instance) const;
+	std::string get_multicast_address(service_t _service, instance_t _instance) const;
+	uint16_t get_multicast_port(service_t _service, instance_t _instance) const;
+	uint16_t get_multicast_group(service_t _service, instance_t _instance) const;
+
 	uint16_t get_reliable_port(service_t _service, instance_t _instance) const;
 	bool has_enabled_magic_cookies(std::string _address, uint16_t _port) const;
 	uint16_t get_unreliable_port(service_t _service, instance_t _instance) const;
@@ -67,6 +71,10 @@
 
 	std::set< std::pair< service_t, instance_t > > get_remote_services() const;
 
+	std::map<service_t, std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > get_eventgroups() const;
+	std::map<service_t, std::map<instance_t, std::set<event_t> > > get_events() const;
+	void set_event(std::shared_ptr<event> &_event) const;
+
 private:
 	bool get_someip_configuration(boost::property_tree::ptree &_tree);
 	bool get_logging_configuration(boost::property_tree::ptree &_tree);
diff --git a/implementation/configuration/include/eventgroup.hpp b/implementation/configuration/include/eventgroup.hpp
index cd58dee..377c17f 100644
--- a/implementation/configuration/include/eventgroup.hpp
+++ b/implementation/configuration/include/eventgroup.hpp
@@ -18,7 +18,6 @@
 
 struct eventgroup {
 	eventgroup_t id_;
-	std::string multicast_;
 	std::set<std::shared_ptr<event> > events_;
 };
 
diff --git a/implementation/configuration/include/service.hpp b/implementation/configuration/include/service.hpp
index 9459648..fd885e4 100644
--- a/implementation/configuration/include/service.hpp
+++ b/implementation/configuration/include/service.hpp
@@ -24,6 +24,10 @@
 	uint16_t reliable_;
 	uint16_t unreliable_;
 
+	std::string multicast_address_;
+	uint16_t multicast_port_;
+	eventgroup_t multicast_group_;
+
 	bool use_magic_cookies_;
 
 	std::shared_ptr<servicegroup> group_;
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
index 4bc8621..ff2d5dc 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -20,6 +20,7 @@
 #include "../include/servicegroup.hpp"
 #include "../include/service.hpp"
 #include "../../logging/include/logger_impl.hpp"
+#include "../../routing/include/event.hpp"
 #include "../../service_discovery/include/defines.hpp"
 
 namespace vsomeip {
@@ -29,696 +30,785 @@
 std::mutex configuration_impl::mutex_;
 
 configuration * configuration_impl::get(const std::string &_path) {
-	configuration *its_configuration(0);
+  configuration *its_configuration(0);
 
-	bool is_freshly_loaded(false);
-	{
-		std::unique_lock < std::mutex > its_lock(mutex_);
+  bool is_freshly_loaded(false);
+  {
+    std::unique_lock < std::mutex > its_lock(mutex_);
 
-		auto found_configuration = the_configurations.find(_path);
-		if (found_configuration != the_configurations.end()) {
-			its_configuration = found_configuration->second;
-		} else {
-			its_configuration = new configuration_impl;
-			if (its_configuration->load(_path)) {
-				the_configurations[_path] = its_configuration;
-				is_freshly_loaded = true;
-			} else {
-				delete its_configuration;
-				its_configuration = 0;
-			}
-		}
-	}
+    auto found_configuration = the_configurations.find(_path);
+    if (found_configuration != the_configurations.end()) {
+      its_configuration = found_configuration->second;
+    } else {
+      its_configuration = new configuration_impl;
+      if (its_configuration->load(_path)) {
+        the_configurations[_path] = its_configuration;
+        is_freshly_loaded = true;
+      } else {
+        delete its_configuration;
+        its_configuration = 0;
+      }
+    }
+  }
 
-	if (is_freshly_loaded)
-		logger_impl::init(_path);
+  if (is_freshly_loaded)
+    logger_impl::init(_path);
 
-	return its_configuration;
+  return its_configuration;
 }
 
-configuration_impl::configuration_impl() :
-		has_console_log_(true), has_file_log_(false), has_dlt_log_(false), logfile_(
-				"/tmp/vsomeip.log"), loglevel_(
-				boost::log::trivial::severity_level::info), routing_host_(
-				"vsomeipd"), is_service_discovery_enabled_(false) {
+configuration_impl::configuration_impl()
+    : has_console_log_(true),
+      has_file_log_(false),
+      has_dlt_log_(false),
+      logfile_("/tmp/vsomeip.log"),
+      loglevel_(boost::log::trivial::severity_level::info),
+      routing_host_("vsomeipd"),
+      is_service_discovery_enabled_(false) {
 
-	unicast_ = unicast_.from_string("127.0.0.1");
+  unicast_ = unicast_.from_string("127.0.0.1");
 }
 
 configuration_impl::~configuration_impl() {
 }
 
 bool configuration_impl::load(const std::string &_path) {
-	bool is_loaded(true);
-	boost::property_tree::ptree its_tree;
+  bool is_loaded(true);
+  boost::property_tree::ptree its_tree;
 
-	try {
-		boost::property_tree::json_parser::read_json(_path, its_tree);
+  try {
+    boost::property_tree::json_parser::read_json(_path, its_tree);
 
-		// Read the configuration data
-		is_loaded = get_someip_configuration(its_tree);
-		is_loaded = get_logging_configuration(its_tree);
-		is_loaded = is_loaded && get_services_configuration(its_tree);
-		is_loaded = is_loaded && get_routing_configuration(its_tree);
-		is_loaded = is_loaded && get_service_discovery_configuration(its_tree);
-		is_loaded = is_loaded && get_applications_configuration(its_tree);
-	} catch (std::exception &e) {
-		std::cerr << e.what() << std::endl;
-		is_loaded = false;
-	}
+    // Read the configuration data
+    is_loaded = get_someip_configuration(its_tree);
+    is_loaded = get_logging_configuration(its_tree);
+    is_loaded = is_loaded && get_services_configuration(its_tree);
+    is_loaded = is_loaded && get_routing_configuration(its_tree);
+    is_loaded = is_loaded && get_service_discovery_configuration(its_tree);
+    is_loaded = is_loaded && get_applications_configuration(its_tree);
+  } catch (std::exception &e) {
+    std::cerr << e.what() << std::endl;
+    is_loaded = false;
+  }
 
-	return is_loaded;
+  return is_loaded;
 }
 
 bool configuration_impl::get_someip_configuration(
-		boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		std::string its_value = _tree.get < std::string > ("unicast");
-		unicast_ = unicast_.from_string(its_value);
-	} catch (...) {
-		is_loaded = false;
-	}
-	return is_loaded;
+    boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    std::string its_value = _tree.get < std::string > ("unicast");
+    unicast_ = unicast_.from_string(its_value);
+  } catch (...) {
+    is_loaded = false;
+  }
+  return is_loaded;
 }
 
 bool configuration_impl::get_logging_configuration(
-		boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		auto its_logging = _tree.get_child("logging");
-		for (auto i = its_logging.begin(); i != its_logging.end(); ++i) {
-			std::string its_key(i->first);
-			if (its_key == "console") {
-				std::string its_value(i->second.data());
-				has_console_log_ = (its_value == "true");
-			} else if (its_key == "file") {
-				for (auto j : i->second) {
-					std::string its_sub_key(j.first);
-					std::string its_sub_value(j.second.data());
-					if (its_sub_key == "enable") {
-						has_file_log_ = (its_sub_value == "true");
-					} else if (its_sub_key == "path") {
-						logfile_ = its_sub_value;
-					}
-				}
-			} else if (its_key == "dlt") {
-				std::string its_value(i->second.data());
-				has_dlt_log_ = (its_value == "true");
-			} else if (its_key == "level") {
-				std::string its_value(i->second.data());
-				loglevel_ =
-						(its_value == "trace" ?
-								boost::log::trivial::severity_level::trace :
-								(its_value == "debug" ?
-										boost::log::trivial::severity_level::debug :
-										(its_value == "info" ?
-												boost::log::trivial::severity_level::info :
-												(its_value == "warning" ?
-														boost::log::trivial::severity_level::warning :
-														(its_value == "error" ?
-																boost::log::trivial::severity_level::error :
-																(its_value
-																		== "fatal" ?
-																		boost::log::trivial::severity_level::fatal :
-																		boost::log::trivial::severity_level::info))))));
-			}
-		}
-	} catch (...) {
-		is_loaded = false;
-	}
-	return is_loaded;
+    boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    auto its_logging = _tree.get_child("logging");
+    for (auto i = its_logging.begin(); i != its_logging.end(); ++i) {
+      std::string its_key(i->first);
+      if (its_key == "console") {
+        std::string its_value(i->second.data());
+        has_console_log_ = (its_value == "true");
+      } else if (its_key == "file") {
+        for (auto j : i->second) {
+          std::string its_sub_key(j.first);
+          std::string its_sub_value(j.second.data());
+          if (its_sub_key == "enable") {
+            has_file_log_ = (its_sub_value == "true");
+          } else if (its_sub_key == "path") {
+            logfile_ = its_sub_value;
+          }
+        }
+      } else if (its_key == "dlt") {
+        std::string its_value(i->second.data());
+        has_dlt_log_ = (its_value == "true");
+      } else if (its_key == "level") {
+        std::string its_value(i->second.data());
+        loglevel_ =
+            (its_value == "trace" ?
+                boost::log::trivial::severity_level::trace :
+                (its_value == "debug" ?
+                    boost::log::trivial::severity_level::debug :
+                    (its_value == "info" ?
+                        boost::log::trivial::severity_level::info :
+                        (its_value == "warning" ?
+                            boost::log::trivial::severity_level::warning :
+                            (its_value == "error" ?
+                                boost::log::trivial::severity_level::error :
+                                (its_value == "fatal" ?
+                                    boost::log::trivial::severity_level::fatal :
+                                    boost::log::trivial::severity_level::info))))));
+      }
+    }
+  } catch (...) {
+    is_loaded = false;
+  }
+  return is_loaded;
 }
 
 bool configuration_impl::get_services_configuration(
-		boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		auto its_services = _tree.get_child("servicegroups");
-		for (auto i = its_services.begin(); i != its_services.end(); ++i)
-			is_loaded = is_loaded && get_servicegroup_configuration(i->second);
-	} catch (...) {
-		is_loaded = false;
-	}
-	return is_loaded;
+    boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    auto its_services = _tree.get_child("servicegroups");
+    for (auto i = its_services.begin(); i != its_services.end(); ++i)
+      is_loaded = is_loaded && get_servicegroup_configuration(i->second);
+  } catch (...) {
+    is_loaded = false;
+  }
+  return is_loaded;
 }
 
 bool configuration_impl::get_servicegroup_configuration(
-		const boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		std::shared_ptr<servicegroup> its_servicegroup(
-				std::make_shared<servicegroup>());
-		its_servicegroup->unicast_ = "local"; // Default
-		for (auto i = _tree.begin(); i != _tree.end(); ++i) {
-			std::string its_key(i->first);
-			if (its_key == "name") {
-				its_servicegroup->name_ = i->second.data();
-			} else if (its_key == "unicast") {
-				its_servicegroup->unicast_ = i->second.data();
-			} else if (its_key == "delays") {
-				is_loaded = is_loaded
-						&& get_delays_configuration(its_servicegroup,
-								i->second);
-			} else if (its_key == "services") {
-				for (auto j = i->second.begin(); j != i->second.end(); ++j)
-					is_loaded = is_loaded
-							&& get_service_configuration(its_servicegroup,
-									j->second);
-			}
-		}
-		servicegroups_[its_servicegroup->name_] = its_servicegroup;
-	} catch (...) {
-		is_loaded = false;
-	}
-	return is_loaded;
+    const boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    std::shared_ptr<servicegroup> its_servicegroup(
+        std::make_shared<servicegroup>());
+    its_servicegroup->unicast_ = "local";  // Default
+    for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+      std::string its_key(i->first);
+      if (its_key == "name") {
+        its_servicegroup->name_ = i->second.data();
+      } else if (its_key == "unicast") {
+        its_servicegroup->unicast_ = i->second.data();
+      } else if (its_key == "delays") {
+        is_loaded = is_loaded
+            && get_delays_configuration(its_servicegroup, i->second);
+      } else if (its_key == "services") {
+        for (auto j = i->second.begin(); j != i->second.end(); ++j)
+          is_loaded = is_loaded
+              && get_service_configuration(its_servicegroup, j->second);
+      }
+    }
+    servicegroups_[its_servicegroup->name_] = its_servicegroup;
+  } catch (...) {
+    is_loaded = false;
+  }
+  return is_loaded;
 }
 
 bool configuration_impl::get_delays_configuration(
-		std::shared_ptr<servicegroup> &_group,
-		const boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		std::stringstream its_converter;
-		for (auto i = _tree.begin(); i != _tree.end(); ++i) {
-			std::string its_key(i->first);
-			if (its_key == "initial") {
-				_group->min_initial_delay_ = i->second.get < uint32_t
-						> ("minimum");
-				_group->max_initial_delay_ = i->second.get < uint32_t
-						> ("maximum");
-			} else if (its_key == "repetition-base") {
-				its_converter << std::dec << i->second.data();
-				its_converter >> _group->repetition_base_delay_;
-			} else if (its_key == "repetition-max") {
-				int tmp_repetition_max;
-				its_converter << std::dec << i->second.data();
-				its_converter >> tmp_repetition_max;
-				_group->repetition_max_ = tmp_repetition_max;
-			} else if (its_key == "cyclic-offer") {
-				its_converter << std::dec << i->second.data();
-				its_converter >> _group->cyclic_offer_delay_;
-			} else if (its_key == "cyclic-request") {
-				its_converter << std::dec << i->second.data();
-				its_converter >> _group->cyclic_request_delay_;
-			}
-			its_converter.str("");
-			its_converter.clear();
-		}
-	} catch (...) {
-		is_loaded = false;
-	}
-	return is_loaded;
+    std::shared_ptr<servicegroup> &_group,
+    const boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    std::stringstream its_converter;
+    for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+      std::string its_key(i->first);
+      if (its_key == "initial") {
+        _group->min_initial_delay_ = i->second.get < uint32_t > ("minimum");
+        _group->max_initial_delay_ = i->second.get < uint32_t > ("maximum");
+      } else if (its_key == "repetition-base") {
+        its_converter << std::dec << i->second.data();
+        its_converter >> _group->repetition_base_delay_;
+      } else if (its_key == "repetition-max") {
+        int tmp_repetition_max;
+        its_converter << std::dec << i->second.data();
+        its_converter >> tmp_repetition_max;
+        _group->repetition_max_ = tmp_repetition_max;
+      } else if (its_key == "cyclic-offer") {
+        its_converter << std::dec << i->second.data();
+        its_converter >> _group->cyclic_offer_delay_;
+      } else if (its_key == "cyclic-request") {
+        its_converter << std::dec << i->second.data();
+        its_converter >> _group->cyclic_request_delay_;
+      }
+      its_converter.str("");
+      its_converter.clear();
+    }
+  } catch (...) {
+    is_loaded = false;
+  }
+  return is_loaded;
 }
 
 bool configuration_impl::get_service_configuration(
-		std::shared_ptr<servicegroup> &_group,
-		const boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		bool use_magic_cookies(false);
+    std::shared_ptr<servicegroup> &_group,
+    const boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    bool use_magic_cookies(false);
 
-		std::shared_ptr<service> its_service(std::make_shared<service>());
-		its_service->reliable_ = its_service->unreliable_ = ILLEGAL_PORT;
-		its_service->use_magic_cookies_ = false;
-		its_service->group_ = _group;
+    std::shared_ptr<service> its_service(std::make_shared<service>());
+    its_service->reliable_ = its_service->unreliable_ = ILLEGAL_PORT;
+    its_service->use_magic_cookies_ = false;
+    its_service->group_ = _group;
+    its_service->multicast_address_ = "";
+    its_service->multicast_port_ = ILLEGAL_PORT;
+    its_service->multicast_group_ = 0xFFFF;  // TODO: use symbolic constant
 
-		for (auto i = _tree.begin(); i != _tree.end(); ++i) {
-			std::string its_key(i->first);
-			std::string its_value(i->second.data());
-			std::stringstream its_converter;
+    for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+      std::string its_key(i->first);
+      std::string its_value(i->second.data());
+      std::stringstream its_converter;
 
-			if (its_key == "reliable") {
-				try {
-					its_value = i->second.get_child("port").data();
-					its_converter << its_value;
-					its_converter >> its_service->reliable_;
-				} catch (...) {
-					its_converter << its_value;
-					its_converter >> its_service->reliable_;
-				}
-				try {
-					its_value =
-							i->second.get_child("enable-magic-cookies").data();
-					use_magic_cookies = ("true" == its_value);
-				} catch (...) {
+      if (its_key == "reliable") {
+        try {
+          its_value = i->second.get_child("port").data();
+          its_converter << its_value;
+          its_converter >> its_service->reliable_;
+        } catch (...) {
+          its_converter << its_value;
+          its_converter >> its_service->reliable_;
+        }
+        try {
+          its_value = i->second.get_child("enable-magic-cookies").data();
+          use_magic_cookies = ("true" == its_value);
+        } catch (...) {
 
-				}
-			} else if (its_key == "unreliable") {
-				its_converter << its_value;
-				its_converter >> its_service->unreliable_;
-			} else if (its_key == "events") {
-				get_event_configuration(its_service, i->second);
-			} else if (its_key == "eventgroups") {
-				get_eventgroup_configuration(its_service, i->second);
-			} else {
-				// Trim "its_value"
-				if (its_value[0] == '0' && its_value[1] == 'x') {
-					its_converter << std::hex << its_value;
-				} else {
-					its_converter << std::dec << its_value;
-				}
+        }
+      } else if (its_key == "unreliable") {
+        its_converter << its_value;
+        its_converter >> its_service->unreliable_;
+      } else if (its_key == "multicast") {
+        try {
+          its_value = i->second.get_child("address").data();
+          its_service->multicast_address_ = its_value;
+          its_value = i->second.get_child("port").data();
+          its_converter << its_value;
+          its_converter >> its_service->multicast_port_;
+        } catch (...) {
+        }
+      } else if (its_key == "events") {
+        get_event_configuration(its_service, i->second);
+      } else if (its_key == "eventgroups") {
+        get_eventgroup_configuration(its_service, i->second);
+      } else {
+        // Trim "its_value"
+        if (its_value[0] == '0' && its_value[1] == 'x') {
+          its_converter << std::hex << its_value;
+        } else {
+          its_converter << std::dec << its_value;
+        }
 
-				if (its_key == "service") {
-					its_converter >> its_service->service_;
-				} else if (its_key == "instance") {
-					its_converter >> its_service->instance_;
-				}
-			}
-		}
+        if (its_key == "service") {
+          its_converter >> its_service->service_;
+        } else if (its_key == "instance") {
+          its_converter >> its_service->instance_;
+        }
+      }
+    }
 
-		auto found_service = services_.find(its_service->service_);
-		if (found_service != services_.end()) {
-			auto found_instance = found_service->second.find(
-					its_service->instance_);
-			if (found_instance != found_service->second.end()) {
-				is_loaded = false;
-			}
-		}
+    auto found_service = services_.find(its_service->service_);
+    if (found_service != services_.end()) {
+      auto found_instance = found_service->second.find(its_service->instance_);
+      if (found_instance != found_service->second.end()) {
+        is_loaded = false;
+      }
+    }
 
-		if (is_loaded) {
-			services_[its_service->service_][its_service->instance_] =
-					its_service;
-		}
+    if (is_loaded) {
+      services_[its_service->service_][its_service->instance_] = its_service;
+    }
 
-		if (use_magic_cookies) {
-			std::string its_unicast(_group->unicast_);
-			if (its_unicast == "local")
-				its_unicast = unicast_.to_string();
-			magic_cookies_[its_unicast].insert(its_service->reliable_);
-		}
-	} catch (...) {
-		is_loaded = false;
-	}
-	return is_loaded;
+    if (use_magic_cookies) {
+      std::string its_unicast(_group->unicast_);
+      if (its_unicast == "local")
+        its_unicast = unicast_.to_string();
+      magic_cookies_[its_unicast].insert(its_service->reliable_);
+    }
+  } catch (...) {
+    is_loaded = false;
+  }
+  return is_loaded;
 }
 
 bool configuration_impl::get_event_configuration(
-		std::shared_ptr<service> &_service,
-		const boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	for (auto i = _tree.begin(); i != _tree.end(); ++i) {
-		event_t its_event_id(0);
-		bool its_is_field(false);
+    std::shared_ptr<service> &_service,
+    const boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+    event_t its_event_id(0);
+    bool its_is_field(false);
 
-		for (auto j = i->second.begin(); j != i->second.end(); ++j) {
-			std::string its_key(j->first);
-			std::string its_value(j->second.data());
-			if (its_key == "event") {
-				std::stringstream its_converter;
-				if (its_value[0] == '0' && its_value[1] == 'x') {
-					its_converter << std::hex << its_value;
-				} else {
-					its_converter << std::dec << its_value;
-				}
-				its_converter >> its_event_id;
-			} else if (its_key == "is_field") {
-				its_is_field = (its_value == "true");
-			}
-		}
+    for (auto j = i->second.begin(); j != i->second.end(); ++j) {
+      std::string its_key(j->first);
+      std::string its_value(j->second.data());
+      if (its_key == "event") {
+        std::stringstream its_converter;
+        if (its_value[0] == '0' && its_value[1] == 'x') {
+          its_converter << std::hex << its_value;
+        } else {
+          its_converter << std::dec << its_value;
+        }
+        its_converter >> its_event_id;
+      } else if (its_key == "is_field") {
+        its_is_field = (its_value == "true");
+      }
+    }
 
-		if (its_event_id > 0) {
-			auto found_event = _service->events_.find(its_event_id);
-			if (found_event != _service->events_.end()) {
-				found_event->second->is_field_ = its_is_field;
-			} else {
-				std::shared_ptr<event> its_event = std::make_shared<event>(its_event_id, its_is_field);
-				_service->events_[its_event_id] = its_event;
-			}
-		}
-	}
-	return is_loaded;
+    if (its_event_id > 0) {
+      auto found_event = _service->events_.find(its_event_id);
+      if (found_event != _service->events_.end()) {
+        found_event->second->is_field_ = its_is_field;
+      } else {
+        std::shared_ptr<event> its_event = std::make_shared < event
+            > (its_event_id, its_is_field);
+        _service->events_[its_event_id] = its_event;
+      }
+    }
+  }
+  return is_loaded;
 }
 bool configuration_impl::get_eventgroup_configuration(
-		std::shared_ptr<service> &_service,
-		const boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	for (auto i = _tree.begin(); i != _tree.end(); ++i) {
-		std::shared_ptr<eventgroup> its_eventgroup = std::make_shared<eventgroup>();
-		for (auto j = i->second.begin(); j != i->second.end(); ++j) {
-			std::string its_key(j->first);
-			if (its_key == "eventgroup") {
-				std::stringstream its_converter;
-				std::string its_value(j->second.data());
-				if (its_value[0] == '0' && its_value[1] == 'x') {
-					its_converter << std::hex << its_value;
-				} else {
-					its_converter << std::dec << its_value;
-				}
-				its_converter >> its_eventgroup->id_;
-			} else if (its_key == "multicast") {
-				std::string its_value(j->second.data());
-				its_eventgroup->multicast_ = its_value;
-			} else if (its_key == "events") {
-				for (auto k = j->second.begin(); k != j->second.end(); ++k) {
-					std::stringstream its_converter;
-					std::string its_value(k->second.data());
-					event_t its_event_id(0);
-					if (its_value[0] == '0' && its_value[1] == 'x') {
-						its_converter << std::hex << its_value;
-					} else {
-						its_converter << std::dec << its_value;
-					}
-					its_converter >> its_event_id;
-					if (0 < its_event_id) {
-						auto find_event = _service->events_.find(its_event_id);
-						if (find_event != _service->events_.end()) {
-							find_event->second->groups_.push_back(its_eventgroup);
-						} else {
-							std::shared_ptr<event> its_event = std::make_shared<event>(its_event_id, false);
-							its_event->groups_.push_back(its_eventgroup);
-							_service->events_[its_event_id] = its_event;
-						}
-					}
-				}
-			}
-		}
+    std::shared_ptr<service> &_service,
+    const boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  bool is_multicast;
+  for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+    is_multicast = false;
+    std::shared_ptr<eventgroup> its_eventgroup = std::make_shared<eventgroup>();
+    for (auto j = i->second.begin(); j != i->second.end(); ++j) {
+      std::string its_key(j->first);
+      if (its_key == "eventgroup") {
+        std::stringstream its_converter;
+        std::string its_value(j->second.data());
+        if (its_value[0] == '0' && its_value[1] == 'x') {
+          its_converter << std::hex << its_value;
+        } else {
+          its_converter << std::dec << its_value;
+        }
+        its_converter >> its_eventgroup->id_;
+      } else if (its_key == "is_multicast") {
+        std::string its_value(j->second.data());
+        is_multicast = (its_value == "true");
+      } else if (its_key == "events") {
+        for (auto k = j->second.begin(); k != j->second.end(); ++k) {
+          std::stringstream its_converter;
+          std::string its_value(k->second.data());
+          event_t its_event_id(0);
+          if (its_value[0] == '0' && its_value[1] == 'x') {
+            its_converter << std::hex << its_value;
+          } else {
+            its_converter << std::dec << its_value;
+          }
+          its_converter >> its_event_id;
+          if (0 < its_event_id) {
+            std::shared_ptr<event> its_event(nullptr);
+            auto find_event = _service->events_.find(its_event_id);
+            if (find_event != _service->events_.end()) {
+              its_event = find_event->second;
+            } else {
+              its_event = std::make_shared<event>(its_event_id, false);
+            }
+            if (its_event) {
+              its_event->groups_.push_back(its_eventgroup);
+              its_eventgroup->events_.insert(its_event);
+              _service->events_[its_event_id] = its_event;
+            }
+          }
+        }
+      }
+    }
 
-		if (its_eventgroup->id_ > 0)
-			_service->eventgroups_[its_eventgroup->id_] = its_eventgroup;
-	}
-	return is_loaded;
+    if (its_eventgroup->id_ > 0) {
+      if (is_multicast) {
+        _service->multicast_group_ = its_eventgroup->id_;
+      }
+      _service->eventgroups_[its_eventgroup->id_] = its_eventgroup;
+    }
+  }
+  return is_loaded;
 }
 
 bool configuration_impl::get_routing_configuration(
-		boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		auto its_routing = _tree.get_child("routing");
-		routing_host_ = its_routing.data();
-	} catch (...) {
-		is_loaded = false;
-	}
-	return is_loaded;
+    boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    auto its_routing = _tree.get_child("routing");
+    routing_host_ = its_routing.data();
+  } catch (...) {
+    is_loaded = false;
+  }
+  return is_loaded;
 }
 
 bool configuration_impl::get_service_discovery_configuration(
-		boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		auto its_service_discovery = _tree.get_child("service-discovery");
-		for (auto i = its_service_discovery.begin();
-				i != its_service_discovery.end(); ++i) {
-			std::string its_key(i->first);
-			std::string its_value(i->second.data());
-			if (its_key == "enable") {
-				is_service_discovery_enabled_ = (its_value == "true");
-			} else if (its_key == "multicast") {
-				service_discovery_multicast_ = its_value;
-			} else if (its_key == "port") {
-				std::stringstream its_converter;
-				its_converter << its_value;
-				its_converter >> service_discovery_port_;
-			} else if (its_key == "protocol") {
-				service_discovery_protocol_ = its_value;
-			}
-		}
-	} catch (...) {
-		is_loaded = false;
-	}
+    boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    auto its_service_discovery = _tree.get_child("service-discovery");
+    for (auto i = its_service_discovery.begin();
+        i != its_service_discovery.end(); ++i) {
+      std::string its_key(i->first);
+      std::string its_value(i->second.data());
+      if (its_key == "enable") {
+        is_service_discovery_enabled_ = (its_value == "true");
+      } else if (its_key == "multicast") {
+        service_discovery_multicast_ = its_value;
+      } else if (its_key == "port") {
+        std::stringstream its_converter;
+        its_converter << its_value;
+        its_converter >> service_discovery_port_;
+      } else if (its_key == "protocol") {
+        service_discovery_protocol_ = its_value;
+      }
+    }
+  } catch (...) {
+    is_loaded = false;
+  }
 
-	return is_loaded;
+  return is_loaded;
 }
 
 bool configuration_impl::get_applications_configuration(
-		boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	try {
-		std::stringstream its_converter;
-		auto its_applications = _tree.get_child("applications");
-		for (auto i = its_applications.begin(); i != its_applications.end();
-				++i)
-			is_loaded = is_loaded && get_application_configuration(i->second);
-	} catch (...) {
-		is_loaded = false;
-	}
+    boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  try {
+    std::stringstream its_converter;
+    auto its_applications = _tree.get_child("applications");
+    for (auto i = its_applications.begin(); i != its_applications.end(); ++i)
+      is_loaded = is_loaded && get_application_configuration(i->second);
+  } catch (...) {
+    is_loaded = false;
+  }
 
-	return is_loaded;
+  return is_loaded;
 }
 
 bool configuration_impl::get_application_configuration(
-		const boost::property_tree::ptree &_tree) {
-	bool is_loaded(true);
-	std::string its_name("");
-	client_t its_id;
-	for (auto i = _tree.begin(); i != _tree.end(); ++i) {
-		std::string its_key(i->first);
-		std::string its_value(i->second.data());
-		std::stringstream its_converter;
-		if (its_key == "name") {
-			its_name = its_value;
-		} else if (its_key == "id") {
-			if (its_value[0] == '0' && its_value[1] == 'x') {
-				its_converter << std::hex << its_value;
-			} else {
-				its_converter << std::dec << its_value;
-			}
-			its_converter >> its_id;
-		}
-	}
-	if (its_name != "" && its_id != 0) {
-		applications_[its_name] = its_id;
-	}
-	return is_loaded;
+    const boost::property_tree::ptree &_tree) {
+  bool is_loaded(true);
+  std::string its_name("");
+  client_t its_id;
+  for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+    std::string its_key(i->first);
+    std::string its_value(i->second.data());
+    std::stringstream its_converter;
+    if (its_key == "name") {
+      its_name = its_value;
+    } else if (its_key == "id") {
+      if (its_value[0] == '0' && its_value[1] == 'x') {
+        its_converter << std::hex << its_value;
+      } else {
+        its_converter << std::dec << its_value;
+      }
+      its_converter >> its_id;
+    }
+  }
+  if (its_name != "" && its_id != 0) {
+    applications_[its_name] = its_id;
+  }
+  return is_loaded;
 }
 
 // Public interface
 const boost::asio::ip::address & configuration_impl::get_unicast() const {
-	return unicast_;
+  return unicast_;
 }
 
 bool configuration_impl::is_v4() const {
-	return unicast_.is_v4();
+  return unicast_.is_v4();
 }
 
 bool configuration_impl::is_v6() const {
-	return unicast_.is_v6();
+  return unicast_.is_v6();
 }
 
 bool configuration_impl::has_console_log() const {
-	return has_console_log_;
+  return has_console_log_;
 }
 
 bool configuration_impl::has_file_log() const {
-	return has_file_log_;
+  return has_file_log_;
 }
 
 bool configuration_impl::has_dlt_log() const {
-	return has_dlt_log_;
+  return has_dlt_log_;
 }
 
 const std::string & configuration_impl::get_logfile() const {
-	return logfile_;
+  return logfile_;
 }
 
 boost::log::trivial::severity_level configuration_impl::get_loglevel() const {
-	return loglevel_;
+  return loglevel_;
 }
 
 std::set<std::string> configuration_impl::get_servicegroups() const {
-	std::set < std::string > its_keys;
-	for (auto i : servicegroups_)
-		its_keys.insert(i.first);
-	return its_keys;
+  std::set < std::string > its_keys;
+  for (auto i : servicegroups_)
+    its_keys.insert(i.first);
+  return its_keys;
 }
 
 bool configuration_impl::is_local_servicegroup(const std::string &_name) const {
-	bool is_local(false);
+  bool is_local(false);
 
-	servicegroup *its_servicegroup = find_servicegroup(_name);
-	if (its_servicegroup) {
-		is_local = (its_servicegroup->unicast_ == "local"
-				|| its_servicegroup->unicast_ == get_unicast().to_string());
-	}
+  servicegroup *its_servicegroup = find_servicegroup(_name);
+  if (its_servicegroup) {
+    is_local = (its_servicegroup->unicast_ == "local"
+        || its_servicegroup->unicast_ == get_unicast().to_string());
+  }
 
-	return is_local;
+  return is_local;
 }
 
 int32_t configuration_impl::get_min_initial_delay(
-		const std::string &_name) const {
-	int32_t its_delay = VSOMEIP_DEFAULT_MIN_INITIAL_DELAY;
+    const std::string &_name) const {
+  int32_t its_delay = VSOMEIP_DEFAULT_MIN_INITIAL_DELAY;
 
-	servicegroup *its_servicegroup = find_servicegroup(_name);
-	if (its_servicegroup)
-		its_delay = its_servicegroup->min_initial_delay_;
+  servicegroup *its_servicegroup = find_servicegroup(_name);
+  if (its_servicegroup)
+    its_delay = its_servicegroup->min_initial_delay_;
 
-	return its_delay;
+  return its_delay;
 }
 
 int32_t configuration_impl::get_max_initial_delay(
-		const std::string &_name) const {
-	int32_t its_delay = VSOMEIP_DEFAULT_MAX_INITIAL_DELAY;
+    const std::string &_name) const {
+  int32_t its_delay = VSOMEIP_DEFAULT_MAX_INITIAL_DELAY;
 
-	servicegroup *its_servicegroup = find_servicegroup(_name);
-	if (its_servicegroup)
-		its_delay = its_servicegroup->max_initial_delay_;
+  servicegroup *its_servicegroup = find_servicegroup(_name);
+  if (its_servicegroup)
+    its_delay = its_servicegroup->max_initial_delay_;
 
-	return its_delay;
+  return its_delay;
 }
 
 int32_t configuration_impl::get_repetition_base_delay(
-		const std::string &_name) const {
-	int32_t its_delay = VSOMEIP_DEFAULT_REPETITION_BASE_DELAY;
+    const std::string &_name) const {
+  int32_t its_delay = VSOMEIP_DEFAULT_REPETITION_BASE_DELAY;
 
-	servicegroup *its_servicegroup = find_servicegroup(_name);
-	if (its_servicegroup)
-		its_delay = its_servicegroup->repetition_base_delay_;
+  servicegroup *its_servicegroup = find_servicegroup(_name);
+  if (its_servicegroup)
+    its_delay = its_servicegroup->repetition_base_delay_;
 
-	return its_delay;
+  return its_delay;
 }
 
 uint8_t configuration_impl::get_repetition_max(const std::string &_name) const {
-	uint8_t its_max = VSOMEIP_DEFAULT_REPETITION_MAX;
+  uint8_t its_max = VSOMEIP_DEFAULT_REPETITION_MAX;
 
-	servicegroup *its_servicegroup = find_servicegroup(_name);
-	if (its_servicegroup)
-		its_max = its_servicegroup->repetition_max_;
+  servicegroup *its_servicegroup = find_servicegroup(_name);
+  if (its_servicegroup)
+    its_max = its_servicegroup->repetition_max_;
 
-	return its_max;
+  return its_max;
 }
 
 int32_t configuration_impl::get_cyclic_offer_delay(
-		const std::string &_name) const {
-	uint32_t its_delay = VSOMEIP_DEFAULT_CYCLIC_OFFER_DELAY;
+    const std::string &_name) const {
+  uint32_t its_delay = VSOMEIP_DEFAULT_CYCLIC_OFFER_DELAY;
 
-	servicegroup *its_servicegroup = find_servicegroup(_name);
-	if (its_servicegroup)
-		its_delay = its_servicegroup->cyclic_offer_delay_;
+  servicegroup *its_servicegroup = find_servicegroup(_name);
+  if (its_servicegroup)
+    its_delay = its_servicegroup->cyclic_offer_delay_;
 
-	return its_delay;
+  return its_delay;
 }
 
 int32_t configuration_impl::get_cyclic_request_delay(
-		const std::string &_name) const {
-	uint32_t its_delay = VSOMEIP_DEFAULT_CYCLIC_REQUEST_DELAY;
+    const std::string &_name) const {
+  uint32_t its_delay = VSOMEIP_DEFAULT_CYCLIC_REQUEST_DELAY;
 
-	servicegroup *its_servicegroup = find_servicegroup(_name);
-	if (its_servicegroup)
-		its_delay = its_servicegroup->cyclic_request_delay_;
+  servicegroup *its_servicegroup = find_servicegroup(_name);
+  if (its_servicegroup)
+    its_delay = its_servicegroup->cyclic_request_delay_;
 
-	return its_delay;
+  return its_delay;
 }
 
 std::string configuration_impl::get_group(service_t _service,
-		instance_t _instance) const {
-	std::string its_group("default");
-	service *its_service = find_service(_service, _instance);
-	if (nullptr != its_service) {
-		its_group = its_service->group_->name_;
-	}
-	return its_group;
+                                          instance_t _instance) const {
+  std::string its_group("default");
+  service *its_service = find_service(_service, _instance);
+  if (nullptr != its_service) {
+    its_group = its_service->group_->name_;
+  }
+  return its_group;
 }
 
-std::string configuration_impl::get_address(service_t _service,
-		instance_t _instance) const {
-	std::string its_address("");
+std::string configuration_impl::get_unicast(service_t _service,
+                                            instance_t _instance) const {
+  std::string its_unicast("");
+  service *its_service = find_service(_service, _instance);
+  if (its_service)
+    its_unicast = its_service->group_->unicast_;
+  return its_unicast;
+}
 
-	service *its_service = find_service(_service, _instance);
-	if (its_service)
-		its_address = its_service->group_->unicast_;
+std::string configuration_impl::get_multicast_address(
+    service_t _service, instance_t _instance) const {
+  std::string its_multicast_address("");
+  service *its_service = find_service(_service, _instance);
+  if (its_service)
+    its_multicast_address = its_service->multicast_address_;
+  return its_multicast_address;
+}
 
-	return its_address;
+uint16_t configuration_impl::get_multicast_port(
+    service_t _service, instance_t _instance) const {
+  uint16_t its_multicast_port(ILLEGAL_PORT);
+  service *its_service = find_service(_service, _instance);
+  if (its_service)
+    its_multicast_port = its_service->multicast_port_;
+  return its_multicast_port;
+}
+
+uint16_t configuration_impl::get_multicast_group(service_t _service,
+                                                 instance_t _instance) const {
+  uint16_t its_multicast_group(0xFFFF);
+  service *its_service = find_service(_service, _instance);
+  if (its_service)
+    its_multicast_group = its_service->multicast_group_;
+  return its_multicast_group;
 }
 
 uint16_t configuration_impl::get_reliable_port(service_t _service,
-		instance_t _instance) const {
-	uint16_t its_reliable = ILLEGAL_PORT;
+                                               instance_t _instance) const {
+  uint16_t its_reliable = ILLEGAL_PORT;
 
-	service *its_service = find_service(_service, _instance);
-	if (its_service)
-		its_reliable = its_service->reliable_;
+  service *its_service = find_service(_service, _instance);
+  if (its_service)
+    its_reliable = its_service->reliable_;
 
-	return its_reliable;
+  return its_reliable;
 }
 
 bool configuration_impl::has_enabled_magic_cookies(std::string _address,
-		uint16_t _port) const {
-	bool has_enabled(false);
-	auto find_address = magic_cookies_.find(_address);
-	if (find_address != magic_cookies_.end()) {
-		auto find_port = find_address->second.find(_port);
-		if (find_port != find_address->second.end()) {
-			has_enabled = true;
-		}
-	}
-	return has_enabled;
+                                                   uint16_t _port) const {
+  bool has_enabled(false);
+  auto find_address = magic_cookies_.find(_address);
+  if (find_address != magic_cookies_.end()) {
+    auto find_port = find_address->second.find(_port);
+    if (find_port != find_address->second.end()) {
+      has_enabled = true;
+    }
+  }
+  return has_enabled;
 }
 
 uint16_t configuration_impl::get_unreliable_port(service_t _service,
-		instance_t _instance) const {
-	uint16_t its_unreliable = ILLEGAL_PORT;
+                                                 instance_t _instance) const {
+  uint16_t its_unreliable = ILLEGAL_PORT;
 
-	service *its_service = find_service(_service, _instance);
-	if (its_service)
-		its_unreliable = its_service->unreliable_;
+  service *its_service = find_service(_service, _instance);
+  if (its_service)
+    its_unreliable = its_service->unreliable_;
 
-	return its_unreliable;
+  return its_unreliable;
 }
 
 const std::string & configuration_impl::get_routing_host() const {
-	return routing_host_;
+  return routing_host_;
 }
 
 bool configuration_impl::is_service_discovery_enabled() const {
-	return is_service_discovery_enabled_;
+  return is_service_discovery_enabled_;
 }
 
 const std::string & configuration_impl::get_service_discovery_protocol() const {
-	return service_discovery_protocol_;
+  return service_discovery_protocol_;
 }
 
 const std::string & configuration_impl::get_service_discovery_multicast() const {
-	return service_discovery_multicast_;
+  return service_discovery_multicast_;
 }
 
 uint16_t configuration_impl::get_service_discovery_port() const {
-	return service_discovery_port_;
+  return service_discovery_port_;
 }
 
 client_t configuration_impl::get_id(const std::string &_name) const {
-	client_t its_client = 0;
+  client_t its_client = 0;
 
-	auto found_application = applications_.find(_name);
-	if (found_application != applications_.end()) {
-		its_client = found_application->second;
-	}
+  auto found_application = applications_.find(_name);
+  if (found_application != applications_.end()) {
+    its_client = found_application->second;
+  }
 
-	return its_client;
+  return its_client;
 }
 
 std::set<std::pair<service_t, instance_t> > configuration_impl::get_remote_services() const {
-	std::set < std::pair<service_t, instance_t> > its_remote_services;
-	for (auto i : services_) {
-		for (auto j : i.second) {
-			if (j.second->group_->unicast_ != "local")
-				its_remote_services.insert(std::make_pair(i.first, j.first));
-		}
-	}
-	return its_remote_services;
+  std::set < std::pair<service_t, instance_t> > its_remote_services;
+  for (auto i : services_) {
+    for (auto j : i.second) {
+      if (j.second->group_->unicast_ != "local")
+        its_remote_services.insert(std::make_pair(i.first, j.first));
+    }
+  }
+  return its_remote_services;
+}
+
+std::map<service_t,
+    std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > configuration_impl::get_eventgroups() const {
+  std::map<service_t,
+      std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > its_eventgroups;
+  for (auto i : services_) {
+    for (auto j : i.second) {
+      if (j.second->group_->unicast_ == "local") {
+        for (auto k : j.second->eventgroups_) {
+          for (auto l : k.second->events_) {
+            its_eventgroups[i.first][j.first][k.second->id_].insert(l->id_);
+          }
+        }
+      }
+    }
+  }
+  return its_eventgroups;
+}
+
+std::map<service_t, std::map<instance_t, std::set<event_t> > > configuration_impl::get_events() const {
+  std::map<service_t, std::map<instance_t, std::set<event_t> > > its_events;
+  for (auto i : services_) {
+    for (auto j : i.second) {
+      if (j.second->group_->unicast_ == "local") {
+        for (auto k : j.second->events_) {
+          its_events[i.first][j.first].insert(k.first);
+        }
+      }
+    }
+  }
+  return its_events;
+}
+
+void configuration_impl::set_event(
+    std::shared_ptr<vsomeip::event> &_event) const {
+  auto found_service = services_.find(_event->get_service());
+  if (found_service != services_.end()) {
+    auto found_instance = found_service->second.find(_event->get_instance());
+    if (found_instance != found_service->second.end()) {
+      auto found_event = found_instance->second->events_.find(
+          _event->get_event());
+      if (found_event != found_instance->second->events_.end()) {
+        _event->set_field(found_event->second->is_field_);
+      }
+    }
+  }
 }
 
 servicegroup *configuration_impl::find_servicegroup(
-		const std::string &_name) const {
-	servicegroup *its_servicegroup(0);
-	auto find_servicegroup = servicegroups_.find(_name);
-	if (find_servicegroup != servicegroups_.end()) {
-		its_servicegroup = find_servicegroup->second.get();
-	}
-	return its_servicegroup;
+    const std::string &_name) const {
+  servicegroup *its_servicegroup(0);
+  auto find_servicegroup = servicegroups_.find(_name);
+  if (find_servicegroup != servicegroups_.end()) {
+    its_servicegroup = find_servicegroup->second.get();
+  }
+  return its_servicegroup;
 }
 
 service *configuration_impl::find_service(service_t _service,
-		instance_t _instance) const {
-	service *its_service(0);
-	auto find_service = services_.find(_service);
-	if (find_service != services_.end()) {
-		auto find_instance = find_service->second.find(_instance);
-		if (find_instance != find_service->second.end()) {
-			its_service = find_instance->second.get();
-		}
-	}
-	return its_service;
+                                          instance_t _instance) const {
+  service *its_service(0);
+  auto find_service = services_.find(_service);
+  if (find_service != services_.end()) {
+    auto find_instance = find_service->second.find(_instance);
+    if (find_instance != find_service->second.end()) {
+      its_service = find_instance->second.get();
+    }
+  }
+  return its_service;
 }
 
-} // namespace config
-} // namespace vsomeip
+}  // namespace config
+}  // namespace vsomeip
diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp
index f648484..f88ea93 100644
--- a/implementation/endpoints/include/client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/client_endpoint_impl.hpp
@@ -38,6 +38,8 @@
 	virtual ~client_endpoint_impl();

 

 	bool send(const uint8_t *_data, uint32_t _size, bool _flush);

+	bool send_to(const boost::asio::ip::address &_address, uint16_t _port,

+	             const byte_t *_data, uint32_t _size, bool _flush = true);

 	bool flush();

 

 	void stop();

diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp
index eb26b7f..f1e58aa 100644
--- a/implementation/endpoints/include/endpoint.hpp
+++ b/implementation/endpoints/include/endpoint.hpp
@@ -7,6 +7,8 @@
 #ifndef VSOMEIP_ENDPOINT_HPP

 #define VSOMEIP_ENDPOINT_HPP

 

+#include <boost/asio/ip/address.hpp>

+

 #include <vsomeip/primitive_types.hpp>

 

 namespace vsomeip {

@@ -22,19 +24,23 @@
 	virtual bool is_connected() const = 0;

 

 	virtual bool send(const byte_t *_data, uint32_t _size, bool _flush = true) = 0;

+	virtual bool send_to(const boost::asio::ip::address &_address, uint16_t _port,

+	                     const byte_t *_data, uint32_t _size, bool _flush = true) = 0;

 	virtual void enable_magic_cookies() = 0;

 	virtual void receive() = 0;

 

 	virtual void open_filter(service_t _service_id) = 0;

 	virtual void close_filter(service_t _service_id) = 0;

 

-	virtual void join(const std::string &_multicast_address) = 0;

-	virtual void leave(const std::string &_multicast_address) = 0;

+	virtual void join(const std::string &_address) = 0;

+	virtual void leave(const std::string &_address) = 0;

 

-	virtual bool get_address(ipv4_address_t &_address) const = 0;

-	virtual bool get_address(ipv6_address_t &_address) const = 0;

+	virtual void add_multicast(service_t _service, event_t _event,

+			const std::string &_address, uint16_t _port) = 0;

+	virtual void remove_multicast(service_t _service, event_t _event) = 0;

+

 	virtual unsigned short get_port() const = 0;

-	virtual bool is_udp() const = 0;

+	virtual bool is_reliable() const = 0;

 };

 

 } // namespace vsomeip

diff --git a/implementation/endpoints/include/endpoint_impl.hpp b/implementation/endpoints/include/endpoint_impl.hpp
index 61d89bb..1be3474 100644
--- a/implementation/endpoints/include/endpoint_impl.hpp
+++ b/implementation/endpoints/include/endpoint_impl.hpp
@@ -33,12 +33,17 @@
 	void open_filter(service_t _service);

 	void close_filter(service_t _service);

 

+	// Dummy implementations as we only need these for UDP (servers)

+	// TODO: redesign

+	void join(const std::string &);

+	void leave(const std::string &);

+	void add_multicast(service_t, event_t, const std::string &, uint16_t);

+	void remove_multicast(service_t, event_t);

+

 	// Dummy implementations as we only need these for server endpoints

-	// TODO: redesign to avoid dummy implementations

-	bool get_address(ipv4_address_t &_address) const;

-	bool get_address(ipv6_address_t &_address) const;

+	// TODO: redesign

 	unsigned short get_port() const;

-	bool is_udp() const;

+	bool is_reliable() const;

 

 public: // required

 	virtual bool is_client() const = 0;

diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp
index 04e91f2..d5abb92 100644
--- a/implementation/endpoints/include/local_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp
@@ -30,9 +30,6 @@
 

 	void send_queued(message_buffer_ptr_t _data);

 

-	void join(const std::string &);

-	void leave(const std::string &);

-

 private:

 	void send_magic_cookie();

 

diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp
index 1ed4721..11e26be 100644
--- a/implementation/endpoints/include/local_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp
@@ -38,12 +38,12 @@
 	void restart();

 	void receive();

 

+	bool send_to(const boost::asio::ip::address &_address, uint16_t _port,

+               const byte_t *_data, uint32_t _size, bool _flush);

 	void send_queued(endpoint_type _target, message_buffer_ptr_t _data);

-	endpoint_type get_remote() const;

-	endpoint_type get_cast() const;

 

-	void join(const std::string &);

-	void leave(const std::string &);

+	endpoint_type get_remote() const;

+	bool get_multicast(service_t, event_t, endpoint_type &) const;

 

 private:

 	class connection

diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp
index 78a2e54..6d4b676 100644
--- a/implementation/endpoints/include/server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/server_endpoint_impl.hpp
@@ -7,10 +7,10 @@
 #ifndef VSOMEIP_SERVER_IMPL_HPP

 #define VSOMEIP_SERVER_IMPL_HPP

 

-#include <deque>

 #include <map>

 #include <memory>

 #include <mutex>

+#include <set>

 #include <vector>

 

 #include <boost/array.hpp>

@@ -21,47 +21,50 @@
 

 namespace vsomeip {

 

-template < typename Protocol, int MaxBufferSize >

-class server_endpoint_impl

-		: public endpoint_impl< MaxBufferSize >,

-		  public std::enable_shared_from_this< server_endpoint_impl<

-		  	  	  	  Protocol, MaxBufferSize > > {

-public:

-	typedef typename Protocol::socket socket_type;

-	typedef typename Protocol::endpoint endpoint_type;

-	typedef boost::array< uint8_t, MaxBufferSize > buffer_type;

+template<typename Protocol, int MaxBufferSize>

+class server_endpoint_impl : public endpoint_impl<MaxBufferSize>,

+    public std::enable_shared_from_this<

+        server_endpoint_impl<Protocol, MaxBufferSize> > {

+ public:

+  typedef typename Protocol::socket socket_type;

+  typedef typename Protocol::endpoint endpoint_type;

+  typedef boost::array<uint8_t, MaxBufferSize> buffer_type;

 

-	server_endpoint_impl(std::shared_ptr< endpoint_host > _host,

-			endpoint_type _local, boost::asio::io_service &_io);

+  server_endpoint_impl(std::shared_ptr<endpoint_host> _host,

+                       endpoint_type _local, boost::asio::io_service &_io);

 

-	bool is_client() const;

-	bool is_connected() const;

+  bool is_client() const;

+  bool is_connected() const;

 

-	bool send(const uint8_t *_data, uint32_t _size, bool _flush);

-	bool flush(endpoint_type _target);

+  bool send(const uint8_t *_data, uint32_t _size, bool _flush);

+  bool flush(endpoint_type _target);

 

-public:

-	void connect_cbk(boost::system::error_code const &_error);

-	void send_cbk(message_buffer_ptr_t _buffer,

-			boost::system::error_code const &_error, std::size_t _bytes);

-	void flush_cbk(endpoint_type _target, const boost::system::error_code &_error);

+ public:

+  void connect_cbk(boost::system::error_code const &_error);

+  void send_cbk(message_buffer_ptr_t _buffer,

+                boost::system::error_code const &_error, std::size_t _bytes);

+  void flush_cbk(endpoint_type _target,

+                 const boost::system::error_code &_error);

 

-public:

-	virtual void send_queued(endpoint_type _target, message_buffer_ptr_t _buffer) = 0;

-	virtual endpoint_type get_remote() const = 0;

-	virtual endpoint_type get_cast() const = 0;

+ public:

+  virtual bool send_intern(endpoint_type _target, const byte_t *_data, uint32_t _port, bool _flush);

+  virtual void send_queued(endpoint_type _target, message_buffer_ptr_t _buffer) = 0;

 

-protected:

-	std::map< endpoint_type, message_buffer_ptr_t > packetizer_;

-	std::map< client_t, std::map< session_t, endpoint_type > > clients_;

+  virtual endpoint_type get_remote() const = 0;

+  virtual bool get_multicast(service_t _service, event_t _event,

+                             endpoint_type &_target) const = 0;

 

-	boost::asio::system_timer flush_timer_;

+ protected:

+  std::map<endpoint_type, message_buffer_ptr_t> packetizer_;

+  std::map<client_t, std::map<session_t, endpoint_type> > clients_;

 

-	endpoint_type local_;

+  boost::asio::system_timer flush_timer_;

 

-	std::mutex mutex_;

+  endpoint_type local_;

+

+  std::mutex mutex_;

 };

 

-} // namespace vsomeip

+}  // namespace vsomeip

 

 #endif // VSOMEIP_SERVICE_ENDPOINT_IMPL_HPP

diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
index f3dd900..dc3f63d 100644
--- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
@@ -28,8 +28,8 @@
 	void start();

 	void send_queued(message_buffer_ptr_t _buffer);

 

-	void join(const std::string &);

-	void leave(const std::string &);

+	unsigned short get_port() const;

+	bool is_reliable() const;

 

 private:

 	bool is_magic_cookie() const;

diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
index 5085bbf..623634c 100644
--- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
@@ -32,17 +32,15 @@
 	void start();

 	void stop();

 

+	bool send_to(const boost::asio::ip::address &_address, uint16_t _port,

+	             const byte_t *_data, uint32_t _size, bool _flush);

 	void send_queued(endpoint_type _target, message_buffer_ptr_t _buffer);

+

 	endpoint_type get_remote() const;

-	endpoint_type get_cast() const;

+	bool get_multicast(service_t, event_t, endpoint_type &) const;

 

-	void join(const std::string &);

-	void leave(const std::string &);

-

-	bool get_address(ipv4_address_t &_address) const;

-	bool get_address(ipv6_address_t &_address) const;

 	unsigned short get_port() const;

-	bool is_udp() const;

+	bool is_reliable() const;

 

 	// dummies to implement endpoint_impl interface

 	// TODO: think about a better design!

diff --git a/implementation/endpoints/include/udp_client_endpoint_impl.hpp b/implementation/endpoints/include/udp_client_endpoint_impl.hpp
index 8918706..e0e348c 100644
--- a/implementation/endpoints/include/udp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_client_endpoint_impl.hpp
@@ -40,10 +40,13 @@
 	void start();

 	void send_queued(message_buffer_ptr_t _buffer);

 

-	void join(const std::string &_multicast_address);

-	void leave(const std::string &_multicast_address);

+	unsigned short get_port() const;

 

-	void receive_cbk(packet_buffer_ptr_t _buffer, boost::system::error_code const &_error, std::size_t _bytes);

+	void join(const std::string &_address);

+	void leave(const std::string &_address);

+

+	void receive_cbk(packet_buffer_ptr_t _buffer,

+			boost::system::error_code const &_error, std::size_t _bytes);

 

 private:

 	void connect();

diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
index 4b8f3aa..da1a98a 100644
--- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
@@ -38,17 +38,20 @@
 	void restart();

 	void receive();

 

+  bool send_to(const boost::asio::ip::address &_address, uint16_t _port,

+               const byte_t *_data, uint32_t _size, bool _flush);

 	void send_queued(endpoint_type _target, message_buffer_ptr_t _buffer);

+

 	endpoint_type get_remote() const;

-	endpoint_type get_cast() const;

+	bool get_multicast(service_t _service, event_t _event, endpoint_type &_target) const;

 

-	void join(const std::string &_multicast_address);

-	void leave(const std::string &_multicast_address);

+	void join(const std::string &_address);

+	void leave(const std::string &_address);

+	void add_multicast(service_t _service, instance_t _instance,

+			const std::string &_address, uint16_t _port);

+	void remove_multicast(service_t _service, instance_t _instance);

 

-	bool get_address(ipv4_address_t &_address) const;

-	bool get_address(ipv6_address_t &_address) const;

 	unsigned short get_port() const;

-	bool is_udp() const;

 

 public:

 	void receive_cbk(packet_buffer_ptr_t _buffer,

@@ -60,8 +63,7 @@
 private:

 	socket_type socket_;

 	endpoint_type remote_;

-	endpoint_type cast_;

-

+	std::map<service_t,	std::map<instance_t, endpoint_type> > multicasts_;

 	message_buffer_t message_;

 };

 

diff --git a/implementation/endpoints/src/client_endpoint_impl.cpp b/implementation/endpoints/src/client_endpoint_impl.cpp
index b7de1be..ce16386 100644
--- a/implementation/endpoints/src/client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/client_endpoint_impl.cpp
@@ -23,172 +23,177 @@
 

 namespace vsomeip {

 

-template < typename Protocol, int MaxBufferSize >

-client_endpoint_impl< Protocol, MaxBufferSize >::client_endpoint_impl(

-		std::shared_ptr< endpoint_host > _host,

-		endpoint_type _remote,

-		boost::asio::io_service &_io)

-	: endpoint_impl< MaxBufferSize >(_host, _io),

-	  socket_(_io),

-	  connect_timer_(_io),

-	  flush_timer_(_io),

-	  remote_(_remote),

-	  packetizer_(std::make_shared< message_buffer_t >()),

-	  connect_timeout_(VSOMEIP_DEFAULT_CONNECT_TIMEOUT), // TODO: use config variable

-	  is_connected_(false) {

+template<typename Protocol, int MaxBufferSize>

+client_endpoint_impl<Protocol, MaxBufferSize>::client_endpoint_impl(

+    std::shared_ptr<endpoint_host> _host, endpoint_type _remote,

+    boost::asio::io_service &_io)

+    : endpoint_impl<MaxBufferSize>(_host, _io),

+      socket_(_io),

+      connect_timer_(_io),

+      flush_timer_(_io),

+      remote_(_remote),

+      packetizer_(std::make_shared<message_buffer_t>()),

+      connect_timeout_(VSOMEIP_DEFAULT_CONNECT_TIMEOUT),  // TODO: use config variable

+      is_connected_(false) {

 }

 

-template < typename Protocol, int MaxBufferSize >

-client_endpoint_impl< Protocol, MaxBufferSize >::~client_endpoint_impl() {

+template<typename Protocol, int MaxBufferSize>

+client_endpoint_impl<Protocol, MaxBufferSize>::~client_endpoint_impl() {

 }

 

-template < typename Protocol, int MaxBufferSize >

-bool client_endpoint_impl< Protocol, MaxBufferSize >::is_client() const {

-	return true;

+template<typename Protocol, int MaxBufferSize>

+bool client_endpoint_impl<Protocol, MaxBufferSize>::is_client() const {

+  return true;

 }

 

-template < typename Protocol, int MaxBufferSize >

-bool client_endpoint_impl< Protocol, MaxBufferSize >::is_connected() const {

-	return is_connected_;

+template<typename Protocol, int MaxBufferSize>

+bool client_endpoint_impl<Protocol, MaxBufferSize>::is_connected() const {

+  return is_connected_;

 }

 

-template < typename Protocol, int MaxBufferSize >

-void client_endpoint_impl< Protocol, MaxBufferSize >::stop() {

-	if (socket_.is_open()) {

-		socket_.close();

-	}

+template<typename Protocol, int MaxBufferSize>

+void client_endpoint_impl<Protocol, MaxBufferSize>::stop() {

+  if (socket_.is_open()) {

+    socket_.close();

+  }

 }

 

-template < typename Protocol, int MaxBufferSize >

-void client_endpoint_impl< Protocol, MaxBufferSize >::restart() {

-	receive();

+template<typename Protocol, int MaxBufferSize>

+void client_endpoint_impl<Protocol, MaxBufferSize>::restart() {

+  receive();

 }

 

-template < typename Protocol, int MaxBufferSize >

-bool client_endpoint_impl< Protocol, MaxBufferSize >::send(

-		const uint8_t *_data, uint32_t _size, bool _flush) {

-	std::unique_lock< std::mutex > its_lock(mutex_);

+template<typename Protocol, int MaxBufferSize>

+bool client_endpoint_impl<Protocol, MaxBufferSize>::send_to(

+    const boost::asio::ip::address &_address, uint16_t _port,

+    const byte_t *_data, uint32_t _size, bool _flush) {

+  VSOMEIP_ERROR

+      << "Clients endpoints must not be used to send to explicitely specified targets";

+  return false;

+}

+

+template<typename Protocol, int MaxBufferSize>

+bool client_endpoint_impl<Protocol, MaxBufferSize>::send(const uint8_t *_data,

+                                                         uint32_t _size,

+                                                         bool _flush) {

+  std::unique_lock < std::mutex > its_lock(mutex_);

 #if 0

-	std::stringstream msg;

-	msg << "cei<" << this << ">::send: ";

-	for (uint32_t i = 0; i < _size; i++)

-		msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";

-	VSOMEIP_DEBUG << msg.str();

+  std::stringstream msg;

+  msg << "cei<" << this << ">::send: ";

+  for (uint32_t i = 0; i < _size; i++)

+  msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";

+  VSOMEIP_DEBUG << msg.str();

 #endif

-	if (packetizer_->size() + _size > MaxBufferSize) {

-		send_queued(packetizer_);

-		packetizer_ = std::make_shared< message_buffer_t >();

-	}

+  if (packetizer_->size() + _size > MaxBufferSize) {

+    send_queued(packetizer_);

+    packetizer_ = std::make_shared<message_buffer_t>();

+  }

 

-	packetizer_->insert(packetizer_->end(), _data, _data + _size);

+  packetizer_->insert(packetizer_->end(), _data, _data + _size);

 

-	if (_flush) {

-		flush_timer_.cancel();

-		send_queued(packetizer_);

-		packetizer_ = std::make_shared< message_buffer_t >();

-	} else {

-		flush_timer_.expires_from_now(

-			std::chrono::milliseconds(VSOMEIP_DEFAULT_FLUSH_TIMEOUT)); // TODO: use config variable

-		flush_timer_.async_wait(

-			std::bind(

-				&client_endpoint_impl<Protocol, MaxBufferSize>::flush_cbk,

-				this->shared_from_this(),

-				std::placeholders::_1

-			)

-		);

-	}

+  if (_flush) {

+    flush_timer_.cancel();

+    send_queued(packetizer_);

+    packetizer_ = std::make_shared<message_buffer_t>();

+  } else {

+    flush_timer_.expires_from_now(

+        std::chrono::milliseconds(VSOMEIP_DEFAULT_FLUSH_TIMEOUT));  // TODO: use config variable

+    flush_timer_.async_wait(

+        std::bind(&client_endpoint_impl<Protocol, MaxBufferSize>::flush_cbk,

+                  this->shared_from_this(), std::placeholders::_1));

+  }

 

-	return true;

+  return true;

 }

 

-template < typename Protocol, int MaxBufferSize >

-bool client_endpoint_impl< Protocol, MaxBufferSize >::flush() {

-	bool is_successful(true);

+template<typename Protocol, int MaxBufferSize>

+bool client_endpoint_impl<Protocol, MaxBufferSize>::flush() {

+  bool is_successful(true);

 

-	if (!packetizer_->empty()) {

-		send_queued(packetizer_);

-		packetizer_ = std::make_shared< message_buffer_t >();

-	} else {

-		is_successful = false;

-	}

+  if (!packetizer_->empty()) {

+    send_queued(packetizer_);

+    packetizer_ = std::make_shared<message_buffer_t>();

+  } else {

+    is_successful = false;

+  }

 

-	return is_successful;

+  return is_successful;

 }

 

-template < typename Protocol, int MaxBufferSize >

-void client_endpoint_impl< Protocol, MaxBufferSize >::connect_cbk(

-		boost::system::error_code const &_error) {

-	if (_error) {

-		socket_.close();

+template<typename Protocol, int MaxBufferSize>

+void client_endpoint_impl<Protocol, MaxBufferSize>::connect_cbk(

+    boost::system::error_code const &_error) {

+  if (_error) {

+    socket_.close();

 

-		connect_timer_.expires_from_now(

-			std::chrono::milliseconds(connect_timeout_));

-		connect_timer_.async_wait(

-			std::bind(

-				&client_endpoint_impl<Protocol, MaxBufferSize>::wait_connect_cbk,

-				this->shared_from_this(),

-				std::placeholders::_1

-			)

-		);

+    connect_timer_.expires_from_now(

+        std::chrono::milliseconds(connect_timeout_));

+    connect_timer_.async_wait(

+        std::bind(

+            &client_endpoint_impl<Protocol, MaxBufferSize>::wait_connect_cbk,

+            this->shared_from_this(), std::placeholders::_1));

 

-		// next time we wait longer

-		connect_timeout_ <<= 1;

+    // next time we wait longer

+    connect_timeout_ <<= 1;

 

-		if (is_connected_) {

-			is_connected_ = false;

-			this->host_->on_disconnect(this->shared_from_this());

-		}

-	} else {

-		connect_timer_.cancel();

-		connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT; // TODO: use config variable

+    if (is_connected_) {

+      is_connected_ = false;

+      this->host_->on_disconnect(this->shared_from_this());

+    }

+  } else {

+    connect_timer_.cancel();

+    connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT;  // TODO: use config variable

 

-		if (!is_connected_) {

-			is_connected_ = true;

-			this->host_->on_connect(this->shared_from_this());

-		}

+    if (!is_connected_) {

+      is_connected_ = true;

+      this->host_->on_connect(this->shared_from_this());

+    }

 

-		receive();

-	}

+    receive();

+  }

 }

 

-template < typename Protocol, int MaxBufferSize >

-void client_endpoint_impl< Protocol, MaxBufferSize >::wait_connect_cbk(

-		boost::system::error_code const &_error) {

-	if (!_error) {

-		connect();

-	}

+template<typename Protocol, int MaxBufferSize>

+void client_endpoint_impl<Protocol, MaxBufferSize>::wait_connect_cbk(

+    boost::system::error_code const &_error) {

+  if (!_error) {

+    connect();

+  }

 }

 

-template < typename Protocol, int MaxBufferSize >

-void client_endpoint_impl< Protocol, MaxBufferSize >::send_cbk(

-		message_buffer_ptr_t _buffer,

-		boost::system::error_code const &_error, std::size_t _bytes) {

+template<typename Protocol, int MaxBufferSize>

+void client_endpoint_impl<Protocol, MaxBufferSize>::send_cbk(

+    message_buffer_ptr_t _buffer, boost::system::error_code const &_error,

+    std::size_t _bytes) {

 #if 0

-		std::stringstream msg;

-		msg << "cei<" << this << ">::scb (" << _error.message() << "): ";

-		for (std::size_t i = 0; i < _data->size(); ++i)

-			msg << std::hex << std::setw(2) << std::setfill('0') << (int)(*_buffer)[i] << " ";

-		VSOMEIP_DEBUG << msg.str();

+  std::stringstream msg;

+  msg << "cei<" << this << ">::scb (" << _error.message() << "): ";

+  for (std::size_t i = 0; i < _data->size(); ++i)

+  msg << std::hex << std::setw(2) << std::setfill('0') << (int)(*_buffer)[i] << " ";

+  VSOMEIP_DEBUG << msg.str();

 #endif

-	if (_error == boost::asio::error::broken_pipe) {

-		is_connected_ = false;

-		socket_.close();

-		connect();

-	}

+  if (_error == boost::asio::error::broken_pipe) {

+    is_connected_ = false;

+    socket_.close();

+    connect();

+  }

 }

 

-template < typename Protocol, int MaxBufferSize >

-void client_endpoint_impl< Protocol, MaxBufferSize >::flush_cbk(

-		boost::system::error_code const &_error) {

-	if (!_error) {

-		(void)flush();

-	}

+template<typename Protocol, int MaxBufferSize>

+void client_endpoint_impl<Protocol, MaxBufferSize>::flush_cbk(

+    boost::system::error_code const &_error) {

+  if (!_error) {

+    (void) flush();

+  }

 }

 

 // Instantiate template

-template class client_endpoint_impl< boost::asio::local::stream_protocol, VSOMEIP_MAX_LOCAL_MESSAGE_SIZE >;

-template class client_endpoint_impl< boost::asio::ip::tcp, VSOMEIP_MAX_TCP_MESSAGE_SIZE >;

-template class client_endpoint_impl< boost::asio::ip::udp, VSOMEIP_MAX_UDP_MESSAGE_SIZE >;

+template class client_endpoint_impl<boost::asio::local::stream_protocol,

+    VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> ;

+template class client_endpoint_impl<boost::asio::ip::tcp,

+    VSOMEIP_MAX_TCP_MESSAGE_SIZE> ;

+template class client_endpoint_impl<boost::asio::ip::udp,

+    VSOMEIP_MAX_UDP_MESSAGE_SIZE> ;

 

-} // namespace vsomeip

+}  // namespace vsomeip

 

diff --git a/implementation/endpoints/src/endpoint_impl.cpp b/implementation/endpoints/src/endpoint_impl.cpp
index 9972bba..e36ac95 100644
--- a/implementation/endpoints/src/endpoint_impl.cpp
+++ b/implementation/endpoints/src/endpoint_impl.cpp
@@ -10,7 +10,6 @@
 

 #include "../include/endpoint_host.hpp"

 #include "../include/endpoint_impl.hpp"

-#include "../../message/include/byteorder.hpp"

 

 namespace vsomeip {

 

@@ -115,13 +114,20 @@
 }

 

 template < int MaxBufferSize >

-bool endpoint_impl< MaxBufferSize >::get_address(ipv4_address_t &_address) const {

-	return false;

+void endpoint_impl< MaxBufferSize >::join(const std::string &) {

 }

 

 template < int MaxBufferSize >

-bool endpoint_impl< MaxBufferSize >::get_address(ipv6_address_t &_address) const {

-	return false;

+void endpoint_impl< MaxBufferSize >::leave(const std::string &) {

+}

+

+template < int MaxBufferSize >

+void endpoint_impl< MaxBufferSize >::add_multicast(

+		service_t, event_t, const std::string &, uint16_t) {

+}

+

+template < int MaxBufferSize >

+void endpoint_impl< MaxBufferSize >::remove_multicast(service_t, event_t) {

 }

 

 template < int MaxBufferSize >

@@ -130,7 +136,7 @@
 }

 

 template < int MaxBufferSize >

-bool endpoint_impl< MaxBufferSize >::is_udp() const {

+bool endpoint_impl< MaxBufferSize >::is_reliable() const {

 	return false;

 }

 

diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp
index c1aba2f..747d5ec 100644
--- a/implementation/endpoints/src/local_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp
@@ -111,12 +111,6 @@
 void local_client_endpoint_impl::send_magic_cookie() {

 }

 

-void local_client_endpoint_impl::join(const std::string &) {

-}

-

-void local_client_endpoint_impl::leave(const std::string &) {

-}

-

 void local_client_endpoint_impl::send_tag_cbk(

 		boost::system::error_code const &_error, std::size_t _bytes) {

 }

diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp
index a6fb06e..5f2357f 100644
--- a/implementation/endpoints/src/local_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp
@@ -46,6 +46,11 @@
 

 }

 

+bool local_server_endpoint_impl::send_to(const boost::asio::ip::address &_address, uint16_t _port,

+                                         const byte_t *_data, uint32_t _size, bool _flush) {

+  return false;

+}

+

 void local_server_endpoint_impl::send_queued(endpoint_type _target, message_buffer_ptr_t _buffer) {

 	auto connection_iterator = connections_.find(_target);

 	if (connection_iterator != connections_.end())

@@ -64,8 +69,9 @@
 	return current_->get_socket().remote_endpoint();

 }

 

-local_server_endpoint_impl::endpoint_type local_server_endpoint_impl::get_cast() const {

-	return get_remote(); // TODO: change inheritance to separate local from ip endpoints

+bool local_server_endpoint_impl::get_multicast(

+		service_t, event_t, local_server_endpoint_impl::endpoint_type &) const {

+	return false;

 }

 

 void local_server_endpoint_impl::remove_connection(local_server_endpoint_impl::connection *_connection) {

@@ -80,12 +86,6 @@
 	}

 }

 

-void local_server_endpoint_impl::join(const std::string &) {

-}

-

-void local_server_endpoint_impl::leave(const std::string &) {

-}

-

 void local_server_endpoint_impl::accept_cbk(

 		connection::ptr _connection, boost::system::error_code const &_error) {

 

diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp
index 6ad224a..65c5dab 100644
--- a/implementation/endpoints/src/server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/server_endpoint_impl.cpp
@@ -17,148 +17,164 @@
 

 #include "../include/server_endpoint_impl.hpp"

 #include "../../configuration/include/internal.hpp"

+#include "../../utility/include/byteorder.hpp"

 #include "../../utility/include/utility.hpp"

 

 namespace vsomeip {

 

-template < typename Protocol, int MaxBufferSize >

-server_endpoint_impl< Protocol, MaxBufferSize >::server_endpoint_impl(

-		std::shared_ptr< endpoint_host > _host, endpoint_type _local, boost::asio::io_service &_io)

-	: endpoint_impl< MaxBufferSize >(_host, _io),

-	  flush_timer_(_io) {

+template<typename Protocol, int MaxBufferSize>

+server_endpoint_impl<Protocol, MaxBufferSize>::server_endpoint_impl(

+    std::shared_ptr<endpoint_host> _host, endpoint_type _local,

+    boost::asio::io_service &_io)

+    : endpoint_impl<MaxBufferSize>(_host, _io),

+      flush_timer_(_io) {

 }

 

-template < typename Protocol, int MaxBufferSize >

-bool server_endpoint_impl< Protocol, MaxBufferSize >::is_client() const {

-	return false;

+template<typename Protocol, int MaxBufferSize>

+bool server_endpoint_impl<Protocol, MaxBufferSize>::is_client() const {

+  return false;

 }

 

-template < typename Protocol, int MaxBufferSize >

-bool server_endpoint_impl< Protocol, MaxBufferSize >::is_connected() const {

-	return true;

+template<typename Protocol, int MaxBufferSize>

+bool server_endpoint_impl<Protocol, MaxBufferSize>::is_connected() const {

+  return true;

 }

 

-template < typename Protocol, int MaxBufferSize >

-bool server_endpoint_impl< Protocol, MaxBufferSize >::send(

-		const uint8_t *_data, uint32_t _size, bool _flush) {

+template<typename Protocol, int MaxBufferSize>

+bool server_endpoint_impl<Protocol, MaxBufferSize>::send(

+    const uint8_t *_data, uint32_t _size, bool _flush) {

 #if 0

-	std::stringstream msg;

-	msg << "sei::send ";

-	for (uint32_t i = 0; i < _size; i++)

-		msg << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";

-	VSOMEIP_DEBUG << msg.str();

+  std::stringstream msg;

+  msg << "sei::send ";

+  for (uint32_t i = 0; i < _size; i++)

+  msg << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";

+  VSOMEIP_DEBUG << msg.str();

 #endif

+  endpoint_type its_target;

+  bool is_valid_target(false);

 

-	endpoint_type its_target;

-	bool is_valid_target(false);

+  if (VSOMEIP_SESSION_POS_MAX < _size) {

+    std::unique_lock < std::mutex > its_lock(mutex_);

 

-	if (VSOMEIP_SESSION_POS_MAX < _size) {

-		std::unique_lock< std::mutex > its_lock(mutex_);

+    service_t its_service;

+    std::memcpy(&its_service, &_data[VSOMEIP_SERVICE_POS_MIN],

+                sizeof(service_t));

 

-		service_t its_service;

-		std::memcpy(&its_service, &_data[VSOMEIP_SERVICE_POS_MIN], sizeof(service_t));

+    client_t its_client;

+    std::memcpy(&its_client, &_data[VSOMEIP_CLIENT_POS_MIN], sizeof(client_t));

+    session_t its_session;

+    std::memcpy(&its_session, &_data[VSOMEIP_SESSION_POS_MIN],

+                sizeof(session_t));

 

-		client_t its_client;

-		std::memcpy(&its_client, &_data[VSOMEIP_CLIENT_POS_MIN], sizeof(client_t));

-		session_t its_session;

-		std::memcpy(&its_session, &_data[VSOMEIP_SESSION_POS_MIN], sizeof(session_t));

+    auto found_client = clients_.find(its_client);

+    if (found_client != clients_.end()) {

+      auto found_session = found_client->second.find(its_session);

+      if (found_session != found_client->second.end()) {

+        its_target = found_session->second;

+        is_valid_target = true;

+      }

+    } else {

+      event_t its_event = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],

+                                                _data[VSOMEIP_METHOD_POS_MAX]);

+      is_valid_target = get_multicast(its_service, its_event, its_target);

+    }

 

-		auto found_client = clients_.find(its_client);

-		if (found_client != clients_.end()) {

-			auto found_session = found_client->second.find(its_session);

-			if (found_session != found_client->second.end()) {

-				its_target = found_session->second;

-				is_valid_target = true;

-			}

-		} else if (its_service == 0xFFFF) {

-			its_target = get_cast();

-			is_valid_target = true;

-		}

-

-		if (is_valid_target) {

-			// find queue and packetizer (buffer)

-			std::shared_ptr< std::vector< byte_t > > target_packetizer;

-

-			auto found_packetizer = packetizer_.find(its_target);

-			if (found_packetizer != packetizer_.end()) {

-				target_packetizer = found_packetizer->second;

-			} else {

-				target_packetizer = std::make_shared< message_buffer_t >();

-				packetizer_.insert(std::make_pair(its_target, target_packetizer));

-			}

-

-			if (target_packetizer->size() + _size > MaxBufferSize) {

-				send_queued(its_target, target_packetizer);

-				packetizer_[its_target] = std::make_shared< message_buffer_t >();

-			}

-

-			target_packetizer->insert(target_packetizer->end(), _data, _data + _size);

-

-			if (_flush) {

-				flush_timer_.cancel();

-				send_queued(its_target, target_packetizer);

-				packetizer_[its_target] = std::make_shared< message_buffer_t >();

-			} else {

-				std::chrono::milliseconds flush_timeout(VSOMEIP_DEFAULT_FLUSH_TIMEOUT);

-				flush_timer_.expires_from_now(flush_timeout); // TODO: use configured value

-				flush_timer_.async_wait(

-					std::bind(

-						&server_endpoint_impl<Protocol, MaxBufferSize>::flush_cbk,

-						this->shared_from_this(),

-						its_target,

-						std::placeholders::_1

-					)

-				);

-			}

-		}

-	}

-

-	return is_valid_target;

+    if (is_valid_target) {

+      is_valid_target = send_intern(its_target, _data, _size, _flush);

+    }

+  }

+  return is_valid_target;

 }

 

-template < typename Protocol, int MaxBufferSize >

-bool server_endpoint_impl< Protocol, MaxBufferSize >::flush(endpoint_type _target) {

-	bool is_flushed = false;

-	std::unique_lock< std::mutex > its_lock(mutex_);

-	auto i = packetizer_.find(_target);

-	if (i != packetizer_.end() && !i->second->empty()) {

-		send_queued(_target, i->second);

-		i->second = std::make_shared< message_buffer_t >();

-		is_flushed = true;

-	}

+template<typename Protocol, int MaxBufferSize>

+bool server_endpoint_impl<Protocol, MaxBufferSize>::send_intern(endpoint_type _target,

+    const byte_t *_data, uint32_t _size, bool _flush) {

 

-	return is_flushed;

+  std::shared_ptr < std::vector<byte_t> > target_packetizer;

+  auto found_packetizer = packetizer_.find(_target);

+  if (found_packetizer != packetizer_.end()) {

+    target_packetizer = found_packetizer->second;

+  } else {

+    target_packetizer = std::make_shared<message_buffer_t>();

+    packetizer_.insert(

+        std::make_pair(_target, target_packetizer));

+  }

+

+  if (target_packetizer->size() + _size > MaxBufferSize) {

+    send_queued(_target, target_packetizer);

+    packetizer_[_target] = std::make_shared<message_buffer_t>();

+  }

+

+  target_packetizer->insert(

+      target_packetizer->end(), _data, _data + _size);

+

+  if (_flush) {

+    flush_timer_.cancel();

+    send_queued(_target, target_packetizer);

+    packetizer_[_target] = std::make_shared<message_buffer_t>();

+  } else {

+    std::chrono::milliseconds flush_timeout(VSOMEIP_DEFAULT_FLUSH_TIMEOUT);

+    flush_timer_.expires_from_now(flush_timeout);  // TODO: use configured value

+    flush_timer_.async_wait(

+        std::bind(

+            &server_endpoint_impl<Protocol, MaxBufferSize>::flush_cbk,

+            this->shared_from_this(), _target,

+            std::placeholders::_1));

+  }

+  return true;

 }

 

-template < typename Protocol, int MaxBufferSize >

-void server_endpoint_impl< Protocol, MaxBufferSize >::connect_cbk(

-		boost::system::error_code const &_error) {

+template<typename Protocol, int MaxBufferSize>

+bool server_endpoint_impl<Protocol, MaxBufferSize>::flush(

+    endpoint_type _target) {

+  bool is_flushed = false;

+  std::unique_lock < std::mutex > its_lock(mutex_);

+  auto i = packetizer_.find(_target);

+  if (i != packetizer_.end() && !i->second->empty()) {

+    send_queued(_target, i->second);

+    i->second = std::make_shared<message_buffer_t>();

+    is_flushed = true;

+  }

+

+  return is_flushed;

 }

 

-template < typename Protocol, int MaxBufferSize >

-void server_endpoint_impl< Protocol, MaxBufferSize >::send_cbk(

-		message_buffer_ptr_t _buffer,

-		boost::system::error_code const &_error, std::size_t _bytes) {

+template<typename Protocol, int MaxBufferSize>

+void server_endpoint_impl<Protocol, MaxBufferSize>::connect_cbk(

+  boost::system::error_code const &_error) {

+}

+

+template<typename Protocol, int MaxBufferSize>

+void server_endpoint_impl<Protocol, MaxBufferSize>::send_cbk(

+  message_buffer_ptr_t _buffer, boost::system::error_code const &_error,

+  std::size_t _bytes) {

 #if 0

-		std::stringstream msg;

-		msg << "sei::scb (" << _error.message() << "): ";

-		for (std::size_t i = 0; i < _buffer->size(); ++i)

-			msg << std::hex << std::setw(2) << std::setfill('0') << (int)(*_buffer)[i] << " ";

-		VSOMEIP_DEBUG << msg.str();

+std::stringstream msg;

+msg << "sei::scb (" << _error.message() << "): ";

+for (std::size_t i = 0; i < _buffer->size(); ++i)

+msg << std::hex << std::setw(2) << std::setfill('0') << (int)(*_buffer)[i] << " ";

+VSOMEIP_DEBUG << msg.str();

 #endif

 }

 

-template < typename Protocol, int MaxBufferSize >

-void server_endpoint_impl< Protocol, MaxBufferSize >::flush_cbk(

-		endpoint_type _target, const boost::system::error_code &_error_code) {

-	if (!_error_code) {

-		(void)flush(_target);

-	}

+template<typename Protocol, int MaxBufferSize>

+void server_endpoint_impl<Protocol, MaxBufferSize>::flush_cbk(

+  endpoint_type _target, const boost::system::error_code &_error_code) {

+if (!_error_code) {

+  (void) flush(_target);

+}

 }

 

 // Instantiate template

-template class server_endpoint_impl< boost::asio::local::stream_protocol, VSOMEIP_MAX_LOCAL_MESSAGE_SIZE >;

-template class server_endpoint_impl< boost::asio::ip::tcp, VSOMEIP_MAX_TCP_MESSAGE_SIZE >;

-template class server_endpoint_impl< boost::asio::ip::udp, VSOMEIP_MAX_UDP_MESSAGE_SIZE >;

+#ifndef __WINDOWS__

+template class server_endpoint_impl<boost::asio::local::stream_protocol,

+VSOMEIP_MAX_LOCAL_MESSAGE_SIZE> ;

+#else

+// TODO: put instantiation for windows here!

+#endif

+template class server_endpoint_impl<boost::asio::ip::tcp,

+VSOMEIP_MAX_TCP_MESSAGE_SIZE> ;

+template class server_endpoint_impl<boost::asio::ip::udp,

+VSOMEIP_MAX_UDP_MESSAGE_SIZE> ;

 

-} // namespace vsomeip

+}  // namespace vsomeip

diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
index 4786d44..2f44baf 100644
--- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
@@ -82,6 +82,14 @@
 	);

 }

 

+unsigned short tcp_client_endpoint_impl::get_port() const {

+  return socket_.local_endpoint().port();

+}

+

+bool tcp_client_endpoint_impl::is_reliable() const {

+  return true;

+}

+

 bool tcp_client_endpoint_impl::is_magic_cookie() const {

 	return (0 == std::memcmp(SERVICE_COOKIE, &message_[0], sizeof(SERVICE_COOKIE)));

 }

@@ -99,12 +107,6 @@
 	}

 }

 

-void tcp_client_endpoint_impl::join(const std::string &) {

-}

-

-void tcp_client_endpoint_impl::leave(const std::string &) {

-}

-

 void tcp_client_endpoint_impl::receive_cbk(

 		packet_buffer_ptr_t _buffer,

 		boost::system::error_code const &_error, std::size_t _bytes) {

diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
index 9d2879a..616f273 100644
--- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
@@ -20,213 +20,194 @@
 namespace vsomeip {

 

 tcp_server_endpoint_impl::tcp_server_endpoint_impl(

-		std::shared_ptr< endpoint_host > _host, endpoint_type _local, boost::asio::io_service &_io)

-	: tcp_server_endpoint_base_impl(_host, _local, _io),

-	  acceptor_(_io, _local), current_(0) {

-	is_supporting_magic_cookies_ = true;

+    std::shared_ptr<endpoint_host> _host, endpoint_type _local,

+    boost::asio::io_service &_io)

+    : tcp_server_endpoint_base_impl(_host, _local, _io),

+      acceptor_(_io, _local),

+      current_(0) {

+  is_supporting_magic_cookies_ = true;

 }

 

 tcp_server_endpoint_impl::~tcp_server_endpoint_impl() {

 }

 

 void tcp_server_endpoint_impl::start() {

-	connection::ptr new_connection = connection::create(this);

+  connection::ptr new_connection = connection::create(this);

 

-	acceptor_.async_accept(

-		new_connection->get_socket(),

-		std::bind(

-			&tcp_server_endpoint_impl::accept_cbk,

-			std::dynamic_pointer_cast< tcp_server_endpoint_impl >(shared_from_this()),

-			new_connection,

-			std::placeholders::_1

-		)

-	);

+  acceptor_.async_accept(

+      new_connection->get_socket(),

+      std::bind(

+          &tcp_server_endpoint_impl::accept_cbk,

+          std::dynamic_pointer_cast < tcp_server_endpoint_impl

+              > (shared_from_this()),

+          new_connection, std::placeholders::_1));

 }

 

 void tcp_server_endpoint_impl::stop() {

-	for (auto& i : connections_)

-		i.second->stop();

-	acceptor_.close();

+  for (auto& i : connections_)

+    i.second->stop();

+  acceptor_.close();

 }

 

-void tcp_server_endpoint_impl::send_queued(endpoint_type _target, message_buffer_ptr_t _buffer) {

-	auto connection_iterator = connections_.find(_target);

-	if (connection_iterator != connections_.end())

-		connection_iterator->second->send_queued(_buffer);

+bool tcp_server_endpoint_impl::send_to(

+    const boost::asio::ip::address &_address, uint16_t _port,

+    const byte_t *_data, uint32_t _size, bool _flush) {

+  endpoint_type its_target(_address, _port);

+  return send_intern(its_target, _data, _size, _flush);

+}

+

+void tcp_server_endpoint_impl::send_queued(endpoint_type _target,

+                                           message_buffer_ptr_t _buffer) {

+  auto connection_iterator = connections_.find(_target);

+  if (connection_iterator != connections_.end())

+    connection_iterator->second->send_queued(_buffer);

 }

 

 tcp_server_endpoint_impl::endpoint_type tcp_server_endpoint_impl::get_remote() const {

-	return current_->get_socket().remote_endpoint();

+  return current_->get_socket().remote_endpoint();

 }

 

-tcp_server_endpoint_impl::endpoint_type tcp_server_endpoint_impl::get_cast() const {

-	return get_remote();

+bool tcp_server_endpoint_impl::get_multicast(

+    service_t, event_t, tcp_server_endpoint_impl::endpoint_type &) const {

+  return false;

 }

 

 void tcp_server_endpoint_impl::accept_cbk(

-		connection::ptr _connection, boost::system::error_code const &_error) {

+    connection::ptr _connection, boost::system::error_code const &_error) {

 

-	if (!_error) {

-			socket_type &new_connection_socket = _connection->get_socket();

-			endpoint_type remote = new_connection_socket.remote_endpoint();

+  if (!_error) {

+    socket_type &new_connection_socket = _connection->get_socket();

+    endpoint_type remote = new_connection_socket.remote_endpoint();

 

-			connections_[remote] = _connection;

-			_connection->start();

-		}

+    connections_[remote] = _connection;

+    _connection->start();

+  }

 

-		start();

-}

-

-void tcp_server_endpoint_impl::join(const std::string &) {

-}

-

-void tcp_server_endpoint_impl::leave(const std::string &) {

-}

-

-bool tcp_server_endpoint_impl::get_address(ipv4_address_t &_address) const {

-	boost::asio::ip::address its_address = acceptor_.local_endpoint().address();

-	if (its_address.is_v4()) {

-		_address = its_address.to_v4().to_bytes();

-	} else {

-		return false;

-	}

-	return true;

-}

-

-bool tcp_server_endpoint_impl::get_address(ipv6_address_t &_address) const {

-	boost::asio::ip::address its_address = acceptor_.local_endpoint().address();

-	if (its_address.is_v6()) {

-		_address = its_address.to_v6().to_bytes();

-	} else {

-		return false;

-	}

-	return true;

+  start();

 }

 

 unsigned short tcp_server_endpoint_impl::get_port() const {

-	return acceptor_.local_endpoint().port();

+  return acceptor_.local_endpoint().port();

 }

 

-bool tcp_server_endpoint_impl::is_udp() const {

-	return false;

+bool tcp_server_endpoint_impl::is_reliable() const {

+  return true;

 }

 

 ///////////////////////////////////////////////////////////////////////////////

 // class tcp_service_impl::connection

 ///////////////////////////////////////////////////////////////////////////////

-tcp_server_endpoint_impl::connection::connection(tcp_server_endpoint_impl *_server)

-	: socket_(_server->service_), server_(_server) {

+tcp_server_endpoint_impl::connection::connection(

+    tcp_server_endpoint_impl *_server)

+    : socket_(_server->service_),

+      server_(_server) {

 }

 

-tcp_server_endpoint_impl::connection::ptr

-tcp_server_endpoint_impl::connection::create(tcp_server_endpoint_impl *_server) {

-	return ptr(new connection(_server));

+tcp_server_endpoint_impl::connection::ptr tcp_server_endpoint_impl::connection::create(

+    tcp_server_endpoint_impl *_server) {

+  return ptr(new connection(_server));

 }

 

 tcp_server_endpoint_impl::socket_type & tcp_server_endpoint_impl::connection::get_socket() {

-	return socket_;

+  return socket_;

 }

 

 void tcp_server_endpoint_impl::connection::start() {

-	packet_buffer_ptr_t its_buffer

-		= std::make_shared< packet_buffer_t >();

-	socket_.async_receive(

-		boost::asio::buffer(*its_buffer),

-		std::bind(

-			&tcp_server_endpoint_impl::connection::receive_cbk,

-			shared_from_this(),

-			its_buffer,

-			std::placeholders::_1,

-			std::placeholders::_2

-		)

-	);

+  packet_buffer_ptr_t its_buffer = std::make_shared<packet_buffer_t>();

+  socket_.async_receive(

+      boost::asio::buffer(*its_buffer),

+      std::bind(&tcp_server_endpoint_impl::connection::receive_cbk,

+                shared_from_this(), its_buffer, std::placeholders::_1,

+                std::placeholders::_2));

 }

 

 void tcp_server_endpoint_impl::connection::stop() {

-	socket_.close();

+  socket_.close();

 }

 

-void tcp_server_endpoint_impl::connection::send_queued(message_buffer_ptr_t _buffer) {

-	if (server_->has_enabled_magic_cookies_)

-		send_magic_cookie(_buffer);

+void tcp_server_endpoint_impl::connection::send_queued(

+    message_buffer_ptr_t _buffer) {

+  if (server_->has_enabled_magic_cookies_)

+    send_magic_cookie(_buffer);

 

-	boost::asio::async_write(

-		socket_,

-		boost::asio::buffer(*_buffer),

-		std::bind(

-			&tcp_server_endpoint_base_impl::send_cbk,

-			server_->shared_from_this(),

-			_buffer,

-			std::placeholders::_1,

-			std::placeholders::_2

-		)

-	);

+  boost::asio::async_write(

+      socket_,

+      boost::asio::buffer(*_buffer),

+      std::bind(&tcp_server_endpoint_base_impl::send_cbk,

+                server_->shared_from_this(), _buffer, std::placeholders::_1,

+                std::placeholders::_2));

 }

 

-void tcp_server_endpoint_impl::connection::send_magic_cookie(message_buffer_ptr_t &_buffer) {

-	if (VSOMEIP_MAX_TCP_MESSAGE_SIZE - _buffer->size() >=

-		VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) {

-		_buffer->insert(

-			_buffer->begin(),

-			SERVICE_COOKIE,

-			SERVICE_COOKIE + sizeof(SERVICE_COOKIE)

-		);

-	}

+void tcp_server_endpoint_impl::connection::send_magic_cookie(

+    message_buffer_ptr_t &_buffer) {

+  if (VSOMEIP_MAX_TCP_MESSAGE_SIZE - _buffer->size() >=

+  VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) {

+    _buffer->insert(_buffer->begin(), SERVICE_COOKIE,

+                    SERVICE_COOKIE + sizeof(SERVICE_COOKIE));

+  }

 }

 

 bool tcp_server_endpoint_impl::connection::is_magic_cookie() const {

-	return (0 == std::memcmp(CLIENT_COOKIE, &message_[0], sizeof(CLIENT_COOKIE)));

+  return (0 == std::memcmp(CLIENT_COOKIE, &message_[0], sizeof(CLIENT_COOKIE)));

 }

 

 void tcp_server_endpoint_impl::connection::receive_cbk(

-		packet_buffer_ptr_t _buffer,

-		boost::system::error_code const &_error, std::size_t _bytes) {

+    packet_buffer_ptr_t _buffer, boost::system::error_code const &_error,

+    std::size_t _bytes) {

 #if 0

-	std::stringstream msg;

-	for (std::size_t i = 0; i < _bytes; ++i)

-		msg << std::hex << std::setw(2) << std::setfill('0') << (int)(*_buffer))[i] << " ";

-	VSOMEIP_DEBUG << msg.str();

+  std::stringstream msg;

+  for (std::size_t i = 0; i < _bytes; ++i)

+  msg << std::hex << std::setw(2) << std::setfill('0') << (int)(*_buffer))[i] << " ";

+  VSOMEIP_DEBUG << msg.str();

 #endif

-	if (!_error && 0 < _bytes) {

-		message_.insert(message_.end(), _buffer->begin(), _buffer->begin() + _bytes);

+  if (!_error && 0 < _bytes) {

+    message_.insert(message_.end(), _buffer->begin(),

+                    _buffer->begin() + _bytes);

 

-		bool has_full_message;

-		do {

-			uint32_t current_message_size = utility::get_message_size(message_);

-			has_full_message = (current_message_size > 0 && current_message_size <= message_.size());

-			if (has_full_message) {

-				if (is_magic_cookie()) {

-					server_->has_enabled_magic_cookies_ = true;

-				} else {

-					if (utility::is_request(message_[VSOMEIP_MESSAGE_TYPE_POS])) {

-						client_t its_client;

-						std::memcpy(&its_client, &message_[VSOMEIP_CLIENT_POS_MIN], sizeof(client_t));

-						session_t its_session;

-						std::memcpy(&its_session, &message_[VSOMEIP_SESSION_POS_MIN], sizeof(session_t));

-						server_->clients_[its_client][its_session] = socket_.remote_endpoint();

-					}

-					server_->host_->on_message(&message_[0], current_message_size, server_);

-				}

-				message_.erase(message_.begin(), message_.begin() + current_message_size);

-			} else if (server_->has_enabled_magic_cookies_ && message_.size() > 0){

-				has_full_message = server_->resync_on_magic_cookie(message_);

-			} else if (message_.size() > VSOMEIP_MAX_TCP_MESSAGE_SIZE) {

-				VSOMEIP_ERROR << "Message exceeds maximum message size. Resetting receiver.";

-				message_.clear();

-			}

-		} while (has_full_message);

+    bool has_full_message;

+    do {

+      uint32_t current_message_size = utility::get_message_size(message_);

+      has_full_message = (current_message_size > 0

+          && current_message_size <= message_.size());

+      if (has_full_message) {

+        if (is_magic_cookie()) {

+          server_->has_enabled_magic_cookies_ = true;

+        } else {

+          if (utility::is_request(message_[VSOMEIP_MESSAGE_TYPE_POS])) {

+            client_t its_client;

+            std::memcpy(&its_client, &message_[VSOMEIP_CLIENT_POS_MIN],

+                        sizeof(client_t));

+            session_t its_session;

+            std::memcpy(&its_session, &message_[VSOMEIP_SESSION_POS_MIN],

+                        sizeof(session_t));

+            server_->clients_[its_client][its_session] =

+                socket_.remote_endpoint();

+          }

+          server_->host_->on_message(&message_[0], current_message_size,

+                                     server_);

+        }

+        message_.erase(message_.begin(),

+                       message_.begin() + current_message_size);

+      } else if (server_->has_enabled_magic_cookies_ && message_.size() > 0) {

+        has_full_message = server_->resync_on_magic_cookie(message_);

+      } else if (message_.size() > VSOMEIP_MAX_TCP_MESSAGE_SIZE) {

+        VSOMEIP_ERROR

+            << "Message exceeds maximum message size. Resetting receiver.";

+        message_.clear();

+      }

+    } while (has_full_message);

 

-		start();

-	}

+    start();

+  }

 }

 

 // Dummies

 void tcp_server_endpoint_impl::receive() {

-	// intentionally left empty

+  // intentionally left empty

 }

 

 void tcp_server_endpoint_impl::restart() {

-	// intentionally left empty

+  // intentionally left empty

 }

 

-} // namespace vsomeip

+}  // namespace vsomeip

diff --git a/implementation/endpoints/src/udp_client_endpoint_impl.cpp b/implementation/endpoints/src/udp_client_endpoint_impl.cpp
index c57ac82..585b056 100644
--- a/implementation/endpoints/src/udp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_client_endpoint_impl.cpp
@@ -79,30 +79,33 @@
 	);

 }

 

-void udp_client_endpoint_impl::join(const std::string &_multicast_address) {

+unsigned short udp_client_endpoint_impl::get_port() const {

+  return socket_.local_endpoint().port();

+}

+

+void udp_client_endpoint_impl::join(const std::string &_address) {

+

 	if (remote_.address().is_v4()) {

 		try {

 			socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));

 			socket_.set_option(boost::asio::ip::multicast::join_group(

-							   boost::asio::ip::address::from_string(_multicast_address)));

+							   boost::asio::ip::address::from_string(_address)));

 		}

 		catch (...) {

-

 		}

 	} else {

 		// TODO: support multicast for IPv6

 	}

 }

 

-void udp_client_endpoint_impl::leave(const std::string &_multicast_address) {

+void udp_client_endpoint_impl::leave(const std::string &_address) {

 	if (remote_.address().is_v4()) {

 		try {

 			socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));

 			socket_.set_option(boost::asio::ip::multicast::leave_group(

-							   boost::asio::ip::address::from_string(_multicast_address)));

+							   boost::asio::ip::address::from_string(_address)));

 		}

 		catch (...) {

-

 		}

 	} else {

 		// TODO: support multicast for IPv6

@@ -112,11 +115,10 @@
 void udp_client_endpoint_impl::receive_cbk(

 		packet_buffer_ptr_t _buffer,

 		boost::system::error_code const &_error, std::size_t _bytes) {

-

 	if (!_error && 0 < _bytes) {

 #if 0

 		std::stringstream msg;

-		msg << "cei::rcb (" << _error.message() << "): ";

+		msg << "ucei::rcb(" << _error.message() << "): ";

 		for (std::size_t i = 0; i < _bytes; ++i)

 			msg << std::hex << std::setw(2) << std::setfill('0') << (int)(*_buffer)[i] << " ";

 		VSOMEIP_DEBUG << msg.str();

@@ -133,11 +135,9 @@
 				this->message_.erase(this->message_.begin(), this->message_.begin() + current_message_size);

 			}

 		} while (has_full_message);

-

-		restart();

-	} else {

-		receive();

 	}

+

+	receive();

 }

 

 } // namespace vsomeip

diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
index 53df320..b63c3a5 100644
--- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
@@ -14,7 +14,7 @@
 

 #include "../include/endpoint_host.hpp"

 #include "../include/udp_server_endpoint_impl.hpp"

-#include "../../message/include/byteorder.hpp"

+#include "../../utility/include/byteorder.hpp"

 #include "../../utility/include/utility.hpp"

 

 namespace ip = boost::asio::ip;

@@ -24,8 +24,7 @@
 udp_server_endpoint_impl::udp_server_endpoint_impl(

 		std::shared_ptr< endpoint_host > _host, endpoint_type _local, boost::asio::io_service &_io)

 	: server_endpoint_impl< ip::udp, VSOMEIP_MAX_UDP_MESSAGE_SIZE >(_host, _local, _io),

-	  socket_(_io, _local),

-	  cast_(_local) {

+	  socket_(_io, _local) {

 	boost::asio::socket_base::broadcast option(true);

 	socket_.set_option(option);

 }

@@ -38,6 +37,8 @@
 }

 

 void udp_server_endpoint_impl::stop() {

+	if (socket_.is_open())

+		socket_.close();

 }

 

 void udp_server_endpoint_impl::receive() {

@@ -61,6 +62,13 @@
 	receive();

 }

 

+bool udp_server_endpoint_impl::send_to(

+    const boost::asio::ip::address &_address, uint16_t _port,

+    const byte_t *_data, uint32_t _size, bool _flush) {

+  endpoint_type its_target(_address, _port);

+  return send_intern(its_target, _data, _size, _flush);

+}

+

 void udp_server_endpoint_impl::send_queued(endpoint_type _target, message_buffer_ptr_t _buffer) {

 #if 0

 		std::stringstream msg;

@@ -86,18 +94,27 @@
 	return remote_;

 }

 

-udp_server_endpoint_impl::endpoint_type udp_server_endpoint_impl::get_cast() const {

-	return cast_;

+bool udp_server_endpoint_impl::get_multicast(service_t _service, event_t _event,

+		udp_server_endpoint_impl::endpoint_type &_target) const {

+	bool is_valid(false);

+	auto find_service = multicasts_.find(_service);

+	if (find_service != multicasts_.end()) {

+		auto find_event = find_service->second.find(_event);

+		if (find_event != find_service->second.end()) {

+			_target = find_event->second;

+			is_valid = true;

+		}

+	}

+	return is_valid;

 }

 

-void udp_server_endpoint_impl::join(const std::string &_multicast_address) {

+void udp_server_endpoint_impl::join(const std::string &_address) {

 	if (local_.address().is_v4()) {

 		try {

-			cast_.address(boost::asio::ip::address::from_string(_multicast_address));

 			socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));

 			socket_.set_option(boost::asio::ip::multicast::enable_loopback(false));

 			socket_.set_option(boost::asio::ip::multicast::join_group(

-					boost::asio::ip::address::from_string(_multicast_address).to_v4()));

+					boost::asio::ip::address::from_string(_address).to_v4()));

 		}

 		catch (const std::exception &e) {

 			VSOMEIP_ERROR << e.what();

@@ -107,12 +124,11 @@
 	}

 }

 

-void udp_server_endpoint_impl::leave(const std::string &_multicast_address) {

+void udp_server_endpoint_impl::leave(const std::string &_address) {

 	if (local_.address().is_v4()) {

 		try {

 			socket_.set_option(boost::asio::ip::multicast::leave_group(

-							   boost::asio::ip::address::from_string(_multicast_address)));

-			cast_.address(cast_.address().to_v4().broadcast());

+							   boost::asio::ip::address::from_string(_address)));

 		}

 		catch (...) {

 

@@ -122,34 +138,26 @@
 	}

 }

 

-bool udp_server_endpoint_impl::get_address(ipv4_address_t &_address) const {

-	boost::asio::ip::address its_address = socket_.local_endpoint().address();

-	if (its_address.is_v4()) {

-		_address = its_address.to_v4().to_bytes();

-	} else {

-		return false;

-	}

-	return true;

+void udp_server_endpoint_impl::add_multicast(service_t _service, instance_t _instance,

+		const std::string &_address, uint16_t _port) {

+	endpoint_type its_endpoint(boost::asio::ip::address::from_string(_address), _port);

+	multicasts_[_service][_instance] = its_endpoint;

 }

 

-bool udp_server_endpoint_impl::get_address(ipv6_address_t &_address) const {

-	boost::asio::ip::address its_address = socket_.local_endpoint().address();

-	if (its_address.is_v6()) {

-		_address = its_address.to_v6().to_bytes();

-	} else {

-		return false;

+void udp_server_endpoint_impl::remove_multicast(service_t _service, instance_t _instance) {

+	auto found_service = multicasts_.find(_service);

+	if (found_service != multicasts_.end()) {

+		auto found_instance = found_service->second.find(_instance);

+		if (found_instance != found_service->second.end()) {

+			found_service->second.erase(_instance);

+		}

 	}

-	return true;

 }

 

 unsigned short udp_server_endpoint_impl::get_port() const {

 	return socket_.local_endpoint().port();

 }

 

-bool udp_server_endpoint_impl::is_udp() const {

-	return false;

-}

-

 // TODO: find a better way to structure the receive functions

 void udp_server_endpoint_impl::receive_cbk(

 		packet_buffer_ptr_t _buffer,

diff --git a/implementation/message/include/event_impl.hpp b/implementation/message/include/event_impl.hpp
deleted file mode 100644
index 689e7af..0000000
--- a/implementation/message/include/event_impl.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (C) 2014 BMW Group
-// Author: Lutz Bichler (lutz.bichler@bmw.de)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_EVENT_IMPL_HPP
-#define VSOMEIP_EVENT_IMPL_HPP
-
-#include <memory>
-#include <mutex>
-
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/system_timer.hpp>
-
-#include <vsomeip/event.hpp>
-
-namespace vsomeip {
-
-class message;
-
-class event_impl: public event {
-public:
-	event_impl(boost::asio::io_service &_io);
-	virtual ~event_impl();
-
-	service_t get_service() const;
-	void set_service(service_t _service);
-
-	instance_t get_instance() const;
-	void set_instance(instance_t _instance);
-
-	event_t get_event() const;
-	void set_event(event_t _event);
-
-	std::shared_ptr< payload > get_payload() const;
-	void set_payload(std::shared_ptr< payload > _payload);
-
-	// SIP_RPC_357
-	void set_update_cycle(std::chrono::milliseconds &_cycle);
-
-	// SIP_RPC_358
-	void set_update_on_change(bool _is_on);
-
-	// SIP_RPC_359 (epsilon change) is not supported!
-
-private:
-	std::mutex mutex_;
-	std::shared_ptr< message > update_;
-
-	boost::asio::system_timer cycle_timer_;
-	std::chrono::milliseconds cycle_;
-
-	bool is_updating_on_change_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_EVENT_IMPL_HPP
diff --git a/implementation/message/src/deserializer.cpp b/implementation/message/src/deserializer.cpp
index 05abcf7..28d45c4 100644
--- a/implementation/message/src/deserializer.cpp
+++ b/implementation/message/src/deserializer.cpp
@@ -13,9 +13,9 @@
 #include <vsomeip/logger.hpp>

 #endif

 

-#include "../include/byteorder.hpp"

 #include "../include/message_impl.hpp"

 #include "../include/deserializer.hpp"

+#include "../../utility/include/byteorder.hpp"

 

 namespace vsomeip {

 

diff --git a/implementation/message/src/event_impl.cpp b/implementation/message/src/event_impl.cpp
deleted file mode 100644
index ed6cee3..0000000
--- a/implementation/message/src/event_impl.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2014 BMW Group
-// Author: Lutz Bichler (lutz.bichler@bmw.de)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <vsomeip/message.hpp>
-#include <vsomeip/runtime.hpp>
-
-#include "../include/event_impl.hpp"
-
-namespace vsomeip {
-
-event_impl::event_impl(boost::asio::io_service &_io)
-	: update_(runtime::get()->create_notification()),
-	  cycle_timer_(_io),
-	  is_updating_on_change_(false) {
-}
-
-event_impl::~event_impl() {
-}
-
-service_t event_impl::get_service() const {
-	return update_->get_service();
-}
-
-void event_impl::set_service(service_t _service) {
-	update_->set_service(_service);
-}
-
-instance_t event_impl::get_instance() const {
-	return update_->get_instance();
-}
-
-void event_impl::set_instance(instance_t _instance) {
-	update_->set_instance(_instance);
-}
-
-event_t event_impl::get_event() const {
-	return update_->get_method();
-}
-
-void event_impl::set_event(event_t _event) {
-	update_->set_method(_event); // TODO: maybe we should check for the leading 0-bit
-}
-
-std::shared_ptr< payload > event_impl::get_payload() const {
-	return update_->get_payload();
-}
-
-void event_impl::set_payload(std::shared_ptr< payload > _payload) {
-	std::unique_lock< std::mutex > its_lock(mutex_);
-
-}
-
-void event_impl::set_update_on_change(bool _is_active) {
-	is_updating_on_change_ = _is_active;
-}
-
-void event_impl::set_update_cycle(std::chrono::milliseconds &_cycle) {
-	cycle_ = _cycle;
-	cycle_timer_.cancel();
-
-	if (std::chrono::milliseconds::zero() != _cycle) {
-		cycle_timer_.expires_from_now(cycle_);
-/*
-
-		std::function< void (boost::system::error_code const &) > its_handler
-					= [this, its_handler] (boost::system::error_code const &_error) {
-							// TODO: Tell the RM[I|P] to do the update
-							cycle_timer_.expires_from_now(cycle_);
-							cycle_timer_.async_wait(its_handler);
-					  };
-
-		cycle_timer_.async_wait(its_handler); */
-	}
-}
-
-} // namespace vsomeip
diff --git a/implementation/message/src/message_base_impl.cpp b/implementation/message/src/message_base_impl.cpp
index 5bef55f..5504c2e 100644
--- a/implementation/message/src/message_base_impl.cpp
+++ b/implementation/message/src/message_base_impl.cpp
@@ -4,8 +4,8 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this

 // file, You can obtain one at http://mozilla.org/MPL/2.0/.

 

-#include "../include/byteorder.hpp"

 #include "../include/message_impl.hpp"

+#include "../../utility/include/byteorder.hpp"

 

 namespace vsomeip {

 

diff --git a/implementation/message/src/message_impl.cpp b/implementation/message/src/message_impl.cpp
index d179358..4be896a 100644
--- a/implementation/message/src/message_impl.cpp
+++ b/implementation/message/src/message_impl.cpp
@@ -8,8 +8,8 @@
 #include <vsomeip/payload.hpp>

 #include <vsomeip/runtime.hpp>

 

-#include "../include/byteorder.hpp"

 #include "../include/message_impl.hpp"

+#include "../../utility/include/byteorder.hpp"

 

 namespace vsomeip {

 

diff --git a/implementation/message/src/serializer.cpp b/implementation/message/src/serializer.cpp
index 990bba5..416e26b 100644
--- a/implementation/message/src/serializer.cpp
+++ b/implementation/message/src/serializer.cpp
@@ -15,8 +15,8 @@
 

 #include <vsomeip/serializable.hpp>

 

-#include "../include/byteorder.hpp"

 #include "../include/serializer.hpp"

+#include "../../utility/include/byteorder.hpp"

 

 namespace vsomeip {

 

diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp
new file mode 100644
index 0000000..2299279
--- /dev/null
+++ b/implementation/routing/include/event.hpp
@@ -0,0 +1,71 @@
+// Copyright (C) 2014 BMW Group
+// Author: Lutz Bichler (lutz.bichler@bmw.de)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_EVENT_IMPL_HPP
+#define VSOMEIP_EVENT_IMPL_HPP
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/system_timer.hpp>
+
+namespace vsomeip {
+
+class endpoint;
+class message;
+class payload;
+class routing_manager;
+
+class event : public std::enable_shared_from_this<event> {
+ public:
+  event(routing_manager *_routing);
+
+  service_t get_service() const;
+  void set_service(service_t _service);
+
+  instance_t get_instance() const;
+  void set_instance(instance_t _instance);
+
+  event_t get_event() const;
+  void set_event(event_t _event);
+
+  std::shared_ptr<payload> get_payload() const;
+  void set_payload(std::shared_ptr<payload> _payload);
+
+  bool is_field() const;
+  void set_field(bool _is_field);
+
+  // SIP_RPC_357
+  void set_update_cycle(std::chrono::milliseconds &_cycle);
+
+  // SIP_RPC_358
+  void set_update_on_change(bool _is_on);
+
+  // SIP_RPC_359 (epsilon change) is not supported!
+
+ private:
+  void update_cbk(boost::system::error_code const &_error);
+  void notify();
+
+ private:
+  routing_manager *routing_;
+  std::mutex mutex_;
+  std::shared_ptr<message> message_;
+
+  bool is_field_;
+
+  boost::asio::system_timer cycle_timer_;
+  std::chrono::milliseconds cycle_;
+
+  bool is_updating_on_change_;
+};
+
+}  // namespace vsomeip
+
+#endif // VSOMEIP_EVENT_IMPL_HPP
diff --git a/implementation/routing/include/eventgroupinfo.hpp b/implementation/routing/include/eventgroupinfo.hpp
index 06c92e0..5305e90 100644
--- a/implementation/routing/include/eventgroupinfo.hpp
+++ b/implementation/routing/include/eventgroupinfo.hpp
@@ -10,37 +10,40 @@
 #include <memory>
 #include <set>
 
+#include <boost/asio/ip/address.hpp>
+
 #include <vsomeip/primitive_types.hpp>
 
 namespace vsomeip {
 
-class endpoint;
+class event;
 
 class eventgroupinfo {
 public:
-	eventgroupinfo(major_version_t _major, ttl_t _ttl);
+	eventgroupinfo();
 	~eventgroupinfo();
 
-	servicegroup * get_group() const;
-	void set_group(servicegroup *_group);
-
 	major_version_t get_major() const;
+	void set_major(major_version_t _major);
 
 	ttl_t get_ttl() const;
 	void set_ttl(ttl_t _ttl);
 
-	std::shared_ptr<endpoint> & get_multicast();
-	void set_multicast(std::shared_ptr<endpoint> &_multicast);
+	bool get_multicast(boost::asio::ip::address &_address, uint16_t &_port);
+	void set_multicast(const boost::asio::ip::address &_address, uint16_t _port);
 
-	void add_client(client_t _client);
-	void remove_client(client_t _client);
+	const std::set<std::shared_ptr<event> > get_events() const;
+	void add_event(std::shared_ptr<event> _event);
 
 private:
 	major_version_t major_;
 	ttl_t ttl_;
 
-	std::shared_ptr<endpoint> multicast_;
-	std::set< client_t > subscribed_;
+	bool is_multicast_;
+	boost::asio::ip::address address_;
+	uint16_t port_;
+
+	std::set<std::shared_ptr<event> > events_;
 };
 
 } // namespace vsomeip
diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp
index 6d5e7fc..ac41eec 100644
--- a/implementation/routing/include/routing_manager_impl.hpp
+++ b/implementation/routing/include/routing_manager_impl.hpp
@@ -36,166 +36,185 @@
 
 class service_discovery;
 
-} // namespace sd
+}  // namespace sd
 
-class routing_manager_impl: public routing_manager,
-		public endpoint_host,
-		public sd::service_discovery_host,
-		public std::enable_shared_from_this<routing_manager_impl> {
-public:
-	routing_manager_impl(routing_manager_host *_host);
-	~routing_manager_impl();
+class routing_manager_impl : public routing_manager, public endpoint_host,
+    public sd::service_discovery_host, public std::enable_shared_from_this<
+        routing_manager_impl> {
+ public:
+  routing_manager_impl(routing_manager_host *_host);
+  ~routing_manager_impl();
 
-	boost::asio::io_service & get_io();
-	std::shared_ptr<configuration> get_configuration() const;
+  boost::asio::io_service & get_io();
+  std::shared_ptr<configuration> get_configuration() const;
 
-	void init();
-	void start();
-	void stop();
+  void init();
+  void start();
+  void stop();
 
-	void offer_service(client_t _client, service_t _service,
-			instance_t _instance, major_version_t _major,
-			minor_version_t _minor, ttl_t _ttl);
+  void offer_service(client_t _client, service_t _service, instance_t _instance,
+                     major_version_t _major, minor_version_t _minor,
+                     ttl_t _ttl);
 
-	void stop_offer_service(client_t _client, service_t _service,
-			instance_t _instance);
+  void stop_offer_service(client_t _client, service_t _service,
+                          instance_t _instance);
 
-	void publish_eventgroup(client_t _client, service_t _service,
-			instance_t _instance, eventgroup_t _eventgroup,
-			major_version_t _major, ttl_t _ttl);
+  void publish_eventgroup(client_t _client, service_t _service,
+                          instance_t _instance, eventgroup_t _eventgroup,
+                          major_version_t _major, ttl_t _ttl);
 
-	void stop_publish_eventgroup(client_t _client, service_t _service,
-			instance_t _instance, eventgroup_t _eventgroup);
+  void stop_publish_eventgroup(client_t _client, service_t _service,
+                               instance_t _instance, eventgroup_t _eventgroup);
 
-	void request_service(client_t _client, service_t _service,
-			instance_t _instance, major_version_t _major,
-			minor_version_t _minor, ttl_t _ttl);
+  void request_service(client_t _client, service_t _service,
+                       instance_t _instance, major_version_t _major,
+                       minor_version_t _minor, ttl_t _ttl);
 
-	void release_service(client_t _client, service_t _service,
-			instance_t _instance);
+  void release_service(client_t _client, service_t _service,
+                       instance_t _instance);
 
-	void subscribe(client_t _client, service_t _service, instance_t _instance,
-			eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl);
+  void subscribe(client_t _client, service_t _service, instance_t _instance,
+                 eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl);
 
-	void unsubscribe(client_t _client, service_t _service, instance_t _instance,
-			eventgroup_t _eventgroup);
+  void unsubscribe(client_t _client, service_t _service, instance_t _instance,
+                   eventgroup_t _eventgroup);
 
-	bool send(client_t _client, std::shared_ptr<message> _message, bool _flush,
-			bool _reliable);
+  bool send(client_t _client, std::shared_ptr<message> _message, bool _flush,
+            bool _reliable);
 
-	bool send(client_t _client, const byte_t *_data, uint32_t _size,
-			instance_t _instance, bool _flush, bool _reliable);
+  bool send(client_t _client, const byte_t *_data, uint32_t _size,
+            instance_t _instance, bool _flush, bool _reliable);
 
-	void set(client_t _client, service_t _service, instance_t _instance,
-			event_t _event, const std::shared_ptr<payload> &_value);
+  void set(client_t _client, service_t _service, instance_t _instance,
+           event_t _event, const std::shared_ptr<payload> &_payload);
 
-	bool is_available(service_t _service, instance_t _instance) const;
+  bool is_available(service_t _service, instance_t _instance) const;
 
-	// interface to stub
-	std::shared_ptr<endpoint> create_local(client_t _client);
-	std::shared_ptr<endpoint> find_local(client_t _client);
-	std::shared_ptr<endpoint> find_or_create_local(client_t _client);
-	void remove_local(client_t _client);
-	std::shared_ptr<endpoint> find_local(service_t _service, instance_t _instance);
+  // interface to stub
+  std::shared_ptr<endpoint> create_local(client_t _client);
+  std::shared_ptr<endpoint> find_local(client_t _client);
+  std::shared_ptr<endpoint> find_or_create_local(client_t _client);
+  void remove_local(client_t _client);
+  std::shared_ptr<endpoint> find_local(service_t _service,
+                                       instance_t _instance);
 
-	// interface "endpoint_host"
-	void on_connect(std::shared_ptr<endpoint> _endpoint);
-	void on_disconnect(std::shared_ptr<endpoint> _endpoint);
-	void on_message(const byte_t *_data, length_t _length, endpoint *_receiver);
+  // interface "endpoint_host"
+  std::shared_ptr<endpoint> find_remote_client(service_t _service,
+                                               instance_t _instance,
+                                               bool _reliable);
+  void on_connect(std::shared_ptr<endpoint> _endpoint);
+  void on_disconnect(std::shared_ptr<endpoint> _endpoint);
+  void on_message(const byte_t *_data, length_t _length, endpoint *_receiver);
 
-	// interface "service_discovery_host"
-	typedef std::map<std::string,
-					 std::shared_ptr<servicegroup> > servicegroups_t;
-	const servicegroups_t  & get_servicegroups() const;
-	service_map_t get_offered_services(const std::string &_name) const;
-	void create_service_discovery_endpoint(const std::string &_address,
-			uint16_t _port, const std::string &_protocol);
+  // interface "service_discovery_host"
+  typedef std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_t;
+  const servicegroups_t & get_servicegroups() const;
+  std::shared_ptr<eventgroupinfo> find_eventgroup(
+      service_t _service, instance_t _instance, eventgroup_t _eventgroup) const;
+  services_t get_offered_services(const std::string &_name) const;
+  void create_service_discovery_endpoint(const std::string &_address,
+                                         uint16_t _port, bool _reliable);
+  bool send_subscribe(const boost::asio::ip::address &_address, uint16_t _port,
+                      bool _reliable, const byte_t *_data, uint32_t _size);
+  void init_routing_info();
+  void add_routing_info(service_t _service, instance_t _instance,
+                        major_version_t _major, minor_version_t _minor,
+                        ttl_t _ttl, const boost::asio::ip::address &_address,
+                        uint16_t _port, bool _reliable);
+  void del_routing_info(service_t _service, instance_t _instance,
+                        bool _reliable);
 
-private:
-	bool deliver_message(const byte_t *_data, length_t _length,
-			instance_t _instance);
+  void init_event_routing_info();
+  void add_subscription(service_t _service, instance_t _instance,
+                        eventgroup_t _eventgroup,
+                        const boost::asio::ip::address &_address,
+                        uint16_t _reliable_port, uint16_t _unreliable_port);
+  void del_subscription(service_t _service, instance_t _instance,
+                        eventgroup_t _eventgroup,
+                        const boost::asio::ip::address &_address,
+                        uint16_t _reliable_port, uint16_t _unreliable_port);
 
-	client_t find_local_client(service_t _service, instance_t _instance);
-	instance_t find_instance(service_t _service, endpoint *_endpoint);
+ private:
+  bool deliver_message(const byte_t *_data, length_t _length,
+                       instance_t _instance);
 
-	std::shared_ptr<serviceinfo> find_service(service_t _service,
-			instance_t _instance);
-	std::shared_ptr<serviceinfo> create_service(service_t _service,
-			instance_t _instance, major_version_t _major,
-			minor_version_t _minor, ttl_t _ttl);
+  client_t find_local_client(service_t _service, instance_t _instance);
+  instance_t find_instance(service_t _service, endpoint *_endpoint);
 
-	std::shared_ptr<endpoint> find_remote_client(service_t _service,
-			instance_t _instance, bool _reliable);
+  std::shared_ptr<serviceinfo> find_service(service_t _service,
+                                            instance_t _instance) const;
+  std::shared_ptr<serviceinfo> create_service(service_t _service,
+                                              instance_t _instance,
+                                              major_version_t _major,
+                                              minor_version_t _minor,
+                                              ttl_t _ttl);
 
-	std::shared_ptr<endpoint> create_client_endpoint(
-			const boost::asio::ip::address &_address, uint16_t _port,
-			bool _reliable);
-	std::shared_ptr<endpoint> find_client_endpoint(
-			const boost::asio::ip::address &_address, uint16_t _port,
-			bool _reliable);
-	std::shared_ptr<endpoint> find_or_create_client_endpoint(
-			const boost::asio::ip::address &_address, uint16_t _port,
-			bool _reliable);
+  std::shared_ptr<endpoint> create_client_endpoint(
+      const boost::asio::ip::address &_address, uint16_t _port, bool _reliable);
+  std::shared_ptr<endpoint> find_client_endpoint(
+      const boost::asio::ip::address &_address, uint16_t _port, bool _reliable);
+  std::shared_ptr<endpoint> find_or_create_client_endpoint(
+      const boost::asio::ip::address &_address, uint16_t _port, bool _reliable);
 
-	std::shared_ptr<endpoint> create_server_endpoint(uint16_t _port,
-			bool _reliable);
-	std::shared_ptr<endpoint> find_server_endpoint(uint16_t _port,
-			bool _reliable);
-	std::shared_ptr<endpoint> find_or_create_server_endpoint(uint16_t _port,
-			bool _reliable);
+  std::shared_ptr<endpoint> create_server_endpoint(uint16_t _port,
+                                                   bool _reliable);
+  std::shared_ptr<endpoint> find_server_endpoint(uint16_t _port,
+                                                 bool _reliable);
+  std::shared_ptr<endpoint> find_or_create_server_endpoint(uint16_t _port,
+                                                           bool _reliable);
 
-	void init_routing_info();
-	void add_routing_info(service_t _service, instance_t _instance,
-			major_version_t _major, minor_version_t _minor, ttl_t _ttl,
-			const boost::asio::ip::address &_address, uint16_t _port,
-			bool _reliable);
-	void del_routing_info(service_t _service, instance_t _instance,
-			bool _reliable);
+  std::set<std::shared_ptr<event> > find_events(service_t _service,
+                                                instance_t _instance,
+                                                eventgroup_t _eventgroup);
+  std::shared_ptr<event> find_event(service_t _service, instance_t _instance,
+                                    event_t _event) const;
 
-private:
-	boost::asio::io_service &io_;
-	routing_manager_host *host_;
+ private:
+  boost::asio::io_service &io_;
+  routing_manager_host *host_;
 
-	std::shared_ptr<configuration> configuration_;
+  std::shared_ptr<configuration> configuration_;
 
-	std::shared_ptr<deserializer> deserializer_;
-	std::shared_ptr<serializer> serializer_;
+  std::shared_ptr<deserializer> deserializer_;
+  std::shared_ptr<serializer> serializer_;
 
-	std::shared_ptr<routing_manager_stub> stub_;
-	std::shared_ptr<sd::service_discovery> discovery_;
+  std::shared_ptr<routing_manager_stub> stub_;
+  std::shared_ptr<sd::service_discovery> discovery_;
 
-	// Routing info
+  // Routing info
 
-	// Local
-	std::map<client_t, std::shared_ptr<endpoint> > local_clients_;
-	std::map<service_t, std::map<instance_t, client_t> > local_services_;
+  // Local
+  std::map<client_t, std::shared_ptr<endpoint> > local_clients_;
+  std::map<service_t, std::map<instance_t, client_t> > local_services_;
 
-	// Server endpoints for local services
-	std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > server_endpoints_;
-	std::map<service_t, std::map<endpoint *, instance_t> > service_instances_;
+  // Server endpoints for local services
+  std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > server_endpoints_;
+  std::map<service_t, std::map<endpoint *, instance_t> > service_instances_;
 
-	// Client endpoints for remote services
-	std::map<boost::asio::ip::address,
-			std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > > client_endpoints_;
-	std::map<service_t,
-			std::map<instance_t, std::map<bool, std::shared_ptr<endpoint> > > > remote_services_;
+  // Client endpoints for remote services
+  std::map<boost::asio::ip::address,
+      std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > > client_endpoints_;
+  std::map<service_t,
+      std::map<instance_t, std::map<bool, std::shared_ptr<endpoint> > > > remote_services_;
 
-	// Servicegroups
-	std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_;
-	std::map<service_t, std::map<instance_t, std::shared_ptr<serviceinfo> > > services_;
+  // Servicegroups
+  std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_;
+  std::map<service_t, std::map<instance_t, std::shared_ptr<serviceinfo> > > services_;
 
-	// Eventgroups
-	std::map<service_t,
-			std::map<instance_t,
-					std::map<eventgroup_t, std::set<std::shared_ptr<endpoint> > > > > eventgroups_;
-	std::map<service_t, std::map<instance_t, std::map<event_t, eventgroup_t> > > events_;
-	std::map<eventgroup_t, std::set<client_t> > eventgroup_clients_;
+  // Eventgroups
+  std::map<service_t,
+      std::map<instance_t,
+          std::map<eventgroup_t, std::shared_ptr<eventgroupinfo> > > > eventgroups_;
+  std::map<service_t,
+      std::map<instance_t, std::map<event_t, std::shared_ptr<event> > > > events_;
 
-	// Mutexes
-	std::recursive_mutex endpoint_mutex_;
-	std::mutex serialize_mutex_;
+  std::map<eventgroup_t, std::set<client_t> > eventgroup_clients_;
+
+  // Mutexes
+  std::recursive_mutex endpoint_mutex_;
+  std::mutex serialize_mutex_;
 };
 
-} // namespace vsomeip
+}  // namespace vsomeip
 
 #endif // VSOMEIP_ROUTING_MANAGER_IMPL_HPP
diff --git a/implementation/routing/include/servicegroup.hpp b/implementation/routing/include/servicegroup.hpp
index 0ea997b..a59be62 100644
--- a/implementation/routing/include/servicegroup.hpp
+++ b/implementation/routing/include/servicegroup.hpp
@@ -11,7 +11,7 @@
 #include <set>
 #include <string>
 
-#include "routing_types.hpp"
+#include "types.hpp"
 
 namespace vsomeip {
 
@@ -27,11 +27,11 @@
 	bool add_service(service_t _service, instance_t _instance, std::shared_ptr< serviceinfo > _info);
 	bool remove_service(service_t _service, instance_t _instance);
 
-	service_map_t get_services() const;
+	services_t get_services() const;
 
 private:
 	std::string name_;
-	service_map_t services_;
+	services_t services_;
 };
 
 } // namespace vsomeip
diff --git a/implementation/routing/include/serviceinfo.hpp b/implementation/routing/include/serviceinfo.hpp
index b38df5a..09b5486 100644
--- a/implementation/routing/include/serviceinfo.hpp
+++ b/implementation/routing/include/serviceinfo.hpp
@@ -9,6 +9,7 @@
 
 #include <memory>
 #include <set>
+#include <string>
 
 #include <vsomeip/primitive_types.hpp>
 
@@ -19,37 +20,50 @@
 
 class serviceinfo {
 public:
-	serviceinfo(major_version_t _major, minor_version_t _minor, ttl_t _ttl);
-	~serviceinfo();
+  serviceinfo(major_version_t _major, minor_version_t _minor, ttl_t _ttl);
+  ~serviceinfo();
 
-	servicegroup * get_group() const;
-	void set_group(servicegroup *_group);
+  servicegroup * get_group() const;
+  void set_group(servicegroup *_group);
 
-	major_version_t get_major() const;
-	minor_version_t get_minor() const;
+  major_version_t get_major() const;
+  minor_version_t get_minor() const;
 
-	ttl_t get_ttl() const;
-	void set_ttl(ttl_t _ttl);
+  ttl_t get_ttl() const;
+  void set_ttl(ttl_t _ttl);
 
-	std::shared_ptr< endpoint > & get_endpoint(bool _reliable);
-	void set_endpoint(std::shared_ptr< endpoint > &_endpoint, bool _reliable);
+  std::shared_ptr<endpoint> get_endpoint(bool _reliable) const;
+  void set_endpoint(std::shared_ptr<endpoint> _endpoint, bool _reliable);
 
-	void add_client(client_t _client);
-	void remove_client(client_t _client);
+  const std::string & get_multicast_address() const;
+  void set_multicast_address(const std::string &_multicast);
+
+  uint16_t get_multicast_port() const;
+  void set_multicast_port(uint16_t _port);
+
+  eventgroup_t get_multicast_group() const;
+  void set_multicast_group(eventgroup_t _multicast_group);
+
+  void add_client(client_t _client);
+  void remove_client(client_t _client);
 
 private:
-	servicegroup *group_;
+  servicegroup *group_;
 
-	major_version_t major_;
-	minor_version_t minor_;
-	ttl_t ttl_;
+  major_version_t major_;
+  minor_version_t minor_;
+  ttl_t ttl_;
 
-	std::shared_ptr< endpoint > reliable_;
-	std::shared_ptr< endpoint > unreliable_;
+  std::shared_ptr<endpoint> reliable_;
+  std::shared_ptr<endpoint> unreliable_;
 
-	std::set< client_t > requesters_;
+  std::string multicast_address_;
+  uint16_t multicast_port_;
+  eventgroup_t multicast_group_;
+
+  std::set<client_t> requesters_;
 };
 
-} // namespace vsomeip
+}  // namespace vsomeip
 
 #endif // VSOMEIP_SERVICEINFO_HPP
diff --git a/implementation/routing/include/routing_types.hpp b/implementation/routing/include/types.hpp
similarity index 85%
rename from implementation/routing/include/routing_types.hpp
rename to implementation/routing/include/types.hpp
index 67f0886..ad28c01 100644
--- a/implementation/routing/include/routing_types.hpp
+++ b/implementation/routing/include/types.hpp
@@ -18,14 +18,14 @@
 
 typedef std::map<service_t,
 		    std::map<instance_t,
-		    	std::shared_ptr<serviceinfo> > > service_map_t;
+		    	std::shared_ptr<serviceinfo> > > services_t;
 
 class eventgroupinfo;
 
 typedef std::map<service_t,
 			std::map<instance_t,
 				std::map<eventgroup_t,
-					std::shared_ptr<eventgroupinfo> > > > eventgroup_map_t;
+					std::shared_ptr<eventgroupinfo> > > > eventgroups_t;
 
 }
 // namespace vsomeip
diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp
new file mode 100644
index 0000000..ebfc5fd
--- /dev/null
+++ b/implementation/routing/src/event.cpp
@@ -0,0 +1,105 @@
+// Copyright (C) 2014 BMW Group
+// Author: Lutz Bichler (lutz.bichler@bmw.de)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iomanip>
+
+#include <vsomeip/defines.hpp>
+#include <vsomeip/logger.hpp>
+#include <vsomeip/message.hpp>
+#include <vsomeip/runtime.hpp>
+
+#include "../include/event.hpp"
+#include "../include/routing_manager.hpp"
+#include "../../configuration/include/internal.hpp"
+
+namespace vsomeip {
+
+event::event(routing_manager *_routing)
+    : routing_(_routing),
+      message_(runtime::get()->create_notification()),
+      cycle_timer_(_routing->get_io()),
+      is_updating_on_change_(true) {
+}
+
+service_t event::get_service() const {
+  return message_->get_service();
+}
+
+void event::set_service(service_t _service) {
+  message_->set_service(_service);
+}
+
+instance_t event::get_instance() const {
+  return message_->get_instance();
+}
+
+void event::set_instance(instance_t _instance) {
+  message_->set_instance(_instance);
+}
+
+event_t event::get_event() const {
+  return message_->get_method();
+}
+
+void event::set_event(event_t _event) {
+  message_->set_method(_event);  // TODO: maybe we should check for the leading 0-bit
+}
+
+bool event::is_field() const {
+  return is_field_;
+}
+
+void event::set_field(bool _is_field) {
+  is_field_ = _is_field;
+}
+
+std::shared_ptr<payload> event::get_payload() const {
+  return message_->get_payload();
+}
+
+void event::set_payload(std::shared_ptr<payload> _payload) {
+  bool is_change = _payload != message_->get_payload();
+  if (true) {
+    message_->set_payload(_payload);
+    if (is_updating_on_change_) {
+      notify();
+    }
+  }
+}
+
+void event::set_update_on_change(bool _is_active) {
+  is_updating_on_change_ = _is_active;
+}
+
+void event::set_update_cycle(std::chrono::milliseconds &_cycle) {
+  cycle_ = _cycle;
+  cycle_timer_.cancel();
+
+  if (std::chrono::milliseconds::zero() != _cycle) {
+    cycle_timer_.expires_from_now(cycle_);
+    std::function<void(boost::system::error_code const &)> its_handler =
+        std::bind(&event::update_cbk, shared_from_this(),
+                  std::placeholders::_1);
+    cycle_timer_.async_wait(its_handler);
+  }
+}
+
+void event::update_cbk(boost::system::error_code const &_error) {
+  if (!_error) {
+    cycle_timer_.expires_from_now(cycle_);
+    notify();
+    std::function<void(boost::system::error_code const &)> its_handler =
+        std::bind(&event::update_cbk, shared_from_this(),
+                  std::placeholders::_1);
+    cycle_timer_.async_wait(its_handler);
+  }
+}
+
+void event::notify() {
+  routing_->send(VSOMEIP_ROUTING_CLIENT, message_, true, true);
+}
+
+}  // namespace vsomeip
diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp
new file mode 100644
index 0000000..bb9de5a
--- /dev/null
+++ b/implementation/routing/src/eventgroupinfo.cpp
@@ -0,0 +1,60 @@
+// Copyright (C) 2014 BMW Group
+// Author: Lutz Bichler (lutz.bichler@bmw.de)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/constants.hpp>
+
+#include "../include/eventgroupinfo.hpp"
+
+namespace vsomeip {
+
+eventgroupinfo::eventgroupinfo()
+    : major_(DEFAULT_MAJOR),
+      ttl_(DEFAULT_TTL),
+      is_multicast_(false) {
+}
+
+eventgroupinfo::~eventgroupinfo() {
+}
+
+major_version_t eventgroupinfo::get_major() const {
+  return major_;
+}
+
+void eventgroupinfo::set_major(major_version_t _major) {
+  major_ = _major;
+}
+
+ttl_t eventgroupinfo::get_ttl() const {
+  return ttl_;
+}
+
+void eventgroupinfo::set_ttl(ttl_t _ttl) {
+  ttl_ = _ttl;
+}
+
+bool eventgroupinfo::get_multicast(boost::asio::ip::address &_address, uint16_t &_port) {
+  if (is_multicast_) {
+    _address = address_;
+    _port = port_;
+  }
+  return is_multicast_;
+}
+
+void eventgroupinfo::set_multicast(const boost::asio::ip::address &_address, uint16_t _port) {
+  address_ = _address;
+  port_ = _port;
+  is_multicast_ = true;
+}
+
+const std::set<std::shared_ptr<event> > eventgroupinfo::get_events() const {
+  return events_;
+}
+
+void eventgroupinfo::add_event(std::shared_ptr<event> _event) {
+  events_.insert(_event);
+}
+
+}  // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index 0ae230b..f9263a7 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -13,6 +13,8 @@
 #include <vsomeip/logger.hpp>
 #include <vsomeip/message.hpp>
 
+#include "../include/event.hpp"
+#include "../include/eventgroupinfo.hpp"
 #include "../include/routing_manager_host.hpp"
 #include "../include/routing_manager_impl.hpp"
 #include "../include/routing_manager_stub.hpp"
@@ -24,810 +26,979 @@
 #include "../../endpoints/include/tcp_server_endpoint_impl.hpp"
 #include "../../endpoints/include/udp_client_endpoint_impl.hpp"
 #include "../../endpoints/include/udp_server_endpoint_impl.hpp"
-#include "../../message/include/byteorder.hpp"
 #include "../../message/include/deserializer.hpp"
-#include "../../message/include/event_impl.hpp"
 #include "../../message/include/serializer.hpp"
 #include "../../service_discovery/include/defines.hpp"
 #include "../../service_discovery/include/runtime.hpp"
 #include "../../service_discovery/include/service_discovery_impl.hpp"
+#include "../../utility/include/byteorder.hpp"
 #include "../../utility/include/utility.hpp"
 
 namespace vsomeip {
 
-routing_manager_impl::routing_manager_impl(routing_manager_host *_host) :
-		host_(_host), io_(_host->get_io()), deserializer_(
-				std::make_shared<deserializer>()), serializer_(
-				std::make_shared<serializer>()), configuration_(
-				host_->get_configuration()) {
+routing_manager_impl::routing_manager_impl(routing_manager_host *_host)
+    : host_(_host),
+      io_(_host->get_io()),
+      deserializer_(std::make_shared<deserializer>()),
+      serializer_(std::make_shared<serializer>()),
+      configuration_(host_->get_configuration()) {
 }
 
 routing_manager_impl::~routing_manager_impl() {
 }
 
 boost::asio::io_service & routing_manager_impl::get_io() {
-	return io_;
+  return io_;
 }
 
 void routing_manager_impl::init() {
-	uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE;
-	if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size)
-		its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE;
-	if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size)
-		its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE;
+  uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE;
+  if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size)
+    its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE;
+  if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size)
+    its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE;
 
-	serializer_->create_data(its_max_message_size);
+  serializer_->create_data(its_max_message_size);
 
-	// TODO: Only instantiate the stub if needed
-	stub_ = std::make_shared < routing_manager_stub > (this);
-	stub_->init();
+  // TODO: Only instantiate the stub if needed
+  stub_ = std::make_shared < routing_manager_stub > (this);
+  stub_->init();
 
-	if (configuration_->is_service_discovery_enabled()) {
-		VSOMEIP_INFO << "Service Discovery enabled.";
-		sd::runtime **its_runtime =
-				static_cast<sd::runtime **>(utility::load_library(
-				VSOMEIP_SD_LIBRARY,
-				VSOMEIP_SD_RUNTIME_SYMBOL_STRING));
+  if (configuration_->is_service_discovery_enabled()) {
+    VSOMEIP_INFO << "Service Discovery enabled.";
+    sd::runtime **its_runtime =
+        static_cast<sd::runtime **>(utility::load_library(
+            VSOMEIP_SD_LIBRARY,
+            VSOMEIP_SD_RUNTIME_SYMBOL_STRING));
 
-		if (0 != its_runtime && 0 != (*its_runtime)) {
-			VSOMEIP_INFO << "Service Discovery module loaded.";
-			discovery_ = (*its_runtime)->create_service_discovery(this);
-			discovery_->init();
-		}
-	} else {
-		init_routing_info();
-	}
+    if (0 != its_runtime && 0 != (*its_runtime)) {
+      VSOMEIP_INFO << "Service Discovery module loaded.";
+      discovery_ = (*its_runtime)->create_service_discovery(this);
+      discovery_->init();
+    }
+
+    init_event_routing_info();
+  } else {
+    init_routing_info();
+  }
 }
 
 void routing_manager_impl::start() {
-	stub_->start();
-	if (discovery_)
-		discovery_->start();
+  stub_->start();
+  if (discovery_)
+    discovery_->start();
 
-	host_->on_event(event_type_e::REGISTERED);
+  host_->on_event(event_type_e::REGISTERED);
 }
 
 void routing_manager_impl::stop() {
-	host_->on_event(event_type_e::DEREGISTERED);
+  host_->on_event(event_type_e::DEREGISTERED);
 
-	if (discovery_)
-		discovery_->stop();
-	stub_->stop();
+  if (discovery_)
+    discovery_->stop();
+  stub_->stop();
 }
 
 void routing_manager_impl::offer_service(client_t _client, service_t _service,
-		instance_t _instance, major_version_t _major, minor_version_t _minor,
-		ttl_t _ttl) {
-	local_services_[_service][_instance] = _client;
+                                         instance_t _instance,
+                                         major_version_t _major,
+                                         minor_version_t _minor, ttl_t _ttl) {
+  local_services_[_service][_instance] = _client;
 
-	// Remote route (incoming only)
-	std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
-	if (its_info) {
-		if (its_info->get_major() == _major
-				&& its_info->get_minor() == _minor) {
-			VSOMEIP_DEBUG << "Setting TTL=" << std::dec << _ttl;
-			its_info->set_ttl(_ttl);
-		} else {
-			host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH);
-		}
-	} else {
-		(void) create_service(_service, _instance, _major, _minor, _ttl);
-	}
+  // Remote route (incoming only)
+  std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
+  if (its_info) {
+    if (its_info->get_major() == _major && its_info->get_minor() == _minor) {
+      its_info->set_ttl(_ttl);
+    } else {
+      host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH);
+    }
+  } else {
+    VSOMEIP_INFO << "CREATING SERVICE [" << std::hex << _service << "."
+        << _instance << "]";
+    (void) create_service(_service, _instance, _major, _minor, _ttl);
+  }
 
-	host_->on_availability(_service, _instance, true);
+  host_->on_availability(_service, _instance, true);
 }
 
 void routing_manager_impl::stop_offer_service(client_t its_client,
-		service_t _service, instance_t _instance) {
-	if (discovery_) {
-		auto found_service = services_.find(_service);
-		if (found_service != services_.end()) {
-			auto found_instance = found_service->second.find(_instance);
-			if (found_instance != found_service->second.end()) {
-				found_instance->second->set_ttl(0);
-			}
-		}
-	} else {
-		// TODO: allow to withdraw a service on one endpoint only
-		del_routing_info(_service, _instance, false);
-		del_routing_info(_service, _instance, true);
-	}
+                                              service_t _service,
+                                              instance_t _instance) {
+  if (discovery_) {
+    auto found_service = services_.find(_service);
+    if (found_service != services_.end()) {
+      auto found_instance = found_service->second.find(_instance);
+      if (found_instance != found_service->second.end()) {
+        found_instance->second->set_ttl(0);
+      }
+    }
+  } else {
+    // TODO: allow to withdraw a service on one endpoint only
+    del_routing_info(_service, _instance, false);
+    del_routing_info(_service, _instance, true);
+  }
 }
 
 void routing_manager_impl::publish_eventgroup(client_t its_client,
-		service_t _service, instance_t _instance, eventgroup_t _eventgroup,
-		major_version_t _major, ttl_t _ttl) {
+                                              service_t _service,
+                                              instance_t _instance,
+                                              eventgroup_t _eventgroup,
+                                              major_version_t _major,
+                                              ttl_t _ttl) {
 }
 
 void routing_manager_impl::stop_publish_eventgroup(client_t its_client,
-		service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+                                                   service_t _service,
+                                                   instance_t _instance,
+                                                   eventgroup_t _eventgroup) {
 
 }
 
 void routing_manager_impl::request_service(client_t _client, service_t _service,
-		instance_t _instance, major_version_t _major, minor_version_t _minor,
-		ttl_t _ttl) {
+                                           instance_t _instance,
+                                           major_version_t _major,
+                                           minor_version_t _minor, ttl_t _ttl) {
 
-	std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
-	if (its_info) {
-		if ((_major > its_info->get_major())
-				|| (_major == its_info->get_major()
-						&& _minor > its_info->get_minor())
-				|| (_ttl > its_info->get_ttl())) {
-			host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH);
-		} else {
-			its_info->add_client(_client);
-		}
-	} else {
-		if (discovery_)
-			discovery_->request_service(_service, _instance, _major, _minor,
-					_ttl);
-	}
+  std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
+  if (its_info) {
+    if ((_major > its_info->get_major())
+        || (_major == its_info->get_major() && _minor > its_info->get_minor())
+        || (_ttl > its_info->get_ttl())) {
+      host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH);
+    } else {
+      its_info->add_client(_client);
+    }
+  } else {
+    if (discovery_)
+      discovery_->request_service(_service, _instance, _major, _minor, _ttl);
+  }
 }
 
 void routing_manager_impl::release_service(client_t _client, service_t _service,
-		instance_t _instance) {
-	std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
-	if (its_info) {
-		its_info->remove_client(_client);
-	} else {
-		if (discovery_)
-			discovery_->release_service(_service, _instance);
-	}
+                                           instance_t _instance) {
+  std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
+  if (its_info) {
+    its_info->remove_client(_client);
+  } else {
+    if (discovery_)
+      discovery_->release_service(_service, _instance);
+  }
 }
 
 void routing_manager_impl::subscribe(client_t _client, service_t _service,
-		instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl) {
-	if (discovery_) {
-		eventgroup_clients_[_eventgroup].insert(_client);
-		discovery_->subscribe(_service, _instance, _eventgroup, _major, _ttl);
-	} else {
-		VSOMEIP_ERROR << "SOME/IP eventgroups require SD to be enabled!";
-	}
+                                     instance_t _instance,
+                                     eventgroup_t _eventgroup,
+                                     major_version_t _major, ttl_t _ttl) {
+  if (discovery_) {
+    eventgroup_clients_[_eventgroup].insert(_client);
+    discovery_->subscribe(_service, _instance, _eventgroup, _major, _ttl);
+  } else {
+    VSOMEIP_ERROR << "SOME/IP eventgroups require SD to be enabled!";
+  }
 }
 
 void routing_manager_impl::unsubscribe(client_t _client, service_t _service,
-		instance_t _instance, eventgroup_t _eventgroup) {
-	if (discovery_) {
-		auto found_eventgroup = eventgroup_clients_.find(_eventgroup);
-		if (found_eventgroup != eventgroup_clients_.end()) {
-			found_eventgroup->second.erase(_client);
-			if (0 == found_eventgroup->second.size()) {
-				eventgroup_clients_.erase(_eventgroup);
-			}
-		}
-		discovery_->unsubscribe(_service, _instance, _eventgroup);
-	} else {
-		VSOMEIP_ERROR << "SOME/IP eventgroups require SD to be enabled!";
-	}
+                                       instance_t _instance,
+                                       eventgroup_t _eventgroup) {
+  if (discovery_) {
+    auto found_eventgroup = eventgroup_clients_.find(_eventgroup);
+    if (found_eventgroup != eventgroup_clients_.end()) {
+      found_eventgroup->second.erase(_client);
+      if (0 == found_eventgroup->second.size()) {
+        eventgroup_clients_.erase(_eventgroup);
+      }
+    }
+    discovery_->unsubscribe(_service, _instance, _eventgroup);
+  } else {
+    VSOMEIP_ERROR << "SOME/IP eventgroups require SD to be enabled!";
+  }
 }
 
 bool routing_manager_impl::send(client_t its_client,
-		std::shared_ptr<message> _message, bool _reliable, bool _flush) {
-	bool is_sent(false);
-	std::unique_lock < std::mutex > its_lock(serialize_mutex_);
+                                std::shared_ptr<message> _message,
+                                bool _reliable, bool _flush) {
+  bool is_sent(false);
+  std::unique_lock < std::mutex > its_lock(serialize_mutex_);
 
-	if (utility::is_request(_message->get_message_type())) {
-		_message->set_client(its_client);
-	}
+  if (utility::is_request(_message->get_message_type())) {
+    _message->set_client(its_client);
+  }
 
-	if (serializer_->serialize(_message.get())) {
-		is_sent = send(its_client, serializer_->get_data(),
-				serializer_->get_size(), _message->get_instance(), _reliable,
-				_flush);
-		serializer_->reset();
-	}
-	return is_sent;
+  if (serializer_->serialize(_message.get())) {
+    is_sent = send(its_client, serializer_->get_data(), serializer_->get_size(),
+                   _message->get_instance(), _reliable, _flush);
+    serializer_->reset();
+  }
+  return is_sent;
 }
 
 bool routing_manager_impl::send(client_t _client, const byte_t *_data,
-		length_t _size, instance_t _instance, bool _flush, bool _reliable) {
-	bool is_sent(false);
+                                length_t _size, instance_t _instance,
+                                bool _flush, bool _reliable) {
+  bool is_sent(false);
 
-	std::shared_ptr<endpoint> its_target;
-	bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]);
+  std::shared_ptr<endpoint> its_target;
+  bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]);
+  bool is_notification = utility::is_notification(_data);
 
-	client_t its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
-			_data[VSOMEIP_CLIENT_POS_MAX]);
-	service_t its_service = VSOMEIP_BYTES_TO_WORD(
-			_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+  client_t its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
+                                              _data[VSOMEIP_CLIENT_POS_MAX]);
+  service_t its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN],
+                                                _data[VSOMEIP_SERVICE_POS_MAX]);
 
-	if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
-		if (is_request) {
-			its_target = find_local(its_service, _instance);
-		} else {
-			its_target = find_local(its_client);
-		}
+  if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
+    if (is_request) {
+      its_target = find_local(its_service, _instance);
+    } else {
+      its_target = find_local(its_client);
+    }
 
-		if (its_target) {
-			std::vector<byte_t> its_command(
-					VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t)
-							+ sizeof(bool) + sizeof(bool));
-			its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SEND;
-			std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
-					sizeof(client_t));
-			std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size,
-					sizeof(_size));
-			std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], _data,
-					_size);
-			std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size],
-					&_instance, sizeof(instance_t));
-			std::memcpy(
-					&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size
-							+ sizeof(instance_t)], &_reliable, sizeof(bool));
-			std::memcpy(
-					&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size
-							+ sizeof(instance_t) + sizeof(bool)], &_flush,
-					sizeof(bool));
-			is_sent = its_target->send(&its_command[0], its_command.size(),
-					_flush);
-		} else {
-			// Check whether hosting application should get the message
-			// If not, check routes to external
-			if ((its_client == host_->get_client() && !is_request)
-					|| (find_local_client(its_service, _instance)
-							== host_->get_client() && is_request)) {
-				// TODO: find out how to handle session id here
-				is_sent = deliver_message(_data, _size, _instance);
-			} else {
-				if (is_request) {
-					its_target = find_remote_client(its_service, _instance,
-							_reliable);
-					if (its_target) {
-						is_sent = its_target->send(_data, _size, _flush);
-					} else {
-						VSOMEIP_ERROR
-								<< "Routing error. Client from remote service could not be found!";
-					}
-				} else {
-					std::shared_ptr<serviceinfo> its_info(
-							find_service(its_service, _instance));
-					if (its_info) {
-						its_target = its_info->get_endpoint(_reliable);
-						if (its_target) {
-							is_sent = its_target->send(_data, _size, _flush);
-						} else {
-							VSOMEIP_ERROR
-									<< "Routing error. Service endpoint could not be found!";
-						}
-					} else {
-						VSOMEIP_ERROR
-								<< "Routing error. Service could not be found!";
-					}
-				}
-			}
-		}
-	}
+    if (its_target) {
+      std::vector<byte_t> its_command(
+          VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t)
+              + sizeof(bool) + sizeof(bool));
+      its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SEND;
+      std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
+                  sizeof(client_t));
+      std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size,
+                  sizeof(_size));
+      std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], _data, _size);
+      std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size], &_instance,
+                  sizeof(instance_t));
+      std::memcpy(
+          &its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t)],
+          &_reliable, sizeof(bool));
+      std::memcpy(
+          &its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t)
+              + sizeof(bool)],
+          &_flush, sizeof(bool));
+      is_sent = its_target->send(&its_command[0], its_command.size(), _flush);
+    } else {
+      // Check whether hosting application should get the message
+      // If not, check routes to external
+      if ((its_client == host_->get_client() && !is_request)
+          || (find_local_client(its_service, _instance) == host_->get_client()
+              && is_request)) {
+        // TODO: find out how to handle session id here
+        is_sent = deliver_message(_data, _size, _instance);
+      } else {
+        if (is_request) {
+          its_target = find_remote_client(its_service, _instance, _reliable);
+          if (its_target) {
+            is_sent = its_target->send(_data, _size, _flush);
+          } else {
+            VSOMEIP_ERROR
+                << "Routing error. Client from remote service could not be found!";
+          }
+        } else {
+          std::shared_ptr<serviceinfo> its_info(
+              find_service(its_service, _instance));
+          if (its_info) {
+            its_target = its_info->get_endpoint(_reliable);
+            if (its_target) {
+              is_sent = its_target->send(_data, _size, _flush);
+            } else {
+              VSOMEIP_ERROR
+                  << "Routing error. Service endpoint could not be found!";
+            }
+          } else {
+            VSOMEIP_ERROR << "Routing error. Service could not be found!";
+          }
+        }
+      }
+    }
+  }
 
-	return is_sent;
+  return is_sent;
 }
 
 void routing_manager_impl::set(client_t its_client, service_t _service,
-		instance_t _instance, event_t _event,
-		const std::shared_ptr<payload> &_value) {
+                               instance_t _instance, event_t _event,
+                               const std::shared_ptr<payload> &_payload) {
+  std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
+  if (its_event) {
+    its_event->set_payload(_payload);
+  } else {
+    VSOMEIP_ERROR << "Event [" << std::hex << std::setw(4) << std::setfill('0')
+        << _service << "." << std::setw(4) << std::setfill('0') << _instance
+        << "." << std::setw(4) << std::setfill('0') << _event
+        << "] is unknown!";
+  }
+}
+
+bool routing_manager_impl::send_subscribe(
+    const boost::asio::ip::address &_address, uint16_t _port, bool _reliable,
+    const byte_t *_data, uint32_t _size) {
+  std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port,
+                                                                _reliable);
+  if (its_endpoint)
+    return its_endpoint->send_to(_address, _port, _data, _size);
+
+  return false;
 }
 
 void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
-		endpoint *_receiver) {
+                                      endpoint *_receiver) {
 #if 0
-	std::stringstream msg;
-	msg << "rmi::on_message: ";
-	for (uint32_t i = 0; i < _size; ++i)
-	msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
-	VSOMEIP_DEBUG << msg.str();
+  std::stringstream msg;
+  msg << "rmi::on_message: ";
+  for (uint32_t i = 0; i < _size; ++i)
+  msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
+  VSOMEIP_DEBUG << msg.str();
 #endif
-	if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) {
-		service_t its_service = VSOMEIP_BYTES_TO_WORD(
-				_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
-		if (its_service == VSOMEIP_SD_SERVICE) {
-			if (discovery_)
-				discovery_->on_message(_data, _size);
-		} else {
-			instance_t its_instance = find_instance(its_service, _receiver);
-			if (its_instance != ANY_INSTANCE) {
-				client_t its_client(VSOMEIP_ROUTING_CLIENT);
-				if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
-					its_client = find_local_client(its_service, its_instance);
-				} else {
-					its_client = VSOMEIP_BYTES_TO_WORD(
-							_data[VSOMEIP_CLIENT_POS_MIN],
-							_data[VSOMEIP_CLIENT_POS_MAX]);
-				}
+  if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) {
+    service_t its_service = VSOMEIP_BYTES_TO_WORD(
+        _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+    if (its_service == VSOMEIP_SD_SERVICE) {
+      if (discovery_)
+        discovery_->on_message(_data, _size);
+    } else {
+      instance_t its_instance = find_instance(its_service, _receiver);
+      if (its_instance != ANY_INSTANCE) {
+        client_t its_client(VSOMEIP_ROUTING_CLIENT);
+        if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+          its_client = find_local_client(its_service, its_instance);
+        } else {
+          its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
+                                             _data[VSOMEIP_CLIENT_POS_MAX]);
+        }
 
-				if (its_client == host_->get_client()) {
-					deliver_message(_data, _size, its_instance);
-				} else if (its_client != VSOMEIP_ROUTING_CLIENT) {
-					send(its_client, _data, _size, its_instance, true, false);
-				} else {
-					VSOMEIP_ERROR << "Could not determine target application!";
-				}
-			} else {
-				VSOMEIP_ERROR << "Could not determine service instance for ["
-						<< its_service << "]";
-			}
-		}
-	} else {
-		//send_error(); // TODO: send error "malformed message"
-	}
+        if (its_client == host_->get_client()) {
+          deliver_message(_data, _size, its_instance);
+        } else if (its_client != VSOMEIP_ROUTING_CLIENT) {
+          send(its_client, _data, _size, its_instance, true, false);
+        } else {
+          VSOMEIP_ERROR << "Could not determine target application!";
+        }
+      } else {
+        VSOMEIP_ERROR << "Could not determine service instance for ["
+            << its_service << "]";
+      }
+    }
+  } else {
+    //send_error(); // TODO: send error "malformed message"
+  }
 }
 
 void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
-	for (auto &its_service : remote_services_) {
-		for (auto &its_instance : its_service.second) {
-			auto found_endpoint = its_instance.second.find(false);
-			if (found_endpoint != its_instance.second.end()) {
-				host_->on_availability(its_service.first, its_instance.first,
-						true);
-			} else {
-				found_endpoint = its_instance.second.find(true);
-				if (found_endpoint != its_instance.second.end()) {
-					host_->on_availability(its_service.first,
-							its_instance.first, true);
-				}
-			}
-		}
-	}
+  for (auto &its_service : remote_services_) {
+    for (auto &its_instance : its_service.second) {
+      auto found_endpoint = its_instance.second.find(false);
+      if (found_endpoint != its_instance.second.end()) {
+        host_->on_availability(its_service.first, its_instance.first, true);
+      } else {
+        found_endpoint = its_instance.second.find(true);
+        if (found_endpoint != its_instance.second.end()) {
+          host_->on_availability(its_service.first, its_instance.first, true);
+        }
+      }
+    }
+  }
 }
 
 void routing_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
-	for (auto &its_service : remote_services_) {
-		for (auto &its_instance : its_service.second) {
-			auto found_endpoint = its_instance.second.find(false);
-			if (found_endpoint != its_instance.second.end()) {
-				host_->on_availability(its_service.first, its_instance.first,
-						false);
-			} else {
-				found_endpoint = its_instance.second.find(true);
-				if (found_endpoint != its_instance.second.end()) {
-					host_->on_availability(its_service.first,
-							its_instance.first, false);
-				}
-			}
-		}
-	}
+  for (auto &its_service : remote_services_) {
+    for (auto &its_instance : its_service.second) {
+      auto found_endpoint = its_instance.second.find(false);
+      if (found_endpoint != its_instance.second.end()) {
+        host_->on_availability(its_service.first, its_instance.first, false);
+      } else {
+        found_endpoint = its_instance.second.find(true);
+        if (found_endpoint != its_instance.second.end()) {
+          host_->on_availability(its_service.first, its_instance.first, false);
+        }
+      }
+    }
+  }
 }
 
 bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
-		instance_t _instance) {
-	bool is_sent(false);
-	deserializer_->set_data(_data, _size);
-	std::shared_ptr<message> its_message(deserializer_->deserialize_message());
-	if (its_message) {
-		its_message->set_instance(_instance);
-		host_->on_message(its_message);
-		is_sent = true;
-	} else {
-		// TODO: send error "Malformed Message"
-		//send_error();
-	}
-	return is_sent;
+                                           instance_t _instance) {
+  bool is_sent(false);
+  deserializer_->set_data(_data, _size);
+  std::shared_ptr<message> its_message(deserializer_->deserialize_message());
+  if (its_message) {
+    its_message->set_instance(_instance);
+    host_->on_message(its_message);
+    is_sent = true;
+  } else {
+    // TODO: send error "Malformed Message"
+    //send_error();
+  }
+  return is_sent;
 }
 
 bool routing_manager_impl::is_available(service_t _service,
-		instance_t _instance) const {
-	auto find_local_service = local_services_.find(_service);
-	if (find_local_service != local_services_.end()) {
-		auto find_local_instance = find_local_service->second.find(_instance);
-		if (find_local_instance != find_local_service->second.end()) {
-			return true;
-		}
-	}
+                                        instance_t _instance) const {
+  auto find_local_service = local_services_.find(_service);
+  if (find_local_service != local_services_.end()) {
+    auto find_local_instance = find_local_service->second.find(_instance);
+    if (find_local_instance != find_local_service->second.end()) {
+      return true;
+    }
+  }
 
-	auto find_remote_service = remote_services_.find(_service);
-	if (find_remote_service != remote_services_.end()) {
-		auto find_remote_instance = find_remote_service->second.find(_instance);
-		if (find_remote_instance != find_remote_service->second.end()) {
-			return true;
-		}
-	}
+  auto find_remote_service = remote_services_.find(_service);
+  if (find_remote_service != remote_services_.end()) {
+    auto find_remote_instance = find_remote_service->second.find(_instance);
+    if (find_remote_instance != find_remote_service->second.end()) {
+      return true;
+    }
+  }
 
-	return false;
+  return false;
 }
 
 const std::map<std::string, std::shared_ptr<servicegroup> > &
 routing_manager_impl::get_servicegroups() const {
-	return servicegroups_;
+  return servicegroups_;
+}
+
+std::shared_ptr<eventgroupinfo> routing_manager_impl::find_eventgroup(
+    service_t _service, instance_t _instance, eventgroup_t _eventgroup) const {
+  std::shared_ptr<eventgroupinfo> its_info(nullptr);
+  auto found_service = eventgroups_.find(_service);
+  if (found_service != eventgroups_.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()) {
+        its_info = found_eventgroup->second;
+        std::shared_ptr<serviceinfo> its_service_info = find_service(_service,
+                                                                     _instance);
+        if (its_service_info) {
+          if (_eventgroup == its_service_info->get_multicast_group()) {
+            boost::asio::ip::address its_multicast_address =
+                boost::asio::ip::address::from_string(
+                    its_service_info->get_multicast_address());
+            uint16_t its_multicast_port =
+                its_service_info->get_multicast_port();
+            its_info->set_multicast(its_multicast_address, its_multicast_port);
+          }
+          its_info->set_major(its_service_info->get_major());
+          its_info->set_ttl(its_service_info->get_ttl());
+        }
+      }
+    }
+  }
+  return its_info;
 }
 
 std::shared_ptr<configuration> routing_manager_impl::get_configuration() const {
-	return host_->get_configuration();
+  return host_->get_configuration();
 }
 
 void routing_manager_impl::create_service_discovery_endpoint(
-		const std::string &_address, uint16_t _port,
-		const std::string &_protocol) {
-	bool is_reliable = (_protocol != "udp");
+    const std::string &_address, uint16_t _port, bool _reliable) {
+  std::shared_ptr<endpoint> its_service_endpoint = find_server_endpoint(
+      _port, _reliable);
+  if (!its_service_endpoint) {
+    its_service_endpoint = create_server_endpoint(_port, _reliable);
 
-	std::shared_ptr<endpoint> its_service_endpoint = find_server_endpoint(_port,
-			is_reliable);
-	if (!its_service_endpoint) {
-		its_service_endpoint = create_server_endpoint(_port, is_reliable);
+    std::shared_ptr<serviceinfo> its_info(
+        std::make_shared < serviceinfo > (ANY_MAJOR, ANY_MINOR, ANY_TTL));
+    its_info->set_endpoint(its_service_endpoint, _reliable);
 
-		std::shared_ptr<serviceinfo> its_info(
-				std::make_shared < serviceinfo
-						> (ANY_MAJOR, ANY_MINOR, ANY_TTL));
-		its_info->set_endpoint(its_service_endpoint, is_reliable);
+    // routing info
+    services_[VSOMEIP_SD_SERVICE][VSOMEIP_SD_INSTANCE] = its_info;
 
-		// routing info
-		services_[VSOMEIP_SD_SERVICE][VSOMEIP_SD_INSTANCE] = its_info;
-
-		its_service_endpoint->join(_address);
-		its_service_endpoint->start();
-	}
+    its_service_endpoint->add_multicast(VSOMEIP_SD_SERVICE, VSOMEIP_SD_METHOD,
+                                        _address, _port);
+    its_service_endpoint->join(_address);
+    its_service_endpoint->start();
+  }
 }
 
-service_map_t routing_manager_impl::get_offered_services(
-		const std::string &_name) const {
-	service_map_t its_offers;
+services_t routing_manager_impl::get_offered_services(
+    const std::string &_name) const {
+  services_t its_offers;
+  auto find_servicegroup = servicegroups_.find(_name);
+  if (find_servicegroup != servicegroups_.end()) {
+    return find_servicegroup->second->get_services();
+  }
 
-	auto find_servicegroup = servicegroups_.find(_name);
-	if (find_servicegroup != servicegroups_.end()) {
-		return find_servicegroup->second->get_services();
-	}
-
-	return its_offers;
+  return its_offers;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // PRIVATE
 ///////////////////////////////////////////////////////////////////////////////
 std::shared_ptr<serviceinfo> routing_manager_impl::find_service(
-		service_t _service, instance_t _instance) {
-	std::shared_ptr<serviceinfo> its_info;
-	auto found_service = services_.find(_service);
-	if (found_service != services_.end()) {
-		auto found_instance = found_service->second.find(_instance);
-		if (found_instance != found_service->second.end()) {
-			its_info = found_instance->second;
-		}
-	}
-	return its_info;
+    service_t _service, instance_t _instance) const {
+  std::shared_ptr<serviceinfo> its_info;
+  auto found_service = services_.find(_service);
+  if (found_service != services_.end()) {
+    auto found_instance = found_service->second.find(_instance);
+    if (found_instance != found_service->second.end()) {
+      its_info = found_instance->second;
+    }
+  }
+  return its_info;
 }
 
 std::shared_ptr<serviceinfo> routing_manager_impl::create_service(
-		service_t _service, instance_t _instance, major_version_t _major,
-		minor_version_t _minor, ttl_t _ttl) {
-	std::shared_ptr<serviceinfo> its_info;
-	if (configuration_) {
-		its_info = std::make_shared < serviceinfo > (_major, _minor, _ttl);
+    service_t _service, instance_t _instance, major_version_t _major,
+    minor_version_t _minor, ttl_t _ttl) {
+  std::shared_ptr<serviceinfo> its_info;
+  if (configuration_) {
+    its_info = std::make_shared < serviceinfo > (_major, _minor, _ttl);
 
-		uint16_t its_reliable_port = configuration_->get_reliable_port(_service,
-				_instance);
-		uint16_t its_unreliable_port = configuration_->get_unreliable_port(
-				_service, _instance);
+    uint16_t its_reliable_port = configuration_->get_reliable_port(_service,
+                                                                   _instance);
+    uint16_t its_unreliable_port = configuration_->get_unreliable_port(
+        _service, _instance);
 
-		if (ILLEGAL_PORT != its_reliable_port) {
-			std::shared_ptr<endpoint> its_reliable_endpoint(
-					find_or_create_server_endpoint(its_reliable_port, true));
-			its_info->set_endpoint(its_reliable_endpoint, true);
+    its_info->set_multicast_address(
+        configuration_->get_multicast_address(_service, _instance));
+    its_info->set_multicast_port(
+        configuration_->get_multicast_port(_service, _instance));
+    its_info->set_multicast_group(
+        configuration_->get_multicast_group(_service, _instance));
 
-			// TODO: put this in a method and check whether an assignment already exists!
-			service_instances_[_service][its_reliable_endpoint.get()] =
-					_instance;
-		}
+    VSOMEIP_DEBUG << "MULTICAST ["
+        << std::hex << _service << "." << _instance << "] --> "
+        << its_info->get_multicast_group();
 
-		if (ILLEGAL_PORT != its_unreliable_port) {
-			std::shared_ptr<endpoint> its_unreliable_endpoint(
-					find_or_create_server_endpoint(its_unreliable_port, false));
-			its_info->set_endpoint(its_unreliable_endpoint, false);
+    std::shared_ptr<endpoint> its_reliable_endpoint;
+    std::shared_ptr<endpoint> its_unreliable_endpoint;
 
-			service_instances_[_service][its_unreliable_endpoint.get()] =
-					_instance;
-		}
+    if (ILLEGAL_PORT != its_reliable_port) {
+      its_reliable_endpoint = find_or_create_server_endpoint(its_reliable_port,
+                                                             true);
+      its_info->set_endpoint(its_reliable_endpoint, true);
 
-		if (ILLEGAL_PORT != its_reliable_port
-				|| ILLEGAL_PORT != its_unreliable_port) {
-			std::string its_servicegroup = configuration_->get_group(_service,
-					_instance);
-			auto found_servicegroup = servicegroups_.find(its_servicegroup);
-			if (found_servicegroup == servicegroups_.end()) {
-				servicegroups_[its_servicegroup] = std::make_shared
-						< servicegroup > (its_servicegroup);
-			}
-			servicegroups_[its_servicegroup]->add_service(_service, _instance,
-					its_info);
-			services_[_service][_instance] = its_info;
-		} else {
-			host_->on_error(error_code_e::PORT_CONFIGURATION_MISSING);
-		}
-	} else {
-		host_->on_error(error_code_e::CONFIGURATION_MISSING);
-	}
+      // TODO: put this in a method and check whether an assignment already exists!
+      service_instances_[_service][its_reliable_endpoint.get()] = _instance;
+    }
 
-	return its_info;
+    if (ILLEGAL_PORT != its_unreliable_port) {
+      its_unreliable_endpoint = find_or_create_server_endpoint(
+          its_unreliable_port, false);
+      its_info->set_endpoint(its_unreliable_endpoint, false);
+
+      service_instances_[_service][its_unreliable_endpoint.get()] = _instance;
+    }
+
+    if (ILLEGAL_PORT != its_reliable_port
+        || ILLEGAL_PORT != its_unreliable_port) {
+      std::string its_servicegroup = configuration_->get_group(_service,
+                                                               _instance);
+      auto found_servicegroup = servicegroups_.find(its_servicegroup);
+      if (found_servicegroup == servicegroups_.end()) {
+        servicegroups_[its_servicegroup] = std::make_shared < servicegroup
+            > (its_servicegroup);
+      }
+
+      servicegroups_[its_servicegroup]->add_service(_service, _instance,
+                                                    its_info);
+      services_[_service][_instance] = its_info;
+    } else {
+      host_->on_error(error_code_e::PORT_CONFIGURATION_MISSING);
+    }
+  } else {
+    host_->on_error(error_code_e::CONFIGURATION_MISSING);
+  }
+
+  return its_info;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint(
-		const boost::asio::ip::address &_address, uint16_t _port,
-		bool _reliable) {
-	std::shared_ptr<endpoint> its_endpoint;
-	try {
-		if (_reliable) {
-			its_endpoint = std::make_shared < tcp_client_endpoint_impl
-					> (shared_from_this(), boost::asio::ip::tcp::endpoint(
-							_address, _port), io_);
+    const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) {
+  std::shared_ptr<endpoint> its_endpoint;
+  try {
+    if (_reliable) {
+      its_endpoint = std::make_shared < tcp_client_endpoint_impl
+          > (shared_from_this(), boost::asio::ip::tcp::endpoint(_address,
+                                                                _port), io_);
 
-			if (configuration_->has_enabled_magic_cookies(_address.to_string(),
-					_port)) {
-				its_endpoint->enable_magic_cookies();
-			}
-		} else {
-			its_endpoint = std::make_shared < udp_client_endpoint_impl
-					> (shared_from_this(), boost::asio::ip::udp::endpoint(
-							_address, _port), io_);
-		}
+      if (configuration_->has_enabled_magic_cookies(_address.to_string(),
+                                                    _port)) {
+        its_endpoint->enable_magic_cookies();
+      }
+    } else {
+      its_endpoint = std::make_shared < udp_client_endpoint_impl
+          > (shared_from_this(), boost::asio::ip::udp::endpoint(_address,
+                                                                _port), io_);
+    }
 
-		client_endpoints_[_address][_port][_reliable] = its_endpoint;
-		its_endpoint->start();
-	} catch (std::exception &e) {
-		host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED);
-	}
+    client_endpoints_[_address][_port][_reliable] = its_endpoint;
+    its_endpoint->start();
+  } catch (std::exception &e) {
+    host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED);
+  }
 
-	return its_endpoint;
+  return its_endpoint;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::find_client_endpoint(
-		const boost::asio::ip::address &_address, uint16_t _port,
-		bool _reliable) {
-	std::shared_ptr<endpoint> its_endpoint;
-	auto found_address = client_endpoints_.find(_address);
-	if (found_address != client_endpoints_.end()) {
-		auto found_port = found_address->second.find(_port);
-		if (found_port != found_address->second.end()) {
-			auto found_endpoint = found_port->second.find(_reliable);
-			if (found_endpoint != found_port->second.end()) {
-				its_endpoint = found_endpoint->second;
-			}
-		}
-	}
-	return its_endpoint;
+    const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) {
+  std::shared_ptr<endpoint> its_endpoint;
+  auto found_address = client_endpoints_.find(_address);
+  if (found_address != client_endpoints_.end()) {
+    auto found_port = found_address->second.find(_port);
+    if (found_port != found_address->second.end()) {
+      auto found_endpoint = found_port->second.find(_reliable);
+      if (found_endpoint != found_port->second.end()) {
+        its_endpoint = found_endpoint->second;
+      }
+    }
+  }
+  return its_endpoint;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::find_or_create_client_endpoint(
-		const boost::asio::ip::address &_address, uint16_t _port,
-		bool _reliable) {
-	std::shared_ptr<endpoint> its_endpoint = find_client_endpoint(_address,
-			_port, _reliable);
-	if (0 == its_endpoint) {
-		its_endpoint = create_client_endpoint(_address, _port, _reliable);
-	}
-	return its_endpoint;
+    const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) {
+  std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_);
+  std::shared_ptr<endpoint> its_endpoint = find_client_endpoint(_address, _port,
+                                                                _reliable);
+  if (0 == its_endpoint) {
+    its_endpoint = create_client_endpoint(_address, _port, _reliable);
+  }
+  return its_endpoint;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint(
-		uint16_t _port, bool _reliable) {
-	std::shared_ptr<endpoint> its_endpoint;
+    uint16_t _port, bool _reliable) {
+  std::shared_ptr<endpoint> its_endpoint;
 
-	try {
-		boost::asio::ip::address its_unicast = configuration_->get_unicast();
-		if (_reliable) {
-			its_endpoint = std::make_shared < tcp_server_endpoint_impl
-					> (shared_from_this(), boost::asio::ip::tcp::endpoint(
-							its_unicast, _port), io_);
-			if (configuration_->has_enabled_magic_cookies(
-					its_unicast.to_string(), _port)) {
-				its_endpoint->enable_magic_cookies();
-			}
-		} else {
-			if (its_unicast.is_v4()) {
-				its_unicast = boost::asio::ip::address_v4::any();
-			} else {
-				// TODO: how is "ANY" specified in IPv6?
-			}
-			its_endpoint = std::make_shared < udp_server_endpoint_impl
-					> (shared_from_this(), boost::asio::ip::udp::endpoint(
-							its_unicast, _port), io_);
-		}
+  try {
+    boost::asio::ip::address its_unicast = configuration_->get_unicast();
+    if (_reliable) {
+      its_endpoint = std::make_shared < tcp_server_endpoint_impl
+          > (shared_from_this(), boost::asio::ip::tcp::endpoint(its_unicast,
+                                                                _port), io_);
+      if (configuration_->has_enabled_magic_cookies(its_unicast.to_string(),
+                                                    _port)) {
+        its_endpoint->enable_magic_cookies();
+      }
+    } else {
+      if (its_unicast.is_v4()) {
+        its_unicast = boost::asio::ip::address_v4::any();
+      } else {
+        // TODO: how is "ANY" specified in IPv6?
+      }
+      its_endpoint = std::make_shared < udp_server_endpoint_impl
+          > (shared_from_this(), boost::asio::ip::udp::endpoint(its_unicast,
+                                                                _port), io_);
+    }
 
-		server_endpoints_[_port][_reliable] = its_endpoint;
-		its_endpoint->start();
-	} catch (std::exception &e) {
-		host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED);
-	}
+    server_endpoints_[_port][_reliable] = its_endpoint;
+    its_endpoint->start();
+  } catch (std::exception &e) {
+    host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED);
+  }
 
-	return its_endpoint;
+  return its_endpoint;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::find_server_endpoint(
-		uint16_t _port, bool _reliable) {
-	std::shared_ptr<endpoint> its_endpoint;
-	auto found_port = server_endpoints_.find(_port);
-	if (found_port != server_endpoints_.end()) {
-		auto found_endpoint = found_port->second.find(_reliable);
-		if (found_endpoint != found_port->second.end()) {
-			its_endpoint = found_endpoint->second;
-		}
-	}
-	return its_endpoint;
+    uint16_t _port, bool _reliable) {
+  std::shared_ptr<endpoint> its_endpoint;
+  auto found_port = server_endpoints_.find(_port);
+  if (found_port != server_endpoints_.end()) {
+    auto found_endpoint = found_port->second.find(_reliable);
+    if (found_endpoint != found_port->second.end()) {
+      its_endpoint = found_endpoint->second;
+    }
+  }
+  return its_endpoint;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::find_or_create_server_endpoint(
-		uint16_t _port, bool _reliable) {
-	std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port,
-			_reliable);
-	if (0 == its_endpoint) {
-		its_endpoint = create_server_endpoint(_port, _reliable);
-	}
-	return its_endpoint;
+    uint16_t _port, bool _reliable) {
+  std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_);
+  std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port,
+                                                                _reliable);
+  if (0 == its_endpoint) {
+    its_endpoint = create_server_endpoint(_port, _reliable);
+  }
+  return its_endpoint;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::find_local(client_t _client) {
-	std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_);
-	std::shared_ptr<endpoint> its_endpoint;
-	auto found_endpoint = local_clients_.find(_client);
-	if (found_endpoint != local_clients_.end()) {
-		its_endpoint = found_endpoint->second;
-	}
-	return its_endpoint;
+  std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_);
+  std::shared_ptr<endpoint> its_endpoint;
+  auto found_endpoint = local_clients_.find(_client);
+  if (found_endpoint != local_clients_.end()) {
+    its_endpoint = found_endpoint->second;
+  }
+  return its_endpoint;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::create_local(client_t _client) {
-	std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_);
+  std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_);
 
-	std::stringstream its_path;
-	its_path << base_path << std::hex << _client;
+  std::stringstream its_path;
+  its_path << base_path << std::hex << _client;
 
-	std::shared_ptr<endpoint> its_endpoint =
-			std::make_shared < local_client_endpoint_impl
-					> (shared_from_this(), boost::asio::local::stream_protocol::endpoint(
-							its_path.str()), io_);
-	local_clients_[_client] = its_endpoint;
-	its_endpoint->start();
-	return its_endpoint;
+  std::shared_ptr<endpoint> its_endpoint = std::make_shared
+      < local_client_endpoint_impl
+      > (shared_from_this(), boost::asio::local::stream_protocol::endpoint(
+          its_path.str()), io_);
+  local_clients_[_client] = its_endpoint;
+  its_endpoint->start();
+  return its_endpoint;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::find_or_create_local(
-		client_t _client) {
-	std::shared_ptr<endpoint> its_endpoint(find_local(_client));
-	if (!its_endpoint) {
-		its_endpoint = create_local(_client);
-	}
-	return its_endpoint;
+    client_t _client) {
+  std::shared_ptr<endpoint> its_endpoint(find_local(_client));
+  if (!its_endpoint) {
+    its_endpoint = create_local(_client);
+  }
+  return its_endpoint;
 }
 
 void routing_manager_impl::remove_local(client_t _client) {
-	std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_);
-	std::shared_ptr<endpoint> its_endpoint = find_local(_client);
-	its_endpoint->stop();
-	local_clients_.erase(_client);
+  std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_);
+  std::shared_ptr<endpoint> its_endpoint = find_local(_client);
+  its_endpoint->stop();
+  local_clients_.erase(_client);
 }
 
-std::shared_ptr<endpoint> routing_manager_impl::find_local(service_t _service,
-		instance_t _instance) {
-	return find_local(find_local_client(_service, _instance));
+std::shared_ptr<endpoint> routing_manager_impl::find_local(
+    service_t _service, instance_t _instance) {
+  return find_local(find_local_client(_service, _instance));
 }
 
 client_t routing_manager_impl::find_local_client(service_t _service,
-		instance_t _instance) {
-	client_t its_client(0);
-	auto found_service = local_services_.find(_service);
-	if (found_service != local_services_.end()) {
-		auto found_instance = found_service->second.find(_instance);
-		if (found_instance != found_service->second.end()) {
-			its_client = found_instance->second;
-		}
-	}
-	return its_client;
+                                                 instance_t _instance) {
+  client_t its_client(0);
+  auto found_service = local_services_.find(_service);
+  if (found_service != local_services_.end()) {
+    auto found_instance = found_service->second.find(_instance);
+    if (found_instance != found_service->second.end()) {
+      its_client = found_instance->second;
+    }
+  }
+  return its_client;
 }
 
 instance_t routing_manager_impl::find_instance(service_t _service,
-		endpoint * _endpoint) {
-	instance_t its_instance(0xFFFF);
-	auto found_service = service_instances_.find(_service);
-	if (found_service != service_instances_.end()) {
-		auto found_endpoint = found_service->second.find(_endpoint);
-		if (found_endpoint != found_service->second.end()) {
-			its_instance = found_endpoint->second;
-		}
-	}
-	return its_instance;
+                                               endpoint * _endpoint) {
+  instance_t its_instance(0xFFFF);
+  auto found_service = service_instances_.find(_service);
+  if (found_service != service_instances_.end()) {
+    auto found_endpoint = found_service->second.find(_endpoint);
+    if (found_endpoint != found_service->second.end()) {
+      its_instance = found_endpoint->second;
+    }
+  }
+  return its_instance;
 }
 
 std::shared_ptr<endpoint> routing_manager_impl::find_remote_client(
-		service_t _service, instance_t _instance, bool _reliable) {
-	std::shared_ptr<endpoint> its_endpoint;
-	auto found_service = remote_services_.find(_service);
-	if (found_service != remote_services_.end()) {
-		auto found_instance = found_service->second.find(_instance);
-		if (found_instance != found_service->second.end()) {
-			auto found_reliability = found_instance->second.find(_reliable);
-			if (found_reliability != found_instance->second.end()) {
-				its_endpoint = found_reliability->second;
-			}
-		}
-	}
-	return its_endpoint;
+    service_t _service, instance_t _instance, bool _reliable) {
+  std::shared_ptr<endpoint> its_endpoint;
+  auto found_service = remote_services_.find(_service);
+  if (found_service != remote_services_.end()) {
+    auto found_instance = found_service->second.find(_instance);
+    if (found_instance != found_service->second.end()) {
+      auto found_reliability = found_instance->second.find(_reliable);
+      if (found_reliability != found_instance->second.end()) {
+        its_endpoint = found_reliability->second;
+      }
+    }
+  }
+  return its_endpoint;
 }
 
-void routing_manager_impl::add_routing_info(service_t _service,
-		instance_t _instance, major_version_t _major, minor_version_t _minor,
-		ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port,
-		bool _reliable) {
-	std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
-	if (!its_info)
-		its_info = create_service(_service, _instance, _major, _minor, _ttl);
+std::shared_ptr<event> routing_manager_impl::find_event(service_t _service,
+                                                        instance_t _instance,
+                                                        event_t _event) const {
+  std::shared_ptr<event> its_event;
+  auto find_service = events_.find(_service);
+  if (find_service != events_.end()) {
+    auto find_instance = find_service->second.find(_instance);
+    if (find_instance != find_service->second.end()) {
+      auto find_event = find_instance->second.find(_event);
+      if (find_event != find_instance->second.end()) {
+        its_event = find_event->second;
+      }
+    }
+  }
+  return its_event;
+}
 
-	std::shared_ptr<endpoint> its_endpoint(
-			create_client_endpoint(_address, _port, _reliable));
-	its_info->set_endpoint(its_endpoint, _reliable);
-	remote_services_[_service][_instance][_reliable] = its_endpoint;
-	service_instances_[_service][its_endpoint.get()] = _instance;
-	services_[_service][_instance] = its_info;
-	stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance);
+std::set<std::shared_ptr<event> > routing_manager_impl::find_events(
+    service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+  std::set < std::shared_ptr<event> > its_events;
+  auto found_service = eventgroups_.find(_service);
+  if (found_service != eventgroups_.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()) {
+        return found_eventgroup->second->get_events();
+      }
+    }
+  }
+  return its_events;
+}
 
-	if (its_endpoint->is_connected())
-		host_->on_availability(_service, _instance, true);
+void routing_manager_impl::add_routing_info(
+    service_t _service, instance_t _instance, major_version_t _major,
+    minor_version_t _minor, ttl_t _ttl,
+    const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) {
+  std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
+  if (!its_info) {
+    its_info = create_service(_service, _instance, _major, _minor, _ttl);
+    services_[_service][_instance] = its_info;
+  }
+
+  std::shared_ptr<endpoint> its_endpoint(
+      find_or_create_client_endpoint(_address, _port, _reliable));
+  its_info->set_endpoint(its_endpoint, _reliable);
+
+  remote_services_[_service][_instance][_reliable] = its_endpoint;
+  service_instances_[_service][its_endpoint.get()] = _instance;
+  stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance);
+
+  if (its_endpoint->is_connected())
+    host_->on_availability(_service, _instance, true);
 }
 
 void routing_manager_impl::del_routing_info(service_t _service,
-		instance_t _instance, bool _reliable) {
-	std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
-	if (its_info) {
-		std::shared_ptr<endpoint> its_empty_endpoint;
+                                            instance_t _instance,
+                                            bool _reliable) {
+  std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
+  if (its_info) {
+    std::shared_ptr<endpoint> its_empty_endpoint;
 
-		// TODO: only tell the application if the service is completely gone
-		host_->on_availability(_service, _instance, false);
-		stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service,
-				_instance);
+    // TODO: only tell the application if the service is completely gone
+    host_->on_availability(_service, _instance, false);
+    stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance);
 
-		std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint(
-				_reliable);
-		if (its_endpoint) {
-			if (1 >= service_instances_[_service].size()) {
-				service_instances_.erase(_service);
-			} else {
-				service_instances_[_service].erase(its_endpoint.get());
-			}
+    std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint(_reliable);
+    if (its_endpoint) {
+      if (1 >= service_instances_[_service].size()) {
+        service_instances_.erase(_service);
+      } else {
+        service_instances_[_service].erase(its_endpoint.get());
+      }
 
-			remote_services_[_service][_instance].erase(_reliable);
-			auto found_endpoint = remote_services_[_service][_instance].find(
-					!_reliable);
-			if (found_endpoint == remote_services_[_service][_instance].end()) {
-				remote_services_[_service].erase(_instance);
-			}
-			if (1 >= remote_services_[_service].size()) {
-				remote_services_.erase(_service);
-			}
-		}
+      remote_services_[_service][_instance].erase(_reliable);
+      auto found_endpoint = remote_services_[_service][_instance].find(
+          !_reliable);
+      if (found_endpoint == remote_services_[_service][_instance].end()) {
+        remote_services_[_service].erase(_instance);
+      }
+      if (1 >= remote_services_[_service].size()) {
+        remote_services_.erase(_service);
+      }
+    }
 
-		if (!its_info->get_endpoint(!_reliable)) {
-			its_info->get_group()->remove_service(_service, _instance);
-			if (1 >= services_[_service].size()) {
-				services_.erase(_service);
-			} else {
-				services_[_service].erase(_instance);
-			}
-		} else {
-			its_info->set_endpoint(its_empty_endpoint, _reliable);
-		}
-	}
+    if (!its_info->get_endpoint(!_reliable)) {
+      its_info->get_group()->remove_service(_service, _instance);
+      if (1 >= services_[_service].size()) {
+        services_.erase(_service);
+      } else {
+        services_[_service].erase(_instance);
+      }
+    } else {
+      its_info->set_endpoint(its_empty_endpoint, _reliable);
+    }
+  }
 }
 
 void routing_manager_impl::init_routing_info() {
-	VSOMEIP_INFO
-			<< "Service Discovery disabled. Using static routing information.";
-	for (auto i : configuration_->get_remote_services()) {
-		std::string its_address = configuration_->get_address(i.first,
-				i.second);
-		uint16_t its_reliable = configuration_->get_reliable_port(i.first,
-				i.second);
-		uint16_t its_unreliable = configuration_->get_unreliable_port(i.first,
-				i.second);
+  VSOMEIP_INFO
+      << "Service Discovery disabled. Using static routing information.";
+  for (auto i : configuration_->get_remote_services()) {
+    std::string its_address = configuration_->get_unicast(i.first, i.second);
+    uint16_t its_reliable = configuration_->get_reliable_port(i.first,
+                                                              i.second);
+    uint16_t its_unreliable = configuration_->get_unreliable_port(i.first,
+                                                                  i.second);
 
-		if (VSOMEIP_INVALID_PORT != its_reliable) {
-			add_routing_info(i.first, i.second,
-					DEFAULT_MAJOR, DEFAULT_MINOR, DEFAULT_TTL,
-					boost::asio::ip::address::from_string(its_address),
-					its_reliable, true);
-		}
+    if (VSOMEIP_INVALID_PORT != its_reliable) {
+      add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR,
+                       DEFAULT_TTL,
+                       boost::asio::ip::address::from_string(its_address),
+                       its_reliable, true);
+    }
 
-		if (VSOMEIP_INVALID_PORT != its_unreliable) {
-			add_routing_info(i.first, i.second,
-					DEFAULT_MAJOR, DEFAULT_MINOR, DEFAULT_TTL,
-					boost::asio::ip::address::from_string(its_address),
-					its_unreliable, false);
-		}
-	}
+    if (VSOMEIP_INVALID_PORT != its_unreliable) {
+      add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR,
+                       DEFAULT_TTL,
+                       boost::asio::ip::address::from_string(its_address),
+                       its_unreliable, false);
+    }
+  }
 }
 
-} // namespace vsomeip
+void routing_manager_impl::init_event_routing_info() {
+  // TODO: the following should be done before(!) initializing
+  // the configuration object to allow the configuration to
+  // directly write to the target structure!
+  std::map<service_t, std::map<instance_t, std::set<event_t> > > its_events =
+      configuration_->get_events();
+  for (auto i : its_events) {
+    for (auto j : i.second) {
+      for (auto k : j.second) {
+        std::shared_ptr<event> its_event(std::make_shared < event > (this));
+        its_event->set_service(i.first);
+        its_event->set_instance(j.first);
+        its_event->set_event(k);
+        configuration_->set_event(its_event);
+        events_[i.first][j.first][k] = its_event;
+      }
+    }
+  }
+
+  std::map<service_t,
+      std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > its_eventgroups =
+      configuration_->get_eventgroups();
+  for (auto i : its_eventgroups) {
+    for (auto j : i.second) {
+      for (auto k : j.second) {
+        eventgroups_[i.first][j.first][k.first] = std::make_shared<
+            eventgroupinfo>();
+        for (auto l : k.second) {
+          std::shared_ptr<event> its_event = find_event(i.first, j.first, l);
+          if (its_event) {
+            eventgroups_[i.first][j.first][k.first]->add_event(its_event);
+          }
+        }
+      }
+    }
+  }
+
+#if 1
+  for (auto i : eventgroups_) {
+    for (auto j : i.second) {
+      for (auto k : j.second) {
+        VSOMEIP_DEBUG << "Eventgroup [" << std::hex << std::setw(4)
+            << std::setfill('0') << i.first << "." << j.first << "." << k.first
+            << "] (MC: ";
+        for (auto l : k.second->get_events()) {
+          VSOMEIP_DEBUG << "  Event " << std::hex << std::setw(4)
+              << std::setfill('0') << l->get_event();
+        }
+      }
+    }
+  }
+#endif
+}
+
+void routing_manager_impl::add_subscription(
+    service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+    const boost::asio::ip::address &_address, uint16_t _reliable_port,
+    uint16_t _unreliable_port) {
+
+  VSOMEIP_INFO << "ADDING A SUBSCRIPTION FOR EVENT [" << std::hex
+      << std::setw(4) << std::setfill('0') << _service << "." << _instance
+      << "." << _eventgroup << "] for " << _address.to_string() << ":"
+      << std::dec << _unreliable_port;
+
+}
+
+void routing_manager_impl::del_subscription(
+    service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+    const boost::asio::ip::address &_address, uint16_t _reliable_port,
+    uint16_t _unreliable_port) {
+
+}
+
+}  // namespace vsomeip
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index e1fdafb..dc6de94 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -11,16 +11,16 @@
 #include <vsomeip/constants.hpp>
 #include <vsomeip/logger.hpp>
 
+#include "../include/event.hpp"
 #include "../include/routing_manager_host.hpp"
 #include "../include/routing_manager_proxy.hpp"
 #include "../../configuration/include/internal.hpp"
 #include "../../endpoints/include/local_client_endpoint_impl.hpp"
 #include "../../endpoints/include/local_server_endpoint_impl.hpp"
-#include "../../message/include/byteorder.hpp"
 #include "../../message/include/deserializer.hpp"
-#include "../../message/include/event_impl.hpp"
 #include "../../message/include/serializer.hpp"
 #include "../../service_discovery/include/runtime.hpp"
+#include "../../utility/include/byteorder.hpp"
 #include "../../utility/include/utility.hpp"
 
 namespace vsomeip {
diff --git a/implementation/routing/src/servicegroup.cpp b/implementation/routing/src/servicegroup.cpp
index ffdcbac..8818c1b 100644
--- a/implementation/routing/src/servicegroup.cpp
+++ b/implementation/routing/src/servicegroup.cpp
@@ -57,7 +57,7 @@
 	return its_result;
 }
 
-service_map_t servicegroup::get_services() const {
+services_t servicegroup::get_services() const {
 	return services_;
 }
 
diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp
index a991466..5fa932a 100644
--- a/implementation/routing/src/serviceinfo.cpp
+++ b/implementation/routing/src/serviceinfo.cpp
@@ -8,62 +8,88 @@
 
 namespace vsomeip {
 
-serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor, ttl_t _ttl)
-	: group_(0), major_(_major), minor_(_minor), ttl_(_ttl) {
+serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor,
+                         ttl_t _ttl)
+    : group_(0),
+      major_(_major),
+      minor_(_minor),
+      ttl_(_ttl),
+      reliable_(nullptr),
+      unreliable_(nullptr),
+      multicast_group_(0xFFFF) {
 }
 
 serviceinfo::~serviceinfo() {
 }
 
 servicegroup * serviceinfo::get_group() const {
-	return group_;
+  return group_;
 }
 
 void serviceinfo::set_group(servicegroup *_group) {
-	group_ = _group;
+  group_ = _group;
 }
 
 major_version_t serviceinfo::get_major() const {
-	return major_;
+  return major_;
 }
 
 minor_version_t serviceinfo::get_minor() const {
-	return minor_;
+  return minor_;
 }
 
 ttl_t serviceinfo::get_ttl() const {
-	return ttl_;
+  return ttl_;
 }
 
 void serviceinfo::set_ttl(ttl_t _ttl) {
-	ttl_ = _ttl;
+  ttl_ = _ttl;
 }
 
-std::shared_ptr< endpoint > & serviceinfo::get_endpoint(bool _reliable) {
-	if (_reliable)
-		return reliable_;
-
-	return unreliable_;
+std::shared_ptr<endpoint> serviceinfo::get_endpoint(bool _reliable) const {
+  return (_reliable ? reliable_ : unreliable_);
 }
 
-void serviceinfo::set_endpoint(std::shared_ptr< endpoint > &_endpoint, bool _reliable) {
-	if (_reliable) {
-		reliable_ = _endpoint;
-	} else {
-		unreliable_ = _endpoint;
-	}
+void serviceinfo::set_endpoint(std::shared_ptr<endpoint> _endpoint,
+                               bool _reliable) {
+  if (_reliable) {
+    reliable_ = _endpoint;
+  } else {
+    unreliable_ = _endpoint;
+  }
+}
+
+const std::string & serviceinfo::get_multicast_address() const {
+  return multicast_address_;
+}
+
+void serviceinfo::set_multicast_address(const std::string &_multicast_address) {
+  multicast_address_ = _multicast_address;
+}
+
+uint16_t serviceinfo::get_multicast_port() const {
+  return multicast_port_;
+}
+
+void serviceinfo::set_multicast_port(uint16_t _multicast_port) {
+  multicast_port_ = _multicast_port;
+}
+
+eventgroup_t serviceinfo::get_multicast_group() const {
+  return multicast_group_;
+}
+
+void serviceinfo::set_multicast_group(eventgroup_t _multicast_group) {
+  multicast_group_ = _multicast_group;
 }
 
 void serviceinfo::add_client(client_t _client) {
-	requesters_.insert(_client);
+  requesters_.insert(_client);
 }
 
 void serviceinfo::remove_client(client_t _client) {
-	requesters_.erase(_client);
+  requesters_.erase(_client);
 }
 
-
-} // namespace vsomeip
-
-
+}  // namespace vsomeip
 
diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp
index 00d388a..8d9eb73 100644
--- a/implementation/runtime/src/application_impl.cpp
+++ b/implementation/runtime/src/application_impl.cpp
@@ -194,9 +194,10 @@
 	}
 }
 
-void application_impl::set(service_t _service, instance_t _instance, event_t,
+void application_impl::set(service_t _service, instance_t _instance, event_t _event,
 		const std::shared_ptr<payload> &_payload) {
-
+  if (routing_)
+    routing_->set(client_, _service, _instance, _event, _payload);
 }
 
 void application_impl::register_event_handler(event_handler_t _handler) {
diff --git a/implementation/service_discovery/include/constants.hpp b/implementation/service_discovery/include/constants.hpp
index 832e87b..598823e 100644
--- a/implementation/service_discovery/include/constants.hpp
+++ b/implementation/service_discovery/include/constants.hpp
@@ -28,8 +28,8 @@
 const uint16_t reserved_word = 0x0;
 const uint32_t reserved_long = 0x0;
 
-const uint8_t udp = 0x06;
-const uint8_t tcp = 0x11;
+const uint8_t tcp = 0x06;
+const uint8_t udp = 0x11;
 
 } // namespace protocol
 } // namespace sd
diff --git a/implementation/service_discovery/include/request.hpp b/implementation/service_discovery/include/request.hpp
new file mode 100644
index 0000000..28d1fa8
--- /dev/null
+++ b/implementation/service_discovery/include/request.hpp
@@ -0,0 +1,42 @@
+// Copyright (C) 2014 BMW Group
+// Author: Lutz Bichler (lutz.bichler@bmw.de)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_SD_REQUEST_HPP
+#define VSOMEIP_SD_REQUEST_HPP
+
+#include <memory>
+
+#include <vsomeip/primitive_types.hpp>
+
+namespace vsomeip {
+
+class endpoint;
+
+namespace sd {
+
+class request {
+public:
+	request(major_version_t _major, minor_version_t _minor, ttl_t _ttl);
+
+	major_version_t get_major() const;
+	void set_major(major_version_t _major);
+
+  minor_version_t get_minor() const;
+  void set_minor(minor_version_t _minor);
+
+	ttl_t get_ttl() const;
+	void set_ttl(ttl_t _ttl);
+
+private:
+	major_version_t major_;
+	minor_version_t minor_;
+	ttl_t ttl_;
+};
+
+} // namespace sd
+} // namespace vsomeip
+
+#endif // VSOMEIP_SD_SUBSCRIPTION_HPP
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp
index d2fab83..47455a0 100644
--- a/implementation/service_discovery/include/service_discovery.hpp
+++ b/implementation/service_discovery/include/service_discovery.hpp
@@ -19,9 +19,7 @@
 
 class service_discovery {
 public:
-	virtual ~service_discovery() {
-	}
-	;
+	virtual ~service_discovery() {};
 
 	virtual std::shared_ptr<configuration> get_configuration() const = 0;
 	virtual boost::asio::io_service & get_io() = 0;
diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp
index 4679e0e..dbd5a16 100644
--- a/implementation/service_discovery/include/service_discovery_host.hpp
+++ b/implementation/service_discovery/include/service_discovery_host.hpp
@@ -13,40 +13,65 @@
 #include <boost/asio/ip/address.hpp>
 #include <boost/asio/io_service.hpp>
 
-#include "../../routing/include/routing_types.hpp"
+#include "../../routing/include/types.hpp"
 
 namespace vsomeip {
 
 class configuration;
+class endpoint;
 
 namespace sd {
 
 class service_discovery_host {
-public:
-	virtual ~service_discovery_host() {};
+ public:
+  virtual ~service_discovery_host() {};
 
-	virtual boost::asio::io_service & get_io() = 0;
-	virtual std::shared_ptr<configuration> get_configuration() const = 0;
+  virtual boost::asio::io_service & get_io() = 0;
+  virtual std::shared_ptr<configuration> get_configuration() const = 0;
 
-	virtual void create_service_discovery_endpoint(const std::string &_address,
-			uint16_t _port, const std::string &_protocol) = 0;
+  virtual void create_service_discovery_endpoint(const std::string &_address,
+                                                 uint16_t _port,
+                                                 bool _reliable) = 0;
 
-	virtual service_map_t get_offered_services(
-			const std::string &_name) const = 0;
+  virtual services_t get_offered_services(const std::string &_name) const = 0;
+  virtual std::shared_ptr<eventgroupinfo> find_eventgroup(
+      service_t _service, instance_t _instance,
+      eventgroup_t _eventgroup) const = 0;
 
-	virtual bool send(client_t _client, std::shared_ptr<message> _message,
-			bool _flush, bool _reliable) = 0;
+  virtual bool send(client_t _client, std::shared_ptr<message> _message,
+                    bool _flush, bool _reliable) = 0;
 
-	virtual void add_routing_info(service_t _service, instance_t _instance,
-			major_version_t _major, minor_version_t _minor, ttl_t _ttl,
-			const boost::asio::ip::address &_address, uint16_t _port,
-			bool _reliable) = 0;
+  virtual bool send_subscribe(const boost::asio::ip::address &_address,
+                              uint16_t _port, bool _reliable,
+                              const byte_t *_data, uint32_t _size) = 0;
 
-	virtual void del_routing_info(service_t _service, instance_t _instance,
-			bool _reliable) = 0;
+  virtual void add_routing_info(service_t _service, instance_t _instance,
+                                major_version_t _major, minor_version_t _minor,
+                                ttl_t _ttl,
+                                const boost::asio::ip::address &_address,
+                                uint16_t _port, bool _reliable) = 0;
+
+  virtual void del_routing_info(service_t _service, instance_t _instance,
+                                bool _reliable) = 0;
+
+  virtual void add_subscription(service_t _service, instance_t _instance,
+                                eventgroup_t _eventgroup,
+                                const boost::asio::ip::address &_address,
+                                uint16_t _reliable_port,
+                                uint16_t _unreliable_port) = 0;
+
+  virtual void del_subscription(service_t _service, instance_t _instance,
+                                eventgroup_t _eventgroup,
+                                const boost::asio::ip::address &_address,
+                                uint16_t _reliable_port,
+                                uint16_t _unreliable_port) = 0;
+
+  virtual std::shared_ptr<endpoint> find_remote_client(service_t _service,
+                                                       instance_t _instance,
+                                                       bool _reliable) = 0;
 };
 
-} // namespace sd
-} // namespace vsomeip
+}  // namespace sd
+}  // namespace vsomeip
 
 #endif // VSOMEIP_SERVICE_DISCOVERY_HOST_HPP
diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp
index d1cb3e1..1393bdb 100644
--- a/implementation/service_discovery/include/service_discovery_impl.hpp
+++ b/implementation/service_discovery/include/service_discovery_impl.hpp
@@ -9,78 +9,123 @@
 
 #include <map>
 #include <memory>
+#include <mutex>
 #include <set>
 
+#include <boost/asio/ip/address.hpp>
+
 #include "service_discovery.hpp"
-#include "../../routing/include/routing_types.hpp"
+#include "../../routing/include/types.hpp"
 
 namespace vsomeip {
 
 class endpoint;
+class serializer;
 
 namespace sd {
 
+class entry_impl;
 class eventgroupentry_impl;
 class option_impl;
+class request;
 class serviceentry_impl;
 class service_discovery_fsm;
 class service_discovery_host;
+class subscription;
 
-class service_discovery_impl: public service_discovery,
-		public std::enable_shared_from_this<service_discovery_impl> {
-public:
-	service_discovery_impl(service_discovery_host *_host);
-	virtual ~service_discovery_impl();
+class service_discovery_impl : public service_discovery,
+    public std::enable_shared_from_this<service_discovery_impl> {
+ public:
+  service_discovery_impl(service_discovery_host *_host);
+  virtual ~service_discovery_impl();
 
-	std::shared_ptr<configuration> get_configuration() const;
-	boost::asio::io_service & get_io();
+  std::shared_ptr<configuration> get_configuration() const;
+  boost::asio::io_service & get_io();
 
-	void init();
-	void start();
-	void stop();
+  void init();
+  void start();
+  void stop();
 
-	void request_service(service_t _service, instance_t _instance,
-			major_version_t _major, minor_version_t _minor, ttl_t _ttl);
-	void release_service(service_t _service, instance_t _instance);
+  void request_service(service_t _service, instance_t _instance,
+                       major_version_t _major, minor_version_t _minor,
+                       ttl_t _ttl);
+  void release_service(service_t _service, instance_t _instance);
 
-	void subscribe(service_t _service, instance_t _instance,
-			eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl);
-	void unsubscribe(service_t _service, instance_t _instance,
-			eventgroup_t _eventgroup);
+  void subscribe(service_t _service, instance_t _instance,
+                 eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl);
+  void unsubscribe(service_t _service, instance_t _instance,
+                   eventgroup_t _eventgroup);
 
-	void send(const std::string &_name, bool _is_announcing);
+  void send(const std::string &_name, bool _is_announcing);
 
-	void on_message(const byte_t *_data, length_t _length);
+  void on_message(const byte_t *_data, length_t _length);
 
-private:
-	void insert_service_option(std::shared_ptr<message_impl> &_message,
-			std::shared_ptr<serviceentry_impl> &_entry,
-			std::shared_ptr<endpoint> _endpoint);
-	void insert_service_entries(std::shared_ptr<message_impl> &_message,
-			service_map_t &_services, bool _is_offer);
+ private:
+  void 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);
+  void insert_service_entries(std::shared_ptr<message_impl> &_message,
+                              services_t &_services, bool _is_offer);
+  void insert_subscription(std::shared_ptr<message_impl> &_message,
+                           service_t _service, instance_t _instance,
+                           eventgroup_t _eventgroup,
+                           std::shared_ptr<subscription> &_subscription,
+                           bool _is_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,
+                               bool _is_subscription);
 
-	void process_serviceentry(std::shared_ptr<serviceentry_impl> &_entry,
-			const std::vector<std::shared_ptr<option_impl> > &_options);
-	void process_eventgroupentry(std::shared_ptr<eventgroupentry_impl> &_entry,
-			const std::vector<std::shared_ptr<option_impl> > &_options);
+  void process_serviceentry(
+      std::shared_ptr<serviceentry_impl> &_entry,
+      const std::vector<std::shared_ptr<option_impl> > &_options);
+  void process_eventgroupentry(
+      std::shared_ptr<eventgroupentry_impl> &_entry,
+      const std::vector<std::shared_ptr<option_impl> > &_options);
 
-private:
-	boost::asio::io_service &io_;
-	service_discovery_host *host_;
+  void handle_service_availability(service_t _service, instance_t _instance,
+                                   major_version_t _major,
+                                   minor_version_t _minor, ttl_t _ttl,
+                                   const boost::asio::ip::address &_address,
+                                   uint16_t _port, bool _reliable);
+  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);
+  void handle_eventgroup_subscription_ack(
+      service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+      major_version_t _major, ttl_t _ttl,
+      const boost::asio::ip::address &_address, uint16_t _port);
 
-	std::shared_ptr<deserializer> deserializer_;
+ private:
+  boost::asio::io_service &io_;
+  service_discovery_host *host_;
 
-	std::shared_ptr<service_discovery_fsm> default_;
-	std::map<std::string, std::shared_ptr<service_discovery_fsm> > additional_;
+  boost::asio::ip::address unicast_;
+  uint16_t port_;
+  bool reliable_;
 
-	service_map_t requested_;
-	eventgroup_map_t subscribed_;
+  std::shared_ptr<serializer> serializer_;
+  std::shared_ptr<deserializer> deserializer_;
 
-	// Sessions
-	// TODO: handle session id per unicast peer and multicast
+  std::shared_ptr<service_discovery_fsm> default_;
+  std::map<std::string, std::shared_ptr<service_discovery_fsm> > additional_;
+
+  std::map<service_t, std::map<instance_t, std::shared_ptr<request> > > requested_;
+  std::map<service_t,
+      std::map<instance_t,
+          std::map<eventgroup_t, std::shared_ptr<subscription> > > > subscribed_;
+
+  std::mutex serialize_mutex_;
+
+  // Sessions
+  std::map<boost::asio::ip::address, session_t> sessions_;
 };
 
-} // namespace sd
-} // namespace vsomeip
+}  // namespace sd
+}  // namespace vsomeip
 
 #endif // VSOMEIP_SERVICE_DISCOVERY_IMPL
diff --git a/implementation/service_discovery/include/subscription.hpp b/implementation/service_discovery/include/subscription.hpp
new file mode 100644
index 0000000..098bccf
--- /dev/null
+++ b/implementation/service_discovery/include/subscription.hpp
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 BMW Group
+// Author: Lutz Bichler (lutz.bichler@bmw.de)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_SD_SUBSCRIPTION_HPP
+#define VSOMEIP_SD_SUBSCRIPTION_HPP
+
+#include <memory>
+
+#include <vsomeip/primitive_types.hpp>
+
+namespace vsomeip {
+
+class endpoint;
+
+namespace sd {
+
+class subscription {
+public:
+	subscription(major_version_t _major, ttl_t _ttl,
+			std::shared_ptr<endpoint> _reliable,
+			std::shared_ptr<endpoint> _unreliable);
+	~subscription();
+
+	major_version_t get_major() const;
+	ttl_t get_ttl() const;
+	void set_ttl(ttl_t _ttl);
+	std::shared_ptr<endpoint> get_endpoint(bool _reliable) const;
+	void set_endpoint(std::shared_ptr<endpoint> _endpoint, bool _reliable);
+
+	bool is_acknowleged() const;
+	void set_acknowledged(bool _is_acknowledged);
+
+private:
+	major_version_t major_;
+	ttl_t ttl_;
+
+	std::shared_ptr<endpoint> reliable_;
+	std::shared_ptr<endpoint> unreliable_;
+
+	bool is_acknowledged_;
+};
+
+} // namespace sd
+} // namespace vsomeip
+
+#endif // VSOMEIP_SD_SUBSCRIPTION_HPP
diff --git a/implementation/service_discovery/src/request.cpp b/implementation/service_discovery/src/request.cpp
new file mode 100644
index 0000000..2637a3f
--- /dev/null
+++ b/implementation/service_discovery/src/request.cpp
@@ -0,0 +1,44 @@
+// Copyright (C) 2014 BMW Group
+// Author: Lutz Bichler (lutz.bichler@bmw.de)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/request.hpp"
+
+namespace vsomeip {
+namespace sd {
+
+request::request(major_version_t _major, minor_version_t _minor, ttl_t _ttl)
+    : major_(_major),
+      minor_(_minor),
+      ttl_(_ttl) {
+
+}
+
+major_version_t request::get_major() const {
+  return major_;
+}
+
+void request::set_major(major_version_t _major) {
+  major_ = _major;
+}
+
+minor_version_t request::get_minor() const {
+  return minor_;
+}
+
+void request::set_minor(minor_version_t _minor) {
+  minor_ = _minor;
+}
+
+ttl_t request::get_ttl() const {
+  return ttl_;
+}
+
+void request::set_ttl(ttl_t _ttl) {
+  ttl_ = _ttl;
+}
+
+}  // namespace sd
+}  // namespace vsomeip
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index 4c44699..1f99c8a 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -15,335 +15,610 @@
 #include "../include/ipv4_option_impl.hpp"
 #include "../include/ipv6_option_impl.hpp"
 #include "../include/message_impl.hpp"
+#include "../include/request.hpp"
 #include "../include/runtime.hpp"
 #include "../include/service_discovery_fsm.hpp"
 #include "../include/service_discovery_host.hpp"
 #include "../include/service_discovery_impl.hpp"
 #include "../include/serviceentry_impl.hpp"
+#include "../include/subscription.hpp"
 #include "../../configuration/include/internal.hpp"
+#include "../../endpoints/include/endpoint.hpp"
 #include "../../endpoints/include/tcp_server_endpoint_impl.hpp"
 #include "../../endpoints/include/udp_server_endpoint_impl.hpp"
+#include "../../message/include/serializer.hpp"
+#include "../../routing/include/eventgroupinfo.hpp"
 #include "../../routing/include/servicegroup.hpp"
 #include "../../routing/include/serviceinfo.hpp"
 
 namespace vsomeip {
 namespace sd {
 
-service_discovery_impl::service_discovery_impl(service_discovery_host *_host) :
-		host_(_host), io_(_host->get_io()), default_(
-				std::make_shared < service_discovery_fsm > ("default", this)), deserializer_(
-				std::make_shared<deserializer>()) {
+service_discovery_impl::service_discovery_impl(service_discovery_host *_host)
+    : host_(_host),
+      io_(_host->get_io()),
+      default_(std::make_shared < service_discovery_fsm > ("default", this)),
+      serializer_(std::make_shared<serializer>()),
+      deserializer_(std::make_shared<deserializer>()) {
 }
 
 service_discovery_impl::~service_discovery_impl() {
 }
 
 std::shared_ptr<configuration> service_discovery_impl::get_configuration() const {
-	return host_->get_configuration();
+  return host_->get_configuration();
 }
 
 boost::asio::io_service & service_discovery_impl::get_io() {
-	return io_;
+  return io_;
 }
 
 void service_discovery_impl::init() {
-	std::shared_ptr<configuration> its_configuration =
-			host_->get_configuration();
-	if (its_configuration) {
-		std::set < std::string > its_servicegroups =
-				its_configuration->get_servicegroups();
-		for (auto its_group : its_servicegroups) {
-			if (its_group != "default"
-					&& its_configuration->is_local_servicegroup(its_group)) {
-				additional_[its_group] = std::make_shared
-						< service_discovery_fsm > (its_group, this);
-			}
-		}
-	} else {
-		VSOMEIP_ERROR << "SD: no configuration found!";
-	}
+  std::shared_ptr<configuration> its_configuration = host_->get_configuration();
+  if (its_configuration) {
+    unicast_ = its_configuration->get_unicast();
 
-	host_->create_service_discovery_endpoint(
-			its_configuration->get_service_discovery_multicast(),
-			its_configuration->get_service_discovery_port(),
-			its_configuration->get_service_discovery_protocol());
+    std::set < std::string > its_servicegroups = its_configuration
+        ->get_servicegroups();
+    for (auto its_group : its_servicegroups) {
+      if (its_group != "default"
+          && its_configuration->is_local_servicegroup(its_group)) {
+        additional_[its_group] = std::make_shared < service_discovery_fsm
+            > (its_group, this);
+      }
+    }
+
+    port_ = its_configuration->get_service_discovery_port();
+    reliable_ = (its_configuration->get_service_discovery_protocol() == "tcp");
+
+    serializer_->create_data(reliable_ ?
+    VSOMEIP_MAX_TCP_MESSAGE_SIZE :
+                                         VSOMEIP_MAX_UDP_MESSAGE_SIZE);
+
+    host_->create_service_discovery_endpoint(
+        its_configuration->get_service_discovery_multicast(), port_, reliable_);
+
+  } else {
+    VSOMEIP_ERROR << "SD: no configuration found!";
+  }
 }
 
 void service_discovery_impl::start() {
-	default_->start();
-	for (auto &its_group : additional_) {
-		its_group.second->start();
-	}
+  default_->start();
+  for (auto &its_group : additional_) {
+    its_group.second->start();
+  }
 
-	default_->process(ev_none());
-	for (auto &its_group : additional_) {
-		its_group.second->process(ev_none());
-	}
+  default_->process(ev_none());
+  for (auto &its_group : additional_) {
+    its_group.second->process(ev_none());
+  }
 }
 
 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) {
-	auto find_service = requested_.find(_service);
-	if (find_service != requested_.end()) {
-		auto find_instance = find_service->second.find(_instance);
-		if (find_instance != find_service->second.end()) {
-			// TODO: check version and report errors
-		} else {
-			find_service->second[_instance]
-			    = std::make_shared< serviceinfo>(_major, _minor, _ttl);
-		}
-	} else {
-		requested_[_service][_instance]
-		    = std::make_shared<serviceinfo>(_major, _minor, _ttl);
-	}
+                                             instance_t _instance,
+                                             major_version_t _major,
+                                             minor_version_t _minor,
+                                             ttl_t _ttl) {
+  auto find_service = requested_.find(_service);
+  if (find_service != requested_.end()) {
+    auto find_instance = find_service->second.find(_instance);
+    if (find_instance != find_service->second.end()) {
+      // TODO: check version and report errors
+    } else {
+      find_service->second[_instance]
+        = std::make_shared<request>(_major, _minor, _ttl);
+    }
+  } else {
+    requested_[_service][_instance]
+      = std::make_shared<request>(_major, _minor, _ttl);
+  }
 }
 
 void service_discovery_impl::release_service(service_t _service,
-		instance_t _instance) {
-	auto find_service = requested_.find(_service);
-	if (find_service != requested_.end()) {
-		find_service->second.erase(_instance);
-	}
+                                             instance_t _instance) {
+  auto find_service = requested_.find(_service);
+  if (find_service != requested_.end()) {
+    find_service->second.erase(_instance);
+  }
 }
 
 void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
-		eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl) {
-	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()) {
+                                       eventgroup_t _eventgroup,
+                                       major_version_t _major, ttl_t _ttl) {
+  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()) {
+        if (found_eventgroup->second->get_major() == _major) {
+          found_eventgroup->second->set_ttl(_ttl);
+        } else {
+          VSOMEIP_ERROR << "Subscriptions to different versions of the same "
+              "service instance are not supported!";
+        }
+        return;
+      }
+    }
+  }
 
-			} else {
-
-			}
-		} else {
-			// insert new subscription
-		}
-	} else {
-		// insert new subscription
-	}
+  std::shared_ptr<endpoint> its_reliable
+    = host_->find_remote_client(_service, _instance, true);
+  std::shared_ptr<endpoint> its_unreliable
+    = host_->find_remote_client(_service, _instance, false);
+  std::shared_ptr<subscription> its_subscription
+    = std::make_shared<subscription>(_major, _ttl,
+                                     its_reliable, its_unreliable);
+  subscribed_[_service][_instance][_eventgroup] = its_subscription;
 }
 
 void service_discovery_impl::unsubscribe(service_t _service,
-		instance_t _instance, eventgroup_t _eventgroup) {
-
+                                         instance_t _instance,
+                                         eventgroup_t _eventgroup) {
+  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()) {
+        found_eventgroup->second->set_ttl(0);  // is read once and removed afterwards!
+      }
+    }
+  }
 }
 
-void service_discovery_impl::insert_service_option(
-		std::shared_ptr<message_impl> &_message,
-		std::shared_ptr<serviceentry_impl> &_entry,
-		std::shared_ptr<endpoint> _endpoint) {
-
-	ipv4_address_t its_address;
-	if (_endpoint->get_address(its_address)) {
-		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(_endpoint->get_port());
-			its_option->set_udp(_endpoint->is_udp());
-			_entry->assign_option(its_option, 1);
-		}
-	} else {
-		ipv6_address_t its_address;
-		if (_endpoint->get_address(its_address)) {
-			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(_endpoint->get_port());
-				its_option->set_udp(_endpoint->is_udp());
-				_entry->assign_option(its_option, 1);
-			}
-		}
-	}
+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) {
+  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_udp(!_is_reliable);
+        _entry->assign_option(its_option, 1);
+      }
+    } 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_udp(!_is_reliable);
+        _entry->assign_option(its_option, 1);
+      }
+    }
+  } 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);
+        _entry->assign_option(its_option, 1);
+      }
+    } 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);
+        _entry->assign_option(its_option, 1);
+      }
+    }
+  }
 }
 
 void service_discovery_impl::insert_service_entries(
-		std::shared_ptr<message_impl> &_message, service_map_t &_services,
-		bool _is_offer) {
-	for (auto its_service : _services) {
-		for (auto its_instance : its_service.second) {
-			auto its_info = its_instance.second;
-			std::shared_ptr<serviceentry_impl> its_entry =
-					_message->create_service_entry();
-			if (its_entry) {
-				its_entry->set_type(
-						(_is_offer ?
-								entry_type_e::OFFER_SERVICE :
-								entry_type_e::FIND_SERVICE));
-				its_entry->set_service(its_service.first);
-				its_entry->set_instance(its_instance.first);
-				its_entry->set_major_version(its_info->get_major());
-				its_entry->set_minor_version(its_info->get_minor());
-				its_entry->set_ttl(its_info->get_ttl());
+    std::shared_ptr<message_impl> &_message, services_t &_services,
+    bool _is_offer) {
+  for (auto its_service : _services) {
+    for (auto its_instance : its_service.second) {
+      auto its_info = its_instance.second;
+      std::shared_ptr<serviceentry_impl> its_entry = _message
+          ->create_service_entry();
+      if (its_entry) {
+        its_entry->set_type(
+            (_is_offer ?
+                entry_type_e::OFFER_SERVICE : entry_type_e::FIND_SERVICE));
+        its_entry->set_service(its_service.first);
+        its_entry->set_instance(its_instance.first);
+        its_entry->set_major_version(its_info->get_major());
+        its_entry->set_minor_version(its_info->get_minor());
+        its_entry->set_ttl(its_info->get_ttl());
 
-				std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint(
-						true);
-				if (its_endpoint) {
-					insert_service_option(_message, its_entry, its_endpoint);
-					if (0 == its_info->get_ttl()) {
-						host_->del_routing_info(its_service.first,
-								its_instance.first, true);
-					}
-				}
+        std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint(true);
+        if (its_endpoint) {
+          insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), true);
+          if (0 == its_info->get_ttl()) {
+            host_->del_routing_info(its_service.first, its_instance.first,
+                                    true);
+          }
+        }
 
-				its_endpoint = its_info->get_endpoint(false);
-				if (its_endpoint) {
-					insert_service_option(_message, its_entry, its_endpoint);
-					if (0 == its_info->get_ttl()) {
-						host_->del_routing_info(its_service.first,
-								its_instance.first, false);
-					}
-				}
-			} else {
-				VSOMEIP_ERROR << "Failed to create service entry.";
-			}
-		}
-	}
+        its_endpoint = its_info->get_endpoint(false);
+        if (its_endpoint) {
+          insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), false);
+          if (0 == its_info->get_ttl()) {
+            host_->del_routing_info(its_service.first, its_instance.first,
+                                    false);
+          }
+        }
+      } else {
+        VSOMEIP_ERROR << "Failed to create service entry.";
+      }
+    }
+  }
+}
+
+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, bool _is_subscription) {
+  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_major_version(_subscription->get_major());
+  its_entry->set_ttl(_subscription->get_ttl());
+  std::shared_ptr<endpoint> its_endpoint = _subscription->get_endpoint(true);
+  if (its_endpoint) {
+    insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), true);
+  }
+  its_endpoint = _subscription->get_endpoint(false);
+  if (its_endpoint) {
+    insert_option(_message, its_entry, unicast_, its_endpoint->get_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, bool _is_subscription) {
+  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_ttl(_info->get_ttl());
+
+  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(const std::string &_name,
-		bool _is_announcing) {
-	std::shared_ptr<message_impl> its_message =
-			runtime::get()->create_message();
+                                  bool _is_announcing) {
+  std::shared_ptr<message_impl> its_message = runtime::get()->create_message();
 
-	// TODO: optimize building of SD message (common options, utilize the two runs)
+  // TODO: optimize building of SD message (common options, utilize the two runs)
 
-	// If we are the default group and not in main phase, include "FindOffer"-entries
-	if (_name == "default" && !_is_announcing) {
-		insert_service_entries(its_message, requested_, false);
-	}
+  // If we are the default group and not in main phase, include "FindOffer"-entries
+  if (_name == "default" && !_is_announcing) {
+    //insert_service_entries(its_message, requested_, false);
+  }
 
-	// Always include the "OfferService"-entries for the service group
-	service_map_t its_offers = host_->get_offered_services(_name);
-	insert_service_entries(its_message, its_offers, true);
+  // Always include the "OfferService"-entries for the service group
+  services_t its_offers = host_->get_offered_services(_name);
+  insert_service_entries(its_message, its_offers, true);
 
-	// Serialize and send
-	host_->send(VSOMEIP_SD_CLIENT, its_message, true, false);
+  // Serialize and send
+  if (its_message->get_entries().size() > 0)
+    host_->send(VSOMEIP_SD_CLIENT, its_message, true, false);
 }
 
 // Interface endpoint_host
 void service_discovery_impl::on_message(const byte_t *_data, length_t _length) {
 #if 0
-	std::stringstream msg;
-	msg << "sdi::on_message: ";
-	for (length_t i = 0; i < _length; ++i)
-	msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
-	VSOMEIP_DEBUG << msg.str();
+  std::stringstream msg;
+  msg << "sdi::on_message: ";
+  for (length_t i = 0; i < _length; ++i)
+  msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
+  VSOMEIP_DEBUG << msg.str();
 #endif
-	deserializer_->set_data(_data, _length);
-	std::shared_ptr<message_impl> its_message(
-			deserializer_->deserialize_sd_message());
-	if (its_message) {
-		std::vector < std::shared_ptr<option_impl> > its_options =
-				its_message->get_options();
-		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);
-			} else {
-				std::shared_ptr<eventgroupentry_impl> its_eventgroup_entry =
-						std::dynamic_pointer_cast < eventgroupentry_impl
-								> (its_entry);
-				process_eventgroupentry(its_eventgroup_entry, its_options);
-			}
-		}
-	}
+  deserializer_->set_data(_data, _length);
+  std::shared_ptr<message_impl> its_message(
+      deserializer_->deserialize_sd_message());
+  if (its_message) {
+    std::vector < std::shared_ptr<option_impl>
+        > its_options = its_message->get_options();
+    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);
+      } else {
+        std::shared_ptr<eventgroupentry_impl> its_eventgroup_entry =
+            std::dynamic_pointer_cast < eventgroupentry_impl > (its_entry);
+        process_eventgroupentry(its_eventgroup_entry, its_options);
+      }
+    }
+  }
 }
 
 // Entry processing
 void service_discovery_impl::process_serviceentry(
-		std::shared_ptr<serviceentry_impl> &_entry,
-		const std::vector<std::shared_ptr<option_impl> > &_options) {
-	service_t its_service = _entry->get_service();
-	instance_t its_instance = _entry->get_instance();
-	major_version_t its_major = _entry->get_major_version();
-	minor_version_t its_minor = _entry->get_minor_version();
-	ttl_t its_ttl = _entry->get_ttl();
+    std::shared_ptr<serviceentry_impl> &_entry,
+    const std::vector<std::shared_ptr<option_impl> > &_options) {
+  service_t its_service = _entry->get_service();
+  instance_t its_instance = _entry->get_instance();
+  major_version_t its_major = _entry->get_major_version();
+  minor_version_t its_minor = _entry->get_minor_version();
+  ttl_t its_ttl = _entry->get_ttl();
 
-	for (auto i : { 1, 2 }) {
-		for (auto its_index : _entry->get_options(i)) {
-			std::vector<byte_t> its_option_address;
-			uint16_t its_option_port = VSOMEIP_INVALID_PORT;
-			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);
+  for (auto i : { 1, 2 }) {
+    for (auto its_index : _entry->get_options(i)) {
+      std::vector<byte_t> its_option_address;
+      uint16_t its_option_port = VSOMEIP_INVALID_PORT;
+      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);
 
-				boost::asio::ip::address_v4 its_ipv4_address(
-						its_ipv4_option->get_address());
-				boost::asio::ip::address its_address(its_ipv4_address);
+          boost::asio::ip::address_v4 its_ipv4_address(
+              its_ipv4_option->get_address());
+          boost::asio::ip::address its_address(its_ipv4_address);
+          its_option_port = its_ipv4_option->get_port();
 
-				its_option_port = its_ipv4_option->get_port();
+          handle_service_availability(its_service, its_instance, its_major,
+                                      its_minor, its_ttl, its_address,
+                                      its_option_port,
+                                      !its_ipv4_option->is_udp());
+          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);
 
-				if (0 < its_ttl) {
-					host_->add_routing_info(its_service, its_instance,
-							its_major, its_minor, its_ttl, its_address,
-							its_option_port, !its_ipv4_option->is_udp());
-				} else {
-					host_->del_routing_info(its_service, its_instance,
-							!its_ipv4_option->is_udp());
-				}
-			}
-				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);
+          boost::asio::ip::address_v6 its_ipv6_address(
+              its_ipv6_option->get_address());
+          boost::asio::ip::address its_address(its_ipv6_address);
+          its_option_port = its_ipv6_option->get_port();
 
-				boost::asio::ip::address_v6 its_ipv6_address(
-						its_ipv6_option->get_address());
-				boost::asio::ip::address its_address(its_ipv6_address);
-
-				its_option_port = its_ipv6_option->get_port();
-
-				if (0 < its_ttl) {
-					host_->add_routing_info(its_service, its_instance,
-							its_major, its_minor, its_ttl, its_address,
-							its_option_port, !its_ipv6_option->is_udp());
-				} else {
-					host_->del_routing_info(its_service, its_instance,
-							!its_ipv6_option->is_udp());
-				}
-			}
-				break;
-			case option_type_e::IP4_MULTICAST:
-			case option_type_e::IP6_MULTICAST:
-				VSOMEIP_ERROR << "Invalid service option (Multicast)";
-				break;
-			default:
-				VSOMEIP_WARNING << "Unsupported service option";
-				break;
-			}
-		}
-	}
+          handle_service_availability(its_service, its_instance, its_major,
+                                      its_minor, its_ttl, its_address,
+                                      its_option_port,
+                                      !its_ipv6_option->is_udp());
+          break;
+        }
+        case option_type_e::IP4_MULTICAST:
+        case option_type_e::IP6_MULTICAST:
+          VSOMEIP_ERROR << "Invalid service option (Multicast)";
+          break;
+        default:
+          VSOMEIP_WARNING << "Unsupported service option";
+          break;
+      }
+    }
+  }
 }
 
 void service_discovery_impl::process_eventgroupentry(
-		std::shared_ptr<eventgroupentry_impl> &_entry,
-		const std::vector<std::shared_ptr<option_impl> > &_options) {
-	service_t its_service = _entry->get_service();
-	instance_t its_instance = _entry->get_instance();
-	eventgroup_t its_eventgroup = _entry->get_eventgroup();
-	major_version_t its_major = _entry->get_major_version();
-	ttl_t its_ttl = _entry->get_ttl();
+    std::shared_ptr<eventgroupentry_impl> &_entry,
+    const std::vector<std::shared_ptr<option_impl> > &_options) {
+  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();
 
-	VSOMEIP_DEBUG << "Eventgroup [" << std::hex << std::setw(4)
-			<< std::setfill('0') << its_service << "." << its_instance << "."
-			<< its_eventgroup << "], version " << std::dec << (int) its_major
-			<< " is offered for " << its_ttl << " seconds.";
+  boost::asio::ip::address its_reliable_address;
+  uint16_t its_reliable_port = VSOMEIP_INVALID_PORT;
+  boost::asio::ip::address its_unreliable_address;
+  uint16_t its_unreliable_port = VSOMEIP_INVALID_PORT;
+
+  for (auto i : { 1, 2 }) {
+    for (auto its_index : _entry->get_options(i)) {
+      std::vector<byte_t> its_option_address;
+      std::shared_ptr<option_impl> its_option = _options[its_index];
+      switch (its_option->get_type()) {
+        case option_type_e::IP4_ENDPOINT: {
+          if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) {
+            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());
+
+            // TODO: add error handling (port already set) here
+            if (its_ipv4_option->is_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();
+            }
+          } else {
+            VSOMEIP_ERROR << "Invalid eventgroup option (IPv4 Endpoint)";
+          }
+          break;
+        }
+        case option_type_e::IP6_ENDPOINT: {
+          if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) {
+            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());
+
+            // TODO: add error handling (port already set) here
+            if (its_ipv6_option->is_udp()) {
+              its_unreliable_address = its_ipv6_address;
+              its_unreliable_port = its_ipv6_option->get_port();
+            } else {
+              its_unreliable_address = its_ipv6_address;
+              its_reliable_port = its_ipv6_option->get_port();
+            }
+          } else {
+            VSOMEIP_ERROR << "Invalid eventgroup option (IPv6 Endpoint)";
+          }
+          break;
+        }
+        case option_type_e::IP4_MULTICAST:
+          if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == _entry->get_type()) {
+            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());
+
+            its_unreliable_address = its_ipv4_address;
+            its_unreliable_port = its_ipv4_option->get_port();
+          } else {
+            VSOMEIP_ERROR << "Invalid eventgroup option (IPv4 Multicast)";
+          }
+          break;
+        case option_type_e::IP6_MULTICAST:
+          if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == _entry->get_type()) {
+            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());
+
+            its_unreliable_address = its_ipv6_address;
+            its_unreliable_port = its_ipv6_option->get_port();
+          } else {
+            VSOMEIP_ERROR << "Invalid eventgroup option (IPv6 Multicast)";
+          }
+          break;
+        default:
+          VSOMEIP_WARNING << "Unsupported eventgroup option";
+          break;
+      }
+    }
+  }
+
+  if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) {
+    handle_eventgroup_subscription(
+        its_service,
+        its_instance,
+        its_eventgroup,
+        its_major,
+        its_ttl,
+        (its_reliable_port != VSOMEIP_INVALID_PORT ?
+            its_reliable_address : its_unreliable_address),
+        its_reliable_port, its_unreliable_port);
+  } else {
+    handle_eventgroup_subscription_ack(its_service, its_instance,
+                                       its_eventgroup, its_major, its_ttl,
+                                       its_unreliable_address,
+                                       its_unreliable_port);
+  }
 }
 
-} // namespace sd
-} // namespace vsomeip
+void service_discovery_impl::handle_service_availability(
+    service_t _service, instance_t _instance, major_version_t _major,
+    minor_version_t _minor, ttl_t _ttl,
+    const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) {
+
+  if (0 < _ttl) {
+    host_->add_routing_info(_service, _instance, _major, _minor, _ttl, _address,
+                            _port, _reliable);
+
+    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 = runtime::get()
+              ->create_message();
+          for (auto its_eventgroup : found_instance->second) {
+            std::shared_ptr<subscription> its_subscription(its_eventgroup.second);
+            if (!its_subscription->is_acknowleged()) {
+              its_subscription->set_endpoint(
+                  host_->find_remote_client(_service, _instance, true), true);
+              its_subscription->set_endpoint(
+                  host_->find_remote_client(_service, _instance, false), false);
+
+              // TODO: consume major & ttl
+              insert_subscription(its_message, _service, _instance,
+                                  its_eventgroup.first, its_subscription, true);
+            }
+          }
+          serializer_->serialize(its_message.get());
+          host_->send_subscribe(_address, port_, reliable_,
+                                serializer_->get_data(),
+                                serializer_->get_size());
+          serializer_->reset();
+        }
+      }
+    }
+  } else {
+    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 &its_eventgroup : found_instance->second) {
+          its_eventgroup.second->set_acknowledged(false);
+        }
+      }
+    }
+    host_->del_routing_info(_service, _instance, _reliable);
+  }
+}
+
+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) {
+  std::shared_ptr<message_impl> its_message = runtime::get()->create_message();
+  if (its_message) {
+    std::shared_ptr<eventgroupinfo> its_info
+      = host_->find_eventgroup(_service, _instance, _eventgroup);
+
+    // Could not find eventgroup --> send Nack
+    if (!its_info || _major > its_info->get_major()
+        || _ttl > its_info->get_ttl()) {
+    } else {
+      host_->add_subscription(_service, _instance, _eventgroup, _address,
+                              _reliable_port, _unreliable_port);
+    }
+
+    insert_subscription_ack(its_message, _service, _instance, _eventgroup,
+                            its_info, false);
+
+    serializer_->serialize(its_message.get());
+    host_->send_subscribe(_address, port_, reliable_, serializer_->get_data(),
+                          serializer_->get_size());
+    serializer_->reset();
+  }
+}
+
+void service_discovery_impl::handle_eventgroup_subscription_ack(
+    service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+    major_version_t _major, ttl_t _ttl,
+    const boost::asio::ip::address &_address, uint16_t _port) {
+  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()) {
+        found_eventgroup->second->set_acknowledged(true);
+      }
+    }
+  }
+}
+
+}  // namespace sd
+}  // namespace vsomeip
diff --git a/implementation/service_discovery/src/subscription.cpp b/implementation/service_discovery/src/subscription.cpp
new file mode 100644
index 0000000..19d115c
--- /dev/null
+++ b/implementation/service_discovery/src/subscription.cpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2014 BMW Group
+// Author: Lutz Bichler (lutz.bichler@bmw.de)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/subscription.hpp"
+
+namespace vsomeip {
+namespace sd {
+
+subscription::subscription(major_version_t _major, ttl_t _ttl,
+                           std::shared_ptr<endpoint> _reliable,
+                               std::shared_ptr<endpoint> _unreliable)
+    : major_(_major),
+      ttl_(_ttl),
+      reliable_(_reliable),
+      unreliable_(_unreliable),
+      is_acknowledged_(false) {
+}
+
+subscription::~subscription() {
+}
+
+major_version_t subscription::get_major() const {
+  return major_;
+}
+
+ttl_t subscription::get_ttl() const {
+  return ttl_;
+}
+
+void subscription::set_ttl(ttl_t _ttl) {
+  ttl_ = _ttl;
+}
+
+std::shared_ptr<endpoint> subscription::get_endpoint(bool _reliable) const {
+  return (_reliable ? reliable_ : unreliable_);
+}
+
+void subscription::set_endpoint(std::shared_ptr<endpoint> _endpoint,
+                                  bool _reliable) {
+  if (_reliable)
+    reliable_ = _endpoint;
+  else
+    unreliable_ = _endpoint;
+}
+
+bool subscription::is_acknowleged() const {
+  return is_acknowledged_;
+}
+
+void subscription::set_acknowledged(bool _is_acknowledged) {
+  is_acknowledged_ = _is_acknowledged;
+}
+
+} // namespace sd
+} // namespace vsomeip
diff --git a/implementation/message/include/byteorder.hpp b/implementation/utility/include/byteorder.hpp
similarity index 100%
rename from implementation/message/include/byteorder.hpp
rename to implementation/utility/include/byteorder.hpp
diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp
index 5fe2ed4..e9b4e9d 100644
--- a/implementation/utility/include/utility.hpp
+++ b/implementation/utility/include/utility.hpp
@@ -33,6 +33,8 @@
 					_type <= message_type_e::REQUEST_NO_RETURN_ACK));
 	}
 
+	static bool is_notification(const byte_t *_data);
+
 	static uint32_t get_message_size(std::vector< byte_t > &_data);
 
 	static bool exists(const std::string &_path);
diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp
index 339503a..e9164c0 100644
--- a/implementation/utility/src/utility.cpp
+++ b/implementation/utility/src/utility.cpp
@@ -10,38 +10,44 @@
 #include <vsomeip/defines.hpp>
 #include <vsomeip/logger.hpp>
 
+#include "../include/byteorder.hpp"
 #include "../include/utility.hpp"
-#include "../../message/include/byteorder.hpp"
 
 namespace vsomeip {
 
-uint32_t utility::get_message_size(std::vector< byte_t > &_data) {
-	uint32_t its_size(0);
-	if (VSOMEIP_SOMEIP_HEADER_SIZE <= _data.size()) {
-		its_size = VSOMEIP_SOMEIP_HEADER_SIZE +
-				   VSOMEIP_BYTES_TO_LONG(
-						   _data[4], _data[5], _data[6], _data[7]);
-	}
-	return its_size;
+bool utility::is_notification(const byte_t *_data) {
+  return (0 == _data[VSOMEIP_CLIENT_POS_MIN]
+      && 0 == _data[VSOMEIP_CLIENT_POS_MAX]
+      && 0 == _data[VSOMEIP_SESSION_POS_MIN]
+      && 0 == _data[VSOMEIP_SESSION_POS_MAX]);
 }
 
-void * utility::load_library(const std::string &_path, const std::string &_symbol) {
-	void * its_symbol = 0;
-
-	void *handle = dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
-	if (0 != handle) {
-		its_symbol = dlsym(handle, _symbol.c_str());
-	} else {
-		VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")";
-	}
-
-	return its_symbol;
+uint32_t utility::get_message_size(std::vector<byte_t> &_data) {
+  uint32_t its_size(0);
+  if (VSOMEIP_SOMEIP_HEADER_SIZE <= _data.size()) {
+    its_size = VSOMEIP_SOMEIP_HEADER_SIZE
+        + VSOMEIP_BYTES_TO_LONG(_data[4], _data[5], _data[6], _data[7]);
+  }
+  return its_size;
 }
 
+void * utility::load_library(const std::string &_path,
+                             const std::string &_symbol) {
+  void * its_symbol = 0;
+
+  void *handle = dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
+  if (0 != handle) {
+    its_symbol = dlsym(handle, _symbol.c_str());
+  } else {
+    VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")";
+  }
+
+  return its_symbol;
+}
 
 bool utility::exists(const std::string &_path) {
-	struct stat its_stat;
-	return (stat(_path.c_str(), &its_stat) == 0);
+  struct stat its_stat;
+  return (stat(_path.c_str(), &its_stat) == 0);
 }
 
-} // namespace vsomeip
+}  // namespace vsomeip
diff --git a/interface/vsomeip/configuration.hpp b/interface/vsomeip/configuration.hpp
index 999210e..16815ff 100644
--- a/interface/vsomeip/configuration.hpp
+++ b/interface/vsomeip/configuration.hpp
@@ -7,6 +7,8 @@
 #ifndef VSOMEIP_CONFIGURATION_HPP
 #define VSOMEIP_CONFIGURATION_HPP
 
+#include <map>
+#include <memory>
 #include <set>
 #include <string>
 
@@ -18,6 +20,8 @@
 
 namespace vsomeip {
 
+class event;
+
 class configuration {
 public:
 	static configuration * get(const std::string &_path = VSOMEIP_DEFAULT_CONFIGURATION_FILE_PATH);
@@ -53,13 +57,20 @@
 	virtual int32_t get_cyclic_offer_delay(const std::string &_name) const = 0;
 	virtual int32_t get_cyclic_request_delay(const std::string &_name) const = 0;
 
-	virtual std::string get_address(service_t _service, instance_t _instance) const = 0;
+	virtual std::string get_unicast(service_t _service, instance_t _instance) const = 0;
+	virtual std::string get_multicast_address(service_t _service, instance_t _instance) const = 0;
+	virtual uint16_t get_multicast_port(service_t _service, instance_t _instance) const = 0;
+	virtual uint16_t get_multicast_group(service_t _service, instance_t _instance) const = 0;
 	virtual uint16_t get_reliable_port(service_t _service, instance_t _instance) const = 0;
 	virtual bool has_enabled_magic_cookies(std::string _address, uint16_t _port) const = 0;
 	virtual uint16_t get_unreliable_port(service_t _service, instance_t _instance) const = 0;
 
 	virtual std::set< std::pair< service_t, instance_t > > get_remote_services() const = 0;
 
+	virtual std::map<service_t, std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > get_eventgroups() const = 0;
+	virtual std::map<service_t, std::map<instance_t, std::set<event_t> > > get_events() const = 0;
+	virtual void set_event(std::shared_ptr<event> &_event) const = 0;
+
 	virtual client_t get_id(const std::string &_name) const = 0;
 };
 
diff --git a/interface/vsomeip/defines.hpp b/interface/vsomeip/defines.hpp
index a1267a0..3fa199f 100644
--- a/interface/vsomeip/defines.hpp
+++ b/interface/vsomeip/defines.hpp
@@ -19,7 +19,7 @@
 #define VSOMEIP_MAX_TCP_MESSAGE_SIZE		4095
 #define VSOMEIP_MAX_UDP_MESSAGE_SIZE		1446
 
-#define VSOMEIP_PACKET_SIZE					100
+#define VSOMEIP_PACKET_SIZE					VSOMEIP_MAX_UDP_MESSAGE_SIZE
 
 #define VSOMEIP_SOMEIP_HEADER_SIZE			8
 #define VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE	8
diff --git a/interface/vsomeip/event.hpp b/interface/vsomeip/event.hpp
deleted file mode 100644
index cd50064..0000000
--- a/interface/vsomeip/event.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2014 BMW Group
-// Author: Lutz Bichler (lutz.bichler@bmw.de)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_EVENT_HPP
-#define VSOMEIP_EVENT_HPP
-
-#include <chrono>
-#include <memory>
-
-#include <vsomeip/primitive_types.hpp>
-
-namespace vsomeip {
-
-class payload;
-
-class event {
-public:
-	virtual ~event() {};
-
-	virtual service_t get_service() const = 0;
-	virtual void set_service(service_t _service) = 0;
-
-	virtual instance_t get_instance() const = 0;
-	virtual void set_instance(instance_t _instance) = 0;
-
-	virtual event_t get_event() const = 0;
-	virtual void set_event(event_t _event) = 0;
-
-	virtual std::shared_ptr< payload > get_payload() const = 0;
-	virtual void set_payload(std::shared_ptr< payload > _payload) = 0;
-
-	virtual void set_update_on_change(bool _is_on) = 0;
-	virtual void set_update_cycle(std::chrono::milliseconds &_cycle) = 0;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_EVENT_HPP
-
diff --git a/test/configuration-test.cpp b/test/configuration-test.cpp
index 9deed47..ba82ad6 100644
--- a/test/configuration-test.cpp
+++ b/test/configuration-test.cpp
@@ -134,7 +134,7 @@
 	check<uint16_t>(its_reliable, DESIRED_RELIABLE_2277_0022, "RELIABLE_TEST_2277_0022");
 	check<uint16_t>(its_unreliable, DESIRED_UNRELIABLE_2277_0022, "UNRELIABLE_TEST_2277_0022");
 
-	std::string its_address_s = its_configuration->get_address(0x1234, 0x0022);
+	std::string its_address_s = its_configuration->get_unicast(0x1234, 0x0022);
 	std::string its_group_name = its_configuration->get_group(0x1234, 0x0022);
 	uint32_t its_min_initial_delay = its_configuration->get_min_initial_delay(its_group_name);
 	uint32_t its_max_initial_delay = its_configuration->get_max_initial_delay(its_group_name);
@@ -196,7 +196,7 @@
 	check<uint32_t>(its_cyclic_offer_delay, DESIRED_CYCLIC_OFFER_DELAY_2277_0022, "CYCLIC_OFFER_DELAY_TEST_2266_0022");
 	check<uint32_t>(its_cyclic_request_delay, DESIRED_CYCLIC_REQUEST_DELAY_2277_0022, "CYCLIC_REQUEST_DELAY_TEST_2266_0022");
 
-	its_address_s = its_configuration->get_address(0x4466, 0x0321);
+	its_address_s = its_configuration->get_unicast(0x4466, 0x0321);
 	check<std::string>(its_address_s, DESIRED_ADDRESS_4466_0321, "ADDRESS_TEST_4466_0321");
 
 	// 5. Service discovery