sandbox / mbed-client-classic

Fork of mbed-client-classic by Christopher Haster

Committer:
geky
Date:
Thu Mar 03 20:40:02 2016 +0000
Revision:
6:e61698377f43
Parent:
5:babbe7026a0c
Child:
7:774e507fc261
Removed leftover initializers

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
geky 4:0c58f5786538 22 #include "m2mnetwork.h"
Christopher Haster 1:2dc916e504c9 23 #include "threadwrapper.h"
Christopher Haster 1:2dc916e504c9 24 #include "mbed_error.h"
Christopher Haster 1:2dc916e504c9 25
geky 4:0c58f5786538 26 #include "NetworkInterface.h"
geky 4:0c58f5786538 27 #include "UDPSocket.h"
geky 4:0c58f5786538 28
geky 4:0c58f5786538 29
Christopher Haster 1:2dc916e504c9 30
Christopher Haster 1:2dc916e504c9 31 M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
Christopher Haster 1:2dc916e504c9 32 M2MConnectionSecurity* sec,
Christopher Haster 1:2dc916e504c9 33 M2MInterface::BindingMode mode,
Christopher Haster 1:2dc916e504c9 34 M2MInterface::NetworkStack stack)
Christopher Haster 1:2dc916e504c9 35 :_base(base),
Christopher Haster 1:2dc916e504c9 36 _observer(observer),
Christopher Haster 1:2dc916e504c9 37 _security_impl(sec),
Christopher Haster 1:2dc916e504c9 38 _use_secure_connection(false),
Christopher Haster 1:2dc916e504c9 39 _binding_mode(mode),
Christopher Haster 1:2dc916e504c9 40 _network_stack(stack),
Christopher Haster 1:2dc916e504c9 41 _resolved(true),
Christopher Haster 1:2dc916e504c9 42 _is_handshaking(false),
geky 4:0c58f5786538 43 _socket(0),
Christopher Haster 1:2dc916e504c9 44 _listening(false),
geky 2:c3434146c3d2 45 _listen_thread(0),
geky 5:babbe7026a0c 46 _socket_thread(0)
Christopher Haster 1:2dc916e504c9 47 {
Christopher Haster 1:2dc916e504c9 48 memset(&_address_buffer, 0, sizeof _address_buffer);
Christopher Haster 1:2dc916e504c9 49 memset(&_address, 0, sizeof _address);
Christopher Haster 1:2dc916e504c9 50 _address._address = _address_buffer;
Christopher Haster 1:2dc916e504c9 51
Christopher Haster 1:2dc916e504c9 52 if (_network_stack != M2MInterface::LwIP_IPv4) {
Christopher Haster 1:2dc916e504c9 53 error("ConnectionHandler: Unsupported network stack, only IPv4 is currently supported");
Christopher Haster 1:2dc916e504c9 54 }
Christopher Haster 1:2dc916e504c9 55
Christopher Haster 1:2dc916e504c9 56 if (_binding_mode == M2MInterface::TCP ||
Christopher Haster 1:2dc916e504c9 57 _binding_mode == M2MInterface::TCP_QUEUE) {
Christopher Haster 1:2dc916e504c9 58 error("ConnectionHandler: Unsupported binding mode, only UDP based modes are currently supported");
Christopher Haster 1:2dc916e504c9 59 }
geky 2:c3434146c3d2 60
geky 2:c3434146c3d2 61 _running = true;
geky 5:babbe7026a0c 62 _socket_thread = rtos::create_thread<
geky 2:c3434146c3d2 63 M2MConnectionHandlerPimpl,
geky 5:babbe7026a0c 64 &M2MConnectionHandlerPimpl::socket_handler>(this, osPriorityAboveNormal);
geky 2:c3434146c3d2 65 _listen_thread = rtos::create_thread<
geky 2:c3434146c3d2 66 M2MConnectionHandlerPimpl,
geky 4:0c58f5786538 67 &M2MConnectionHandlerPimpl::listen_handler>(this, osPriorityAboveNormal);
Christopher Haster 1:2dc916e504c9 68 }
Christopher Haster 1:2dc916e504c9 69
Christopher Haster 1:2dc916e504c9 70 M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()
Christopher Haster 1:2dc916e504c9 71 {
geky 2:c3434146c3d2 72 _listening = false;
geky 2:c3434146c3d2 73 _running = false;
geky 2:c3434146c3d2 74
geky 2:c3434146c3d2 75 if (_listen_thread) {
geky 2:c3434146c3d2 76 delete _listen_thread;
geky 2:c3434146c3d2 77 _listen_thread = 0;
geky 2:c3434146c3d2 78 }
geky 2:c3434146c3d2 79
geky 5:babbe7026a0c 80 if (_socket_thread) {
geky 5:babbe7026a0c 81 delete _socket_thread;
geky 5:babbe7026a0c 82 _socket_thread = 0;
geky 2:c3434146c3d2 83 }
geky 2:c3434146c3d2 84
geky 4:0c58f5786538 85 if (_socket) {
geky 4:0c58f5786538 86 delete _socket;
geky 4:0c58f5786538 87 _socket = 0;
geky 4:0c58f5786538 88 }
geky 4:0c58f5786538 89
Christopher Haster 1:2dc916e504c9 90 delete _security_impl;
Christopher Haster 1:2dc916e504c9 91 }
Christopher Haster 1:2dc916e504c9 92
Christopher Haster 1:2dc916e504c9 93 bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port)
Christopher Haster 1:2dc916e504c9 94 {
geky 4:0c58f5786538 95 return true;
Christopher Haster 1:2dc916e504c9 96 }
Christopher Haster 1:2dc916e504c9 97
Christopher Haster 1:2dc916e504c9 98 bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address,
Christopher Haster 1:2dc916e504c9 99 const uint16_t server_port,
Christopher Haster 1:2dc916e504c9 100 M2MConnectionObserver::ServerType server_type,
Christopher Haster 1:2dc916e504c9 101 const M2MSecurity* security)
Christopher Haster 1:2dc916e504c9 102 {
geky 4:0c58f5786538 103 NetworkInterface *iface = M2MNetwork::getInterface();
geky 4:0c58f5786538 104 if (!iface) {
Christopher Haster 1:2dc916e504c9 105 return false;
Christopher Haster 1:2dc916e504c9 106 }
geky 4:0c58f5786538 107
geky 4:0c58f5786538 108 if (_socket) {
geky 4:0c58f5786538 109 delete _socket;
geky 4:0c58f5786538 110 }
geky 4:0c58f5786538 111
geky 4:0c58f5786538 112 _socket = new UDPSocket(iface);
geky 4:0c58f5786538 113 if (_socket->open(server_address.c_str(), server_port) < 0) {
geky 4:0c58f5786538 114 return false;
geky 4:0c58f5786538 115 }
Christopher Haster 1:2dc916e504c9 116
Christopher Haster 1:2dc916e504c9 117 if (security) {
Christopher Haster 1:2dc916e504c9 118 if (security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate ||
Christopher Haster 1:2dc916e504c9 119 security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) {
Christopher Haster 1:2dc916e504c9 120 if (_security_impl != NULL) {
Christopher Haster 1:2dc916e504c9 121 _security_impl->reset();
Christopher Haster 1:2dc916e504c9 122 _security_impl->init(security);
Christopher Haster 1:2dc916e504c9 123
Christopher Haster 1:2dc916e504c9 124 if (_security_impl->connect(_base) < 0) {
Christopher Haster 1:2dc916e504c9 125 return false;
Christopher Haster 1:2dc916e504c9 126 }
Christopher Haster 1:2dc916e504c9 127
Christopher Haster 1:2dc916e504c9 128 _use_secure_connection = true;
Christopher Haster 1:2dc916e504c9 129 }
Christopher Haster 1:2dc916e504c9 130 }
Christopher Haster 1:2dc916e504c9 131 }
Christopher Haster 1:2dc916e504c9 132
geky 4:0c58f5786538 133 _address._address = (void*)_socket->getIPAddress();
geky 4:0c58f5786538 134 _address._length = strlen((char*)_address._address);
geky 4:0c58f5786538 135 _address._port = _socket->getPort();
geky 4:0c58f5786538 136 _address._stack = _network_stack;
geky 4:0c58f5786538 137
Christopher Haster 1:2dc916e504c9 138 _observer.address_ready(_address,
Christopher Haster 1:2dc916e504c9 139 server_type,
Christopher Haster 1:2dc916e504c9 140 _address._port);
Christopher Haster 1:2dc916e504c9 141
Christopher Haster 1:2dc916e504c9 142 return true;
Christopher Haster 1:2dc916e504c9 143 }
Christopher Haster 1:2dc916e504c9 144
geky 2:c3434146c3d2 145
geky 5:babbe7026a0c 146 void M2MConnectionHandlerPimpl::socket_handler()
geky 2:c3434146c3d2 147 {
geky 2:c3434146c3d2 148 while (_running) {
geky 5:babbe7026a0c 149 if (!_socket || !_socket->isConnected()) {
geky 2:c3434146c3d2 150 rtos::Thread::wait(1000);
geky 4:0c58f5786538 151 continue;
geky 2:c3434146c3d2 152 }
geky 4:0c58f5786538 153
geky 5:babbe7026a0c 154 // check recvs
geky 4:0c58f5786538 155 int size = _socket->recv((char*)_recv_buffer, sizeof _recv_buffer, false);
geky 5:babbe7026a0c 156 if (size > 0) {
geky 5:babbe7026a0c 157 _recv_queue.put(new std::string(_recv_buffer, _recv_buffer+size));
geky 4:0c58f5786538 158 continue;
geky 4:0c58f5786538 159 }
geky 5:babbe7026a0c 160
geky 5:babbe7026a0c 161 // check sends
geky 5:babbe7026a0c 162 osEvent e = _send_queue.get(0);
geky 5:babbe7026a0c 163 if (e.status == osEventMessage) {
geky 5:babbe7026a0c 164 std::string *packet = (std::string*)e.value.p;
geky 5:babbe7026a0c 165 int size = _socket->send((char*)packet->data(), packet->size());
geky 5:babbe7026a0c 166 delete packet;
geky 5:babbe7026a0c 167 continue;
geky 5:babbe7026a0c 168 }
geky 5:babbe7026a0c 169
geky 5:babbe7026a0c 170 // no activity
geky 5:babbe7026a0c 171 rtos::Thread::wait(10);
geky 2:c3434146c3d2 172 }
geky 2:c3434146c3d2 173 }
geky 2:c3434146c3d2 174
geky 2:c3434146c3d2 175
Christopher Haster 1:2dc916e504c9 176 bool M2MConnectionHandlerPimpl::send_data(uint8_t *data,
Christopher Haster 1:2dc916e504c9 177 uint16_t data_len,
Christopher Haster 1:2dc916e504c9 178 sn_nsdl_addr_s *address)
Christopher Haster 1:2dc916e504c9 179 {
Christopher Haster 1:2dc916e504c9 180 if (address == NULL || data == NULL) {
Christopher Haster 1:2dc916e504c9 181 return false;
Christopher Haster 1:2dc916e504c9 182 }
Christopher Haster 1:2dc916e504c9 183
Christopher Haster 1:2dc916e504c9 184 if (_use_secure_connection) {
Christopher Haster 1:2dc916e504c9 185 if (_security_impl->send_message(data, data_len) < 0) {
Christopher Haster 1:2dc916e504c9 186 return false;
Christopher Haster 1:2dc916e504c9 187 }
Christopher Haster 1:2dc916e504c9 188 } else {
geky 2:c3434146c3d2 189 if (send_to_socket(data, data_len) < 0) {
Christopher Haster 1:2dc916e504c9 190 return false;
Christopher Haster 1:2dc916e504c9 191 }
Christopher Haster 1:2dc916e504c9 192 }
Christopher Haster 1:2dc916e504c9 193
Christopher Haster 1:2dc916e504c9 194 _observer.data_sent();
Christopher Haster 1:2dc916e504c9 195 return true;
Christopher Haster 1:2dc916e504c9 196 }
Christopher Haster 1:2dc916e504c9 197
Christopher Haster 1:2dc916e504c9 198 bool M2MConnectionHandlerPimpl::start_listening_for_data()
Christopher Haster 1:2dc916e504c9 199 {
Christopher Haster 1:2dc916e504c9 200 _listening = true;
Christopher Haster 1:2dc916e504c9 201 return true;
Christopher Haster 1:2dc916e504c9 202 }
Christopher Haster 1:2dc916e504c9 203
Christopher Haster 1:2dc916e504c9 204 void M2MConnectionHandlerPimpl::stop_listening()
Christopher Haster 1:2dc916e504c9 205 {
geky 2:c3434146c3d2 206 _listening = false;
Christopher Haster 1:2dc916e504c9 207 }
Christopher Haster 1:2dc916e504c9 208
geky 2:c3434146c3d2 209 void M2MConnectionHandlerPimpl::listen_handler()
Christopher Haster 1:2dc916e504c9 210 {
geky 2:c3434146c3d2 211 while (_running) {
geky 4:0c58f5786538 212 if (!_listening) {
geky 4:0c58f5786538 213 rtos::Thread::wait(1000);
geky 4:0c58f5786538 214 continue;
geky 4:0c58f5786538 215 }
geky 4:0c58f5786538 216
geky 4:0c58f5786538 217 memset(_listen_buffer, 0, sizeof _listen_buffer);
geky 4:0c58f5786538 218 int size;
geky 2:c3434146c3d2 219
geky 4:0c58f5786538 220 if (_use_secure_connection) {
geky 4:0c58f5786538 221 size = _security_impl->read(_listen_buffer, sizeof _listen_buffer);
geky 4:0c58f5786538 222 } else {
geky 4:0c58f5786538 223 size = receive_from_socket(_listen_buffer, sizeof _listen_buffer);
geky 4:0c58f5786538 224 }
geky 2:c3434146c3d2 225
geky 4:0c58f5786538 226 if (size > 0) {
geky 4:0c58f5786538 227 _observer.data_available((uint8_t*)_listen_buffer, size, _address);
geky 4:0c58f5786538 228 } else if (size != 0) {
geky 4:0c58f5786538 229 _listening = false;
geky 4:0c58f5786538 230 _observer.socket_error(2);
Christopher Haster 1:2dc916e504c9 231 }
Christopher Haster 1:2dc916e504c9 232 }
Christopher Haster 1:2dc916e504c9 233 }
Christopher Haster 1:2dc916e504c9 234
Christopher Haster 1:2dc916e504c9 235
Christopher Haster 1:2dc916e504c9 236 int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len)
Christopher Haster 1:2dc916e504c9 237 {
geky 2:c3434146c3d2 238 if (_send_queue.put(new std::string(buf, buf+len)) != osOK) {
Christopher Haster 1:2dc916e504c9 239 return M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE;
Christopher Haster 1:2dc916e504c9 240 } else {
geky 2:c3434146c3d2 241 return len;
Christopher Haster 1:2dc916e504c9 242 }
Christopher Haster 1:2dc916e504c9 243 }
Christopher Haster 1:2dc916e504c9 244
Christopher Haster 1:2dc916e504c9 245 int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len)
Christopher Haster 1:2dc916e504c9 246 {
geky 2:c3434146c3d2 247 osEvent e = _recv_queue.get();
geky 2:c3434146c3d2 248 if (e.status == osEventMessage) {
geky 2:c3434146c3d2 249 std::string *packet = (std::string*)e.value.p;
geky 2:c3434146c3d2 250 int size = packet->size();
geky 2:c3434146c3d2 251
geky 2:c3434146c3d2 252 if (size <= len) {
geky 2:c3434146c3d2 253 memcpy(buf, packet->data(), size);
geky 2:c3434146c3d2 254 delete packet;
geky 2:c3434146c3d2 255 return size;
geky 2:c3434146c3d2 256 }
geky 2:c3434146c3d2 257 }
Christopher Haster 1:2dc916e504c9 258
geky 2:c3434146c3d2 259 return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
Christopher Haster 1:2dc916e504c9 260 }
Christopher Haster 1:2dc916e504c9 261
Christopher Haster 1:2dc916e504c9 262 void M2MConnectionHandlerPimpl::handle_connection_error(int /*error*/)
Christopher Haster 1:2dc916e504c9 263 {
Christopher Haster 1:2dc916e504c9 264 _observer.socket_error(4);
Christopher Haster 1:2dc916e504c9 265 }