sandbox / mbed-client-classic

Fork of mbed-client-classic by Christopher Haster

Revision:
1:2dc916e504c9
Child:
2:c3434146c3d2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/m2mconnectionhandlerpimpl.cpp	Fri Jan 22 16:53:32 2016 -0600
@@ -0,0 +1,200 @@
+/*
+ * 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),
+ _reading_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");
+    }
+}
+
+M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()
+{
+    stop_listening();
+    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;
+}
+
+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 (_socket.sendTo(_endpoint, (char*)data, data_len) < 0) {
+            return false;
+        }
+    }
+    
+    _observer.data_sent();
+    return true;
+}
+
+bool M2MConnectionHandlerPimpl::start_listening_for_data()
+{
+    _listening = true;
+    _reading_thread = create_thread<M2MConnectionHandlerPimpl,
+                                   &M2MConnectionHandlerPimpl::receive_data>(this);
+    return true;
+}
+
+void M2MConnectionHandlerPimpl::stop_listening()
+{
+    if (_reading_thread) {
+        _listening = false;
+        delete _reading_thread;
+        _reading_thread = 0;
+    }
+}
+
+void M2MConnectionHandlerPimpl::receive_data()
+{
+    while (_listening) {
+        if (_use_secure_connection) {
+            memset(_receive_buffer, 0, sizeof _receive_buffer);
+
+            int size = _security_impl->read(_receive_buffer, sizeof _receive_buffer);
+            if (size > 0) {
+                _observer.data_available((uint8_t*)_receive_buffer,
+                                         size, _address);
+            } else if (size != 0 && size != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ) {
+                _listening = false;
+                _observer.socket_error(1);
+            }
+        } else {
+            memset(_receive_buffer, 0, sizeof _receive_buffer);
+
+            int size = _socket.receiveFrom(_endpoint, (char*)_receive_buffer, sizeof _receive_buffer);
+            if (size > 0) {
+                _observer.data_available((uint8_t*)_receive_buffer,
+                                         size, _address);
+            } else if (size != 0) {
+                _listening = false;
+                _observer.socket_error(2);
+            }
+        }
+    }
+}
+
+
+int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len)
+{
+    int size = _socket.sendTo(_endpoint, (char*)buf, len);
+    
+    if (size == 0) {
+        return M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE;
+    } else {
+        return size;
+    }
+}
+
+int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len)
+{
+    Endpoint recv_endpoint;
+    int size = _socket.receiveFrom(recv_endpoint, (char*)buf, len);
+    
+    if (size == 0) {
+        return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
+    } else {
+        return size;
+    }
+}
+
+void M2MConnectionHandlerPimpl::handle_connection_error(int /*error*/)
+{
+    _observer.socket_error(4);
+}