mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #2249 from c1728p9/client_nanostack_and_seperated
Client nanostack and seperatedpull/2230/merge
commit
5d7317626c
|
@ -0,0 +1,83 @@
|
|||
# How to contribute
|
||||
|
||||
This directory structure is entirely generated or copied from another repositories. Do not send patches against it, they cannot be accepted because all code will be entirely overwritten on next release.
|
||||
|
||||
Instead follow these instructions to send and test your contributions against master repositories.
|
||||
|
||||
## Directory structure
|
||||
|
||||
This directory consist of following modules
|
||||
|
||||
* [mbed-client](#mbed-client)
|
||||
* [mbed-client-c](#mbed-client-c)
|
||||
* [mbed-client-mbed-tls](#mbed-client-mbed-tls)
|
||||
* [mbed-client-classic](#mbed-client-classic)
|
||||
* [mbed-client-randlib](#mbed-client-randlib)
|
||||
* [coap-service](#coap-service)
|
||||
|
||||
|
||||
## mbed-client
|
||||
|
||||
mbed-cient is copied from master repository from here: https://github.com/ARMmbed/mbed-client
|
||||
|
||||
To replace the copied version with master repository follow these steps:
|
||||
|
||||
* Remove mbed-client directory: `rm -rf mbed-client`
|
||||
* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client.git`
|
||||
|
||||
Now you have mbed-client directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests.
|
||||
|
||||
## mbed-client-c
|
||||
|
||||
mbed-client-c is copied from master repository from here: https://github.com/ARMmbed/mbed-client-c
|
||||
|
||||
To replace the copied version with master repository follow these steps:
|
||||
|
||||
* Remove mbed-client-c directory: `rm -rf mbed-client-c`
|
||||
* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client-c.git`
|
||||
|
||||
Now you have mbed-client-c directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests.
|
||||
|
||||
## mbed-client-classic
|
||||
|
||||
mbed-client-classic is copied from master repository from here: https://github.com/ARMmbed/mbed-client-classic
|
||||
|
||||
To replace the copied version with master repository follow these steps:
|
||||
|
||||
* Remove mbed-client-classic directory: `rm -rf mbed-client-classic`
|
||||
* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client-classic.git`
|
||||
|
||||
Now you have mbed-client-classic directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests.
|
||||
|
||||
## mbed-client-mbed-tls
|
||||
|
||||
mbed-client-mbed-tls is copied from master repository from here: https://github.com/ARMmbed/mbed-client-mbed-tls
|
||||
|
||||
To replace the copied version with master repository follow these steps:
|
||||
|
||||
* Remove mbed-client-mbed-tls directory: `rm -rf mbed-client-mbed-tls`
|
||||
* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client-mbed-tls.git`
|
||||
|
||||
Now you have mbed-client-mbed-tls directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests.
|
||||
|
||||
## mbed-client-randlib
|
||||
|
||||
mbed-client-randlib is copied from master repository from here: https://github.com/ARMmbed/mbed-client-randlib
|
||||
|
||||
To replace the copied version with master repository follow these steps:
|
||||
|
||||
* Remove mbed-client-randlib directory: `rm -rf mbed-client-randlib`
|
||||
* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client-randlib.git`
|
||||
|
||||
Now you have mbed-client-randlib directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests.
|
||||
|
||||
## coap-service
|
||||
|
||||
coap-service is copied from master repository from here: https://github.com/ARMmbed/coap-service
|
||||
|
||||
To replace the copied version with master repository follow these steps:
|
||||
|
||||
* Remove coap-service directory: `rm -rf coap-service`
|
||||
* Clone from the master: `git clone git@github.com:ARMmbed/coap-service.git`
|
||||
|
||||
Now you have coap-service directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests.
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License 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.
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_CONNECTION_HANDLER_PIMPL_H__
|
||||
#define M2M_CONNECTION_HANDLER_PIMPL_H__
|
||||
|
||||
#include "ns_types.h"
|
||||
#include "mbed-client/m2mconfig.h"
|
||||
#include "mbed-client/m2mconstants.h"
|
||||
#include "mbed-client/m2minterface.h"
|
||||
#include "mbed-client/m2mconnectionobserver.h"
|
||||
#include "mbed-client/m2mconnectionsecurity.h"
|
||||
#include "nsdl-c/sn_nsdl.h"
|
||||
|
||||
#include "Socket.h"
|
||||
|
||||
|
||||
class M2MConnectionSecurity;
|
||||
class M2MConnectionHandler;
|
||||
class M2MSecurity;
|
||||
|
||||
/**
|
||||
* @brief M2MConnectionHandlerPimpl.
|
||||
* This class handles the socket connection for LWM2M Client
|
||||
*/
|
||||
|
||||
|
||||
class M2MConnectionHandlerPimpl {
|
||||
public:
|
||||
|
||||
enum SocketEvent {
|
||||
ESocketIdle = 0x00,
|
||||
ESocketReadytoRead = 0x02,
|
||||
ESocketDnsHandler = 0x04,
|
||||
ESocketSend = 0x08
|
||||
};
|
||||
|
||||
struct TaskIdentifier {
|
||||
M2MConnectionHandlerPimpl *pimpl;
|
||||
void *data_ptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
|
||||
M2MConnectionSecurity* sec,
|
||||
M2MInterface::BindingMode mode,
|
||||
M2MInterface::NetworkStack stack);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~M2MConnectionHandlerPimpl();
|
||||
|
||||
/**
|
||||
* @brief This binds the socket connection.
|
||||
* @param listen_port Port to listen for incoming connection.
|
||||
* @return true if successful else false.
|
||||
*/
|
||||
bool bind_connection(const uint16_t listen_port);
|
||||
|
||||
/**
|
||||
* @brief This resolves the server address. Output is
|
||||
* returned through callback
|
||||
* @param String server address.
|
||||
* @param uint16_t Server port.
|
||||
* @param ServerType, Server Type to be resolved.
|
||||
* @return true if address is valid else false.
|
||||
*/
|
||||
bool resolve_server_address(const String& server_address,
|
||||
const uint16_t server_port,
|
||||
M2MConnectionObserver::ServerType server_type,
|
||||
const M2MSecurity* security);
|
||||
|
||||
/**
|
||||
* @brief Sends data, to the connected sent to server.
|
||||
* @param data, Data to be sent.
|
||||
*/
|
||||
bool send_data(uint8_t *data_ptr,
|
||||
uint16_t data_len,
|
||||
sn_nsdl_addr_s *address_ptr);
|
||||
|
||||
/**
|
||||
* @brief Listens for incoming data from remote server
|
||||
* @return true if successful else false.
|
||||
*/
|
||||
bool start_listening_for_data();
|
||||
|
||||
/**
|
||||
* @brief Stops listening for incoming data
|
||||
*/
|
||||
void stop_listening();
|
||||
|
||||
/**
|
||||
* @brief send_to_socket Sends directly to socket. This is used by
|
||||
* security classes to send after data has been encrypted.
|
||||
* @param buf Buffer to send
|
||||
* @param len Length of a buffer
|
||||
* @return Number of bytes sent or -1 if failed
|
||||
*/
|
||||
int send_to_socket(const unsigned char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Receives directly from the socket. This
|
||||
* is used by the security classes to receive raw data to be decrypted.
|
||||
* \param buf Buffer to send.
|
||||
* \param len The length of the buffer.
|
||||
* \param timeout Timeout defined from DTLS to wait for blocking receive calls
|
||||
* before timing out, by default value is 0.
|
||||
* \return Number of bytes read or negative number if failed.
|
||||
*/
|
||||
int receive_from_socket(unsigned char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Error handling for DTLS connectivity.
|
||||
* @param error, Error code from TLS library
|
||||
*/
|
||||
void handle_connection_error(int error);
|
||||
|
||||
/**
|
||||
* \brief Sets the network interface handler that is used by client to connect
|
||||
* to a network over IP..
|
||||
* \param handler A network interface handler that is used by client to connect.
|
||||
* This API is optional but provides a mechanism for different platforms to
|
||||
* manage usage of underlying network interface by client.
|
||||
*/
|
||||
void set_platform_network_handler(void *handler = NULL);
|
||||
|
||||
/**
|
||||
* \brief Claims mutex to prevent thread clashes
|
||||
* in multithreaded environment.
|
||||
*/
|
||||
void claim_mutex();
|
||||
|
||||
/**
|
||||
* \brief Releases mutex to prevent thread clashes
|
||||
* in multithreaded environment.
|
||||
*/
|
||||
void release_mutex();
|
||||
|
||||
/**
|
||||
* @brief Callback handler for sending data over socket.
|
||||
*/
|
||||
void send_handler();
|
||||
|
||||
/**
|
||||
* @brief Callback handler for receiving data over socket.
|
||||
*/
|
||||
void receive_handler();
|
||||
|
||||
/**
|
||||
* @brief Callback handler for receiving data for secured connection.
|
||||
*/
|
||||
void receive_handshake_handler();
|
||||
|
||||
/**
|
||||
* @brief Returns true if DTLS handshake is still ongoing.
|
||||
*/
|
||||
bool is_handshake_ongoing();
|
||||
|
||||
/**
|
||||
* @brief Returns connection handler tasklet ID.
|
||||
*/
|
||||
int8_t connection_tasklet_handler();
|
||||
|
||||
/**
|
||||
* @brief Handles DNS resolving through event loop.
|
||||
*/
|
||||
void dns_handler();
|
||||
|
||||
/**
|
||||
* @brief Sends data to socket through event loop.
|
||||
*/
|
||||
void send_socket_data(uint8_t *data, uint16_t data_len);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Callback handler for socket events.
|
||||
*/
|
||||
void socket_event();
|
||||
|
||||
/**
|
||||
* @brief Initialize mbed OS socket
|
||||
*/
|
||||
void init_socket();
|
||||
|
||||
/**
|
||||
* @brief Check socket type
|
||||
* @return True if TCP connection otherwise false
|
||||
*/
|
||||
bool is_tcp_connection();
|
||||
|
||||
/**
|
||||
* @brief Close and delete socket
|
||||
*/
|
||||
void close_socket();
|
||||
|
||||
/**
|
||||
* @brief Enables keepalive for TCP connections.
|
||||
*/
|
||||
void enable_keepalive();
|
||||
|
||||
private:
|
||||
M2MConnectionHandler *_base;
|
||||
M2MConnectionObserver &_observer;
|
||||
M2MConnectionSecurity *_security_impl; //owned
|
||||
const M2MSecurity *_security; //non-owned
|
||||
bool _use_secure_connection;
|
||||
M2MInterface::BindingMode _binding_mode;
|
||||
M2MInterface::NetworkStack _network_stack;
|
||||
M2MConnectionObserver::SocketAddress _address;
|
||||
unsigned char _address_buffer[NSAPI_IP_SIZE];
|
||||
Socket *_socket;
|
||||
bool _is_handshaking;
|
||||
bool _listening;
|
||||
M2MConnectionObserver::ServerType _server_type;
|
||||
uint16_t _server_port;
|
||||
uint16_t _listen_port;
|
||||
bool _running;
|
||||
unsigned char _recv_buffer[BUFFER_LENGTH];
|
||||
NetworkInterface *_net_iface; //doesn't own
|
||||
SocketAddress *_socket_address;
|
||||
static int8_t _tasklet_id;
|
||||
String _server_address;
|
||||
|
||||
friend class Test_M2MConnectionHandlerPimpl;
|
||||
friend class Test_M2MConnectionHandlerPimpl_mbed;
|
||||
friend class M2MConnection_TestObserver;
|
||||
};
|
||||
|
||||
#endif //M2M_CONNECTION_HANDLER_PIMPL_H__
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_TIMER_PIMPL_H__
|
||||
#define M2M_TIMER_PIMPL_H__
|
||||
|
||||
#include "ns_types.h"
|
||||
|
||||
#include "mbed-client/m2mtimerobserver.h"
|
||||
|
||||
class M2MTimerPimpl {
|
||||
private:
|
||||
|
||||
// Prevents the use of assignment operator
|
||||
M2MTimerPimpl& operator=(const M2MTimerPimpl& other);
|
||||
|
||||
// Prevents the use of copy constructor
|
||||
M2MTimerPimpl(const M2MTimerPimpl& other);
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
M2MTimerPimpl(M2MTimerObserver& _observer);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~M2MTimerPimpl();
|
||||
|
||||
/**
|
||||
* Starts timer
|
||||
* @param interval Timer's interval in milliseconds
|
||||
* @param single_shot defines if timer is ticked
|
||||
* once or is it restarted everytime timer is expired.
|
||||
*/
|
||||
void start_timer(uint64_t interval, M2MTimerObserver::Type type, bool single_shot = true);
|
||||
|
||||
/**
|
||||
* @brief Starts timer in DTLS manner
|
||||
* @param intermediate_interval Intermediate interval to use, must be smaller than tiotal (usually 1/4 of total)
|
||||
* @param total_interval Total interval to use; This is the timeout value of a DTLS packet
|
||||
* @param type Type of the timer
|
||||
*/
|
||||
void start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type);
|
||||
|
||||
/**
|
||||
* Stops timer.
|
||||
* This cancels the ongoing timer.
|
||||
*/
|
||||
void stop_timer();
|
||||
|
||||
/**
|
||||
* Callback function for timer completion.
|
||||
*/
|
||||
void timer_expired();
|
||||
|
||||
/**
|
||||
* @brief Checks if the intermediate interval has passed
|
||||
* @return true if interval has passed, false otherwise
|
||||
*/
|
||||
bool is_intermediate_interval_passed();
|
||||
|
||||
/**
|
||||
* @brief Checks if the total interval has passed
|
||||
* @return true if interval has passed, false otherwise
|
||||
*/
|
||||
bool is_total_interval_passed();
|
||||
|
||||
inline int8_t get_timer_id() const;
|
||||
|
||||
private:
|
||||
|
||||
void start();
|
||||
void cancel();
|
||||
|
||||
private:
|
||||
M2MTimerObserver& _observer;
|
||||
bool _single_shot;
|
||||
uint64_t _interval;
|
||||
M2MTimerObserver::Type _type;
|
||||
|
||||
uint64_t _intermediate_interval;
|
||||
uint64_t _total_interval;
|
||||
uint8_t _status;
|
||||
bool _dtls_type;
|
||||
|
||||
// this is the timer-id of this object, used to map the
|
||||
// timer event callback to the correct object.
|
||||
int8_t _timer_id;
|
||||
|
||||
static int8_t _tasklet_id;
|
||||
static int8_t _next_timer_id;
|
||||
|
||||
friend class M2MTimer;
|
||||
};
|
||||
|
||||
inline int8_t M2MTimerPimpl::get_timer_id() const
|
||||
{
|
||||
return _timer_id;
|
||||
}
|
||||
|
||||
#endif //M2M_TIMER_PIMPL_H__
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "mbed-client-classic/m2mconnectionhandlerpimpl.h"
|
||||
#include "mbed-client/m2mconnectionobserver.h"
|
||||
#include "mbed-client/m2mconnectionhandler.h"
|
||||
#include "mbed-client/m2mconstants.h"
|
||||
|
||||
M2MConnectionHandler::M2MConnectionHandler(M2MConnectionObserver &observer,
|
||||
M2MConnectionSecurity* sec,
|
||||
M2MInterface::BindingMode mode,
|
||||
M2MInterface::NetworkStack stack)
|
||||
:_observer(observer)
|
||||
{
|
||||
_private_impl = new M2MConnectionHandlerPimpl(this, observer, sec, mode, stack);
|
||||
}
|
||||
|
||||
M2MConnectionHandler::~M2MConnectionHandler()
|
||||
{
|
||||
delete _private_impl;
|
||||
}
|
||||
|
||||
bool M2MConnectionHandler::bind_connection(const uint16_t listen_port)
|
||||
{
|
||||
|
||||
return _private_impl->bind_connection(listen_port);
|
||||
}
|
||||
|
||||
bool M2MConnectionHandler::resolve_server_address(const String& server_address,
|
||||
const uint16_t server_port,
|
||||
M2MConnectionObserver::ServerType server_type,
|
||||
const M2MSecurity* security)
|
||||
{
|
||||
return _private_impl->resolve_server_address(server_address, server_port,
|
||||
server_type, security);
|
||||
}
|
||||
|
||||
bool M2MConnectionHandler::start_listening_for_data()
|
||||
{
|
||||
return _private_impl->start_listening_for_data();
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::stop_listening()
|
||||
{
|
||||
_private_impl->stop_listening();
|
||||
}
|
||||
|
||||
int M2MConnectionHandler::send_to_socket(const unsigned char *buf, size_t len)
|
||||
{
|
||||
return _private_impl->send_to_socket(buf, len);
|
||||
}
|
||||
|
||||
int M2MConnectionHandler::receive_from_socket(unsigned char *buf, size_t len)
|
||||
{
|
||||
return _private_impl->receive_from_socket(buf, len);
|
||||
}
|
||||
|
||||
bool M2MConnectionHandler::send_data(uint8_t *data,
|
||||
uint16_t data_len,
|
||||
sn_nsdl_addr_s *address)
|
||||
{
|
||||
return _private_impl->send_data(data, data_len, address);
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::handle_connection_error(int error)
|
||||
{
|
||||
_private_impl->handle_connection_error(error);
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::set_platform_network_handler(void *handler)
|
||||
{
|
||||
_private_impl->set_platform_network_handler(handler);
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::claim_mutex()
|
||||
{
|
||||
_private_impl->claim_mutex();
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::release_mutex()
|
||||
{
|
||||
_private_impl->release_mutex();
|
||||
}
|
|
@ -0,0 +1,574 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "mbed-client-classic/m2mconnectionhandlerpimpl.h"
|
||||
#include "mbed-client/m2mconnectionobserver.h"
|
||||
#include "mbed-client/m2mconstants.h"
|
||||
#include "mbed-client/m2msecurity.h"
|
||||
#include "mbed-client/m2mconnectionhandler.h"
|
||||
|
||||
#include "NetworkInterface.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "TCPSocket.h"
|
||||
|
||||
#include "eventOS_event.h"
|
||||
#include "eventOS_scheduler.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
|
||||
#define TRACE_GROUP "mClt"
|
||||
|
||||
int8_t M2MConnectionHandlerPimpl::_tasklet_id = -1;
|
||||
|
||||
extern "C" void connection_tasklet_event_handler(arm_event_s *event)
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::connection_tasklet_event_handler");
|
||||
M2MConnectionHandlerPimpl::TaskIdentifier *task_id = (M2MConnectionHandlerPimpl::TaskIdentifier*)event->data_ptr;
|
||||
M2MConnectionHandlerPimpl* pimpl = (M2MConnectionHandlerPimpl*)task_id->pimpl;
|
||||
if(pimpl) {
|
||||
eventOS_scheduler_set_active_tasklet(pimpl->connection_tasklet_handler());
|
||||
}
|
||||
switch (event->event_type) {
|
||||
case M2MConnectionHandlerPimpl::ESocketIdle:
|
||||
tr_debug("Connection Tasklet Generated");
|
||||
break;
|
||||
case M2MConnectionHandlerPimpl::ESocketReadytoRead:
|
||||
tr_debug("connection_tasklet_event_handler - ESocketReadytoRead");
|
||||
if(pimpl) {
|
||||
if(pimpl->is_handshake_ongoing()) {
|
||||
pimpl->receive_handshake_handler();
|
||||
} else {
|
||||
pimpl->receive_handler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case M2MConnectionHandlerPimpl::ESocketDnsHandler:
|
||||
tr_debug("connection_tasklet_event_handler - ESocketDnsHandler");
|
||||
if(pimpl) {
|
||||
pimpl->dns_handler();
|
||||
}
|
||||
break;
|
||||
case M2MConnectionHandlerPimpl::ESocketSend:
|
||||
tr_debug("connection_tasklet_event_handler - ESocketSend");
|
||||
if(pimpl) {
|
||||
pimpl->send_socket_data((uint8_t*)task_id->data_ptr,(uint16_t)event->event_data);
|
||||
if (task_id->data_ptr) {
|
||||
free(task_id->data_ptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (task_id) {
|
||||
free(task_id);
|
||||
}
|
||||
}
|
||||
|
||||
M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
|
||||
M2MConnectionSecurity* sec,
|
||||
M2MInterface::BindingMode mode,
|
||||
M2MInterface::NetworkStack stack)
|
||||
:_base(base),
|
||||
_observer(observer),
|
||||
_security_impl(sec),
|
||||
_use_secure_connection(false),
|
||||
_binding_mode(mode),
|
||||
_network_stack(stack),
|
||||
_socket(0),
|
||||
_is_handshaking(false),
|
||||
_listening(true),
|
||||
_server_type(M2MConnectionObserver::LWM2MServer),
|
||||
_server_port(0),
|
||||
_listen_port(0),
|
||||
_running(false),
|
||||
_net_iface(0),
|
||||
_socket_address(0)
|
||||
{
|
||||
memset(&_address_buffer, 0, sizeof _address_buffer);
|
||||
memset(&_address, 0, sizeof _address);
|
||||
_address._address = _address_buffer;
|
||||
|
||||
if (_network_stack != M2MInterface::LwIP_IPv4) {
|
||||
error("ConnectionHandler: Unsupported network stack, only IPv4 is currently supported");
|
||||
}
|
||||
_running = true;
|
||||
tr_debug("M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl() - Initializing thread");
|
||||
eventOS_scheduler_mutex_wait();
|
||||
if (M2MConnectionHandlerPimpl::_tasklet_id == -1) {
|
||||
M2MConnectionHandlerPimpl::_tasklet_id = eventOS_event_handler_create(&connection_tasklet_event_handler, ESocketIdle);
|
||||
}
|
||||
eventOS_scheduler_mutex_release();
|
||||
}
|
||||
|
||||
M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()");
|
||||
if (_socket) {
|
||||
delete _socket;
|
||||
_socket = 0;
|
||||
}
|
||||
_net_iface = 0;
|
||||
delete _security_impl;
|
||||
tr_debug("M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl() - OUT");
|
||||
}
|
||||
|
||||
bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port)
|
||||
{
|
||||
_listen_port = listen_port;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address,
|
||||
const uint16_t server_port,
|
||||
M2MConnectionObserver::ServerType server_type,
|
||||
const M2MSecurity* security)
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::resolve_server_address()");
|
||||
if (!_net_iface) {
|
||||
return false;
|
||||
}
|
||||
_security = security;
|
||||
_server_port = server_port;
|
||||
_server_type = server_type;
|
||||
_server_address = server_address;
|
||||
TaskIdentifier* task = (TaskIdentifier*)malloc(sizeof(TaskIdentifier));
|
||||
if (!task) {
|
||||
return false;
|
||||
}
|
||||
task->pimpl = this;
|
||||
|
||||
arm_event_s event;
|
||||
event.receiver = M2MConnectionHandlerPimpl::_tasklet_id;
|
||||
event.sender = 0;
|
||||
event.event_type = ESocketDnsHandler;
|
||||
event.data_ptr = task;
|
||||
event.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
|
||||
return eventOS_event_send(&event) == 0 ? true : false;
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::dns_handler()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::dns_handler()");
|
||||
_socket_address = new SocketAddress(_net_iface,_server_address.c_str(), _server_port);
|
||||
if(*_socket_address) {
|
||||
_address._address = (void*)_socket_address->get_ip_address();
|
||||
tr_debug("IP Address %s",_socket_address->get_ip_address());
|
||||
tr_debug("Port %d",_socket_address->get_port());
|
||||
_address._length = strlen((char*)_address._address);
|
||||
_address._port = _socket_address->get_port();
|
||||
_address._stack = _network_stack;
|
||||
} else {
|
||||
_observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR, true);
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
|
||||
close_socket();
|
||||
init_socket();
|
||||
|
||||
if(is_tcp_connection()) {
|
||||
tr_debug("M2MConnectionHandlerPimpl::resolve_server_address - Using TCP");
|
||||
if (((TCPSocket*)_socket)->connect(*_socket_address) < 0) {
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_running = true;
|
||||
|
||||
if (_security) {
|
||||
if (_security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate ||
|
||||
_security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) {
|
||||
|
||||
if( _security_impl != NULL ){
|
||||
_security_impl->reset();
|
||||
if (_security_impl->init(_security) == 0) {
|
||||
_is_handshaking = true;
|
||||
tr_debug("M2MConnectionHandlerPimpl::resolve_server_address - connect DTLS");
|
||||
if(_security_impl->start_connecting_non_blocking(_base) < 0 ){
|
||||
tr_debug("M2MConnectionHandlerPimpl::dns_handler - handshake failed");
|
||||
_is_handshaking = false;
|
||||
_observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR);
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tr_error("M2MConnectionHandlerPimpl::resolve_server_address - init failed");
|
||||
_observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false);
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tr_error("M2MConnectionHandlerPimpl::dns_handler - sec is null");
|
||||
_observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false);
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!_is_handshaking) {
|
||||
enable_keepalive();
|
||||
_observer.address_ready(_address,
|
||||
_server_type,
|
||||
_address._port);
|
||||
}
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::send_handler()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::send_handler()");
|
||||
_observer.data_sent();
|
||||
}
|
||||
|
||||
bool M2MConnectionHandlerPimpl::send_data(uint8_t *data,
|
||||
uint16_t data_len,
|
||||
sn_nsdl_addr_s *address)
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::send_data()");
|
||||
if (address == NULL || data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *buffer = (uint8_t*)malloc(data_len);
|
||||
if(!buffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TaskIdentifier* task = (TaskIdentifier*)malloc(sizeof(TaskIdentifier));
|
||||
if (!task) {
|
||||
free(buffer);
|
||||
return false;
|
||||
}
|
||||
task->pimpl = this;
|
||||
memcpy(buffer, data, data_len);
|
||||
task->data_ptr = buffer;
|
||||
arm_event_s event;
|
||||
event.receiver = M2MConnectionHandlerPimpl::_tasklet_id;
|
||||
event.sender = 0;
|
||||
event.event_type = ESocketSend;
|
||||
event.data_ptr = task;
|
||||
event.event_data = data_len;
|
||||
event.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
|
||||
|
||||
return eventOS_event_send(&event) == 0 ? true : false;
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::send_socket_data(uint8_t *data,
|
||||
uint16_t data_len)
|
||||
{
|
||||
bool success = false;
|
||||
if( _use_secure_connection ){
|
||||
if( _security_impl->send_message(data, data_len) > 0){
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
int32_t ret = -1;
|
||||
if(is_tcp_connection()){
|
||||
//We need to "shim" the length in front
|
||||
uint16_t d_len = data_len+4;
|
||||
uint8_t* d = (uint8_t*)malloc(data_len+4);
|
||||
|
||||
d[0] = (data_len >> 24 )& 0xff;
|
||||
d[1] = (data_len >> 16 )& 0xff;
|
||||
d[2] = (data_len >> 8 )& 0xff;
|
||||
d[3] = data_len & 0xff;
|
||||
memmove(d+4, data, data_len);
|
||||
ret = ((TCPSocket*)_socket)->send(d,d_len);
|
||||
free(d);
|
||||
}else {
|
||||
ret = ((UDPSocket*)_socket)->sendto(*_socket_address,data, data_len);
|
||||
}
|
||||
if (ret > 0) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR, true);
|
||||
close_socket();
|
||||
}
|
||||
}
|
||||
|
||||
int8_t M2MConnectionHandlerPimpl::connection_tasklet_handler()
|
||||
{
|
||||
return M2MConnectionHandlerPimpl::_tasklet_id;
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::socket_event()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::socket_event()");
|
||||
|
||||
TaskIdentifier* task = (TaskIdentifier*)malloc(sizeof(TaskIdentifier));
|
||||
if (!task) {
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
|
||||
return;
|
||||
}
|
||||
task->pimpl = this;
|
||||
|
||||
arm_event_s event;
|
||||
event.receiver = M2MConnectionHandlerPimpl::_tasklet_id;
|
||||
event.sender = 0;
|
||||
event.event_type = ESocketReadytoRead;
|
||||
event.data_ptr = task;
|
||||
event.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
|
||||
int8_t error = eventOS_event_send(&event);
|
||||
if(error != 0) {
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool M2MConnectionHandlerPimpl::start_listening_for_data()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::start_listening_for_data()");
|
||||
// Boolean return required for other platforms,
|
||||
// not needed in mbed OS Socket.
|
||||
_listening = true;
|
||||
_running = true;
|
||||
return _listening;
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::stop_listening()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::stop_listening()");
|
||||
_listening = false;
|
||||
if(_security_impl) {
|
||||
_security_impl->reset();
|
||||
}
|
||||
}
|
||||
|
||||
int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len)
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::send_to_socket len - %d", len);
|
||||
int size = -1;
|
||||
if(is_tcp_connection()) {
|
||||
size = ((TCPSocket*)_socket)->send(buf,len);
|
||||
} else {
|
||||
size = ((UDPSocket*)_socket)->sendto(*_socket_address,buf,len);
|
||||
}
|
||||
tr_debug("M2MConnectionHandlerPimpl::send_to_socket size - %d", size);
|
||||
if(NSAPI_ERROR_WOULD_BLOCK == size){
|
||||
if(_is_handshaking) {
|
||||
return M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE;
|
||||
} else {
|
||||
return len;
|
||||
}
|
||||
}else if(size < 0){
|
||||
return -1;
|
||||
}else{
|
||||
if(!_is_handshaking) {
|
||||
_observer.data_sent();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len)
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::receive_from_socket");
|
||||
int recv = -1;
|
||||
if(is_tcp_connection()) {
|
||||
recv = ((TCPSocket*)_socket)->recv(buf, len);
|
||||
} else {
|
||||
recv = ((UDPSocket*)_socket)->recvfrom(NULL,buf, len);
|
||||
}
|
||||
tr_debug("M2MConnectionHandlerPimpl::receive_from_socket recv size %d", recv);
|
||||
if(NSAPI_ERROR_WOULD_BLOCK == recv){
|
||||
return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
|
||||
}else if(recv < 0){
|
||||
return -1;
|
||||
}else{
|
||||
return recv;
|
||||
}
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::handle_connection_error(int error)
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::handle_connection_error");
|
||||
_observer.socket_error(error);
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::set_platform_network_handler(void *handler)
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::set_platform_network_handler");
|
||||
_net_iface = (NetworkInterface*)handler;
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::receive_handshake_handler()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler()");
|
||||
if( _is_handshaking ){
|
||||
int ret = _security_impl->continue_connecting();
|
||||
tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler() - ret %d", ret);
|
||||
if( ret == M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ ){ //We wait for next readable event
|
||||
tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler() - We wait for next readable event");
|
||||
return;
|
||||
} else if( ret == 0 ){
|
||||
_is_handshaking = false;
|
||||
_use_secure_connection = true;
|
||||
enable_keepalive();
|
||||
_observer.address_ready(_address,
|
||||
_server_type,
|
||||
_server_port);
|
||||
}else if( ret < 0 ){
|
||||
_is_handshaking = false;
|
||||
_observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, true);
|
||||
close_socket();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool M2MConnectionHandlerPimpl::is_handshake_ongoing()
|
||||
{
|
||||
return _is_handshaking;
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::receive_handler()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::receive_handler()");
|
||||
memset(_recv_buffer, 0, 1024);
|
||||
size_t receive_length = sizeof(_recv_buffer);
|
||||
|
||||
if(_listening) {
|
||||
if( _use_secure_connection ){
|
||||
int rcv_size = _security_impl->read(_recv_buffer, receive_length);
|
||||
|
||||
if(rcv_size >= 0){
|
||||
_observer.data_available((uint8_t*)_recv_buffer,
|
||||
rcv_size, _address);
|
||||
} else if (M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ != rcv_size) {
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
int recv = -1;
|
||||
if(is_tcp_connection()){
|
||||
recv = ((TCPSocket*)_socket)->recv(_recv_buffer, receive_length);
|
||||
|
||||
}else{
|
||||
recv = ((UDPSocket*)_socket)->recvfrom(NULL,_recv_buffer, receive_length);
|
||||
}
|
||||
if (recv > 0) {
|
||||
// Send data for processing.
|
||||
if(is_tcp_connection()){
|
||||
//We need to "shim" out the length from the front
|
||||
if( receive_length > 4 ){
|
||||
uint64_t len = (_recv_buffer[0] << 24 & 0xFF000000) + (_recv_buffer[1] << 16 & 0xFF0000);
|
||||
len += (_recv_buffer[2] << 8 & 0xFF00) + (_recv_buffer[3] & 0xFF);
|
||||
if(len > 0) {
|
||||
uint8_t* buf = (uint8_t*)malloc(len);
|
||||
if(buf) {
|
||||
memmove(buf, _recv_buffer+4, len);
|
||||
// Observer for TCP plain mode
|
||||
_observer.data_available(buf,len,_address);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
|
||||
close_socket();
|
||||
}
|
||||
} else { // Observer for UDP plain mode
|
||||
tr_debug("M2MConnectionHandlerPimpl::receive_handler - data received %d", recv);
|
||||
_observer.data_available((uint8_t*)_recv_buffer,
|
||||
recv, _address);
|
||||
}
|
||||
} else if(NSAPI_ERROR_WOULD_BLOCK != recv) {
|
||||
// Socket error in receiving
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
|
||||
close_socket();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::claim_mutex()
|
||||
{
|
||||
eventOS_scheduler_mutex_wait();
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::release_mutex()
|
||||
{
|
||||
eventOS_scheduler_mutex_release();
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::init_socket()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::init_socket - IN");
|
||||
_is_handshaking = false;
|
||||
_running = true;
|
||||
|
||||
if(is_tcp_connection()) {
|
||||
tr_debug("M2MConnectionHandlerPimpl::init_socket - Using TCP");
|
||||
_socket = new TCPSocket(_net_iface);
|
||||
if(_socket) {
|
||||
_socket->attach(this, &M2MConnectionHandlerPimpl::socket_event);
|
||||
} else {
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tr_debug("M2MConnectionHandlerPimpl::init_socket - Using UDP - port %d", _listen_port);
|
||||
_socket = new UDPSocket(_net_iface);
|
||||
if(_socket) {
|
||||
_socket->bind(_listen_port);
|
||||
_socket->attach(this, &M2MConnectionHandlerPimpl::socket_event);
|
||||
} else {
|
||||
_observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_socket->set_blocking(false);
|
||||
tr_debug("M2MConnectionHandlerPimpl::init_socket - OUT");
|
||||
}
|
||||
|
||||
bool M2MConnectionHandlerPimpl::is_tcp_connection()
|
||||
{
|
||||
return _binding_mode == M2MInterface::TCP ||
|
||||
_binding_mode == M2MInterface::TCP_QUEUE ? true : false;
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::close_socket()
|
||||
{
|
||||
tr_debug("M2MConnectionHandlerPimpl::close_socket() - IN");
|
||||
if(_socket) {
|
||||
_running = false;
|
||||
_socket->close();
|
||||
delete _socket;
|
||||
_socket = NULL;
|
||||
}
|
||||
tr_debug("M2MConnectionHandlerPimpl::close_socket() - OUT");
|
||||
}
|
||||
|
||||
void M2MConnectionHandlerPimpl::enable_keepalive()
|
||||
{
|
||||
#if MBED_CLIENT_TCP_KEEPALIVE_TIME
|
||||
if(is_tcp_connection()) {
|
||||
int keepalive = MBED_CLIENT_TCP_KEEPALIVE_TIME;
|
||||
int enable = 1;
|
||||
tr_debug("M2MConnectionHandlerPimpl::resolve_hostname - keepalive %d s\n", keepalive);
|
||||
if(_socket->setsockopt(1,NSAPI_KEEPALIVE,&enable,sizeof(enable)) != 0) {
|
||||
tr_error("M2MConnectionHandlerPimpl::enable_keepalive - setsockopt fail to Set Keepalive\n");
|
||||
}
|
||||
if(_socket->setsockopt(1,NSAPI_KEEPINTVL,&keepalive,sizeof(keepalive)) != 0) {
|
||||
tr_error("M2MConnectionHandlerPimpl::enable_keepalive - setsockopt fail to Set Keepalive TimeInterval\n");
|
||||
}
|
||||
if(_socket->setsockopt(1,NSAPI_KEEPIDLE,&keepalive,sizeof(keepalive)) != 0) {
|
||||
tr_error("M2MConnectionHandlerPimpl::enable_keepalive - setsockopt fail to Set Keepalive Time\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "mbed-client/m2mtimer.h"
|
||||
#include "mbed-client/m2mtimerobserver.h"
|
||||
#include "mbed-client-classic/m2mtimerpimpl.h"
|
||||
|
||||
|
||||
M2MTimer::M2MTimer(M2MTimerObserver& observer)
|
||||
: _observer(observer)
|
||||
{
|
||||
_private_impl = new M2MTimerPimpl(observer);
|
||||
}
|
||||
|
||||
M2MTimer::~M2MTimer()
|
||||
{
|
||||
delete _private_impl;
|
||||
//_private_impl = NULL;
|
||||
}
|
||||
|
||||
void M2MTimer::start_timer( uint64_t interval,
|
||||
M2MTimerObserver::Type type,
|
||||
bool single_shot)
|
||||
{
|
||||
_private_impl->start_timer(interval,
|
||||
type,
|
||||
single_shot);
|
||||
}
|
||||
|
||||
void M2MTimer::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type){
|
||||
_private_impl->start_dtls_timer(intermediate_interval, total_interval, type);
|
||||
}
|
||||
|
||||
void M2MTimer::stop_timer()
|
||||
{
|
||||
_private_impl->stop_timer();
|
||||
}
|
||||
|
||||
bool M2MTimer::is_intermediate_interval_passed(){
|
||||
return _private_impl->is_intermediate_interval_passed();
|
||||
}
|
||||
|
||||
bool M2MTimer::is_total_interval_passed(){
|
||||
return _private_impl->is_total_interval_passed();
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2016 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "mbed-client-classic/m2mtimerpimpl.h"
|
||||
#include "mbed-client/m2mtimerobserver.h"
|
||||
#include "mbed-client/m2mvector.h"
|
||||
|
||||
#include "eventOS_event.h"
|
||||
#include "eventOS_event_timer.h"
|
||||
#include "eventOS_scheduler.h"
|
||||
#include "ns_hal_init.h"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
|
||||
#define TRACE_GROUP "mClt"
|
||||
|
||||
#define MBED_CLIENT_TIMER_EVENT 10
|
||||
|
||||
#ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
|
||||
#define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
|
||||
#else
|
||||
#define MBED_CLIENT_EVENT_LOOP_SIZE 1024
|
||||
#endif
|
||||
|
||||
int8_t M2MTimerPimpl::_tasklet_id = -1;
|
||||
|
||||
int8_t M2MTimerPimpl::_next_timer_id = 1;
|
||||
|
||||
static m2m::Vector<M2MTimerPimpl*> timer_impl_list;
|
||||
|
||||
extern "C" void tasklet_func(arm_event_s *event)
|
||||
{
|
||||
// skip the init event as there will be a timer event after
|
||||
if (event->event_type == MBED_CLIENT_TIMER_EVENT) {
|
||||
|
||||
bool timer_found = false;
|
||||
eventOS_scheduler_mutex_wait();
|
||||
int timer_count = timer_impl_list.size();
|
||||
for (int index = 0; index < timer_count; index++) {
|
||||
M2MTimerPimpl* timer = timer_impl_list[index];
|
||||
if (timer->get_timer_id() == event->event_id) {
|
||||
eventOS_scheduler_mutex_release();
|
||||
timer_found = true;
|
||||
timer->timer_expired();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!timer_found) {
|
||||
eventOS_scheduler_mutex_release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
M2MTimerPimpl::M2MTimerPimpl(M2MTimerObserver& observer)
|
||||
: _observer(observer),
|
||||
_single_shot(true),
|
||||
_interval(0),
|
||||
_type(M2MTimerObserver::Notdefined),
|
||||
_intermediate_interval(0),
|
||||
_total_interval(0),
|
||||
_status(0),
|
||||
_dtls_type(false)
|
||||
{
|
||||
ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL);
|
||||
eventOS_scheduler_mutex_wait();
|
||||
if (_tasklet_id < 0) {
|
||||
_tasklet_id = eventOS_event_handler_create(tasklet_func, MBED_CLIENT_TIMER_EVENT);
|
||||
assert(_tasklet_id >= 0);
|
||||
}
|
||||
|
||||
// XXX: this wraps over quite soon
|
||||
_timer_id = M2MTimerPimpl::_next_timer_id++;
|
||||
|
||||
timer_impl_list.push_back(this);
|
||||
eventOS_scheduler_mutex_release();
|
||||
}
|
||||
|
||||
M2MTimerPimpl::~M2MTimerPimpl()
|
||||
{
|
||||
// cancel the timer request, if any is pending
|
||||
cancel();
|
||||
|
||||
// there is no turning back, event os does not have eventOS_event_handler_delete() or similar,
|
||||
// so the tasklet is lost forever. Same goes with timer_impl_list, which leaks now memory.
|
||||
|
||||
// remove the timer from object list
|
||||
eventOS_scheduler_mutex_wait();
|
||||
int timer_count = timer_impl_list.size();
|
||||
for (int index = 0; index < timer_count; index++) {
|
||||
|
||||
const M2MTimerPimpl* timer = timer_impl_list[index];
|
||||
if (timer->get_timer_id() == _timer_id) {
|
||||
|
||||
timer_impl_list.erase(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
eventOS_scheduler_mutex_release();
|
||||
}
|
||||
|
||||
void M2MTimerPimpl::start_timer( uint64_t interval,
|
||||
M2MTimerObserver::Type type,
|
||||
bool single_shot)
|
||||
{
|
||||
assert(interval <= INT32_MAX);
|
||||
|
||||
_dtls_type = false;
|
||||
_intermediate_interval = 0;
|
||||
_total_interval = 0;
|
||||
_status = 0;
|
||||
_single_shot = single_shot;
|
||||
_interval = interval;
|
||||
_type = type;
|
||||
start();
|
||||
}
|
||||
|
||||
void M2MTimerPimpl::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type)
|
||||
{
|
||||
assert(intermediate_interval <= INT32_MAX);
|
||||
assert(intermediate_interval <= total_interval);
|
||||
|
||||
_dtls_type = true;
|
||||
_intermediate_interval = intermediate_interval;
|
||||
_total_interval = total_interval;
|
||||
_interval = _intermediate_interval;
|
||||
_status = 0;
|
||||
_single_shot = false;
|
||||
_type = type;
|
||||
start();
|
||||
}
|
||||
|
||||
void M2MTimerPimpl::start()
|
||||
{
|
||||
int status;
|
||||
|
||||
status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT,
|
||||
M2MTimerPimpl::_tasklet_id,
|
||||
_interval);
|
||||
assert(status == 0);
|
||||
}
|
||||
|
||||
void M2MTimerPimpl::cancel()
|
||||
{
|
||||
eventOS_event_timer_cancel(_timer_id, M2MTimerPimpl::_tasklet_id);
|
||||
}
|
||||
|
||||
void M2MTimerPimpl::stop_timer()
|
||||
{
|
||||
_interval = 0;
|
||||
_single_shot = true;
|
||||
cancel();
|
||||
}
|
||||
|
||||
void M2MTimerPimpl::timer_expired()
|
||||
{
|
||||
_status++;
|
||||
_observer.timer_expired(_type);
|
||||
|
||||
if ((!_dtls_type) && (!_single_shot)) {
|
||||
// start next round of periodic timer
|
||||
start();
|
||||
} else if ((_dtls_type) && (!is_total_interval_passed())) {
|
||||
// if only the intermediate time has passed, we need still wait up to total time
|
||||
_interval = _total_interval - _intermediate_interval;
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
bool M2MTimerPimpl::is_intermediate_interval_passed()
|
||||
{
|
||||
if (_status > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool M2MTimerPimpl::is_total_interval_passed()
|
||||
{
|
||||
if (_status > 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
.yotta.json
|
||||
coverage/
|
||||
lcov/
|
||||
yotta_modules/
|
||||
yotta_targets/
|
||||
upload.tar.gz
|
||||
build/
|
|
@ -0,0 +1 @@
|
|||
test/*
|
|
@ -0,0 +1,2 @@
|
|||
Unless specifically indicated otherwise in a file, files are licensed
|
||||
under the Apache 2.0 license, as can be found in: apache-2.0.txt
|
|
@ -0,0 +1,2 @@
|
|||
# mbed-client-mbedtls
|
||||
Mbedtls specific implementation, which can be used by mbed clients
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
|
||||
Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
|
@ -0,0 +1,15 @@
|
|||
INCLUDE_DIRS := \
|
||||
../ \
|
||||
. \
|
||||
../../nsdl-c \
|
||||
../../libService/libService \
|
||||
../../libService/exported-libs/mbed-client-libservice \
|
||||
../../libService \
|
||||
../../mbedtls/include \
|
||||
../lwm2m-client \
|
||||
../lwm2m-client/mbed-client \
|
||||
../lwm2m-client-linux/source \
|
||||
../lwm2m-client-mbedtls \
|
||||
source \
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
<xsl:output encoding="UTF-8" indent="yes" method="html"/>
|
||||
<xsl:strip-space elements="*"/>
|
||||
|
||||
<xsl:variable name="list"
|
||||
select="document('index.xml')/list" />
|
||||
|
||||
<xsl:template match="/">
|
||||
<h1>
|
||||
Unittest report
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Total tests run <xsl:value-of select="sum(document($list/entry/@name)/testsuite/@tests)"/>
|
||||
, failures: <xsl:value-of select="sum(document($list/entry/@name)/testsuite/@failures) + sum(document($list/entry/@name)/testsuite/@errors)"/>
|
||||
</b>
|
||||
|
||||
<xsl:for-each select="document($list/entry/@name)" >
|
||||
<xsl:apply-templates select="testsuite"/>
|
||||
</xsl:for-each>
|
||||
</p>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="testsuite">
|
||||
<h2>
|
||||
<xsl:value-of select="@name" />
|
||||
</h2>
|
||||
<table border="1" cellSpacing="0" cellPadding="10" >
|
||||
<tr>
|
||||
<th>Tests run</th>
|
||||
<th>Tests failed</th>
|
||||
<th>Other errors</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><xsl:value-of select="@tests"/></td>
|
||||
<td><xsl:value-of select="@failures"/></td>
|
||||
<td><xsl:value-of select="@errors"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<table border="1" cellSpacing="0" cellPadding="10" >
|
||||
<tr>
|
||||
<th>Tests name</th>
|
||||
<th>PASS/FAIL</th>
|
||||
<th>Failing case</th>
|
||||
<th>Reason</th>
|
||||
</tr>
|
||||
<xsl:apply-templates select="testcase"/>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="testcase">
|
||||
<xsl:choose>
|
||||
<xsl:when test="failure">
|
||||
<tr><td><font color="#FF0000"><xsl:value-of select="@name" /></font></td><xsl:apply-templates select="failure"/></tr>
|
||||
</xsl:when>
|
||||
<xsl:when test="error">
|
||||
<tr><td><font color="#FF0000"><xsl:value-of select="@name" /></font></td><xsl:apply-templates select="error"/></tr>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<tr><td><xsl:value-of select="@name" /></td><td><font color="#00FF00">PASS</font></td><td></td><td></td></tr>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="failure">
|
||||
<td>
|
||||
<b><font color="#FF0000">FAIL</font></b>
|
||||
</td>
|
||||
<td>
|
||||
<font color="#ff0000">
|
||||
<xsl:value-of select="@message" />
|
||||
</font>
|
||||
</td>
|
||||
<td>
|
||||
<font color="#ff0000">
|
||||
<xsl:value-of select="@type" />
|
||||
</font>
|
||||
</td>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="error">
|
||||
<td>
|
||||
<b><font color="#FF0000">FAIL</font></b>
|
||||
</td>
|
||||
<td>
|
||||
<font color="#ff0000">
|
||||
<xsl:value-of select="@message" />
|
||||
</font>
|
||||
</td>
|
||||
<td>
|
||||
<font color="#ff0000">
|
||||
<xsl:value-of select="@type" />
|
||||
</font>
|
||||
</td>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __M2M_CONNECTION_SECURITY_PIMPL_H__
|
||||
#define __M2M_CONNECTION_SECURITY_PIMPL_H__
|
||||
|
||||
#include "mbed-client/m2mconnectionsecurity.h"
|
||||
#include "mbed-client/m2mtimerobserver.h"
|
||||
#include "mbed-client/m2mconstants.h"
|
||||
#include "mbed-client/m2msecurity.h"
|
||||
|
||||
#include "mbedtls/config.h"
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/certs.h"
|
||||
#include "mbedtls/entropy_poll.h"
|
||||
|
||||
class M2MTimer;
|
||||
|
||||
//TODO: Should we let application to select these or not??
|
||||
const static int PSK_SUITES[] = {
|
||||
MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
|
||||
MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The M2MConnectionSecurityPimpl class
|
||||
*/
|
||||
class M2MConnectionSecurityPimpl : public M2MTimerObserver {
|
||||
|
||||
private:
|
||||
|
||||
// Prevents the use of assignment operator by accident.
|
||||
M2MConnectionSecurityPimpl& operator=( const M2MConnectionSecurityPimpl& /*other*/ );
|
||||
// Prevents the use of copy constructor by accident
|
||||
M2MConnectionSecurityPimpl( const M2MConnectionSecurityPimpl& /*other*/ );
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~M2MConnectionSecurityPimpl();
|
||||
|
||||
/**
|
||||
* \brief Resets the socket connection states.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* \brief Initiatlizes the socket connection states.
|
||||
*/
|
||||
int init(const M2MSecurity *security);
|
||||
|
||||
/**
|
||||
* \brief Starts the connection in non-blocking mode.
|
||||
* \param connHandler The ConnectionHandler object that maintains the socket.
|
||||
* \return Returns the state of the connection. Successful or not.
|
||||
*/
|
||||
int start_connecting_non_blocking(M2MConnectionHandler* connHandler);
|
||||
|
||||
/**
|
||||
* \brief Continues connectivity logic for secure connection.
|
||||
* \return Returns an error code if any while continuing the connection sequence.
|
||||
*/
|
||||
int continue_connecting();
|
||||
|
||||
/**
|
||||
* \brief Connects the client to the server.
|
||||
* \param connHandler The ConnectionHandler object that maintains the socket.
|
||||
* \return Returns the state of the connection. Successful or not.
|
||||
*/
|
||||
int connect(M2MConnectionHandler* connHandler);
|
||||
|
||||
/**
|
||||
* \brief Sends data to the server.
|
||||
* \param message The data to be sent.
|
||||
* \param len The length of the data.
|
||||
* @return Indicates whether the data is sent successfully or not.
|
||||
*/
|
||||
int send_message(unsigned char *message, int len);
|
||||
|
||||
/**
|
||||
* \brief Reads the data received from the server.
|
||||
* \param message The data to be read.
|
||||
* \param len The length of the data.
|
||||
* \return Indicates whether the data is read successfully or not.
|
||||
*/
|
||||
int read(unsigned char* buffer, uint16_t len);
|
||||
|
||||
/**
|
||||
* \brief Sets the function callback that will be called by mbed-client for
|
||||
* fetching random number from application for ensuring strong entropy.
|
||||
* \param random_callback A function pointer that will be called by mbed-client
|
||||
* while performing secure handshake.
|
||||
* Function signature should be uint32_t (*random_number_callback)(void);
|
||||
*/
|
||||
void set_random_number_callback(random_number_cb callback);
|
||||
|
||||
/**
|
||||
* \brief Sets the function callback that will be called by mbed-client for
|
||||
* providing entropy source from application for ensuring strong entropy.
|
||||
* \param entropy_callback A function pointer that will be called by mbed-client
|
||||
* while performing secure handshake.
|
||||
* Function signature , if using mbed-client-mbedtls should be
|
||||
* int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output,
|
||||
* size_t len, size_t *olen);
|
||||
*/
|
||||
void set_entropy_callback(entropy_cb callback);
|
||||
|
||||
protected: //From M2MTimerObserver
|
||||
|
||||
virtual void timer_expired(M2MTimerObserver::Type type);
|
||||
|
||||
private:
|
||||
|
||||
int start_handshake();
|
||||
|
||||
private:
|
||||
|
||||
bool _init_done;
|
||||
mbedtls_ssl_config _conf;
|
||||
mbedtls_ssl_context _ssl;
|
||||
mbedtls_x509_crt _cacert;
|
||||
mbedtls_x509_crt _owncert;
|
||||
mbedtls_pk_context _pkey;
|
||||
mbedtls_ctr_drbg_context _ctr_drbg;
|
||||
mbedtls_entropy_context _entropy;
|
||||
uint32_t _flags;
|
||||
M2MTimer *_timer;
|
||||
M2MConnectionSecurity::SecurityMode _sec_mode;
|
||||
|
||||
friend class Test_M2MConnectionSecurityPimpl;
|
||||
};
|
||||
|
||||
#endif //__M2M_CONNECTION_SECURITY_PIMPL_H__
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "mbed-client-mbedtls",
|
||||
"version": "3.0.3",
|
||||
"description": "Mbedtls specific implementation, which can be used by mbed client",
|
||||
"keywords": [
|
||||
"mbed-client-mbedtls"
|
||||
],
|
||||
"author": "Antti Kauppila",
|
||||
"repository": {
|
||||
"url": "git@github.com:ARMmbed/mbed-client-mbedtls.git",
|
||||
"type": "git"
|
||||
},
|
||||
"homepage": "https://github.com/ARMmbed/mbed-client-mbedtls",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"mbedtls": "^2.0.0"
|
||||
},
|
||||
"targetDependencies": {}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
# Execute script with root path where to find binaries.
|
||||
# For example ./run_unit_tests_with_valgrind.sh ./build/x86-linux-native-coverage/test/mbedclient/
|
||||
|
||||
input="binaries.txt"
|
||||
valgrind_logs="valgrind_logs"
|
||||
rm -rf $valgrind_logs
|
||||
mkdir $valgrind_logs
|
||||
find $1 -type f -executable -exec sh -c "file -i '{}' | grep -q 'x-executable; charset=binary'" \; -print > $input
|
||||
while file= read -r binary
|
||||
do
|
||||
valgrind --track-origins=yes --xml=yes --xml-file="${valgrind_logs}/valgrind_$(basename $binary).xml" "$binary"
|
||||
|
||||
done < "$input"
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "mbed-client/m2mconnectionhandler.h"
|
||||
#include "mbed-client/m2mconnectionsecurity.h"
|
||||
#include "mbed-client/m2mtimer.h"
|
||||
#include "mbed-client/m2msecurity.h"
|
||||
#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h"
|
||||
|
||||
M2MConnectionSecurity::M2MConnectionSecurity(SecurityMode mode)
|
||||
{
|
||||
_private_impl = new M2MConnectionSecurityPimpl(mode);
|
||||
}
|
||||
|
||||
M2MConnectionSecurity::~M2MConnectionSecurity(){
|
||||
delete _private_impl;
|
||||
}
|
||||
|
||||
void M2MConnectionSecurity::reset(){
|
||||
_private_impl->reset();
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::init(const M2MSecurity *security){
|
||||
return _private_impl->init(security);
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::start_connecting_non_blocking(M2MConnectionHandler* connHandler)
|
||||
{
|
||||
return _private_impl->start_connecting_non_blocking(connHandler);
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::continue_connecting()
|
||||
{
|
||||
return _private_impl->continue_connecting();
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::connect(M2MConnectionHandler* connHandler){
|
||||
return _private_impl->connect(connHandler);
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::send_message(unsigned char *message, int len){
|
||||
return _private_impl->send_message(message, len);
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::read(unsigned char* buffer, uint16_t len){
|
||||
return _private_impl->read(buffer, len);
|
||||
}
|
||||
|
||||
void M2MConnectionSecurity::set_random_number_callback(random_number_cb callback)
|
||||
{
|
||||
_private_impl->set_random_number_callback(callback);
|
||||
}
|
||||
|
||||
void M2MConnectionSecurity::set_entropy_callback(entropy_cb callback)
|
||||
{
|
||||
_private_impl->set_entropy_callback(callback);
|
||||
}
|
|
@ -0,0 +1,454 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
|
||||
#include "mbed-client/m2mconnectionhandler.h"
|
||||
#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h"
|
||||
#include "mbed-client/m2mtimer.h"
|
||||
#include "mbed-client/m2msecurity.h"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include <string.h>
|
||||
|
||||
#define TRACE_GROUP "mClt"
|
||||
|
||||
void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms );
|
||||
int mbedtls_timing_get_delay( void *data );
|
||||
int entropy_poll( void *data, unsigned char *output, size_t len, size_t *olen );
|
||||
//Point these back to M2MConnectionHandler!!!
|
||||
int f_send( void *ctx, const unsigned char *buf, size_t len );
|
||||
int f_recv(void *ctx, unsigned char *buf, size_t len);
|
||||
int f_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t some);
|
||||
|
||||
bool cancelled;
|
||||
random_number_cb __random_number_callback;
|
||||
entropy_cb __entropy_callback;
|
||||
|
||||
//Comment out following define to enable tracing from mbedtls
|
||||
//#define ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS
|
||||
#ifdef ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS
|
||||
static void mbedtls_debug( void *ctx, int level,
|
||||
const char *file, int line, const char *str )
|
||||
{
|
||||
((void) level);
|
||||
tr_debug("%s", str);
|
||||
}
|
||||
|
||||
static int verify_cert_chains(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
|
||||
{
|
||||
char buf[1024];
|
||||
(void) data;
|
||||
|
||||
printf("\nVerifying certificate at depth %d:\n", depth);
|
||||
mbedtls_x509_crt_info(buf, sizeof (buf) - 1, " ", crt);
|
||||
printf("%s", buf);
|
||||
|
||||
if (*flags == 0)
|
||||
printf("No verification issue for this certificate\n");
|
||||
else
|
||||
{
|
||||
mbedtls_x509_crt_verify_info(buf, sizeof (buf), " ! ", *flags);
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
M2MConnectionSecurityPimpl::M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode)
|
||||
: _flags(0),
|
||||
_sec_mode(mode)
|
||||
{
|
||||
_init_done = false;
|
||||
cancelled = true;
|
||||
_timer = new M2MTimer(*this);
|
||||
mbedtls_ssl_init( &_ssl );
|
||||
mbedtls_ssl_config_init( &_conf );
|
||||
mbedtls_x509_crt_init( &_cacert );
|
||||
mbedtls_x509_crt_init(&_owncert);
|
||||
mbedtls_pk_init(&_pkey);
|
||||
mbedtls_ctr_drbg_init( &_ctr_drbg );
|
||||
mbedtls_entropy_init( &_entropy );
|
||||
}
|
||||
|
||||
M2MConnectionSecurityPimpl::~M2MConnectionSecurityPimpl(){
|
||||
mbedtls_ssl_config_free(&_conf);
|
||||
mbedtls_ssl_free(&_ssl);
|
||||
mbedtls_x509_crt_free(&_cacert);
|
||||
mbedtls_x509_crt_free(&_owncert);
|
||||
mbedtls_pk_free(&_pkey);
|
||||
mbedtls_ctr_drbg_free( &_ctr_drbg );
|
||||
mbedtls_entropy_free( &_entropy );
|
||||
delete _timer;
|
||||
}
|
||||
|
||||
void M2MConnectionSecurityPimpl::timer_expired(M2MTimerObserver::Type type){
|
||||
tr_debug("M2MConnectionSecurityPimpl::timer_expired");
|
||||
if(type == M2MTimerObserver::Dtls && !cancelled){
|
||||
int error = continue_connecting();
|
||||
if(MBEDTLS_ERR_SSL_TIMEOUT == error || error == -1) {
|
||||
tr_error("M2MConnectionSecurityPimpl::timer_expired - handshake timeout");
|
||||
if(_ssl.p_bio) {
|
||||
M2MConnectionHandler* ptr = (M2MConnectionHandler*)_ssl.p_bio;
|
||||
ptr->handle_connection_error(M2MConnectionHandler::SSL_HANDSHAKE_ERROR);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void M2MConnectionSecurityPimpl::reset(){
|
||||
_init_done = false;
|
||||
cancelled = true;
|
||||
mbedtls_ssl_config_free(&_conf);
|
||||
mbedtls_ssl_free(&_ssl);
|
||||
mbedtls_x509_crt_free(&_cacert);
|
||||
mbedtls_x509_crt_free(&_owncert);
|
||||
mbedtls_pk_free(&_pkey);
|
||||
mbedtls_ctr_drbg_free( &_ctr_drbg );
|
||||
mbedtls_entropy_free( &_entropy );
|
||||
_timer->stop_timer();
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::init(const M2MSecurity *security)
|
||||
{
|
||||
tr_debug("M2MConnectionSecurityPimpl::init");
|
||||
int ret = -1;
|
||||
if (security != NULL) {
|
||||
const char *pers = "dtls_client";
|
||||
mbedtls_ssl_init( &_ssl );
|
||||
mbedtls_ssl_config_init( &_conf );
|
||||
mbedtls_x509_crt_init( &_cacert );
|
||||
mbedtls_x509_crt_init(&_owncert);
|
||||
mbedtls_pk_init(&_pkey);
|
||||
mbedtls_ctr_drbg_init( &_ctr_drbg );
|
||||
mbedtls_entropy_init( &_entropy );
|
||||
|
||||
int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
|
||||
if( _sec_mode == M2MConnectionSecurity::TLS ){
|
||||
mode = MBEDTLS_SSL_TRANSPORT_STREAM;
|
||||
}
|
||||
|
||||
if( mbedtls_entropy_add_source( &_entropy, entropy_poll, NULL,
|
||||
128, 0 ) < 0 ){
|
||||
return -1;
|
||||
}
|
||||
if(__entropy_callback.entropy_source_ptr) {
|
||||
if( mbedtls_entropy_add_source( &_entropy, __entropy_callback.entropy_source_ptr,
|
||||
__entropy_callback.p_source,__entropy_callback.threshold,
|
||||
__entropy_callback.strong ) < 0 ){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if( mbedtls_ctr_drbg_seed( &_ctr_drbg, mbedtls_entropy_func, &_entropy,
|
||||
(const unsigned char *) pers,
|
||||
strlen( pers ) ) != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( mbedtls_ssl_config_defaults( &_conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
mode, 0 ) != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
M2MSecurity::SecurityModeType cert_mode =
|
||||
(M2MSecurity::SecurityModeType)security->resource_value_int(M2MSecurity::SecurityMode);
|
||||
|
||||
// Note: these are relatively large buffers, no point to make copy of them here as mbedtls will make a copy of them.
|
||||
const uint8_t *srv_public_key = NULL;
|
||||
const uint8_t *public_key = NULL;
|
||||
const uint8_t *sec_key = NULL;
|
||||
|
||||
uint32_t srv_public_key_size = security->resource_value_buffer(M2MSecurity::ServerPublicKey, srv_public_key);
|
||||
uint32_t public_key_size = security->resource_value_buffer(M2MSecurity::PublicKey, public_key);
|
||||
uint32_t sec_key_size = security->resource_value_buffer(M2MSecurity::Secretkey, sec_key);
|
||||
if( srv_public_key == NULL || public_key == NULL || sec_key == NULL ||
|
||||
srv_public_key_size == 0 || public_key_size == 0 || sec_key_size == 0 ){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( cert_mode == M2MSecurity::Certificate ){
|
||||
if ( mbedtls_x509_crt_parse( &_cacert, (const unsigned char *) srv_public_key,
|
||||
srv_public_key_size + 1) < 0 ||
|
||||
mbedtls_x509_crt_parse( &_owncert, (const unsigned char *) public_key,
|
||||
public_key_size + 1) < 0 ||
|
||||
mbedtls_pk_parse_key(&_pkey, (const unsigned char *) sec_key,
|
||||
sec_key_size + 1, NULL, 0 ) < 0 ) {
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if ( ret == 0 ) {
|
||||
mbedtls_ssl_conf_own_cert(&_conf, &_owncert, &_pkey);
|
||||
mbedtls_ssl_conf_authmode( &_conf, MBEDTLS_SSL_VERIFY_REQUIRED );
|
||||
mbedtls_ssl_conf_ca_chain( &_conf, &_cacert, NULL );
|
||||
}
|
||||
|
||||
} else if ( cert_mode == M2MSecurity::Psk ){
|
||||
if (mbedtls_ssl_conf_psk(&_conf, sec_key, sec_key_size, public_key, public_key_size) == 0) {
|
||||
ret = 0;
|
||||
}
|
||||
mbedtls_ssl_conf_ciphersuites(&_conf, PSK_SUITES);
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS
|
||||
mbedtls_ssl_conf_dbg( &_conf, mbedtls_debug, stdout );
|
||||
mbedtls_debug_set_threshold(5);
|
||||
mbedtls_ssl_conf_verify(&_conf, verify_cert_chains, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
if( ret == 0 ){
|
||||
_init_done = true;
|
||||
}
|
||||
tr_debug("M2MConnectionSecurityPimpl::init - ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int M2MConnectionSecurityPimpl::start_handshake(){
|
||||
tr_debug("M2MConnectionSecurityPimpl::start_handshake");
|
||||
int ret = -1;
|
||||
do
|
||||
{
|
||||
ret = mbedtls_ssl_handshake( &_ssl );
|
||||
}
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
|
||||
if( ret != 0 ) {
|
||||
ret = -1;
|
||||
}else {
|
||||
if( ( _flags = mbedtls_ssl_get_verify_result( &_ssl ) ) != 0 ) {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
tr_debug("M2MConnectionSecurityPimpl::start_handshake - OUT");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler){
|
||||
|
||||
tr_debug("M2MConnectionSecurityPimpl::connect");
|
||||
int ret=-1;
|
||||
if(!_init_done){
|
||||
return ret;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_rng( &_conf, mbedtls_ctr_drbg_random, &_ctr_drbg );
|
||||
|
||||
if( ( ret = mbedtls_ssl_setup( &_ssl, &_conf ) ) != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mbedtls_ssl_set_bio( &_ssl, connHandler,
|
||||
f_send, f_recv, f_recv_timeout );
|
||||
|
||||
mbedtls_ssl_set_timer_cb( &_ssl, _timer, mbedtls_timing_set_delay,
|
||||
mbedtls_timing_get_delay );
|
||||
|
||||
ret = start_handshake();
|
||||
_timer->stop_timer();
|
||||
tr_debug("M2MConnectionSecurityPimpl::connect - handshake ret: %d, ssl state: %d", ret, _ssl.state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::start_connecting_non_blocking(M2MConnectionHandler* connHandler)
|
||||
{
|
||||
tr_debug("M2MConnectionSecurityPimpl::start_connecting_non_blocking");
|
||||
int ret=-1;
|
||||
if(!_init_done){
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
|
||||
if( _sec_mode == M2MConnectionSecurity::TLS ){
|
||||
mode = MBEDTLS_SSL_TRANSPORT_STREAM;
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_ssl_config_defaults( &_conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
mode, 0 ) ) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// This is for non-blocking sockets total timeout is 1+2+4+8+16+29=60 seconds
|
||||
mbedtls_ssl_conf_handshake_timeout( &_conf, 10000, 29000 );
|
||||
mbedtls_ssl_conf_rng( &_conf, mbedtls_ctr_drbg_random, &_ctr_drbg );
|
||||
|
||||
if( ( ret = mbedtls_ssl_setup( &_ssl, &_conf ) ) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
mbedtls_ssl_set_bio( &_ssl, connHandler,
|
||||
f_send, f_recv, f_recv_timeout );
|
||||
|
||||
mbedtls_ssl_set_timer_cb( &_ssl, _timer, mbedtls_timing_set_delay,
|
||||
mbedtls_timing_get_delay );
|
||||
|
||||
ret = mbedtls_ssl_handshake_step( &_ssl );
|
||||
if( ret == 0 ){
|
||||
ret = mbedtls_ssl_handshake_step( &_ssl );
|
||||
}
|
||||
|
||||
if( ret >= 0){
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
tr_debug("M2MConnectionSecurityPimpl::start_connecting_non_blocking - handshake ret: %d, ssl state: %d", ret, _ssl.state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::continue_connecting()
|
||||
{
|
||||
tr_debug("M2MConnectionSecurityPimpl::continue_connecting");
|
||||
int ret=-1;
|
||||
while( ret != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ ){
|
||||
ret = mbedtls_ssl_handshake_step( &_ssl );
|
||||
if( MBEDTLS_ERR_SSL_WANT_READ == ret ){
|
||||
ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
|
||||
}
|
||||
else if (ret != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if( _ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER ){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
tr_debug("M2MConnectionSecurityPimpl::continue_connecting, ret: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len){
|
||||
tr_debug("M2MConnectionSecurityPimpl::send_message");
|
||||
int ret=-1;
|
||||
if(!_init_done){
|
||||
return ret;
|
||||
}
|
||||
|
||||
do ret = mbedtls_ssl_write( &_ssl, (unsigned char *) message, len );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
|
||||
tr_debug("M2MConnectionSecurityPimpl::send_message - ret: %d", ret);
|
||||
return ret; //bytes written
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len){
|
||||
int ret=-1;
|
||||
if(!_init_done){
|
||||
tr_error("M2MConnectionSecurityPimpl::read - init not done!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset( buffer, 0, len );
|
||||
do ret = mbedtls_ssl_read( &_ssl, buffer, len-1 );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
|
||||
return ret; //bytes read
|
||||
}
|
||||
|
||||
int f_send( void *ctx, const unsigned char *buf, size_t len){
|
||||
M2MConnectionHandler* handler = ((M2MConnectionHandler *) ctx);
|
||||
return handler->send_to_socket(buf, len);
|
||||
}
|
||||
|
||||
int f_recv(void *ctx, unsigned char *buf, size_t len){
|
||||
M2MConnectionHandler* handler = ((M2MConnectionHandler *) ctx);
|
||||
return handler->receive_from_socket(buf, len);
|
||||
}
|
||||
|
||||
int f_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t /*some*/){
|
||||
return f_recv(ctx, buf, len);
|
||||
}
|
||||
|
||||
int entropy_poll( void *, unsigned char *output, size_t len,
|
||||
size_t *olen )
|
||||
{
|
||||
uint32_t rdm = 0;
|
||||
if(__random_number_callback) {
|
||||
rdm = __random_number_callback();
|
||||
} else {
|
||||
rdm = time(NULL);
|
||||
}
|
||||
for(uint16_t i=0; i < len; i++){
|
||||
srand(rdm);
|
||||
output[i] = rand() % 256;
|
||||
}
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ){
|
||||
tr_debug("mbedtls_timing_set_delay - intermediate: %d", int_ms);
|
||||
tr_debug("mbedtls_timing_set_delay - final: %d", fin_ms);
|
||||
M2MTimer* timer = static_cast<M2MTimer*> (data);
|
||||
if(!timer) {
|
||||
return;
|
||||
}
|
||||
if( int_ms > 0 && fin_ms > 0 ){
|
||||
tr_debug("mbedtls_timing_set_delay - start");
|
||||
cancelled = false;
|
||||
timer->stop_timer();
|
||||
timer->start_dtls_timer(int_ms, fin_ms);
|
||||
}else{
|
||||
tr_debug("mbedtls_timing_set_delay - stop");
|
||||
cancelled = true;
|
||||
timer->stop_timer();
|
||||
}
|
||||
}
|
||||
|
||||
int mbedtls_timing_get_delay( void *data ){
|
||||
tr_debug("mbedtls_timing_get_delay");
|
||||
M2MTimer* timer = static_cast<M2MTimer*> (data);
|
||||
if(!timer){
|
||||
return 0;
|
||||
}
|
||||
if(true == cancelled) {
|
||||
tr_debug("mbedtls_timing_get_delay - ret -1");
|
||||
return -1;
|
||||
} else if( timer->is_total_interval_passed() ){
|
||||
tr_debug("mbedtls_timing_get_delay - ret 2");
|
||||
return 2;
|
||||
}else if( timer->is_intermediate_interval_passed() ){
|
||||
tr_debug("mbedtls_timing_get_delay - ret 1");
|
||||
return 1;
|
||||
}else{
|
||||
tr_debug("mbedtls_timing_get_delay - ret 0");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void M2MConnectionSecurityPimpl::set_random_number_callback(random_number_cb callback)
|
||||
{
|
||||
__random_number_callback = callback;
|
||||
}
|
||||
|
||||
void M2MConnectionSecurityPimpl::set_entropy_callback(entropy_cb callback)
|
||||
{
|
||||
__entropy_callback = callback;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
SRCS += \
|
||||
source/m2mconnectionsecurity.cpp \
|
||||
source/m2mconnectionsecuritypimpl.cpp \
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,562 @@
|
|||
#---------
|
||||
#
|
||||
# MakefileWorker.mk
|
||||
#
|
||||
# Include this helper file in your makefile
|
||||
# It makes
|
||||
# A static library
|
||||
# A test executable
|
||||
#
|
||||
# See this example for parameter settings
|
||||
# examples/Makefile
|
||||
#
|
||||
#----------
|
||||
# Inputs - these variables describe what to build
|
||||
#
|
||||
# INCLUDE_DIRS - Directories used to search for include files.
|
||||
# This generates a -I for each directory
|
||||
# SRC_DIRS - Directories containing source file to built into the library
|
||||
# SRC_FILES - Specific source files to build into library. Helpful when not all code
|
||||
# in a directory can be built for test (hopefully a temporary situation)
|
||||
# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner
|
||||
# These do not go in a library. They are explicitly included in the test runner
|
||||
# TEST_SRC_FILES - Specific source files to build into the unit test runner
|
||||
# These do not go in a library. They are explicitly included in the test runner
|
||||
# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner
|
||||
# These do not go in a library. They are explicitly included in the test runner
|
||||
#----------
|
||||
# You can adjust these variables to influence how to build the test target
|
||||
# and where to put and name outputs
|
||||
# See below to determine defaults
|
||||
# COMPONENT_NAME - the name of the thing being built
|
||||
# TEST_TARGET - name the test executable. By default it is
|
||||
# $(COMPONENT_NAME)_tests
|
||||
# Helpful if you want 1 > make files in the same directory with different
|
||||
# executables as output.
|
||||
# CPPUTEST_HOME - where CppUTest home dir found
|
||||
# TARGET_PLATFORM - Influences how the outputs are generated by modifying the
|
||||
# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the
|
||||
# normal objs and lib directories. Also modifies where to search for the
|
||||
# CPPUTEST_LIB to link against.
|
||||
# CPPUTEST_OBJS_DIR - a directory where o and d files go
|
||||
# CPPUTEST_LIB_DIR - a directory where libs go
|
||||
# CPPUTEST_ENABLE_DEBUG - build for debug
|
||||
# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete
|
||||
# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out
|
||||
# of the test harness
|
||||
# CPPUTEST_USE_GCOV - Turn on coverage analysis
|
||||
# Clean then build with this flag set to Y, then 'make gcov'
|
||||
# CPPUTEST_MAPFILE - generate a map file
|
||||
# CPPUTEST_WARNINGFLAGS - overly picky by default
|
||||
# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make
|
||||
# other targets. Like CSlim, which is part of fitnesse
|
||||
# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user
|
||||
# specification of source files and directories that aren't below
|
||||
# the user's Makefile in the directory tree, like:
|
||||
# SRC_DIRS += ../../lib/foo
|
||||
# It defaults to N, and shouldn't be necessary except in the above case.
|
||||
#----------
|
||||
#
|
||||
# Other flags users can initialize to sneak in their settings
|
||||
# CPPUTEST_CXXFLAGS - flags for the C++ compiler
|
||||
# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor
|
||||
# CPPUTEST_CFLAGS - flags for the C complier
|
||||
# CPPUTEST_LDFLAGS - Linker flags
|
||||
#----------
|
||||
|
||||
# Some behavior is weird on some platforms. Need to discover the platform.
|
||||
|
||||
# Platforms
|
||||
UNAME_OUTPUT = "$(shell uname -a)"
|
||||
MACOSX_STR = Darwin
|
||||
MINGW_STR = MINGW
|
||||
CYGWIN_STR = CYGWIN
|
||||
LINUX_STR = Linux
|
||||
SUNOS_STR = SunOS
|
||||
UNKNWOWN_OS_STR = Unknown
|
||||
|
||||
# Compilers
|
||||
CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)"
|
||||
CLANG_STR = clang
|
||||
SUNSTUDIO_CXX_STR = SunStudio
|
||||
|
||||
UNAME_OS = $(UNKNWOWN_OS_STR)
|
||||
|
||||
ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR))
|
||||
UNAME_OS = $(MINGW_STR)
|
||||
endif
|
||||
|
||||
ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR))
|
||||
UNAME_OS = $(CYGWIN_STR)
|
||||
endif
|
||||
|
||||
ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR))
|
||||
UNAME_OS = $(LINUX_STR)
|
||||
endif
|
||||
|
||||
ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR))
|
||||
UNAME_OS = $(MACOSX_STR)
|
||||
#lion has a problem with the 'v' part of -a
|
||||
UNAME_OUTPUT = "$(shell uname -pmnrs)"
|
||||
endif
|
||||
|
||||
ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR))
|
||||
UNAME_OS = $(SUNOS_STR)
|
||||
|
||||
SUNSTUDIO_CXX_ERR_STR = CC -flags
|
||||
ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR))
|
||||
CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)"
|
||||
COMPILER_NAME = $(SUNSTUDIO_CXX_STR)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR))
|
||||
COMPILER_NAME = $(CLANG_STR)
|
||||
endif
|
||||
|
||||
#Kludge for mingw, it does not have cc.exe, but gcc.exe will do
|
||||
ifeq ($(UNAME_OS),$(MINGW_STR))
|
||||
CC := gcc
|
||||
endif
|
||||
|
||||
#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the
|
||||
# Standard C++ library as a shared library. Unbelievable.
|
||||
ifeq ($(UNAME_OS),$(MINGW_STR))
|
||||
CPPUTEST_LDFLAGS += -static
|
||||
endif
|
||||
ifeq ($(UNAME_OS),$(CYGWIN_STR))
|
||||
CPPUTEST_LDFLAGS += -static
|
||||
endif
|
||||
|
||||
|
||||
#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic
|
||||
ifeq ($(UNAME_OS),$(MACOSX_STR))
|
||||
ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9)
|
||||
CPPUTEST_PEDANTIC_ERRORS = N
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef COMPONENT_NAME
|
||||
COMPONENT_NAME = name_this_in_the_makefile
|
||||
endif
|
||||
|
||||
# Debug on by default
|
||||
ifndef CPPUTEST_ENABLE_DEBUG
|
||||
CPPUTEST_ENABLE_DEBUG = Y
|
||||
endif
|
||||
|
||||
# new and delete for memory leak detection on by default
|
||||
ifndef CPPUTEST_USE_MEM_LEAK_DETECTION
|
||||
CPPUTEST_USE_MEM_LEAK_DETECTION = Y
|
||||
endif
|
||||
|
||||
# Use the standard C library
|
||||
ifndef CPPUTEST_USE_STD_C_LIB
|
||||
CPPUTEST_USE_STD_C_LIB = Y
|
||||
endif
|
||||
|
||||
# Use the standard C++ library
|
||||
ifndef CPPUTEST_USE_STD_CPP_LIB
|
||||
CPPUTEST_USE_STD_CPP_LIB = Y
|
||||
endif
|
||||
|
||||
# Use gcov, off by default
|
||||
ifndef CPPUTEST_USE_GCOV
|
||||
CPPUTEST_USE_GCOV = N
|
||||
endif
|
||||
|
||||
ifndef CPPUTEST_PEDANTIC_ERRORS
|
||||
CPPUTEST_PEDANTIC_ERRORS = Y
|
||||
endif
|
||||
|
||||
# Default warnings
|
||||
ifndef CPPUTEST_WARNINGFLAGS
|
||||
CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum -Wconversion
|
||||
ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y)
|
||||
# CPPUTEST_WARNINGFLAGS += -pedantic-errors
|
||||
CPPUTEST_WARNINGFLAGS += -pedantic
|
||||
endif
|
||||
ifeq ($(UNAME_OS),$(LINUX_STR))
|
||||
CPPUTEST_WARNINGFLAGS += -Wsign-conversion
|
||||
endif
|
||||
CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual
|
||||
CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes
|
||||
endif
|
||||
|
||||
#Wonderful extra compiler warnings with clang
|
||||
ifeq ($(COMPILER_NAME),$(CLANG_STR))
|
||||
# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that.
|
||||
# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit)
|
||||
# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor
|
||||
# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled.
|
||||
CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables
|
||||
CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded
|
||||
endif
|
||||
|
||||
# Uhm. Maybe put some warning flags for SunStudio here?
|
||||
ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR))
|
||||
CPPUTEST_CXX_WARNINGFLAGS =
|
||||
CPPUTEST_C_WARNINGFLAGS =
|
||||
endif
|
||||
|
||||
# Default dir for temporary files (d, o)
|
||||
ifndef CPPUTEST_OBJS_DIR
|
||||
ifndef TARGET_PLATFORM
|
||||
CPPUTEST_OBJS_DIR = objs
|
||||
else
|
||||
CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Default dir for the outout library
|
||||
ifndef CPPUTEST_LIB_DIR
|
||||
ifndef TARGET_PLATFORM
|
||||
CPPUTEST_LIB_DIR = lib
|
||||
else
|
||||
CPPUTEST_LIB_DIR = lib/$(TARGET_PLATFORM)
|
||||
endif
|
||||
endif
|
||||
|
||||
# No map by default
|
||||
ifndef CPPUTEST_MAP_FILE
|
||||
CPPUTEST_MAP_FILE = N
|
||||
endif
|
||||
|
||||
# No extentions is default
|
||||
ifndef CPPUTEST_USE_EXTENSIONS
|
||||
CPPUTEST_USE_EXTENSIONS = N
|
||||
endif
|
||||
|
||||
# No VPATH is default
|
||||
ifndef CPPUTEST_USE_VPATH
|
||||
CPPUTEST_USE_VPATH := N
|
||||
endif
|
||||
# Make empty, instead of 'N', for usage in $(if ) conditionals
|
||||
ifneq ($(CPPUTEST_USE_VPATH), Y)
|
||||
CPPUTEST_USE_VPATH :=
|
||||
endif
|
||||
|
||||
ifndef TARGET_PLATFORM
|
||||
#CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib
|
||||
CPPUTEST_LIB_LINK_DIR = /usr/lib/x86_64-linux-gnu
|
||||
else
|
||||
CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib/$(TARGET_PLATFORM)
|
||||
endif
|
||||
|
||||
# --------------------------------------
|
||||
# derived flags in the following area
|
||||
# --------------------------------------
|
||||
|
||||
# Without the C library, we'll need to disable the C++ library and ...
|
||||
ifeq ($(CPPUTEST_USE_STD_C_LIB), N)
|
||||
CPPUTEST_USE_STD_CPP_LIB = N
|
||||
CPPUTEST_USE_MEM_LEAK_DETECTION = N
|
||||
CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED
|
||||
CPPUTEST_CPPFLAGS += -nostdinc
|
||||
endif
|
||||
|
||||
CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION
|
||||
|
||||
ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N)
|
||||
CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED
|
||||
else
|
||||
ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE
|
||||
CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h
|
||||
endif
|
||||
ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE
|
||||
CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CPPUTEST_ENABLE_DEBUG), Y)
|
||||
CPPUTEST_CXXFLAGS += -g
|
||||
CPPUTEST_CFLAGS += -g
|
||||
CPPUTEST_LDFLAGS += -g
|
||||
endif
|
||||
|
||||
ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N)
|
||||
CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED
|
||||
ifeq ($(CPPUTEST_USE_STD_C_LIB), Y)
|
||||
CPPUTEST_CXXFLAGS += -nostdinc++
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef $(GMOCK_HOME)
|
||||
GTEST_HOME = $(GMOCK_HOME)/gtest
|
||||
CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include
|
||||
GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a
|
||||
LD_LIBRARIES += $(GMOCK_LIBRARY)
|
||||
CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS
|
||||
CPPUTEST_WARNINGFLAGS =
|
||||
CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME)
|
||||
GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a
|
||||
LD_LIBRARIES += $(GTEST_LIBRARY)
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(CPPUTEST_USE_GCOV), Y)
|
||||
CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage
|
||||
CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
endif
|
||||
|
||||
CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS)
|
||||
CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS)
|
||||
CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE)
|
||||
CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE)
|
||||
CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS)
|
||||
|
||||
TARGET_MAP = $(COMPONENT_NAME).map.txt
|
||||
ifeq ($(CPPUTEST_MAP_FILE), Y)
|
||||
CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP)
|
||||
endif
|
||||
|
||||
# Link with CppUTest lib
|
||||
CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a
|
||||
|
||||
ifeq ($(CPPUTEST_USE_EXTENSIONS), Y)
|
||||
CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a
|
||||
endif
|
||||
|
||||
ifdef CPPUTEST_STATIC_REALTIME
|
||||
LD_LIBRARIES += -lrt
|
||||
endif
|
||||
|
||||
TARGET_LIB = \
|
||||
$(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a
|
||||
|
||||
ifndef TEST_TARGET
|
||||
ifndef TARGET_PLATFORM
|
||||
TEST_TARGET = $(COMPONENT_NAME)_tests
|
||||
else
|
||||
TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests
|
||||
endif
|
||||
endif
|
||||
|
||||
#Helper Functions
|
||||
get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c)
|
||||
get_dirs_from_dirspec = $(wildcard $1)
|
||||
get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir)))
|
||||
__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2))))
|
||||
src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2))
|
||||
src_to_o = $(call src_to,.o,$1)
|
||||
src_to_d = $(call src_to,.d,$1)
|
||||
src_to_gcda = $(call src_to,.gcda,$1)
|
||||
src_to_gcno = $(call src_to,.gcno,$1)
|
||||
time = $(shell date +%s)
|
||||
delta_t = $(eval minus, $1, $2)
|
||||
debug_print_list = $(foreach word,$1,echo " $(word)";) echo;
|
||||
|
||||
#Derived
|
||||
STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP)
|
||||
|
||||
SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES)
|
||||
OBJ = $(call src_to_o,$(SRC))
|
||||
|
||||
STUFF_TO_CLEAN += $(OBJ)
|
||||
|
||||
TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES)
|
||||
TEST_OBJS = $(call src_to_o,$(TEST_SRC))
|
||||
STUFF_TO_CLEAN += $(TEST_OBJS)
|
||||
|
||||
|
||||
MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS))
|
||||
MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC))
|
||||
STUFF_TO_CLEAN += $(MOCKS_OBJS)
|
||||
|
||||
ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC)
|
||||
|
||||
# If we're using VPATH
|
||||
ifeq ($(CPPUTEST_USE_VPATH), Y)
|
||||
# gather all the source directories and add them
|
||||
VPATH += $(sort $(dir $(ALL_SRC)))
|
||||
# Add the component name to the objs dir path, to differentiate between same-name objects
|
||||
CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR))
|
||||
endif
|
||||
|
||||
#Test coverage with gcov
|
||||
GCOV_OUTPUT = gcov_output.txt
|
||||
GCOV_REPORT = gcov_report.txt
|
||||
GCOV_ERROR = gcov_error.txt
|
||||
GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC))
|
||||
GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC))
|
||||
TEST_OUTPUT = $(TEST_TARGET).txt
|
||||
STUFF_TO_CLEAN += \
|
||||
$(GCOV_OUTPUT)\
|
||||
$(GCOV_REPORT)\
|
||||
$(GCOV_REPORT).html\
|
||||
$(GCOV_ERROR)\
|
||||
$(GCOV_GCDA_FILES)\
|
||||
$(GCOV_GCNO_FILES)\
|
||||
$(TEST_OUTPUT)
|
||||
|
||||
#The gcda files for gcov need to be deleted before each run
|
||||
#To avoid annoying messages.
|
||||
GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR)
|
||||
RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) -ojunit
|
||||
|
||||
ifeq ($(CPPUTEST_USE_GCOV), Y)
|
||||
|
||||
ifeq ($(COMPILER_NAME),$(CLANG_STR))
|
||||
LD_LIBRARIES += --coverage
|
||||
else
|
||||
LD_LIBRARIES += -lgcov
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS))
|
||||
INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir))
|
||||
MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS))
|
||||
INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir))
|
||||
|
||||
CPPUTEST_CPPFLAGS += $(INCLUDES) $(CPPUTESTFLAGS)
|
||||
|
||||
DEP_FILES = $(call src_to_d, $(ALL_SRC))
|
||||
STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END)
|
||||
STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output
|
||||
|
||||
# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags
|
||||
CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS)
|
||||
CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS)
|
||||
CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS)
|
||||
LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS)
|
||||
|
||||
# Don't consider creating the archive a warning condition that does STDERR output
|
||||
ARFLAGS := $(ARFLAGS)c
|
||||
|
||||
DEP_FLAGS=-MMD -MP
|
||||
|
||||
# Some macros for programs to be overridden. For some reason, these are not in Make defaults
|
||||
RANLIB = ranlib
|
||||
|
||||
# Targets
|
||||
|
||||
.PHONY: all
|
||||
all: start $(TEST_TARGET)
|
||||
$(RUN_TEST_TARGET)
|
||||
|
||||
.PHONY: start
|
||||
start: $(TEST_TARGET)
|
||||
$(SILENCE)START_TIME=$(call time)
|
||||
|
||||
.PHONY: all_no_tests
|
||||
all_no_tests: $(TEST_TARGET)
|
||||
|
||||
.PHONY: flags
|
||||
flags:
|
||||
@echo
|
||||
@echo "OS ${UNAME_OS}"
|
||||
@echo "Compile C and C++ source with CPPFLAGS:"
|
||||
@$(call debug_print_list,$(CPPFLAGS))
|
||||
@echo "Compile C++ source with CXXFLAGS:"
|
||||
@$(call debug_print_list,$(CXXFLAGS))
|
||||
@echo "Compile C source with CFLAGS:"
|
||||
@$(call debug_print_list,$(CFLAGS))
|
||||
@echo "Link with LDFLAGS:"
|
||||
@$(call debug_print_list,$(LDFLAGS))
|
||||
@echo "Link with LD_LIBRARIES:"
|
||||
@$(call debug_print_list,$(LD_LIBRARIES))
|
||||
@echo "Create libraries with ARFLAGS:"
|
||||
@$(call debug_print_list,$(ARFLAGS))
|
||||
|
||||
TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START)
|
||||
test-deps: $(TEST_DEPS)
|
||||
|
||||
$(TEST_TARGET): $(TEST_DEPS)
|
||||
@echo Linking $@
|
||||
$(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS)
|
||||
|
||||
$(TARGET_LIB): $(OBJ)
|
||||
@echo Building archive $@
|
||||
$(SILENCE)mkdir -p $(dir $@)
|
||||
$(SILENCE)$(AR) $(ARFLAGS) $@ $^
|
||||
$(SILENCE)$(RANLIB) $@
|
||||
|
||||
test: $(TEST_TARGET)
|
||||
$(RUN_TEST_TARGET) | tee $(TEST_OUTPUT)
|
||||
|
||||
vtest: $(TEST_TARGET)
|
||||
$(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT)
|
||||
|
||||
$(CPPUTEST_OBJS_DIR)/%.o: %.cc
|
||||
@echo compiling $(notdir $<)
|
||||
$(SILENCE)mkdir -p $(dir $@)
|
||||
$(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(CPPUTEST_OBJS_DIR)/%.o: %.cpp
|
||||
@echo compiling $(notdir $<)
|
||||
$(SILENCE)mkdir -p $(dir $@)
|
||||
$(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(CPPUTEST_OBJS_DIR)/%.o: %.c
|
||||
@echo compiling $(notdir $<)
|
||||
$(SILENCE)mkdir -p $(dir $@)
|
||||
$(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
ifneq "$(MAKECMDGOALS)" "clean"
|
||||
-include $(DEP_FILES)
|
||||
endif
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@echo Making clean
|
||||
$(SILENCE)$(RM) $(STUFF_TO_CLEAN)
|
||||
$(SILENCE)rm -rf gcov objs #$(CPPUTEST_OBJS_DIR)
|
||||
$(SILENCE)rm -rf $(CPPUTEST_LIB_DIR)
|
||||
$(SILENCE)find . -name "*.gcno" | xargs rm -f
|
||||
$(SILENCE)find . -name "*.gcda" | xargs rm -f
|
||||
|
||||
#realclean gets rid of all gcov, o and d files in the directory tree
|
||||
#not just the ones made by this makefile
|
||||
.PHONY: realclean
|
||||
realclean: clean
|
||||
$(SILENCE)rm -rf gcov
|
||||
$(SILENCE)find . -name "*.gdcno" | xargs rm -f
|
||||
$(SILENCE)find . -name "*.[do]" | xargs rm -f
|
||||
|
||||
gcov: test
|
||||
ifeq ($(CPPUTEST_USE_VPATH), Y)
|
||||
$(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR)
|
||||
else
|
||||
$(SILENCE)for d in $(SRC_DIRS) ; do \
|
||||
gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \
|
||||
done
|
||||
$(SILENCE)for f in $(SRC_FILES) ; do \
|
||||
gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \
|
||||
done
|
||||
endif
|
||||
# $(CPPUTEST_HOME)/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT)
|
||||
/usr/share/cpputest/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT)
|
||||
$(SILENCE)cat $(GCOV_REPORT)
|
||||
$(SILENCE)mkdir -p gcov
|
||||
$(SILENCE)mv *.gcov gcov
|
||||
$(SILENCE)mv gcov_* gcov
|
||||
@echo "See gcov directory for details"
|
||||
|
||||
.PHONEY: format
|
||||
format:
|
||||
$(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR)
|
||||
|
||||
.PHONEY: debug
|
||||
debug:
|
||||
@echo
|
||||
@echo "Target Source files:"
|
||||
@$(call debug_print_list,$(SRC))
|
||||
@echo "Target Object files:"
|
||||
@$(call debug_print_list,$(OBJ))
|
||||
@echo "Test Source files:"
|
||||
@$(call debug_print_list,$(TEST_SRC))
|
||||
@echo "Test Object files:"
|
||||
@$(call debug_print_list,$(TEST_OBJS))
|
||||
@echo "Mock Source files:"
|
||||
@$(call debug_print_list,$(MOCKS_SRC))
|
||||
@echo "Mock Object files:"
|
||||
@$(call debug_print_list,$(MOCKS_OBJS))
|
||||
@echo "All Input Dependency files:"
|
||||
@$(call debug_print_list,$(DEP_FILES))
|
||||
@echo Stuff to clean:
|
||||
@$(call debug_print_list,$(STUFF_TO_CLEAN))
|
||||
@echo Includes:
|
||||
@$(call debug_print_list,$(INCLUDES))
|
||||
|
||||
-include $(OTHER_MAKEFILE_TO_INCLUDE)
|
|
@ -0,0 +1,202 @@
|
|||
/* General C++ Object Thunking class
|
||||
*
|
||||
* - allows direct callbacks to non-static C++ class functions
|
||||
* - keeps track for the corresponding class instance
|
||||
* - supports an optional context parameter for the called function
|
||||
* - ideally suited for class object receiving interrupts (NVIC_SetVector)
|
||||
*
|
||||
* Copyright (c) 2014-2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __CTHUNK_H__
|
||||
#define __CTHUNK_H__
|
||||
|
||||
#define CTHUNK_ADDRESS 1
|
||||
|
||||
#if defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__thumb2__)
|
||||
#define CTHUNK_VARIABLES volatile uint32_t code[1]
|
||||
/**
|
||||
* CTHUNK disassembly for Cortex-M3/M4 (thumb2):
|
||||
* * ldm.w pc,{r0,r1,r2,pc}
|
||||
*
|
||||
* This instruction loads the arguments for the static thunking function to r0-r2, and
|
||||
* branches to that function by loading its address into PC.
|
||||
*
|
||||
* This is safe for both regular calling and interrupt calling, since it only touches scratch registers
|
||||
* which should be saved by the caller, and are automatically saved as part of the IRQ context switch.
|
||||
*/
|
||||
#define CTHUNK_ASSIGMENT m_thunk.code[0] = 0x8007E89F
|
||||
|
||||
#elif defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0)
|
||||
/*
|
||||
* CTHUNK disassembly for Cortex M0 (thumb):
|
||||
* * push {r0,r1,r2,r3,r4,lr} save touched registers and return address
|
||||
* * movs r4,#4 set up address to load arguments from (immediately following this code block) (1)
|
||||
* * add r4,pc set up address to load arguments from (immediately following this code block) (2)
|
||||
* * ldm r4!,{r0,r1,r2,r3} load arguments for static thunk function
|
||||
* * blx r3 call static thunk function
|
||||
* * pop {r0,r1,r2,r3,r4,pc} restore scratch registers and return from function
|
||||
*/
|
||||
#define CTHUNK_VARIABLES volatile uint32_t code[3]
|
||||
#define CTHUNK_ASSIGMENT do { \
|
||||
m_thunk.code[0] = 0x2404B51F; \
|
||||
m_thunk.code[1] = 0xCC0F447C; \
|
||||
m_thunk.code[2] = 0xBD1F4798; \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#error "Target is not currently suported."
|
||||
#endif
|
||||
|
||||
/* IRQ/Exception compatible thunk entry function */
|
||||
typedef void (*CThunkEntry)(void);
|
||||
|
||||
template<class T>
|
||||
class CThunk
|
||||
{
|
||||
public:
|
||||
typedef void (T::*CCallbackSimple)(void);
|
||||
typedef void (T::*CCallback)(void* context);
|
||||
|
||||
inline CThunk(T *instance)
|
||||
{
|
||||
init(instance, NULL, NULL);
|
||||
}
|
||||
|
||||
inline CThunk(T *instance, CCallback cb)
|
||||
{
|
||||
init(instance, cb, NULL);
|
||||
}
|
||||
|
||||
~CThunk() {
|
||||
|
||||
}
|
||||
|
||||
inline CThunk(T *instance, CCallbackSimple cb)
|
||||
{
|
||||
init(instance, (CCallback)cb, NULL);
|
||||
}
|
||||
|
||||
inline CThunk(T &instance, CCallback cb)
|
||||
{
|
||||
init(instance, cb, NULL);
|
||||
}
|
||||
|
||||
inline CThunk(T &instance, CCallbackSimple cb)
|
||||
{
|
||||
init(instance, (CCallback)cb, NULL);
|
||||
}
|
||||
|
||||
inline CThunk(T &instance, CCallback cb, void* ctx)
|
||||
{
|
||||
init(instance, cb, ctx);
|
||||
}
|
||||
|
||||
inline void callback(CCallback cb)
|
||||
{
|
||||
m_callback = cb;
|
||||
}
|
||||
|
||||
inline void callback(CCallbackSimple cb)
|
||||
{
|
||||
m_callback = (CCallback)cb;
|
||||
}
|
||||
|
||||
inline void context(void* ctx)
|
||||
{
|
||||
m_thunk.context = (uint32_t)ctx;
|
||||
}
|
||||
|
||||
inline void context(uint32_t ctx)
|
||||
{
|
||||
m_thunk.context = ctx;
|
||||
}
|
||||
|
||||
inline uint32_t entry(void)
|
||||
{
|
||||
return (((uint32_t)&m_thunk)|CTHUNK_ADDRESS);
|
||||
}
|
||||
|
||||
/* get thunk entry point for connecting rhunk to an IRQ table */
|
||||
inline operator CThunkEntry(void)
|
||||
{
|
||||
return (CThunkEntry)entry();
|
||||
}
|
||||
|
||||
/* get thunk entry point for connecting rhunk to an IRQ table */
|
||||
inline operator uint32_t(void)
|
||||
{
|
||||
return entry();
|
||||
}
|
||||
|
||||
/* simple test function */
|
||||
inline void call(void)
|
||||
{
|
||||
(((CThunkEntry)(entry()))());
|
||||
}
|
||||
|
||||
private:
|
||||
T* m_instance;
|
||||
volatile CCallback m_callback;
|
||||
|
||||
// TODO: this needs proper fix, to refactor toolchain header file and all its use
|
||||
// PACKED there is not defined properly for IAR
|
||||
#if defined (__ICCARM__)
|
||||
typedef __packed struct
|
||||
{
|
||||
CTHUNK_VARIABLES;
|
||||
volatile uint32_t instance;
|
||||
volatile uint32_t context;
|
||||
volatile uint32_t callback;
|
||||
volatile uint32_t trampoline;
|
||||
} CThunkTrampoline;
|
||||
#else
|
||||
typedef struct
|
||||
{
|
||||
CTHUNK_VARIABLES;
|
||||
volatile uint32_t instance;
|
||||
volatile uint32_t context;
|
||||
volatile uint32_t callback;
|
||||
volatile uint32_t trampoline;
|
||||
} __attribute__((__packed__)) CThunkTrampoline;
|
||||
#endif
|
||||
|
||||
static void trampoline(T* instance, void* ctx, CCallback* cb)
|
||||
{
|
||||
if(instance && *cb) {
|
||||
(static_cast<T*>(instance)->**cb)(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
volatile CThunkTrampoline m_thunk;
|
||||
|
||||
inline void init(T *instance, CCallback cb, void* ctx)
|
||||
{
|
||||
/* remember callback - need to add this level of redirection
|
||||
as pointer size for member functions differs between platforms */
|
||||
m_callback = cb;
|
||||
|
||||
/* populate thunking trampoline */
|
||||
// CTHUNK_ASSIGMENT;
|
||||
// m_thunk.context = (uint32_t)ctx;
|
||||
// m_thunk.instance = (uint32_t)instance;
|
||||
// m_thunk.callback = (uint32_t)&m_callback;
|
||||
// m_thunk.trampoline = (uint32_t)&trampoline;
|
||||
|
||||
// __ISB();
|
||||
// __DSB();
|
||||
}
|
||||
};
|
||||
|
||||
#endif/*__CTHUNK_H__*/
|
|
@ -0,0 +1,604 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 MBED_FUNCTIONPOINTER_H
|
||||
#define MBED_FUNCTIONPOINTER_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <new>
|
||||
#include "FunctionPointerBase.h"
|
||||
#include "FunctionPointerBind.h"
|
||||
|
||||
namespace mbed {
|
||||
/** A class for storing and calling a pointer to a static or member void function without arguments
|
||||
*/
|
||||
template <typename R>
|
||||
class FunctionPointer0 : public FunctionPointerBase<R>{
|
||||
public:
|
||||
typedef R(*static_fp)(void);
|
||||
typedef struct arg_struct{
|
||||
} ArgStruct;
|
||||
/** Create a FunctionPointer, attaching a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
FunctionPointer0(static_fp function = 0):
|
||||
FunctionPointerBase<R>()
|
||||
{
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FunctionPointer, attaching a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FunctionPointer0(T *object, R (T::*member)(void)):
|
||||
FunctionPointerBase<R>()
|
||||
{
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
void attach(static_fp function) {
|
||||
FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer0::staticcaller;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(void)) {
|
||||
FunctionPointerBase<R>::_object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(void)>(FunctionPointerBase<R>::_member) = member;
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer0::membercaller<T>;
|
||||
}
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(){
|
||||
return FunctionPointerBase<R>::call(NULL);
|
||||
}
|
||||
|
||||
FunctionPointerBind<R> bind() {
|
||||
FunctionPointerBind<R> fp;
|
||||
fp.bind(&FunctionPointerBase<R>::_nullops, (ArgStruct *) NULL, this);
|
||||
return fp;
|
||||
}
|
||||
|
||||
static_fp get_function()const {
|
||||
return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
|
||||
}
|
||||
|
||||
R operator ()(void) {
|
||||
return call();
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static R membercaller(void *object, uintptr_t *member, void *arg) {
|
||||
(void) arg;
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
|
||||
return (o->**m)();
|
||||
}
|
||||
static R staticcaller(void *object, uintptr_t *member, void *arg) {
|
||||
(void) arg;
|
||||
(void) member;
|
||||
static_fp f = reinterpret_cast<static_fp>(object);
|
||||
return f();
|
||||
}
|
||||
};
|
||||
|
||||
/* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member void function with one argument
|
||||
*/
|
||||
template <typename R, typename A1>
|
||||
class FunctionPointer1 : public FunctionPointerBase<R> {
|
||||
protected:
|
||||
typedef struct arg_struct{
|
||||
A1 a1;
|
||||
arg_struct(const A1 *b1) {
|
||||
a1 = *b1;
|
||||
}
|
||||
} ArgStruct;
|
||||
|
||||
public:
|
||||
typedef R(*static_fp)(A1);
|
||||
/** Create a FunctionPointer, attaching a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
FunctionPointer1(static_fp function = 0) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FunctionPointer, attaching a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FunctionPointer1(T *object, R (T::*member)(A1)) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
void attach(static_fp function) {
|
||||
FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer1::staticcaller;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(A1))
|
||||
{
|
||||
FunctionPointerBase<R>::_object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(A1)>(FunctionPointerBase<R>::_member) = member;
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer1::membercaller<T>;
|
||||
}
|
||||
|
||||
FunctionPointerBind<R> bind(const A1 &a1) {
|
||||
FunctionPointerBind<R> fp;
|
||||
fp.bind(&_fp1_ops, (ArgStruct *) NULL, this, &a1);
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(A1 a1)
|
||||
{
|
||||
ArgStruct Args(&a1);
|
||||
return FunctionPointerBase<R>::call(&Args);
|
||||
}
|
||||
|
||||
static_fp get_function()const
|
||||
{
|
||||
return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
|
||||
}
|
||||
|
||||
R operator ()(A1 a) {
|
||||
return call(a);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static R membercaller(void *object, uintptr_t *member, void *arg) {
|
||||
ArgStruct *Args = static_cast<ArgStruct *>(arg);
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
|
||||
return (o->**m)(Args->a1);
|
||||
}
|
||||
static R staticcaller(void *object, uintptr_t *member, void *arg) {
|
||||
ArgStruct *Args = static_cast<ArgStruct *>(arg);
|
||||
(void) member;
|
||||
static_fp f = reinterpret_cast<static_fp>(object);
|
||||
return f(Args->a1);
|
||||
}
|
||||
/* static void constructor(void * dest, va_list args) {
|
||||
new(dest) ArgStruct(va_arg(args,A1*));
|
||||
}
|
||||
static void copy_constructor(void *dest , void* src) {
|
||||
ArgStruct *src_args = static_cast<ArgStruct *>(src);
|
||||
new(dest) ArgStruct(&(src_args->a1));
|
||||
}
|
||||
static void destructor(void *args) {
|
||||
ArgStruct *argstruct = static_cast<ArgStruct *>(args);
|
||||
argstruct->~arg_struct();
|
||||
}
|
||||
*/
|
||||
protected:
|
||||
static const struct FunctionPointerBase<R>::ArgOps _fp1_ops;
|
||||
};
|
||||
|
||||
template <typename R, typename A1>
|
||||
const struct FunctionPointerBase<R>::ArgOps FunctionPointer1<R,A1>::_fp1_ops = {
|
||||
FunctionPointer1<R,A1>::constructor,
|
||||
FunctionPointer1<R,A1>::copy_constructor,
|
||||
FunctionPointer1<R,A1>::destructor
|
||||
};
|
||||
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member void function with two arguments
|
||||
*/
|
||||
template <typename R, typename A1, typename A2>
|
||||
class FunctionPointer2 : public FunctionPointerBase<R> {
|
||||
protected:
|
||||
typedef struct arg_struct{
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
arg_struct(const A1 *b1, const A2 *b2) {
|
||||
a1 = *b1;
|
||||
a2 = *b2;
|
||||
}
|
||||
} ArgStruct;
|
||||
|
||||
public:
|
||||
typedef R(*static_fp)(A1, A2);
|
||||
/** Create a FunctionPointer, attaching a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
FunctionPointer2(static_fp function = 0) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FunctionPointer, attaching a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FunctionPointer2(T *object, R (T::*member)(A1, A2)) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
void attach(static_fp function) {
|
||||
FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer2::staticcaller;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(A1, A2))
|
||||
{
|
||||
FunctionPointerBase<R>::_object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(A1, A2)>(FunctionPointerBase<R>::_member) = member;
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer2::membercaller<T>;
|
||||
}
|
||||
|
||||
FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2) {
|
||||
FunctionPointerBind<R> fp;
|
||||
fp.bind(&_fp2_ops, (ArgStruct *) NULL, this, &a1, &a2);
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(A1 a1, A2 a2)
|
||||
{
|
||||
ArgStruct Args(&a1, &a2);
|
||||
return FunctionPointerBase<R>::call(&Args);
|
||||
}
|
||||
|
||||
static_fp get_function()const
|
||||
{
|
||||
return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
|
||||
}
|
||||
|
||||
R operator ()(A1 a1, A2 a2) {
|
||||
return call(a1, a2);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static R membercaller(void *object, uintptr_t *member, void *arg) {
|
||||
ArgStruct *Args = static_cast<ArgStruct *>(arg);
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member);
|
||||
return (o->**m)(Args->a1, Args->a2);
|
||||
}
|
||||
static R staticcaller(void *object, uintptr_t *member, void *arg) {
|
||||
ArgStruct *Args = static_cast<ArgStruct *>(arg);
|
||||
(void) member;
|
||||
static_fp f = reinterpret_cast<static_fp>(object);
|
||||
return f(Args->a1, Args->a2);
|
||||
}
|
||||
/* static void constructor(void * dest, va_list args) {
|
||||
A1 *a1 = va_arg(args, A1*);
|
||||
A2 *a2 = va_arg(args, A2*);
|
||||
new(dest) ArgStruct(a1, a2);
|
||||
}
|
||||
static void copy_constructor(void *dest , void* src) {
|
||||
ArgStruct *src_args = static_cast<ArgStruct *>(src);
|
||||
new(dest) ArgStruct(&(src_args->a1), &(src_args->a2));
|
||||
}
|
||||
static void destructor(void *args) {
|
||||
ArgStruct *argstruct = static_cast<ArgStruct *>(args);
|
||||
argstruct->~arg_struct();
|
||||
}
|
||||
*/
|
||||
protected:
|
||||
static const struct FunctionPointerBase<R>::ArgOps _fp2_ops;
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2>
|
||||
const struct FunctionPointerBase<R>::ArgOps FunctionPointer2<R,A1,A2>::_fp2_ops = {
|
||||
FunctionPointer2<R,A1,A2>::constructor,
|
||||
FunctionPointer2<R,A1,A2>::copy_constructor,
|
||||
FunctionPointer2<R,A1,A2>::destructor
|
||||
};
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member void function with three arguments
|
||||
*/
|
||||
template <typename R, typename A1, typename A2, typename A3>
|
||||
class FunctionPointer3 : public FunctionPointerBase<R> {
|
||||
protected:
|
||||
typedef struct arg_struct{
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
arg_struct(const A1 *b1, const A2 *b2, const A3* b3) {
|
||||
a1 = *b1;
|
||||
a2 = *b2;
|
||||
a3 = *b3;
|
||||
}
|
||||
} ArgStruct;
|
||||
|
||||
public:
|
||||
typedef R(*static_fp)(A1, A2, A3);
|
||||
/** Create a FunctionPointer, attaching a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
FunctionPointer3(static_fp function = 0) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FunctionPointer, attaching a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FunctionPointer3(T *object, R (T::*member)(A1, A2, A3)) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
void attach(static_fp function) {
|
||||
FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer3::staticcaller;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(A1, A2, A3))
|
||||
{
|
||||
FunctionPointerBase<R>::_object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(A1, A2, A3)>(FunctionPointerBase<R>::_member) = member;
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer3::membercaller<T>;
|
||||
}
|
||||
|
||||
FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2, const A3 &a3) {
|
||||
FunctionPointerBind<R> fp;
|
||||
fp.bind(&_fp3_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3);
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
ArgStruct Args(&a1, &a2, &a3);
|
||||
return FunctionPointerBase<R>::call(&Args);
|
||||
}
|
||||
|
||||
static_fp get_function()const
|
||||
{
|
||||
return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
|
||||
}
|
||||
|
||||
R operator ()(A1 a1, A2 a2, A3 a3) {
|
||||
return call(a1, a2, a3);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static R membercaller(void *object, uintptr_t *member, void *arg) {
|
||||
ArgStruct *Args = static_cast<ArgStruct *>(arg);
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
|
||||
return (o->**m)(Args->a1, Args->a2, Args->a3);
|
||||
}
|
||||
static R staticcaller(void *object, uintptr_t *member, void *arg) {
|
||||
ArgStruct *Args = static_cast<ArgStruct *>(arg);
|
||||
(void) member;
|
||||
static_fp f = reinterpret_cast<static_fp>(object);
|
||||
return f(Args->a1, Args->a2, Args->a3);
|
||||
}
|
||||
/* static void constructor(void * dest, va_list args) {
|
||||
A1 *a1 = va_arg(args, A1*);
|
||||
A2 *a2 = va_arg(args, A2*);
|
||||
A3 *a3 = va_arg(args, A3*);
|
||||
new(dest) ArgStruct(a1, a2, a3);
|
||||
}
|
||||
static void copy_constructor(void *dest , void* src) {
|
||||
ArgStruct *src_args = static_cast<ArgStruct *>(src);
|
||||
new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3));
|
||||
}
|
||||
static void destructor(void *args) {
|
||||
ArgStruct *argstruct = static_cast<ArgStruct *>(args);
|
||||
argstruct->~arg_struct();
|
||||
}
|
||||
*/
|
||||
protected:
|
||||
static const struct FunctionPointerBase<R>::ArgOps _fp3_ops;
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2, typename A3>
|
||||
const struct FunctionPointerBase<R>::ArgOps FunctionPointer3<R,A1,A2,A3>::_fp3_ops = {
|
||||
FunctionPointer3<R,A1,A2,A3>::constructor,
|
||||
FunctionPointer3<R,A1,A2,A3>::copy_constructor,
|
||||
FunctionPointer3<R,A1,A2,A3>::destructor
|
||||
};
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member void function with four arguments
|
||||
*/
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||
class FunctionPointer4 : public FunctionPointerBase<R> {
|
||||
protected:
|
||||
typedef struct arg_struct{
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
arg_struct(const A1 *b1, const A2 *b2, const A3* b3, const A4* b4) {
|
||||
a1 = *b1;
|
||||
a2 = *b2;
|
||||
a3 = *b3;
|
||||
a4 = *b4;
|
||||
}
|
||||
} ArgStruct;
|
||||
|
||||
public:
|
||||
typedef R(*static_fp)(A1, A2, A3, A4);
|
||||
/** Create a FunctionPointer, attaching a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
FunctionPointer4(static_fp function = 0) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FunctionPointer, attaching a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FunctionPointer4(T *object, R (T::*member)(A1, A2, A3, A4)) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
void attach(static_fp function) {
|
||||
FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer4::staticcaller;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(A1, A2, A3, A4))
|
||||
{
|
||||
FunctionPointerBase<R>::_object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(FunctionPointerBase<R>::_member) = member;
|
||||
FunctionPointerBase<R>::_membercaller = &FunctionPointer4::membercaller<T>;
|
||||
}
|
||||
|
||||
FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) {
|
||||
FunctionPointerBind<R> fp;
|
||||
fp.bind(&_fp4_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3, &a4);
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(A1 a1, A2 a2, A3 a3, A4 a4)
|
||||
{
|
||||
ArgStruct Args(&a1, &a2, &a3, &a4);
|
||||
return FunctionPointerBase<R>::call(&Args);
|
||||
}
|
||||
|
||||
static_fp get_function()const
|
||||
{
|
||||
return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
|
||||
}
|
||||
|
||||
R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) {
|
||||
return call(a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static R membercaller(void *object, uintptr_t *member, void *arg) {
|
||||
ArgStruct *Args = static_cast<ArgStruct *>(arg);
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(A1, A2, A3, A4) = reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(member);
|
||||
return (o->**m)(Args->a1, Args->a2, Args->a3, Args->a4);
|
||||
}
|
||||
static R staticcaller(void *object, uintptr_t *member, void *arg) {
|
||||
ArgStruct *Args = static_cast<ArgStruct *>(arg);
|
||||
(void) member;
|
||||
static_fp f = reinterpret_cast<static_fp>(object);
|
||||
return f(Args->a1, Args->a2, Args->a3, Args->a4);
|
||||
}
|
||||
/* static void constructor(void * dest, va_list args) {
|
||||
A1 *a1 = va_arg(args, A1*);
|
||||
A2 *a2 = va_arg(args, A2*);
|
||||
A3 *a3 = va_arg(args, A3*);
|
||||
A4 *a4 = va_arg(args, A4*);
|
||||
new(dest) ArgStruct(a1, a2, a3, a4);
|
||||
}
|
||||
static void copy_constructor(void *dest , void* src) {
|
||||
ArgStruct *src_args = static_cast<ArgStruct *>(src);
|
||||
new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3), &(src_args->a4));
|
||||
}
|
||||
static void destructor(void *args) {
|
||||
ArgStruct *argstruct = static_cast<ArgStruct *>(args);
|
||||
argstruct->~arg_struct();
|
||||
}
|
||||
*/
|
||||
protected:
|
||||
static const struct FunctionPointerBase<R>::ArgOps _fp4_ops;
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||
const struct FunctionPointerBase<R>::ArgOps FunctionPointer4<R,A1,A2,A3,A4>::_fp4_ops = {
|
||||
FunctionPointer4<R,A1,A2,A3,A4>::constructor,
|
||||
FunctionPointer4<R,A1,A2,A3,A4>::copy_constructor,
|
||||
FunctionPointer4<R,A1,A2,A3,A4>::destructor
|
||||
};
|
||||
|
||||
typedef FunctionPointer0<void> FunctionPointer;
|
||||
//typedef FunctionPointer1<void, int> event_callback_t;
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif
|
|
@ -0,0 +1,89 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 MBED_FUNCTIONPOINTERBASE_H
|
||||
#define MBED_FUNCTIONPOINTERBASE_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
namespace mbed {
|
||||
|
||||
template<typename R>
|
||||
class FunctionPointerBase {
|
||||
public:
|
||||
operator bool(void) const {
|
||||
return (_membercaller != NULL) && (_object != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current function pointer assignment
|
||||
* After clear(), this instance will point to nothing (NULL)
|
||||
*/
|
||||
virtual void clear() {
|
||||
_membercaller = NULL;
|
||||
_object = NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
struct ArgOps {
|
||||
void (*constructor)(void *, va_list);
|
||||
void (*copy_args)(void *, void *);
|
||||
void (*destructor)(void *);
|
||||
};
|
||||
void * _object; // object Pointer/function pointer
|
||||
R (*_membercaller)(void *, uintptr_t *, void *);
|
||||
// aligned raw member function pointer storage - converted back by registered _membercaller
|
||||
uintptr_t _member[4];
|
||||
static const struct ArgOps _nullops;
|
||||
|
||||
protected:
|
||||
FunctionPointerBase():_object(NULL), _membercaller(NULL) {}
|
||||
FunctionPointerBase(const FunctionPointerBase<R> & fp) {
|
||||
copy(&fp);
|
||||
}
|
||||
virtual ~FunctionPointerBase() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the member pointed to by object::member or (function)object
|
||||
* @param arg
|
||||
* @return
|
||||
*/
|
||||
inline R call(void* arg) {
|
||||
return _membercaller(_object, _member, arg);
|
||||
}
|
||||
|
||||
void copy(const FunctionPointerBase<R> * fp) {
|
||||
_object = fp->_object;
|
||||
memcpy (_member, fp->_member, sizeof(_member));
|
||||
_membercaller = fp->_membercaller;
|
||||
}
|
||||
private:
|
||||
static void _null_constructor(void * dest, va_list args) {(void) dest;(void) args;}
|
||||
static void _null_copy_args(void *dest , void* src) {(void) dest; (void) src;}
|
||||
static void _null_destructor(void *args) {(void) args;}
|
||||
|
||||
};
|
||||
template<typename R>
|
||||
const struct FunctionPointerBase<R>::ArgOps FunctionPointerBase<R>::_nullops = {
|
||||
FunctionPointerBase<R>::_null_constructor,
|
||||
FunctionPointerBase<R>::_null_copy_args,
|
||||
FunctionPointerBase<R>::_null_destructor
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,112 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 MBED_FUNCTIONPOINTERBIND_H__
|
||||
#define MBED_FUNCTIONPOINTERBIND_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include "FunctionPointerBase.h"
|
||||
|
||||
#ifndef EVENT_STORAGE_SIZE
|
||||
#define EVENT_STORAGE_SIZE 32
|
||||
#endif
|
||||
|
||||
#define MBED_STATIC_ASSERT(MBED_STATIC_ASSERT_FAILED,MSG)\
|
||||
switch(0){\
|
||||
case 0:case (MBED_STATIC_ASSERT_FAILED): \
|
||||
break;}
|
||||
|
||||
namespace mbed{
|
||||
|
||||
template<typename R>
|
||||
class FunctionPointerBind : public FunctionPointerBase<R> {
|
||||
public:
|
||||
// Call the Event
|
||||
inline R call() {
|
||||
return FunctionPointerBase<R>::call(static_cast<void *>(_storage));
|
||||
}
|
||||
FunctionPointerBind():
|
||||
FunctionPointerBase<R>(),
|
||||
_ops(&FunctionPointerBase<R>::_nullops)
|
||||
{}
|
||||
|
||||
FunctionPointerBind(const FunctionPointerBind<R> & fp):
|
||||
FunctionPointerBase<R>(),
|
||||
_ops(&FunctionPointerBase<R>::_nullops) {
|
||||
*this = fp;
|
||||
}
|
||||
|
||||
virtual ~FunctionPointerBind() {
|
||||
_ops->destructor(_storage);
|
||||
}
|
||||
|
||||
FunctionPointerBind<R> & operator=(const FunctionPointerBind<R>& rhs) {
|
||||
if (_ops != &FunctionPointerBase<R>::_nullops) {
|
||||
_ops->destructor(_storage);
|
||||
}
|
||||
FunctionPointerBase<R>::copy(&rhs);
|
||||
_ops = rhs._ops;
|
||||
_ops->copy_args(_storage, (void *)rhs._storage);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current binding, making this instance unbound
|
||||
*/
|
||||
virtual void clear() {
|
||||
if (_ops != &FunctionPointerBase<R>::_nullops) {
|
||||
_ops->destructor(_storage);
|
||||
}
|
||||
_ops = &FunctionPointerBase<R>::_nullops;
|
||||
FunctionPointerBase<R>::clear();
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
FunctionPointerBind<R> & bind(const struct FunctionPointerBase<R>::ArgOps * ops , S * argStruct, FunctionPointerBase<R> *fp, ...) {
|
||||
MBED_STATIC_ASSERT(sizeof(S) <= sizeof(_storage), ERROR: Arguments too large for FunctionPointerBind internal storage)
|
||||
if (_ops != &FunctionPointerBase<R>::_nullops) {
|
||||
_ops->destructor(_storage);
|
||||
}
|
||||
_ops = ops;
|
||||
FunctionPointerBase<R>::copy(fp);
|
||||
assert(this->_ops != NULL);
|
||||
assert(this->_ops->constructor != NULL);
|
||||
if (argStruct) {
|
||||
this->_ops->copy_args(this->_storage, (void *)argStruct);
|
||||
} else {
|
||||
va_list args;
|
||||
va_start(args, fp);
|
||||
this->_ops->constructor(_storage, args);
|
||||
va_end(args);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
R operator()() {
|
||||
return call();
|
||||
}
|
||||
|
||||
protected:
|
||||
const struct FunctionPointerBase<R>::ArgOps * _ops;
|
||||
uint32_t _storage[(EVENT_STORAGE_SIZE+sizeof(uint32_t)-1)/sizeof(uint32_t)];
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MBED_FUNCTIONPOINTERBIND_H__
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 TICKER_H
|
||||
#define TICKER_H
|
||||
|
||||
namespace mbed
|
||||
{
|
||||
typedef uint64_t timestamp_t;
|
||||
|
||||
class Ticker{
|
||||
public :
|
||||
Ticker() {}
|
||||
~Ticker(){}
|
||||
|
||||
// Ticker
|
||||
template<typename T>
|
||||
void attach_us(T* tptr, void (T::*mptr)(void), timestamp_t){}
|
||||
|
||||
void detach();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TICKER_H
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
#include "CppUTest/TestPlugin.h"
|
||||
#include "CppUTest/TestRegistry.h"
|
||||
#include "CppUTestExt/MockSupportPlugin.h"
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
return CommandLineTestRunner::RunAllTests(ac, av);
|
||||
}
|
||||
|
||||
//#include "../m2mbase/m2mbasetest.h"
|
||||
#include "../m2mobject/m2mobjecttest.h"
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 IP6STRING_H
|
||||
#define IP6STRING_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**
|
||||
* Print binary IPv6 address to a string.
|
||||
* String must contain enough room for full address, 40 bytes exact.
|
||||
* IPv4 tunneling addresses are not covered.
|
||||
* \param ip6addr IPv6 address.
|
||||
* \p buffer to write string to.
|
||||
*/
|
||||
uint_fast8_t ip6tos(const void *ip6addr, char *p);
|
||||
|
||||
/**
|
||||
* Convert numeric IPv6 address string to a binary.
|
||||
* IPv4 tunneling addresses are not covered.
|
||||
* \param ip6addr IPv6 address in string format.
|
||||
* \param len Lenght of ipv6 string, maximum of 41.
|
||||
* \param dest buffer for address. MUST be 16 bytes.
|
||||
*/
|
||||
void stoip6(const char *ip6addr, size_t len, void *dest);
|
||||
/**
|
||||
* Find out numeric IPv6 address prefix length
|
||||
* \param ip6addr IPv6 address in string format
|
||||
* \return prefix length or 0 if it not given
|
||||
*/
|
||||
unsigned char sipv6_prefixlength(const char *ip6addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 MBED_H
|
||||
#define MBED_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#endif // MBED_H
|
|
@ -0,0 +1,736 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 NS_LIST_H_
|
||||
#define NS_LIST_H_
|
||||
|
||||
#include "ns_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file
|
||||
* \brief Linked list support library
|
||||
*
|
||||
* The ns_list.h file provides a doubly-linked list/queue, providing O(1)
|
||||
* performance for all insertion/removal operations, and access to either
|
||||
* end of the list.
|
||||
*
|
||||
* Memory footprint is two pointers for the list head, and two pointers in each
|
||||
* list entry. It is similar in concept to BSD's TAILQ.
|
||||
*
|
||||
* Although the API is symmetrical and O(1) in both directions, due to internal
|
||||
* pointer design, it is *slightly* more efficient to insert at the end when
|
||||
* used as a queue, and to iterate forwards rather than backwards.
|
||||
*
|
||||
* Example of an entry type that can be stored to this list.
|
||||
* ~~~
|
||||
* typedef struct example_entry
|
||||
* {
|
||||
* uint8_t *data;
|
||||
* uint32_t data_count;
|
||||
* ns_list_link_t link;
|
||||
* }
|
||||
* example_entry_t;
|
||||
*
|
||||
* static NS_LIST_HEAD(example_entry_t, link) my_list;
|
||||
* ns_list_init(&my_list);
|
||||
* ~~~
|
||||
* OR
|
||||
* ~~~
|
||||
* NS_LIST_HEAD(example_entry_t, link) my_list = NS_LIST_INIT(my_list);
|
||||
* ~~~
|
||||
* OR
|
||||
* ~~~
|
||||
* static NS_LIST_DEFINE(my_list, example_entry_t, link);
|
||||
* ~~~
|
||||
* OR
|
||||
* ~~~
|
||||
* typedef NS_LIST_HEAD(example_entry_t, link) example_list_t;
|
||||
* example_list_t NS_LIST_NAME_INIT(my_list);
|
||||
* ~~~
|
||||
* NOTE: the link field SHALL NOT be accessed by the user.
|
||||
*
|
||||
* An entry can exist on multiple lists by having multiple link fields.
|
||||
*
|
||||
* All the list operations are implemented as macros, most of which are backed
|
||||
* by optionally-inline functions. The macros do not evaluate any arguments more
|
||||
* than once, unless documented.
|
||||
*
|
||||
* In macro documentation, `list_t` refers to a list type defined using
|
||||
* NS_LIST_HEAD(), and `entry_t` to the entry type that was passed to it.
|
||||
*/
|
||||
|
||||
/** \brief Underlying generic linked list head.
|
||||
*
|
||||
* Users should not use this type directly, but use the NS_LIST_HEAD() macro.
|
||||
*/
|
||||
typedef struct ns_list
|
||||
{
|
||||
void *first_entry; ///< Pointer to first entry, or NULL if list is empty
|
||||
void **last_nextptr; ///< Pointer to last entry's `next` pointer, or
|
||||
///< to head's `first_entry` pointer if list is empty
|
||||
} ns_list_t;
|
||||
|
||||
/** \brief Declare a list head type
|
||||
*
|
||||
* This union stores the real list head, and also encodes as compile-time type
|
||||
* information the offset of the link pointer, and the type of the entry.
|
||||
*
|
||||
* Note that type information is compiler-dependent; this means
|
||||
* ns_list_get_first() could return either `void *`, or a pointer to the actual
|
||||
* entry type. So `ns_list_get_first()->data` is not a portable construct -
|
||||
* always assign returned entry pointers to a properly typed pointer variable.
|
||||
* This assignment will be then type-checked where the compiler supports it, and
|
||||
* will dereference correctly on compilers that don't support this extension.
|
||||
* ~~~
|
||||
* NS_LIST_HEAD(example_entry_t, link) my_list;
|
||||
*
|
||||
* example_entry_t *entry = ns_list_get_first(&my_list);
|
||||
* do_something(entry->data);
|
||||
* ~~~
|
||||
* Each use of this macro generates a new anonymous union, so these two lists
|
||||
* have different types:
|
||||
* ~~~
|
||||
* NS_LIST_HEAD(example_entry_t, link) my_list1;
|
||||
* NS_LIST_HEAD(example_entry_t, link) my_list2;
|
||||
* ~~~
|
||||
* If you need to use a list type in multiple places, eg as a function
|
||||
* parameter, use typedef:
|
||||
* ~~~
|
||||
* typedef NS_LIST_HEAD(example_entry_t, link) example_list_t;
|
||||
*
|
||||
* void example_function(example_list_t *);
|
||||
* ~~~
|
||||
*/
|
||||
#define NS_LIST_HEAD(entry_type, field) \
|
||||
union \
|
||||
{ \
|
||||
ns_list_t slist; \
|
||||
NS_STATIC_ASSERT(offsetof(entry_type, field) <= UINT_FAST8_MAX, "link offset too large") \
|
||||
char (*offset)[offsetof(entry_type, field)]; \
|
||||
entry_type *type; \
|
||||
}
|
||||
|
||||
/// \privatesection
|
||||
/** \brief Get offset of link field in entry.
|
||||
* \return `(ns_list_offset_t)` The offset of the link field for entries on the specified list
|
||||
*/
|
||||
#define NS_LIST_OFFSET_(list) ((ns_list_offset_t) sizeof *(list)->offset)
|
||||
|
||||
/** \brief Get the entry type.
|
||||
* \def NS_LIST_TYPE_
|
||||
*
|
||||
* \return The type of entry on the specified list.
|
||||
*
|
||||
* Only available if the compiler provides a "typeof" operator.
|
||||
*/
|
||||
#if defined __cplusplus && __cplusplus >= 201103L
|
||||
#define NS_LIST_TYPE_(list) decltype(*(list)->type)
|
||||
#elif defined __GNUC__
|
||||
#define NS_LIST_TYPE_(list) __typeof__(*(list)->type)
|
||||
#endif
|
||||
|
||||
/** \brief Check for compatible pointer types
|
||||
*
|
||||
* Although this can be done portably, the GCC custom version is provided to
|
||||
* produce a clearer diagnostic, and it produces an error rather than a warning.
|
||||
*
|
||||
* The portable version will produce a diagnostic about a pointer mismatch on
|
||||
* the == inside the sizeof operator. For example ARM/Norcroft C gives the error:
|
||||
*
|
||||
* operand types are incompatible ("entry_t *" and "other_t *")
|
||||
*/
|
||||
#ifdef CPPCHECK
|
||||
#define NS_PTR_MATCH_(a, b, str) ((void) 0)
|
||||
#elif defined __GNUC__
|
||||
#define NS_PTR_MATCH_(a, b, str) __extension__ \
|
||||
({ NS_STATIC_ASSERT(__builtin_types_compatible_p(__typeof__ (*(a)), __typeof__ (*(b))), \
|
||||
str) })
|
||||
#else
|
||||
#define NS_PTR_MATCH_(a, b, str) ((void) sizeof ((a) == (b)))
|
||||
#endif
|
||||
|
||||
/** \brief Internal macro to cast returned entry pointers to correct type.
|
||||
*
|
||||
* Not portable in C, alas. With GCC or C++11, the "get entry" macros return
|
||||
* correctly-typed pointers. Otherwise, the macros return `void *`.
|
||||
*
|
||||
* The attempt at a portable version would work if the C `?:` operator wasn't
|
||||
* broken - `x ? (t *) : (void *)` should really have type `(t *)` in C, but
|
||||
* it has type `(void *)`, which only makes sense for C++. The `?:` is left in,
|
||||
* in case some day it works. Some compilers may still warn if this is
|
||||
* assigned to a different type.
|
||||
*/
|
||||
#ifdef NS_LIST_TYPE_
|
||||
#define NS_LIST_TYPECAST_(list, val) ((NS_LIST_TYPE_(list) *) (val))
|
||||
#else
|
||||
#define NS_LIST_TYPECAST_(list, val) (0 ? (list)->type : (val))
|
||||
#endif
|
||||
|
||||
/** \brief Internal macro to check types of input entry pointer. */
|
||||
#define NS_LIST_TYPECHECK_(list, entry) \
|
||||
(NS_PTR_MATCH_((list)->type, (entry), "incorrect entry type for list"), (entry))
|
||||
|
||||
/** \brief Type used to pass link offset to underlying functions
|
||||
*
|
||||
* We could use size_t, but it would be unnecessarily large on 8-bit systems,
|
||||
* where we can be (pretty) confident we won't have next pointers more than
|
||||
* 256 bytes into a structure.
|
||||
*/
|
||||
typedef uint_fast8_t ns_list_offset_t;
|
||||
|
||||
/// \publicsection
|
||||
/** \brief The type for the link member in the user's entry structure.
|
||||
*
|
||||
* Users should not access this member directly - just pass its name to the
|
||||
* list head macros. The funny prev pointer simplifies common operations
|
||||
* (eg insertion, removal), at the expense of complicating rare reverse iteration.
|
||||
*
|
||||
* NB - the list implementation relies on next being the first member.
|
||||
*/
|
||||
typedef struct ns_list_link
|
||||
{
|
||||
void *next; ///< Pointer to next entry, or NULL if none
|
||||
void **prev; ///< Pointer to previous entry's (or head's) next pointer
|
||||
} ns_list_link_t;
|
||||
|
||||
/** \brief "Poison" value placed in unattached entries' link pointers.
|
||||
* \internal What are good values for this? Platform dependent, maybe just NULL
|
||||
*/
|
||||
#define NS_LIST_POISON ((void *) 0xDEADBEEF)
|
||||
|
||||
/** \brief Initialiser for an entry's link member
|
||||
*
|
||||
* This initialiser is not required by the library, but a user may want an
|
||||
* initialiser to include in their own entry initialiser. See
|
||||
* ns_list_link_init() for more discussion.
|
||||
*/
|
||||
#define NS_LIST_LINK_INIT(name) \
|
||||
NS_FUNNY_INTPTR_OK \
|
||||
{ NS_LIST_POISON, NS_LIST_POISON } \
|
||||
NS_FUNNY_INTPTR_RESTORE
|
||||
|
||||
/** \hideinitializer \brief Initialise an entry's list link
|
||||
*
|
||||
* This "initialises" an unattached entry's link by filling the fields with
|
||||
* poison. This is optional, as unattached entries field pointers are not
|
||||
* meaningful, and it is not valid to call ns_list_get_next or similar on
|
||||
* an unattached entry.
|
||||
*
|
||||
* \param entry Pointer to an entry
|
||||
* \param field The name of the link member to initialise
|
||||
*/
|
||||
#define ns_list_link_init(entry, field) ns_list_link_init_(&(entry)->field)
|
||||
|
||||
/** \hideinitializer \brief Initialise a list
|
||||
*
|
||||
* Initialise a list head before use. A list head must be initialised using this
|
||||
* function or one of the NS_LIST_INIT()-type macros before use. A zero-initialised
|
||||
* list head is *not* valid.
|
||||
*
|
||||
* If used on a list containing existing entries, those entries will
|
||||
* become detached. (They are not modified, but their links are now effectively
|
||||
* undefined).
|
||||
*
|
||||
* \param list Pointer to a NS_LIST_HEAD() structure.
|
||||
*/
|
||||
#define ns_list_init(list) ns_list_init_(&(list)->slist)
|
||||
|
||||
/** \brief Initialiser for an empty list
|
||||
*
|
||||
* Usage in an enclosing initialiser:
|
||||
* ~~~
|
||||
* static my_type_including_list_t x = {
|
||||
* "Something",
|
||||
* 23,
|
||||
* NS_LIST_INIT(x),
|
||||
* };
|
||||
* ~~~
|
||||
* NS_LIST_DEFINE() or NS_LIST_NAME_INIT() may provide a shorter alternative
|
||||
* in simpler cases.
|
||||
*/
|
||||
#define NS_LIST_INIT(name) { { NULL, &(name).slist.first_entry } }
|
||||
|
||||
/** \brief Name and initialiser for an empty list
|
||||
*
|
||||
* Usage:
|
||||
* ~~~
|
||||
* list_t NS_LIST_NAME_INIT(foo);
|
||||
* ~~~
|
||||
* acts as
|
||||
* ~~~
|
||||
* list_t foo = { empty list };
|
||||
* ~~~
|
||||
* Also useful with designated initialisers:
|
||||
* ~~~
|
||||
* .NS_LIST_NAME_INIT(foo),
|
||||
* ~~~
|
||||
* acts as
|
||||
* ~~~
|
||||
* .foo = { empty list },
|
||||
* ~~~
|
||||
*/
|
||||
#define NS_LIST_NAME_INIT(name) name = NS_LIST_INIT(name)
|
||||
|
||||
/** \brief Define a list, and initialise to empty.
|
||||
*
|
||||
* Usage:
|
||||
* ~~~
|
||||
* static NS_LIST_DEFINE(my_list, entry_t, link);
|
||||
* ~~~
|
||||
* acts as
|
||||
* ~~~
|
||||
* static list_type my_list = { empty list };
|
||||
* ~~~
|
||||
*/
|
||||
#define NS_LIST_DEFINE(name, type, field) \
|
||||
NS_LIST_HEAD(type, field) NS_LIST_NAME_INIT(name)
|
||||
|
||||
/** \hideinitializer \brief Add an entry to the start of the linked list.
|
||||
*
|
||||
* ns_list_add_to_end() is *slightly* more efficient than ns_list_add_to_start().
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param entry `(entry_t * restrict)` Pointer to new entry to add.
|
||||
*/
|
||||
#define ns_list_add_to_start(list, entry) \
|
||||
ns_list_add_to_start_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \hideinitializer \brief Add an entry to the end of the linked list.
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param entry `(entry_t * restrict)` Pointer to new entry to add.
|
||||
*/
|
||||
#define ns_list_add_to_end(list, entry) \
|
||||
ns_list_add_to_end_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \hideinitializer \brief Add an entry before a specified entry.
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param before `(entry_t *)` Existing entry before which to place the new entry.
|
||||
* \param entry `(entry_t * restrict)` Pointer to new entry to add.
|
||||
*/
|
||||
#define ns_list_add_before(list, before, entry) \
|
||||
ns_list_add_before_(NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, before), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \hideinitializer \brief Add an entry after a specified entry.
|
||||
*
|
||||
* ns_list_add_before() is *slightly* more efficient than ns_list_add_after().
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param after `(entry_t *)` Existing entry after which to place the new entry.
|
||||
* \param entry `(entry_t * restrict)` Pointer to new entry to add.
|
||||
*/
|
||||
#define ns_list_add_after(list, after, entry) \
|
||||
ns_list_add_after_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, after), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \brief Check if a list is empty.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
*
|
||||
* \return `(bool)` true if the list is empty.
|
||||
*/
|
||||
#define ns_list_is_empty(list) ((bool) ((list)->slist.first_entry == NULL))
|
||||
|
||||
/** \brief Get the first entry.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
*
|
||||
* \return `(entry_t *)` Pointer to first entry.
|
||||
* \return NULL if list is empty.
|
||||
*/
|
||||
#define ns_list_get_first(list) NS_LIST_TYPECAST_(list, (list)->slist.first_entry)
|
||||
|
||||
/** \hideinitializer \brief Get the previous entry.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
* \param current `(const entry_t *)` Pointer to current entry.
|
||||
*
|
||||
* \return `(entry_t *)` Pointer to previous entry.
|
||||
* \return NULL if current entry is first.
|
||||
*/
|
||||
#define ns_list_get_previous(list, current) \
|
||||
NS_LIST_TYPECAST_(list, ns_list_get_previous_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current)))
|
||||
|
||||
/** \hideinitializer \brief Get the next entry.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
* \param current `(const entry_t *)` Pointer to current entry.
|
||||
*
|
||||
* \return `(entry_t *)` Pointer to next entry.
|
||||
* \return NULL if current entry is last.
|
||||
*/
|
||||
#define ns_list_get_next(list, current) \
|
||||
NS_LIST_TYPECAST_(list, ns_list_get_next_(NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current)))
|
||||
|
||||
/** \hideinitializer \brief Get the last entry.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
*
|
||||
* \return `(entry_t *)` Pointer to last entry.
|
||||
* \return NULL if list is empty.
|
||||
*/
|
||||
#define ns_list_get_last(list) \
|
||||
NS_LIST_TYPECAST_(list, ns_list_get_last_(&(list)->slist, NS_LIST_OFFSET_(list)))
|
||||
|
||||
/** \hideinitializer \brief Remove an entry.
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param entry `(entry_t *)` Entry on list to be removed.
|
||||
*/
|
||||
#define ns_list_remove(list, entry) \
|
||||
ns_list_remove_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \hideinitializer \brief Replace an entry.
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param current `(entry_t *)` Existing entry on list to be replaced.
|
||||
* \param replacement `(entry_t * restrict)` New entry to be the replacement.
|
||||
*/
|
||||
#define ns_list_replace(list, current, replacement) \
|
||||
ns_list_replace_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current), NS_LIST_TYPECHECK_(list, replacement))
|
||||
|
||||
/** \hideinitializer \brief Concatenate two lists.
|
||||
*
|
||||
* Attach the entries on the source list to the end of the destination
|
||||
* list, leaving the source list empty.
|
||||
*
|
||||
* \param dst `(list_t *)` Pointer to destination list.
|
||||
* \param src `(list_t *)` Pointer to source list.
|
||||
*
|
||||
*/
|
||||
#define ns_list_concatenate(dst, src) \
|
||||
(NS_PTR_MATCH_(dst, src, "concatenating different list types"), \
|
||||
ns_list_concatenate_(&(dst)->slist, &(src)->slist, NS_LIST_OFFSET_(src)))
|
||||
|
||||
/** \brief Iterate forwards over a list.
|
||||
*
|
||||
* Example:
|
||||
* ~~~
|
||||
* ns_list_foreach(const my_entry_t, cur, &my_list)
|
||||
* {
|
||||
* printf("%s\n", cur->name);
|
||||
* }
|
||||
* ~~~
|
||||
* Deletion of the current entry is not permitted as its next is checked after
|
||||
* running user code.
|
||||
*
|
||||
* The iteration pointer is declared inside the loop, using C99/C++, so it
|
||||
* is not accessible after the loop. This encourages good code style, and
|
||||
* matches the semantics of C++11's "ranged for", which only provides the
|
||||
* declaration form:
|
||||
* ~~~
|
||||
* for (const my_entry_t cur : my_list)
|
||||
* ~~~
|
||||
* If you need to see the value of the iteration pointer after a `break`,
|
||||
* you will need to assign it to a variable declared outside the loop before
|
||||
* breaking:
|
||||
* ~~~
|
||||
* my_entry_t *match = NULL;
|
||||
* ns_list_foreach(my_entry_t, cur, &my_list)
|
||||
* {
|
||||
* if (cur->id == id)
|
||||
* {
|
||||
* match = cur;
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* ~~~
|
||||
*
|
||||
* The user has to specify the entry type for the pointer definition, as type
|
||||
* extraction from the list argument isn't portable. On the other hand, this
|
||||
* also permits const qualifiers, as in the example above, and serves as
|
||||
* documentation. The entry type will be checked against the list type where the
|
||||
* compiler supports it.
|
||||
*
|
||||
* \param type Entry type `([const] entry_t)`.
|
||||
* \param e Name for iteration pointer to be defined
|
||||
* inside the loop.
|
||||
* \param list `(const list_t *)` Pointer to list - evaluated multiple times.
|
||||
*/
|
||||
#define ns_list_foreach(type, e, list) \
|
||||
for (type *e = ns_list_get_first(list); e; e = ns_list_get_next(list, e))
|
||||
|
||||
/** \brief Iterate forwards over a list, where user may delete.
|
||||
*
|
||||
* As ns_list_foreach(), but deletion of current entry is permitted as its
|
||||
* next pointer is recorded before running user code.
|
||||
*
|
||||
* Example:
|
||||
* ~~~
|
||||
* ns_list_foreach_safe(my_entry_t, cur, &my_list)
|
||||
* {
|
||||
* ns_list_remove(cur);
|
||||
* }
|
||||
* ~~~
|
||||
* \param type Entry type `(entry_t)`.
|
||||
* \param e Name for iteration pointer to be defined
|
||||
* inside the loop.
|
||||
* \param list `(list_t *)` Pointer to list - evaluated multiple times.
|
||||
*/
|
||||
#define ns_list_foreach_safe(type, e, list) \
|
||||
for (type *e = ns_list_get_first(list), *_next; \
|
||||
e && (_next = ns_list_get_next(list, e), true); e = _next)
|
||||
|
||||
/** \brief Iterate backwards over a list.
|
||||
*
|
||||
* As ns_list_foreach(), but going backwards - see its documentation.
|
||||
* Iterating forwards is *slightly* more efficient.
|
||||
*/
|
||||
#define ns_list_foreach_reverse(type, e, list) \
|
||||
for (type *e = ns_list_get_last(list); e; e = ns_list_get_previous(list, e))
|
||||
|
||||
/** \brief Iterate backwards over a list, where user may delete.
|
||||
*
|
||||
* As ns_list_foreach_safe(), but going backwards - see its documentation.
|
||||
* Iterating forwards is *slightly* more efficient.
|
||||
*/
|
||||
#define ns_list_foreach_reverse_safe(type, e, list) \
|
||||
for (type *e = ns_list_get_last(list), *_next; \
|
||||
e && (_next = ns_list_get_previous(list, e), true); e = _next)
|
||||
|
||||
/** \hideinitializer \brief Count entries on a list
|
||||
*
|
||||
* Unlike other operations, this is O(n). Note: if list might contain over
|
||||
* 65535 entries, this function **must not** be used to get the entry count.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
|
||||
* \return `(uint_fast16_t)` Number of entries that are stored in list.
|
||||
*/
|
||||
#define ns_list_count(list) ns_list_count_(&(list)->slist, NS_LIST_OFFSET_(list))
|
||||
|
||||
/** \privatesection
|
||||
* Internal functions - designed to be accessed using corresponding macros above
|
||||
*/
|
||||
NS_INLINE void ns_list_init_(ns_list_t *list);
|
||||
NS_INLINE void ns_list_link_init_(ns_list_link_t *link);
|
||||
NS_INLINE void ns_list_add_to_start_(ns_list_t *list, ns_list_offset_t link_offset, void * restrict entry);
|
||||
NS_INLINE void ns_list_add_to_end_(ns_list_t *list, ns_list_offset_t link_offset, void * restrict entry);
|
||||
NS_INLINE void ns_list_add_before_(ns_list_offset_t link_offset, void *before, void * restrict entry);
|
||||
NS_INLINE void ns_list_add_after_(ns_list_t *list, ns_list_offset_t link_offset, void *after, void * restrict entry);
|
||||
NS_INLINE void *ns_list_get_next_(ns_list_offset_t link_offset, const void *current);
|
||||
NS_INLINE void *ns_list_get_previous_(const ns_list_t *list, ns_list_offset_t link_offset, const void *current);
|
||||
NS_INLINE void *ns_list_get_last_(const ns_list_t *list, ns_list_offset_t offset);
|
||||
NS_INLINE void ns_list_remove_(ns_list_t *list, ns_list_offset_t link_offset, void *entry);
|
||||
NS_INLINE void ns_list_replace_(ns_list_t *list, ns_list_offset_t link_offset, void *current, void * restrict replacement);
|
||||
NS_INLINE void ns_list_concatenate_(ns_list_t *dst, ns_list_t *src, ns_list_offset_t offset);
|
||||
NS_INLINE uint_fast16_t ns_list_count_(const ns_list_t *list, ns_list_offset_t link_offset);
|
||||
|
||||
/* Provide definitions, either for inlining, or for ns_list.c */
|
||||
#if defined NS_ALLOW_INLINING || defined NS_LIST_FN
|
||||
#ifndef NS_LIST_FN
|
||||
#define NS_LIST_FN NS_INLINE
|
||||
#endif
|
||||
|
||||
/* Pointer to the link member in entry e */
|
||||
#define NS_LIST_LINK_(e, offset) ((ns_list_link_t *)((char *)(e) + offset))
|
||||
|
||||
/* Lvalue of the next link pointer in entry e */
|
||||
#define NS_LIST_NEXT_(e, offset) (NS_LIST_LINK_(e, offset)->next)
|
||||
|
||||
/* Lvalue of the prev link pointer in entry e */
|
||||
#define NS_LIST_PREV_(e, offset) (NS_LIST_LINK_(e, offset)->prev)
|
||||
|
||||
/* Convert a pointer to a link member back to the entry;
|
||||
* works for linkptr either being a ns_list_link_t pointer, or its next pointer,
|
||||
* as the next pointer is first in the ns_list_link_t */
|
||||
#define NS_LIST_ENTRY_(linkptr, offset) ((void *)((char *)(linkptr) - offset))
|
||||
|
||||
NS_LIST_FN void ns_list_init_(ns_list_t *list)
|
||||
{
|
||||
list->first_entry = NULL;
|
||||
list->last_nextptr = &list->first_entry;
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_link_init_(ns_list_link_t *link)
|
||||
{
|
||||
NS_FUNNY_INTPTR_OK
|
||||
link->next = NS_LIST_POISON;
|
||||
link->prev = NS_LIST_POISON;
|
||||
NS_FUNNY_INTPTR_RESTORE
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_add_to_start_(ns_list_t *list, ns_list_offset_t offset, void * restrict entry)
|
||||
{
|
||||
void *next;
|
||||
|
||||
NS_LIST_PREV_(entry, offset) = &list->first_entry;
|
||||
NS_LIST_NEXT_(entry, offset) = next = list->first_entry;
|
||||
|
||||
if (next)
|
||||
{
|
||||
NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
|
||||
list->first_entry = entry;
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_add_after_(ns_list_t *list, ns_list_offset_t offset, void *current, void * restrict entry)
|
||||
{
|
||||
void *next;
|
||||
|
||||
NS_LIST_PREV_(entry, offset) = &NS_LIST_NEXT_(current, offset);
|
||||
NS_LIST_NEXT_(entry, offset) = next = NS_LIST_NEXT_(current, offset);
|
||||
|
||||
if (next)
|
||||
{
|
||||
NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
|
||||
NS_LIST_NEXT_(current, offset) = entry;
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_add_before_(ns_list_offset_t offset, void *current, void * restrict entry)
|
||||
{
|
||||
void **prev_nextptr;
|
||||
|
||||
NS_LIST_NEXT_(entry, offset) = current;
|
||||
NS_LIST_PREV_(entry, offset) = prev_nextptr = NS_LIST_PREV_(current, offset);
|
||||
*prev_nextptr = entry;
|
||||
NS_LIST_PREV_(current, offset) = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_add_to_end_(ns_list_t *list, ns_list_offset_t offset, void * restrict entry)
|
||||
{
|
||||
void **prev_nextptr;
|
||||
|
||||
NS_LIST_NEXT_(entry, offset) = NULL;
|
||||
NS_LIST_PREV_(entry, offset) = prev_nextptr = list->last_nextptr;
|
||||
*prev_nextptr = entry;
|
||||
list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void *ns_list_get_next_(ns_list_offset_t offset, const void *current)
|
||||
{
|
||||
return NS_LIST_NEXT_(current, offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void *ns_list_get_previous_(const ns_list_t *list, ns_list_offset_t offset, const void *current)
|
||||
{
|
||||
if(current == list->first_entry)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Tricky. We don't have a direct previous pointer, but a pointer to the
|
||||
// pointer that points to us - ie &head->first_entry OR &{prev}->next.
|
||||
// This makes life easier on insertion and removal, but this is where we
|
||||
// pay the price.
|
||||
|
||||
// We have to check manually for being the first entry above, so we know it's
|
||||
// a real link's next pointer. Then next is the first field of
|
||||
// ns_list_link_t, so we can use the normal offset value.
|
||||
|
||||
return NS_LIST_ENTRY_(NS_LIST_PREV_(current, offset), offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void *ns_list_get_last_(const ns_list_t *list, ns_list_offset_t offset)
|
||||
{
|
||||
if(!list->first_entry)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// See comments in ns_list_get_previous_()
|
||||
return NS_LIST_ENTRY_(list->last_nextptr, offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_remove_(ns_list_t *list, ns_list_offset_t offset, void *removed)
|
||||
{
|
||||
void *next;
|
||||
void **prev_nextptr;
|
||||
|
||||
next = NS_LIST_NEXT_(removed, offset);
|
||||
prev_nextptr = NS_LIST_PREV_(removed, offset);
|
||||
if (next)
|
||||
{
|
||||
NS_LIST_PREV_(next, offset) = prev_nextptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->last_nextptr = prev_nextptr;
|
||||
}
|
||||
*prev_nextptr = next;
|
||||
|
||||
ns_list_link_init_(NS_LIST_LINK_(removed, offset));
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_replace_(ns_list_t *list, ns_list_offset_t offset, void *current, void * restrict replacement)
|
||||
{
|
||||
void *next;
|
||||
void **prev_nextptr;
|
||||
|
||||
NS_LIST_PREV_(replacement, offset) = prev_nextptr = NS_LIST_PREV_(current, offset);
|
||||
NS_LIST_NEXT_(replacement, offset) = next = NS_LIST_NEXT_(current, offset);
|
||||
|
||||
if (next)
|
||||
{
|
||||
NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(replacement, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
list->last_nextptr = &NS_LIST_NEXT_(replacement, offset);
|
||||
}
|
||||
*prev_nextptr = replacement;
|
||||
|
||||
ns_list_link_init_(NS_LIST_LINK_(current, offset));
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_concatenate_(ns_list_t *dst, ns_list_t *src, ns_list_offset_t offset)
|
||||
{
|
||||
ns_list_link_t *src_first;
|
||||
|
||||
src_first = src->first_entry;
|
||||
if (!src_first)
|
||||
return;
|
||||
|
||||
*dst->last_nextptr = src_first;
|
||||
NS_LIST_PREV_(src_first, offset) = dst->last_nextptr;
|
||||
dst->last_nextptr = src->last_nextptr;
|
||||
|
||||
ns_list_init_(src);
|
||||
}
|
||||
|
||||
NS_LIST_FN uint_fast16_t ns_list_count_(const ns_list_t *list, ns_list_offset_t offset)
|
||||
{
|
||||
uint_fast16_t count = 0;
|
||||
|
||||
for (void *p = list->first_entry; p; p = NS_LIST_NEXT_(p, offset))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif /* defined NS_ALLOW_INLINING || defined NS_LIST_FN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NS_LIST_H_ */
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
/*
|
||||
* ns_types.h - Basic compiler and type setup for Nanostack libraries.
|
||||
*/
|
||||
#ifndef NS_TYPES_H_
|
||||
#define NS_TYPES_H_
|
||||
|
||||
/** \file
|
||||
* \brief Basic compiler and type setup
|
||||
*
|
||||
* We currently assume C99 or later.
|
||||
*
|
||||
* C99 features being relied on:
|
||||
*
|
||||
* - <inttypes.h> and <stdbool.h>
|
||||
* - inline (with C99 semantics, not C++ as per default GCC);
|
||||
* - designated initialisers;
|
||||
* - compound literals;
|
||||
* - restrict;
|
||||
* - [static N] in array parameters;
|
||||
* - declarations in for statements;
|
||||
* - mixing declarations and statements
|
||||
*
|
||||
* Compilers should be set to C99 or later mode when building Nanomesh source.
|
||||
* For GCC this means "-std=gnu99" (C99 with usual GNU extensions).
|
||||
*
|
||||
* Also, a little extra care is required for public header files that could be
|
||||
* included from C++, especially as C++ lacks some C99 features.
|
||||
*
|
||||
* (TODO: as this is exposed to API users, do we need a predefine to distinguish
|
||||
* internal and external use, for finer control? Not yet, but maybe...)
|
||||
*/
|
||||
|
||||
/* Make sure <stdint.h> defines its macros if C++ */
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h> // includes <stdint.h>; debugf() users need PRIu32 etc
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined __GNUC__ && defined __arm__
|
||||
/* arm-none-eabi-gcc 4.8-2014q3 has a problem in its <inttypes.h>:
|
||||
* int_fast32_t is defined as int, but PRI<x>FAST32 are defined as "l<x>".
|
||||
* Try to detect this situation and override it.
|
||||
* Very hard to detect types in the preprocessor - this is best I could do.
|
||||
* Expansion works by:
|
||||
* NS_TEST_Y(INT_FAST32_MAX) -> NS_TEST_X(2147483647) -> __NS2147483647 -> 1
|
||||
* Nested macros are needed so we don't get __NSINT_FAST32_MAX.
|
||||
*/
|
||||
#define __NS2147483647 1
|
||||
#define __NS2147483647L 2
|
||||
#define NS_TEST_X(x) __NS##x
|
||||
#define NS_TEST_Y(x) NS_TEST_X(x)
|
||||
|
||||
#if NS_TEST_Y(INT_FAST32_MAX) == __NS2147483647 && \
|
||||
NS_TEST_Y(INT_LEAST32_MAX) == __NS2147483647L && \
|
||||
NS_TEST_Y(INT32_MAX) == __NS2147483647L
|
||||
|
||||
// Fast 32-bit types are int, others are long - this is the problem case in
|
||||
// arm-none-eabi-gcc.
|
||||
#undef PRIoFAST32
|
||||
#undef PRIuFAST32
|
||||
#undef PRIxFAST32
|
||||
#undef PRIXFAST32
|
||||
#undef PRIdFAST32
|
||||
#undef PRIiFAST32
|
||||
#define PRIoFAST32 "o"
|
||||
#define PRIuFAST32 "u"
|
||||
#define PRIxFAST32 "x"
|
||||
#define PRIXFAST32 "X"
|
||||
#define PRIdFAST32 "d"
|
||||
#define PRIiFAST32 "i"
|
||||
#endif
|
||||
#undef NS_TEST_X
|
||||
#undef NS_TEST_Y
|
||||
#undef __NS2147483647
|
||||
#undef __NS2147483647L
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create the optional <stdint.h> 24-bit types if they don't exist (worth trying
|
||||
* to use them, as they could exist and be more efficient than 32-bit on 8-bit
|
||||
* systems...)
|
||||
*/
|
||||
#ifndef UINT24_LEAST_MAX
|
||||
typedef uint_least32_t uint_least24_t;
|
||||
#define UINT_LEAST24_MAX UINT_LEAST32_MAX
|
||||
#define UINT24_C(x) UINT32_C(x)
|
||||
#define PRIoLEAST24 PRIoLEAST32
|
||||
#define PRIuLEAST24 PRIuLEAST32
|
||||
#define PRIxLEAST24 PRIxLEAST32
|
||||
#define PRIXLEAST24 PRIXLEAST32
|
||||
#endif
|
||||
|
||||
#ifndef INT24_LEAST_MAX
|
||||
typedef int_least32_t int_least24_t;
|
||||
#define INT24_LEAST_MIN INT_LEAST32_MIN
|
||||
#define INT24_LEAST_MAX INT_LEAST32_MAX
|
||||
#define INT24_C(x) INT32_C(x)
|
||||
#define PRIdLEAST24 PRIdLEAST32
|
||||
#define PRIiLEAST24 PRIiLEAST32
|
||||
#endif
|
||||
|
||||
#ifndef UINT24_FAST_MAX
|
||||
typedef uint_fast32_t uint_fast24_t;
|
||||
#define UINT_FAST24_MAX UINT_FAST32_MAX
|
||||
#define PRIoFAST24 PRIoFAST32
|
||||
#define PRIuFAST24 PRIuFAST32
|
||||
#define PRIxFAST24 PRIxFAST32
|
||||
#define PRIXFAST24 PRIXFAST32
|
||||
#endif
|
||||
|
||||
#ifndef INT24_FAST_MAX
|
||||
typedef int_fast32_t int_fast24_t;
|
||||
#define INT_FAST24_MIN INT_FAST32_MIN
|
||||
#define INT_FAST24_MAX INT_FAST32_MAX
|
||||
#define PRIdFAST24 PRIdFAST32
|
||||
#define PRIiFAST24 PRIiFAST32
|
||||
#endif
|
||||
|
||||
/* C11's "noreturn" macro, emulated if necessary */
|
||||
#ifndef noreturn
|
||||
#if defined __cplusplus && __cplusplus >= 201103L
|
||||
// noreturn is a C++11 keyword
|
||||
#elif __STDC_VERSION__ >= 201112L
|
||||
#include <stdnoreturn.h>
|
||||
#elif defined __GNUC__
|
||||
#define noreturn /*__attribute__((__noreturn__))*/
|
||||
#elif defined __CC_ARM
|
||||
#define noreturn __declspec(noreturn)
|
||||
#elif defined __IAR_SYSTEMS_ICC__
|
||||
#define noreturn __noreturn
|
||||
#else
|
||||
#define noreturn
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* C11's "alignas" macro, emulated for integer expressions if necessary */
|
||||
#ifndef __alignas_is_defined
|
||||
#if __STDC_VERSION__ >= 201112L || (defined __cplusplus && __cplusplus >= 201103L)
|
||||
#include <stdalign.h>
|
||||
#elif defined __GNUC__
|
||||
#define alignas(n) __attribute__((__aligned__(n)))
|
||||
#define __alignas_is_defined 1
|
||||
#elif defined __CC_ARM || defined __TASKING__
|
||||
#define alignas(n) __align(n)
|
||||
#define __alignas_is_defined 1
|
||||
#elif defined __IAR_SYSTEMS_ICC__
|
||||
/* Does this really just apply to the next variable? */
|
||||
#define alignas(n) __Alignas(data_alignment=n)
|
||||
#define __Alignas(x) _Pragma(#x)
|
||||
#define __alignas_is_defined 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Marker for functions or objects that may be unused, suppressing warnings.
|
||||
* Place after the identifier:
|
||||
* ~~~
|
||||
* static int X MAYBE_UNUSED = 3;
|
||||
* static int foo(void) MAYBE_UNUSED;
|
||||
* ~~~
|
||||
*/
|
||||
#if defined __CC_ARM || defined __GNUC__
|
||||
#define MAYBE_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* C++ (even C++11) doesn't provide restrict: define away or provide
|
||||
* alternative.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#ifdef __GNUC__
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/**
|
||||
* C++ doesn't allow "static" in function parameter types: ie
|
||||
* ~~~
|
||||
* entry_t *find_entry(const uint8_t address[static 16])
|
||||
* ~~~
|
||||
* If a header file may be included from C++, use this __static define instead.
|
||||
*
|
||||
* (Syntax introduced in C99 - `uint8_t address[16]` in a prototype was always
|
||||
* equivalent to `uint8_t *address`, but the C99 addition of static tells the
|
||||
* compiler that address is never NULL, and always points to at least 16
|
||||
* elements. This adds no new type-checking, but the information could aid
|
||||
* compiler optimisation, and it can serve as documentation).
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define __static
|
||||
#else
|
||||
#define __static static
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define NS_GCC_VERSION (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNUC_PATCHLEVEL__)
|
||||
#endif
|
||||
|
||||
/** \brief Compile-time assertion
|
||||
*
|
||||
* C11 provides _Static_assert, as does GCC even in C99 or C++ mode (and
|
||||
* as a freestanding implementation, we can't rely on <assert.h> to get
|
||||
* the static_assert macro).
|
||||
* C++11 provides static_assert as a keyword.
|
||||
*
|
||||
* The assertion acts as a declaration that can be placed at file scope, in a
|
||||
* code block (except after a label), or as a member of a struct/union. It
|
||||
* produces a compiler error if "test" evaluates to 0.
|
||||
*
|
||||
* Note that this *includes* the required semicolon when defined, else it
|
||||
* is totally empty, permitting use in structs. (If the user provided the `;`,
|
||||
* it would leave an illegal stray `;` if unavailable).
|
||||
*/
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
#define NS_STATIC_ASSERT(test, str) _Static_assert(test, str);
|
||||
#elif defined __cplusplus && __cplusplus >= 201103L
|
||||
#define NS_STATIC_ASSERT(test, str) static_assert(test, str);
|
||||
#elif defined __GNUC__ && NS_GCC_VERSION >= 40600
|
||||
//#define NS_STATIC_ASSERT(test, str) __extension__ _Static_assert(test, str);
|
||||
#define NS_STATIC_ASSERT(test, str)
|
||||
#else
|
||||
#define NS_STATIC_ASSERT(test, str)
|
||||
#endif
|
||||
|
||||
#define static_assert _Static_assert
|
||||
|
||||
/** \brief Pragma to suppress warnings about unusual pointer values.
|
||||
*
|
||||
* Useful if using "poison" values.
|
||||
*/
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#define NS_FUNNY_INTPTR_OK _Pragma("diag_suppress=Pe1053")
|
||||
#define NS_FUNNY_INTPTR_RESTORE _Pragma("diag_default=Pe1053")
|
||||
#else
|
||||
#define NS_FUNNY_INTPTR_OK
|
||||
#define NS_FUNNY_INTPTR_RESTORE
|
||||
#endif
|
||||
|
||||
/** \brief Convert pointer to member to pointer to containing structure */
|
||||
#define NS_CONTAINER_OF(ptr, type, member) \
|
||||
((type *) ((char *) (ptr) - offsetof(type, member)))
|
||||
|
||||
/*
|
||||
* Inlining could cause problems when mixing with C++; provide a mechanism to
|
||||
* disable it. This could also be turned off for other reasons (although
|
||||
* this can usually be done through a compiler flag, eg -O0 on gcc).
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
#define NS_ALLOW_INLINING
|
||||
#endif
|
||||
|
||||
/* There is inlining problem in GCC version 4.1.x and we know it works in 4.6.3 */
|
||||
#if defined __GNUC__ && NS_GCC_VERSION < 40600
|
||||
#undef NS_ALLOW_INLINING
|
||||
#endif
|
||||
|
||||
/** \brief Mark a potentially-inlineable function.
|
||||
*
|
||||
* We follow C99 semantics, which requires precisely one external definition.
|
||||
* To also allow inlining to be totally bypassed under control of
|
||||
* NS_ALLOW_INLINING, code can be structured as per the example of ns_list:
|
||||
*
|
||||
* foo.h
|
||||
* -----
|
||||
* ~~~
|
||||
* NS_INLINE int my_func(int);
|
||||
*
|
||||
* #if defined NS_ALLOW_INLINING || defined FOO_FN
|
||||
* #ifndef FOO_FN
|
||||
* #define FOO_FN NS_INLINE
|
||||
* #endif
|
||||
* FOO_FN int my_func(int a)
|
||||
* {
|
||||
* definition;
|
||||
* }
|
||||
* #endif
|
||||
* ~~~
|
||||
* foo.c
|
||||
* -----
|
||||
* ~~~
|
||||
* #define FOO_FN extern
|
||||
* #include "foo.h"
|
||||
* ~~~
|
||||
* Which generates:
|
||||
* ~~~
|
||||
* NS_ALLOW_INLINING set NS_ALLOW_INLINING unset
|
||||
* ===================== =======================
|
||||
* Include foo.h Include foo.h
|
||||
* ------------- -------------
|
||||
* inline int my_func(int); int my_func(int);
|
||||
*
|
||||
* // inline definition
|
||||
* inline int my_func(int a)
|
||||
* {
|
||||
* definition;
|
||||
* }
|
||||
*
|
||||
* Compile foo.c Compile foo.c
|
||||
* ------------- -------------
|
||||
* (from .h) inline int my_func(int); int my_func(int);
|
||||
*
|
||||
* // external definition
|
||||
* // because of no "inline" // normal external definition
|
||||
* extern int my_func(int a) extern int my_func(int a)
|
||||
* { {
|
||||
* definition; definition;
|
||||
* } }
|
||||
* ~~~
|
||||
*
|
||||
* Note that even with inline keywords, whether the compiler inlines or not is
|
||||
* up to it. For example, gcc at "-O0" will not inline at all, and will always
|
||||
* call the real functions in foo.o, just as if NS_ALLOW_INLINING was unset.
|
||||
* At "-O2", gcc could potentially inline everything, meaning that foo.o is not
|
||||
* referenced at all.
|
||||
*
|
||||
* Alternatively, you could use "static inline", which gives every caller its
|
||||
* own internal definition. This is compatible with C++ inlining (which expects
|
||||
* the linker to eliminate duplicates), but in C it's less efficient if the code
|
||||
* ends up non-inlined, and it's harder to breakpoint. I don't recommend it
|
||||
* except for the most trivial functions (which could then probably be macros).
|
||||
*/
|
||||
#ifdef NS_ALLOW_INLINING
|
||||
#define NS_INLINE inline
|
||||
#else
|
||||
#define NS_INLINE
|
||||
#endif
|
||||
|
||||
#if defined __SDCC_mcs51 || defined __ICC8051__ || defined __C51__
|
||||
|
||||
/* The 8051 environments: SDCC (historic), IAR (current), Keil (future?) */
|
||||
|
||||
#define NS_LARGE __xdata
|
||||
#define NS_LARGE_PTR __xdata
|
||||
#ifdef __ICC8051__
|
||||
#define NS_REENTRANT
|
||||
#define NS_REENTRANT_PREFIX __idata_reentrant
|
||||
#else
|
||||
#define NS_REENTRANT __reentrant
|
||||
#define NS_REENTRANT_PREFIX
|
||||
#endif
|
||||
#define NS_NEAR_FUNC __near_func
|
||||
|
||||
#else
|
||||
|
||||
/* "Normal" systems. Define it all away. */
|
||||
#define NS_LARGE
|
||||
#define NS_LARGE_PTR
|
||||
#define NS_REENTRANT
|
||||
#define NS_REENTRANT_PREFIX
|
||||
#define NS_NEAR_FUNC
|
||||
|
||||
#endif
|
||||
|
||||
/** \brief Scatter-gather descriptor
|
||||
*
|
||||
* Slightly optimised for small platforms - we assume we won't need any
|
||||
* element bigger than 64K.
|
||||
*/
|
||||
typedef struct ns_iovec
|
||||
{
|
||||
void *iov_base;
|
||||
uint_fast16_t iov_len;
|
||||
} ns_iovec_t;
|
||||
#endif /* NS_TYPES_H */
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__
|
||||
#define __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "socket_types.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef SOCKET_MAX_STACKS
|
||||
#define SOCKET_MAX_STACKS 2
|
||||
#endif
|
||||
|
||||
typedef socket_error_t (*socket_init)();
|
||||
typedef socket_error_t (*socket_create)(struct socket *socket,
|
||||
const socket_address_family_t af, const socket_proto_family_t pf,
|
||||
socket_api_handler_t const handler);
|
||||
typedef socket_error_t (*socket_destroy)(struct socket *socket);
|
||||
typedef socket_error_t (*socket_close)(struct socket *socket);
|
||||
typedef socket_api_handler_t (*socket_periodic_task)(const struct socket * socket);
|
||||
typedef uint32_t (*socket_periodic_interval)(const struct socket * socket);
|
||||
typedef socket_error_t (*socket_resolve)(struct socket *socket, const char *address);
|
||||
typedef socket_error_t (*socket_connect)(struct socket *sock, const struct socket_addr *address, const uint16_t port);
|
||||
typedef socket_error_t (*socket_bind)(struct socket *socket, const struct socket_addr *address, const uint16_t port);
|
||||
typedef socket_error_t (*socket_str2addr)(const struct socket *socket, struct socket_addr *addr, const char *address);
|
||||
typedef socket_error_t (*socket_start_listen)(struct socket *socket, const uint32_t backlog);
|
||||
typedef socket_error_t (*socket_stop_listen)(struct socket *socket);
|
||||
typedef socket_error_t (*socket_accept)(struct socket *sock, socket_api_handler_t handler);
|
||||
typedef socket_error_t (*socket_reject)(struct socket *sock);
|
||||
typedef socket_error_t (*socket_send)(struct socket *socket, const void * buf, const size_t len);
|
||||
typedef socket_error_t (*socket_send_to)(struct socket *socket, const void * buf, const size_t len, const struct socket_addr *addr, const uint16_t port);
|
||||
typedef socket_error_t (*socket_recv)(struct socket *socket, void * buf, size_t *len);
|
||||
typedef socket_error_t (*socket_recv_from)(struct socket *socket, void * buf, size_t *len, struct socket_addr *addr, uint16_t *port);
|
||||
|
||||
typedef socket_error_t (*socket_get_local_addr)(const struct socket *socket, struct socket_addr *addr);
|
||||
typedef socket_error_t (*socket_get_remote_addr)(const struct socket *socket, struct socket_addr *addr);
|
||||
typedef socket_error_t (*socket_get_local_port)(const struct socket *socket, uint16_t *port);
|
||||
typedef socket_error_t (*socket_get_remote_port)(const struct socket *socket, uint16_t *port);
|
||||
|
||||
typedef uint8_t (*socket_is_connected)(const struct socket *socket);
|
||||
typedef uint8_t (*socket_is_bound)(const struct socket *socket);
|
||||
|
||||
struct socket_api {
|
||||
socket_stack_t stack;
|
||||
uint32_t version;
|
||||
socket_init init;
|
||||
socket_create create;
|
||||
socket_destroy destroy;
|
||||
socket_close close;
|
||||
socket_periodic_task periodic_task;
|
||||
socket_periodic_interval periodic_interval;
|
||||
socket_resolve resolve;
|
||||
socket_connect connect;
|
||||
socket_str2addr str2addr;
|
||||
socket_bind bind;
|
||||
socket_start_listen start_listen;
|
||||
socket_stop_listen stop_listen;
|
||||
socket_accept accept;
|
||||
socket_reject reject;
|
||||
socket_send send;
|
||||
socket_send_to send_to;
|
||||
socket_recv recv;
|
||||
socket_recv_from recv_from;
|
||||
socket_is_connected is_connected;
|
||||
socket_is_bound is_bound;
|
||||
socket_get_local_addr get_local_addr;
|
||||
socket_get_remote_addr get_remote_addr;
|
||||
socket_get_local_port get_local_port;
|
||||
socket_get_remote_port get_remote_port;
|
||||
};
|
||||
#define SOCKET_API_FIRST_PTR init
|
||||
#define SOCKET_API_LAST_PTR get_remote_port
|
||||
|
||||
socket_error_t socket_register_stack(const struct socket_api * api);
|
||||
const char * socket_strerror(const socket_error_t err);
|
||||
const struct socket_api * socket_get_api(const socket_stack_t stack);
|
||||
|
||||
static inline int socket_addr_is_ipv4(const struct socket_addr *addr)
|
||||
{
|
||||
if ((addr->ipv6be[0] == 0) &&
|
||||
(addr->ipv6be[1] == 0) &&
|
||||
(addr->ipv6be[2] == 0)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static inline int socket_addr_is_any(const struct socket_addr *addr)
|
||||
{
|
||||
if ((addr->ipv6be[0] == 0) &&
|
||||
(addr->ipv6be[1] == 0) &&
|
||||
(addr->ipv6be[2] == 0) &&
|
||||
(addr->ipv6be[3] == 0)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static inline void socket_addr_set_ipv4_addr(struct socket_addr *addr, uint32_t ipv4addr)
|
||||
{
|
||||
addr->ipv6be[0] = 0;
|
||||
addr->ipv6be[1] = 0;
|
||||
addr->ipv6be[2] = 0;
|
||||
addr->ipv6be[3] = ipv4addr;
|
||||
}
|
||||
static inline uint32_t socket_addr_get_ipv4_addr(const struct socket_addr *addr)
|
||||
{
|
||||
if (!socket_addr_is_ipv4(addr)) {
|
||||
return 0;
|
||||
}
|
||||
return addr->ipv6be[3];
|
||||
}
|
||||
static inline const uint32_t * socket_addr_get_ipv4_addrp(const struct socket_addr *addr)
|
||||
{
|
||||
if (!socket_addr_is_ipv4(addr)) {
|
||||
return NULL;
|
||||
}
|
||||
return &addr->ipv6be[3];
|
||||
}
|
||||
static inline void socket_addr_set_any(struct socket_addr *addr)
|
||||
{
|
||||
addr->ipv6be[0] = 0;
|
||||
addr->ipv6be[1] = 0;
|
||||
addr->ipv6be[2] = 0;
|
||||
addr->ipv6be[3] = 0;
|
||||
}
|
||||
|
||||
static inline void socket_addr_copy(struct socket_addr *dest, const struct socket_addr *src)
|
||||
{
|
||||
(dest)->ipv6be[0] = (src)->ipv6be[0];
|
||||
(dest)->ipv6be[1] = (src)->ipv6be[1];
|
||||
(dest)->ipv6be[2] = (src)->ipv6be[2];
|
||||
(dest)->ipv6be[3] = (src)->ipv6be[3];
|
||||
}
|
||||
static inline int socket_addr_cmp(const struct socket_addr *a, const struct socket_addr *b)
|
||||
{
|
||||
return
|
||||
a->ipv6be[0] != b->ipv6be[0] ||
|
||||
a->ipv6be[1] != b->ipv6be[1] ||
|
||||
a->ipv6be[2] != b->ipv6be[2] ||
|
||||
a->ipv6be[3] != b->ipv6be[3];
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__ */
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__
|
||||
#define __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MBED_NET_LWIP
|
||||
#define MBED_NET_LWIP 1
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SOCKET_ERROR_NONE = 0,
|
||||
SOCKET_ERROR_UNKNOWN,
|
||||
SOCKET_ERROR_UNIMPLEMENTED,
|
||||
SOCKET_ERROR_BUSY,
|
||||
SOCKET_ERROR_NULL_PTR,
|
||||
SOCKET_ERROR_BAD_FAMILY,
|
||||
SOCKET_ERROR_TIMEOUT,
|
||||
SOCKET_ERROR_BAD_ALLOC,
|
||||
SOCKET_ERROR_NO_CONNECTION,
|
||||
SOCKET_ERROR_SIZE,
|
||||
SOCKET_ERROR_STACK_EXISTS,
|
||||
SOCKET_ERROR_STACKS,
|
||||
SOCKET_ERROR_BAD_STACK,
|
||||
SOCKET_ERROR_BAD_ADDRESS,
|
||||
SOCKET_ERROR_DNS_FAILED,
|
||||
SOCKET_ERROR_WOULD_BLOCK,
|
||||
SOCKET_ERROR_CLOSED,
|
||||
SOCKET_ERROR_VALUE,
|
||||
SOCKET_ERROR_ADDRESS_IN_USE,
|
||||
SOCKET_ERROR_ALREADY_CONNECTED,
|
||||
SOCKET_ERROR_ABORT,
|
||||
SOCKET_ERROR_RESET,
|
||||
SOCKET_ERROR_BAD_ARGUMENT,
|
||||
SOCKET_ERROR_INTERFACE_ERROR,
|
||||
SOCKET_ERROR_API_VERSION,
|
||||
SOCKET_ERROR_NOT_BOUND,
|
||||
|
||||
} socket_error_t;
|
||||
|
||||
typedef enum {
|
||||
SOCKET_ALLOC_HEAP = 0,
|
||||
SOCKET_ALLOC_POOL_BEST,
|
||||
} socket_alloc_pool_t;
|
||||
|
||||
typedef enum {
|
||||
SOCKET_AF_UNINIT,
|
||||
SOCKET_AF_INET4,
|
||||
SOCKET_AF_INET6,
|
||||
SOCKET_AF_MAX,
|
||||
} socket_address_family_t;
|
||||
|
||||
typedef enum {
|
||||
SOCKET_PROTO_UNINIT = 0,
|
||||
SOCKET_DGRAM,
|
||||
SOCKET_STREAM,
|
||||
SOCKET_PROTO_MAX,
|
||||
} socket_proto_family_t;
|
||||
|
||||
typedef enum {
|
||||
SOCKET_EVENT_NONE = 0,
|
||||
SOCKET_EVENT_ERROR,
|
||||
SOCKET_EVENT_RX_DONE,
|
||||
SOCKET_EVENT_TX_DONE,
|
||||
SOCKET_EVENT_RX_ERROR,
|
||||
SOCKET_EVENT_TX_ERROR,
|
||||
SOCKET_EVENT_CONNECT,
|
||||
SOCKET_EVENT_DISCONNECT,
|
||||
SOCKET_EVENT_DNS,
|
||||
SOCKET_EVENT_ACCEPT,
|
||||
} event_flag_t;
|
||||
|
||||
typedef enum {
|
||||
SOCKET_STATUS_IDLE = 0,
|
||||
SOCKET_STATUS_RX_BUSY = 1 << 0,
|
||||
SOCKET_STATUS_TX_BUSY = 1 << 1,
|
||||
SOCKET_STATUS_CONNECTED = 1 << 2,
|
||||
SOCKET_STATUS_BOUND = 1 << 3,
|
||||
} socket_status_t;
|
||||
|
||||
typedef enum {
|
||||
SOCKET_STACK_UNINIT = 0,
|
||||
SOCKET_STACK_LWIP_IPV4,
|
||||
SOCKET_STACK_LWIP_IPV6,
|
||||
SOCKET_STACK_RESERVED,
|
||||
SOCKET_STACK_NANOSTACK_IPV6,
|
||||
SOCKET_STACK_PICOTCP,
|
||||
SOCKET_STACK_MAX,
|
||||
} socket_stack_t;
|
||||
|
||||
typedef enum {
|
||||
SOCKET_BUFFER_UNINITIALISED = 0,
|
||||
SOCKET_BUFFER_RAW,
|
||||
SOCKET_BUFFER_LWIP_PBUF,
|
||||
SOCKET_BUFFER_NANOSTACK_PBUF,
|
||||
} socket_buffer_type_t;
|
||||
|
||||
struct socket_addr {
|
||||
uint32_t ipv6be[4];
|
||||
};
|
||||
|
||||
struct socket_buffer {
|
||||
socket_buffer_type_t type;
|
||||
const struct socket_buf_api *api;
|
||||
void *impl;
|
||||
};
|
||||
|
||||
struct socket_rawbuf {
|
||||
void * buf;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
typedef void (*socket_api_handler_t)(void);
|
||||
typedef struct {
|
||||
void * (*alloc)(void *,const size_t);
|
||||
void (*dealloc)(void *, void *);
|
||||
void *context;
|
||||
} socket_allocator_t;
|
||||
|
||||
struct socket_tx_info {
|
||||
uint16_t sentbytes;
|
||||
};
|
||||
|
||||
struct socket_dns_info {
|
||||
struct socket_addr addr; // A stack-specific socket address struct
|
||||
const char *domain;
|
||||
};
|
||||
|
||||
struct socket_accept_info {
|
||||
void * newimpl;
|
||||
uint8_t reject;
|
||||
};
|
||||
|
||||
struct socket_event {
|
||||
event_flag_t event;
|
||||
struct socket *sock;
|
||||
union {
|
||||
struct socket_tx_info t;
|
||||
socket_error_t e;
|
||||
struct socket_dns_info d;
|
||||
struct socket_accept_info a;
|
||||
} i;
|
||||
};
|
||||
typedef struct socket_event socket_event_t;
|
||||
|
||||
struct socket {
|
||||
socket_api_handler_t handler;
|
||||
socket_event_t *event; // TODO: (CThunk upgrade/Alpha3)
|
||||
const struct socket_api *api;
|
||||
void *impl;
|
||||
socket_status_t status;
|
||||
uint8_t family;
|
||||
socket_stack_t stack;
|
||||
void *rxBufChain; // TODO: Only required in some stacks, which do not support BSD-style buffering
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__ */
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_SOCKET_H__
|
||||
#define __MBED_NET_SOCKETS_SOCKET_H__
|
||||
|
||||
/* Include all versions of the API */
|
||||
#include "v0/Socket.h"
|
||||
|
||||
/* Set the current namespace */
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace current {
|
||||
using namespace mbed::Sockets::v0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __MBED_NET_SOCKETS_SOCKET_H__
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_SOCKETADDR_H__
|
||||
#define __MBED_NET_SOCKETS_SOCKETADDR_H__
|
||||
|
||||
/* Include all versions of the API */
|
||||
#include "v0/SocketAddr.h"
|
||||
|
||||
/* Set the current namespace */
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace current {
|
||||
using namespace mbed::Sockets::v0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __MBED_NET_SOCKETS_SOCKETADDR_H__
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_UDPSOCKET_H__
|
||||
#define __MBED_NET_SOCKETS_UDPSOCKET_H__
|
||||
|
||||
/* Include all versions of the API */
|
||||
#include "v0/UDPSocket.h"
|
||||
|
||||
/* Set the current namespace */
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace current {
|
||||
using namespace mbed::Sockets::v0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __MBED_NET_SOCKETS_UDPSOCKET_H__
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_V0_SOCKET_H__
|
||||
#define __MBED_NET_SOCKETS_V0_SOCKET_H__
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "mbed.h"
|
||||
#include "FunctionPointer.h"
|
||||
#include "CThunk.h"
|
||||
#include "sal/socket_types.h"
|
||||
#include "SocketAddr.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace v0 {
|
||||
|
||||
/**
|
||||
* \brief Socket implements most of the interfaces required for sockets.
|
||||
* Socket is a pure virtual class; it should never be instantiated directly, but it provides
|
||||
* common functionality for derived classes.
|
||||
*/
|
||||
class Socket {
|
||||
public:
|
||||
typedef FunctionPointer3<void, Socket *, struct socket_addr, const char *> DNSHandler_t;
|
||||
typedef FunctionPointer2<void, Socket *, socket_error_t> ErrorHandler_t;
|
||||
typedef FunctionPointer1<void, Socket *> ReadableHandler_t;
|
||||
typedef FunctionPointer2<void, Socket *, uint16_t> SentHandler_t;
|
||||
protected:
|
||||
/**
|
||||
* Socket constructor
|
||||
* Initializes the Socket object. Initializes the underlying struct socket. Does not instantiate
|
||||
* an underlying network stack socket.
|
||||
* Since it is somewhat awkward to provide the network stack, a future change will provide
|
||||
* a way to pass the network interface to the socket constructor, which will extract the stack from
|
||||
* the interface.
|
||||
* @param[in] stack The network stack to use for this socket.
|
||||
*/
|
||||
Socket(const socket_stack_t stack);
|
||||
/**
|
||||
* Socket destructor
|
||||
* Frees the underlying socket implementation.
|
||||
*/
|
||||
virtual ~Socket();
|
||||
public:
|
||||
/**
|
||||
* Start the process of resolving a domain name.
|
||||
* If the input is a text IP address, an event is queued immediately; otherwise, onDNS is
|
||||
* queued as soon as DNS is resolved.
|
||||
* The socket must have been opened before resolve is called
|
||||
* @param[in] address The domain name to resolve
|
||||
* @param[in] onDNS The handler to call when the name is resolved
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t resolve(const char* address, const DNSHandler_t &onDNS);
|
||||
/**
|
||||
* Open the socket.
|
||||
* Instantiates and initializes the underlying socket. Receive is started immediately after
|
||||
* the socket is opened.
|
||||
* @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported
|
||||
* @param[in] pf Protocol family (SOCKET_DGRAM or SOCKET_STREAM)
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t open(const socket_address_family_t af, const socket_proto_family_t pf);
|
||||
/**
|
||||
* Binds the socket's local address and IP.
|
||||
* 0.0.0.0 is accepted as a local address if only the port is meant to be bound.
|
||||
* The behaviour of bind("0.0.0.0",...) is undefined where two or more stacks are in use.
|
||||
*
|
||||
* @param[in] address The string representation of the address to bind
|
||||
* @param[in] port The local port to bind
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t bind(const char *address, const uint16_t port);
|
||||
/**
|
||||
* bind(const SocketAddr *, const uint16_t) is the same as bind(const char *, const uint16_t),
|
||||
* except that the address passed in is a SocketAddr.
|
||||
* @param[in] address The address to bind
|
||||
* @param[in] port The local port to bind
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t bind(const SocketAddr *address, const uint16_t port);
|
||||
/**
|
||||
* Set the error handler.
|
||||
* Errors are ignored if onError is not set.
|
||||
* @param[in] onError
|
||||
*/
|
||||
virtual void setOnError(const ErrorHandler_t &onError);
|
||||
/**
|
||||
* Set the received data handler
|
||||
* Received data is queued until it is read using recv or recv_from.
|
||||
* @param[in] onReadable the handler to use for receive events
|
||||
*/
|
||||
virtual void setOnReadable(const ReadableHandler_t &onReadable);
|
||||
/**
|
||||
* Receive a message
|
||||
* @param[out] buf The buffer to fill
|
||||
* @param[in,out] len A pointer to the size of the receive buffer. Sets the maximum number of bytes
|
||||
* to read but is updated with the actual number of bytes copied on success. len is not changed on
|
||||
* failure
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t recv(void * buf, size_t *len);
|
||||
/**
|
||||
* Receive a message with the sender address and port
|
||||
* This API is not valid for SOCK_STREAM
|
||||
* @param[out] buf The buffer to fill
|
||||
* @param[in,out] len A pointer to the size of the receive buffer. Sets the maximum number of bytes
|
||||
* to read but is updated with the actual number of bytes copied on success. len is not changed on
|
||||
* failure
|
||||
* @param[out] remote_addr Pointer to an address structure to fill with the sender address
|
||||
* @param[out] remote_port Pointer to a uint16_t to fill with the sender port
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t recv_from(void * buf, size_t *len, SocketAddr *remote_addr, uint16_t *remote_port);
|
||||
/**
|
||||
* Set the onSent handler.
|
||||
* The exact moment this handler is called varies from implementation to implementation.
|
||||
* On LwIP, onSent is called when the remote host ACK's data in TCP sockets, or when the message enters
|
||||
* the network stack in UDP sockets.
|
||||
* @param[in] onSent The handler to call when a send completes
|
||||
*/
|
||||
virtual void setOnSent(const SentHandler_t &onSent);
|
||||
/**
|
||||
* Send a message
|
||||
* Sends a message over an open connection. This call is valid for UDP sockets, provided that connect()
|
||||
* has been called.
|
||||
* @param[in] buf The payload to send
|
||||
* @param[in] len The size of the payload
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t send(const void * buf, const size_t len);
|
||||
/**
|
||||
* Send a message to a specific address and port
|
||||
* This API is not valid for SOCK_STREAM
|
||||
* @param[in] buf The payload to send
|
||||
* @param[in] len The size of the payload
|
||||
* @param[in] address The address to send to
|
||||
* @param[in] port The remote port to send to
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t send_to(const void * buf, const size_t len, const SocketAddr *remote_addr, uint16_t remote_port);
|
||||
/**
|
||||
* Shuts down a socket.
|
||||
* Sending and receiving are no longer possible after close() is called.
|
||||
* The socket is not deallocated on close. A socket must not be reopened, it should be
|
||||
* destroyed (either with delete, or by going out of scope) after calling close.
|
||||
* Calling open on a closed socket can result in a memory leak.
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t close();
|
||||
/**
|
||||
* Error checking utility
|
||||
* Generates an event on error, does nothing on SOCKET_ERROR_NONE
|
||||
* @param[in] err the error code to check
|
||||
* @return false if err is SOCKET_ERROR_NONE, true otherwise
|
||||
*/
|
||||
virtual bool error_check(socket_error_t err);
|
||||
|
||||
/**
|
||||
* Checks the socket status to determine whether it is still connected.
|
||||
* @return true if the socket is connected, false if it is not
|
||||
*/
|
||||
virtual bool isConnected() const;
|
||||
|
||||
/**
|
||||
* Get the local address of the socket if bound.
|
||||
* There are several failing conditions for this method:
|
||||
* 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR
|
||||
* 2. If the socket has not been bound, returns SOCKET_ERROR_NOT_BOUND
|
||||
* 3. If addr is NULL, returns SOCKET_ERROR_NULL_PTR
|
||||
*
|
||||
* Otherwise, populates the SocketAddr object with the local address
|
||||
*
|
||||
* @param[out] addr a pointer to a SocketAddr object
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure (see description)
|
||||
*/
|
||||
virtual socket_error_t getLocalAddr(SocketAddr *addr) const;
|
||||
|
||||
/**
|
||||
* Get the local port of the socket if bound.
|
||||
* There are several failing conditions for this method:
|
||||
* 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR
|
||||
* 2. If the socket has not been bound, returns SOCKET_ERROR_NOT_BOUND
|
||||
* 3. If port is NULL, returns SOCKET_ERROR_NULL_PTR
|
||||
*
|
||||
* Otherwise, populates the uint16_t object with the local port
|
||||
*
|
||||
* @param[out] port a pointer to a uint16_t
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure (see description)
|
||||
*/
|
||||
virtual socket_error_t getLocalPort(uint16_t *port) const;
|
||||
|
||||
/**
|
||||
* Get the remote address of the socket if connected.
|
||||
* There are several failing conditions for this method:
|
||||
* 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR
|
||||
* 2. If the socket has not been connected, returns SOCKET_ERROR_NO_CONNECTION
|
||||
* 3. If addr is NULL, returns SOCKET_ERROR_NULL_PTR
|
||||
*
|
||||
* Otherwise, populates the SocketAddr object with the remote address
|
||||
*
|
||||
* @param[out] addr a pointer to a SocketAddr object
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure (see description)
|
||||
*/
|
||||
virtual socket_error_t getRemoteAddr(SocketAddr *addr) const;
|
||||
/**
|
||||
* Get the remote port of the socket if connected.
|
||||
* There are several failing conditions for this method:
|
||||
* 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR
|
||||
* 2. If the socket has not been connected, returns SOCKET_ERROR_NO_CONNECTION
|
||||
* 3. If port is NULL, returns SOCKET_ERROR_NULL_PTR
|
||||
*
|
||||
* Otherwise, populates the uint16_t object with the remote port
|
||||
*
|
||||
* @param[out] port a pointer to a uint16_t
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure (see description)
|
||||
*/
|
||||
virtual socket_error_t getRemotePort(uint16_t *port) const;
|
||||
|
||||
#if 0 // not implemented yet
|
||||
static long ntohl(long);
|
||||
static short ntohs(short);
|
||||
static long long ntohll(long long);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The internal event handler
|
||||
* @param[in] ev The event to handle
|
||||
*/
|
||||
virtual void _eventHandler(struct socket_event *ev);
|
||||
|
||||
protected:
|
||||
DNSHandler_t _onDNS;
|
||||
ErrorHandler_t _onError;
|
||||
ReadableHandler_t _onReadable;
|
||||
SentHandler_t _onSent;
|
||||
|
||||
CThunk<Socket> _irq;
|
||||
struct socket _socket;
|
||||
private:
|
||||
socket_event_t *_event;
|
||||
/**
|
||||
* Internal event handler.
|
||||
* @param[in] arg
|
||||
*/
|
||||
void _nvEventHandler(void * arg);
|
||||
};
|
||||
} // namespace v0
|
||||
} // namespace Sockets
|
||||
} // namespace mbed
|
||||
#endif // __MBED_NET_SOCKETS_V0_SOCKET_H__
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_V0_SOCKETADDR_H__
|
||||
#define __MBED_NET_SOCKETS_V0_SOCKETADDR_H__
|
||||
|
||||
#include "sal/socket_types.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace v0 {
|
||||
|
||||
class SocketAddr {
|
||||
public:
|
||||
struct socket_addr * getAddr() {return &_addr;}
|
||||
const struct socket_addr * getAddr() const {return &_addr;}
|
||||
void setAddr(const struct socket_addr *addr);
|
||||
void setAddr(const SocketAddr *addr);
|
||||
size_t getAddrSize() const {return sizeof(_addr.ipv6be);}
|
||||
bool is_v4();
|
||||
|
||||
int fmtIPv4(char *buf, size_t size);
|
||||
int fmtIPv6(char *buf, size_t size);
|
||||
protected:
|
||||
struct socket_addr _addr;
|
||||
};
|
||||
} // namespace v0
|
||||
} // namespace Sockets
|
||||
} // namespace mbed
|
||||
#endif // __MBED_NET_SOCKETS_V0_SOCKETADDR_H__
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_V0_TCP_ASYNCH__
|
||||
#define __MBED_NET_SOCKETS_V0_TCP_ASYNCH__
|
||||
|
||||
#include "Socket.h"
|
||||
#include "sal/socket_api.h"
|
||||
|
||||
#include "Ticker.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace v0 {
|
||||
class TCPAsynch: public Socket {
|
||||
protected:
|
||||
TCPAsynch(const socket_stack_t stack);
|
||||
~TCPAsynch();
|
||||
|
||||
public:
|
||||
virtual socket_error_t open(const socket_address_family_t af);
|
||||
protected:
|
||||
static Ticker _ticker;
|
||||
static FunctionPointer0<void> _tick_handler;
|
||||
// uintptr_t is used to guarantee that there will always be a large enough
|
||||
// counter to avoid overflows. Memory allocation will always fail before
|
||||
// counter overflow if the counter is the same size as the pointer type and
|
||||
// sizeof(TCPAsynch) > 0
|
||||
static uintptr_t _TCPSockets;
|
||||
};
|
||||
} // namespace v0
|
||||
} // namespace Sockets
|
||||
} // namespace mbed
|
||||
#endif // __MBED_NET_SOCKETS_V0_TCP_ASYNCH__
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_V0_TCPLISTENER_H__
|
||||
#define __MBED_NET_SOCKETS_V0_TCPLISTENER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "mbed/FunctionPointer.h"
|
||||
#include "TCPAsynch.h"
|
||||
#include "TCPStream.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace v0 {
|
||||
/** \brief TCPListener: a TCP server socket
|
||||
* The TCPListener listens for incoming connections. Prior to listening, the
|
||||
* TCPListener must be bound to a port and, optionally, an address.
|
||||
*/
|
||||
class TCPListener: public TCPAsynch {
|
||||
public:
|
||||
typedef FunctionPointer2<void, TCPListener *, void *> IncomingHandler_t;
|
||||
/**
|
||||
* The TCP Listener constructor.
|
||||
* @param[in] stack the network stack to use
|
||||
*/
|
||||
TCPListener(const socket_stack_t stack);
|
||||
|
||||
/**
|
||||
* The TCP Listener destructor
|
||||
* This performs teardown of the listener
|
||||
*/
|
||||
~TCPListener();
|
||||
|
||||
/**
|
||||
* Begin listening for incoming connections.
|
||||
* The supplied listenHandler will be called whenever an incoming connection arrives
|
||||
* To reject a connection, the event handler needs to set the reject flag in the event.
|
||||
* @param[in] listenHandler The event handler to call when an incoming connection arrives
|
||||
* @param[in] backlog The number of connection requests to keep in the backlog
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
socket_error_t start_listening(IncomingHandler_t listenHandler, uint32_t backlog = 0);
|
||||
/**
|
||||
* Stop listening for incoming connections
|
||||
* After this call, the server will reject incoming connections until start_listening is called again
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
socket_error_t stop_listening();
|
||||
|
||||
/**
|
||||
* accept is a utility function for constructing a new TCPStream from an incoming connection
|
||||
* The event passed to the listenHandler contains a pointer to a low level implementation of an
|
||||
* already connected socket. This function
|
||||
* @param new_impl
|
||||
* @return
|
||||
*/
|
||||
virtual TCPStream * accept(void *new_impl);
|
||||
virtual void reject(void *new_impl);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Internal event handler
|
||||
* @param[in] ev the event to handle
|
||||
*/
|
||||
void _eventHandler(struct socket_event *ev);
|
||||
|
||||
IncomingHandler_t _onIncoming;
|
||||
};
|
||||
} // namespace v0
|
||||
} // namespace Sockets
|
||||
} // namespace mbed
|
||||
#endif // __MBED_NET_SOCKETS_V0_TCPLISTENER_H__
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_V0_TCPSTREAM_H__
|
||||
#define __MBED_NET_SOCKETS_V0_TCPSTREAM_H__
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "Ticker.h"
|
||||
#include "TCPAsynch.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace v0 {
|
||||
|
||||
class TCPStream: public TCPAsynch {
|
||||
public:
|
||||
typedef FunctionPointer1<void, TCPStream *> ConnectHandler_t;
|
||||
typedef FunctionPointer1<void, TCPStream *> DisconnectHandler_t;
|
||||
/**
|
||||
* TCP socket constructor.
|
||||
* Does not allocate an underlying TCP Socket instance.
|
||||
* @param[in] stack The network stack to use for this socket.
|
||||
*/
|
||||
TCPStream(const socket_stack_t stack);
|
||||
/**
|
||||
* TCP socket constructor.
|
||||
* Does not allocate an underlying TCP Socket instance. This version is for use with
|
||||
* TCPListener::accept(). The struct socket instance passed into this constructor should
|
||||
* be a fully initialized socket, with an initialized impl field. TCPStream will copy
|
||||
* the stack, API, protocol family, and impl pointer from sock.
|
||||
* @param[in] sock The TCP socket instance to use for this TCP socket.
|
||||
*/
|
||||
TCPStream(const struct socket * sock);
|
||||
/**
|
||||
* TCP socket destructor
|
||||
*/
|
||||
~TCPStream();
|
||||
/**
|
||||
* Connect to a remote host.
|
||||
* Initates the TCP Connection process. onConnect is called when the connection
|
||||
* is acknowledged.
|
||||
* @param[in] address The remote host to connect to
|
||||
* @param[in] port The remote port to connect to
|
||||
* @param[in] onConnect
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
virtual socket_error_t connect(const SocketAddr &address, const uint16_t port,
|
||||
const ConnectHandler_t &onConnect);
|
||||
/**
|
||||
* Set a disconnect handler
|
||||
* This handler only needs to be configured once onConnect has been called
|
||||
* @param[in] h the handler to call when a connection is disconnected
|
||||
*/
|
||||
virtual void setOnDisconnect(const DisconnectHandler_t &h) { _onDisconnect = h; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Internal event handler
|
||||
* @param[in] ev the event to handle
|
||||
*/
|
||||
void _eventHandler(struct socket_event *ev);
|
||||
|
||||
protected:
|
||||
ConnectHandler_t _onConnect;
|
||||
DisconnectHandler_t _onDisconnect;
|
||||
};
|
||||
} // namespace v0
|
||||
} // namespace Sockets
|
||||
} // namespace mbed
|
||||
#endif // __MBED_NET_SOCKETS_V0_TCPSTREAM_H__
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 __MBED_NET_SOCKETS_V0_UDPSOCKET_H__
|
||||
#define __MBED_NET_SOCKETS_V0_UDPSOCKET_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "Socket.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace Sockets {
|
||||
namespace v0 {
|
||||
|
||||
/* UDP socket class */
|
||||
class UDPSocket: public Socket {
|
||||
public:
|
||||
/**
|
||||
* UDP socket constructor.
|
||||
* Does not allocate an underlying UDP Socket instance.
|
||||
* @param[in] stack The network stack to use for this socket.
|
||||
*/
|
||||
UDPSocket(socket_stack_t stack);
|
||||
/**
|
||||
* UDP Socket destructor
|
||||
*/
|
||||
~UDPSocket();
|
||||
/**
|
||||
* Open a UDP socket
|
||||
* Instantiates and initializes the underlying socket. Receive is started immediately after
|
||||
* the socket is opened.
|
||||
* @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
socket_error_t inline open(const socket_address_family_t af)
|
||||
{
|
||||
return Socket::open(af,SOCKET_DGRAM);
|
||||
}
|
||||
/**
|
||||
* Connect to a remote host.
|
||||
* This is an internal configuration API only. No network traffic is generated.
|
||||
* @param[in] address The remote host to connect to
|
||||
* @param[in] port The remote port to connect to
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
socket_error_t connect(const SocketAddr *address, const uint16_t port);
|
||||
};
|
||||
} // namespace v0
|
||||
} // namespace Sockets
|
||||
} // namespace mbed
|
||||
#endif // __MBED_NET_SOCKETS_V0_UDPSOCKET_H__
|
|
@ -0,0 +1,27 @@
|
|||
if(TARGET_LIKE_LINUX)
|
||||
include("../includes.txt")
|
||||
add_executable(m2mconnectionsecurity_mbedtls
|
||||
"../../../../source/m2mconnectionsecurity.cpp"
|
||||
"main.cpp"
|
||||
"m2mconnectionsecurity_mbedtlstest.cpp"
|
||||
"test_m2mconnectionsecurity_mbedtls.cpp"
|
||||
"../stub/m2msecurity_stub.cpp"
|
||||
"../stub/m2mstring_stub.cpp"
|
||||
"../stub/m2mobject_stub.cpp"
|
||||
"../stub/m2mbase_stub.cpp"
|
||||
"../stub/m2mtimer_stub.cpp"
|
||||
"../stub/mbedtls_stub.cpp"
|
||||
"../stub/m2mconnectionhandler_stub.cpp"
|
||||
"../stub/m2mconnectionsecuritypimpl_stub.cpp"
|
||||
)
|
||||
target_link_libraries(m2mconnectionsecurity_mbedtls
|
||||
CppUTest
|
||||
CppUTestExt
|
||||
)
|
||||
set_target_properties(m2mconnectionsecurity_mbedtls
|
||||
PROPERTIES COMPILE_FLAGS "${UTEST_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${UTEST_LINK_FLAGS}")
|
||||
set(binary "m2mconnectionsecurity_mbedtls -ojunit")
|
||||
add_test(m2mconnectionsecurity_mbedtls ${binary})
|
||||
|
||||
endif()
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
//CppUTest includes should be after your and system includes
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "test_m2mconnectionsecurity_mbedtls.h"
|
||||
|
||||
|
||||
TEST_GROUP(M2MConnectionSecurity_mbedtls)
|
||||
{
|
||||
Test_M2MConnectionSecurity* inst;
|
||||
|
||||
void setup()
|
||||
{
|
||||
inst = new Test_M2MConnectionSecurity();
|
||||
}
|
||||
void teardown()
|
||||
{
|
||||
delete inst;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, Create)
|
||||
{
|
||||
CHECK(inst != NULL);
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_constructor)
|
||||
{
|
||||
inst->test_constructor();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_destructor)
|
||||
{
|
||||
inst->test_destructor();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_reset)
|
||||
{
|
||||
inst->test_reset();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_init)
|
||||
{
|
||||
inst->test_init();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_connect)
|
||||
{
|
||||
inst->test_connect();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_start_connecting_non_blocking)
|
||||
{
|
||||
inst->test_start_connecting_non_blocking();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_continue_connecting)
|
||||
{
|
||||
inst->test_continue_connecting();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_send_message)
|
||||
{
|
||||
inst->test_send_message();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_read)
|
||||
{
|
||||
inst->test_read();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_set_random_number_callback)
|
||||
{
|
||||
inst->test_set_random_number_callback();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurity_mbedtls, test_set_entropy_callback)
|
||||
{
|
||||
inst->test_set_entropy_callback();
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
#include "CppUTest/TestPlugin.h"
|
||||
#include "CppUTest/TestRegistry.h"
|
||||
#include "CppUTestExt/MockSupportPlugin.h"
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
return CommandLineTestRunner::RunAllTests(ac, av);
|
||||
}
|
||||
|
||||
IMPORT_TEST_GROUP(M2MConnectionSecurity_mbedtls);
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "test_m2mconnectionsecurity_mbedtls.h"
|
||||
#include "m2mtimerobserver.h"
|
||||
#include "m2msecurity.h"
|
||||
#include "m2msecurity_stub.h"
|
||||
#include "mbedtls_stub.h"
|
||||
#include "m2mconnectionhandler.h"
|
||||
#include "mbed-client-mbed-os/m2mconnectionhandlerpimpl.h"
|
||||
#include "m2mconnectionsecuritypimpl_stub.h"
|
||||
|
||||
entropy_cb ent_cb;
|
||||
|
||||
class TestObserver : public M2MConnectionObserver {
|
||||
|
||||
public:
|
||||
TestObserver(){}
|
||||
void data_available(uint8_t*,
|
||||
uint16_t,
|
||||
const M2MConnectionObserver::SocketAddress &){}
|
||||
|
||||
void socket_error(uint8_t error_code){}
|
||||
|
||||
void address_ready(const M2MConnectionObserver::SocketAddress &,
|
||||
M2MConnectionObserver::ServerType,
|
||||
const uint16_t){}
|
||||
|
||||
void data_sent(){}
|
||||
};
|
||||
|
||||
Test_M2MConnectionSecurity::Test_M2MConnectionSecurity()
|
||||
{
|
||||
mbedtls_stub::clear();
|
||||
m2msecurity_stub::clear();
|
||||
}
|
||||
|
||||
Test_M2MConnectionSecurity::~Test_M2MConnectionSecurity()
|
||||
{
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_constructor()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_destructor()
|
||||
{
|
||||
M2MConnectionSecurity* impl = new M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
delete impl;
|
||||
//Memory leak detector will report an error if leaks
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_reset()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
impl.reset();
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_init()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
m2mconnectionsecuritypimpl_stub::int_value = 7;
|
||||
CHECK( 7 == impl.init(NULL) );
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_connect()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
m2mconnectionsecuritypimpl_stub::int_value = 7;
|
||||
CHECK( 7 == impl.connect(NULL));
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_start_connecting_non_blocking()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
m2mconnectionsecuritypimpl_stub::int_value = 7;
|
||||
CHECK( 7 == impl.start_connecting_non_blocking(NULL));
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_continue_connecting()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
m2mconnectionsecuritypimpl_stub::int_value = 7;
|
||||
CHECK( 7 == impl.continue_connecting());
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_send_message()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
unsigned char msg[6] = "hello";
|
||||
m2mconnectionsecuritypimpl_stub::int_value = 7;
|
||||
CHECK( 7 == impl.send_message(msg, 5) );
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_read()
|
||||
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
unsigned char msg[50];
|
||||
m2mconnectionsecuritypimpl_stub::int_value = 7;
|
||||
CHECK( 7 == impl.read(msg, 49));
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_set_random_number_callback()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
random_number_cb cb(&test_random_callback);
|
||||
impl.set_random_number_callback(cb);
|
||||
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurity::test_set_entropy_callback()
|
||||
{
|
||||
M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS);
|
||||
impl.set_entropy_callback(ent_cb);
|
||||
}
|
||||
|
||||
uint32_t test_random_callback(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 TEST_M2M_CONNECTION_SECURITY_H
|
||||
#define TEST_M2M_CONNECTION_SECURITY_H
|
||||
|
||||
#include "m2mconnectionsecurity.h"
|
||||
|
||||
uint32_t test_random_callback(void);
|
||||
|
||||
class Test_M2MConnectionSecurity
|
||||
{
|
||||
public:
|
||||
Test_M2MConnectionSecurity();
|
||||
|
||||
virtual ~Test_M2MConnectionSecurity();
|
||||
|
||||
void test_constructor();
|
||||
|
||||
void test_destructor();
|
||||
|
||||
void test_reset();
|
||||
|
||||
void test_init();
|
||||
|
||||
void test_connect();
|
||||
|
||||
void test_start_connecting_non_blocking();
|
||||
|
||||
void test_continue_connecting();
|
||||
|
||||
void test_send_message();
|
||||
|
||||
void test_read();
|
||||
|
||||
void test_set_random_number_callback();
|
||||
|
||||
void test_set_entropy_callback();
|
||||
};
|
||||
|
||||
|
||||
#endif // TEST_M2M_CONNECTION_SECURITY_H
|
|
@ -0,0 +1,28 @@
|
|||
if(TARGET_LIKE_LINUX)
|
||||
include("../includes.txt")
|
||||
add_executable(m2mconnectionsecuritypimpl_mbedtls
|
||||
"../../../../yotta_modules/mbed-client-mbedtls/source/m2mconnectionsecuritypimpl.cpp"
|
||||
"main.cpp"
|
||||
"m2mconnectionsecuritypimpl_mbedtlstest.cpp"
|
||||
"test_m2mconnectionsecuritypimpl_mbedtls.cpp"
|
||||
"../stub/m2msecurity_stub.cpp"
|
||||
"../stub/m2mstring_stub.cpp"
|
||||
"../stub/m2mobject_stub.cpp"
|
||||
"../stub/m2mbase_stub.cpp"
|
||||
"../stub/m2mtimer_stub.cpp"
|
||||
"../stub/mbedtls_stub.cpp"
|
||||
"../stub/m2mconnectionhandler_stub.cpp"
|
||||
"../stub/m2mconnectionsecurity_stub.cpp"
|
||||
)
|
||||
|
||||
target_link_libraries(m2mconnectionsecuritypimpl_mbedtls
|
||||
CppUTest
|
||||
CppUTestExt
|
||||
)
|
||||
set_target_properties(m2mconnectionsecuritypimpl_mbedtls
|
||||
PROPERTIES COMPILE_FLAGS "${UTEST_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${UTEST_LINK_FLAGS}")
|
||||
set(binary "m2mconnectionsecuritypimpl_mbedtls -ojunit")
|
||||
add_test(m2mconnectionsecuritypimpl_mbedtls ${binary})
|
||||
|
||||
endif()
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
//CppUTest includes should be after your and system includes
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "test_m2mconnectionsecuritypimpl_mbedtls.h"
|
||||
|
||||
|
||||
TEST_GROUP(M2MConnectionSecurityPimpl_mbedtls)
|
||||
{
|
||||
Test_M2MConnectionSecurityPimpl* inst;
|
||||
|
||||
void setup()
|
||||
{
|
||||
inst = new Test_M2MConnectionSecurityPimpl();
|
||||
}
|
||||
void teardown()
|
||||
{
|
||||
delete inst;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, Create)
|
||||
{
|
||||
CHECK(inst != NULL);
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_constructor)
|
||||
{
|
||||
inst->test_constructor();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_destructor)
|
||||
{
|
||||
inst->test_destructor();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_reset)
|
||||
{
|
||||
inst->test_reset();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_init)
|
||||
{
|
||||
inst->test_init();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_connect)
|
||||
{
|
||||
inst->test_connect();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_start_connecting_non_blocking)
|
||||
{
|
||||
inst->test_start_connecting_non_blocking();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_continue_connecting)
|
||||
{
|
||||
inst->test_continue_connecting();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_send_message)
|
||||
{
|
||||
inst->test_send_message();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_read)
|
||||
{
|
||||
inst->test_read();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_timer_expired)
|
||||
{
|
||||
inst->test_timer_expired();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_set_random_number_callback)
|
||||
{
|
||||
inst->test_set_random_number_callback();
|
||||
}
|
||||
|
||||
TEST(M2MConnectionSecurityPimpl_mbedtls, test_set_entropy_callback)
|
||||
{
|
||||
inst->test_set_entropy_callback();
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "CppUTest/CommandLineTestRunner.h"
|
||||
#include "CppUTest/TestPlugin.h"
|
||||
#include "CppUTest/TestRegistry.h"
|
||||
#include "CppUTestExt/MockSupportPlugin.h"
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
return CommandLineTestRunner::RunAllTests(ac, av);
|
||||
}
|
||||
|
||||
IMPORT_TEST_GROUP(M2MConnectionSecurityPimpl_mbedtls);
|
|
@ -0,0 +1,409 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "CppUTest/TestHarness.h"
|
||||
#include "test_m2mconnectionsecuritypimpl_mbedtls.h"
|
||||
#include "m2mtimerobserver.h"
|
||||
#include "m2msecurity.h"
|
||||
#include "m2msecurity_stub.h"
|
||||
#include "mbedtls_stub.h"
|
||||
#include "mbed-client/m2mconnectionhandler.h"
|
||||
#include "m2mtimer_stub.h"
|
||||
|
||||
uint32_t get_random_number(void)
|
||||
{
|
||||
return time(NULL);
|
||||
}
|
||||
|
||||
entropy_cb ent_cb;
|
||||
|
||||
int ent_poll( void *, unsigned char *output, size_t len,
|
||||
size_t *olen )
|
||||
{
|
||||
for(uint16_t i=0; i < len; i++){
|
||||
srand(time(NULL));
|
||||
output[i] = rand() % 256;
|
||||
}
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
class TestObserver : public M2MConnectionObserver {
|
||||
|
||||
public:
|
||||
TestObserver(){}
|
||||
void data_available(uint8_t*,
|
||||
uint16_t,
|
||||
const M2MConnectionObserver::SocketAddress &){}
|
||||
|
||||
void socket_error(uint8_t error_code, bool retry = true){}
|
||||
|
||||
void address_ready(const M2MConnectionObserver::SocketAddress &,
|
||||
M2MConnectionObserver::ServerType,
|
||||
const uint16_t){}
|
||||
|
||||
void data_sent(){}
|
||||
};
|
||||
|
||||
Test_M2MConnectionSecurityPimpl::Test_M2MConnectionSecurityPimpl()
|
||||
{
|
||||
mbedtls_stub::clear();
|
||||
m2msecurity_stub::clear();
|
||||
}
|
||||
|
||||
Test_M2MConnectionSecurityPimpl::~Test_M2MConnectionSecurityPimpl()
|
||||
{
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_constructor()
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
CHECK(impl._timer != NULL);
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_destructor()
|
||||
{
|
||||
M2MConnectionSecurityPimpl* impl = new M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
delete impl;
|
||||
//Memory leak detector will report an error if leaks
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_reset()
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
impl._init_done = true;
|
||||
impl.reset();
|
||||
CHECK(impl._init_done == false);
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_init()
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
CHECK( -1 == impl.init(NULL) );
|
||||
|
||||
m2msecurity_stub::int_value = 5;
|
||||
M2MSecurity* sec = new M2MSecurity(M2MSecurity::Bootstrap);
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
m2msecurity_stub::int_value = 5;
|
||||
m2msecurity_stub::has_value = true;
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = -1;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Psk;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
m2msecurity_stub::int_value = 5;
|
||||
m2msecurity_stub::has_value = true;
|
||||
mbedtls_stub::expected_int = -1;
|
||||
mbedtls_stub::crt_expected_int = -1;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
mbedtls_stub::crt_expected_int = 0;
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
mbedtls_stub::retArray[2] = 0;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Psk;
|
||||
CHECK( 0 == impl.init(sec) );
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = -1;
|
||||
mbedtls_stub::retArray[2] = -1;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Certificate;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Certificate;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
mbedtls_stub::retArray[2] = 0;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Certificate;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
mbedtls_stub::retArray[2] = 0;
|
||||
mbedtls_stub::retArray[3] = 0;
|
||||
mbedtls_stub::retArray[4] = -1;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Certificate;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
mbedtls_stub::retArray[2] = 0;
|
||||
mbedtls_stub::retArray[3] = 0;
|
||||
mbedtls_stub::retArray[4] = 0;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Certificate;
|
||||
CHECK( 0 == impl.init(sec) );
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
mbedtls_stub::retArray[2] = 0;
|
||||
m2msecurity_stub::int_value = 99;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
impl.set_random_number_callback(NULL);
|
||||
|
||||
ent_cb.entropy_source_ptr = ent_poll;
|
||||
ent_cb.p_source = NULL;
|
||||
ent_cb.threshold = 128;
|
||||
ent_cb.strong = 0;
|
||||
|
||||
m2msecurity_stub::int_value = 5;
|
||||
m2msecurity_stub::has_value = false;
|
||||
mbedtls_stub::useCounter = false;
|
||||
mbedtls_stub::expected_int = 0;
|
||||
mbedtls_stub::crt_expected_int = 0;
|
||||
mbedtls_stub::counter = 1;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Certificate;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
impl.set_entropy_callback(ent_cb);
|
||||
m2msecurity_stub::int_value = 5;
|
||||
m2msecurity_stub::has_value = false;
|
||||
mbedtls_stub::useCounter = false;
|
||||
mbedtls_stub::expected_int = -1;
|
||||
mbedtls_stub::crt_expected_int = 0;
|
||||
mbedtls_stub::counter = 1;
|
||||
m2msecurity_stub::int_value = M2MSecurity::Certificate;
|
||||
CHECK( -1 == impl.init(sec) );
|
||||
|
||||
delete sec;
|
||||
mbedtls_stub::clear();
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_connect()
|
||||
{
|
||||
mbedtls_stub::invalidate_timer = true;
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
CHECK( -1 == impl.connect(NULL));
|
||||
|
||||
impl._init_done = true;
|
||||
CHECK( -1 == impl.connect(NULL));
|
||||
|
||||
m2msecurity_stub::int_value = 5;
|
||||
m2msecurity_stub::has_value = true;
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
CHECK( -1 == impl.connect(NULL));
|
||||
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
CHECK( -1 == impl.connect(NULL));
|
||||
|
||||
m2mtimer_stub::bool_value = true;
|
||||
|
||||
TestObserver obs;
|
||||
M2MConnectionHandler* obj = new M2MConnectionHandler(obs, NULL, M2MInterface::NOT_SET,M2MInterface::LwIP_IPv4);
|
||||
|
||||
mbedtls_stub::expected_uint32_value = 12;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
mbedtls_stub::retArray[2] = MBEDTLS_ERR_SSL_WANT_READ;
|
||||
mbedtls_stub::retArray[3] = MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
mbedtls_stub::retArray[4] = 0;
|
||||
CHECK( -1 == impl.connect(obj));
|
||||
|
||||
delete obj;
|
||||
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::expected_uint32_value = 0;
|
||||
CHECK( 0 == impl.connect(NULL));
|
||||
|
||||
//Tests mbedtls_timing_get_delay() for intermediate case
|
||||
mbedtls_stub::counter = 0;
|
||||
m2mtimer_stub::total_bool_value = false;
|
||||
m2mtimer_stub::bool_value = true;
|
||||
mbedtls_stub::expected_uint32_value = 1;
|
||||
|
||||
CHECK( -1 == impl.connect(obj));
|
||||
|
||||
//Tests mbedtls_timing_get_delay() for cancelled case
|
||||
mbedtls_stub::invalidate_timer = true;
|
||||
|
||||
mbedtls_stub::counter = 0;
|
||||
m2mtimer_stub::total_bool_value = true;
|
||||
CHECK( -1 == impl.connect(obj));
|
||||
|
||||
//Tests mbedtls_timing_get_delay() for NULL case
|
||||
mbedtls_stub::counter = 0;
|
||||
delete(impl._timer);
|
||||
impl._timer = NULL;
|
||||
CHECK( -1 == impl.connect(obj));
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_start_connecting_non_blocking()
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
CHECK( -1 == impl.start_connecting_non_blocking(NULL));
|
||||
|
||||
m2mtimer_stub::total_bool_value = false;
|
||||
impl._init_done = true;
|
||||
impl._sec_mode = M2MConnectionSecurity::TLS;
|
||||
CHECK( -1 == impl.start_connecting_non_blocking(NULL));
|
||||
|
||||
m2msecurity_stub::int_value = 5;
|
||||
m2msecurity_stub::has_value = true;
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
CHECK( -1 == impl.start_connecting_non_blocking(NULL));
|
||||
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
CHECK( -1 == impl.start_connecting_non_blocking(NULL));
|
||||
|
||||
TestObserver obs;
|
||||
M2MConnectionHandler* obj = new M2MConnectionHandler(obs, NULL, M2MInterface::NOT_SET, M2MInterface::LwIP_IPv4);
|
||||
|
||||
m2mtimer_stub::total_bool_value = true;
|
||||
mbedtls_stub::expected_uint32_value = 12;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
mbedtls_stub::retArray[2] = 0;
|
||||
mbedtls_stub::retArray[3] = 0;
|
||||
mbedtls_stub::retArray[4] = 0;
|
||||
CHECK( 1 == impl.start_connecting_non_blocking(obj));
|
||||
|
||||
delete obj;
|
||||
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::expected_uint32_value = 0;
|
||||
mbedtls_stub::retArray[3] = -1;
|
||||
CHECK( -1 == impl.start_connecting_non_blocking(NULL));
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_continue_connecting()
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
impl._ssl.state = MBEDTLS_SSL_HELLO_REQUEST;
|
||||
mbedtls_stub::expected_int = MBEDTLS_ERR_SSL_WANT_READ;
|
||||
CHECK( M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ == impl.continue_connecting());
|
||||
|
||||
mbedtls_stub::expected_int = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST;
|
||||
impl._ssl.state = MBEDTLS_SSL_CLIENT_HELLO;
|
||||
CHECK( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST == impl.continue_connecting());
|
||||
|
||||
mbedtls_stub::expected_int = -6;
|
||||
impl._ssl.state = MBEDTLS_SSL_HANDSHAKE_OVER;
|
||||
CHECK( -6 == impl.continue_connecting());
|
||||
|
||||
mbedtls_stub::expected_int = 0;
|
||||
impl._ssl.state = MBEDTLS_SSL_HANDSHAKE_OVER;
|
||||
CHECK( 0 == impl.continue_connecting());
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_send_message()
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
unsigned char msg[6] = "hello";
|
||||
CHECK( -1 == impl.send_message(msg, 5) );
|
||||
impl._init_done = true;
|
||||
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = MBEDTLS_ERR_SSL_WANT_READ;
|
||||
mbedtls_stub::retArray[1] = MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
mbedtls_stub::retArray[2] = 65;
|
||||
CHECK( 65 == impl.send_message(msg, 5) );
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_read()
|
||||
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
unsigned char msg[50];
|
||||
CHECK( -1 == impl.read(msg, 49));
|
||||
|
||||
impl._init_done = true;
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = MBEDTLS_ERR_SSL_WANT_READ;
|
||||
mbedtls_stub::retArray[1] = MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
mbedtls_stub::retArray[2] = 25;
|
||||
CHECK( 25 == impl.read(msg, 49));
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_timer_expired()
|
||||
{
|
||||
//This uses static function so we need to prepare test using connect() function.
|
||||
mbedtls_stub::invalidate_timer = false;
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
impl._init_done = true;
|
||||
m2msecurity_stub::int_value = 5;
|
||||
m2msecurity_stub::has_value = true;
|
||||
mbedtls_stub::useCounter = true;
|
||||
mbedtls_stub::counter = 0;
|
||||
mbedtls_stub::retArray[0] = 0;
|
||||
mbedtls_stub::retArray[1] = 0;
|
||||
mbedtls_stub::retArray[3] = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
|
||||
impl.connect(NULL);
|
||||
|
||||
void *bio = malloc(1);
|
||||
impl._ssl.p_bio = bio;
|
||||
impl.timer_expired(M2MTimerObserver::Dtls);
|
||||
|
||||
// For testing blocking mode use case
|
||||
mbedtls_stub::useCounter = false;
|
||||
mbedtls_stub::expected_int = MBEDTLS_ERR_SSL_TIMEOUT;
|
||||
|
||||
impl.timer_expired(M2MTimerObserver::Dtls);
|
||||
free(bio);
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_set_random_number_callback()
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
random_number_cb cb(&test_random_callback);
|
||||
impl.set_random_number_callback(cb);
|
||||
}
|
||||
|
||||
void Test_M2MConnectionSecurityPimpl::test_set_entropy_callback()
|
||||
{
|
||||
M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS);
|
||||
impl.set_entropy_callback(ent_cb);
|
||||
}
|
||||
|
||||
uint32_t test_random_callback(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 TEST_M2M_CONNECTION_SECURITY_PIMPL_H
|
||||
#define TEST_M2M_CONNECTION_SECURITY_PIMPL_H
|
||||
|
||||
#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h"
|
||||
|
||||
uint32_t test_random_callback(void);
|
||||
|
||||
class Test_M2MConnectionSecurityPimpl
|
||||
{
|
||||
public:
|
||||
Test_M2MConnectionSecurityPimpl();
|
||||
|
||||
virtual ~Test_M2MConnectionSecurityPimpl();
|
||||
|
||||
void test_constructor();
|
||||
|
||||
void test_destructor();
|
||||
|
||||
void test_reset();
|
||||
|
||||
void test_init();
|
||||
|
||||
void test_connect();
|
||||
|
||||
void test_start_connecting_non_blocking();
|
||||
|
||||
void test_continue_connecting();
|
||||
|
||||
void test_send_message();
|
||||
|
||||
void test_read();
|
||||
|
||||
void test_timer_expired();
|
||||
|
||||
void test_set_random_number_callback();
|
||||
|
||||
void test_set_entropy_callback();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // TEST_M2M_CONNECTION_SECURITY_PIMPL_H
|
|
@ -0,0 +1,28 @@
|
|||
#--- Inputs ----#
|
||||
CPPUTEST_HOME = /usr
|
||||
CPPUTEST_USE_EXTENSIONS = Y
|
||||
CPPUTEST_USE_VPATH = Y
|
||||
CPPUTEST_USE_GCOV = Y
|
||||
CPP_PLATFORM = gcc
|
||||
INCLUDE_DIRS =\
|
||||
.\
|
||||
../common\
|
||||
../stub\
|
||||
../../../../source/include\
|
||||
../../../../source\
|
||||
../../../../\
|
||||
../../../../yotta_modules/mbed-client/mbed-client\
|
||||
../../../../yotta_modules/mbed-client\
|
||||
../../../../yotta_modules/mbed-client/source\
|
||||
../../../../yotta_modules/mbed-client/source/include\
|
||||
../../../../yotta_modules/mbed-client-c\
|
||||
../../../../yotta_modules/mbed-client-c/source/libNsdl\
|
||||
../../../../yotta_modules/mbed-client-c/source/libNsdl/src/include\
|
||||
../../../../yotta_modules/mbedtls\
|
||||
../../../../yotta_modules/mbed-client-mbed-os\
|
||||
../../../../yotta_modules/nanostack-libservice\
|
||||
../../../../yotta_modules/mbed-trace\
|
||||
/usr/include\
|
||||
$(CPPUTEST_HOME)/include\
|
||||
|
||||
CPPUTESTFLAGS = -D__thumb2__ -w
|
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "common_stub.h"
|
||||
#include "sn_grs.h"
|
||||
#include <sys/socket.h>
|
||||
|
||||
socket_error_t common_stub::error;
|
||||
socket_event_t * common_stub::event;
|
||||
socket_addr * common_stub::addr;
|
||||
void * common_stub::void_value;
|
||||
bool common_stub::visited;
|
||||
bool common_stub::bool_value;
|
||||
int common_stub::int_value;
|
||||
int common_stub::int2_value;
|
||||
addrinfo* common_stub::addrinfo;
|
||||
uint16_t common_stub::uint_value;
|
||||
omalw_certificate_list_t *common_stub::cert;
|
||||
sn_coap_hdr_s *common_stub::coap_header;
|
||||
sn_nsdl_resource_info_s *common_stub::resource;
|
||||
pthread_t common_stub::thread;
|
||||
const char* common_stub::char_value;
|
||||
|
||||
using namespace mbed;
|
||||
using namespace mbed::Sockets::v0;
|
||||
|
||||
void common_stub::clear()
|
||||
{
|
||||
int_value = -1;
|
||||
int2_value = -1;
|
||||
uint_value = 0;
|
||||
error = SOCKET_ERROR_NONE;
|
||||
event = NULL;
|
||||
addr = NULL;
|
||||
void_value = NULL;
|
||||
cert = NULL;
|
||||
visited = false;
|
||||
bool_value= false;
|
||||
coap_header = NULL;
|
||||
resource = NULL;
|
||||
addrinfo = NULL;
|
||||
char_value = NULL;
|
||||
}
|
||||
|
||||
UDPSocket::UDPSocket(socket_stack_t stack) :Socket(stack)
|
||||
{
|
||||
}
|
||||
|
||||
UDPSocket::~UDPSocket()
|
||||
{
|
||||
}
|
||||
|
||||
socket_error_t UDPSocket::connect(const SocketAddr *, const uint16_t )
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
//SocketAddr
|
||||
|
||||
void SocketAddr::setAddr(const struct socket_addr *)
|
||||
{
|
||||
}
|
||||
|
||||
void SocketAddr::setAddr(const SocketAddr *)
|
||||
{
|
||||
}
|
||||
|
||||
bool SocketAddr::SocketAddr::is_v4()
|
||||
{
|
||||
return common_stub::bool_value;
|
||||
}
|
||||
|
||||
void mbed::Ticker::detach()
|
||||
{
|
||||
common_stub::visited = true;
|
||||
}
|
||||
|
||||
|
||||
// SN_NSDL_LIB
|
||||
|
||||
struct nsdl_s *sn_nsdl_init (uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *),
|
||||
uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
|
||||
void *(*sn_nsdl_alloc)(uint16_t),void (*sn_nsdl_free)(void *))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t sn_nsdl_register_endpoint(struct nsdl_s *, sn_nsdl_ep_parameters_s *)
|
||||
{
|
||||
return common_stub::uint_value;
|
||||
}
|
||||
|
||||
uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *)
|
||||
{
|
||||
return common_stub::uint_value;
|
||||
}
|
||||
|
||||
uint16_t sn_nsdl_update_registration(struct nsdl_s *,uint8_t *, uint8_t)
|
||||
{
|
||||
return common_stub::uint_value;
|
||||
}
|
||||
|
||||
uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *, uint8_t *, uint8_t,
|
||||
uint8_t *, uint16_t,
|
||||
uint8_t *, uint8_t,
|
||||
sn_coap_msg_type_e , uint8_t)
|
||||
{
|
||||
return common_stub::uint_value;
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_destroy(struct nsdl_s *handle)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *, sn_coap_hdr_s *, uint8_t )
|
||||
{
|
||||
return common_stub::coap_header;
|
||||
}
|
||||
|
||||
sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *, uint16_t, uint8_t *)
|
||||
{
|
||||
return common_stub::resource;
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_process_coap(struct nsdl_s *, uint8_t *, uint16_t , sn_nsdl_addr_s *)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_exec(struct nsdl_s *, uint32_t)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *, sn_coap_hdr_s *header)
|
||||
{
|
||||
if(header && header != common_stub::coap_header){
|
||||
if( header->content_type_ptr ){
|
||||
free(header->content_type_ptr);
|
||||
header->content_type_ptr = NULL;
|
||||
}
|
||||
if( header->options_list_ptr){
|
||||
free(header->options_list_ptr);
|
||||
header->options_list_ptr = NULL;
|
||||
}
|
||||
free(header);
|
||||
header = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_create_resource(struct nsdl_s *, sn_nsdl_resource_info_s *)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_delete_resource(struct nsdl_s *, uint16_t , uint8_t *)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_send_coap_message(struct nsdl_s *, sn_nsdl_addr_s *, sn_coap_hdr_s *)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_update_resource(struct nsdl_s *, sn_nsdl_resource_info_s *)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int8_t set_NSP_address(struct nsdl_s *, uint8_t *, uint16_t, sn_nsdl_addr_type_e)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *, sn_nsdl_addr_s *,
|
||||
sn_nsdl_ep_parameters_s *,
|
||||
sn_nsdl_bs_ep_info_t *)
|
||||
{
|
||||
return common_stub::uint_value;
|
||||
}
|
||||
|
||||
omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *)
|
||||
{
|
||||
return common_stub::cert;
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_update_certificates(struct nsdl_s *, omalw_certificate_list_t*, uint8_t)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *, sn_nsdl_oma_device_t *)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
//Coap Headers
|
||||
|
||||
sn_coap_hdr_s *sn_coap_build_response(struct coap_s *, sn_coap_hdr_s *, uint8_t )
|
||||
{
|
||||
return common_stub::coap_header;
|
||||
}
|
||||
|
||||
void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *, sn_coap_hdr_s *)
|
||||
{
|
||||
}
|
||||
|
||||
int8_t sn_coap_protocol_set_retransmission_parameters(uint8_t, uint8_t)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
// IP6String.h
|
||||
uint_fast8_t ip6tos(const void *, char *)
|
||||
{
|
||||
}
|
||||
|
||||
//Socket
|
||||
Socket::Socket(const socket_stack_t ) : _irq(this)
|
||||
{
|
||||
_socket.api = NULL;
|
||||
}
|
||||
|
||||
Socket::~Socket()
|
||||
{
|
||||
}
|
||||
|
||||
socket_error_t Socket::open(const socket_address_family_t , const socket_proto_family_t )
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
bool Socket::error_check(socket_error_t )
|
||||
{
|
||||
return common_stub::bool_value;
|
||||
}
|
||||
|
||||
void Socket::_eventHandler(struct socket_event *)
|
||||
{
|
||||
}
|
||||
|
||||
void Socket::setOnError(const ErrorHandler_t &)
|
||||
{
|
||||
}
|
||||
|
||||
void Socket::setOnReadable(const ReadableHandler_t &)
|
||||
{
|
||||
}
|
||||
|
||||
void Socket::setOnSent(const SentHandler_t & )
|
||||
{
|
||||
}
|
||||
|
||||
void Socket::_nvEventHandler(void * )
|
||||
{
|
||||
}
|
||||
|
||||
socket_error_t Socket::getLocalAddr(SocketAddr *) const
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
socket_error_t Socket::getLocalPort(uint16_t *) const
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
socket_error_t Socket::getRemoteAddr(SocketAddr *) const
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
socket_error_t Socket::getRemotePort(uint16_t *) const
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
socket_error_t Socket::resolve(const char* , const DNSHandler_t & )
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
socket_error_t Socket::bind(const char * , const uint16_t )
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
socket_error_t Socket::bind(const SocketAddr * , const uint16_t )
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
socket_error_t Socket::close()
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
socket_error_t Socket::recv(void * , size_t *)
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
socket_error_t Socket::recv_from(void * , size_t *, SocketAddr *, uint16_t *)
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
socket_error_t Socket::send(const void * , const size_t )
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
socket_error_t Socket::send_to(const void * , const size_t , const SocketAddr *, uint16_t )
|
||||
{
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
bool Socket::isConnected() const {
|
||||
return common_stub::error;
|
||||
}
|
||||
|
||||
// pthread
|
||||
int pthread_equal (pthread_t , pthread_t ) __THROW
|
||||
{
|
||||
return common_stub::int2_value;
|
||||
}
|
||||
|
||||
pthread_t pthread_self (void) __THROW
|
||||
{
|
||||
return common_stub::thread;
|
||||
}
|
||||
|
||||
int pthread_detach (pthread_t) __THROW
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int pthread_create (pthread_t * ,
|
||||
const pthread_attr_t *,
|
||||
void *(*__start_routine) (void *),
|
||||
void *) __THROWNL
|
||||
{
|
||||
__start_routine(NULL);
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int pthread_cancel (pthread_t)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int pthread_join (pthread_t , void **)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
void pthread_exit (void *__retval)/* __attribute__ ((__noreturn__))*/
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// sys/socket
|
||||
#ifndef __SOCKADDR_ARG
|
||||
# define __SOCKADDR_ARG struct sockaddr *__restrict
|
||||
#endif
|
||||
|
||||
#ifndef __CONST_SOCKADDR_ARG
|
||||
# define __CONST_SOCKADDR_ARG const struct sockaddr *
|
||||
#endif
|
||||
|
||||
#ifndef __socklen_t_defined
|
||||
typedef __socklen_t socklen_t;
|
||||
# define __socklen_t_defined
|
||||
#endif
|
||||
|
||||
int bind (int , __CONST_SOCKADDR_ARG , socklen_t )
|
||||
__THROW
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
ssize_t sendto (int , const void *, size_t ,
|
||||
int , __CONST_SOCKADDR_ARG ,
|
||||
socklen_t )
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
ssize_t recvfrom (int , void * , size_t ,
|
||||
int , __SOCKADDR_ARG ,
|
||||
socklen_t * )
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
int getaddrinfo (const char *__restrict,
|
||||
const char *__restrict,
|
||||
const struct addrinfo *__restrict,
|
||||
struct addrinfo **__restrict addr)
|
||||
{
|
||||
//*addr = (addrinfo*)malloc(sizeof(addrinfo));
|
||||
//(*addr)->ai_addr = (sockaddr*)malloc(sizeof(sockaddr));
|
||||
*addr = common_stub::addrinfo;
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
||||
void freeaddrinfo (struct addrinfo * addr)
|
||||
__THROW
|
||||
{
|
||||
// free(addr->ai_addr);
|
||||
// free(addr);
|
||||
}
|
||||
|
||||
const char *inet_ntop (int, const void *__restrict,
|
||||
char *__restrict, socklen_t)
|
||||
__THROW
|
||||
{
|
||||
return common_stub::char_value;
|
||||
}
|
||||
|
||||
int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
|
||||
{
|
||||
return common_stub::int_value;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 COMMON_STUB_H
|
||||
#define COMMON_STUB_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
//#include "UDPSocket.h"
|
||||
#include "sockets/UDPSocket.h"
|
||||
#include "nsdlaccesshelper.h"
|
||||
#include "ip6string.h"
|
||||
#include "Ticker.h"
|
||||
|
||||
//some internal test related stuff
|
||||
namespace common_stub
|
||||
{
|
||||
extern socket_error_t error;
|
||||
extern socket_event_t* event;
|
||||
extern socket_addr* addr;
|
||||
extern bool visited;
|
||||
extern bool bool_value;
|
||||
extern void* void_value;
|
||||
extern int int_value;
|
||||
extern int int2_value;
|
||||
extern uint16_t uint_value;
|
||||
extern omalw_certificate_list_t *cert;
|
||||
extern addrinfo* addrinfo;
|
||||
extern sn_coap_hdr_s *coap_header;
|
||||
extern sn_nsdl_resource_info_s *resource;
|
||||
extern pthread_t thread;
|
||||
extern const char *char_value;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // COMMON_STUB_H
|
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "m2mbase_stub.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
uint8_t m2mbase_stub::uint8_value;
|
||||
uint16_t m2mbase_stub::uint16_value;
|
||||
uint32_t m2mbase_stub::uint32_value;
|
||||
uint16_t m2mbase_stub::int_value;
|
||||
int32_t m2mbase_stub::name_id_value;
|
||||
|
||||
bool m2mbase_stub::bool_value;
|
||||
String *m2mbase_stub::string_value;
|
||||
|
||||
M2MBase::BaseType m2mbase_stub::base_type;
|
||||
M2MBase::Operation m2mbase_stub::operation;
|
||||
M2MBase::Mode m2mbase_stub::mode_value;
|
||||
M2MBase::Observation m2mbase_stub::observation_level_value;
|
||||
|
||||
void *m2mbase_stub::void_value;
|
||||
M2MObservationHandler *m2mbase_stub::observe;
|
||||
M2MReportHandler *m2mbase_stub::report;
|
||||
bool m2mbase_stub::is_value_updated_function_set;
|
||||
|
||||
|
||||
void m2mbase_stub::clear()
|
||||
{
|
||||
int_value = 0;
|
||||
uint8_value = 0;
|
||||
uint16_value = 0;
|
||||
uint32_value = 0;
|
||||
string_value = NULL;
|
||||
name_id_value = -1;
|
||||
mode_value = M2MBase::Static;
|
||||
base_type = M2MBase::Object;
|
||||
observation_level_value = M2MBase::None;
|
||||
bool_value = false;
|
||||
m2mbase_stub::operation = M2MBase::NOT_ALLOWED;
|
||||
void_value = NULL;
|
||||
observe = NULL;
|
||||
report = NULL;
|
||||
is_value_updated_function_set = false;
|
||||
}
|
||||
|
||||
M2MBase::M2MBase(const String &/*resource_name*/,
|
||||
M2MBase::Mode /*mode*/)
|
||||
{
|
||||
}
|
||||
|
||||
M2MBase& M2MBase::operator=(const M2MBase& other)
|
||||
{
|
||||
if (this != &other) { // protect against invalid self-assignment
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
M2MBase::M2MBase(const M2MBase& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
|
||||
M2MBase::~M2MBase()
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_operation(M2MBase::Operation opr)
|
||||
{
|
||||
m2mbase_stub::operation = opr;
|
||||
}
|
||||
|
||||
void M2MBase::set_interface_description(const String &/*desc*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_resource_type(const String &/*res_type*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_coap_content_type(const uint8_t /*con_type*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_instance_id(const uint16_t /*inst_id*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_observation_number(const uint16_t /*observation_number*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_max_age(const uint32_t /*max_age*/)
|
||||
{
|
||||
}
|
||||
|
||||
M2MBase::Operation M2MBase::operation() const
|
||||
{
|
||||
return m2mbase_stub::operation;
|
||||
}
|
||||
|
||||
const String& M2MBase::name() const
|
||||
{
|
||||
return *m2mbase_stub::string_value;
|
||||
}
|
||||
|
||||
int32_t M2MBase::name_id() const
|
||||
{
|
||||
return m2mbase_stub::name_id_value;
|
||||
}
|
||||
|
||||
uint16_t M2MBase::instance_id() const
|
||||
{
|
||||
return m2mbase_stub::int_value;
|
||||
}
|
||||
|
||||
const String& M2MBase::interface_description() const
|
||||
{
|
||||
return *m2mbase_stub::string_value;
|
||||
}
|
||||
|
||||
const String& M2MBase::resource_type() const
|
||||
{
|
||||
return *m2mbase_stub::string_value;
|
||||
}
|
||||
|
||||
uint8_t M2MBase::coap_content_type() const
|
||||
{
|
||||
return m2mbase_stub::uint8_value;
|
||||
}
|
||||
|
||||
uint32_t M2MBase::max_age() const
|
||||
{
|
||||
return m2mbase_stub::uint32_value;
|
||||
}
|
||||
|
||||
void M2MBase::set_observable(bool /*observable*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::add_observation_level(M2MBase::Observation)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::remove_observation_level(M2MBase::Observation)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_under_observation(bool /*observed*/,
|
||||
M2MObservationHandler */*handler*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_observation_token(const uint8_t */*token*/,
|
||||
const uint8_t /*length*/)
|
||||
{
|
||||
}
|
||||
|
||||
bool M2MBase::is_observable() const
|
||||
{
|
||||
return m2mbase_stub::bool_value;
|
||||
}
|
||||
|
||||
M2MBase::Observation M2MBase::observation_level() const
|
||||
{
|
||||
return m2mbase_stub::observation_level_value;
|
||||
}
|
||||
|
||||
void M2MBase::get_observation_token(uint8_t *&/*token*/,
|
||||
uint32_t &/*length*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::set_base_type(M2MBase::BaseType /*type*/)
|
||||
{
|
||||
}
|
||||
|
||||
M2MBase::BaseType M2MBase::base_type() const
|
||||
{
|
||||
return m2mbase_stub::base_type;
|
||||
}
|
||||
|
||||
M2MBase::Mode M2MBase::mode() const
|
||||
{
|
||||
return m2mbase_stub::mode_value;
|
||||
}
|
||||
|
||||
uint16_t M2MBase::observation_number() const
|
||||
{
|
||||
return m2mbase_stub::uint16_value;
|
||||
}
|
||||
|
||||
void M2MBase::remove_resource_from_coap(const String &)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MBase::remove_object_from_coap()
|
||||
{
|
||||
}
|
||||
|
||||
bool M2MBase::handle_observation_attribute(char *&query)
|
||||
{
|
||||
return m2mbase_stub::bool_value;
|
||||
}
|
||||
|
||||
void M2MBase::observation_to_be_sent(m2m::Vector<uint16_t>, bool)
|
||||
{
|
||||
}
|
||||
|
||||
void *M2MBase::memory_alloc(uint32_t size)
|
||||
{
|
||||
if(size)
|
||||
return malloc(size);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void M2MBase::memory_free(void *ptr)
|
||||
{
|
||||
if(ptr)
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size)
|
||||
{
|
||||
assert(source != NULL);
|
||||
|
||||
uint8_t* result = (uint8_t*)memory_alloc(size + 1);
|
||||
if (result) {
|
||||
memcpy(result, source, size);
|
||||
result[size] = '\0';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size)
|
||||
{
|
||||
assert(source != NULL);
|
||||
|
||||
uint8_t* result = (uint8_t*)memory_alloc(size);
|
||||
if (result) {
|
||||
memcpy(result, source, size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
M2MReportHandler* M2MBase::report_handler()
|
||||
{
|
||||
return m2mbase_stub::report;
|
||||
}
|
||||
|
||||
M2MObservationHandler* M2MBase::observation_handler()
|
||||
{
|
||||
return m2mbase_stub::observe;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/,
|
||||
sn_coap_hdr_s */*received_coap_header*/,
|
||||
M2MObservationHandler */*observation_handler*/)
|
||||
{
|
||||
//Handled in M2MResource, M2MObjectInstance and M2MObject classes
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/,
|
||||
sn_coap_hdr_s */*received_coap_header*/,
|
||||
M2MObservationHandler */*observation_handler*/,
|
||||
bool &execute_value_updated)
|
||||
{
|
||||
//Handled in M2MResource, M2MObjectInstance and M2MObject classes
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/,
|
||||
sn_coap_hdr_s */*received_coap_header*/,
|
||||
M2MObservationHandler */*observation_handler*/,
|
||||
bool &)
|
||||
{
|
||||
//Handled in M2MResource, M2MObjectInstance and M2MObject classes
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void M2MBase::set_register_uri( bool register_uri)
|
||||
{
|
||||
}
|
||||
|
||||
bool M2MBase::register_uri()
|
||||
{
|
||||
return m2mbase_stub::bool_value;
|
||||
}
|
||||
|
||||
void M2MBase::set_uri_path(const String &uri_path)
|
||||
{
|
||||
}
|
||||
|
||||
const String& M2MBase::uri_path() const
|
||||
{
|
||||
return *m2mbase_stub::string_value;
|
||||
}
|
||||
|
||||
bool M2MBase::is_under_observation() const
|
||||
{
|
||||
return m2mbase_stub::bool_value;
|
||||
}
|
||||
|
||||
void M2MBase::set_value_updated_function(value_updated_callback callback)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void M2MBase::set_value_updated_function(value_updated_callback2 callback)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool M2MBase::is_value_updated_function_set()
|
||||
{
|
||||
return m2mbase_stub::is_value_updated_function_set;
|
||||
}
|
||||
|
||||
void M2MBase::execute_value_updated(const String& name)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_BASE_STUB_H
|
||||
#define M2M_BASE_STUB_H
|
||||
|
||||
#include "m2mbase.h"
|
||||
|
||||
//some internal test related stuff
|
||||
namespace m2mbase_stub
|
||||
{
|
||||
extern uint8_t uint8_value;
|
||||
extern uint16_t uint16_value;
|
||||
extern uint32_t uint32_value;
|
||||
extern uint16_t int_value;
|
||||
extern int32_t name_id_value;
|
||||
extern String *string_value;
|
||||
extern bool bool_value;
|
||||
extern M2MBase::BaseType base_type;
|
||||
extern M2MBase::Mode mode_value;
|
||||
extern M2MBase::Operation operation;
|
||||
extern void *void_value;
|
||||
extern M2MObservationHandler *observe;
|
||||
extern M2MReportHandler *report;
|
||||
extern M2MBase::Observation observation_level_value;
|
||||
extern bool is_value_updated_function_set;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // M2M_BASE_STUB_H
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "m2mconnectionhandler_stub.h"
|
||||
#include "m2mconnectionsecurity.h"
|
||||
#include "common_stub.h"
|
||||
|
||||
int m2mconnectionhandler_stub::int_value;
|
||||
uint16_t m2mconnectionhandler_stub::uint_value;
|
||||
bool m2mconnectionhandler_stub::bool_value;
|
||||
|
||||
void m2mconnectionhandler_stub::clear()
|
||||
{
|
||||
int_value = -1;
|
||||
uint_value = 0;
|
||||
bool_value = false;
|
||||
}
|
||||
|
||||
M2MConnectionHandler::M2MConnectionHandler(M2MConnectionObserver &observer,
|
||||
M2MConnectionSecurity* sec,
|
||||
M2MInterface::BindingMode,
|
||||
M2MInterface::NetworkStack)
|
||||
:_observer(observer)
|
||||
{
|
||||
if( sec ){
|
||||
delete sec;
|
||||
sec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
M2MConnectionHandler::~M2MConnectionHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool M2MConnectionHandler::bind_connection(const uint16_t)
|
||||
{
|
||||
return m2mconnectionhandler_stub::bool_value;
|
||||
}
|
||||
|
||||
bool M2MConnectionHandler::resolve_server_address(const String&,
|
||||
const uint16_t,
|
||||
M2MConnectionObserver::ServerType,
|
||||
const M2MSecurity* )
|
||||
{
|
||||
return m2mconnectionhandler_stub::bool_value;
|
||||
}
|
||||
|
||||
bool M2MConnectionHandler::start_listening_for_data()
|
||||
{
|
||||
return m2mconnectionhandler_stub::bool_value;
|
||||
}
|
||||
|
||||
bool M2MConnectionHandler::send_data(uint8_t *,
|
||||
uint16_t ,
|
||||
sn_nsdl_addr_s *)
|
||||
{
|
||||
return m2mconnectionhandler_stub::bool_value;
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::stop_listening()
|
||||
{
|
||||
}
|
||||
|
||||
int M2MConnectionHandler::send_to_socket(const unsigned char *, size_t )
|
||||
{
|
||||
return m2mconnectionhandler_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionHandler::receive_from_socket(unsigned char *buf, size_t len)
|
||||
{
|
||||
return m2mconnectionhandler_stub::int_value;
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::handle_connection_error(int)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::set_platform_network_handler(void *)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::claim_mutex()
|
||||
{
|
||||
}
|
||||
|
||||
void M2MConnectionHandler::release_mutex()
|
||||
{
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_CONNECTION_HANDLER_IMPL_MBED_STUB_H
|
||||
#define M2M_CONNECTION_HANDLER_IMPL_MBED_STUB_H
|
||||
|
||||
#include "m2mconnectionhandler.h"
|
||||
|
||||
//some internal test related stuff
|
||||
namespace m2mconnectionhandler_stub
|
||||
{
|
||||
extern int int_value;
|
||||
extern uint16_t uint_value;
|
||||
extern bool bool_value;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // M2M_CONNECTION_HANDLER_IMPL_STUB_H
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
|
||||
#include "m2mconnectionhandler.h"
|
||||
#include "m2mconnectionsecurity.h"
|
||||
#include "m2mtimer.h"
|
||||
#include "m2msecurity.h"
|
||||
#include <string.h>
|
||||
#include "m2mconnectionsecurity_stub.h"
|
||||
|
||||
bool m2mconnectionsecurityimpl_stub::use_inc_int;
|
||||
int m2mconnectionsecurityimpl_stub::inc_int_value;
|
||||
int m2mconnectionsecurityimpl_stub::int_value;
|
||||
|
||||
void m2mconnectionsecurityimpl_stub::clear()
|
||||
{
|
||||
int_value = -1;
|
||||
use_inc_int = false;
|
||||
inc_int_value = 0;
|
||||
}
|
||||
|
||||
M2MConnectionSecurity::M2MConnectionSecurity(M2MConnectionSecurity::SecurityMode mode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
M2MConnectionSecurity::~M2MConnectionSecurity(){
|
||||
}
|
||||
|
||||
void M2MConnectionSecurity::reset(){
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::init(const M2MSecurity *security){
|
||||
if(m2mconnectionsecurityimpl_stub::use_inc_int){
|
||||
return m2mconnectionsecurityimpl_stub::inc_int_value++;
|
||||
}
|
||||
return m2mconnectionsecurityimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::connect(M2MConnectionHandler* connHandler){
|
||||
if(m2mconnectionsecurityimpl_stub::use_inc_int){
|
||||
return m2mconnectionsecurityimpl_stub::inc_int_value++;
|
||||
}
|
||||
return m2mconnectionsecurityimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::start_connecting_non_blocking(M2MConnectionHandler* connHandler)
|
||||
{
|
||||
if(m2mconnectionsecurityimpl_stub::use_inc_int){
|
||||
return m2mconnectionsecurityimpl_stub::inc_int_value++;
|
||||
}
|
||||
return m2mconnectionsecurityimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::continue_connecting()
|
||||
{
|
||||
if(m2mconnectionsecurityimpl_stub::use_inc_int){
|
||||
return m2mconnectionsecurityimpl_stub::inc_int_value++;
|
||||
}
|
||||
return m2mconnectionsecurityimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::send_message(unsigned char *message, int len){
|
||||
if(m2mconnectionsecurityimpl_stub::use_inc_int){
|
||||
return m2mconnectionsecurityimpl_stub::inc_int_value++;
|
||||
}
|
||||
return m2mconnectionsecurityimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurity::read(unsigned char* buffer, uint16_t len){
|
||||
if(m2mconnectionsecurityimpl_stub::use_inc_int){
|
||||
return m2mconnectionsecurityimpl_stub::inc_int_value++;
|
||||
}
|
||||
return m2mconnectionsecurityimpl_stub::int_value;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_CONNECTION_SECURITY_IMPL_STUB_H
|
||||
#define M2M_CONNECTION_SECURITY_IMPL_STUB_H
|
||||
|
||||
//some internal test related stuff
|
||||
namespace m2mconnectionsecurityimpl_stub
|
||||
{
|
||||
extern int int_value;
|
||||
extern bool use_inc_int;
|
||||
extern int inc_int_value;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // M2M_CONNECTION_SECURITY_IMPL_STUB_H
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
|
||||
#include "m2mconnectionhandler.h"
|
||||
#include "m2mconnectionsecurity.h"
|
||||
#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h"
|
||||
#include "m2mtimer.h"
|
||||
#include "m2msecurity.h"
|
||||
#include <string.h>
|
||||
#include "m2mconnectionsecuritypimpl_stub.h"
|
||||
|
||||
int m2mconnectionsecuritypimpl_stub::int_value;
|
||||
|
||||
void m2mconnectionsecuritypimpl_stub::clear()
|
||||
{
|
||||
int_value = -1;
|
||||
}
|
||||
|
||||
M2MConnectionSecurityPimpl::M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
M2MConnectionSecurityPimpl::~M2MConnectionSecurityPimpl(){
|
||||
}
|
||||
|
||||
void M2MConnectionSecurityPimpl::reset(){
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::init(const M2MSecurity *security){
|
||||
return m2mconnectionsecuritypimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler){
|
||||
return m2mconnectionsecuritypimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::start_connecting_non_blocking(M2MConnectionHandler* connHandler)
|
||||
{
|
||||
return m2mconnectionsecuritypimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::continue_connecting()
|
||||
{
|
||||
return m2mconnectionsecuritypimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len){
|
||||
return m2mconnectionsecuritypimpl_stub::int_value;
|
||||
}
|
||||
|
||||
int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len){
|
||||
return m2mconnectionsecuritypimpl_stub::int_value;
|
||||
}
|
||||
|
||||
void M2MConnectionSecurityPimpl::timer_expired(M2MTimerObserver::Type type){
|
||||
}
|
||||
|
||||
void M2MConnectionSecurityPimpl::set_random_number_callback(random_number_cb){
|
||||
}
|
||||
|
||||
void M2MConnectionSecurityPimpl::set_entropy_callback(entropy_cb){
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_CONNECTION_SECURITY_PIMPL_STUB_H
|
||||
#define M2M_CONNECTION_SECURITY_PIMPL_STUB_H
|
||||
|
||||
//some internal test related stuff
|
||||
namespace m2mconnectionsecuritypimpl_stub
|
||||
{
|
||||
extern int int_value;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // M2M_CONNECTION_SECURITY_PIMPL_STUB_H
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "m2mobject_stub.h"
|
||||
|
||||
u_int16_t m2mobject_stub::int_value;
|
||||
bool m2mobject_stub::bool_value;
|
||||
M2MObjectInstance* m2mobject_stub::inst;
|
||||
M2MObjectInstanceList m2mobject_stub::instance_list;
|
||||
M2MBase::BaseType m2mobject_stub::base_type;
|
||||
sn_coap_hdr_s *m2mobject_stub::header;
|
||||
|
||||
void m2mobject_stub::clear()
|
||||
{
|
||||
int_value = 0;
|
||||
bool_value = false;
|
||||
m2mobject_stub::base_type = M2MBase::Object;
|
||||
instance_list.clear();
|
||||
header = NULL;
|
||||
}
|
||||
|
||||
M2MObject::M2MObject(const String &object_name)
|
||||
: M2MBase(object_name,M2MBase::Dynamic)
|
||||
{
|
||||
}
|
||||
|
||||
M2MObject::~M2MObject()
|
||||
{
|
||||
}
|
||||
|
||||
M2MObject& M2MObject::operator=(const M2MObject& )
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
M2MObject::M2MObject(const M2MObject& other)
|
||||
: M2MBase(other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
M2MObjectInstance* M2MObject::create_object_instance(uint16_t instance_id)
|
||||
{
|
||||
return m2mobject_stub::inst;
|
||||
}
|
||||
|
||||
bool M2MObject::remove_object_instance(uint16_t)
|
||||
{
|
||||
return m2mobject_stub::bool_value;
|
||||
}
|
||||
|
||||
M2MObjectInstance* M2MObject::object_instance(uint16_t) const
|
||||
{
|
||||
return m2mobject_stub::inst;
|
||||
}
|
||||
|
||||
const M2MObjectInstanceList& M2MObject::instances() const
|
||||
{
|
||||
return m2mobject_stub::instance_list;
|
||||
}
|
||||
|
||||
uint16_t M2MObject::instance_count() const
|
||||
{
|
||||
return m2mobject_stub::int_value;
|
||||
}
|
||||
|
||||
M2MBase::BaseType M2MObject::base_type() const
|
||||
{
|
||||
return m2mobject_stub::base_type;
|
||||
}
|
||||
|
||||
void M2MObject::add_observation_level(M2MBase::Observation)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void M2MObject::remove_observation_level(M2MBase::Observation)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
sn_coap_hdr_s* M2MObject::handle_get_request(nsdl_s *,
|
||||
sn_coap_hdr_s *,
|
||||
M2MObservationHandler *)
|
||||
{
|
||||
return m2mobject_stub::header;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s* M2MObject::handle_put_request(nsdl_s *,
|
||||
sn_coap_hdr_s *,
|
||||
M2MObservationHandler *,
|
||||
bool &execute)
|
||||
{
|
||||
execute = m2mobject_stub::bool_value;
|
||||
return m2mobject_stub::header;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s* M2MObject::handle_post_request(nsdl_s *,
|
||||
sn_coap_hdr_s *,
|
||||
M2MObservationHandler *,
|
||||
bool &)
|
||||
{
|
||||
return m2mobject_stub::header;
|
||||
}
|
||||
|
||||
void M2MObject::notification_update(uint16_t obj_instance_id)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_OBJECT_STUB_H
|
||||
#define M2M_OBJECT_STUB_H
|
||||
|
||||
#include "m2mobject.h"
|
||||
#include "m2mobjectinstance.h"
|
||||
|
||||
//some internal test related stuff
|
||||
namespace m2mobject_stub
|
||||
{
|
||||
extern u_int16_t int_value;
|
||||
extern M2MObjectInstance* inst;
|
||||
extern bool bool_value;
|
||||
extern M2MObjectInstanceList instance_list;
|
||||
extern M2MBase::BaseType base_type;
|
||||
extern sn_coap_hdr_s *header;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // M2M_OBJECT_STUB_H
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "m2msecurity_stub.h"
|
||||
|
||||
bool m2msecurity_stub::has_value;
|
||||
uint32_t m2msecurity_stub::int_value;
|
||||
bool m2msecurity_stub::bool_value;
|
||||
String *m2msecurity_stub::string_value;
|
||||
M2MResource* m2msecurity_stub::resource;
|
||||
|
||||
void m2msecurity_stub::clear()
|
||||
{
|
||||
has_value = false;
|
||||
int_value = -1;
|
||||
bool_value = false;
|
||||
string_value = NULL;
|
||||
resource = NULL;
|
||||
}
|
||||
|
||||
M2MSecurity::M2MSecurity(ServerType ser_type)
|
||||
: M2MObject("0"),
|
||||
_server_type(ser_type),
|
||||
_server_instance(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
M2MSecurity::~M2MSecurity()
|
||||
{
|
||||
}
|
||||
|
||||
M2MResource* M2MSecurity::create_resource(SecurityResource, uint32_t)
|
||||
{
|
||||
return m2msecurity_stub::resource;
|
||||
}
|
||||
|
||||
bool M2MSecurity::delete_resource(SecurityResource)
|
||||
{
|
||||
return m2msecurity_stub::bool_value;
|
||||
}
|
||||
|
||||
bool M2MSecurity::set_resource_value(SecurityResource,
|
||||
const String &)
|
||||
{
|
||||
return m2msecurity_stub::bool_value;
|
||||
}
|
||||
|
||||
bool M2MSecurity::set_resource_value(SecurityResource,
|
||||
uint32_t)
|
||||
{
|
||||
return m2msecurity_stub::bool_value;
|
||||
}
|
||||
|
||||
bool M2MSecurity::set_resource_value(SecurityResource,
|
||||
const uint8_t *,
|
||||
const uint16_t)
|
||||
{
|
||||
return m2msecurity_stub::bool_value;
|
||||
}
|
||||
|
||||
String M2MSecurity::resource_value_string(SecurityResource) const
|
||||
{
|
||||
return *m2msecurity_stub::string_value;
|
||||
}
|
||||
|
||||
uint32_t M2MSecurity::resource_value_buffer(SecurityResource,
|
||||
uint8_t *&value) const
|
||||
{
|
||||
if( m2msecurity_stub::has_value ){
|
||||
value = (uint8_t *)malloc(5);
|
||||
return 5;
|
||||
}
|
||||
return m2msecurity_stub::int_value;
|
||||
}
|
||||
|
||||
uint32_t M2MSecurity::resource_value_buffer(SecurityResource,
|
||||
const uint8_t *&value) const
|
||||
{
|
||||
if( m2msecurity_stub::has_value ){
|
||||
value = (const uint8_t*)"dummy";
|
||||
return 6;
|
||||
}
|
||||
return m2msecurity_stub::int_value;
|
||||
}
|
||||
|
||||
uint32_t M2MSecurity::resource_value_int(SecurityResource) const
|
||||
{
|
||||
return m2msecurity_stub::int_value;
|
||||
}
|
||||
|
||||
bool M2MSecurity::is_resource_present(SecurityResource) const
|
||||
{
|
||||
return m2msecurity_stub::bool_value;
|
||||
}
|
||||
|
||||
uint16_t M2MSecurity::total_resource_count() const
|
||||
{
|
||||
return (uint16_t)m2msecurity_stub::int_value;
|
||||
}
|
||||
|
||||
M2MSecurity::ServerType M2MSecurity::server_type() const
|
||||
{
|
||||
return _server_type;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_SECURITY_STUB_H
|
||||
#define M2M_SECURITY_STUB_H
|
||||
|
||||
#include "m2msecurity.h"
|
||||
|
||||
//some internal test related stuff
|
||||
namespace m2msecurity_stub
|
||||
{
|
||||
extern bool has_value;
|
||||
extern uint32_t int_value;
|
||||
extern bool bool_value;
|
||||
extern String *string_value;
|
||||
extern M2MResource* resource;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // M2M_SECURITY_STUB_H
|
||||
|
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "m2mstring.h"
|
||||
#include <string.h> // strlen
|
||||
#include <stdlib.h> // malloc, realloc
|
||||
#include <assert.h>
|
||||
#include <algorithm> // min
|
||||
|
||||
namespace m2m {
|
||||
|
||||
const String::size_type String::npos = static_cast<size_t>(-1);
|
||||
|
||||
char* String::strdup(const char* s)
|
||||
{
|
||||
const size_t len = strlen(s)+1;
|
||||
char *p2 = static_cast<char*>(malloc(len));
|
||||
memcpy(p2, s, len);
|
||||
allocated_ = len;
|
||||
size_ = len-1;
|
||||
return p2;
|
||||
}
|
||||
|
||||
String::String()
|
||||
: p( strdup("") )
|
||||
{
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
free(p);
|
||||
p = 0;
|
||||
}
|
||||
|
||||
String::String(const String& s)
|
||||
: p(0)
|
||||
{
|
||||
if( &s != NULL ) {
|
||||
p = static_cast<char*>(malloc(s.size_ + 1));
|
||||
|
||||
allocated_ = s.size_ + 1;
|
||||
size_ = s.size_;
|
||||
memcpy(p, s.p, size_ + 1);
|
||||
}
|
||||
}
|
||||
|
||||
String::String(const char* s)
|
||||
: p(strdup(s))
|
||||
{
|
||||
}
|
||||
|
||||
String& String::operator=(const char* s)
|
||||
{
|
||||
if ( p != s ) {
|
||||
// s could point into our own string, so we have to allocate a new string
|
||||
const size_t len = strlen(s);
|
||||
char* copy = (char*) malloc( len + 1);
|
||||
memmove(copy, s, len+1); // trailing 0
|
||||
free( p );
|
||||
p = copy;
|
||||
size_ = len;
|
||||
allocated_ = len+1;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::operator=(const String& s)
|
||||
{
|
||||
return operator=(s.p);
|
||||
}
|
||||
|
||||
String& String::operator+=(const String& s)
|
||||
{
|
||||
if (s.size_ > 0) {
|
||||
this->reserve(size_ + s.size_);
|
||||
memmove(p+size_, s.p, s.size_+1); // trailing 0
|
||||
size_ += s.size_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// since p and s may overlap, we have to copy our own string first
|
||||
String& String::operator+=(const char* s)
|
||||
{
|
||||
const size_type lens = strlen(s);
|
||||
if (lens > 0) {
|
||||
if (size_ + lens + 1 <= allocated_) {
|
||||
memmove(p+size_, s, lens+1); // trailing 0
|
||||
size_ += lens;
|
||||
} else {
|
||||
String s2( *this ); // copy own data
|
||||
s2.reserve(size_ + lens);
|
||||
memmove(s2.p+size_, s, lens+1); // trailing 0
|
||||
s2.size_ = size_ + lens;
|
||||
this->swap( s2 );
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::operator+=(const char c)
|
||||
{
|
||||
push_back(c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void String::push_back(const char c) {
|
||||
|
||||
if (size_ == allocated_ - 1) {
|
||||
size_t more = (allocated_* 3) / 2; // factor 1.5
|
||||
if ( more < 4 ) more = 4;
|
||||
reserve( size_ + more );
|
||||
}
|
||||
|
||||
p[size_] = c;
|
||||
size_++;
|
||||
p[size_] = 0;
|
||||
}
|
||||
|
||||
bool String::operator==(const char* s) const
|
||||
{
|
||||
if( s == NULL ) {
|
||||
if( p == NULL ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool ret = strcmp(p, s);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
bool String::operator==(const String& s) const
|
||||
{
|
||||
bool ret = strcmp(p, s.p);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
void String::clear()
|
||||
{
|
||||
size_ = 0;
|
||||
p[0] = 0;
|
||||
}
|
||||
|
||||
String String::substr(const size_type pos, size_type length) const
|
||||
{
|
||||
String s;
|
||||
const size_type len = size_;
|
||||
|
||||
if ( pos <= len ) {
|
||||
|
||||
size_type remain = len - pos;
|
||||
|
||||
if ( length > remain )
|
||||
length = remain;
|
||||
|
||||
s.reserve( length );
|
||||
|
||||
memcpy(s.p, p + pos, length);
|
||||
s.p[length] = '\0';
|
||||
s.size_ = length;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// checked access, accessing the NUL at end is allowed
|
||||
char String::at(const size_type i) const
|
||||
{
|
||||
if ( i <= strlen(p) ) {
|
||||
return p[i];
|
||||
} else {
|
||||
return '\0';
|
||||
}
|
||||
}
|
||||
|
||||
String& String::erase(size_type pos, size_type len)
|
||||
{
|
||||
if (len > 0) {
|
||||
|
||||
if ( pos < size_ ) { // user must not remove trailing 0
|
||||
|
||||
size_type s2 = size_;
|
||||
size_type remain = s2 - pos - len;
|
||||
|
||||
if (remain > 0) {
|
||||
// erase by overwriting
|
||||
memmove(p + pos, p + pos + len, remain);
|
||||
}
|
||||
|
||||
//if ( remain < 0 ) remain = 0;
|
||||
|
||||
// remove unused space
|
||||
this->resize( pos+remain );
|
||||
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::append( const char* str, size_type n) {
|
||||
if (str && n > 0) {
|
||||
size_t lens = strlen(str);
|
||||
if (n > lens)
|
||||
n = lens;
|
||||
size_t newlen = size_ + n;
|
||||
this->reserve( newlen );
|
||||
memmove(p+size_, str, n); // p and s.p MAY overlap
|
||||
p[newlen] = 0; // add NUL termination
|
||||
size_ = newlen;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::append_raw( const char* str, size_type n) {
|
||||
if (str && n > 0) {
|
||||
size_t newlen = size_ + n;
|
||||
this->reserve( newlen );
|
||||
memmove(p+size_, str, n); // p and s.p MAY overlap
|
||||
p[newlen] = 0; // add NUL termination
|
||||
size_ = newlen;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void String::append_int(int param) {
|
||||
|
||||
// max len of "-9223372036854775808" plus zero termination
|
||||
char conv_buff[20+1];
|
||||
|
||||
int len = itoa_c(param, conv_buff);
|
||||
append_raw(conv_buff, len);
|
||||
}
|
||||
|
||||
int String::compare( size_type pos, size_type len, const String& str ) const {
|
||||
int r = -1;
|
||||
if (pos <= size_) {
|
||||
if ( len > size_ - pos)
|
||||
len = size_ - pos; // limit len to available length
|
||||
|
||||
const size_type osize = str.size();
|
||||
const size_type len2 = std::min(len, osize);
|
||||
r = strncmp( p + pos, str.p, len2);
|
||||
if (r==0) // equal so far, now compare sizes
|
||||
r = len < osize ? -1 : ( len == osize ? 0 : +1 );
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int String::compare( size_type pos, size_type len, const char* str ) const {
|
||||
int r = -1;
|
||||
if (pos <= size_) {
|
||||
|
||||
if ( len > size_ - pos)
|
||||
len = size_ - pos; // limit len to available length
|
||||
|
||||
const size_type osize = strlen(str);
|
||||
const size_type len2 = std::min(len, osize);
|
||||
r = strncmp( p + pos, str, len2);
|
||||
if (r==0) // equal so far, now compare sizes
|
||||
r = len < osize ? -1 : ( len == osize ? 0 : +1 );
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int String::find_last_of(char c) const {
|
||||
int r = -1;
|
||||
char *v;
|
||||
v = strrchr(p,c);
|
||||
if (v != NULL) {
|
||||
r = 0;
|
||||
char* i = p;
|
||||
while (v != i) {
|
||||
i++;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void String::new_realloc( size_type n) {
|
||||
if (n > 0 ) {
|
||||
char* pnew = static_cast<char*>(realloc(p, n)); // could return NULL
|
||||
if (pnew)
|
||||
p = pnew;
|
||||
}
|
||||
}
|
||||
|
||||
void String::reserve( const size_type n) {
|
||||
if (n >= allocated_ ) {
|
||||
this->new_realloc(n + 1);
|
||||
allocated_ = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void String::resize( const size_type n) {
|
||||
this->resize( n, 0 );
|
||||
}
|
||||
|
||||
void String::resize( const size_type n, const char c) {
|
||||
if (n < size_ ) {
|
||||
p[n] = 0;
|
||||
size_ = n;
|
||||
}
|
||||
else if (n > size_ ) {
|
||||
this->reserve( n );
|
||||
for (size_type i=size_; i < n; ++i )
|
||||
p[i] = c;
|
||||
p[n] = 0;
|
||||
size_ = n;
|
||||
}
|
||||
}
|
||||
|
||||
void String::swap( String& s ) {
|
||||
std::swap( allocated_, s.allocated_ );
|
||||
std::swap( size_, s.size_ );
|
||||
std::swap( p, s.p );
|
||||
}
|
||||
|
||||
|
||||
// Comparison
|
||||
bool operator<( const String& s1, const String& s2 ) {
|
||||
return strcmp( s1.c_str(), s2.c_str() ) < 0;
|
||||
}
|
||||
|
||||
void reverse(char s[], uint32_t length)
|
||||
{
|
||||
uint32_t i, j;
|
||||
char c;
|
||||
|
||||
for (i = 0, j = length-1; i<j; i++, j--) {
|
||||
c = s[i];
|
||||
s[i] = s[j];
|
||||
s[j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t itoa_c (int64_t n, char s[])
|
||||
{
|
||||
int64_t sign;
|
||||
uint32_t i;
|
||||
|
||||
if ((sign = n) < 0)
|
||||
n = -n;
|
||||
|
||||
i = 0;
|
||||
|
||||
do {
|
||||
s[i++] = n % 10 + '0';
|
||||
}
|
||||
while ((n /= 10) > 0);
|
||||
|
||||
if (sign < 0)
|
||||
s[i++] = '-';
|
||||
|
||||
s[i] = '\0';
|
||||
|
||||
m2m::reverse(s, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, uint8_t *array, uint32_t array_size)
|
||||
{
|
||||
uint8_t* buffer = NULL;
|
||||
size = 0;
|
||||
if (array) {
|
||||
value = String::convert_array_to_integer(array, array_size);
|
||||
}
|
||||
|
||||
if(value < 0xFF) {
|
||||
size = 1;
|
||||
} else if(value < 0xFFFF) {
|
||||
size = 2;
|
||||
} else if(value < 0xFFFFFF) {
|
||||
size = 3;
|
||||
} else if(value < 0xFFFFFFFF) {
|
||||
size = 4;
|
||||
} else if(value < 0xFFFFFFFFFF) {
|
||||
size = 5;
|
||||
} else if(value < 0xFFFFFFFFFFFF) {
|
||||
size = 6;
|
||||
} else if(value < 0xFFFFFFFFFFFFFF) {
|
||||
size = 7;
|
||||
} else {
|
||||
size = 8;
|
||||
}
|
||||
|
||||
buffer = (uint8_t*)malloc(size);
|
||||
if (buffer) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
buffer[i] = (value >> ((size - i - 1) * 8));
|
||||
}
|
||||
} else {
|
||||
size = 0;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int64_t String::convert_array_to_integer(uint8_t *value, uint32_t size)
|
||||
{
|
||||
int64_t temp_64 = 0;
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
temp_64 += (uint64_t)(*value++) << i * 8;
|
||||
}
|
||||
return temp_64;
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
#include "m2mtimer_stub.h"
|
||||
|
||||
bool m2mtimer_stub::bool_value;
|
||||
bool m2mtimer_stub::total_bool_value;
|
||||
|
||||
void m2mtimer_stub::clear()
|
||||
{
|
||||
bool_value = false;
|
||||
total_bool_value = false;
|
||||
}
|
||||
|
||||
// Prevents the use of assignment operator
|
||||
M2MTimer& M2MTimer::operator=(const M2MTimer& /*other*/)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Prevents the use of copy constructor
|
||||
M2MTimer::M2MTimer(const M2MTimer& other)
|
||||
: _observer(other._observer)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
M2MTimer::M2MTimer(M2MTimerObserver& observer)
|
||||
: _observer(observer)
|
||||
{
|
||||
}
|
||||
|
||||
M2MTimer::~M2MTimer()
|
||||
{
|
||||
}
|
||||
|
||||
void M2MTimer::start_timer(uint64_t /*interval*/,
|
||||
M2MTimerObserver::Type /*type*/,
|
||||
bool /*single_shot*/)
|
||||
{
|
||||
}
|
||||
|
||||
void M2MTimer::start_dtls_timer(uint64_t , uint64_t , M2MTimerObserver::Type )
|
||||
{
|
||||
}
|
||||
|
||||
void M2MTimer::stop_timer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool M2MTimer::is_intermediate_interval_passed(){
|
||||
return m2mtimer_stub::bool_value;
|
||||
}
|
||||
|
||||
bool M2MTimer::is_total_interval_passed(){
|
||||
return m2mtimer_stub::total_bool_value;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 M2M_TIMER_STUB_H
|
||||
#define M2M_TIMER_STUB_H
|
||||
|
||||
#include "m2mtimer.h"
|
||||
|
||||
//some internal test related stuff
|
||||
namespace m2mtimer_stub
|
||||
{
|
||||
extern bool bool_value;
|
||||
extern bool total_bool_value;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // M2M_TIMER_STUB_H
|
||||
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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.
|
||||
*/
|
||||
|
||||
#include "mbedtls_stub.h"
|
||||
|
||||
bool mbedtls_stub::useCounter;
|
||||
int mbedtls_stub::counter;
|
||||
int mbedtls_stub::retArray[20];
|
||||
int mbedtls_stub::crt_expected_int;
|
||||
int mbedtls_stub::expected_int;
|
||||
uint32_t mbedtls_stub::expected_uint32_value;
|
||||
bool mbedtls_stub::invalidate_timer;
|
||||
|
||||
void mbedtls_stub::clear()
|
||||
{
|
||||
mbedtls_stub::useCounter = false;
|
||||
counter = 0;
|
||||
expected_int = -1;
|
||||
crt_expected_int = -1;
|
||||
expected_uint32_value = 0;
|
||||
for( int i=0; i < 20; i++ ){
|
||||
retArray[i] = -1;
|
||||
}
|
||||
invalidate_timer = false;
|
||||
}
|
||||
|
||||
//From ssl.h
|
||||
int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
int mbedtls_ssl_close_notify( mbedtls_ssl_context * )
|
||||
{
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
void mbedtls_ssl_init( mbedtls_ssl_context * ){
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_ssl_config_init( mbedtls_ssl_config * ){
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *, uint32_t, uint32_t)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_ssl_free( mbedtls_ssl_context * ){
|
||||
|
||||
}
|
||||
|
||||
int mbedtls_ssl_session_reset( mbedtls_ssl_context * ){
|
||||
|
||||
}
|
||||
|
||||
int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *,
|
||||
mbedtls_x509_crt *,
|
||||
mbedtls_pk_context * ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *, int ){
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *,
|
||||
mbedtls_x509_crt *,
|
||||
mbedtls_x509_crl * ){
|
||||
|
||||
}
|
||||
|
||||
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *,
|
||||
const unsigned char *, size_t ,
|
||||
const unsigned char *, size_t ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
int mbedtls_ssl_config_defaults( mbedtls_ssl_config *,
|
||||
int , int, int ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
void mbedtls_ssl_conf_rng( mbedtls_ssl_config *,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void * ){
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *,
|
||||
const int *)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int mbedtls_ssl_setup( mbedtls_ssl_context *,
|
||||
const mbedtls_ssl_config * ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
|
||||
void *p_bio,
|
||||
int (*f_send)(void *, const unsigned char *, size_t),
|
||||
int (*f_recv)(void *, unsigned char *, size_t),
|
||||
int (*f_recv_timeout)(void *, unsigned char *, size_t, uint32_t) ){
|
||||
if( p_bio != NULL ){
|
||||
f_send( p_bio, NULL, 0 );
|
||||
f_recv( p_bio, NULL, 0 );
|
||||
f_recv_timeout( p_bio, NULL, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *,
|
||||
void *ctx,
|
||||
void (*f_set_timer)(void *, uint32_t int_ms, uint32_t fin_ms),
|
||||
int (*f_get_timer)(void *) ){
|
||||
f_set_timer(ctx, 1, 2);
|
||||
f_get_timer(ctx);
|
||||
if(mbedtls_stub::invalidate_timer){
|
||||
f_set_timer(ctx, 0, 0);
|
||||
}
|
||||
f_get_timer(ctx);
|
||||
}
|
||||
|
||||
int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context * ){
|
||||
return mbedtls_stub::expected_uint32_value;
|
||||
}
|
||||
|
||||
int mbedtls_ssl_read( mbedtls_ssl_context *, unsigned char *, size_t ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
int mbedtls_ssl_write( mbedtls_ssl_context *, const unsigned char *, size_t ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//From crt_drbg.h
|
||||
int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *,
|
||||
int (*f_entropy)(void *, unsigned char *, size_t),
|
||||
void *,
|
||||
const unsigned char *,
|
||||
size_t ){
|
||||
return mbedtls_stub::crt_expected_int;
|
||||
}
|
||||
|
||||
void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context * ){
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context * ){
|
||||
|
||||
}
|
||||
|
||||
int mbedtls_ctr_drbg_random_with_add( void *,
|
||||
unsigned char *, size_t ,
|
||||
const unsigned char *, size_t ){
|
||||
return mbedtls_stub::crt_expected_int;
|
||||
}
|
||||
|
||||
int mbedtls_ctr_drbg_random( void *p_rng,
|
||||
unsigned char *output, size_t output_len ){
|
||||
return mbedtls_stub::crt_expected_int;
|
||||
}
|
||||
|
||||
//From x509_crt.h
|
||||
void mbedtls_x509_crt_init( mbedtls_x509_crt * ){
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_x509_crt_free( mbedtls_x509_crt * ){
|
||||
|
||||
}
|
||||
|
||||
int mbedtls_x509_crt_parse( mbedtls_x509_crt *, const unsigned char *, size_t ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
//From entropy.h
|
||||
void mbedtls_entropy_init( mbedtls_entropy_context * ){
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_entropy_free( mbedtls_entropy_context *ctx ){
|
||||
|
||||
}
|
||||
|
||||
int mbedtls_entropy_func( void *, unsigned char *, size_t ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
int mbedtls_entropy_add_source( mbedtls_entropy_context *,
|
||||
mbedtls_entropy_f_source_ptr f_source, void *,
|
||||
size_t, int ){
|
||||
unsigned char buf[2];
|
||||
size_t len;
|
||||
f_source(NULL, buf, 1, &len);
|
||||
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
if(mbedtls_stub::counter == 1){
|
||||
mbedtls_stub::counter--;
|
||||
return 0;
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
//From pk.h
|
||||
int mbedtls_pk_parse_key( mbedtls_pk_context *,
|
||||
const unsigned char *, size_t ,
|
||||
const unsigned char *, size_t ){
|
||||
if( mbedtls_stub::useCounter ){
|
||||
return mbedtls_stub::retArray[mbedtls_stub::counter++];
|
||||
}
|
||||
return mbedtls_stub::expected_int;
|
||||
}
|
||||
|
||||
void mbedtls_pk_init( mbedtls_pk_context *ctx )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_pk_free( mbedtls_pk_context *ctx )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void mbedtls_ssl_config_free( mbedtls_ssl_config * )
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 MBEDTLS_STUB_H
|
||||
#define MBEDTLS_STUB_H
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/x509_crt.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/pk.h"
|
||||
|
||||
namespace mbedtls_stub
|
||||
{
|
||||
extern int crt_expected_int;
|
||||
extern bool useCounter;
|
||||
extern int counter;
|
||||
extern int retArray[20];
|
||||
extern int expected_int;
|
||||
extern uint32_t expected_uint32_value;
|
||||
extern bool invalidate_timer;
|
||||
void clear();
|
||||
}
|
||||
|
||||
#endif // MBEDTLS_STUB_H
|
|
@ -0,0 +1,293 @@
|
|||
#
|
||||
# Toolchain rules for building libraries
|
||||
#
|
||||
# Support multi-platform builds
|
||||
# You may define PLATFORM=.. prefix for compiler
|
||||
# if PLATFORM is defined it will owerride CC and AR
|
||||
# You may also specify CC and AR separately.
|
||||
# example: Compile with KEIL
|
||||
# make CC=ArmCC AR=ArmAR
|
||||
#
|
||||
# example: Cross Compile with Gnu toolchain, for embedded Linux
|
||||
# make PLATFORM=arm-linux-gnueabi-
|
||||
#
|
||||
# Special rules for IAR-ARM toolchains added, AR tool on that does not follow common arquements.
|
||||
# make CC=iccarm uses iarchive.exe for creating a archive.
|
||||
#
|
||||
# Special rules for IAR-RL78 toolchain added, uses own AR and compiler requires specific flags
|
||||
# make CC=iccrl78
|
||||
#
|
||||
# When using ArmCC, Select CPU by defining one of following supported values
|
||||
# CPU=Cortex-M0
|
||||
# CPU=Cortex-M3
|
||||
# CPU=Cortex-M4
|
||||
#
|
||||
# example:
|
||||
# make CC=armcc CPU=Cortex-M4
|
||||
|
||||
#
|
||||
# If PLATFORM prefix is defined,
|
||||
# generate CC and AR accordingly
|
||||
#
|
||||
ifneq ($(strip $(PLATFORM)),)
|
||||
CC:=$(PLATFORM)gcc
|
||||
AR:=$(PLATFORM)ar
|
||||
endif
|
||||
|
||||
#
|
||||
# Windows specific tweaks for echo and mkdir to work
|
||||
#
|
||||
ifeq ($(OS),Windows_NT)
|
||||
SHELL := cmd.exe
|
||||
mkdir = if not exist $(1) md $(subst /,\,$(1))
|
||||
else
|
||||
mkdir = mkdir -p $(1)
|
||||
endif
|
||||
|
||||
#
|
||||
# Append CC and CPU to library names
|
||||
#
|
||||
LIB:=$(LIB:%.a=%_$(CC).a)
|
||||
ifneq (,$(CPU))
|
||||
LIB:=$(LIB:%.a=%_$(CPU).a)
|
||||
endif
|
||||
|
||||
##########################################################
|
||||
# TOOLCHAIN SPECIFIC RULES AND FLAGS #
|
||||
##########################################################
|
||||
|
||||
#
|
||||
# GCC toolchains
|
||||
#
|
||||
ifneq (,$(findstring gcc,$(CC)))
|
||||
# Flags for common toolchain, usually GCC or CC
|
||||
AROPTS=-rsc $@ $^
|
||||
override CFLAGS += -Wall -pedantic-errors
|
||||
# Dependency generation
|
||||
override CFLAGS += -MMD -MP
|
||||
ifneq (,$(CPU))
|
||||
# CPU must be lowercase on GCC
|
||||
CPU_L:=$(shell echo $(CPU) | tr A-Z a-z)
|
||||
override CFLAGS += -mcpu=$(CPU_L)
|
||||
# Use THUMB instructions of Cortex-M cores
|
||||
ifeq (cortex-m,$(findstring cortex-m,$(CPU_L)))
|
||||
override CFLAGS += -mthumb
|
||||
endif
|
||||
endif
|
||||
# Debug
|
||||
ifeq ($(DEBUG),1)
|
||||
override CFLAGS += -g -O0
|
||||
else
|
||||
override CFLAGS += -O2
|
||||
endif
|
||||
# Enable Coverage generation
|
||||
ifeq ($(COVERAGE),1)
|
||||
override CFLAGS += -ftest-coverage -fprofile-arcs
|
||||
override LDFLAGS += -ftest-coverage -fprofile-arcs
|
||||
endif
|
||||
COMPILE = $(CC) -std=gnu99 -c -o $@
|
||||
CXXCOMPILE = $(CC) -std=c++11 -c -o $@
|
||||
|
||||
#
|
||||
# IAR-ARM toolchain
|
||||
#
|
||||
else ifneq (,$(findstring iccarm,$(CC)))
|
||||
AR:=iarchive
|
||||
AROPTS=$^ --create -o $@
|
||||
DLIB_FILE=$(subst bin\iccarm.exe,inc\c\DLib_Config_Full.h,$(shell where iccarm))
|
||||
override CFLAGS += --dlib_config '$(DLIB_FILE)' --cpu Cortex-M4 --vla --diag_suppress Pa50
|
||||
# Dependency generation
|
||||
override CFLAGS += --dependencies=m $(basename $@).d
|
||||
# Debug
|
||||
ifeq ($(DEBUG),1)
|
||||
override CFLAGS += --debug -On
|
||||
else
|
||||
override CFLAGS += -Om
|
||||
endif
|
||||
COMPILE = $(CC) -c -o $@
|
||||
|
||||
#
|
||||
# ArmCC toolchain (Used by Keil)
|
||||
#
|
||||
else ifneq (,$(findstring armcc,$(CC)))
|
||||
AR:=armar
|
||||
AROPTS=-rsc $@ $^
|
||||
override CFLAGS += --c99 --no_wrap_diagnostics
|
||||
# Dependency generation
|
||||
override CFLAGS += --depend $(basename $@).d --phony_targets
|
||||
LIB:=$(LIB:%.a=%.lib)
|
||||
ifneq (,$(CPU))
|
||||
override CFLAGS += --cpu=$(CPU)
|
||||
endif
|
||||
# Debug
|
||||
ifeq ($(DEBUG),1)
|
||||
override CFLAGS += -g -O0
|
||||
else
|
||||
override CFLAGS += -O2
|
||||
endif
|
||||
COMPILE = $(CC) -c -o $@
|
||||
|
||||
#
|
||||
# IAR Renesas78 toolchain
|
||||
#
|
||||
else ifneq (,$(findstring iccrl78,$(CC)))
|
||||
AR:=xar
|
||||
AROPTS=$@ $^
|
||||
# Hack to get \lib include path which contains dlib config headers for compiler
|
||||
DIR=$(subst iccrl78.exe,..\lib\,$(shell where iccrl78))
|
||||
override CFLAGS += --core rl78_1 --code_model far --data_model far --dlib_config full --vla --no_wrap_diagnostics -I'$(DIR)'
|
||||
# Dependency generation
|
||||
LIB:=$(LIB:%.a=%.lib)
|
||||
override CFLAGS += --dependencies=m $(basename $@).d
|
||||
# Debug
|
||||
ifeq ($(DEBUG),1)
|
||||
override CFLAGS += --debug -Oh
|
||||
else
|
||||
override CFLAGS += -Ohz
|
||||
endif
|
||||
COMPILE = $(CC) -o $@
|
||||
|
||||
#
|
||||
# IAR MSP430 toolchain
|
||||
#
|
||||
else ifneq (,$(findstring icc430,$(CC)))
|
||||
AR:=xar
|
||||
AROPTS=$@ $^
|
||||
# Hack to get \lib include path which contains dlib config headers for compiler
|
||||
DIR=$(subst bin\icc430.exe,lib,$(shell where icc430))
|
||||
DLIB_FILE=$(subst bin\icc430.exe,lib\dlib\dl430xllff.h,$(shell where icc430))
|
||||
override CFLAGS += --dlib_config '$(DLIB_FILE)' --vla --core 430X --data_model large --no_wrap_diagnostics -I'$(DIR)'
|
||||
# Dependency generation
|
||||
LIB:=$(LIB:%.a=%.lib)
|
||||
override CFLAGS += --dependencies=m $(basename $@).d
|
||||
# Debug
|
||||
ifeq ($(DEBUG),1)
|
||||
override CFLAGS += --debug -On
|
||||
else
|
||||
override CFLAGS += -Ohz
|
||||
endif
|
||||
COMPILE = $(CC) -o $@
|
||||
|
||||
#
|
||||
# CppCheck toolchain
|
||||
# This is used only for static testing the code.
|
||||
# cppcheck is used in place of compiler and linker phase is ignored
|
||||
else ifneq (,$(findstring cppcheck,$(CC)))
|
||||
AR = cppcheck -q --enable=warning --enable=style --std=c99 --inline-suppr -DCPPCHECK $(CPPCHECK_OPTS) $(CFLAGS) $(SRCS)
|
||||
COMPILE = true
|
||||
CPPCHECK = 1
|
||||
LIB:= "ignored_with_cppcheck"
|
||||
|
||||
|
||||
###################################
|
||||
# End of toolchain specific rules #
|
||||
###################################
|
||||
endif
|
||||
|
||||
#
|
||||
# Generate VERSION tag
|
||||
#
|
||||
ifeq (,$(CPPCHECK))
|
||||
VERSION := $(shell git describe --tags --long --dirty --always)
|
||||
CFLAGS += -DVERSION='"$(VERSION)"'
|
||||
endif
|
||||
|
||||
############################################################
|
||||
# AUTOMATICALLY GENERATE LIBRARY COMPILATION RULES #
|
||||
# #
|
||||
# Use: #
|
||||
# $(eval $(call generate_rules,$(OUTPUT_LIB),$(SRCS))) #
|
||||
# at the end of your Makefile #
|
||||
# #
|
||||
############################################################
|
||||
|
||||
define generate_rules
|
||||
|
||||
DEST_LIB := $(1)
|
||||
LIB_SRCS := $(2)
|
||||
C_SRCS := $$(filter %.c,$$(LIB_SRCS))
|
||||
CXX_SRCS := $$(filter %.cpp,$$(LIB_SRCS))
|
||||
all: $$(DEST_LIB)
|
||||
|
||||
#
|
||||
# Define build dir outside from src folders
|
||||
#
|
||||
BUILD_DIR := output/$$(CC)
|
||||
ifneq (,$$(CPU))
|
||||
BUILD_DIR := $$(BUILD_DIR)_$$(CPU)
|
||||
endif
|
||||
ifneq (generic,$$(CONFIG))
|
||||
BUILD_DIR := $$(BUILD_DIR)_$$(CONFIG)
|
||||
endif
|
||||
OBJS := $$(C_SRCS:%.c=$$(BUILD_DIR)/%.o) $$(CXX_SRCS:%.cpp=$$(BUILD_DIR)/%.o)
|
||||
|
||||
# Include auto-dependencies
|
||||
-include $$(OBJS:.o=.d)
|
||||
|
||||
# Create list of output directories.
|
||||
OBJ_DIRS := $$(sort $$(dir $$(OBJS)))
|
||||
|
||||
# requires directories to be created before build.
|
||||
# '|' means do not care about timestamps of requisities
|
||||
$$(OBJS): | $$(OBJ_DIRS)
|
||||
|
||||
# Need to redefine build rule to find the sources
|
||||
# from correct folder.
|
||||
$$(BUILD_DIR)/%.o: %.c
|
||||
ifeq ($(V),1)
|
||||
$$(COMPILE) $$(CFLAGS) $$<
|
||||
else ifeq (1,$(CPPCHECK))
|
||||
@$$(COMPILE) $$(CFLAGS) $$<
|
||||
else ifeq (1,$(UNITTEST))
|
||||
@echo Building unittest $$<
|
||||
ifneq ($(OS),Windows_NT)
|
||||
ruby $(UNIT_TEST_BASE)/../auto/generate_test_runner.rb Test.c Test_Runner.c
|
||||
endif
|
||||
@gcc $$(CFLAGS) $$(SRCS) -o $$(OUTPUT_LIB)
|
||||
else
|
||||
@echo Building $$<
|
||||
@$$(COMPILE) $$(CFLAGS) $$<
|
||||
endif
|
||||
|
||||
# Same again for C++
|
||||
$$(BUILD_DIR)/%.o: %.cpp
|
||||
ifeq ($(V),1)
|
||||
$$(CXXCOMPILE) $$(CFLAGS) $$<
|
||||
else ifeq (1,$(CPPCHECK))
|
||||
@$$(CXXCOMPILE) $$(CFLAGS) $$<
|
||||
else
|
||||
@echo Building $$<
|
||||
@$$(CXXCOMPILE) $$(CFLAGS) $$<
|
||||
endif
|
||||
|
||||
# Rule to create a object directory
|
||||
$$(OBJ_DIRS):
|
||||
@-$$(call mkdir,$$@)
|
||||
|
||||
$$(DEST_LIB): $$(OBJS)
|
||||
ifeq ($(V),1)
|
||||
-$$(addprefix $$(RM) ,$$(wildcard $$@))
|
||||
$$(AR) $$(AROPTS)
|
||||
else ifeq (1,$(CPPCHECK))
|
||||
@$$(AR) $$(AROPTS)
|
||||
else ifeq (1,$(UNITTEST))
|
||||
#ifneq ($(OS),Windows_NT)
|
||||
# lcov -q --capture -i --directory $(CURDIR) --output-file lib_base.info
|
||||
# ./$$@
|
||||
# lcov -q --capture --directory $(CURDIR) --output-file lib_test.info
|
||||
# lcov -a lib_base.info -a lib_test.info -o coverage.info
|
||||
#endif
|
||||
else
|
||||
@echo Linking $$(notdir $$@)
|
||||
@-$$(addprefix $$(RM) ,$$(wildcard $$@))
|
||||
@$$(AR) $$(AROPTS)
|
||||
endif
|
||||
|
||||
clean:
|
||||
@$(RM) -r $$(BUILD_DIR)
|
||||
@$(RM) $$(DEST_LIB)
|
||||
|
||||
clean-all:
|
||||
@$(RM) -r output *.a
|
||||
|
||||
endef
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
# not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# * http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License 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.
|
||||
|
||||
echo
|
||||
echo "Creating report"
|
||||
echo
|
||||
|
||||
echo '<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml-stylesheet type="text/xsl" href="junit_xsl.xslt"?>
|
||||
<list>' >> lcov/index.xml
|
||||
|
||||
for f in lcov/results/*.xml
|
||||
do
|
||||
name=${f##*/}
|
||||
echo '<entry name="results/'"$name"'" />'>> lcov/index.xml
|
||||
done
|
||||
|
||||
echo '</list>' >> lcov/index.xml
|
||||
|
||||
echo
|
||||
echo "Report created to lcov/index.xml (outputs html)"
|
||||
echo
|
|
@ -0,0 +1,36 @@
|
|||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
yotta_modules
|
||||
yotta_targets
|
||||
build
|
||||
lcov/*
|
||||
output/*
|
||||
.yotta.json
|
|
@ -0,0 +1,4 @@
|
|||
config/*
|
||||
docs/*
|
||||
doxygen/*
|
||||
test/*
|
|
@ -0,0 +1,7 @@
|
|||
# files for linux builds
|
||||
|
||||
# ignore linux test application
|
||||
test/lwm2mtestapplication/*
|
||||
test/lwm2m/*
|
||||
coverage/*
|
||||
results/*
|
|
@ -0,0 +1,11 @@
|
|||
ARM mbed Client
|
||||
================
|
||||
|
||||
## Introduction
|
||||
This is the Doxygen generated documentation of mbed Client.
|
||||
It should be used in conjunction with the [mbed Client Guide](https://docs.mbed.com/docs/mbed-client-guide/en/latest/)
|
||||
hosted in http://docs.mbed.com.
|
||||
|
||||
# API documentation
|
||||
|
||||
See [Files](files.html) section to find a documentation about specific API.
|
|
@ -0,0 +1,202 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License 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.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
ARM mbed Client
|
||||
=======================
|
||||
|
||||
This repository contains ARM mbed Client: a library that connects devices to mbed Device Connector Service, mbed Device Server (mDS) and to mbed-enabled cloud services from our partners.
|
||||
|
||||
The documentation is collected under the docs directory and the **mbed Client Guide** is also hosted [here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/).
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
FLAGS += \
|
||||
TARGET_LIKE_LINUX
|
|
@ -0,0 +1,417 @@
|
|||
# How to use the mbed Client API
|
||||
|
||||
This section explains how to use our C++ API to create and configure different types of Objects, Object Instances and Resources for mbed Client to comply with the OMA LWM2M specifications. These resources can then be communicated to mbed Device Server.
|
||||
|
||||
<span class="notes">**Note:** The API complies with the OMA LWM2M specifications.</span>
|
||||
|
||||
As per the OMA LWM2M specification:
|
||||
|
||||
- The client must have defined Objects, under which it can create Object Instances.
|
||||
- The client must have created Object Instances under Objects, which will eventually contain Resources.
|
||||
- The client must have Resources under Object Instances which belong to Objects.
|
||||
- The client must have created Resources under Object Instance. You can create M2MResource from the M2MObjectInstance class.
|
||||
- The client must have created Resource Instances under Resources. You can create M2MResourceInstance from the M2MObjectInstance class.
|
||||
|
||||
|
||||
## How to create and configure Objects
|
||||
|
||||
With this API, you can create and configure the following Objects:
|
||||
|
||||
- [Device Objects](#device-object)
|
||||
- [Security Objects](#security-object)
|
||||
- [Custom Objects](#custom-object)
|
||||
|
||||
The M2MObject class is derived from the M2MBase class, so all the public methods can be used from the M2MObject and its derived classes.
|
||||
|
||||
### Creating OMA-defined Objects
|
||||
|
||||
#### Device Object
|
||||
|
||||
To create a Device Object:
|
||||
|
||||
`static M2MDevice *create_device();`
|
||||
|
||||
Because there can be only one instance of M2MDevice, it is a static class and you can delete it as follows:
|
||||
|
||||
`M2MDevice::delete_instance();`
|
||||
|
||||
Check the [M2MDevice class documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MDevice.html) to see how to configure the Device Object.
|
||||
|
||||
#### Security Object
|
||||
|
||||
To create a Security Object:
|
||||
|
||||
`static M2MSecurity *create_security(M2MSecurity::ServerType server_type);`
|
||||
|
||||
You can create a Bootstrap or normal mbed Device Server by passing the appropriate `enum` value.
|
||||
|
||||
Check the [M2MSecurity class documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MSecurity.html) to see how to configure the Security Object, as well as how to create appropriate Resources and assign values to them.
|
||||
|
||||
#### Custom Object
|
||||
|
||||
For a Custom Object, you need to pass the name of the Object that you would like to create (for example `Test`); this will create an Object with that name in mbed Device Server.
|
||||
|
||||
To create an M2MObject:
|
||||
|
||||
`static M2MObject *create_object(const String &name);`
|
||||
|
||||
#### Configuring the Object
|
||||
|
||||
Once you have created an Object (whether OMA-specific or custom), you can configure various parameters in it to control or modify communication with mbed Device Server.
|
||||
|
||||
```
|
||||
M2MObject * _object = M2MInterfaceFactory::create_object("Test");
|
||||
if(_object) {
|
||||
_object->set_register_uri(true); // The registration message explicitly sends this object path as registered resource such as /Test.
|
||||
}
|
||||
```
|
||||
|
||||
Here, we discuss a few of the most important parameters, which you must configure properly to work with the Objects.
|
||||
|
||||
##### Setting Operation Mode
|
||||
|
||||
To set the operation mode of the Objects so that they can handle `GET`, `PUT`, `POST`, `DELETE` or a combination of these requests coming from mbed Device Server:
|
||||
|
||||
```
|
||||
virtual void set_operation(M2MBase::Operation operation);
|
||||
_object->set_operation(M2MBase::GET_PUT_POST_ALLOWED); // This defines the REST operations that can be performed on this object.
|
||||
```
|
||||
|
||||
##### Setting Observable Mode
|
||||
|
||||
To set the Object to be an observing resource:
|
||||
|
||||
`virtual void set_observable(bool observable);`
|
||||
|
||||
By default, all the created objects are non-observable. You can set them to be observable or not observable using this API.
|
||||
|
||||
```
|
||||
_object->set_observable(true); // The object can be observed from server.
|
||||
_object->set_observable(false); // The object cannot be observed from server.
|
||||
```
|
||||
|
||||
##### Setting CoAP content type
|
||||
|
||||
Currently, the only available content type is the OMA TLV type. The OMA TLV type works only for Objects with a numeric value. For example, if you are creating a custom Object it must be of a numeric type such as `100`.
|
||||
|
||||
`M2MObject * _object = M2MInterfaceFactory::create_object("100");`
|
||||
|
||||
By default, all the numeric objects are assigned the CoAP content type of `99` by mbed Client but if you want your Object to assign any other CoAP content type, for example 120, you can do that by setting the object's CoAP content type as shown below:
|
||||
|
||||
```
|
||||
virtual void set_coap_content_type(const uint8_t content_type);
|
||||
_object->set_coap_content_type(120);
|
||||
```
|
||||
|
||||
<span class="tips">**Tip:** In future releases, we will introduce support for the JSON content types.</span>
|
||||
|
||||
## How to create and configure Object Instances
|
||||
|
||||
With this API, you can create and configure the following Object Instances:
|
||||
|
||||
- [Device Object Instance](#device-object-instance)
|
||||
- [Security Object Instance](#security-object-instance)
|
||||
- [Custom Object Instance](#custom-object-instance)
|
||||
|
||||
The `M2MObjectInstance` class is derived from the `M2MBase` class, so all the public methods from `M2MObjectInstance` and its derived classes can be used.
|
||||
|
||||
### Creating an OMA-defined Object Instance
|
||||
|
||||
#### Device Object Instance
|
||||
|
||||
Because there can only be one instance for the Device Object, the Object Instance is automatically created when creating an M2MDevice Object.
|
||||
|
||||
#### Security Object Instance
|
||||
|
||||
Because there can only be one instance for the Security Object, the Object Instance is automatically created when creating an M2MDevice Object based on a selected server type.
|
||||
|
||||
#### Custom Object Instances
|
||||
|
||||
Object Instances need IDs. Normally, the IDs start from '0' and increment,
|
||||
so the Object Instance structure on the mbed Device Server side would look like this:
|
||||
|
||||
`Object/Object Instance ID`
|
||||
|
||||
When you create an Object Instance, you therefore need to pass the ID that you would like to create. For example, if you pass `0`, you get an object `/Test/0` on mbed Device Server.
|
||||
|
||||
To create an M2M Object Instance:
|
||||
|
||||
`M2MObject::create_object_instance(uint16_t instance_id);`
|
||||
|
||||
You can pass an Object Instance ID to create appropriate Object Instances. Normally, Object Instances will start from `0` and increment. So the Object Instance structure on the mbed Device Server side would look like this:
|
||||
|
||||
`Object/Object Instance ID`
|
||||
|
||||
```
|
||||
M2MObjectInstance * object_instance = _object->create_object_instance(0);
|
||||
if(object_instance) {
|
||||
object_instance->set_register_uri(true); // The registration message explicitly sends this object instance path as registered resource such as /Test/0.
|
||||
}
|
||||
```
|
||||
|
||||
### Configuring the Object Instance
|
||||
|
||||
When you have created an Object Instance (whether OMA-specific or custom), you can configure various parameters in it to control or modify communication with mbed Device Server.
|
||||
|
||||
Here, we present a few of the most important parameters that you must configure properly to work with the object instances.
|
||||
|
||||
##### Setting Operation Mode
|
||||
|
||||
To set the operation mode of the Objects so that they can handle `GET`, `PUT`, `POST`, `DELETE` or a combination of these requests coming from mbed Device Server:
|
||||
|
||||
```
|
||||
virtual void set_operation(M2MBase::Operation operation);
|
||||
object_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED); // This defines the REST operations that can be performed on this object instance.
|
||||
```
|
||||
|
||||
##### Setting Observable Mode
|
||||
|
||||
To set the Object Instance to be an observing resource:
|
||||
|
||||
`virtual void set_observable(bool observable);`
|
||||
|
||||
By default, all the created Object Instances are non-observable. You can set them to be observable or not observable using this API.
|
||||
|
||||
```
|
||||
_object_instance->set_observable(true); // This defines that the Object Instance can be observed from server.
|
||||
_object_instance->set_observable(false); // This defines that the Object Instance cannot be observed from server.
|
||||
```
|
||||
|
||||
##### Setting CoAP content type
|
||||
|
||||
Currently, the only available content type is the OMA TLV type. The OMA TLV type works only for Objects and Object Instances with a numeric value. For example, if you are creating a custom Object and Object Instances it must be of a numeric type such as `100`.
|
||||
|
||||
```
|
||||
M2MObject * _object = M2MInterfaceFactory::create_object("100");
|
||||
M2MObjectInstance * object_instance = _object->create_object_instance(0);
|
||||
```
|
||||
|
||||
By default, all numeric objects are assigned the CoAP content type of `99` by mbed Client but if you want your Object Instance to assign any other CoAP content type, for example 120, you can do that by setting the object's CoAP content type as follows:
|
||||
|
||||
```
|
||||
virtual void set_coap_content_type(const uint8_t content_type);
|
||||
object_instance->set_coap_content_type(120);
|
||||
```
|
||||
|
||||
<span class="tips">**Tip:** In future version, we will introduce support for the JSON content types.</span>
|
||||
|
||||
There are additional APIs that provide getter and remove functions for Object Instances in the `M2MObjectInstance` class; [check the API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html) for their usage.
|
||||
|
||||
## How to create and configure Resources and Resource Instances
|
||||
|
||||
With this API, you can create and configure the following Resources and Resource Instances:
|
||||
|
||||
- [Device Object Resources](#device-object-resources)
|
||||
- [Security Object Resources](#security-object-resources)
|
||||
- [Custom Resources](#custom-resources)
|
||||
|
||||
|
||||
The `M2MResource` class is derived from the `M2MResourceInstance`, which in turn is derived from the `M2MBase` class, so all the public methods can be used from `M2MResource` or `M2MResourceInstance` and their derived classes.
|
||||
|
||||
### Creating OMA-defined Resources
|
||||
|
||||
#### Device Object Resources
|
||||
|
||||
There are direct APIs to create and set values for the Device Resources. You can create the required Resource and set values based on their data types.
|
||||
|
||||
- For Resources that take string values:
|
||||
|
||||
`M2MResource* create_resource(DeviceResource resource, const String &value);`
|
||||
|
||||
- For Resources that take integer values:
|
||||
|
||||
`M2MResource* create_resource(DeviceResource resource, uint32_t value);`
|
||||
|
||||
- There are a few Resources that can have multiple instances. To create these Resources:
|
||||
|
||||
`M2MResourceInstance* create_resource_instance(DeviceResource resource, uint32_t value,uint16_t instance_id);`
|
||||
|
||||
Where `instance_id` is the Resource Instance ID, for example `/3/0/11/0`.
|
||||
|
||||
Check the [M2MDevice API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MDevice.html) to find which enums are supported for `integer` or `string` value types.
|
||||
|
||||
There are other APIs in the `M2MDevice` class that you can use to set, remove and modify new values for the resources.
|
||||
|
||||
#### Security Object Resources
|
||||
|
||||
_Mandatory Resources_
|
||||
|
||||
Most of the mandatory Resources are created automatically when you create an M2MSecurity Object. You can set their values based on their data types.
|
||||
|
||||
Resources that are automatically created and their accepted data types:
|
||||
|
||||
- `SecurityMode`
|
||||
- `ShortServerID`
|
||||
- `M2MServerUri`
|
||||
- `BootstrapServer`
|
||||
- `PublicKey`
|
||||
- `ServerPublicKey`
|
||||
- `Secretkey`
|
||||
|
||||
For Resources (`SecurityMode`, `ShortServerID`) that take integer values, you can set the values as follows:
|
||||
|
||||
`bool set_resource_value(SecurityResource resource,uint32_t value);`
|
||||
|
||||
```
|
||||
security_object->set_resource_value(M2MSecurity::SecurityMode, 1);
|
||||
security_object->set_resource_value(M2MSecurity::ShortServerID, 1);
|
||||
```
|
||||
|
||||
For Resources (`M2MServerUri`) that take string values, you can set the values as follows:
|
||||
|
||||
`bool set_resource_value(SecurityResource resource,const String &value);`
|
||||
|
||||
```
|
||||
security_object->set_resource_value(M2MSecurity::M2MServerUri, "coap://api.connector.mbed.com:5684");
|
||||
```
|
||||
|
||||
For Resources (`PublicKey`, `ServerPublicKey`, `Secretkey`) that take binary values, you can set the values as follows:
|
||||
|
||||
`bool set_resource_value(SecurityResource resource,onst uint8_t *value,const uint16_t length);`
|
||||
|
||||
```
|
||||
uint8_t key[] = {"key"};
|
||||
security_object->set_resource_value(M2MSecurity::PublicKey, key, sizeof(key));
|
||||
```
|
||||
|
||||
_Optional Resources_
|
||||
|
||||
Optional Resources as defined in the Security Object:
|
||||
|
||||
- `SMSSecurityMode`
|
||||
- `M2MServerSMSNumber`
|
||||
- `ClientHoldOffTime`
|
||||
|
||||
To create and set values for the optional Resources that take an integer value:
|
||||
|
||||
`M2MResource* create_resource(SecurityResource resource, uint32_t value);`
|
||||
|
||||
`security_object->create_resource(M2MSecurity::M2MServerSMSNumber, 123542323);`
|
||||
|
||||
|
||||
Check the [M2MSecurity API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MSecurity.html) to find which enums are supported for `integer`, `string` or `uint8_t*` value types.
|
||||
|
||||
There are more APIs in the `M2MSecurity` class that you can use to set, remove and modify Resource values.
|
||||
|
||||
#### Custom Resources
|
||||
|
||||
For Custom Objects, you can create Resources of two types:
|
||||
|
||||
- **M2MResource**: a resource with a single instance, for example `/Test/0/Resource`.
|
||||
|
||||
- **M2MResourceInstance**: a resource with multiple instances, for example `/Test/0/Resource/0`, `/Test/0/Resource/1`.
|
||||
|
||||
For each of these types, the Resource and Resource Instances can be either static or dynamic:
|
||||
|
||||
- **Static**: Resource and Resource Instances whose value does not change over time, these are not observable.
|
||||
- **Dynamic**: Resource and Resource Instances whose value can change. These can be made observable.
|
||||
|
||||
**Creating dynamic and static single-instance Resources**
|
||||
|
||||
- To create a single-instance Resource with a static value (`/Test/0/Resource`): [see parameters here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html#aaa596f731688730d7a883b7f1251a662)
|
||||
|
||||
```
|
||||
M2MObject * object = M2MInterfaceFactory::create_object("Test");
|
||||
M2MObjectInstance * object_instance = object->create_object_instance(0);
|
||||
|
||||
uint8_t value[] ={"value"};
|
||||
M2MResource* resource = object_instance->create_static_resource("Resource", "sensor",M2MResourceInstance::INTEGER,value,sizeof(value),false);
|
||||
```
|
||||
|
||||
- To create an observable single-instance Resource (`/Test/0/Resource`) with a dynamic value that can be set later on: [see parameters here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html#a9b3f88dc2d28512ea6c3db6f74168c3f)
|
||||
|
||||
```
|
||||
M2MObject * object = M2MInterfaceFactory::create_object("Test");
|
||||
M2MObjectInstance * object_instance = object->create_object_instance(0);
|
||||
|
||||
uint8_t value[] ={"value"};
|
||||
M2MResource* resource = object_instance->create_dynamic_resource("Resource", "sensor",M2MResourceInstance::INTEGER,value,sizeof(value), true, false);
|
||||
```
|
||||
|
||||
**Creating dynamic and static Resource Instances**
|
||||
|
||||
- To create a Resource Instance (`/Test/0/Resource/0`) with a static value: [see parameters here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html#a6acac6e65bfbc8b731ab4afcc805c41b)
|
||||
|
||||
```
|
||||
M2MObject * object = M2MInterfaceFactory::create_object("Test");
|
||||
M2MObjectInstance * object_instance = object->create_object_instance(0);
|
||||
|
||||
uint8_t value[] ={"value"};
|
||||
M2MResourceInstance* resource_instance = object_instance->create_static_resource_instance("Resource", "sensor",M2MResourceInstance::INTEGER,value,sizeof(value),0);
|
||||
```
|
||||
|
||||
|
||||
- To create an observable Resource Instance (`/Test/0/Resource/0`) with a dynamic value that can be set later on: [see parameters here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html#adcaba046a484282983380edf8a370cfa)
|
||||
|
||||
```
|
||||
M2MObject * object = M2MInterfaceFactory::create_object("Test");
|
||||
M2MObjectInstance * object_instance = object->create_object_instance(0);
|
||||
|
||||
uint8_t value[] ={"value"};
|
||||
M2MResource* resource = object_instance->create_dynamic_resource_instance("Resource", "sensor",M2MResourceInstance::INTEGER,value,sizeof(value), true, 0);
|
||||
```
|
||||
|
||||
#### Configuring the Resource and Resource Instance
|
||||
|
||||
When you have created a Resource or Resource Instance (whether OMA-specific or custom), you can configure various parameters to control or modify communication with mbed Device Server.
|
||||
|
||||
Here, we present a few of the most important parameters that you must configure properly to work with the Resource and Resource Instance.
|
||||
|
||||
##### Setting Operation Mode
|
||||
|
||||
You can set the Resource or Resource Instance operation mode so that they can handle `GET`, `PUT`, `POST`, `DELETE` or a combination of these requests coming from mbed Device Server.
|
||||
|
||||
To set the operation mode:
|
||||
|
||||
```
|
||||
virtual void set_operation(M2MBase::Operation operation);
|
||||
resource->set_operation(M2MBase::GET_PUT_POST_ALLOWED); // This defines the REST operations that can be performed on this Resource.
|
||||
resource_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED); // This defines the REST operations that can be performed on this Resource Instance.
|
||||
```
|
||||
##### Setting Observable Mode
|
||||
|
||||
To set the Resource or Resource Instance to be an observable resource:
|
||||
|
||||
`virtual void set_observable(bool observable);`
|
||||
|
||||
By default, all created static Resources or Resource Instances are non-observable. While creating a dynamic Resource or Resource Instance you can specify through API whether they are observable or not. You can change that later as well as follows:
|
||||
|
||||
```
|
||||
resource->set_observable(true); // This defines that the Resource or Resource Instance can be observed from server.
|
||||
resource->set_observable(false); // This defines that the Resource or Resource Instance cannot be observed from server.
|
||||
```
|
||||
|
||||
##### Setting the value of a dynamic Resource or Resource Instance
|
||||
|
||||
You can set the value of a dynamic Resource or Resource Instance so that they can be sent to mbed Device Server using `GET` requests.
|
||||
|
||||
To set the values:
|
||||
|
||||
```
|
||||
virtual bool set_value(const uint8_t *value, const uint32_t value_length);
|
||||
uint8_t value[] = {"value"};
|
||||
resource->set_value(value,sizeof(value));
|
||||
```
|
||||
|
||||
##### Setting an executable function
|
||||
|
||||
For dynamic Resources, you can pass a function pointer to the Resource or Resource Instance. It will be executed when mbed Device Server calls a `POST` method on that resource. The Resource or Resource Instance must support the `POST` operation mode for this feature to work.
|
||||
|
||||
To pass the function pointer:
|
||||
|
||||
```
|
||||
virtual void set_execute_function(execute_callback callback);
|
||||
void execute_function_example(void *) {
|
||||
// Code
|
||||
};
|
||||
resource->set_execute_function(execute_callback(this,&execute_function_example));
|
||||
```
|
||||
In case execute callback function is defined as a global function and it's outside of your class scope you can use overloaded set_execute_function:
|
||||
```
|
||||
virtual void set_execute_function(execute_callback_2 callback);
|
||||
static void c_style_function(void *) {
|
||||
// Code
|
||||
}
|
||||
resource->set_execute_function(&c_style_function);
|
||||
```
|
||||
There are additional APIs that provide getter and remove functions for Resource and Resource Instances in the `M2MResource` and `M2MResourceInstance` classes. Check [the API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html) for their usage.
|
|
@ -0,0 +1,144 @@
|
|||
# ARM mbed Client overview
|
||||
|
||||
ARM mbed Client is a library that provides the means to connect constrained embedded devices to mbed Device Connector Service, mbed Device Server and to mbed-enabled cloud services from our partners.
|
||||
|
||||
The mbed Client high-level APIs allow mbed OS developers to create applications with LWM2M features as described in the [Lightweight Machine to Machine Technical Specification](http://technical.openmobilealliance.org/Technical/technical-information/release-program/current-releases/oma-lightweightm2m-v1-0):
|
||||
|
||||
- Manage devices on mbed Device Server.
|
||||
- Securely communicate with internet services over the industry standard TLS/DTLS.
|
||||
- Fully control the endpoint and application logic.
|
||||
|
||||
The API is written in C++ to allow quick application development.
|
||||
|
||||
## Managing devices on mbed Device Server
|
||||
|
||||
mbed Client supports the following three features introduced in the subsequent chapters:
|
||||
|
||||
- [Client Registration and Deregistration](client_reg_dereg.md)
|
||||
- [Device Management and Service Enablement](dev_man_serv_enable.md)
|
||||
- [Information Reporting](info_reporting.md)
|
||||
|
||||
The API also provides an interface to define the application endpoint information. This information will be delivered to mbed Device Server during the registration operation.
|
||||
|
||||
First, you need to create an interface for mbed Client:
|
||||
|
||||
```
|
||||
#include "mbed-client/m2minterfacefactory.h"
|
||||
#include "mbed-client/m2minterface.h"
|
||||
|
||||
M2MInterface* interface = M2MInterfaceFactory::create_interface(*this,
|
||||
"mbed-endpoint",
|
||||
"test",
|
||||
3600,
|
||||
5684,
|
||||
"",
|
||||
M2MInterface::UDP,
|
||||
M2MInterface::LwIP_IPv4,
|
||||
"");
|
||||
```
|
||||
|
||||
### Setting up own random number generator function
|
||||
|
||||
To provide a stronger security mechanism, mbed Client requires a random number generator to feed a random number into the underlying SSL library. There is a default PRNG seeded with RTC for security but some platforms do not have RTC, and for some, time value seeded PRNG is not secure enough.
|
||||
|
||||
Now, an application can pass its own RNG implementation to mbed Client as function pointer callback through an API, `set_random_number_callback(random_number_cb callback)`.
|
||||
|
||||
Here is an example on how you can use it from an application:
|
||||
|
||||
```
|
||||
#include "mbed-client/m2minterfacefactory.h"
|
||||
#include "mbed-client/m2minterface.h"
|
||||
|
||||
uint32_t get_random_number(void)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
printf("\Your application's RNG logic\n");
|
||||
return i;
|
||||
}
|
||||
|
||||
_interface->set_random_number_callback(&get_random_number);
|
||||
|
||||
```
|
||||
|
||||
### Setting up own entropy function for additional secure connectivity
|
||||
|
||||
mbed Client provides an API to add your own entropy source into the underlying SSL library. There is a default entropy source provided by mbed Client. It uses PRNG seeded with RTC for the security but some platforms do not have RTC, and for some, this level of security may not be strong enough.
|
||||
|
||||
Now, an application can pass its own entropy source to mbed Client as function pointer callback through an API, `set_entropy_callback(entropy_cb callback)`.
|
||||
|
||||
Here is an example on how you can use it from an application:
|
||||
|
||||
```
|
||||
#include "mbed-client/m2minterfacefactory.h"
|
||||
#include "mbed-client/m2minterface.h"
|
||||
|
||||
entropy_cb ent_cb;
|
||||
|
||||
int ent_poll( void *, unsigned char *output, size_t len,
|
||||
size_t *olen )
|
||||
{
|
||||
for(uint16_t i=0; i < len; i++){
|
||||
srand(time(NULL));
|
||||
output[i] = rand() % 256;
|
||||
}
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
ent_cb.entropy_source_ptr = ent_poll;
|
||||
ent_cb.p_source = NULL;
|
||||
ent_cb.threshold = 128;
|
||||
ent_cb.strong = 0;
|
||||
|
||||
_interface->set_entropy_callback(ent_cb);
|
||||
|
||||
```
|
||||
|
||||
### Maximum UDP message size
|
||||
|
||||
The maximum single UDP message size that mbed Client can receive is 1152 bytes. The actual payload size is 1137 bytes, the header information using the remaining 15 bytes.
|
||||
|
||||
For transferring larger amounts of data, the Blockwise feature must be deployed. When using this feature, mbed Client can handle messages up to 64KB. This feature is disabled by default.
|
||||
|
||||
To enable the Blockwise feature, you need to create a `config.json` file in the application level.
|
||||
|
||||
*Example:*
|
||||
```
|
||||
{
|
||||
"coap_max_blockwise_payload_size": 1024
|
||||
}
|
||||
```
|
||||
|
||||
Acceptable values for the `coap_max_blockwise_payload_size` flag are:
|
||||
0, 16, 32, 64, 128, 256, 512 and 1024. Value 0 means that the feature is not used.
|
||||
|
||||
### CoAP message deduplication
|
||||
|
||||
Message duplication is disabled by default. More information about deduplication in the [CoAP specification](https://tools.ietf.org/html/rfc7252#page-24).
|
||||
|
||||
To enable message deduplication, you need to create a `config.json` file in the application level.
|
||||
|
||||
*Example:*
|
||||
```
|
||||
{
|
||||
"coap_duplication_max_msgs_count": 1
|
||||
}
|
||||
```
|
||||
Recommended values for the `coap_duplication_max_msgs_count` flag are 0 to 6. Value 0 means that the feature is not used. It is not recommended to use higher value than 6, because it increases the memory consumption.
|
||||
|
||||
## How to use the API
|
||||
More information on how to use the API effectively to create and configure Objects, Object Instances and Resources, can be found [here](Howto.md).
|
||||
|
||||
## API documentation
|
||||
|
||||
The documentation for this API is [available here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html).
|
||||
|
||||
## Example application
|
||||
|
||||
We have an example application for
|
||||
|
||||
1. [mbed OS](https://github.com/ARMmbed/mbed-client-examples).
|
||||
|
||||
2. [Ubuntu](https://github.com/ARMmbed/mbed-client-linux-example).
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
# The Client Registration feature
|
||||
|
||||
The client uses the Client Registration to register with mbed Device Server, update registration and deregister.
|
||||
|
||||
Currently, only one-to-one client-server registration is supported. One-to-many client-server registrations will be supported in an upcoming release.
|
||||
|
||||
The Client Registration includes multiple sub-features. Currently supported:
|
||||
|
||||
- [Register](#the-register-feature)
|
||||
- [Update](#the-update-feature)
|
||||
- [Deregister](#the-deregister-feature)
|
||||
|
||||
## The Register feature
|
||||
|
||||
This API enables the client registration functionality.
|
||||
|
||||
When registering, the client:
|
||||
|
||||
* Performs the **Register** operation and provides parameters that mbed Device Server requires to register the client (for example Endpoint Name).
|
||||
|
||||
* Maintains the registration and session (for example, it sets the Lifetime and Queue Mode towards mbed Device Server).
|
||||
|
||||
* Provides information on the Objects the client supports and existing Object Instances in the client.
|
||||
|
||||
### Registering your client
|
||||
|
||||
To provide information to mbed Device Server and issue the register command:
|
||||
|
||||
**Step 1.** Create an mbed DS Object. This object contains information about mbed Device Server, such as its address and security mode.
|
||||
|
||||
```
|
||||
#include "mbed-client/m2msecurity.h"
|
||||
M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
|
||||
if(security) {
|
||||
security->set_resource_value(M2MSecurity::M2MServerUri, LWM2M_SERVER_ADDRESS);
|
||||
security->set_resource_value(M2MSecurity::BootstrapServer, 0);
|
||||
security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity);
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2.** mbed Client supports both non-secure and secure mode operations. For secure mode, you need to provide a certificate, private key and server public key through the API.
|
||||
|
||||
To create a secure mode operation:
|
||||
|
||||
```
|
||||
#include "mbed-client/m2msecurity.h"
|
||||
M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
|
||||
if(security) {
|
||||
security->set_resource_value(M2MSecurity::M2MServerUri, LWM2M_SERVER_ADDRESS);
|
||||
security->set_resource_value(M2MSecurity::BootstrapServer, 0);
|
||||
security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate);
|
||||
security->set_resource_value(M2MSecurity::ServerPublicKey,<SERVER_CERT>,sizeof(<SERVER_CERT>));
|
||||
security->set_resource_value(M2MSecurity::PublicKey,<CERT>,sizeof(<CERT>));
|
||||
security->set_resource_value(M2MSecurity::Secretkey,<KEY>,sizeof(<KEY>));
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3.** Register all the resources that you would like to monitor or follow using mbed Device Server. To do this, create the resource objects and pass them to the Register API for registration purposes.
|
||||
|
||||
For example, if you want to register your OMA LWM2M based Device object, you need to create the object and set the values for mandatory resources as follows:
|
||||
|
||||
```
|
||||
#include "mbed-client/m2mdevice.h"
|
||||
M2MDevice *device = M2MInterfaceFactory::create_device();
|
||||
if(device) {
|
||||
device->create_resource(M2MDevice::Manufacturer,MANUFACTURER);
|
||||
device->create_resource(M2MDevice::DeviceType,TYPE);
|
||||
device->create_resource(M2MDevice::ModelNumber,MODEL_NUMBER);
|
||||
device->create_resource(M2MDevice::SerialNumber,SERIAL_NUMBER);
|
||||
}
|
||||
```
|
||||
|
||||
<span class="notes">**Note:** You can register other resources, including custom resources. Please check the [API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html) for a detailed description of the M2MObject, M2MObjectInstance and M2MResource classes.</span>
|
||||
|
||||
**Step 4.** You have the registration server object and resources that you want to register. Now, you need to call the register API and pass the following objects as parameters:
|
||||
|
||||
```
|
||||
M2MInterface::register_object(M2MSecurity* register_object, M2MObjectList object_list);
|
||||
```
|
||||
|
||||
**Success or failure callback**
|
||||
|
||||
Because this is an asynchronous operation, you will receive the result of this operation through a callback defined in `m2minterfaceobserver.h` in your application.
|
||||
|
||||
_Success_
|
||||
|
||||
If the register operation is successful and the client can register all your resources to mbed DS, your application will receive the following callback:
|
||||
|
||||
```
|
||||
void object_registered(M2MSecurity *server_object, const M2MServer& server)
|
||||
```
|
||||
|
||||
The `M2MSecurity *server_object` specifies to which mbed Device Server instance the client has just registered and `M2MServer &server` contains the data related to mbed Device Server, including the Short ServerID and the client registration period.
|
||||
|
||||
_Failure_
|
||||
|
||||
If the registration operation fails for some reason, you will receive the following callback:
|
||||
|
||||
```
|
||||
void error(M2MInterface::Error error)
|
||||
```
|
||||
|
||||
You will get more information about the error from the `error` parameter passed with the callback; use it to fix the source of the error.
|
||||
|
||||
## The Update feature
|
||||
|
||||
Periodically, or in response to events within the client or as initiated by mbed Device Server, the client updates its registration information with mbed Device Server by sending it an **Update** operation.
|
||||
|
||||
Normally, the enabler will update the registration automatically, but if you want to renew the registration before that, you can use this API.
|
||||
|
||||
To update your registration:
|
||||
|
||||
```
|
||||
M2MInterface::update_registration(M2MSecurity* security_object, const uint32_t lifetime)
|
||||
```
|
||||
|
||||
**Success or failure callback**
|
||||
|
||||
_Success_
|
||||
|
||||
If the update operation is successful, your application will receive the following callback:
|
||||
|
||||
```
|
||||
void registration_updated(M2MSecurity *const M2MServer& server)
|
||||
```
|
||||
|
||||
The `M2MSecurity *server_object` specifies with which mbed Device Server instance the client has just updated the registration and `M2MServer &server` contains the data related to mbed Device Server, including the Short ServerID and the client registration period.
|
||||
|
||||
_Failure_
|
||||
|
||||
If the update operation fails for some reason, you will receive the following callback:
|
||||
|
||||
```
|
||||
void error(M2MInterface::Error error)
|
||||
```
|
||||
|
||||
## The Deregister feature
|
||||
|
||||
The client can deregister from mbed Device Server when it no longer requires access to the server. When mbed Device Server receives the **Deregister** message it removes the device's registration information from its database. When the client needs mbed Device Server again, it has to register again.
|
||||
|
||||
To deregister your endpoint client:
|
||||
|
||||
If the endpoint has multiple server registrations, you need to provide the `server_object` of the server from which would like to deregister. If there is only one registration, you can pass `NULL` and the client will deregister from the default registration.
|
||||
|
||||
```
|
||||
M2MInterface::unregister_object(M2MSecurity *object);
|
||||
```
|
||||
|
||||
**Success or failure callback**
|
||||
|
||||
Because this is an asynchronous operation, you will receive the result of this operation through a callback defined in `m2minterfaceobserver.h` in your application.
|
||||
|
||||
_Success_
|
||||
|
||||
If the client is successfully deregistered from mbed Device Server, your application will receive the following callback:
|
||||
|
||||
```
|
||||
void object_unregistered(M2MSecurity *server_object)
|
||||
```
|
||||
|
||||
The `M2MSecurity *server_object` specifies from which mbed Device Server instance the client has just deregistered.
|
||||
|
||||
_Failure_
|
||||
|
||||
If the deregistration operation fails for some reason, you will receive the following callback:
|
||||
|
||||
```
|
||||
void error(M2MInterface::Error error)
|
||||
```
|
||||
|
||||
You will get more information about the error from the `error` parameter passed with the callback; use it to fix the source of the problem.
|
|
@ -0,0 +1,162 @@
|
|||
mbed Client data types
|
||||
======================
|
||||
|
||||
This chapter describes how the different data types are processed in the mbed Client and the REST API.
|
||||
|
||||
The following two aspects are considered:
|
||||
|
||||
- How the different data types should be passed to API on mbed Client.
|
||||
- How the data is received on REST API side, and how it is converted into right data type.
|
||||
|
||||
## Using mbed Client data types
|
||||
|
||||
When data is transferred from mbed Client to mbed Device Server, the following need to be kept in mind:
|
||||
|
||||
- mbed Client is based on CoAP client. The Resource values are represented as text/plain format.
|
||||
- Different data type values have to be converted into corresponding text/plain format.
|
||||
- For example, an integer value 100 is passed in a text buffer format of 100 and it appears on the web service side as 100 in text format.
|
||||
- The service must interpret this data to an appropriate format.
|
||||
|
||||
### Transferring integers from mbed Client to mbed Device Server
|
||||
|
||||
**Integer (from the application)**:
|
||||
|
||||
```
|
||||
int value = 1;
|
||||
M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::INTEGER, true);
|
||||
char buffer[20];
|
||||
int size = sprintf(buffer,"%d",value);
|
||||
instance->set_value((const uint8_t*)buffer, size);
|
||||
```
|
||||
|
||||
If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache:
|
||||
|
||||
```
|
||||
instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds).
|
||||
```
|
||||
|
||||
**Response on the REST API**:
|
||||
|
||||
```
|
||||
{"async-response-id":...{ "id" : "1131895768#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "MQ==", "ct" : "text/plain", "max-age" : 0 }
|
||||
```
|
||||
|
||||
- Base64 encoded value of the payload -> `MQ==`
|
||||
- Base64 decoded value of the payload -> `1`
|
||||
|
||||
<span class="notes">**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64.</span>
|
||||
|
||||
### Transferring a float value from mbed Client to mbed Device Server
|
||||
|
||||
**Float (from the application)**:
|
||||
|
||||
```
|
||||
float value = 1.0232f;
|
||||
M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::FLOAT, true);
|
||||
char buffer[20];
|
||||
int size = sprintf(buffer,"%f",_value);
|
||||
instance->set_value((const uint8_t*)buffer, size);
|
||||
```
|
||||
|
||||
If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache:
|
||||
|
||||
```
|
||||
instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds).
|
||||
```
|
||||
|
||||
**Response on the REST API**:
|
||||
|
||||
```
|
||||
{"async-response-id":...{ "id" : "1132945328#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "MS4wMjMyMDA=",
|
||||
"ct" : "text/plain", "max-age" : 0 }
|
||||
```
|
||||
|
||||
- Base64 encoded value of the payload -> `MS4wMjMyMDA=`
|
||||
- Base64 decoded value of the payload -> `1.023200`
|
||||
|
||||
<span class="notes">**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64.</span>
|
||||
|
||||
### Transferring a boolean value from mbed Client to mbed Device Server
|
||||
|
||||
**Boolean (from the application)**:
|
||||
|
||||
```
|
||||
bool value = true;
|
||||
M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::BOOLEAN, true);
|
||||
char buffer[20];
|
||||
int size = sprintf(buffer,"%d",_value);
|
||||
instance->set_value((const uint8_t*)buffer, size);
|
||||
```
|
||||
|
||||
If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache:
|
||||
|
||||
```
|
||||
instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds).
|
||||
```
|
||||
|
||||
**Response on the REST API**:
|
||||
|
||||
```
|
||||
{"async-response-id":….{ "id" : "1131895768#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "MQ==", "ct" : "text/plain", "max-age" : 0 }
|
||||
```
|
||||
|
||||
- Base64 encoded value of the payload -> `MQ==`
|
||||
- Base64 decoded value of the payload -> `1`
|
||||
|
||||
<span class="notes">**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64.</span>
|
||||
|
||||
### Transferring a string value from mbed Client to mbed Device Server
|
||||
|
||||
**String (from the application)**:
|
||||
|
||||
```
|
||||
M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::STRING, true);
|
||||
char buffer[10] = “Test Data”;
|
||||
instance->set_value((const uint8_t*)buffer, 10);
|
||||
```
|
||||
|
||||
If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache:
|
||||
|
||||
```
|
||||
instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds).
|
||||
```
|
||||
|
||||
**Response on the REST API**:
|
||||
|
||||
```
|
||||
{"async-response-id":... { "id" : "1133335779#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "VGVzdCBEYXRh",
|
||||
"ct" : "text/plain", "max-age" : 0 }
|
||||
```
|
||||
|
||||
- Base64 encoded value of the payload -> `VGVzdCBEYXRh`
|
||||
- Base64 decoded value of the payload -> `Test Data`
|
||||
|
||||
<span class="notes">**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64.</span>
|
||||
|
||||
### Transferring an opaque value from mbed Client to mbed Device Server
|
||||
|
||||
**Opaque(from the application)**:
|
||||
|
||||
```
|
||||
M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::OPAQUE, true);
|
||||
uint8_t buffer[12] = “Opaque Data”;
|
||||
instance->set_value(buffer, 12);
|
||||
```
|
||||
|
||||
If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache:
|
||||
|
||||
```
|
||||
instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds).
|
||||
```
|
||||
|
||||
**Response on the REST API**:
|
||||
|
||||
```
|
||||
{"async-response-id":... { "id" : "1134045351#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "T3BhcXVlIERhdGEA",
|
||||
"ct" : "application/octet-stream", "max-age" : 0 }
|
||||
```
|
||||
|
||||
- Base64 encoded value of the payload -> `T3BhcXVlIERhdGEA`
|
||||
- Base64 decoded value of the payload -> `Opaque Data`
|
||||
|
||||
<span class="notes">**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64.</span>
|
|
@ -0,0 +1,191 @@
|
|||
# The Device Management and Service Enabler feature
|
||||
|
||||
mbed Device Server uses the Device Management and Service Enabler to access Object Instances and Resources available on the client. The interface provides this access through the following operations:
|
||||
|
||||
- [Create](#the-create-operation)
|
||||
- Delete
|
||||
- [Read](#the-read-operation)
|
||||
- [Write](#the-write-operation)
|
||||
- [Write Attributes](#the-write-attributes-operation)
|
||||
- [Execute](#the-execute-operation)
|
||||
|
||||
Currently, support for the Create and Delete actions is limited to Object Instances.
|
||||
|
||||
The Device Management and Service Enabler Interface supports the following data types:
|
||||
|
||||
- Text: for Resources.
|
||||
- TLV: for Object and Object Instances.
|
||||
|
||||
## The Create operation
|
||||
|
||||
There are two types of resources you can create:
|
||||
|
||||
- Static: you set the value of the resource once and it does not change during the course of operations.
|
||||
- Dynamic: the value is expected to change during the course of operations. Therefore, the value is fetched from setter APIs every time the server requests a read operation.
|
||||
|
||||
Here is an example of creating a custom static Resource:
|
||||
|
||||
```
|
||||
#include "mbed-client/m2mobject.h"
|
||||
#include "mbed-client/m2mobjectinstance.h"
|
||||
#include "mbed-client/m2mresource.h"
|
||||
_object = M2MInterfaceFactory::create_object("Test");
|
||||
if(_object) {
|
||||
M2MObjectInstance* inst = _object->create_object_instance();
|
||||
if(inst) {
|
||||
inst->create_static_resource("S",
|
||||
"ResourceTest",
|
||||
STATIC_VALUE,
|
||||
sizeof(STATIC_VALUE)-1);
|
||||
```
|
||||
|
||||
And here is an example of creating a custom dynamic Resource:
|
||||
|
||||
```
|
||||
#include "mbed-client/m2mobject.h"
|
||||
#include "mbed-client/m2mobjectinstance.h"
|
||||
#include "mbed-client/m2mresource.h"
|
||||
_object = M2MInterfaceFactory::create_object("Test");
|
||||
if(_object) {
|
||||
M2MObjectInstance* inst = _object->create_object_instance();
|
||||
if(inst) {
|
||||
M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",true);
|
||||
char buffer[20];
|
||||
int size = sprintf(buffer,"%d",_value);
|
||||
res->set_operation(M2MBase::GET_PUT_ALLOWED);
|
||||
res->set_value((const uint8_t*)buffer,
|
||||
(const uint32_t)size);
|
||||
```
|
||||
|
||||
For more information on different resource functionalities, please check the [API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html) for the M2MObject, M2MObjectInstance and M2MResource classes.
|
||||
|
||||
## The Read operation
|
||||
|
||||
The Client API allows setting values to Resources, an array of Resource Instances, an Object Instance or all the Object Instances of an Object (TLV format supported). mbed Device Server can then read these values using the **Read** operation.
|
||||
|
||||
## The Write operation
|
||||
|
||||
The **Write** operation is used to overwrite the value of a Resource, an array of Resource Instances or multiple Resources from an Object Instance.
|
||||
|
||||
Whenever there is a valid `PUT` operation for any of the resources, the application will receive a callback:
|
||||
|
||||
```
|
||||
void value_updated(M2MBase *base, M2MBase::BaseType type)
|
||||
```
|
||||
Where `M2MBase` is the Object whose value has been updated and `M2MBase::BaseType` is the object type.
|
||||
|
||||
Check the code snippet below for usage.
|
||||
```
|
||||
void value_updated(M2MBase *base, M2MBase::BaseType type) {
|
||||
M2MResource* resource = NULL;
|
||||
M2MResourceInstance* res_instance = NULL;
|
||||
M2MObjectInstance* obj_instance = NULL;
|
||||
M2MObject* obj = NULL;
|
||||
String object_name = "";
|
||||
String resource_name = "";
|
||||
uint16_t object_instance_id = 0;
|
||||
uint16_t resource_instance_id = 0;
|
||||
if(base) {
|
||||
switch(base->base_type()) {
|
||||
case M2MBase::Object:
|
||||
obj = (M2MObject *)base;
|
||||
object_name = obj->name();
|
||||
break;
|
||||
case M2MBase::ObjectInstance:
|
||||
obj_instance = (M2MObjectInstance *)base;
|
||||
object_name = obj_instance->name();
|
||||
object_instance_id = obj_instance->instance_id();
|
||||
break;
|
||||
case M2MBase::Resource: {
|
||||
resource = (M2MResource*)base;
|
||||
object_name = resource->object_name();
|
||||
object_instance_id = resource->object_instance_id();
|
||||
resource_name = resource->name();
|
||||
printf("Value updated, object name %s, object instance id %d, resource name %s\r\n",
|
||||
resource->object_name().c_str(), resource->object_instance_id(), resource->name().c_str());
|
||||
}
|
||||
break;
|
||||
case M2MBase::ResourceInstance: {
|
||||
res_instance = (M2MResourceInstance*)base;
|
||||
object_name = res_instance->object_name();
|
||||
object_instance_id = res_instance->object_instance_id();
|
||||
resource_name = res_instance->name();
|
||||
resource_instance_id = res_instance->instance_id();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## The Write Attributes operation
|
||||
|
||||
Any readable Resource can have attributes that are considered during the [**Observe** operation](info_reporting.md#the-observe-feature). The following attributes are used:
|
||||
|
||||
- Minimum Period (pmin)
|
||||
- Maximum Period (pmax)
|
||||
- Greater Than (gt)
|
||||
- Less Than (lt)
|
||||
- Step (st)
|
||||
|
||||
mbed Device Server sets the endpoint attribute values that are used to determine when the endpoint sends the Resource value to the server.
|
||||
|
||||
Check the [LWM2M Specification](http://technical.openmobilealliance.org/Technical/technical-information/release-program/current-releases/oma-lightweightm2m-v1-0) for details of all the possible **Write Attributes** defined for different types of Objects and Resources.
|
||||
|
||||
## The Execute operation
|
||||
|
||||
mbed Device Server uses the **Execute** operation to perform an action. This operation can only be performed on individual Resources.
|
||||
|
||||
<span class="notes">**Note:** mbed Client returns an error when the **Execute** operation is received for Object Instances or Resource Instances.</span>
|
||||
|
||||
If you want to execute a piece of code in your application, you can pass a `POST` request from mbed Device Server.
|
||||
When your Resource receives the `POST` request, mbed Client parses the payload from the request and wraps it in the `M2MResource::M2MExecuteParameter` class. The class object is passed through the execute callback function.
|
||||
You can then typecast the `void*` argument into the corresponding `M2MResource::M2MExecuteParameter` and access the passed payload and its length through the given API. M2MResource::M2MExecuteParameter contains also information which object and object instance resource belongs to. Make sure that the payload sent through POST request is in `plain/text` format and that the content-type is set as “plain/text” on the POST request call.
|
||||
|
||||
Check the code snippet below for usage.
|
||||
|
||||
```
|
||||
#include "mbed-client/m2mobject.h"
|
||||
#include "mbed-client/m2mobjectinstance.h"
|
||||
#include "mbed-client/m2mresource.h"
|
||||
static void execute_function_2(void *argument) {
|
||||
if(argument) {
|
||||
M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
|
||||
int payload_length = param->get_argument_value_length();
|
||||
uint8_t* payload = param->get_argument_value();
|
||||
String object_name = param->get_argument_object_name();
|
||||
uint16_t object_instance_id = param->get_argument_object_instance_id();
|
||||
String resource_name = param->get_argument_resource_name();
|
||||
}
|
||||
|
||||
void M2MLWClient::execute_function(void *argument) {
|
||||
if(argument) {
|
||||
M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
|
||||
int payload_length = param->get_argument_value_length();
|
||||
uint8_t* payload = param->get_argument_value();
|
||||
String object_name = param->get_argument_object_name();
|
||||
uint16_t object_instance_id = param->get_argument_object_instance_id();
|
||||
String resource_name = param->get_argument_resource_name();
|
||||
}
|
||||
|
||||
_object = M2MInterfaceFactory::create_object("Test");
|
||||
if(_object) {
|
||||
M2MObjectInstance* inst = _object->create_object_instance();
|
||||
if(inst) {
|
||||
M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",true);
|
||||
char buffer[20];
|
||||
int size = sprintf(buffer,"%d",_value);
|
||||
res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
|
||||
res->set_value((const uint8_t*)buffer,
|
||||
(const uint32_t)size);
|
||||
res->set_execute_function(execute_callback(this,&M2MLWClient::execute_function));
|
||||
/* Overloaded function can be used If callback function is not in class scope.
|
||||
res->set_execute_function(&execute_function_2);
|
||||
*/
|
||||
```
|
||||
|
||||
The POST method allows the client to respond immediately with the updated payload value as a piggyback response. If you want to send the payload response to the server later (because the Execute operation may take longer time on device to complete), you can handle this through the API.
|
||||
|
||||
You can set the resource API `void set_delayed_response(bool)` to `true`. In this case, the POST request response to the server is an empty acknowledgment. When your resource is ready with the response, you can simply call `send_delayed_post_response()` on that resource and the client sends the latest resource value to the server as part of a separate response to the POST request. By default, `void set_delayed_response(bool)` is `false`, which means that the POST response returns the resource value as a piggyback payload immediately.
|
|
@ -0,0 +1,14 @@
|
|||
# Useful reading
|
||||
|
||||
[Getting started with mbed Device Connector](https://docs.mbed.com/docs/getting-started-with-mbed-device-connector/en/latest/) provides you:
|
||||
|
||||
- a generic introduction to mbed Device Connector.
|
||||
- a quick start guide for using mbed Device Connector.
|
||||
|
||||
[mbed Device Connector Web Interfaces](https://docs.mbed.com/docs/mbed-device-connector-web-interfaces/en/latest/) provides you:
|
||||
|
||||
- an overview to the Web Interfaces, explaining how the web applications interact with mbed Device Connector using the REST API.
|
||||
|
||||
[mbed Device Connector developer site](https://www.mbed.com/en/development/cloud/mbed-device-connector-service/)
|
||||
|
||||
- a web site for developers
|
|
@ -0,0 +1,15 @@
|
|||
About this document
|
||||
=====================
|
||||
|
||||
This document introduces the mbed Client and the use of its API. The document is divided into the following chapters:
|
||||
|
||||
- [**Introduction**](Introduction.md) is a brief introduction to the mbed Client and its features.
|
||||
- [**The Client Registration feature**](client_reg_dereg.md) introduces the Client Registration feature in detail.
|
||||
- [**The Device Management and Service Enabler feature**](dev_man_serv_enable.md) introduces the Device Management and Service Enabler feature in detail.
|
||||
- [**The Information Reporting feature**](info_reporting.md) introduces the Information Reporting feature in detail.
|
||||
- [**mbed Client data types**](data_types.md) describes how the different data types are processed in the mbed Client and the REST API.
|
||||
- [**How to use the mbed Client API**](Howto.md) contains detailed instructions on using the mbed Client API.
|
||||
- [**Porting mbed Client**](porting-guide.md) is meant for advanced users and tells how to build mbed Client and port it for different platforms.
|
||||
- [**Useful reading**](further-reading.md) links you to mbed Device Connector documentation and the developer site.
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# The Information Reporting feature
|
||||
|
||||
mbed Device Server uses the Information Reporting to observe any changes in a registered Resource on the client. The server registers to observe the Resource. When the Resource changes, it sends a notification with its new value to all servers who asked to observe it.
|
||||
|
||||
The interface supports the following sub-features:
|
||||
|
||||
## The Observe feature
|
||||
|
||||
mbed Device Server initiates an observation request to observe the changing value of either an Object, Object Instance or Resource.
|
||||
|
||||
<span class="tips">**Tip:** Related parameters for the **Observe** operation are described in the [Write Attributes](dev_man_serv_enable.md#write-attributes) section.</span>
|
||||
|
||||
## The Notify feature
|
||||
|
||||
The client sends the **Notify** operation to mbed Device Server during a valid observation on a Resource, when the notification conditions are met.
|
||||
|
||||
## Cancel
|
||||
|
||||
mbed Device Server sends the **Cancel Observation** operation to the client to end an observation relationship for an Object Instance or a Resource.
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
# Known Issues
|
||||
|
||||
## About this document
|
||||
|
||||
This is the list of known issues for the 15.11 release of [mbed Client](https://github.com/ARMmbed/mbed-client). We publish mbed-client as module in GitHub, and track open issues as tickets in the repository. That makes for an easy development flow, but doesn’t make it very easy for you to get a single view of all the issues that affect the whole release.
|
||||
|
||||
The purpose of this document is to provide that single view of all the key issues we are aware of. It isn’t a complete list; it’s a filtered and reviewed list, focusing on the issues we thought you’d want to be aware of. Each item explains the problem, as well as workarounds if those are possible. For items filed through GitHub, we’ve included a link to the issue so that you can follow the discussion and code - or even suggest a solution.
|
||||
|
||||
For more information about an issue, contact us on the [mbed forums](http://forums.mbed.com).
|
||||
|
||||
### Other information not in this document
|
||||
|
||||
We’re still very actively building mbed Client and the 15.11 release is a technology preview. As such there are some other limitations of the release that you can find described in the [release note](https://www.mbed.com/en/development/software/mbed-client/releases/mbed-client1511).
|
||||
|
||||
#### Important Note for Windows Users
|
||||
|
||||
If you are using this release on Microsoft Windows, please be advised that because of the way Windows handles filename and paths, you may have problems if you attempt to use this in a deep directory hierarchy with a long path name (e.g. `c:\some\very\long\path`). If you experience problems unpacking or building this release, please try it in a location with a shorter path before filing a bug. Thanks.
|
||||
|
||||
***
|
||||
### mbed Client API may not be fully interoperable with other LWM2M servers.
|
||||
|
||||
*Description*: mbed Client API is OMA LWM2M compatible. However, some features may not be fully interoperable against other open source LWM2M servers. This is the first release version and more features will be made interoperable over coming releases.
|
||||
|
||||
*Workaround*: mbed Client is compatible with mbed Device Connector Service, which can be tested at [https://connector.mbed.com](https://connector.mbed.com).
|
||||
|
||||
*Reported Issue*: ARM internal reference IOTCLT-366
|
||||
|
||||
*Priority*: Major
|
||||
|
||||
### mbed Client for Linux doesn't support IPv6 connectivity
|
||||
|
||||
*Description*: mbed Client for Linux platform currently works only for IPv4-enabled LWM2M server addresses. IPv6 address support is currently broken.
|
||||
|
||||
*Workaround*: mbed Client is compatible with mbed Device Connector Service which can be tested from [https://connector.mbed.com](https://connector.mbed.com) over IPv4 Address.
|
||||
|
||||
*Reported Issue*: https://github.com/ARMmbed/mbed-client-linux/issues/19
|
||||
|
||||
*Priority*: Major
|
||||
|
||||
### mbed Client will occasionally disconnect from LWM2M Server because of network errors
|
||||
|
||||
*Description*: If mbed Client is kept running for long durations (over 24 hours) with long lifetime values, it occasionally goes offline due to unstable network conditions - and doesn't send periodic updates to LWM2M server.
|
||||
|
||||
*Workaround*: Set the periodic lifetime value to less than 15 minutes if you want to run stability tests. Also, implement a network error handling mechanism on the application side, to handle `error()` callbacks received from the mbed-client library.
|
||||
|
||||
*Reported Issue*: ARM internal reference IOTCLT-206
|
||||
|
||||
*Priority*: Major
|
||||
|
||||
### mbed Client might experience a memory leak when running for long durations
|
||||
|
||||
*Description*: mbed Client might have memory leak issues when left running for longer than 12 hours.
|
||||
|
||||
*Workaround*: None
|
||||
|
||||
*Reported Issue*: ARM internal reference IOTCLT-290
|
||||
|
||||
*Priority*: Major
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# mbed Client Known Issues
|
||||
|
||||
## About this document
|
||||
|
||||
This is the list of known issues for the [16.03 release of mbed Client](Release_Note.md).
|
||||
|
||||
We publish mbed Client as a collection of modules on GitHub. Issues are raised in the specific repositories and then tracked internally.
|
||||
|
||||
The purpose of this document is to provide a single view of the outstanding key issues that have not been addressed for this release. As such it is a filtered and reviewed list based on priority and potential impact. Each item summarises the problem and includes any known workarounds, along with a link to the GitHub issue (if applicable). We welcome any comments or proposed solutions.
|
||||
|
||||
For more information about an issue, contact us on the [forums](http://forums.mbed.com).
|
||||
|
||||
## Additional information
|
||||
|
||||
For further information regarding this release please refer to the release notes referenced above.
|
||||
|
||||
# Known issues
|
||||
|
||||
## mbed Client API does not support float data type
|
||||
* **Description**: mbed Client API doesn't work correctly with float data type, as it is disabled in the FRDM target configuration.
|
||||
* **Workaround**: No workaround at the moment. There will be a fix for target-mbed-gcc soon, which will enable float data type usage.
|
||||
* **Reported Issue**: ARM internal reference IOTCLT-649
|
||||
* **Priority**: Critical
|
||||
|
||||
## mbed-trace module has a missing test dependency on Linux and Windows build targets.
|
||||
* **Description**: The mbed-trace library has a test-dependency on cpputest, which is not yet available in the yotta registry. Since you can't download this dependency, "yt test" for mbed-trace will fail.
|
||||
* **Workaround**: No workaround available.
|
||||
* **Reported Issue**: ARM internal reference IOTCLT-650
|
||||
* **Priority**: Critical
|
||||
|
||||
## mbed Client API may not be fully interoperable with other LWM2M servers.
|
||||
* **Description**: mbed Client API is OMA LWM2M compatible. However, some features may not be fully interoperable against other open source LWM2M servers.
|
||||
* **Workaround**: mbed Client is compatible with mbed Device Connector Service, which can be tested at [https://connector.mbed.com](https://connector.mbed.com).
|
||||
* **Reported Issue**: ARM internal reference IOTCLT-366
|
||||
* **Priority**: Major
|
||||
|
||||
## mbed Client example application may drop off from Connector if kept running for a long duration.
|
||||
* **Description**: mbed Client example application sometimes drops off from Connector after a few hours. This may happen when mbed Client is kept running for long durations (over 24 hours) - it occasionally goes offline due to unstable network conditions, and doesn't send periodic updates to Connector.
|
||||
* **Workaround**: Set the periodic lifetime value to less than 15 minutes if you want to run stability tests. Also, implement a network error handling mechanism on the application side, to handle error() callbacks received from the mbed-client library.
|
||||
* **Reported Issue**: [https://github.com/ARMmbed/mbed-client-examples/issues/52](https://github.com/ARMmbed/mbed-client-examples/issues/52)
|
||||
* **Priority**: Major
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
# Release note for mbed Client 16.03
|
||||
|
||||
mbed Client is an OS-agnostic embedded software library that provides the means to connect and manage constrained embedded devices to web applications through mbed Device Server.
|
||||
|
||||
## Release summary
|
||||
|
||||
This is an iterative release of mbed Client, which is available for mbed OS as well as for Ubuntu-like Linux distributions. We’re continuously maturing mbed Client and adding new features to mbed Client.. This release builds on the Technology Preview 15.11 release through the introduction of new APIs, enhanced functionalities and bug fixes.
|
||||
## Collaboration
|
||||
We’re building mbed Client as a collaborative project, bringing together industry and open source community contributions. If you’d like to work on mbed Client with us, we’d encourage you [to pitch in](https://github.com/ARMmbed/mbed-os/blob/master/CONTRIBUTING.md). With this technology preview we’re ready to start receiving contributions back from the community.
|
||||
## Documentation
|
||||
To get started with mbed Client, please visit our [getting started guide](https://docs.mbed.com/docs/mbed-client-guide/en/latest/).
|
||||
# Changes since last release
|
||||
|
||||
## New APIs and functions
|
||||
|
||||
* New APIs:
|
||||
* Setting the max-age of a resource value. See [https://tools.ietf.org/html/draft-ietf-core-coap-09#section-5.10.6](https://tools.ietf.org/html/draft-ietf-core-coap-09#section-5.10.6).
|
||||
* Omitting registered resources' URI path from the registration message's body (which is sent from the client to the server).
|
||||
* Allowing the client to send a delayed response to POST requests. See [https://tools.ietf.org/html/draft-ietf-core-coap-09#section-5.2.2](https://tools.ietf.org/html/draft-ietf-core-coap-09#section-5.2.2).
|
||||
* Getting Object and Object Instance information from Resource Object.
|
||||
* Added a new class for handling arguments received from POST method for Resource.
|
||||
* Enabled CoAP Blockwise payload handling by client. See [https://tools.ietf.org/html/draft-ietf-core-block-08#section-2](https://tools.ietf.org/html/draft-ietf-core-block-08#section-2).
|
||||
* Added support for handling observation cancellation through a RESET message from Device Connector Server.
|
||||
* Disabled Bootstrap API functionality from source code.
|
||||
|
||||
## Bug fixes
|
||||
|
||||
1. Multiple fixes related to Object, Object Instance and Resource Observation.
|
||||
2. Multiple fixes related to Write Attributes parameter handling for Object, Object Instance and Resource.
|
||||
3. Multiple fixes for creating and deleting object instances.
|
||||
4. Fixes related to sending notifications from multiple resource levels.
|
||||
5. Fixing memory leaks.
|
||||
6. Fixing mbed Client IPv6 connectivity for Linux.
|
||||
7. Memory handling in the ``m2mstring`` class.
|
||||
8. Fix for preventing the client from sending multiple confirmable messages on mbed OS.
|
||||
|
||||
# Modules versions
|
||||
|
||||
mbed Client is available as part of mbed OS or as a standalone component for Ubuntu-like Linux distributions.
|
||||
|
||||
The yotta modules & versions released for these different product configurations are listed below.
|
||||
|
||||
mbed Client as part of mbed OS:
|
||||
|
||||
1. mbed-client-quickstart (example)
|
||||
1. mbed-client - 1.6.x
|
||||
1. mbed-client-c - 2.2.x
|
||||
1. nanostack-libservice - 3.1.x
|
||||
1. mbed-client-mbedtls - 1.0.x
|
||||
1. mbedtls - 2.2.0
|
||||
1. mbed-client-mbed-os - 1.1.x
|
||||
1. mbed-client-examples
|
||||
1. target-frdm-k64f-gcc - 2.0.0
|
||||
|
||||
|
||||
mbed Client as a standalone distribution for Ubuntu-like Linux distributions:
|
||||
|
||||
1. mbed-client-linux-example
|
||||
1. mbed-client - 1.6.x
|
||||
1. mbed-client-c - 2.2.x
|
||||
1. nanostack-libservice - 3.1.x
|
||||
1. mbed-client-mbedtls - 1.0.x
|
||||
1. mbedtls - 2.2.0
|
||||
1. mbed-client-linux - 1.1.x
|
||||
1. target-x86-linux-native - 1.0.0
|
||||
1. target-linux-native - 1.0.0
|
||||
|
||||
|
||||
### Known issues
|
||||
|
||||
The known issues list for this release is available as [a separate document](Known_Issues.md)
|
||||
|
||||
### Other ways of accessing this release
|
||||
|
||||
|
||||
We prefer that you access and collaborate with mbed Client online. However, the release may also be downloaded as a [tar archive file](https://mbed-media.mbed.com/filer_public/7b/75/7b75d9fe-bf15-4818-b959-c54e11e767af/mbed-client-1603.zip).
|
||||
|
||||
|
|
@ -0,0 +1,558 @@
|
|||
<span class="notes">**Note:** To port mbed Client, you need to [install yotta and its dependencies](https://github.com/ARMmbed/yotta/blob/master/docs/index.md).</span>
|
||||
|
||||
# mbed Client structure and build process
|
||||
|
||||
<span class="tips">**Tip:** Before embarking on your own port, you should build the core mbed Client for an existing compilation target to get an understanding of how the mbed Client builds.</span>
|
||||
|
||||
mbed Client is structured as a set of modules. Each module declares which other modules it depends on. When you build a module, our build system `yotta` looks at these dependencies and installs the necessary modules before completing the build.
|
||||
|
||||
This is also the process to build applications for the mbed Client (including the example application in the release). The application declares dependencies on the mbed Client and when it is built, `yotta` ensures that the modules (and anything that they depend on, recursively) are present before building.
|
||||
|
||||
In general, `yotta` downloads and installs the necessary modules over the internet from the public yotta Registry (which saves published versions of modules) or from a specified source control URL.
|
||||
|
||||
# Components of mbed Client
|
||||
|
||||
## Component software modules
|
||||
|
||||
mbed Client consists of one main component. More major components will be added in future development phases:
|
||||
|
||||
* `mbed-client` is the core mbed Client, providing C++ APIs for the mbed Client.
|
||||
|
||||
This module depends on further internal modules:
|
||||
|
||||
```
|
||||
mbed-client x.x.x
|
||||
|
|
||||
|_mbed-client-c x.x.x
|
||||
| |_mbed-client-libservice x.x.x
|
||||
|
|
||||
|_mbed-client-linux x.x.x
|
||||
```
|
||||
|
||||
To list the dependency trees, use the [`yotta list --all` command](http://docs.yottabuild.org/reference/commands.html).
|
||||
|
||||
<span class="notes">**Note**: In this case, we have listed the dependencies for the `x86-linux-native` compilation target. Different modules are needed for different compilation targets.</span>
|
||||
|
||||
We are using the [mbed Client Linux example](https://github.com/ARMmbed/mbed-client-linux-example) in this document. You can see that it depends directly only on the `mbed-client` and `mbed-client-linux` modules. These modules depend internally on various other modules.
|
||||
|
||||
```
|
||||
mbed-client-linux-example x.x.x
|
||||
|
|
||||
|_mbed-client x.x.x
|
||||
|
|
||||
|_mbed-client-c x.x.x
|
||||
| |_mbed-client-libservice x.x.x
|
||||
|
|
||||
|_mbed-client-linux x.x.x
|
||||
```
|
||||
|
||||
## Compilation targets
|
||||
|
||||
To compile for a target board, you need a [target description](http://docs.yottabuild.org/tutorial/targets.html) that describes how to compile for the target.
|
||||
|
||||
The `mbed-client` module uses the platform name that each target defines to choose which `mbed-client-<platform-name>` module to depend on to provide the platform-specific implementation.
|
||||
|
||||
# Porting mbed Client to a different platform
|
||||
|
||||
To port mbed Client to a new platform:
|
||||
|
||||
1. [Request for a development repository](#requesting-for-a-development-repository).
|
||||
2. [Create a yotta compilation target for your board](#creating-a-yotta-compilation-target).
|
||||
3. [Implement the `mbed-client-xxx` module for your target platform](#implementing-mbed-client-xxx).
|
||||
4. [Modify the `module.json` of the `mbed-client` module](#modifying-the-json-file-in-the-mbed-client-module).
|
||||
5. [Verify that your implementation is correct](#testing-and-verification).
|
||||
|
||||
The `yotta` build system is designed for easy reuse of generic modules. If you intend to support multiple platforms that share common features, we recommend moving the common functionality into a separate module and use it for each platform.
|
||||
|
||||
## Requesting for a development repository
|
||||
|
||||
We provide private git repositories to our partners porting mbed Client. Only the members of the mbed Client team and relevant partner contacts and engineers have access to these repositories.
|
||||
|
||||
When you contact `support@mbed.org`, a repository will be created for your module. You also need to provide the target description of your board as follows:
|
||||
|
||||
- **`mbed-client-<platform-name>`** is the module that provides the `mbed-client-xxx` implementation for your platform. You may choose to split it into further modules in the future, to enable sharing of code, but we recommend that you implement the port for your first board in this module itself.
|
||||
|
||||
- **`target-<targetname>`** contains the yotta target description of the target you are porting to. This is usually your platform name.
|
||||
|
||||
## Creating a yotta compilation target
|
||||
|
||||
An example on compiling for linux target can be found in the `yotta_targets` directory of [the example application] (https://github.com/ARMmbed/mbed-client-linux-example).
|
||||
|
||||
Please, refer to the [yotta documentation](http://yottadocs.mbed.com/tutorial/targets.html) for setting up your compilation target.
|
||||
|
||||
1.To make your target available locally (without publishing it), you use the `yotta link-target` command to link it into the global install targets directory:
|
||||
|
||||
```
|
||||
# in the directory of your target:
|
||||
yotta link-target
|
||||
```
|
||||
|
||||
2.Use `yotta link-target <targetname>` command to make the globally linked target available when compiling another module.
|
||||
|
||||
3.Use the `yotta target <targetname>` command to select your target for the compilation.
|
||||
|
||||
## Implementing mbed-client-xxx
|
||||
|
||||
Clone your `mbed-client-<your-platform-name>` module and `mbed-client` modules from GitHub.
|
||||
|
||||
The `mbed-client-<your-platform-name>` module needs to provide a socket and timer implementation for your target platform. The `mbed-client-xxx` module should include files `m2mconnectionhandler.h`and `m2mtimer.h` from `mbed-client` and implement a corresponding `.cpp` file that points to the platform-specific private implementations of the timer and the socket.
|
||||
|
||||
<span class="notes">**Note**: Private implementation classes **must** be named as `M2MConnectionHandlerPimpl` and `M2MTimerPimpl`, because of forward declarations.</span>
|
||||
|
||||
An example of mbed-client-platform:
|
||||
|
||||
```
|
||||
|_module.json
|
||||
|
|
||||
|_mbed-client-platform
|
||||
| |_m2mconnectionhandlerpimpl.h
|
||||
| |_m2mtimerpimpl.h
|
||||
|
|
||||
|_source
|
||||
|_m2mconnectionhandler.cpp
|
||||
|_m2mconnectionhandlerpimpl.cpp
|
||||
|_m2mtimer.cpp
|
||||
|_m2mtimerpimpl.cpp
|
||||
```
|
||||
|
||||
To make your module available to other modules that you want to build, you need to use the [`yotta link`](http://docs.yottabuild.org/reference/commands.html#yotta-link) command to link it to the module where you want to test it out.
|
||||
|
||||
For example, to use your local your in-development mbed-client implementation, use the command `yotta link mbed-client-xxx` in the main `mbed-client` module.
|
||||
|
||||
```
|
||||
# in mbed-client, link your module:
|
||||
yotta link mbed-client-xxx
|
||||
```
|
||||
|
||||
You can also just commit and push your untested code to GitHub, but it is always a good idea to test before committing.
|
||||
|
||||
Your `mbed-client-xxx` module must provide a platform-specific implementation for the mbed-client. The APIs that need porting are defined in the `mbed-client-linux` module. The header files contain documentation alongside the declaration of each function, where the function is described along with its parameters and return value.
|
||||
|
||||
There are two header files that require porting for your platform:
|
||||
|
||||
- `m2mconnectionhandler.h`
|
||||
- `m2mtimer.h`
|
||||
|
||||
To see how this is done in Linux, check the `mbed-client-linux` module from the mbed [Client Linux Example](https://github.com/ARMmbed/mbed-client-linux-example).
|
||||
|
||||
### Implementing the M2MConnectionHandler class for your platform
|
||||
|
||||
```
|
||||
/*
|
||||
* Copyright (c) 2015 ARM. All rights reserved.
|
||||
*/
|
||||
#ifndef M2M_CONNECTION_HANDLER_H__
|
||||
#define M2M_CONNECTION_HANDLER_H__
|
||||
|
||||
#include "mbed-client/m2mconfig.h"
|
||||
#include "mbed-client/m2minterface.h"
|
||||
#include "mbed-client/m2mconnectionobserver.h"
|
||||
#include "nsdl-c/sn_nsdl.h"
|
||||
|
||||
/**
|
||||
* \brief M2MConnectionHandler.
|
||||
* This class handles the socket connection for the LWM2M Client.
|
||||
*/
|
||||
|
||||
class M2MConnectionHandler {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @enum ConnectionError
|
||||
* This enum defines an error that can come from
|
||||
* socket read and write operation.
|
||||
*/
|
||||
typedef enum {
|
||||
CONNECTION_ERROR_WANTS_READ = -1000,
|
||||
CONNECTION_ERROR_WANTS_WRITE = -1001,
|
||||
ERROR_NONE = 0,
|
||||
SSL_CONNECTION_ERROR,
|
||||
SOCKET_READ_ERROR,
|
||||
SOCKET_SEND_ERROR,
|
||||
SOCKET_ABORT,
|
||||
DNS_RESOLVING_ERROR,
|
||||
SSL_HANDSHAKE_ERROR
|
||||
}ConnectionError;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
*/
|
||||
M2MConnectionHandler(M2MConnectionObserver &observer,
|
||||
M2MConnectionSecurity* sec,
|
||||
M2MInterface::BindingMode mode,
|
||||
M2MInterface::NetworkStack stack);
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
*/
|
||||
~M2MConnectionHandler();
|
||||
|
||||
/**
|
||||
* \brief This binds the socket connection.
|
||||
* \param listen_port Port to be listened to for an incoming connection.
|
||||
* \return True if successful, else false.
|
||||
*/
|
||||
bool bind_connection(const uint16_t listen_port);
|
||||
|
||||
/**
|
||||
* \brief This resolves the server address. Output is
|
||||
* returned through a callback.
|
||||
* \param String The server address.
|
||||
* \param uint16_t The server port.
|
||||
* \param ServerType The server type to be resolved.
|
||||
* \param security The M2MSecurity object that determines which
|
||||
* type of secure connection will be used by the socket.
|
||||
* \return True if address is valid, else false.
|
||||
*/
|
||||
bool resolve_server_address(const String& server_address,
|
||||
const uint16_t server_port,
|
||||
M2MConnectionObserver::ServerType server_type,
|
||||
const M2MSecurity* security);
|
||||
|
||||
/**
|
||||
* \brief Sends data to the connected server.
|
||||
* \param data_ptr The data to be sent.
|
||||
* \param data_len The length of data to be sent.
|
||||
* \param address_ptr The address structure to which the data needs to be sent.
|
||||
* \return True if data is sent successfully, else false.
|
||||
*/
|
||||
bool send_data(uint8_t *data_ptr,
|
||||
uint16_t data_len,
|
||||
sn_nsdl_addr_s *address_ptr);
|
||||
|
||||
/**
|
||||
* \brief Listens to the incoming data from a remote server.
|
||||
* \return True if successful, else false.
|
||||
*/
|
||||
bool start_listening_for_data();
|
||||
|
||||
/**
|
||||
* \brief Stops listening to the incoming data.
|
||||
*/
|
||||
void stop_listening();
|
||||
|
||||
/**
|
||||
* \brief Sends directly to the socket. This is used by
|
||||
* security classes to send the data after it has been encrypted.
|
||||
* \param buf Buffer to send.
|
||||
* \param len The length of the buffer.
|
||||
* \return Number of bytes sent or -1 if failed.
|
||||
*/
|
||||
int send_to_socket(const unsigned char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Receives directly from the socket. This
|
||||
* is used by the security classes to receive raw data to be decrypted.
|
||||
* \param buf Buffer to send.
|
||||
* \param len The length of the buffer.
|
||||
* \return Number of bytes read or -1 if failed.
|
||||
*/
|
||||
int receive_from_socket(unsigned char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Closes the open connection.
|
||||
*/
|
||||
void close_connection();
|
||||
|
||||
/**
|
||||
* \brief Error handling for DTLS connectivity.
|
||||
* \param error Error code from the TLS library.
|
||||
*/
|
||||
void handle_connection_error(int error);
|
||||
|
||||
/**
|
||||
* \brief Sets the network interface handler that is used by client to connect
|
||||
* to a network over IP..
|
||||
* \param handler A network interface handler that is used by client to connect.
|
||||
* This API is optional but provides a mechanism for different platforms to
|
||||
* manage usage of underlying network interface by client.
|
||||
*/
|
||||
void set_platform_network_handler(void *handler = NULL);
|
||||
|
||||
/**
|
||||
* \brief Claims mutex to prevent thread clashes
|
||||
* in multithreaded environment.
|
||||
*/
|
||||
void claim_mutex();
|
||||
|
||||
/**
|
||||
* \brief Releases mutex to prevent thread clashes
|
||||
* in multithreaded environment.
|
||||
*/
|
||||
void release_mutex();
|
||||
|
||||
private:
|
||||
|
||||
M2MConnectionObserver &_observer;
|
||||
M2MConnectionHandlerPimpl *_private_impl;
|
||||
|
||||
friend class Test_M2MConnectionHandler;
|
||||
friend class Test_M2MConnectionHandler_mbed;
|
||||
friend class Test_M2MConnectionHandler_linux;
|
||||
friend class M2MConnection_TestObserver;
|
||||
};
|
||||
|
||||
#endif //M2M_CONNECTION_HANDLER_H__
|
||||
|
||||
```
|
||||
|
||||
Please note that some of these functions are asynchronous in nature and some are expecting a callback from the network. For example, receiving data from a socket needs to be communicated back to `mbed-client` so that the library can act on the data received. The callback comes through the Observer class defined in `M2MConnectionObserver`.
|
||||
|
||||
The file `m2mconnectionobserver.h` is present in `mbed-client`. To see how the callback needs to be called, check the implementation in `m2mconnectionhandlerpimpl.cpp` in `mbed-client-linux`.
|
||||
|
||||
```
|
||||
/*
|
||||
* Copyright (c) 2015 ARM. All rights reserved.
|
||||
*/
|
||||
#ifndef M2M_CONNECTION_OBSERVER_H__
|
||||
#define M2M_CONNECTION_OBSERVER_H__
|
||||
|
||||
#include "mbed-client/m2minterface.h"
|
||||
|
||||
/**
|
||||
* @brief Observer class for informing socket activity to the state machine
|
||||
*/
|
||||
|
||||
class M2MConnectionObserver
|
||||
{
|
||||
|
||||
public :
|
||||
|
||||
/**
|
||||
* \enum ServerType, Defines the type of the
|
||||
* server that the client wants to use.
|
||||
*/
|
||||
typedef enum {
|
||||
Bootstrap,
|
||||
LWM2MServer
|
||||
}ServerType;
|
||||
|
||||
/**
|
||||
* \brief The M2MSocketAddress struct.
|
||||
* Unified container for holding socket address data
|
||||
* across different platforms.
|
||||
*/
|
||||
struct SocketAddress{
|
||||
M2MInterface::NetworkStack _stack;
|
||||
void *_address;
|
||||
uint8_t _length;
|
||||
uint16_t _port;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Indicates that data is available from socket.
|
||||
* \param data The data read from the socket.
|
||||
* \param data_size The length of the data read from the socket.
|
||||
* \param address The address of the server where the data is coming from.
|
||||
*/
|
||||
virtual void data_available(uint8_t* data,
|
||||
uint16_t data_size,
|
||||
const M2MConnectionObserver::SocketAddress &address) = 0;
|
||||
|
||||
/**
|
||||
* \brief Indicates an error occured in socket.
|
||||
* \param error_code The error code from socket, it cannot be used any further.
|
||||
* \param retry Indicates whether to re-establish connection.
|
||||
*/
|
||||
virtual void socket_error(uint8_t error_code, bool retry = true) = 0;
|
||||
|
||||
/**
|
||||
* \brief Indicates that the server address resolving is ready.
|
||||
* \param address The resolved socket address.
|
||||
* \param server_type The type of the server.
|
||||
* \param server_port The port of the resolved server address.
|
||||
*/
|
||||
virtual void address_ready(const M2MConnectionObserver::SocketAddress &address,
|
||||
M2MConnectionObserver::ServerType server_type,
|
||||
const uint16_t server_port) = 0;
|
||||
|
||||
/**
|
||||
* \brief Indicates that data has been sent successfully.
|
||||
*/
|
||||
virtual void data_sent() = 0;
|
||||
};
|
||||
|
||||
#endif // M2M_CONNECTION_OBSERVER_H__
|
||||
|
||||
```
|
||||
|
||||
### Implementing M2MTimer class for your platform
|
||||
|
||||
This class provides the periodic timer functionality for your platform.
|
||||
|
||||
```
|
||||
/*
|
||||
* Copyright (c) 2015 ARM. All rights reserved.
|
||||
*/
|
||||
#ifndef M2M_TIMER_H
|
||||
#define M2M_TIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class M2MTimerObserver;
|
||||
/**
|
||||
* @brief M2MTimerImpl
|
||||
* Private implementation class for timer, this can be
|
||||
* modified based on the board on which mbed Client needs
|
||||
* to be used.
|
||||
*/
|
||||
class M2MTimerImpl
|
||||
{
|
||||
private:
|
||||
|
||||
// Prevents the use of assignment operator
|
||||
M2MTimer& operator=(const M2MTimer& other);
|
||||
|
||||
// Prevents the use of copy constructor
|
||||
M2MTimer(const M2MTimer& other);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
M2MTimer(M2MTimerObserver& _observer);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~M2MTimer();
|
||||
|
||||
/**
|
||||
* Starts timer
|
||||
* @param interval Timer's interval in milliseconds
|
||||
* @param single_shot defines if timer is ticked
|
||||
* once or is it restarted everytime timer expires.
|
||||
*/
|
||||
void start_timer(uint64_t interval, bool single_shot = true);
|
||||
|
||||
/**
|
||||
* @brief Starts timer in DTLS manner.
|
||||
* @param intermediate_interval Intermediate interval to use, must be smaller than tiotal (usually 1/4 of total).
|
||||
* @param total_interval Total interval to use, this is the timeout value of a DTLS packet.
|
||||
* @param type Type of the timer
|
||||
*/
|
||||
void start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval,
|
||||
M2MTimerObserver::Type type = M2MTimerObserver::Dtls);
|
||||
|
||||
/**
|
||||
* Stops timer.
|
||||
* This cancels the ongoing timer.
|
||||
*/
|
||||
void stop_timer();
|
||||
|
||||
/**
|
||||
* @brief Checks if the intermediate interval has passed.
|
||||
* @return true if interval has passed, false otherwise.
|
||||
*/
|
||||
bool is_intermediate_interval_passed();
|
||||
|
||||
/**
|
||||
* @brief Checks if the total interval has passed.
|
||||
* @return true if interval has passed, false otherwise.
|
||||
*/
|
||||
bool is_total_interval_passed();
|
||||
|
||||
};
|
||||
|
||||
#endif // M2M_TIMER_H
|
||||
```
|
||||
|
||||
The timer API functions are asynchronous in nature and whenever a timer event is available, `mbed-client` is notified, so that the library can act on the _timer expired_ signal. The callback is received through an Observer class defined in `M2MTimerObserver` .
|
||||
|
||||
The file `m2mtimerobserver.h` is present in `mbed-client`. To see how the callback needs to be called, check the implementation in `m2mtimerimpl.cpp` in `mbed-client-linux`.
|
||||
|
||||
```
|
||||
/*
|
||||
* Copyright (c) 2015 ARM. All rights reserved.
|
||||
*/
|
||||
#ifndef M2M_TIMER_OBSERVER_H
|
||||
#define M2M_TIMER_OBSERVER_H
|
||||
|
||||
/**
|
||||
* Observer class for informing the parent class of the timer expiry.
|
||||
*/
|
||||
class M2MTimerObserver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \enum Defines the types of timer
|
||||
* that can be created for mbed Client.
|
||||
*/
|
||||
typedef enum {
|
||||
Notdefined,
|
||||
Registration,
|
||||
NsdlExecution,
|
||||
PMinTimer,
|
||||
PMaxTimer,
|
||||
Dtls,
|
||||
QueueSleep,
|
||||
RetryTimer
|
||||
}Type;
|
||||
|
||||
/**
|
||||
* \brief Indicates that the timer has expired.
|
||||
* \param type The type of the timer that has expired.
|
||||
*/
|
||||
virtual void timer_expired(M2MTimerObserver::Type type =
|
||||
M2MTimerObserver::Notdefined) = 0;
|
||||
};
|
||||
|
||||
#endif // M2M_TIMER_OBSERVER_H
|
||||
```
|
||||
|
||||
## Modifying the `json` file in the `mbed-client` module
|
||||
|
||||
You need to add your target name to `module.json` so that when you set `yt target <platform>`, yotta can resolve the dependency correctly and link the main library with your module.
|
||||
|
||||
Two platforms, mbed OS and Linux, are already supported. You just need to add your module support after that.
|
||||
|
||||
```
|
||||
{
|
||||
"name": "mbed-client",
|
||||
"version": "1.12.0",
|
||||
"description": "Mbed Client API",
|
||||
"private": true,
|
||||
"keywords": [],
|
||||
"author": "XXX XXX <xxx.xxx@xxx.com>",
|
||||
"homepage": "https://github.com/ARMmbed/mbed-client",
|
||||
"licenses": [
|
||||
{
|
||||
"url": "https://spdx.org/licenses/Apache-2.0",
|
||||
"type": "Apache-2.0"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"mbed-client-c": "^2.0.0"
|
||||
},
|
||||
"targetDependencies": {
|
||||
"arm": {
|
||||
"mbed-client-mbed": "^3.0.0"
|
||||
},
|
||||
"linux": {
|
||||
"mbed-client-linux": "^3.0.0"
|
||||
},
|
||||
"<your platform as defined in target.json>" : {
|
||||
"mbed-client-platform": "<published version , can be done later, first link locally as explained in the steps above>"
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing and verification
|
||||
|
||||
You can build your mbed-client port immediately:
|
||||
|
||||
```
|
||||
# use the target we previously made locally available (not necessary if your target has been published):
|
||||
yotta link-target <yourtargetname>
|
||||
# build!
|
||||
yotta build
|
||||
```
|
||||
|
||||
A `helloworld-mbedclient` program will be produced inside the `build/<yourtargetname>/test/` directory. This test application may require some changes to compile and run for your platform. Check for compilation errors. If you find any, fix the test application for your testing.
|
||||
|
||||
Follow the `readme` [instructions](https://github.com/ARMmbed/mbed-client-linux-example) of the `mbed-client-linux` example to see what the test application can do.
|
|
@ -0,0 +1,56 @@
|
|||
# mbed Client 15.11 Technology Preview Release Note
|
||||
|
||||
This is the first Technology Preview of mbed Client, which is available for mbed OS as well as Linux. We’re actively working on mbed Client and we expect to make exciting changes in the next six months. We’re making this technology preview available so you can see the trajectory we’re on. Our focus in this release is on laying the foundation for mbed Client development and collaboration, particularly core tools, technology and testing.
|
||||
|
||||
We expect mbed Client developers to be able to access, build and run example projects and to explore the underlying code.
|
||||
|
||||
## About this release
|
||||
|
||||
Note that this is a technology preview release, which means that this release is not yet suitable for volume production use. The software is still maturing, and a number of things may change, including module names, repository URLs, APIs, header file names and configuration parameters. We'll try to mitigate the impact that these changes have on your code where possible.
|
||||
|
||||
Note that in this release we're changing our version numbering scheme for mbed Client releases, to a calendar-based (year and month YY.MM) scheme. This release (15.11) has previously been called 3.0 in some communications.
|
||||
|
||||
## Collaboration
|
||||
|
||||
We’re building mbed Client as a collaborative project, bringing together industry and open source community contributions. If you’d like to work on mbed Client with us, we’d encourage you [to pitch in](https://github.com/ARMmbed/mbed-os/blob/master/CONTRIBUTING.md). With this technology preview we’re ready to start receiving contributions back from the community.
|
||||
|
||||
## Documentation
|
||||
|
||||
To get started with mbed Client, please visit our [getting started guide](https://docs.mbed.com/docs/mbed-client-guide/en/latest/).
|
||||
|
||||
## Changes since the last release
|
||||
|
||||
This section documents the changes between this release and the earlier mbed Client Beta (15.09) release.
|
||||
|
||||
This release contains the following new features:
|
||||
Securely connect to mbed Device Server (mbed DS) over TCP connection through TLS. The supported secure connection includes Certificate mode. We still support non-secure connection mode for fast development and debugging.
|
||||
|
||||
New LWM2M Firmware Object class preview for application development.
|
||||
|
||||
## Known issues
|
||||
|
||||
The known issues for this release are described [on GitHub](https://github.com/ARMmbed/mbed-client/blob/master/docs/known-issues-mbed-client1511.md).
|
||||
|
||||
## Other ways of accessing this release
|
||||
|
||||
We prefer that you access and collaborate with mbed Client online. However, the release may also be downloaded as an archive [on mbed.com](https://www.mbed.com/en/development/software/mbed-client/releases/mbed-client1511/).
|
||||
|
||||
# Module versions in this release
|
||||
|
||||
This release comprises the following yotta modules and their versions:
|
||||
|
||||
|
||||
| Module | Version |
|
||||
|----------------------------------|------------|
|
||||
| `mbed-client` | 1.2.1 |
|
||||
| `mbed-client-c` | 1.1.1 |
|
||||
| `mbed-client-libservice` | 3.0.8 |
|
||||
| `mbed-client-linux` | 1.1.0 |
|
||||
| `mbed-client-linux-example` | 1.0.0 |
|
||||
| `mbedtls` | 2.2.0 |
|
||||
| `mbed-client-mbed-tls` | 1.0.9 |
|
||||
| `target-x86-linux-native` | 1.0.0 |
|
||||
| `target-linux-native` | 1.0.0 |
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,88 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) 2016 ARM Limited. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
# not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# * http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License 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.
|
||||
|
||||
echo
|
||||
echo "Build mbed Client API for executable size collection"
|
||||
echo
|
||||
|
||||
BUILD_TARGET="frdm-k64f-armcc"
|
||||
|
||||
yt target $BUILD_TARGET
|
||||
yt build
|
||||
|
||||
SIZE_CMD="size --totals"
|
||||
|
||||
OUTPUT_PATH="results/"
|
||||
OUTPUT_FILE_POSTFIX="_${BUILD_TARGET}_size.txt"
|
||||
|
||||
MAIN_MODULE_NAME="mbed-client"
|
||||
|
||||
# yotta dependencies
|
||||
YOTTA_DEPS=(
|
||||
'cmsis-core'
|
||||
'cmsis-core-k64f'
|
||||
'core-util'
|
||||
'dlmalloc'
|
||||
'greentea-client'
|
||||
'mbed-client-c'
|
||||
'mbed-client-mbed-os'
|
||||
'mbed-client-mbedtls'
|
||||
'mbed-drivers'
|
||||
'mbed-hal'
|
||||
'mbed-hal-frdm-k64f'
|
||||
'mbed-hal-k64f'
|
||||
'mbed-hal-ksdk-mcu'
|
||||
'mbedtls'
|
||||
'mbed-trace'
|
||||
'minar'
|
||||
'minar-platform-mbed'
|
||||
'nanostack-libservice'
|
||||
'sal'
|
||||
'sal-driver-lwip-k64f-eth'
|
||||
'sal-iface-eth'
|
||||
'sal-stack-lwip'
|
||||
'sockets'
|
||||
'ualloc'
|
||||
'uvisor-lib'
|
||||
)
|
||||
|
||||
|
||||
# yotta dummy dependencies, which have different naming
|
||||
YOTTA_DUMMY_DEPS=(
|
||||
'cmsis-core-freescale'
|
||||
'compiler-polyfill'
|
||||
'mbed-hal-freescale'
|
||||
'minar-platform'
|
||||
)
|
||||
|
||||
|
||||
echo "Writing object file size informations to ${OUTPUT_PATH}"
|
||||
|
||||
# the "main" module is in build/<target>/source/<module>.ar
|
||||
${SIZE_CMD} ./build/${BUILD_TARGET}/source/${MAIN_MODULE_NAME}.ar >${OUTPUT_PATH}${MAIN_MODULE_NAME}${OUTPUT_FILE_POSTFIX}
|
||||
|
||||
# these are the direct deps, found as build/<target>/ym/<module>/source/<module>.ar
|
||||
for MODULE in "${YOTTA_DEPS[@]}"
|
||||
do
|
||||
${SIZE_CMD} ./build/${BUILD_TARGET}/ym/${MODULE}/source/${MODULE}.ar >${OUTPUT_PATH}${MODULE}${OUTPUT_FILE_POSTFIX}
|
||||
done
|
||||
|
||||
# dummy libs, which are named with different logic
|
||||
for MODULE in "${YOTTA_DUMMY_DEPS[@]}"
|
||||
do
|
||||
# on paths the "-" char needs to be converted to "_"
|
||||
MODULE_PATH=${MODULE//-/_}
|
||||
${SIZE_CMD} ./build/${BUILD_TARGET}/ym/${MODULE}/yotta_dummy_lib_${MODULE_PATH}/${MODULE}.ar >${OUTPUT_PATH}${MODULE}${OUTPUT_FILE_POSTFIX}
|
||||
done
|
|
@ -0,0 +1,14 @@
|
|||
INCLUDE_DIRS := \
|
||||
../ \
|
||||
. \
|
||||
../../nsdl-c \
|
||||
../../libService/libService \
|
||||
../../libService/exported-libs/mbed-client-libservice \
|
||||
../../libService \
|
||||
../../mbedtls/include \
|
||||
../lwm2m-client-linux \
|
||||
../lwm2m-client-linux/source \
|
||||
../lwm2m-client-mbedtls \
|
||||
source \
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
<xsl:output encoding="UTF-8" indent="yes" method="html"/>
|
||||
<xsl:strip-space elements="*"/>
|
||||
|
||||
<xsl:variable name="list"
|
||||
select="document('index.xml')/list" />
|
||||
|
||||
<xsl:template match="/">
|
||||
<h1>
|
||||
Unittest report
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Total tests run <xsl:value-of select="sum(document($list/entry/@name)/testsuite/@tests)"/>
|
||||
, failures: <xsl:value-of select="sum(document($list/entry/@name)/testsuite/@failures) + sum(document($list/entry/@name)/testsuite/@errors)"/>
|
||||
</b>
|
||||
|
||||
<xsl:for-each select="document($list/entry/@name)" >
|
||||
<xsl:apply-templates select="testsuite"/>
|
||||
</xsl:for-each>
|
||||
</p>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="testsuite">
|
||||
<h2>
|
||||
<xsl:value-of select="@name" />
|
||||
</h2>
|
||||
<table border="1" cellSpacing="0" cellPadding="10" >
|
||||
<tr>
|
||||
<th>Tests run</th>
|
||||
<th>Tests failed</th>
|
||||
<th>Other errors</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><xsl:value-of select="@tests"/></td>
|
||||
<td><xsl:value-of select="@failures"/></td>
|
||||
<td><xsl:value-of select="@errors"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<table border="1" cellSpacing="0" cellPadding="10" >
|
||||
<tr>
|
||||
<th>Tests name</th>
|
||||
<th>PASS/FAIL</th>
|
||||
<th>Failing case</th>
|
||||
<th>Reason</th>
|
||||
</tr>
|
||||
<xsl:apply-templates select="testcase"/>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="testcase">
|
||||
<xsl:choose>
|
||||
<xsl:when test="failure">
|
||||
<tr><td><font color="#FF0000"><xsl:value-of select="@name" /></font></td><xsl:apply-templates select="failure"/></tr>
|
||||
</xsl:when>
|
||||
<xsl:when test="error">
|
||||
<tr><td><font color="#FF0000"><xsl:value-of select="@name" /></font></td><xsl:apply-templates select="error"/></tr>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<tr><td><xsl:value-of select="@name" /></td><td><font color="#00FF00">PASS</font></td><td></td><td></td></tr>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="failure">
|
||||
<td>
|
||||
<b><font color="#FF0000">FAIL</font></b>
|
||||
</td>
|
||||
<td>
|
||||
<font color="#ff0000">
|
||||
<xsl:value-of select="@message" />
|
||||
</font>
|
||||
</td>
|
||||
<td>
|
||||
<font color="#ff0000">
|
||||
<xsl:value-of select="@type" />
|
||||
</font>
|
||||
</td>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="error">
|
||||
<td>
|
||||
<b><font color="#FF0000">FAIL</font></b>
|
||||
</td>
|
||||
<td>
|
||||
<font color="#ff0000">
|
||||
<xsl:value-of select="@message" />
|
||||
</font>
|
||||
</td>
|
||||
<td>
|
||||
<font color="#ff0000">
|
||||
<xsl:value-of select="@type" />
|
||||
</font>
|
||||
</td>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 FUNCTIONPOINTER_H
|
||||
#define FUNCTIONPOINTER_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member void function
|
||||
*/
|
||||
template <typename R>
|
||||
class FP0{
|
||||
public:
|
||||
/** Create a Function Pointer, attaching a static function
|
||||
*
|
||||
* \param function The void static function to attach (default is none)
|
||||
*/
|
||||
FP0(R (*function)(void) = 0) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FP, attaching a member function
|
||||
*
|
||||
* \param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* \param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FP0(T *object, R (T::*member)(void)) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* \param function The void static function to attach (default is none)
|
||||
*/
|
||||
void attach(R (*function)(void)) {
|
||||
_p.function = function;
|
||||
_membercaller = 0;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* \param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* \param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(void)) {
|
||||
_p.object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(void)>(_member) = member;
|
||||
_membercaller = &FP0::membercaller<T>;
|
||||
}
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(){
|
||||
if (_membercaller == 0 && _p.function) {
|
||||
return _p.function();
|
||||
} else if (_membercaller && _p.object) {
|
||||
return _membercaller(_p.object, _member);
|
||||
}
|
||||
return (R)0;
|
||||
}
|
||||
|
||||
typedef R (*static_fp)();
|
||||
static_fp get_function() const {
|
||||
return (R(*)())_p.function;
|
||||
}
|
||||
|
||||
R operator ()(void) {
|
||||
return call();
|
||||
}
|
||||
operator bool(void) {
|
||||
void *q = &_p.function;
|
||||
return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static void membercaller(void *object, uintptr_t *member) {
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
|
||||
(o->**m)();
|
||||
}
|
||||
|
||||
union {
|
||||
R (*function)(void); // static function pointer - 0 if none attached
|
||||
void *object; // object this pointer - 0 if none attached
|
||||
} _p;
|
||||
uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
|
||||
R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
|
||||
};
|
||||
|
||||
/* If we had variadic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member void function
|
||||
*/
|
||||
template <typename R, typename A1>
|
||||
class FP1{
|
||||
public:
|
||||
/** Create a FP, attaching a static function
|
||||
*
|
||||
* \param function The void static function to attach (default is none)
|
||||
*/
|
||||
FP1(R (*function)(A1) = 0) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FP, attaching a member function
|
||||
*
|
||||
* \param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* \param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FP1(T *object, R (T::*member)(A1)) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* \param function The void static function to attach (default is none)
|
||||
*/
|
||||
void attach(R (*function)(A1)) {
|
||||
_p.function = function;
|
||||
_membercaller = 0;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* \param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* \param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(A1)) {
|
||||
_p.object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(A1)>(_member) = member;
|
||||
_membercaller = &FP1::membercaller<T>;
|
||||
}
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(A1 a){
|
||||
if (_membercaller == 0 && _p.function) {
|
||||
return _p.function(a);
|
||||
} else if (_membercaller && _p.object) {
|
||||
return _membercaller(_p.object, _member, a);
|
||||
}
|
||||
return (R)0;
|
||||
}
|
||||
|
||||
typedef R (*static_fp)();
|
||||
static_fp get_function() const {
|
||||
return (R(*)())_p.function;
|
||||
}
|
||||
|
||||
R operator ()(A1 a) {
|
||||
return call(a);
|
||||
}
|
||||
operator bool(void)
|
||||
{
|
||||
void *q = &_p.function;
|
||||
return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
|
||||
}
|
||||
private:
|
||||
template<typename T>
|
||||
static void membercaller(void *object, uintptr_t *member, A1 a) {
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
|
||||
(o->**m)(a);
|
||||
}
|
||||
|
||||
union {
|
||||
R (*function)(A1); // static function pointer - 0 if none attached
|
||||
void *object; // object this pointer - 0 if none attached
|
||||
} _p;
|
||||
uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
|
||||
R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef FP0<void> FP;
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue