blob: de6e022c6100cca26327a6f8ca24ec088f3bee1f [file] [log] [blame]
//
// client_impl.cpp
//
// This file is part of the BMW Some/IP implementation.
//
// Copyright ������ 2013, 2014 Bayerische Motoren Werke AG (BMW).
// All rights reserved.
//
#include <chrono>
#include <boost/asio/buffer.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/bind.hpp>
#include <vsomeip/config.hpp>
#include <vsomeip/endpoint.hpp>
#include <vsomeip_internal/client_impl.hpp>
#include <vsomeip_internal/log_macros.hpp>
#include <vsomeip_internal/managing_proxy_impl.hpp>
namespace vsomeip {
template < typename Protocol, int MaxBufferSize >
client_impl< Protocol, MaxBufferSize >::client_impl(
managing_proxy_impl *_owner, const endpoint *_location)
: participant_impl< MaxBufferSize >(_owner, _location),
socket_(_owner->get_service()),
connect_timer_(_owner->get_service()),
flush_timer_(_owner->get_service()),
local_(boost::asio::ip::address::from_string(_location->get_address()),
_location->get_port()),
connect_timeout_(VSOMEIP_DEFAULT_CONNECT_TIMEOUT), // TODO: use config variable
is_connected_(false) {
}
template < typename Protocol, int MaxBufferSize >
client_impl< Protocol, MaxBufferSize >::~client_impl() {
}
template < typename Protocol, int MaxBufferSize >
const uint8_t * client_impl< Protocol, MaxBufferSize >::get_buffer() const {
return buffer_.data();
}
template < typename Protocol, int MaxBufferSize >
bool client_impl< Protocol, MaxBufferSize >::is_client() const {
return true;
}
template < typename Protocol, int MaxBufferSize >
void client_impl< Protocol, MaxBufferSize >::stop() {
if (socket_.is_open())
socket_.close();
}
template < typename Protocol, int MaxBufferSize >
void client_impl< Protocol, MaxBufferSize >::restart() {
receive();
}
template < typename Protocol, int MaxBufferSize >
bool client_impl< Protocol, MaxBufferSize >::send(
const uint8_t *_data, uint32_t _size, bool _flush) {
bool is_queue_empty(packet_queue_.empty());
if (packetizer_.size() + _size > MaxBufferSize) {
VSOMEIP_WARNING << "Implicitly flushing.";
packet_queue_.push_back(packetizer_);
packetizer_.clear();
if (is_queue_empty && is_connected_)
send_queued();
}
packetizer_.insert(packetizer_.end(), _data, _data + _size);
if (_flush) {
flush_timer_.cancel();
packet_queue_.push_back(packetizer_);
packetizer_.clear();
if (is_queue_empty && is_connected_)
send_queued();
} else {
flush_timer_.expires_from_now(
std::chrono::milliseconds(VSOMEIP_DEFAULT_FLUSH_TIMEOUT)); // TODO: use config variable
flush_timer_.async_wait(
boost::bind(
&client_impl<Protocol, MaxBufferSize>::flush_cbk,
this,
boost::asio::placeholders::error
)
);
}
return true;
}
template < typename Protocol, int MaxBufferSize >
bool client_impl< Protocol, MaxBufferSize >::flush() {
bool is_successful(true);
if (!packetizer_.empty()) {
packet_queue_.push_back(packetizer_);
packetizer_.clear();
send_queued();
} else {
is_successful = false;
}
return is_successful;
}
template < typename Protocol, int MaxBufferSize >
void client_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(
boost::bind(
&client_impl<Protocol, MaxBufferSize>::wait_connect_cbk,
this,
boost::asio::placeholders::error
)
);
// next time we wait longer
connect_timeout_ <<= 1;
} else {
connect_timer_.cancel();
connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT; // TODO: use config variable
is_connected_ = true;
if (!packet_queue_.empty()) {
send_queued();
}
receive();
}
}
template < typename Protocol, int MaxBufferSize >
void client_impl< Protocol, MaxBufferSize >::wait_connect_cbk(
boost::system::error_code const &_error) {
if (!_error) {
connect();
}
}
template < typename Protocol, int MaxBufferSize >
void client_impl< Protocol, MaxBufferSize >::send_cbk(
boost::system::error_code const &_error, std::size_t _bytes) {
if (!_error && _bytes > 0) {
packet_queue_.pop_front();
if (!packet_queue_.empty()) {
send_queued();
}
} else {
if (_error == boost::asio::error::broken_pipe) {
is_connected_ = false;
socket_.close();
connect();
}
}
}
template < typename Protocol, int MaxBufferSize >
void client_impl< Protocol, MaxBufferSize >::flush_cbk(
boost::system::error_code const &_error) {
if (!_error) {
(void)flush();
}
}
// Instantiate template
template class client_impl< boost::asio::ip::tcp, VSOMEIP_MAX_TCP_MESSAGE_SIZE >;
template class client_impl< boost::asio::ip::udp, VSOMEIP_MAX_UDP_MESSAGE_SIZE >;
} // namespace vsomeip