sandbox / mbed-client-classic

Fork of mbed-client-classic by Christopher Haster

Committer:
Christopher Haster
Date:
Fri Jan 22 16:53:32 2016 -0600
Revision:
1:2dc916e504c9
Child:
2:c3434146c3d2
Moving mbed-client-classic into mercurial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Christopher Haster 1:2dc916e504c9 1 /*
Christopher Haster 1:2dc916e504c9 2 * Copyright (c) 2015 ARM Limited. All rights reserved.
Christopher Haster 1:2dc916e504c9 3 * SPDX-License-Identifier: Apache-2.0
Christopher Haster 1:2dc916e504c9 4 * Licensed under the Apache License, Version 2.0 (the License); you may
Christopher Haster 1:2dc916e504c9 5 * not use this file except in compliance with the License.
Christopher Haster 1:2dc916e504c9 6 * You may obtain a copy of the License at
Christopher Haster 1:2dc916e504c9 7 *
Christopher Haster 1:2dc916e504c9 8 * http://www.apache.org/licenses/LICENSE-2.0
Christopher Haster 1:2dc916e504c9 9 *
Christopher Haster 1:2dc916e504c9 10 * Unless required by applicable law or agreed to in writing, software
Christopher Haster 1:2dc916e504c9 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
Christopher Haster 1:2dc916e504c9 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Christopher Haster 1:2dc916e504c9 13 * See the License for the specific language governing permissions and
Christopher Haster 1:2dc916e504c9 14 * limitations under the License.
Christopher Haster 1:2dc916e504c9 15 */
Christopher Haster 1:2dc916e504c9 16 #include "mbed-client-classic/m2mconnectionhandlerpimpl.h"
Christopher Haster 1:2dc916e504c9 17 #include "mbed-client/m2mconnectionobserver.h"
Christopher Haster 1:2dc916e504c9 18 #include "mbed-client/m2mconstants.h"
Christopher Haster 1:2dc916e504c9 19 #include "mbed-client/m2msecurity.h"
Christopher Haster 1:2dc916e504c9 20 #include "mbed-client/m2mconnectionhandler.h"
Christopher Haster 1:2dc916e504c9 21
Christopher Haster 1:2dc916e504c9 22 #include "Socket/TCPSocketConnection.h"
Christopher Haster 1:2dc916e504c9 23 #include "Socket/UDPSocket.h"
Christopher Haster 1:2dc916e504c9 24 #include "threadwrapper.h"
Christopher Haster 1:2dc916e504c9 25 #include "mbed_error.h"
Christopher Haster 1:2dc916e504c9 26
Christopher Haster 1:2dc916e504c9 27
Christopher Haster 1:2dc916e504c9 28 M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
Christopher Haster 1:2dc916e504c9 29 M2MConnectionSecurity* sec,
Christopher Haster 1:2dc916e504c9 30 M2MInterface::BindingMode mode,
Christopher Haster 1:2dc916e504c9 31 M2MInterface::NetworkStack stack)
Christopher Haster 1:2dc916e504c9 32 :_base(base),
Christopher Haster 1:2dc916e504c9 33 _observer(observer),
Christopher Haster 1:2dc916e504c9 34 _security_impl(sec),
Christopher Haster 1:2dc916e504c9 35 _use_secure_connection(false),
Christopher Haster 1:2dc916e504c9 36 _binding_mode(mode),
Christopher Haster 1:2dc916e504c9 37 _network_stack(stack),
Christopher Haster 1:2dc916e504c9 38 _resolved(true),
Christopher Haster 1:2dc916e504c9 39 _is_handshaking(false),
Christopher Haster 1:2dc916e504c9 40 _listening(false),
Christopher Haster 1:2dc916e504c9 41 _reading_thread(0)
Christopher Haster 1:2dc916e504c9 42 {
Christopher Haster 1:2dc916e504c9 43 memset(&_address_buffer, 0, sizeof _address_buffer);
Christopher Haster 1:2dc916e504c9 44 memset(&_address, 0, sizeof _address);
Christopher Haster 1:2dc916e504c9 45 _address._address = _address_buffer;
Christopher Haster 1:2dc916e504c9 46
Christopher Haster 1:2dc916e504c9 47 if (_network_stack != M2MInterface::LwIP_IPv4) {
Christopher Haster 1:2dc916e504c9 48 error("ConnectionHandler: Unsupported network stack, only IPv4 is currently supported");
Christopher Haster 1:2dc916e504c9 49 }
Christopher Haster 1:2dc916e504c9 50
Christopher Haster 1:2dc916e504c9 51 if (_binding_mode == M2MInterface::TCP ||
Christopher Haster 1:2dc916e504c9 52 _binding_mode == M2MInterface::TCP_QUEUE) {
Christopher Haster 1:2dc916e504c9 53 error("ConnectionHandler: Unsupported binding mode, only UDP based modes are currently supported");
Christopher Haster 1:2dc916e504c9 54 }
Christopher Haster 1:2dc916e504c9 55 }
Christopher Haster 1:2dc916e504c9 56
Christopher Haster 1:2dc916e504c9 57 M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()
Christopher Haster 1:2dc916e504c9 58 {
Christopher Haster 1:2dc916e504c9 59 stop_listening();
Christopher Haster 1:2dc916e504c9 60 delete _security_impl;
Christopher Haster 1:2dc916e504c9 61 }
Christopher Haster 1:2dc916e504c9 62
Christopher Haster 1:2dc916e504c9 63 bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port)
Christopher Haster 1:2dc916e504c9 64 {
Christopher Haster 1:2dc916e504c9 65 return !(_socket.bind(listen_port) < 0);
Christopher Haster 1:2dc916e504c9 66 }
Christopher Haster 1:2dc916e504c9 67
Christopher Haster 1:2dc916e504c9 68 bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address,
Christopher Haster 1:2dc916e504c9 69 const uint16_t server_port,
Christopher Haster 1:2dc916e504c9 70 M2MConnectionObserver::ServerType server_type,
Christopher Haster 1:2dc916e504c9 71 const M2MSecurity* security)
Christopher Haster 1:2dc916e504c9 72 {
Christopher Haster 1:2dc916e504c9 73 if (_endpoint.set_address(server_address.c_str(), server_port) < 0) {
Christopher Haster 1:2dc916e504c9 74 return false;
Christopher Haster 1:2dc916e504c9 75 }
Christopher Haster 1:2dc916e504c9 76
Christopher Haster 1:2dc916e504c9 77 inet_aton(_endpoint.get_address(), _address._address);
Christopher Haster 1:2dc916e504c9 78 _address._port = _endpoint.get_port();
Christopher Haster 1:2dc916e504c9 79 _address._length = 4;
Christopher Haster 1:2dc916e504c9 80 _address._stack = _network_stack;
Christopher Haster 1:2dc916e504c9 81
Christopher Haster 1:2dc916e504c9 82 if (security) {
Christopher Haster 1:2dc916e504c9 83 if (security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate ||
Christopher Haster 1:2dc916e504c9 84 security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) {
Christopher Haster 1:2dc916e504c9 85 if (_security_impl != NULL) {
Christopher Haster 1:2dc916e504c9 86 _security_impl->reset();
Christopher Haster 1:2dc916e504c9 87 _security_impl->init(security);
Christopher Haster 1:2dc916e504c9 88
Christopher Haster 1:2dc916e504c9 89 if (_security_impl->connect(_base) < 0) {
Christopher Haster 1:2dc916e504c9 90 return false;
Christopher Haster 1:2dc916e504c9 91 }
Christopher Haster 1:2dc916e504c9 92
Christopher Haster 1:2dc916e504c9 93 _use_secure_connection = true;
Christopher Haster 1:2dc916e504c9 94 }
Christopher Haster 1:2dc916e504c9 95 }
Christopher Haster 1:2dc916e504c9 96 }
Christopher Haster 1:2dc916e504c9 97
Christopher Haster 1:2dc916e504c9 98 _observer.address_ready(_address,
Christopher Haster 1:2dc916e504c9 99 server_type,
Christopher Haster 1:2dc916e504c9 100 _address._port);
Christopher Haster 1:2dc916e504c9 101
Christopher Haster 1:2dc916e504c9 102 return true;
Christopher Haster 1:2dc916e504c9 103 }
Christopher Haster 1:2dc916e504c9 104
Christopher Haster 1:2dc916e504c9 105 bool M2MConnectionHandlerPimpl::send_data(uint8_t *data,
Christopher Haster 1:2dc916e504c9 106 uint16_t data_len,
Christopher Haster 1:2dc916e504c9 107 sn_nsdl_addr_s *address)
Christopher Haster 1:2dc916e504c9 108 {
Christopher Haster 1:2dc916e504c9 109 if (address == NULL || data == NULL) {
Christopher Haster 1:2dc916e504c9 110 return false;
Christopher Haster 1:2dc916e504c9 111 }
Christopher Haster 1:2dc916e504c9 112
Christopher Haster 1:2dc916e504c9 113 if (_use_secure_connection) {
Christopher Haster 1:2dc916e504c9 114 if (_security_impl->send_message(data, data_len) < 0) {
Christopher Haster 1:2dc916e504c9 115 return false;
Christopher Haster 1:2dc916e504c9 116 }
Christopher Haster 1:2dc916e504c9 117 } else {
Christopher Haster 1:2dc916e504c9 118 if (_socket.sendTo(_endpoint, (char*)data, data_len) < 0) {
Christopher Haster 1:2dc916e504c9 119 return false;
Christopher Haster 1:2dc916e504c9 120 }
Christopher Haster 1:2dc916e504c9 121 }
Christopher Haster 1:2dc916e504c9 122
Christopher Haster 1:2dc916e504c9 123 _observer.data_sent();
Christopher Haster 1:2dc916e504c9 124 return true;
Christopher Haster 1:2dc916e504c9 125 }
Christopher Haster 1:2dc916e504c9 126
Christopher Haster 1:2dc916e504c9 127 bool M2MConnectionHandlerPimpl::start_listening_for_data()
Christopher Haster 1:2dc916e504c9 128 {
Christopher Haster 1:2dc916e504c9 129 _listening = true;
Christopher Haster 1:2dc916e504c9 130 _reading_thread = create_thread<M2MConnectionHandlerPimpl,
Christopher Haster 1:2dc916e504c9 131 &M2MConnectionHandlerPimpl::receive_data>(this);
Christopher Haster 1:2dc916e504c9 132 return true;
Christopher Haster 1:2dc916e504c9 133 }
Christopher Haster 1:2dc916e504c9 134
Christopher Haster 1:2dc916e504c9 135 void M2MConnectionHandlerPimpl::stop_listening()
Christopher Haster 1:2dc916e504c9 136 {
Christopher Haster 1:2dc916e504c9 137 if (_reading_thread) {
Christopher Haster 1:2dc916e504c9 138 _listening = false;
Christopher Haster 1:2dc916e504c9 139 delete _reading_thread;
Christopher Haster 1:2dc916e504c9 140 _reading_thread = 0;
Christopher Haster 1:2dc916e504c9 141 }
Christopher Haster 1:2dc916e504c9 142 }
Christopher Haster 1:2dc916e504c9 143
Christopher Haster 1:2dc916e504c9 144 void M2MConnectionHandlerPimpl::receive_data()
Christopher Haster 1:2dc916e504c9 145 {
Christopher Haster 1:2dc916e504c9 146 while (_listening) {
Christopher Haster 1:2dc916e504c9 147 if (_use_secure_connection) {
Christopher Haster 1:2dc916e504c9 148 memset(_receive_buffer, 0, sizeof _receive_buffer);
Christopher Haster 1:2dc916e504c9 149
Christopher Haster 1:2dc916e504c9 150 int size = _security_impl->read(_receive_buffer, sizeof _receive_buffer);
Christopher Haster 1:2dc916e504c9 151 if (size > 0) {
Christopher Haster 1:2dc916e504c9 152 _observer.data_available((uint8_t*)_receive_buffer,
Christopher Haster 1:2dc916e504c9 153 size, _address);
Christopher Haster 1:2dc916e504c9 154 } else if (size != 0 && size != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ) {
Christopher Haster 1:2dc916e504c9 155 _listening = false;
Christopher Haster 1:2dc916e504c9 156 _observer.socket_error(1);
Christopher Haster 1:2dc916e504c9 157 }
Christopher Haster 1:2dc916e504c9 158 } else {
Christopher Haster 1:2dc916e504c9 159 memset(_receive_buffer, 0, sizeof _receive_buffer);
Christopher Haster 1:2dc916e504c9 160
Christopher Haster 1:2dc916e504c9 161 int size = _socket.receiveFrom(_endpoint, (char*)_receive_buffer, sizeof _receive_buffer);
Christopher Haster 1:2dc916e504c9 162 if (size > 0) {
Christopher Haster 1:2dc916e504c9 163 _observer.data_available((uint8_t*)_receive_buffer,
Christopher Haster 1:2dc916e504c9 164 size, _address);
Christopher Haster 1:2dc916e504c9 165 } else if (size != 0) {
Christopher Haster 1:2dc916e504c9 166 _listening = false;
Christopher Haster 1:2dc916e504c9 167 _observer.socket_error(2);
Christopher Haster 1:2dc916e504c9 168 }
Christopher Haster 1:2dc916e504c9 169 }
Christopher Haster 1:2dc916e504c9 170 }
Christopher Haster 1:2dc916e504c9 171 }
Christopher Haster 1:2dc916e504c9 172
Christopher Haster 1:2dc916e504c9 173
Christopher Haster 1:2dc916e504c9 174 int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len)
Christopher Haster 1:2dc916e504c9 175 {
Christopher Haster 1:2dc916e504c9 176 int size = _socket.sendTo(_endpoint, (char*)buf, len);
Christopher Haster 1:2dc916e504c9 177
Christopher Haster 1:2dc916e504c9 178 if (size == 0) {
Christopher Haster 1:2dc916e504c9 179 return M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE;
Christopher Haster 1:2dc916e504c9 180 } else {
Christopher Haster 1:2dc916e504c9 181 return size;
Christopher Haster 1:2dc916e504c9 182 }
Christopher Haster 1:2dc916e504c9 183 }
Christopher Haster 1:2dc916e504c9 184
Christopher Haster 1:2dc916e504c9 185 int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len)
Christopher Haster 1:2dc916e504c9 186 {
Christopher Haster 1:2dc916e504c9 187 Endpoint recv_endpoint;
Christopher Haster 1:2dc916e504c9 188 int size = _socket.receiveFrom(recv_endpoint, (char*)buf, len);
Christopher Haster 1:2dc916e504c9 189
Christopher Haster 1:2dc916e504c9 190 if (size == 0) {
Christopher Haster 1:2dc916e504c9 191 return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
Christopher Haster 1:2dc916e504c9 192 } else {
Christopher Haster 1:2dc916e504c9 193 return size;
Christopher Haster 1:2dc916e504c9 194 }
Christopher Haster 1:2dc916e504c9 195 }
Christopher Haster 1:2dc916e504c9 196
Christopher Haster 1:2dc916e504c9 197 void M2MConnectionHandlerPimpl::handle_connection_error(int /*error*/)
Christopher Haster 1:2dc916e504c9 198 {
Christopher Haster 1:2dc916e504c9 199 _observer.socket_error(4);
Christopher Haster 1:2dc916e504c9 200 }