sandbox / mbed-client-classic

Fork of mbed-client-classic by Christopher Haster

Committer:
geky
Date:
Thu Mar 03 19:22:34 2016 +0000
Revision:
5:babbe7026a0c
Parent:
4:0c58f5786538
Child:
6:e61698377f43
Adopted the NetworkSocketAPI

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