• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 
6 #include <iomanip>
7 #include <sstream>
8 
9 #include <boost/asio/ip/multicast.hpp>
10 #include <vsomeip/internal/logger.hpp>
11 
12 #include "../include/endpoint_host.hpp"
13 #include "../include/tp.hpp"
14 #include "../../routing/include/routing_host.hpp"
15 #include "../include/udp_client_endpoint_impl.hpp"
16 #include "../../utility/include/utility.hpp"
17 #include "../../utility/include/byteorder.hpp"
18 
19 
20 namespace vsomeip_v3 {
21 
udp_client_endpoint_impl(const std::shared_ptr<endpoint_host> & _endpoint_host,const std::shared_ptr<routing_host> & _routing_host,const endpoint_type & _local,const endpoint_type & _remote,boost::asio::io_service & _io,const std::shared_ptr<configuration> & _configuration)22 udp_client_endpoint_impl::udp_client_endpoint_impl(
23         const std::shared_ptr<endpoint_host>& _endpoint_host,
24         const std::shared_ptr<routing_host>& _routing_host,
25         const endpoint_type& _local,
26         const endpoint_type& _remote,
27         boost::asio::io_service &_io,
28         const std::shared_ptr<configuration>& _configuration)
29     : udp_client_endpoint_base_impl(_endpoint_host, _routing_host, _local,
30                                     _remote, _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE,
31                                     _configuration->get_endpoint_queue_limit(
32                                             _remote.address().to_string(),
33                                             _remote.port()),
34                                     _configuration),
35       remote_address_(_remote.address()),
36       remote_port_(_remote.port()),
37       udp_receive_buffer_size_(_configuration->get_udp_receive_buffer_size()),
38       tp_reassembler_(std::make_shared<tp::tp_reassembler>(
39               _configuration->get_max_message_size_unreliable(), _io)) {
40     is_supporting_someip_tp_ = true;
41 }
42 
~udp_client_endpoint_impl()43 udp_client_endpoint_impl::~udp_client_endpoint_impl() {
44     std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
45     if (its_host) {
46         its_host->release_port(local_.port(), false);
47     }
48     tp_reassembler_->stop();
49 }
50 
is_local() const51 bool udp_client_endpoint_impl::is_local() const {
52     return false;
53 }
54 
connect()55 void udp_client_endpoint_impl::connect() {
56     std::lock_guard<std::mutex> its_lock(socket_mutex_);
57     boost::system::error_code its_error;
58     socket_->open(remote_.protocol(), its_error);
59     if (!its_error || its_error == boost::asio::error::already_open) {
60         // Enable SO_REUSEADDR to avoid bind problems with services going offline
61         // and coming online again and the user has specified only a small number
62         // of ports in the clients section for one service instance
63         socket_->set_option(boost::asio::socket_base::reuse_address(true), its_error);
64         if (its_error) {
65             VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't enable "
66                     << "SO_REUSEADDR: " << its_error.message()
67                     << " local port:" << std::dec << local_.port()
68                     << " remote:" << get_address_port_remote();
69         }
70 
71         socket_->set_option(boost::asio::socket_base::receive_buffer_size(
72                 udp_receive_buffer_size_), its_error);
73         if (its_error) {
74             VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't set "
75                     << "SO_RCVBUF: " << its_error.message()
76                     << " to: " << std::dec << udp_receive_buffer_size_
77                     << " local port:" << std::dec << local_.port()
78                     << " remote:" << get_address_port_remote();
79         }
80 
81         boost::asio::socket_base::receive_buffer_size its_option;
82         socket_->get_option(its_option, its_error);
83     #ifdef __linux__
84         // If regular setting of the buffer size did not work, try to force
85         // (requires CAP_NET_ADMIN to be successful)
86         if (its_option.value() < 0
87                 || its_option.value() < udp_receive_buffer_size_) {
88             its_error.assign(setsockopt(socket_->native_handle(),
89                         SOL_SOCKET, SO_RCVBUFFORCE,
90                         &udp_receive_buffer_size_, sizeof(udp_receive_buffer_size_)),
91                     boost::system::generic_category());
92             if (!its_error) {
93                 VSOMEIP_INFO << "udp_client_endpoint_impl::connect: "
94                         << "SO_RCVBUFFORCE successful!";
95             }
96             socket_->get_option(its_option, its_error);
97         }
98     #endif
99         if (its_error) {
100             VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't get "
101                     << "SO_RCVBUF: " << its_error.message()
102                     << " local port:" << std::dec << local_.port()
103                      << " remote:" << get_address_port_remote();
104         } else {
105             VSOMEIP_INFO << "udp_client_endpoint_impl::connect: SO_RCVBUF is: "
106                     << std::dec << its_option.value()
107                     << " (" << udp_receive_buffer_size_ << ")"
108                     << " local port:" << std::dec << local_.port()
109                     << " remote:" << get_address_port_remote();
110         }
111 
112 #ifndef _WIN32
113         // If specified, bind to device
114         std::string its_device(configuration_->get_device());
115         if (its_device != "") {
116             if (setsockopt(socket_->native_handle(),
117                     SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (socklen_t)its_device.size()) == -1) {
118                 VSOMEIP_WARNING << "UDP Client: Could not bind to device \"" << its_device << "\"";
119             }
120         }
121 #endif
122 
123         // In case a client endpoint port was configured,
124         // bind to it before connecting
125         if (local_.port() != ILLEGAL_PORT) {
126             boost::system::error_code its_bind_error;
127             socket_->bind(local_, its_bind_error);
128             if(its_bind_error) {
129                 VSOMEIP_WARNING << "udp_client_endpoint::connect: "
130                         "Error binding socket: " << its_bind_error.message()
131                         << " local: " << local_.address().to_string()
132                         << ":" << std::dec << local_.port()
133                         << " remote:" << get_address_port_remote();
134 
135                 std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
136                 if (its_host) {
137                     // set new client port depending on service / instance / remote port
138                     if (!its_host->on_bind_error(shared_from_this(), remote_port_)) {
139                         VSOMEIP_WARNING << "udp_client_endpoint::connect: "
140                                 "Failed to set new local port for uce: "
141                                 << " local: " << local_.address().to_string()
142                                 << ":" << std::dec << local_.port()
143                                 << " remote:" << get_address_port_remote();
144                     } else {
145                         local_.port(local_port_);
146                         VSOMEIP_INFO << "udp_client_endpoint::connect: "
147                                 "Using new new local port for uce: "
148                                 << " local: " << local_.address().to_string()
149                                 << ":" << std::dec << local_.port()
150                                 << " remote:" << get_address_port_remote();
151                     }
152                 }
153 
154 
155                 try {
156                     // don't connect on bind error to avoid using a random port
157                     strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
158                                     shared_from_this(), its_bind_error));
159                 } catch (const std::exception &e) {
160                     VSOMEIP_ERROR << "udp_client_endpoint_impl::connect: "
161                             << e.what() << " remote:" << get_address_port_remote();
162                 }
163                 return;
164             }
165             return;
166         }
167 
168         state_ = cei_state_e::CONNECTING;
169         socket_->async_connect(
170             remote_,
171             strand_.wrap(
172                 std::bind(
173                     &udp_client_endpoint_base_impl::connect_cbk,
174                     shared_from_this(),
175                     std::placeholders::_1
176                 )
177             )
178         );
179     } else {
180         VSOMEIP_WARNING << "udp_client_endpoint::connect: Error opening socket: "
181                 << its_error.message() << " remote:" << get_address_port_remote();
182         strand_.post(std::bind(&udp_client_endpoint_base_impl::connect_cbk,
183                         shared_from_this(), its_error));
184     }
185 }
186 
start()187 void udp_client_endpoint_impl::start() {
188     connect();
189 }
190 
restart(bool _force)191 void udp_client_endpoint_impl::restart(bool _force) {
192     if (!_force && state_ == cei_state_e::CONNECTING) {
193         return;
194     }
195     state_ = cei_state_e::CONNECTING;
196     {
197         std::lock_guard<std::mutex> its_lock(mutex_);
198         queue_.clear();
199     }
200     std::string local;
201     {
202         std::lock_guard<std::mutex> its_lock(socket_mutex_);
203         local = get_address_port_local();
204     }
205     shutdown_and_close_socket(false);
206     was_not_connected_ = true;
207     reconnect_counter_ = 0;
208     VSOMEIP_WARNING << "uce::restart: local: " << local
209             << " remote: " << get_address_port_remote();
210     start_connect_timer();
211 }
212 
send_queued(message_buffer_ptr_t _buffer)213 void udp_client_endpoint_impl::send_queued(message_buffer_ptr_t _buffer) {
214 #if 0
215     std::stringstream msg;
216     msg << "ucei<" << remote_.address() << ":"
217         << std::dec << remote_.port()  << ">::sq: ";
218     for (std::size_t i = 0; i < _buffer->size(); i++)
219         msg << std::hex << std::setw(2) << std::setfill('0')
220             << (int)(*_buffer)[i] << " ";
221     VSOMEIP_INFO << msg.str();
222 #endif
223     {
224         std::lock_guard<std::mutex> its_lock(socket_mutex_);
225         socket_->async_send(
226             boost::asio::buffer(*_buffer),
227             std::bind(
228                 &udp_client_endpoint_base_impl::send_cbk,
229                 shared_from_this(),
230                 std::placeholders::_1,
231                 std::placeholders::_2,
232                 _buffer
233             )
234         );
235     }
236 }
237 
get_configured_times_from_endpoint(service_t _service,method_t _method,std::chrono::nanoseconds * _debouncing,std::chrono::nanoseconds * _maximum_retention) const238 void udp_client_endpoint_impl::get_configured_times_from_endpoint(
239         service_t _service, method_t _method,
240         std::chrono::nanoseconds *_debouncing,
241         std::chrono::nanoseconds *_maximum_retention) const {
242     configuration_->get_configured_timing_requests(_service,
243             remote_address_.to_string(), remote_port_, _method,
244             _debouncing, _maximum_retention);
245 }
246 
receive()247 void udp_client_endpoint_impl::receive() {
248     std::lock_guard<std::mutex> its_lock(socket_mutex_);
249     if (!socket_->is_open()) {
250         return;
251     }
252     message_buffer_ptr_t its_buffer = std::make_shared<message_buffer_t>(VSOMEIP_MAX_UDP_MESSAGE_SIZE);
253     socket_->async_receive_from(
254         boost::asio::buffer(*its_buffer),
255         const_cast<endpoint_type&>(remote_),
256         strand_.wrap(
257             std::bind(
258                 &udp_client_endpoint_impl::receive_cbk,
259                 std::dynamic_pointer_cast<
260                     udp_client_endpoint_impl
261                 >(shared_from_this()),
262                 std::placeholders::_1,
263                 std::placeholders::_2,
264                 its_buffer
265             )
266         )
267     );
268 }
269 
get_remote_address(boost::asio::ip::address & _address) const270 bool udp_client_endpoint_impl::get_remote_address(
271         boost::asio::ip::address &_address) const {
272     if (remote_address_.is_unspecified()) {
273         return false;
274     }
275     _address = remote_address_;
276     return true;
277 }
278 
set_local_port()279 void udp_client_endpoint_impl::set_local_port() {
280     std::lock_guard<std::mutex> its_lock(socket_mutex_);
281     boost::system::error_code its_error;
282     if (socket_->is_open()) {
283         endpoint_type its_endpoint = socket_->local_endpoint(its_error);
284         if (!its_error) {
285             local_port_ = its_endpoint.port();
286         } else {
287             VSOMEIP_WARNING << "udp_client_endpoint_impl::set_local_port() "
288                     << " couldn't get local_endpoint: " << its_error.message();
289         }
290     }
291 }
292 
get_remote_port() const293 std::uint16_t udp_client_endpoint_impl::get_remote_port() const {
294     return remote_port_;
295 }
296 
receive_cbk(boost::system::error_code const & _error,std::size_t _bytes,const message_buffer_ptr_t & _recv_buffer)297 void udp_client_endpoint_impl::receive_cbk(
298         boost::system::error_code const &_error, std::size_t _bytes,
299         const message_buffer_ptr_t& _recv_buffer) {
300     if (_error == boost::asio::error::operation_aborted) {
301         // endpoint was stopped
302         return;
303     }
304     std::shared_ptr<routing_host> its_host = routing_host_.lock();
305     if (!_error && 0 < _bytes && its_host) {
306 #if 0
307         std::stringstream msg;
308         msg << "ucei::rcb(" << _error.message() << "): ";
309         for (std::size_t i = 0; i < _bytes; ++i)
310             msg << std::hex << std::setw(2) << std::setfill('0')
311                 << (int) (*_recv_buffer)[i] << " ";
312         VSOMEIP_INFO << msg.str();
313 #endif
314         std::size_t remaining_bytes = _bytes;
315         std::size_t i = 0;
316 
317         do {
318             uint64_t read_message_size
319                 = utility::get_message_size(&(*_recv_buffer)[i],
320                         remaining_bytes);
321             if (read_message_size > MESSAGE_SIZE_UNLIMITED) {
322                 VSOMEIP_ERROR << "Message size exceeds allowed maximum!";
323                 return;
324             }
325             uint32_t current_message_size = static_cast<uint32_t>(read_message_size);
326             if (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE &&
327                     current_message_size <= remaining_bytes) {
328                 if (remaining_bytes - current_message_size > remaining_bytes) {
329                     VSOMEIP_ERROR << "buffer underflow in udp client endpoint ~> abort!";
330                     return;
331                 } else if (current_message_size > VSOMEIP_RETURN_CODE_POS &&
332                     ((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
333                      !utility::is_valid_message_type(tp::tp::tp_flag_unset((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])) ||
334                      !utility::is_valid_return_code(static_cast<return_code_e>((*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS]))
335                     )) {
336                     if ((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
337                         VSOMEIP_ERROR << "uce: Wrong protocol version: 0x"
338                                 << std::hex << std::setw(2) << std::setfill('0')
339                                 << std::uint32_t((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS])
340                                 << " local: " << get_address_port_local()
341                                 << " remote: " << get_address_port_remote();
342                         // ensure to send back a message w/ wrong protocol version
343                         its_host->on_message(&(*_recv_buffer)[i],
344                                              VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
345                                              boost::asio::ip::address(),
346                                              VSOMEIP_ROUTING_CLIENT,
347                                              std::make_pair(ANY_UID, ANY_GID),
348                                              remote_address_,
349                                              remote_port_);
350                     } else if (!utility::is_valid_message_type(tp::tp::tp_flag_unset(
351                             (*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS]))) {
352                         VSOMEIP_ERROR << "uce: Invalid message type: 0x"
353                                 << std::hex << std::setw(2) << std::setfill('0')
354                                 << std::uint32_t((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])
355                                 << " local: " << get_address_port_local()
356                                 << " remote: " << get_address_port_remote();
357                     } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
358                             (*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS]))) {
359                         VSOMEIP_ERROR << "uce: Invalid return code: 0x"
360                                 << std::hex << std::setw(2) << std::setfill('0')
361                                 << std::uint32_t((*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS])
362                                 << " local: " << get_address_port_local()
363                                 << " remote: " << get_address_port_remote();
364                     }
365                     receive();
366                     return;
367                 } else if (tp::tp::tp_flag_is_set((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])) {
368                     const auto res = tp_reassembler_->process_tp_message(
369                             &(*_recv_buffer)[i], current_message_size,
370                             remote_address_, remote_port_);
371                     if (res.first) {
372                         its_host->on_message(&res.second[0],
373                                 static_cast<std::uint32_t>(res.second.size()),
374                                 this, boost::asio::ip::address(),
375                                 VSOMEIP_ROUTING_CLIENT,
376                                 std::make_pair(ANY_UID, ANY_GID),
377                                 remote_address_,
378                                 remote_port_);
379                     }
380                 } else {
381                     its_host->on_message(&(*_recv_buffer)[i], current_message_size,
382                             this, boost::asio::ip::address(),
383                             VSOMEIP_ROUTING_CLIENT,
384                             std::make_pair(ANY_UID, ANY_GID),
385                             remote_address_,
386                             remote_port_);
387                 }
388                 remaining_bytes -= current_message_size;
389             } else {
390                 VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad "
391                         "length field. Message size: " << current_message_size
392                         << " Bytes. From: " << remote_.address() << ":"
393                         << remote_.port() << ". Dropping message.";
394                 remaining_bytes = 0;
395             }
396             i += current_message_size;
397         } while (remaining_bytes > 0);
398     }
399     if (!_error) {
400         receive();
401     } else {
402         if (_error == boost::asio::error::connection_refused) {
403             VSOMEIP_WARNING << "uce::receive_cbk: local: " << get_address_port_local()
404                     << " remote: " << get_address_port_remote()
405                     << " error: " << _error.message();
406             std::shared_ptr<endpoint_host> its_ep_host = endpoint_host_.lock();
407             its_ep_host->on_disconnect(shared_from_this());
408             restart(false);
409         } else {
410             receive();
411         }
412     }
413 }
414 
get_address_port_remote() const415 const std::string udp_client_endpoint_impl::get_address_port_remote() const {
416     boost::system::error_code ec;
417     std::string its_address_port;
418     its_address_port.reserve(21);
419     boost::asio::ip::address its_address;
420     if (get_remote_address(its_address)) {
421         its_address_port += its_address.to_string();
422     }
423     its_address_port += ":";
424     its_address_port += std::to_string(remote_port_);
425     return its_address_port;
426 }
427 
get_address_port_local() const428 const std::string udp_client_endpoint_impl::get_address_port_local() const {
429     std::string its_address_port;
430     its_address_port.reserve(21);
431     boost::system::error_code ec;
432     if (socket_->is_open()) {
433         endpoint_type its_local_endpoint = socket_->local_endpoint(ec);
434         if (!ec) {
435             its_address_port += its_local_endpoint.address().to_string(ec);
436             its_address_port += ":";
437             its_address_port.append(std::to_string(its_local_endpoint.port()));
438         }
439     }
440     return its_address_port;
441 }
442 
print_status()443 void udp_client_endpoint_impl::print_status() {
444     std::size_t its_data_size(0);
445     std::size_t its_queue_size(0);
446     {
447         std::lock_guard<std::mutex> its_lock(mutex_);
448         its_queue_size = queue_.size();
449         its_data_size = queue_size_;
450     }
451     std::string local;
452     {
453         std::lock_guard<std::mutex> its_lock(socket_mutex_);
454         local = get_address_port_local();
455     }
456 
457     VSOMEIP_INFO << "status uce: " << local << " -> "
458             << get_address_port_remote()
459             << " queue: " << std::dec << its_queue_size
460             << " data: " << std::dec << its_data_size;
461 }
462 
get_remote_information() const463 std::string udp_client_endpoint_impl::get_remote_information() const {
464     boost::system::error_code ec;
465     return remote_.address().to_string(ec) + ":"
466             + std::to_string(remote_.port());
467 }
468 
send_cbk(boost::system::error_code const & _error,std::size_t _bytes,const message_buffer_ptr_t & _sent_msg)469 void udp_client_endpoint_impl::send_cbk(boost::system::error_code const &_error, std::size_t _bytes,
470                   const message_buffer_ptr_t &_sent_msg) {
471     (void)_bytes;
472     if (!_error) {
473         std::lock_guard<std::mutex> its_lock(mutex_);
474         if (queue_.size() > 0) {
475             queue_size_ -= queue_.front()->size();
476             queue_.pop_front();
477             auto its_buffer = get_front();
478             if (its_buffer)
479                 send_queued(its_buffer);
480         }
481     } else if (_error == boost::asio::error::broken_pipe) {
482         state_ = cei_state_e::CLOSED;
483         bool stopping(false);
484         {
485             std::lock_guard<std::mutex> its_lock(mutex_);
486             stopping = sending_blocked_;
487             if (stopping) {
488                 queue_.clear();
489                 queue_size_ = 0;
490             } else {
491                 service_t its_service(0);
492                 method_t its_method(0);
493                 client_t its_client(0);
494                 session_t its_session(0);
495                 if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
496                     its_service = VSOMEIP_BYTES_TO_WORD(
497                             (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
498                             (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
499                     its_method = VSOMEIP_BYTES_TO_WORD(
500                             (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
501                             (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
502                     its_client = VSOMEIP_BYTES_TO_WORD(
503                             (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
504                             (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
505                     its_session = VSOMEIP_BYTES_TO_WORD(
506                             (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
507                             (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
508                 }
509                 VSOMEIP_WARNING << "uce::send_cbk received error: "
510                         << _error.message() << " (" << std::dec
511                         << _error.value() << ") " << get_remote_information()
512                         << " " << std::dec << queue_.size()
513                         << " " << std::dec << queue_size_ << " ("
514                         << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
515                         << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
516                         << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
517                         << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
518             }
519         }
520         if (!stopping) {
521             print_status();
522         }
523         was_not_connected_ = true;
524         shutdown_and_close_socket(true);
525         strand_.dispatch(std::bind(&client_endpoint_impl::connect,
526                 this->shared_from_this()));
527     } else if (_error == boost::asio::error::not_connected
528             || _error == boost::asio::error::bad_descriptor
529             || _error == boost::asio::error::no_permission) {
530         state_ = cei_state_e::CLOSED;
531         if (_error == boost::asio::error::no_permission) {
532             VSOMEIP_WARNING << "uce::send_cbk received error: " << _error.message()
533                     << " (" << std::dec << _error.value() << ") "
534                     << get_remote_information();
535             std::lock_guard<std::mutex> its_lock(mutex_);
536             queue_.clear();
537             queue_size_ = 0;
538         }
539         was_not_connected_ = true;
540         shutdown_and_close_socket(true);
541         strand_.dispatch(std::bind(&client_endpoint_impl::connect,
542                 this->shared_from_this()));
543     } else if (_error == boost::asio::error::operation_aborted) {
544         VSOMEIP_WARNING << "uce::send_cbk received error: " << _error.message();
545         // endpoint was stopped
546         sending_blocked_ = true;
547         shutdown_and_close_socket(false);
548     } else if (_error == boost::system::errc::destination_address_required) {
549         VSOMEIP_WARNING << "uce::send_cbk received error: " << _error.message()
550                 << " (" << std::dec << _error.value() << ") "
551                 << get_remote_information();
552         was_not_connected_ = true;
553     } else {
554         if (state_ == cei_state_e::CONNECTING) {
555             VSOMEIP_WARNING << "uce::send_cbk endpoint is already restarting:"
556                     << get_remote_information();
557         } else {
558             state_ = cei_state_e::CONNECTING;
559             shutdown_and_close_socket(false);
560             std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
561             if (its_host) {
562                 its_host->on_disconnect(shared_from_this());
563             }
564             restart(true);
565         }
566         service_t its_service(0);
567         method_t its_method(0);
568         client_t its_client(0);
569         session_t its_session(0);
570         if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
571             its_service = VSOMEIP_BYTES_TO_WORD(
572                     (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
573                     (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
574             its_method = VSOMEIP_BYTES_TO_WORD(
575                     (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
576                     (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
577             its_client = VSOMEIP_BYTES_TO_WORD(
578                     (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
579                     (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
580             its_session = VSOMEIP_BYTES_TO_WORD(
581                     (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
582                     (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
583         }
584         VSOMEIP_WARNING << "uce::send_cbk received error: " << _error.message()
585                 << " (" << std::dec << _error.value() << ") "
586                 << get_remote_information() << " "
587                 << " " << std::dec << queue_.size()
588                 << " " << std::dec << queue_size_ << " ("
589                 << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
590                 << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
591                 << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
592                 << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
593         print_status();
594     }
595 }
596 
tp_segmentation_enabled(service_t _service,method_t _method) const597 bool udp_client_endpoint_impl::tp_segmentation_enabled(service_t _service,
598                                                        method_t _method) const {
599     return configuration_->tp_segment_messages_client_to_service(_service,
600             remote_address_.to_string(), remote_port_, _method);
601 }
602 
is_reliable() const603 bool udp_client_endpoint_impl::is_reliable() const {
604     return false;
605 }
606 
get_max_allowed_reconnects() const607 std::uint32_t udp_client_endpoint_impl::get_max_allowed_reconnects() const {
608     return MAX_RECONNECTS_UNLIMITED;
609 }
610 
max_allowed_reconnects_reached()611 void udp_client_endpoint_impl::max_allowed_reconnects_reached() {
612     return;
613 }
614 
615 } // namespace vsomeip_v3
616