From cf3a5e51d7ec45a02b3a8854657cc270c3893c5a Mon Sep 17 00:00:00 2001 From: "michal.szwaj" Date: Thu, 5 Apr 2018 18:09:15 +0200 Subject: [PATCH] Draft of ping implementation --- .../autoapp/Projection/AndroidAutoEntity.hpp | 7 +- .../openauto/autoapp/Projection/IPinger.hpp | 47 ++++++++++ .../openauto/autoapp/Projection/Pinger.hpp | 57 ++++++++++++ src/autoapp/Projection/AndroidAutoEntity.cpp | 40 +++++++-- .../Projection/AndroidAutoEntityFactory.cpp | 4 +- src/autoapp/Projection/Pinger.cpp | 86 +++++++++++++++++++ src/autoapp/UI/ConnectDialog.cpp | 2 - 7 files changed, 234 insertions(+), 9 deletions(-) create mode 100644 include/f1x/openauto/autoapp/Projection/IPinger.hpp create mode 100644 include/f1x/openauto/autoapp/Projection/Pinger.hpp create mode 100644 src/autoapp/Projection/Pinger.cpp diff --git a/include/f1x/openauto/autoapp/Projection/AndroidAutoEntity.hpp b/include/f1x/openauto/autoapp/Projection/AndroidAutoEntity.hpp index b085d5e..786ee77 100644 --- a/include/f1x/openauto/autoapp/Projection/AndroidAutoEntity.hpp +++ b/include/f1x/openauto/autoapp/Projection/AndroidAutoEntity.hpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace f1x { @@ -43,7 +44,8 @@ public: aasdk::messenger::ICryptor::Pointer cryptor, aasdk::transport::ITransport::Pointer transport, configuration::IConfiguration::Pointer configuration, - IServiceFactory& serviceFactory); + IServiceFactory& serviceFactory, + IPinger::Pointer pinger); ~AndroidAutoEntity() override; void start(IAndroidAutoEntityEventHandler& eventHandler) override; @@ -55,17 +57,20 @@ public: void onShutdownRequest(const aasdk::proto::messages::ShutdownRequest& request) override; void onShutdownResponse(const aasdk::proto::messages::ShutdownResponse& response) override; void onNavigationFocusRequest(const aasdk::proto::messages::NavigationFocusRequest& request) override; + void onPingResponse(const aasdk::proto::messages::PingResponse& response) override; void onChannelError(const aasdk::error::Error& e) override; private: using std::enable_shared_from_this::shared_from_this; void triggerQuit(); + void ping(); boost::asio::io_service::strand strand_; aasdk::messenger::ICryptor::Pointer cryptor_; aasdk::transport::ITransport::Pointer transport_; configuration::IConfiguration::Pointer configuration_; IServiceFactory& serviceFactory_; + IPinger::Pointer pinger_; aasdk::messenger::IMessenger::Pointer messenger_; aasdk::channel::control::ControlServiceChannel::Pointer controlServiceChannel_; ServiceList serviceList_; diff --git a/include/f1x/openauto/autoapp/Projection/IPinger.hpp b/include/f1x/openauto/autoapp/Projection/IPinger.hpp new file mode 100644 index 0000000..63def2b --- /dev/null +++ b/include/f1x/openauto/autoapp/Projection/IPinger.hpp @@ -0,0 +1,47 @@ +/* +* This file is part of openauto project. +* Copyright (C) 2018 f1x.studio (Michal Szwaj) +* +* openauto is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. + +* openauto is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with openauto. If not, see . +*/ + +#pragma once + +#include + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace projection +{ + +class IPinger +{ +public: + typedef std::shared_ptr Pointer; + typedef aasdk::io::Promise Promise; + + virtual ~IPinger() = default; + virtual void ping(Promise::Pointer promise) = 0; + virtual void pong() = 0; + virtual void cancel() = 0; +}; + +} +} +} +} diff --git a/include/f1x/openauto/autoapp/Projection/Pinger.hpp b/include/f1x/openauto/autoapp/Projection/Pinger.hpp new file mode 100644 index 0000000..8ddaafc --- /dev/null +++ b/include/f1x/openauto/autoapp/Projection/Pinger.hpp @@ -0,0 +1,57 @@ +/* +* This file is part of openauto project. +* Copyright (C) 2018 f1x.studio (Michal Szwaj) +* +* openauto is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. + +* openauto is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with openauto. If not, see . +*/ + +#pragma once + +#include + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace projection +{ + +class Pinger: public IPinger, std::enable_shared_from_this +{ +public: + Pinger(boost::asio::io_service& ioService, time_t duration); + + void ping(Promise::Pointer promise) override; + void pong() override; + void cancel() override; + +private: + using std::enable_shared_from_this::shared_from_this; + + void onTimerExceeded(const boost::system::error_code& error); + + boost::asio::io_service::strand strand_; + boost::asio::deadline_timer timer_; + time_t duration_; + Promise::Pointer promise_; + int64_t pingsCount_; + int64_t pongsCount_; +}; + +} +} +} +} diff --git a/src/autoapp/Projection/AndroidAutoEntity.cpp b/src/autoapp/Projection/AndroidAutoEntity.cpp index a0c690c..5e77ba0 100644 --- a/src/autoapp/Projection/AndroidAutoEntity.cpp +++ b/src/autoapp/Projection/AndroidAutoEntity.cpp @@ -35,12 +35,14 @@ AndroidAutoEntity::AndroidAutoEntity(boost::asio::io_service& ioService, aasdk::messenger::ICryptor::Pointer cryptor, aasdk::transport::ITransport::Pointer transport, configuration::IConfiguration::Pointer configuration, - IServiceFactory& serviceFactory) + IServiceFactory& serviceFactory, + IPinger::Pointer pinger) : strand_(ioService) , cryptor_(std::move(cryptor)) , transport_(std::move(transport)) , configuration_(std::move(configuration)) , serviceFactory_(serviceFactory) + , pinger_(std::move(pinger)) , messenger_(std::make_shared(ioService, std::make_shared(ioService, transport_, cryptor_), std::make_shared(ioService, transport_, cryptor_))) @@ -178,6 +180,8 @@ void AndroidAutoEntity::onServiceDiscoveryRequest(const aasdk::proto::messages:: promise->then([]() {}, std::bind(&AndroidAutoEntity::onChannelError, this->shared_from_this(), std::placeholders::_1)); controlServiceChannel_->sendServiceDiscoveryResponse(serviceDiscoveryResponse, std::move(promise)); controlServiceChannel_->receive(this->shared_from_this()); + + this->ping(); } void AndroidAutoEntity::onAudioFocusRequest(const aasdk::proto::messages::AudioFocusRequest& request) @@ -205,10 +209,8 @@ void AndroidAutoEntity::onShutdownRequest(const aasdk::proto::messages::Shutdown aasdk::proto::messages::ShutdownResponse response; auto promise = aasdk::channel::SendPromise::defer(strand_); - promise->then([this, self = this->shared_from_this()]() { - this->triggerQuit(); - }, - std::bind(&AndroidAutoEntity::onChannelError, this->shared_from_this(), std::placeholders::_1)); + promise->then(std::bind(&AndroidAutoEntity::triggerQuit, this->shared_from_this()), + std::bind(&AndroidAutoEntity::onChannelError, this->shared_from_this(), std::placeholders::_1)); controlServiceChannel_->sendShutdownResponse(response, std::move(promise)); controlServiceChannel_->receive(this->shared_from_this()); @@ -233,6 +235,14 @@ void AndroidAutoEntity::onNavigationFocusRequest(const aasdk::proto::messages::N controlServiceChannel_->receive(this->shared_from_this()); } +void AndroidAutoEntity::onPingResponse(const aasdk::proto::messages::PingResponse&) +{ + OPENAUTO_LOG(info) << "[AndroidAutoEntity] ping response"; + + pinger_->pong(); + controlServiceChannel_->receive(this->shared_from_this()); +} + void AndroidAutoEntity::onChannelError(const aasdk::error::Error& e) { OPENAUTO_LOG(error) << "[AndroidAutoEntity] channel error: " << e.what(); @@ -247,6 +257,26 @@ void AndroidAutoEntity::triggerQuit() } } +void AndroidAutoEntity::ping() +{ + auto promise = IPinger::Promise::defer(strand_); + promise->then([this, self = this->shared_from_this()]() { + auto promise = aasdk::channel::SendPromise::defer(strand_); + promise->then([]() {}, std::bind(&AndroidAutoEntity::onChannelError, this->shared_from_this(), std::placeholders::_1)); + + aasdk::proto::messages::PingRequest request; + controlServiceChannel_->sendPingRequest(request, std::move(promise)); + + this->ping(); + }, + [this, self = this->shared_from_this()]() { + OPENAUTO_LOG(error) << "[AndroidAutoEntity] ping timer exceeded."; + this->triggerQuit(); + }); + + pinger_->ping(std::move(promise)); +} + } } } diff --git a/src/autoapp/Projection/AndroidAutoEntityFactory.cpp b/src/autoapp/Projection/AndroidAutoEntityFactory.cpp index 0eb6942..a704d03 100644 --- a/src/autoapp/Projection/AndroidAutoEntityFactory.cpp +++ b/src/autoapp/Projection/AndroidAutoEntityFactory.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace f1x { @@ -59,8 +60,9 @@ IAndroidAutoEntity::Pointer AndroidAutoEntityFactory::create(aasdk::transport::I { auto sslWrapper(std::make_shared()); auto cryptor(std::make_shared(std::move(sslWrapper))); + auto pinger(std::make_shared(ioService_, 5000)); - return std::make_shared(ioService_, std::move(cryptor), std::move(transport), configuration_, serviceFactory_); + return std::make_shared(ioService_, std::move(cryptor), std::move(transport), configuration_, serviceFactory_, std::move(pinger)); } } diff --git a/src/autoapp/Projection/Pinger.cpp b/src/autoapp/Projection/Pinger.cpp new file mode 100644 index 0000000..7dd5284 --- /dev/null +++ b/src/autoapp/Projection/Pinger.cpp @@ -0,0 +1,86 @@ +/* +* This file is part of openauto project. +* Copyright (C) 2018 f1x.studio (Michal Szwaj) +* +* openauto is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. + +* openauto is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with openauto. If not, see . +*/ + +#include + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace projection +{ + +Pinger::Pinger(boost::asio::io_service& ioService, time_t duration) + : strand_(ioService) + , timer_(ioService) + , duration_(duration) + , pingsCount_(0) + , pongsCount_(0) +{ + +} + +void Pinger::ping(Promise::Pointer promise) +{ + strand_.dispatch([this, self = this->shared_from_this(), promise = std::move(promise)]() mutable { + ++pingsCount_; + + promise_ = std::move(promise); + timer_.expires_from_now(boost::posix_time::milliseconds(duration_)); + timer_.async_wait(strand_.wrap(std::bind(&Pinger::onTimerExceeded, this->shared_from_this(), std::placeholders::_1))); + }); +} + +void Pinger::pong() +{ + strand_.dispatch([this, self = this->shared_from_this()]() { + ++pongsCount_; + }); +} + +void Pinger::onTimerExceeded(const boost::system::error_code& error) +{ + if(!error && promise_ != nullptr) + { + if(std::abs(pingsCount_ - pongsCount_) > 1) + { + promise_->reject(); + } + else + { + promise_->resolve(); + } + + promise_.reset(); + } +} + +void Pinger::cancel() +{ + strand_.dispatch([this, self = this->shared_from_this()]() { + promise_.reset(); + timer_.cancel(); + }); +} + +} +} +} +} diff --git a/src/autoapp/UI/ConnectDialog.cpp b/src/autoapp/UI/ConnectDialog.cpp index 08b4f56..127e216 100644 --- a/src/autoapp/UI/ConnectDialog.cpp +++ b/src/autoapp/UI/ConnectDialog.cpp @@ -46,8 +46,6 @@ void ConnectDialog::onConnectButtonClicked() try { - tcpWrapper_.setKeepAliveOption(*socket, true); - tcpWrapper_.setNoDelayOption(*socket, true); tcpWrapper_.asyncConnect(*socket, ipAddress, 5277, std::bind(&ConnectDialog::connectHandler, this, std::placeholders::_1, ipAddress, socket)); } catch(const boost::system::system_error& se)