Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mconnectionhandlerpimpl.h Source File

m2mconnectionhandlerpimpl.h

00001 /*
00002  * Copyright (c) 2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #ifndef M2M_CONNECTION_HANDLER_PIMPL_H__
00017 #define M2M_CONNECTION_HANDLER_PIMPL_H__
00018 
00019 #include "ns_types.h"
00020 #include "ns_list.h"
00021 #include "eventOS_event.h"
00022 #include "mbed-client/m2mconfig.h"
00023 #include "mbed-client/m2mconstants.h"
00024 #include "mbed-client/m2minterface.h"
00025 #include "mbed-client/m2mconnectionobserver.h"
00026 #include "mbed-client/m2mconnectionsecurity.h"
00027 #include "nsdl-c/sn_nsdl.h"
00028 #include "pal.h"
00029 
00030 
00031 class M2MConnectionSecurity;
00032 class M2MConnectionHandler;
00033 class M2MSecurity;
00034 
00035 /**
00036  * @brief M2MConnectionHandlerPimpl.
00037  * This class handles the socket connection for LWM2M Client
00038  */
00039 
00040 
00041 class M2MConnectionHandlerPimpl {
00042 public:
00043 
00044     enum SocketEvent {
00045         ESocketIdle          = 0x00,
00046         ESocketCallback      = 0x02,
00047         ESocketConnect       = 0x04,
00048         ESocketSend          = 0x08,
00049         ESocketDnsResolved   = 0x10,
00050         ESocketDnsError      = 0x20,
00051         ESocketClose         = 0x40,
00052         ESocketTimerCallback = 0x80
00053     };
00054 
00055     /**
00056     * @brief Constructor
00057     */
00058     M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
00059                               M2MConnectionSecurity* sec,
00060                               M2MInterface::BindingMode mode,
00061                               M2MInterface::NetworkStack /*stack*/);
00062 
00063     /**
00064     * @brief Destructor
00065     */
00066     ~M2MConnectionHandlerPimpl();
00067 
00068     void start_timer(void);
00069 
00070     /**
00071     * @brief This binds the socket connection.
00072     * @param listen_port Port to listen for incoming connection.
00073     * @return true if successful else false.
00074     */
00075     bool bind_connection(const uint16_t listen_port);
00076 
00077     /**
00078     * @brief This resolves the server address. Output is
00079     * returned through callback
00080     * @param String server address.
00081     * @param uint16_t Server port.
00082     * @param ServerType, Server Type to be resolved.
00083     * @return true if address is valid else false.
00084     */
00085     bool resolve_server_address(const String& server_address,
00086                                 const uint16_t server_port,
00087                                 M2MConnectionObserver::ServerType server_type,
00088                                 const M2MSecurity* security);
00089 
00090     /**
00091     * @brief Sends data, to the connected sent to server.
00092     * @param data, Data to be sent.
00093     */
00094     bool send_data(uint8_t *data_ptr,
00095                    uint16_t data_len,
00096                    sn_nsdl_addr_s *address_ptr);
00097 
00098     /**
00099     * @brief Listens for incoming data from remote server
00100     * @return true if successful else false.
00101     */
00102     bool start_listening_for_data();
00103 
00104     /**
00105     * @brief Stops listening for incoming data
00106     */
00107     void stop_listening();
00108 
00109     /**
00110     * @brief Error handling for DTLS connectivity.
00111     * @param error, Error code from TLS library
00112     */
00113     void handle_connection_error(int error);
00114 
00115     /**
00116      * \brief Sets the network interface handler that is used by client to connect
00117      * to a network over IP..
00118      * \param handler A network interface handler that is used by client to connect.
00119      *  This API is optional but provides a mechanism for different platforms to
00120      * manage usage of underlying network interface by client.
00121      */
00122     void set_platform_network_handler(void *handler = NULL);
00123 
00124     /**
00125     * \brief Claims mutex to prevent thread clashes
00126     * in multithreaded environment.
00127     */
00128     void claim_mutex();
00129 
00130     /**
00131     * \brief Releases mutex to prevent thread clashes
00132     * in multithreaded environment.
00133     */
00134     void release_mutex();
00135 
00136     /**
00137     * @brief Callback handler for receiving data over socket.
00138     */
00139     void receive_handler();
00140 
00141     /**
00142     * @brief Returns true if DTLS handshake is still ongoing.
00143     */
00144     bool is_handshake_ongoing() const;
00145 
00146     /**
00147     * @brief Sends data to socket through event loop.
00148     */
00149     void send_socket_data();
00150 
00151     /**
00152     * @brief This function is used for generating socket events.
00153     */
00154     void send_socket_event(SocketEvent event_type);
00155 
00156     /**
00157     * @brief Does DNS resolving. Return true if DNS has been resolved
00158     * or triggered though DNS thread.
00159     */
00160     bool address_resolver(void);
00161 
00162     /**
00163      * @brief handler for eventloop events. Note, this needs to be public as it is called
00164      * from C wrapper.
00165      */
00166     void event_handler(arm_event_s *event);
00167 
00168     /**
00169     * \brief Closes the open connection.
00170     * \note This must be called from the same event loop context!
00171     */
00172     void force_close();
00173 
00174 private:
00175 
00176     /**
00177     * @brief Terminate the DNS thread, if any is used. The #ifdef magic is inside this
00178     * method, so it can be used without ifdef guards.
00179      */
00180     void terminate_dns_thread();
00181 
00182     /**
00183     * @brief Handles socket initialization and connect phase.
00184     */
00185     void socket_connect_handler();
00186 
00187     /**
00188     * @brief Callback handler for receiving data for secured connection.
00189     */
00190     void receive_handshake_handler();
00191 
00192     /**
00193     * @brief Callback handler for socket events.
00194     */
00195     void socket_event();
00196 
00197     /**
00198     * @brief Handles the result set by address_resolver.
00199     */
00200     void handle_dns_result(bool success);
00201 
00202 
00203     /**
00204     * @brief Initialize socket
00205     */
00206     bool init_socket();
00207 
00208     /**
00209     * @brief Check socket type
00210     * @return True if TCP connection otherwise false
00211     */
00212     bool is_tcp_connection() const;
00213 
00214     /**
00215     * @brief Close and delete socket
00216     */
00217     void close_socket();
00218 
00219 public:
00220 
00221     /**
00222      * @brief Internal helper for sending an event.
00223      */
00224     bool send_event(SocketEvent event_type);
00225 
00226 private:
00227     typedef struct send_data_queue {
00228         uint8_t *data;
00229         uint16_t offset;
00230         uint16_t data_len;
00231         ns_list_link_t link;
00232     } send_data_queue_s;
00233 
00234     /**
00235      * @brief Get first item from the queue list.
00236      */
00237     send_data_queue_s* get_item_from_list();
00238 
00239     /**
00240      * @brief Add queue data back to list.
00241      */
00242     void add_item_to_list(send_data_queue_s* data);
00243 
00244 private:
00245     enum SocketState {
00246 
00247         /* NOTE: Order of these values does matter, do not make unplanned changes to it. */
00248 
00249         /** Socket has not been initialized/connected yet. */
00250         ESocketStateDisconnected,
00251 
00252         /** pal_close() is in progress. */
00253         ESocketStateCloseBeingCalled,
00254 
00255         /** DNS resolving in progress. */
00256         ESocketStateDNSResolving,
00257 
00258         /** DNS resolving done, connection needs to be initialized.  */
00259         EsocketStateInitializeConnection,
00260 
00261         /** pal_connect() is in progress. */
00262         ESocketStateConnectBeingCalled,
00263 
00264         /** pal_connect() has been called and we are waiting for asynchronous response. */
00265         ESocketStateConnecting,
00266 
00267         /** pal_connect is complete and the (D)TLS handshake is to be done if in secure mode. */
00268         ESocketStateConnected,
00269 
00270         /** (D)TLS Handshaking in progress */
00271         ESocketStateHandshaking,
00272 
00273         /** Unsecure Connection to the server has been established */
00274         ESocketStateUnsecureConnection,
00275 
00276         /** Secure Connection to the server has been established */
00277         ESocketStateSecureConnection
00278     };
00279 
00280     typedef NS_LIST_HEAD(send_data_queue_s, link) send_data_list_t;
00281 
00282     M2MConnectionHandler                        *_base;
00283     M2MConnectionObserver                       &_observer;
00284     M2MConnectionSecurity                       *_security_impl; //owned
00285     const M2MSecurity                           *_security; //non-owned
00286     M2MInterface::BindingMode                   _binding_mode;
00287     M2MConnectionObserver::SocketAddress        _address;
00288 
00289     // _address._address will point to one of these two
00290     palIpV4Addr_t                               _ipV4Addr;
00291     palIpV6Addr_t                               _ipV6Addr;
00292 
00293     palSocket_t                                 _socket;
00294     M2MConnectionObserver::ServerType           _server_type;
00295     uint16_t                                    _server_port;
00296     uint16_t                                    _listen_port;
00297     uint32_t                                    _net_iface;
00298 #if (PAL_DNS_API_VERSION < 2)
00299     palSocketLength_t                           _socket_address_len;
00300 #endif
00301 #if MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
00302 #if (PAL_DNS_API_VERSION == 2)
00303     palDNSQuery_t                                _handler_async_DNS;
00304 #endif
00305 #endif
00306     volatile palSocketAddress_t                 _socket_address;
00307     static int8_t                               _tasklet_id;
00308     String                                      _server_address;
00309 
00310     // A state variable for the socket itself, which is needed to handle the
00311     // asynchronous events and callbacks. Note: the state may be accessed from
00312     // event sender and receiver threads.
00313     SocketState                                 _socket_state;
00314     uint8_t                                     _handshake_retry;
00315 
00316     /**
00317      * This is a flag which is set before sending a socket callback event
00318      * and cleared when the event handler side is started. It is meant to get rid of
00319      * event storm which happens whenever one socket transfers data and spurious
00320      * events are sent to all the other sockets.
00321      */
00322     volatile bool                               _suppressable_event_in_flight;
00323 
00324     send_data_list_t                            _linked_list_send_data;
00325 
00326     bool                                        _secure_connection;
00327 
00328 friend class Test_M2MConnectionHandlerPimpl;
00329 friend class Test_M2MConnectionHandlerPimpl_mbed;
00330 friend class Test_M2MConnectionHandlerPimpl_classic;
00331 friend class M2MConnection_TestObserver;
00332 };
00333 
00334 #endif //M2M_CONNECTION_HANDLER_PIMPL_H__