mbed client lightswitch demo
Dependencies: mbed Socket lwip-eth lwip-sys lwip
Fork of mbed-client-classic-example-lwip by
Diff: mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp
- Revision:
- 11:cada08fc8a70
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp Thu Jun 09 17:08:36 2016 +0000
@@ -0,0 +1,253 @@
+/*
+ * 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 "Socket/TCPSocketConnection.h"
+#include "Socket/UDPSocket.h"
+#include "threadwrapper.h"
+#include "mbed_error.h"
+
+
+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),
+ _resolved(true),
+ _is_handshaking(false),
+ _listening(false),
+ _listen_thread(0),
+ _recv_thread(0),
+ _send_thread(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");
+ }
+
+ if (_binding_mode == M2MInterface::TCP ||
+ _binding_mode == M2MInterface::TCP_QUEUE) {
+ error("ConnectionHandler: Unsupported binding mode, only UDP based modes are currently supported");
+ }
+
+ _running = true;
+ _recv_thread = rtos::create_thread<
+ M2MConnectionHandlerPimpl,
+ &M2MConnectionHandlerPimpl::recv_handler>(this, osPriorityAboveNormal);
+ _send_thread = rtos::create_thread<
+ M2MConnectionHandlerPimpl,
+ &M2MConnectionHandlerPimpl::send_handler>(this);
+ _listen_thread = rtos::create_thread<
+ M2MConnectionHandlerPimpl,
+ &M2MConnectionHandlerPimpl::listen_handler>(this);
+}
+
+M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()
+{
+ _listening = false;
+ _running = false;
+
+ if (_listen_thread) {
+ delete _listen_thread;
+ _listen_thread = 0;
+ }
+
+ if (_recv_thread) {
+ delete _recv_thread;
+ _recv_thread = 0;
+ }
+
+ if (_send_thread) {
+ delete _send_thread;
+ _send_thread = 0;
+ }
+
+ delete _security_impl;
+}
+
+bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port)
+{
+ return !(_socket.bind(listen_port) < 0);
+}
+
+bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address,
+ const uint16_t server_port,
+ M2MConnectionObserver::ServerType server_type,
+ const M2MSecurity* security)
+{
+ if (_endpoint.set_address(server_address.c_str(), server_port) < 0) {
+ return false;
+ }
+
+ inet_aton(_endpoint.get_address(), _address._address);
+ _address._port = _endpoint.get_port();
+ _address._length = 4;
+ _address._stack = _network_stack;
+
+ 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();
+ _security_impl->init(security);
+
+ if (_security_impl->connect(_base) < 0) {
+ return false;
+ }
+
+ _use_secure_connection = true;
+ }
+ }
+ }
+
+ _observer.address_ready(_address,
+ server_type,
+ _address._port);
+
+ return true;
+}
+
+
+void M2MConnectionHandlerPimpl::recv_handler()
+{
+ while (_running) {
+ Endpoint recv_endpoint;
+ int size = _socket.receiveFrom(recv_endpoint,
+ (char*)_recv_buffer, sizeof _recv_buffer);
+
+ if (size > 0) {
+ _recv_queue.put(new std::string(_recv_buffer, _recv_buffer+size));
+ } else {
+ rtos::Thread::wait(1000);
+ }
+ }
+}
+
+void M2MConnectionHandlerPimpl::send_handler()
+{
+ while (_running) {
+ osEvent e = _send_queue.get();
+ if (e.status == osEventMessage) {
+ std::string *packet = (std::string*)e.value.p;
+ int size = _socket.sendTo(_endpoint, (char*)packet->data(), packet->size());
+ delete packet;
+ } else {
+ rtos::Thread::wait(1000);
+ }
+ }
+}
+
+bool M2MConnectionHandlerPimpl::send_data(uint8_t *data,
+ uint16_t data_len,
+ sn_nsdl_addr_s *address)
+{
+ if (address == NULL || data == NULL) {
+ return false;
+ }
+
+ if (_use_secure_connection) {
+ if (_security_impl->send_message(data, data_len) < 0) {
+ return false;
+ }
+ } else {
+ if (send_to_socket(data, data_len) < 0) {
+ return false;
+ }
+ }
+
+ _observer.data_sent();
+ return true;
+}
+
+bool M2MConnectionHandlerPimpl::start_listening_for_data()
+{
+ _listening = true;
+ return true;
+}
+
+void M2MConnectionHandlerPimpl::stop_listening()
+{
+ _listening = false;
+}
+
+void M2MConnectionHandlerPimpl::listen_handler()
+{
+ while (_running) {
+ if (_listening) {
+ memset(_listen_buffer, 0, sizeof _listen_buffer);
+ int size;
+
+ if (_use_secure_connection) {
+ size = _security_impl->read(_listen_buffer, sizeof _listen_buffer);
+ } else {
+ size = receive_from_socket(_listen_buffer, sizeof _listen_buffer);
+ }
+
+ if (size > 0) {
+ _observer.data_available((uint8_t*)_listen_buffer, size, _address);
+ } else if (size != 0) {
+ _listening = false;
+ _observer.socket_error(2);
+ }
+ } else {
+ rtos::Thread::wait(1000);
+ }
+ }
+}
+
+
+int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len)
+{
+ if (_send_queue.put(new std::string(buf, buf+len)) != osOK) {
+ return M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE;
+ } else {
+ return len;
+ }
+}
+
+int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len)
+{
+ osEvent e = _recv_queue.get();
+ if (e.status == osEventMessage) {
+ std::string *packet = (std::string*)e.value.p;
+ int size = packet->size();
+
+ if (size <= len) {
+ memcpy(buf, packet->data(), size);
+ delete packet;
+ return size;
+ }
+ }
+
+ return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
+}
+
+void M2MConnectionHandlerPimpl::handle_connection_error(int /*error*/)
+{
+ _observer.socket_error(4);
+}
Austin Blackstone
