Simple interface for Mbed Cloud Client

Dependents:  

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     };
00053 
00054     /**
00055     * @brief Constructor
00056     */
00057     M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
00058                               M2MConnectionSecurity* sec,
00059                               M2MInterface::BindingMode mode,
00060                               M2MInterface::NetworkStack /*stack*/);
00061 
00062     /**
00063     * @brief Destructor
00064     */
00065     ~M2MConnectionHandlerPimpl();
00066 
00067     void start_timer(void);
00068 
00069     /**
00070     * @brief This binds the socket connection.
00071     * @param listen_port Port to listen for incoming connection.
00072     * @return true if successful else false.
00073     */
00074     bool bind_connection(const uint16_t listen_port);
00075 
00076     /**
00077     * @brief This resolves the server address. Output is
00078     * returned through callback
00079     * @param String server address.
00080     * @param uint16_t Server port.
00081     * @param ServerType, Server Type to be resolved.
00082     * @return true if address is valid else false.
00083     */
00084     bool resolve_server_address(const String& server_address,
00085                                 const uint16_t server_port,
00086                                 M2MConnectionObserver::ServerType server_type,
00087                                 const M2MSecurity* security);
00088 
00089     /**
00090     * @brief Sends data, to the connected sent to server.
00091     * @param data, Data to be sent.
00092     */
00093     bool send_data(uint8_t *data_ptr,
00094                    uint16_t data_len,
00095                    sn_nsdl_addr_s *address_ptr);
00096 
00097     /**
00098     * @brief Listens for incoming data from remote server
00099     * @return true if successful else false.
00100     */
00101     bool start_listening_for_data();
00102 
00103     /**
00104     * @brief Stops listening for incoming data
00105     */
00106     void stop_listening();
00107 
00108     /**
00109     * @brief Error handling for DTLS connectivity.
00110     * @param error, Error code from TLS library
00111     */
00112     void handle_connection_error(int error);
00113 
00114     /**
00115      * \brief Sets the network interface handler that is used by client to connect
00116      * to a network over IP..
00117      * \param handler A network interface handler that is used by client to connect.
00118      *  This API is optional but provides a mechanism for different platforms to
00119      * manage usage of underlying network interface by client.
00120      */
00121     void set_platform_network_handler(void *handler = NULL);
00122 
00123     /**
00124     * \brief Claims mutex to prevent thread clashes
00125     * in multithreaded environment.
00126     */
00127     void claim_mutex();
00128 
00129     /**
00130     * \brief Releases mutex to prevent thread clashes
00131     * in multithreaded environment.
00132     */
00133     void release_mutex();
00134 
00135     /**
00136     * @brief Callback handler for receiving data over socket.
00137     */
00138     void receive_handler();
00139 
00140     /**
00141     * @brief Returns true if DTLS handshake is still ongoing.
00142     */
00143     bool is_handshake_ongoing() const;
00144 
00145     /**
00146     * @brief Sends data to socket through event loop.
00147     */
00148     void send_socket_data();
00149 
00150     /**
00151     * @brief This function is used for generating socket events.
00152     */
00153     void send_socket_event(SocketEvent event_type);
00154 
00155     /**
00156     * @brief Does DNS resolving, called by dns_thread.
00157     */
00158     void address_resolver(void);
00159 
00160     /**
00161      * @brief handler for eventloop events. Note, this needs to be public as it is called
00162      * from C wrapper.
00163      */
00164     void event_handler(arm_event_s *event);
00165 
00166 private:
00167 
00168     /**
00169     * @brief Terminate the DNS thread, if any is used. The #ifdef magic is inside this
00170     * method, so it can be used without ifdef guards.
00171      */
00172     void terminate_dns_thread();
00173 
00174     /**
00175     * @brief Handles socket initialization and connect phase.
00176     */
00177     void socket_connect_handler();
00178 
00179     /**
00180     * @brief Callback handler for receiving data for secured connection.
00181     */
00182     void receive_handshake_handler();
00183 
00184     /**
00185     * @brief Callback handler for socket events.
00186     */
00187     void socket_event();
00188 
00189     /**
00190     * @brief Handles the result set by address_resolver.
00191     */
00192     void handle_dns_result(bool success);
00193 
00194 
00195     /**
00196     * @brief Initialize socket
00197     */
00198     bool init_socket();
00199 
00200     /**
00201     * @brief Check socket type
00202     * @return True if TCP connection otherwise false
00203     */
00204     bool is_tcp_connection() const;
00205 
00206     /**
00207     * @brief Close and delete socket
00208     */
00209     void close_socket();
00210 
00211     /**
00212     * @brief Enables keepalive for TCP connections.
00213     */
00214     void enable_keepalive();
00215 
00216     /**
00217      * @brief Internal helper for sending an event.
00218      */
00219     bool send_event(SocketEvent event_type);
00220 
00221     typedef struct send_data_queue {
00222         uint8_t *data;
00223         uint16_t offset;
00224         uint16_t data_len;
00225         ns_list_link_t link;
00226     } send_data_queue_s;
00227 
00228     /**
00229      * @brief Get first item from the queue list.
00230      */
00231     send_data_queue_s* get_item_from_list();
00232 
00233     /**
00234      * @brief Add queue data back to list.
00235      */
00236     void add_item_to_list(send_data_queue_s* data);
00237 
00238 private:
00239     enum SocketState {
00240 
00241         /* NOTE: Order of these values does matter, do not make unplanned changes to it. */
00242 
00243         /** Socket has not been initialized/connected yet. */
00244         ESocketStateDisconnected,
00245 
00246         /** pal_close() is in progress. */
00247         ESocketStateCloseBeingCalled,
00248 
00249         /** DNS resolving in progress. */
00250         ESocketStateDNSResolving,
00251 
00252         /** DNS resolving done, connection needs to be initialized.  */
00253         EsocketStateInitializeConnection,
00254 
00255         /** pal_connect() is in progress. */
00256         ESocketStateConnectBeingCalled,
00257 
00258         /** pal_connect() has been called and we are waiting for asynchronous response. */
00259         ESocketStateConnecting,
00260 
00261         /** pal_connect is complete and the (D)TLS handshake is to be done if in secure mode. */
00262         ESocketStateConnected,
00263 
00264         /** (D)TLS Handshaking in progress */
00265         ESocketStateHandshaking,
00266 
00267         /** Unsecure Connection to the server has been established */
00268         ESocketStateUnsecureConnection,
00269 
00270         /** Secure Connection to the server has been established */
00271         ESocketStateSecureConnection
00272     };
00273 
00274     typedef NS_LIST_HEAD(send_data_queue_s, link) send_data_list_t;
00275 
00276     M2MConnectionHandler                        *_base;
00277     M2MConnectionObserver                       &_observer;
00278     M2MConnectionSecurity                       *_security_impl; //owned
00279     const M2MSecurity                           *_security; //non-owned
00280     M2MInterface::BindingMode                   _binding_mode;
00281     M2MConnectionObserver::SocketAddress        _address;
00282 
00283     // _address._address will point to one of these two
00284     palIpV4Addr_t                               _ipV4Addr;
00285     palIpV6Addr_t                               _ipV6Addr;
00286 
00287     palSocket_t                                 _socket;
00288     M2MConnectionObserver::ServerType           _server_type;
00289     uint16_t                                    _server_port;
00290     uint16_t                                    _listen_port;
00291     uint32_t                                    _net_iface;
00292     volatile palSocketAddress_t                 _socket_address;
00293     static int8_t                               _tasklet_id;
00294     String                                      _server_address;
00295 
00296 #ifdef MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
00297     palThreadID_t                               _dns_thread_id;
00298 #endif
00299 
00300     // A state variable for the socket itself, which is needed to handle the
00301     // asynchronous events and callbacks. Note: the state may be accessed from
00302     // event sender and receiver threads.
00303     SocketState                                 _socket_state;
00304     uint8_t                                     _handshake_retry;
00305 
00306     /**
00307      * This is a flag which is set before sending a socket callback event
00308      * and cleared when the event handler side is started. It is meant to get rid of
00309      * event storm which happens whenever one socket transfers data and spurious
00310      * events are sent to all the other sockets.
00311      */
00312     volatile bool                               _suppressable_event_in_flight;
00313 
00314     send_data_list_t                            _linked_list_send_data;
00315 
00316     bool                                        _secure_connection;
00317 
00318 friend class Test_M2MConnectionHandlerPimpl;
00319 friend class Test_M2MConnectionHandlerPimpl_mbed;
00320 friend class Test_M2MConnectionHandlerPimpl_classic;
00321 friend class M2MConnection_TestObserver;
00322 };
00323 
00324 #endif //M2M_CONNECTION_HANDLER_PIMPL_H__