summaryrefslogtreecommitdiff
path: root/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h')
-rw-r--r--src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h524
1 files changed, 524 insertions, 0 deletions
diff --git a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h
new file mode 100644
index 0000000000..3732e23a4c
--- /dev/null
+++ b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_PROTOCOL_HANDLER_INCLUDE_PROTOCOL_HANDLER_PROTOCOL_HANDLER_IMPL_H_
+#define SRC_COMPONENTS_PROTOCOL_HANDLER_INCLUDE_PROTOCOL_HANDLER_PROTOCOL_HANDLER_IMPL_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include "utils/prioritized_queue.h"
+#include "utils/message_queue.h"
+#include "utils/threads/message_loop_thread.h"
+#include "utils/shared_ptr.h"
+
+#include "protocol_handler/protocol_handler.h"
+#include "protocol_handler/protocol_packet.h"
+#include "protocol_handler/session_observer.h"
+#include "protocol_handler/protocol_observer.h"
+#include "transport_manager/common.h"
+#include "transport_manager/transport_manager.h"
+#include "transport_manager/transport_manager_listener_empty.h"
+#ifdef TIME_TESTER
+#include "time_metric_observer.h"
+#endif // TIME_TESTER
+
+#ifdef ENABLE_SECURITY
+#include "security_manager/security_manager.h"
+#endif // ENABLE_SECURITY
+
+/**
+ *\namespace protocol_handlerHandler
+ *\brief Namespace for SmartDeviceLink ProtocolHandler related functionality.
+ */
+namespace protocol_handler {
+class ProtocolObserver;
+class SessionObserver;
+
+class MessagesFromMobileAppHandler;
+class MessagesToMobileAppHandler;
+
+using transport_manager::TransportManagerListenerEmpty;
+
+/**
+ * @brief Type definition for variable that hold shared pointer to raw message.
+ */
+typedef utils::SharedPtr<protocol_handler::ProtocolPacket> ProtocolFramePtr;
+
+typedef std::multimap<int32_t, RawMessagePtr> MessagesOverNaviMap;
+typedef std::set<ProtocolObserver*> ProtocolObservers;
+typedef transport_manager::ConnectionUID ConnectionID;
+
+namespace impl {
+/*
+ * These dummy classes are here to locally impose strong typing on different
+ * kinds of messages
+ * Currently there is no type difference between incoming and outgoing messages
+ * TODO(ik): replace these with globally defined message types
+ * when we have them.
+ */
+struct RawFordMessageFromMobile: public ProtocolFramePtr {
+ explicit RawFordMessageFromMobile(const ProtocolFramePtr message)
+ : ProtocolFramePtr(message) {}
+ // PrioritizedQueue requires this method to decide which priority to assign
+ size_t PriorityOrder() const {
+ return MessagePriority::FromServiceType(
+ ServiceTypeFromByte(get()->service_type())).OrderingValue(); }
+};
+
+struct RawFordMessageToMobile: public ProtocolFramePtr {
+ explicit RawFordMessageToMobile(const ProtocolFramePtr message,
+ bool final_message)
+ : ProtocolFramePtr(message), is_final(final_message) {}
+ // PrioritizedQueue requires this method to decide which priority to assign
+ size_t PriorityOrder() const {
+ return MessagePriority::FromServiceType(
+ ServiceTypeFromByte(get()->service_type())).OrderingValue(); }
+ // Signals whether connection to mobile must be closed after processing this message
+ bool is_final;
+};
+
+// Short type names for prioritized message queues
+typedef threads::MessageLoopThread<
+ utils::PrioritizedQueue<RawFordMessageFromMobile> > FromMobileQueue;
+typedef threads::MessageLoopThread<
+ utils::PrioritizedQueue<RawFordMessageToMobile> > ToMobileQueue;
+} // namespace impl
+
+/**
+ * \class ProtocolHandlerImpl
+ * \brief Class for handling message exchange between Transport and higher
+ * layers. Receives message in form of array of bytes, parses its protocol,
+ * handles according to parsing results (version number, start/end session etc
+ * and if needed passes message to JSON Handler or notifies Connection Handler
+ * about activities around sessions.
+ */
+class ProtocolHandlerImpl
+ : public ProtocolHandler,
+ public TransportManagerListenerEmpty,
+ public impl::FromMobileQueue::Handler,
+ public impl::ToMobileQueue::Handler {
+ public:
+ /**
+ * \brief Constructor
+ * \param transportManager Pointer to Transport layer handler for
+ * message exchange.
+ */
+ explicit ProtocolHandlerImpl(
+ transport_manager::TransportManager *transport_manager_param);
+
+ /**
+ * \brief Destructor
+ */
+ ~ProtocolHandlerImpl();
+
+ /**
+ * \brief Adds pointer to higher layer handler for message exchange
+ * \param observer Pointer to object of the class implementing
+ * IProtocolObserver
+ */
+ void AddProtocolObserver(ProtocolObserver *observer);
+
+ /**
+ * \brief Removes pointer to higher layer handler for message exchange
+ * \param observer Pointer to object of the class implementing
+ * IProtocolObserver.
+ */
+ void RemoveProtocolObserver(ProtocolObserver *observer);
+
+ /**
+ * \brief Sets pointer for Connection Handler layer for managing sessions
+ * \param observer Pointer to object of the class implementing
+ * ISessionObserver
+ */
+ void set_session_observer(SessionObserver *observer);
+
+#ifdef ENABLE_SECURITY
+ /**
+ * \brief Sets pointer for SecurityManager layer for managing protection routine
+ * \param security_manager Pointer to SecurityManager object
+ */
+ void set_security_manager(security_manager::SecurityManager *security_manager);
+#endif // ENABLE_SECURITY
+
+ /**
+ * \brief Method for sending message to Mobile Application
+ * \param message Message with params to be sent to Mobile App
+ */
+ void SendMessageToMobileApp(const RawMessagePtr message,
+ bool final_message) OVERRIDE;
+
+ /**
+ * \brief Sends number of processed frames in case of binary nav streaming
+ * \param connection_key Id of connection over which message is to be sent
+ * \param number_of_frames Number of frames processed by
+ * streaming server and displayed to user.
+ */
+ void SendFramesNumber(uint32_t connection_key, int32_t number_of_frames);
+
+#ifdef TIME_TESTER
+ /**
+ * @brief Setup observer for time metric.
+ *
+ * @param observer - pointer to observer
+ */
+ void SetTimeMetricObserver(PHMetricObserver *observer);
+#endif // TIME_TESTER
+
+ /*
+ * Prepare and send heartbeat message to mobile
+ */
+ void SendHeartBeat(int32_t connection_id, uint8_t session_id);
+
+ /**
+ * \brief Sends ending session to mobile application
+ * \param connection_id Identifier of connection within which
+ * session exists
+ * \param session_id ID of session to be ended
+ */
+ void SendEndSession(int32_t connection_id, uint8_t session_id);
+
+ // TODO(Ezamakhov): move Ack/Nack as interface for StartSessionHandler
+ /**
+ * \brief Sends acknowledgement of starting session to mobile application
+ * with session number and hash code for second version of protocol
+ * was started
+ * \param connection_id Identifier of connection within which session
+ * \param session_id ID of session to be sent to mobile application
+ * \param protocol_version Version of protocol used for communication
+ * \param hash_code For second version of protocol: identifier of session
+ * to be sent to
+ * mobile app for using when ending session
+ * \param service_type Type of session: RPC or BULK Data. RPC by default
+ * \param protection Protection flag
+ */
+ void SendStartSessionAck(ConnectionID connection_id,
+ uint8_t session_id,
+ uint8_t protocol_version,
+ uint32_t hash_code,
+ uint8_t service_type,
+ bool protection);
+
+ /**
+ * \brief Sends fail of starting session to mobile application
+ * \param connection_id Identifier of connection within which session
+ * \param session_id ID of session to be sent to mobile application
+ * \param protocol_version Version of protocol used for communication
+ * \param service_type Type of session: RPC or BULK Data. RPC by default
+ */
+ void SendStartSessionNAck(ConnectionID connection_id,
+ uint8_t session_id,
+ uint8_t protocol_version,
+ uint8_t service_type);
+
+ /**
+ * \brief Sends acknowledgement of end session/service to mobile application
+ * with session number for second version of protocol.
+ * \param connection_id Identifier of connection
+ * \param connection_handle Identifier of connection within which session
+ * was started
+ * \param session_id ID of session to be sent to mobile application
+ * \param protocol_version Version of protocol used for communication
+ * mobile app for using when ending session.
+ * \param service_type Type of session: RPC or BULK Data. RPC by default
+ */
+ void SendEndSessionAck(ConnectionID connection_id ,
+ uint8_t session_id,
+ uint8_t protocol_version,
+ uint8_t service_type);
+
+ /**
+ * \brief Sends fail of ending session to mobile application
+ * \param connection_id Identifier of connection within which
+ * session exists
+ * \param session_id ID of session ment to be ended
+ * \param protocol_version Version of protocol used for communication
+ * \param service_type Type of session: RPC or BULK Data. RPC by default
+ */
+ void SendEndSessionNAck(ConnectionID connection_id ,
+ uint32_t session_id,
+ uint8_t protocol_version,
+ uint8_t service_type);
+
+ private:
+ /*
+ * Prepare and send heartbeat acknowledge message
+ */
+ RESULT_CODE SendHeartBeatAck(ConnectionID connection_id,
+ uint8_t session_id,
+ uint32_t message_id);
+
+ /**
+ * @brief Notifies about receiving message from TM.
+ *
+ * @param message Received message
+ **/
+ virtual void OnTMMessageReceived(
+ const RawMessagePtr message);
+
+ /**
+ * @brief Notifies about error on receiving message from TM.
+ *
+ * @param error Occurred error
+ **/
+ virtual void OnTMMessageReceiveFailed(
+ const transport_manager::DataReceiveError &error);
+
+ /**
+ * @brief Notifies about successfully sending message.
+ *
+ **/
+ virtual void OnTMMessageSend(const RawMessagePtr message);
+
+ /**
+ * @brief Notifies about error occurred during
+ * sending message.
+ *
+ * @param error Describes occurred error.
+ * @param message Message during sending which error occurred.
+ **/
+ virtual void OnTMMessageSendFailed(
+ const transport_manager::DataSendError &error,
+ const RawMessagePtr message);
+
+ virtual void OnConnectionEstablished(
+ const transport_manager::DeviceInfo &device_info,
+ const transport_manager::ConnectionUID &connection_id);
+
+ virtual void OnConnectionClosed(
+ const transport_manager::ConnectionUID &connection_id);
+
+ /**
+ * @brief Notifies subscribers about message
+ * received from mobile device.
+ * @param message Message with already parsed header.
+ */
+ void NotifySubscribers(const RawMessagePtr message);
+
+ /**
+ * \brief Sends message which size permits to send it in one frame.
+ * \param connection_handle Identifier of connection through which message
+ * is to be sent.
+ * \param session_id ID of session through which message is to be sent.
+ * \param protocol_version Version of Protocol used in message.
+ * \param service_type Type of session, RPC or BULK Data
+ * \param data_size Size of message excluding protocol header
+ * \param data Message string
+ * \param is_final_message if is_final_message = true - it is last message
+ * \return \saRESULT_CODE Status of operation
+ */
+ RESULT_CODE SendSingleFrameMessage(ConnectionID connection_id,
+ const uint8_t session_id,
+ uint32_t protocol_version,
+ const uint8_t service_type,
+ size_t data_size,
+ const uint8_t *data,
+ const bool is_final_message);
+
+ /**
+ * \brief Sends message which size doesn't permit to send it in one frame.
+ * \param connection_handle Identifier of connection through which message
+ * is to be sent.
+ * \param session_id ID of session through which message is to be sent.
+ * \param protocol_version Version of Protocol used in message.
+ * \param service_type Type of session, RPC or BULK Data
+ * \param data_size Size of message excluding protocol header
+ * \param data Message string
+ * \param max_data_size Maximum allowed size of single frame.
+ * \param is_final_message if is_final_message = true - it is last message
+ * \return \saRESULT_CODE Status of operation
+ */
+ RESULT_CODE SendMultiFrameMessage(ConnectionID connection_id,
+ const uint8_t session_id,
+ uint32_t protocol_version,
+ const uint8_t service_type,
+ const size_t data_size,
+ const uint8_t *data,
+ const size_t max_data_size,
+ const bool is_final_message);
+
+ /**
+ * \brief Sends message already containing protocol header.
+ * \param packet Message with protocol header
+ * \return \saRESULT_CODE Status of operation
+ */
+ RESULT_CODE SendFrame(const ProtocolFramePtr packet);
+
+ /**
+ * \brief Handles received message.
+ * \param connection_handle Identifier of connection through which message
+ * is received.
+ * \param packet Received message with protocol header.
+ * \return \saRESULT_CODE Status of operation
+ */
+ RESULT_CODE HandleMessage(
+ ConnectionID connection_id ,
+ const ProtocolFramePtr packet);
+
+ /**
+ * \brief Handles message received in single frame.
+ * \param connection_handle Identifier of connection through which message
+ * is received.
+ * \param packet Frame of message with protocol header.
+ * \return \saRESULT_CODE Status of operation
+ */
+ RESULT_CODE HandleSingleFrameMessage(
+ ConnectionID connection_id ,
+ const ProtocolFramePtr packet);
+ /**
+ * \brief Handles message received in multiple frames. Collects all frames
+ * of message.
+ * \param connection_handle Identifier of connection through which message
+ * is received.
+ * \param packet Current frame of message with protocol header.
+ * \return \saRESULT_CODE Status of operation
+ */
+ RESULT_CODE HandleMultiFrameMessage(
+ ConnectionID connection_id ,
+ const ProtocolFramePtr packet);
+
+ /**
+ * \brief Handles message received in single frame.
+ * \param connection_handle Identifier of connection through which message
+ * is received.
+ * \param packet Received message with protocol header.
+ * \return \saRESULT_CODE Status of operation
+ */
+ RESULT_CODE HandleControlMessage(
+ ConnectionID connection_id ,
+ const ProtocolFramePtr packet);
+
+ RESULT_CODE HandleControlMessageEndSession(
+ ConnectionID connection_id ,
+ const ProtocolPacket &packet);
+
+ RESULT_CODE HandleControlMessageStartSession(
+ ConnectionID connection_id ,
+ const ProtocolPacket &packet);
+
+ RESULT_CODE HandleControlMessageHeartBeat(
+ ConnectionID connection_id ,
+ const ProtocolPacket &packet);
+
+ /**
+ * \brief Sends Mobile Navi Ack message
+ */
+ RESULT_CODE SendMobileNaviAck(
+ ConnectionID connection_id ,
+ int32_t connection_key);
+
+ // threads::MessageLoopThread<*>::Handler implementations
+ // CALLED ON raw_ford_messages_from_mobile_ thread!
+ void Handle(const impl::RawFordMessageFromMobile message);
+ // CALLED ON raw_ford_messages_to_mobile_ thread!
+ void Handle(const impl::RawFordMessageToMobile message);
+
+#ifdef ENABLE_SECURITY
+ /**
+ * \brief Encryption/Decryption methodes for SecureSecvice check
+ * \param packet frame of message to encrypted/decrypted
+ */
+ RESULT_CODE EncryptFrame(ProtocolFramePtr packet);
+ RESULT_CODE DecryptFrame(ProtocolFramePtr packet);
+#endif // ENABLE_SECURITY
+ private:
+ /**
+ *\brief Pointer on instance of class implementing IProtocolObserver
+ *\brief (JSON Handler)
+ */
+ ProtocolObservers protocol_observers_;
+
+ /**
+ *\brief Pointer on instance of class implementing ISessionObserver
+ *\brief (Connection Handler)
+ */
+ SessionObserver *session_observer_;
+
+ /**
+ *\brief Pointer on instance of Transport layer handler for message exchange.
+ */
+ transport_manager::TransportManager *transport_manager_;
+
+ /**
+ *\brief Map of frames for messages received in multiple frames.
+ */
+ std::map<int32_t, ProtocolFramePtr> incomplete_multi_frame_messages_;
+
+ /**
+ * \brief Map of messages (frames) recieved over mobile nave session
+ * for map streaming.
+ */
+ MessagesOverNaviMap message_over_navi_session_;
+
+ /**
+ * \brief Untill specified otherwise, amount of message recievied
+ * over streaming session to send Ack
+ */
+ const uint32_t kPeriodForNaviAck;
+
+ /**
+ *\brief Counter of messages sent in each session.
+ */
+ std::map<uint8_t, uint32_t> message_counters_;
+
+ /**
+ *\brief map for session last message.
+ */
+ std::map<uint8_t, uint32_t> sessions_last_message_id_;
+
+ /**
+ *\brief Connections that must be closed after their last messages were sent
+ */
+ std::list<uint32_t> ready_to_close_connections_;
+
+
+ class IncomingDataHandler;
+ std::auto_ptr<IncomingDataHandler> incoming_data_handler_;
+
+#ifdef ENABLE_SECURITY
+ security_manager::SecurityManager *security_manager_;
+#endif // ENABLE_SECURITY
+
+ // Thread that pumps non-parsed messages coming from mobile side.
+ impl::FromMobileQueue raw_ford_messages_from_mobile_;
+ // Thread that pumps messages prepared to being sent to mobile side.
+ impl::ToMobileQueue raw_ford_messages_to_mobile_;
+
+ sync_primitives::Lock protocol_observers_lock_;
+
+#ifdef TIME_TESTER
+ PHMetricObserver *metric_observer_;
+#endif // TIME_TESTER
+};
+} // namespace protocol_handler
+
+#endif // SRC_COMPONENTS_PROTOCOL_HANDLER_INCLUDE_PROTOCOL_HANDLER_PROTOCOL_HANDLER_IMPL_H_