273 lines
12 KiB
C++
273 lines
12 KiB
C++
/*
|
|
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License").
|
|
* You may not use this file except in compliance with the License.
|
|
* A copy of the License is located at
|
|
*
|
|
* http://aws.amazon.com/apache2.0/
|
|
*
|
|
* or in the "license" file accompanying this file. This file is distributed
|
|
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
|
* express or implied. See the License for the specific language governing
|
|
* permissions and limitations under the License.
|
|
*/
|
|
|
|
#ifndef ALEXA_CLIENT_SDK_ACL_INCLUDE_ACL_TRANSPORT_MESSAGEROUTER_H_
|
|
#define ALEXA_CLIENT_SDK_ACL_INCLUDE_ACL_TRANSPORT_MESSAGEROUTER_H_
|
|
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <acsdkShutdownManagerInterfaces/ShutdownNotifierInterface.h>
|
|
#include <AVSCommon/AVS/Attachment/AttachmentManagerInterface.h>
|
|
#include <AVSCommon/AVS/MessageRequest.h>
|
|
#include <AVSCommon/SDKInterfaces/AuthDelegateInterface.h>
|
|
#include <AVSCommon/Utils/Threading/Executor.h>
|
|
#include <AVSCommon/Utils/Timing/Timer.h>
|
|
|
|
#include "ACL/Transport/MessageConsumerInterface.h"
|
|
#include "ACL/Transport/MessageRouterInterface.h"
|
|
#include "ACL/Transport/MessageRouterObserverInterface.h"
|
|
#include "ACL/Transport/TransportFactoryInterface.h"
|
|
#include "ACL/Transport/TransportInterface.h"
|
|
#include "ACL/Transport/TransportObserverInterface.h"
|
|
#include "ACL/Transport/SynchronizedMessageRequestQueue.h"
|
|
|
|
namespace alexaClientSDK {
|
|
namespace acl {
|
|
|
|
/**
|
|
* This an abstract base class which specifies the interface to manage an actual connection over some medium to AVS.
|
|
*
|
|
* Implementations of this class are required to be thread-safe.
|
|
*/
|
|
class MessageRouter
|
|
: public MessageRouterInterface
|
|
, public TransportObserverInterface
|
|
, public MessageConsumerInterface
|
|
, public std::enable_shared_from_this<MessageRouter> {
|
|
public:
|
|
/// Amount of time to allow for an automatic reconnect before notifying of a server side disconnect.
|
|
static const std::chrono::milliseconds DEFAULT_SERVER_SIDE_DISCONNECT_GRACE_PERIOD;
|
|
|
|
/**
|
|
* Factory function for creating an instance of MessageRouterInterface.
|
|
*
|
|
* @param shutdownNotifier The object with which to register to be told when to shut down.
|
|
* @param authDelegate An implementation of an AuthDelegate, which will provide valid access tokens with which
|
|
* the MessageRouter can authorize the client to AVS.
|
|
* @param attachmentManager The AttachmentManager, which allows ACL to write attachments received from AVS.
|
|
* @param transportFactory Factory used to create new transport objects.
|
|
*/
|
|
static std::shared_ptr<MessageRouterInterface> createMessageRouterInterface(
|
|
const std::shared_ptr<acsdkShutdownManagerInterfaces::ShutdownNotifierInterface>& shutdownNotifier,
|
|
const std::shared_ptr<avsCommon::sdkInterfaces::AuthDelegateInterface>& authDelegate,
|
|
const std::shared_ptr<avsCommon::avs::attachment::AttachmentManagerInterface>& attachmentManager,
|
|
const std::shared_ptr<TransportFactoryInterface>& transportFactory);
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @deprecated
|
|
* @param authDelegate An implementation of an AuthDelegate, which will provide valid access tokens with which
|
|
* the MessageRouter can authorize the client to AVS.
|
|
* @param attachmentManager The AttachmentManager, which allows ACL to write attachments received from AVS.
|
|
* @param transportFactory Factory used to create new transport objects.
|
|
* @param avsGateway The gateway to connect to AVS. The value will be set by the @c AVSGatewayManager based on
|
|
* either the previously verified gateway or a value from the config file. If both are not present, a default value
|
|
* is used.
|
|
* @param engineType optional parameter of engine type associated with this MessageRouter. Default to be
|
|
* ENGINE_TYPE_ALEXA_VOICE_SERVICES.
|
|
* @param serverSideDisconnectGracePeriod How long to allow for an automatic reconnection before reporting
|
|
* a server side disconnect to our observer.
|
|
*/
|
|
MessageRouter(
|
|
std::shared_ptr<avsCommon::sdkInterfaces::AuthDelegateInterface> authDelegate,
|
|
std::shared_ptr<avsCommon::avs::attachment::AttachmentManagerInterface> attachmentManager,
|
|
std::shared_ptr<TransportFactoryInterface> transportFactory,
|
|
const std::string& avsGateway = "",
|
|
int engineType = avsCommon::sdkInterfaces::ENGINE_TYPE_ALEXA_VOICE_SERVICES,
|
|
std::chrono::milliseconds serverSideDisconnectGracePeriod = DEFAULT_SERVER_SIDE_DISCONNECT_GRACE_PERIOD);
|
|
|
|
/// @name MessageRouterInterface methods.
|
|
/// @{
|
|
void enable() override;
|
|
void disable() override;
|
|
ConnectionStatus getConnectionStatus() override;
|
|
void sendMessage(std::shared_ptr<avsCommon::avs::MessageRequest> request) override;
|
|
void setAVSGateway(const std::string& avsGateway) override;
|
|
std::string getAVSGateway() override;
|
|
void onWakeConnectionRetry() override;
|
|
void onWakeVerifyConnectivity() override;
|
|
void setObserver(std::shared_ptr<MessageRouterObserverInterface> observer) override;
|
|
/// @}
|
|
|
|
void onConnected(std::shared_ptr<TransportInterface> transport) override;
|
|
|
|
void onDisconnected(
|
|
std::shared_ptr<TransportInterface> transport,
|
|
avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::ChangedReason reason) override;
|
|
|
|
void onServerSideDisconnect(std::shared_ptr<TransportInterface> transport) override;
|
|
|
|
void consumeMessage(const std::string& contextId, const std::string& message) override;
|
|
|
|
void doShutdown() override;
|
|
|
|
private:
|
|
/**
|
|
* Set the connection state. If it changes, notify our observer.
|
|
* @c m_connectionMutex must be locked to call this method.
|
|
*
|
|
* @param status The current status of the connection.
|
|
* @param reason The reason the connection status changed.
|
|
*/
|
|
void setConnectionStatusLocked(
|
|
const avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::Status status,
|
|
const avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::ChangedReason reason);
|
|
|
|
/**
|
|
* Notify the connection observer when the status has changed.
|
|
* Architectural note:
|
|
* @li A derived class cannot access the required observer method directly due a friend relationship at the base
|
|
* class level. However this method bridges the gap, and allows the observer's public interface to remain
|
|
* unchanged.
|
|
*
|
|
* @param status The current status of the connection.
|
|
* @param reason The reason the connection status changed.
|
|
*/
|
|
void notifyObserverOnConnectionStatusChanged(
|
|
const avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::Status status,
|
|
const avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::ChangedReason reason);
|
|
|
|
/**
|
|
* Without any further queueing to the executor, notify the connection observer that the status has changed.
|
|
*
|
|
* @param status The current status of the connection.
|
|
* @param reason The reason the connection status changed.
|
|
*/
|
|
void handleNotifyObserverOnConnectionStatusChanged(
|
|
const avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::Status status,
|
|
const avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::ChangedReason reason);
|
|
|
|
/**
|
|
* Notify the message observer of an incoming message from AVS.
|
|
* Architectural note:
|
|
* @li A derived class cannot access the required observer method directly due a friend relationship at the base
|
|
* class level. However this method bridges the gap, and allows the observer's public interface to remain
|
|
* unchanged.
|
|
*
|
|
* @param contextId The context id for the current message.
|
|
* @param message The AVS message in string representation.
|
|
*/
|
|
void notifyObserverOnReceive(const std::string& contextId, const std::string& message);
|
|
|
|
/**
|
|
* Creates a new transport, and begins the connection process. The new transport immediately becomes the active
|
|
* transport. @c m_connectionMutex must be locked to call this method.
|
|
*/
|
|
void createActiveTransportLocked();
|
|
|
|
/**
|
|
* Disconnects all transports. @c m_connectionMutex must be locked to call this method.
|
|
*
|
|
* @param reason The reason the last transport was disconnected
|
|
* @param lock Reference to the @c unique_lock that must be held when this method is called. The lock may be
|
|
* released during the execution of this method, but will be locked when this method exits.
|
|
*/
|
|
void disconnectAllTransportsLocked(
|
|
std::unique_lock<std::mutex>& lock,
|
|
const avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::ChangedReason reason);
|
|
|
|
/**
|
|
* Get the observer.
|
|
*
|
|
* @return The observer.
|
|
*/
|
|
std::shared_ptr<MessageRouterObserverInterface> getObserver();
|
|
|
|
/**
|
|
* Reset m_activeTransport. First check if m_activeTransport is in m_transports. If not, issue
|
|
* a warning (because it should be) and queue the safe release of our reference to the transport.
|
|
* @c m_connectionMutex must be locked to call this method.
|
|
*/
|
|
void safelyResetActiveTransportLocked();
|
|
|
|
/**
|
|
* Hold a reference to a transport until its shutdown() method (executed on our executor) returns.
|
|
*
|
|
* @param transport The TransportInterface instance to retain a reference to.
|
|
*/
|
|
void safelyReleaseTransport(std::shared_ptr<TransportInterface> transport);
|
|
|
|
/// The observer object. Access serialized with @c m_connectionMutex.
|
|
std::shared_ptr<MessageRouterObserverInterface> m_observer;
|
|
|
|
/// The current AVS gateway. Access serialized with @c m_connectionMutex.
|
|
std::string m_avsGateway;
|
|
|
|
/// The AuthDelegateInterface which provides a valid access token.
|
|
std::shared_ptr<avsCommon::sdkInterfaces::AuthDelegateInterface> m_authDelegate;
|
|
|
|
/// This mutex guards access to all connection related state, specifically the status and all transport interaction.
|
|
std::mutex m_connectionMutex;
|
|
|
|
/// The current connection status. Access serialized with @c m_connectionMutex.
|
|
avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::Status m_connectionStatus;
|
|
|
|
/// The current connection reason. Access serialized with @c m_connectionMutex.
|
|
avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::ChangedReason m_connectionReason;
|
|
|
|
/// The engine type associated with this MessageRouter
|
|
int m_engineType;
|
|
|
|
/**
|
|
* When the MessageRouter is enabled, any disconnect should automatically trigger a reconnect with AVS.
|
|
* Access serialized with @c m_connectionMutex.
|
|
*/
|
|
bool m_isEnabled;
|
|
|
|
/// A vector of all transports which are not disconnected. Access serialized with @c m_connectionMutex.
|
|
std::vector<std::shared_ptr<TransportInterface>> m_transports;
|
|
|
|
/// The current active transport to send messages on. Access serialized with @c m_connectionMutex.
|
|
std::shared_ptr<TransportInterface> m_activeTransport;
|
|
|
|
/// The attachment manager.
|
|
std::shared_ptr<avsCommon::avs::attachment::AttachmentManagerInterface> m_attachmentManager;
|
|
|
|
/// The transport factory.
|
|
std::shared_ptr<TransportFactoryInterface> m_transportFactory;
|
|
|
|
/// The synchonized queue of messages to send that is shared between transports.
|
|
std::shared_ptr<SynchronizedMessageRequestQueue> m_requestQueue;
|
|
|
|
/// Timer used to smooth over server side disconnects.
|
|
avsCommon::utils::timing::Timer m_serverSideDisconnectTimer;
|
|
|
|
/// True if notification of a server side disconnect should be delivered when the timer triggers.
|
|
bool m_serverSideDisconnectNotificationPending;
|
|
|
|
/// The last connection status reported to our observer.
|
|
avsCommon::sdkInterfaces::ConnectionStatusObserverInterface::Status m_lastReportedConnectionStatus;
|
|
|
|
/// Amount of time to allow for an automatic reconnect before notifying of a server side disconnect.
|
|
const std::chrono::milliseconds m_serverSideReconnectGracePeriod;
|
|
|
|
protected:
|
|
/**
|
|
* Executor to perform asynchronous operations:
|
|
* @li Delivery of connection status notifications.
|
|
* @li completion of send operations delayed by a pending connection state.
|
|
*/
|
|
avsCommon::utils::threading::Executor m_executor;
|
|
};
|
|
|
|
} // namespace acl
|
|
} // namespace alexaClientSDK
|
|
|
|
#endif // ALEXA_CLIENT_SDK_ACL_INCLUDE_ACL_TRANSPORT_MESSAGEROUTER_H_
|