Pfp Cybersecurity (Aka Power Fingerprinting, Inc.) / Mbed OS pfp-emon-nxp

Dependencies:   FXAS21002 FXOS8700Q

Committer:
vithyat
Date:
Wed Aug 28 19:24:56 2019 +0000
Revision:
0:977e87915078
init

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vithyat 0:977e87915078 1 /*
vithyat 0:977e87915078 2 * Copyright (c) 2015 - 2017 ARM Limited. All rights reserved.
vithyat 0:977e87915078 3 * SPDX-License-Identifier: Apache-2.0
vithyat 0:977e87915078 4 * Licensed under the Apache License, Version 2.0 (the License); you may
vithyat 0:977e87915078 5 * not use this file except in compliance with the License.
vithyat 0:977e87915078 6 * You may obtain a copy of the License at
vithyat 0:977e87915078 7 *
vithyat 0:977e87915078 8 * http://www.apache.org/licenses/LICENSE-2.0
vithyat 0:977e87915078 9 *
vithyat 0:977e87915078 10 * Unless required by applicable law or agreed to in writing, software
vithyat 0:977e87915078 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
vithyat 0:977e87915078 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
vithyat 0:977e87915078 13 * See the License for the specific language governing permissions and
vithyat 0:977e87915078 14 * limitations under the License.
vithyat 0:977e87915078 15 */
vithyat 0:977e87915078 16
vithyat 0:977e87915078 17 // fixup the compilation on ARMCC for PRIu32
vithyat 0:977e87915078 18 #define __STDC_FORMAT_MACROS
vithyat 0:977e87915078 19 #include <inttypes.h>
vithyat 0:977e87915078 20
vithyat 0:977e87915078 21 #include "mbed-client-classic/m2mconnectionhandlerpimpl.h"
vithyat 0:977e87915078 22 #include "mbed-client/m2mconnectionobserver.h"
vithyat 0:977e87915078 23 #include "mbed-client/m2mconstants.h"
vithyat 0:977e87915078 24 #include "mbed-client/m2msecurity.h"
vithyat 0:977e87915078 25 #include "mbed-client/m2mconnectionhandler.h"
vithyat 0:977e87915078 26
vithyat 0:977e87915078 27 #include "pal.h"
vithyat 0:977e87915078 28
vithyat 0:977e87915078 29 #include "eventOS_scheduler.h"
vithyat 0:977e87915078 30
vithyat 0:977e87915078 31 #include "eventOS_event_timer.h"
vithyat 0:977e87915078 32
vithyat 0:977e87915078 33 #include "mbed-trace/mbed_trace.h"
vithyat 0:977e87915078 34
vithyat 0:977e87915078 35 #include <stdlib.h> // free() and malloc()
vithyat 0:977e87915078 36
vithyat 0:977e87915078 37 #define TRACE_GROUP "mClt"
vithyat 0:977e87915078 38
vithyat 0:977e87915078 39 #ifndef MBED_CONF_MBED_CLIENT_TLS_MAX_RETRY
vithyat 0:977e87915078 40 #define MBED_CONF_MBED_CLIENT_TLS_MAX_RETRY 60
vithyat 0:977e87915078 41 #endif
vithyat 0:977e87915078 42
vithyat 0:977e87915078 43 #if (PAL_DNS_API_VERSION == 1) && defined(TARGET_LIKE_MBED)
vithyat 0:977e87915078 44 #error "For async PAL DNS only API v2 or greater is supported on Mbed."
vithyat 0:977e87915078 45 #endif
vithyat 0:977e87915078 46
vithyat 0:977e87915078 47 int8_t M2MConnectionHandlerPimpl::_tasklet_id = -1;
vithyat 0:977e87915078 48
vithyat 0:977e87915078 49 // This is called from event loop, but as it is static C function, this is just a wrapper
vithyat 0:977e87915078 50 // which calls C++ on the instance.
vithyat 0:977e87915078 51 extern "C" void eventloop_event_handler(arm_event_s *event)
vithyat 0:977e87915078 52 {
vithyat 0:977e87915078 53 tr_debug("M2MConnectionHandlerPimpl::eventloop_event_handler %d", event->event_type);
vithyat 0:977e87915078 54 if (event->event_type != M2MConnectionHandlerPimpl::ESocketIdle) {
vithyat 0:977e87915078 55 if(!event->data_ptr) {
vithyat 0:977e87915078 56 tr_error("M2MConnectionHandlerPimpl::eventloop_event_handler event->data_ptr=NULL !!!!");
vithyat 0:977e87915078 57 assert(event->data_ptr);
vithyat 0:977e87915078 58 }
vithyat 0:977e87915078 59 M2MConnectionHandlerPimpl* instance = (M2MConnectionHandlerPimpl*)event->data_ptr;
vithyat 0:977e87915078 60 instance->event_handler(event);
vithyat 0:977e87915078 61 }
vithyat 0:977e87915078 62 }
vithyat 0:977e87915078 63
vithyat 0:977e87915078 64 // event handler that forwards the event according to its type and/or connection state
vithyat 0:977e87915078 65 void M2MConnectionHandlerPimpl::event_handler(arm_event_s *event)
vithyat 0:977e87915078 66 {
vithyat 0:977e87915078 67 switch (event->event_type) {
vithyat 0:977e87915078 68
vithyat 0:977e87915078 69 // Event from socket callback method
vithyat 0:977e87915078 70 case M2MConnectionHandlerPimpl::ESocketCallback:
vithyat 0:977e87915078 71 case M2MConnectionHandlerPimpl::ESocketTimerCallback:
vithyat 0:977e87915078 72
vithyat 0:977e87915078 73 // this will enable sending more events during this event processing, but that is less evil than missing one
vithyat 0:977e87915078 74 _suppressable_event_in_flight = false;
vithyat 0:977e87915078 75
vithyat 0:977e87915078 76 if (_socket_state == M2MConnectionHandlerPimpl::ESocketStateHandshaking) {
vithyat 0:977e87915078 77 receive_handshake_handler();
vithyat 0:977e87915078 78 } else if ((_socket_state == M2MConnectionHandlerPimpl::ESocketStateUnsecureConnection) ||
vithyat 0:977e87915078 79 (_socket_state == M2MConnectionHandlerPimpl::ESocketStateSecureConnection)) {
vithyat 0:977e87915078 80 // the connection is established
vithyat 0:977e87915078 81 receive_handler();
vithyat 0:977e87915078 82 } else {
vithyat 0:977e87915078 83 socket_connect_handler();
vithyat 0:977e87915078 84 }
vithyat 0:977e87915078 85
vithyat 0:977e87915078 86 // Receive processing could have changed state, so recheck
vithyat 0:977e87915078 87 if ((_socket_state == M2MConnectionHandlerPimpl::ESocketStateUnsecureConnection) ||
vithyat 0:977e87915078 88 (_socket_state == M2MConnectionHandlerPimpl::ESocketStateSecureConnection)) {
vithyat 0:977e87915078 89 // the connection is established
vithyat 0:977e87915078 90 send_socket_data();
vithyat 0:977e87915078 91 }
vithyat 0:977e87915078 92 break;
vithyat 0:977e87915078 93
vithyat 0:977e87915078 94 // Data send request from client side
vithyat 0:977e87915078 95 case M2MConnectionHandlerPimpl::ESocketSend:
vithyat 0:977e87915078 96 send_socket_data();
vithyat 0:977e87915078 97 break;
vithyat 0:977e87915078 98
vithyat 0:977e87915078 99 // DNS resolved successfully
vithyat 0:977e87915078 100 case M2MConnectionHandlerPimpl::ESocketDnsResolved:
vithyat 0:977e87915078 101 handle_dns_result(true);
vithyat 0:977e87915078 102 break;
vithyat 0:977e87915078 103
vithyat 0:977e87915078 104 // DNS resolving failed
vithyat 0:977e87915078 105 case M2MConnectionHandlerPimpl::ESocketDnsError:
vithyat 0:977e87915078 106 handle_dns_result(false);
vithyat 0:977e87915078 107 break;
vithyat 0:977e87915078 108
vithyat 0:977e87915078 109 // Establish the connection by connecting the socket
vithyat 0:977e87915078 110 case M2MConnectionHandlerPimpl::ESocketConnect:
vithyat 0:977e87915078 111 socket_connect_handler();
vithyat 0:977e87915078 112 break;
vithyat 0:977e87915078 113
vithyat 0:977e87915078 114 case M2MConnectionHandlerPimpl::ESocketClose:
vithyat 0:977e87915078 115 close_socket();
vithyat 0:977e87915078 116 break;
vithyat 0:977e87915078 117
vithyat 0:977e87915078 118 default:
vithyat 0:977e87915078 119 tr_debug("M2MConnectionHandlerPimpl::connection_event_handler: default type: %d", (int)event->event_type);
vithyat 0:977e87915078 120 break;
vithyat 0:977e87915078 121 }
vithyat 0:977e87915078 122 }
vithyat 0:977e87915078 123
vithyat 0:977e87915078 124 // This callback is used from PAL sockets, it is called with object instance as argument.
vithyat 0:977e87915078 125 // This is received from "some" socket event from "some" socket and the C++ side is responsible
vithyat 0:977e87915078 126 // of forwarding it or ignoring the event completely.
vithyat 0:977e87915078 127 extern "C" void socket_event_handler(void* arg)
vithyat 0:977e87915078 128 {
vithyat 0:977e87915078 129 M2MConnectionHandlerPimpl* instance = (M2MConnectionHandlerPimpl*)arg;
vithyat 0:977e87915078 130
vithyat 0:977e87915078 131 if (!instance) {
vithyat 0:977e87915078 132 tr_error("Invalid callback argument");
vithyat 0:977e87915078 133 return;
vithyat 0:977e87915078 134 }
vithyat 0:977e87915078 135
vithyat 0:977e87915078 136 instance->send_socket_event(M2MConnectionHandlerPimpl::ESocketCallback);
vithyat 0:977e87915078 137 }
vithyat 0:977e87915078 138
vithyat 0:977e87915078 139 void M2MConnectionHandlerPimpl::send_socket_event(SocketEvent event_type)
vithyat 0:977e87915078 140 {
vithyat 0:977e87915078 141 // the socket callback events can safely be suppressed, the receiving end must tolerate that
vithyat 0:977e87915078 142 if (event_type == ESocketCallback) {
vithyat 0:977e87915078 143 // only the socket connected state supports retries somehow
vithyat 0:977e87915078 144 if (_suppressable_event_in_flight == false) {
vithyat 0:977e87915078 145 _suppressable_event_in_flight = true;
vithyat 0:977e87915078 146 } else {
vithyat 0:977e87915078 147 // XXX: DO NOT ADD FOLLOWING LINE TO OFFICIAL GIT, THIS WILL KILL SOME NETWORK STACKS
vithyat 0:977e87915078 148 // IF EVENT IS SENT FROM A INTERRUPT CONTEXT
vithyat 0:977e87915078 149 // tr_debug("** SKIPPING event");
vithyat 0:977e87915078 150 return;
vithyat 0:977e87915078 151 }
vithyat 0:977e87915078 152 }
vithyat 0:977e87915078 153
vithyat 0:977e87915078 154 if (!send_event(event_type)) {
vithyat 0:977e87915078 155 // TODO: give a proper error based on state instead of this
vithyat 0:977e87915078 156 _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
vithyat 0:977e87915078 157 }
vithyat 0:977e87915078 158 }
vithyat 0:977e87915078 159
vithyat 0:977e87915078 160 M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
vithyat 0:977e87915078 161 M2MConnectionSecurity* sec,
vithyat 0:977e87915078 162 M2MInterface::BindingMode mode,
vithyat 0:977e87915078 163 M2MInterface::NetworkStack stack)
vithyat 0:977e87915078 164 :_base(base),
vithyat 0:977e87915078 165 _observer(observer),
vithyat 0:977e87915078 166 _security_impl(sec),
vithyat 0:977e87915078 167 _security(NULL),
vithyat 0:977e87915078 168 _binding_mode(mode),
vithyat 0:977e87915078 169 _socket(0),
vithyat 0:977e87915078 170 _server_type(M2MConnectionObserver::LWM2MServer),
vithyat 0:977e87915078 171 _server_port(0),
vithyat 0:977e87915078 172 _listen_port(0),
vithyat 0:977e87915078 173 _net_iface(0),
vithyat 0:977e87915078 174 #if (PAL_DNS_API_VERSION == 0) || (PAL_DNS_API_VERSION == 1)
vithyat 0:977e87915078 175 _socket_address_len(0),
vithyat 0:977e87915078 176 #elif (PAL_DNS_API_VERSION == 2)
vithyat 0:977e87915078 177 _handler_async_DNS(0),
vithyat 0:977e87915078 178 #endif
vithyat 0:977e87915078 179 _socket_state(ESocketStateDisconnected),
vithyat 0:977e87915078 180 _handshake_retry(0),
vithyat 0:977e87915078 181 _suppressable_event_in_flight(false),
vithyat 0:977e87915078 182 _secure_connection(false)
vithyat 0:977e87915078 183 {
vithyat 0:977e87915078 184 #ifndef PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 185 if (is_tcp_connection()) {
vithyat 0:977e87915078 186 tr_error("ConnectionHandler: TCP support not available.");
vithyat 0:977e87915078 187 return;
vithyat 0:977e87915078 188 }
vithyat 0:977e87915078 189 #endif
vithyat 0:977e87915078 190
vithyat 0:977e87915078 191 if (PAL_SUCCESS != pal_init()) {
vithyat 0:977e87915078 192 tr_error("PAL init failed.");
vithyat 0:977e87915078 193 }
vithyat 0:977e87915078 194
vithyat 0:977e87915078 195 memset(&_address, 0, sizeof _address);
vithyat 0:977e87915078 196 memset((void*)&_socket_address, 0, sizeof _socket_address);
vithyat 0:977e87915078 197 memset(&_ipV4Addr, 0, sizeof(palIpV4Addr_t));
vithyat 0:977e87915078 198 memset(&_ipV6Addr, 0, sizeof(palIpV6Addr_t));
vithyat 0:977e87915078 199 ns_list_init(&_linked_list_send_data);
vithyat 0:977e87915078 200
vithyat 0:977e87915078 201 eventOS_scheduler_mutex_wait();
vithyat 0:977e87915078 202 if (M2MConnectionHandlerPimpl::_tasklet_id == -1) {
vithyat 0:977e87915078 203 M2MConnectionHandlerPimpl::_tasklet_id = eventOS_event_handler_create(&eventloop_event_handler, ESocketIdle);
vithyat 0:977e87915078 204 }
vithyat 0:977e87915078 205 eventOS_scheduler_mutex_release();
vithyat 0:977e87915078 206 }
vithyat 0:977e87915078 207
vithyat 0:977e87915078 208 M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()
vithyat 0:977e87915078 209 {
vithyat 0:977e87915078 210 tr_debug("~M2MConnectionHandlerPimpl()");
vithyat 0:977e87915078 211 #if (PAL_DNS_API_VERSION == 2)
vithyat 0:977e87915078 212 if ( _handler_async_DNS > 0) {
vithyat 0:977e87915078 213 pal_cancelAddressInfoAsync(_handler_async_DNS);
vithyat 0:977e87915078 214 }
vithyat 0:977e87915078 215 #endif
vithyat 0:977e87915078 216
vithyat 0:977e87915078 217 close_socket();
vithyat 0:977e87915078 218 delete _security_impl;
vithyat 0:977e87915078 219 _security_impl = NULL;
vithyat 0:977e87915078 220 pal_destroy();
vithyat 0:977e87915078 221 tr_debug("~M2MConnectionHandlerPimpl() - OUT");
vithyat 0:977e87915078 222 }
vithyat 0:977e87915078 223
vithyat 0:977e87915078 224 bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port)
vithyat 0:977e87915078 225 {
vithyat 0:977e87915078 226 _listen_port = listen_port;
vithyat 0:977e87915078 227 return true;
vithyat 0:977e87915078 228 }
vithyat 0:977e87915078 229
vithyat 0:977e87915078 230 bool M2MConnectionHandlerPimpl::send_event(SocketEvent event_type)
vithyat 0:977e87915078 231 {
vithyat 0:977e87915078 232 arm_event_s event = {0};
vithyat 0:977e87915078 233
vithyat 0:977e87915078 234 event.receiver = M2MConnectionHandlerPimpl::_tasklet_id;
vithyat 0:977e87915078 235 event.sender = 0;
vithyat 0:977e87915078 236 event.event_type = event_type;
vithyat 0:977e87915078 237 event.data_ptr = this;
vithyat 0:977e87915078 238 event.event_data = 0;
vithyat 0:977e87915078 239 event.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
vithyat 0:977e87915078 240 return !eventOS_event_send(&event);
vithyat 0:977e87915078 241 }
vithyat 0:977e87915078 242
vithyat 0:977e87915078 243
vithyat 0:977e87915078 244 // This callback is used from PAL pal_getAddressInfoAsync,
vithyat 0:977e87915078 245 #if (PAL_DNS_API_VERSION == 2)
vithyat 0:977e87915078 246 extern "C" void address_resolver_cb(const char* url, palSocketAddress_t* address, palStatus_t status, void* callbackArgument)
vithyat 0:977e87915078 247 {
vithyat 0:977e87915078 248 tr_debug("M2MConnectionHandlerPimpl::address_resolver callback");
vithyat 0:977e87915078 249 M2MConnectionHandlerPimpl* instance = (M2MConnectionHandlerPimpl*)callbackArgument;
vithyat 0:977e87915078 250
vithyat 0:977e87915078 251 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 252 tr_error("M2MConnectionHandlerPimpl::address_resolver callback failed with %" PRIx32, status);
vithyat 0:977e87915078 253 if (!(instance->send_event(M2MConnectionHandlerPimpl::ESocketDnsError))) {
vithyat 0:977e87915078 254 tr_error("M2MConnectionHandlerPimpl::address_resolver callback, error event alloc fail.");
vithyat 0:977e87915078 255 }
vithyat 0:977e87915078 256 } else {
vithyat 0:977e87915078 257 if (!(instance->send_event(M2MConnectionHandlerPimpl::ESocketDnsResolved))) {
vithyat 0:977e87915078 258 tr_error("M2MConnectionHandlerPimpl::address_resolver callback, resolved event alloc fail.");
vithyat 0:977e87915078 259 }
vithyat 0:977e87915078 260 }
vithyat 0:977e87915078 261 }
vithyat 0:977e87915078 262 #endif
vithyat 0:977e87915078 263
vithyat 0:977e87915078 264 bool M2MConnectionHandlerPimpl::address_resolver(void)
vithyat 0:977e87915078 265 {
vithyat 0:977e87915078 266 palStatus_t status;
vithyat 0:977e87915078 267 bool ret = false;
vithyat 0:977e87915078 268
vithyat 0:977e87915078 269 #if (PAL_DNS_API_VERSION == 2)
vithyat 0:977e87915078 270 tr_debug("M2MConnectionHandlerPimpl::address_resolver:asynchronous DNS");
vithyat 0:977e87915078 271 _handler_async_DNS = 0;
vithyat 0:977e87915078 272 status = pal_getAddressInfoAsync(_server_address.c_str(), (palSocketAddress_t*)&_socket_address, &address_resolver_cb, this, &_handler_async_DNS);
vithyat 0:977e87915078 273 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 274 tr_error("M2MConnectionHandlerPimpl::address_resolver, pal_getAddressInfoAsync fail. %" PRIx32, status);
vithyat 0:977e87915078 275 _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
vithyat 0:977e87915078 276 }
vithyat 0:977e87915078 277 else {
vithyat 0:977e87915078 278 ret = true;
vithyat 0:977e87915078 279 }
vithyat 0:977e87915078 280 #else // #if (PAL_DNS_API_VERSION == 0)
vithyat 0:977e87915078 281 tr_debug("M2MConnectionHandlerPimpl::address_resolver:synchronous DNS");
vithyat 0:977e87915078 282 status = pal_getAddressInfo(_server_address.c_str(), (palSocketAddress_t*)&_socket_address, &_socket_address_len);
vithyat 0:977e87915078 283 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 284 tr_error("M2MConnectionHandlerPimpl::getAddressInfo failed with %" PRIx32, status);
vithyat 0:977e87915078 285 if (!send_event(ESocketDnsError)) {
vithyat 0:977e87915078 286 tr_error("M2MConnectionHandlerPimpl::address_resolver, error event alloc fail.");
vithyat 0:977e87915078 287 }
vithyat 0:977e87915078 288 } else {
vithyat 0:977e87915078 289 if (!send_event(ESocketDnsResolved)) {
vithyat 0:977e87915078 290 tr_error("M2MConnectionHandlerPimpl::address_resolver, resolved event alloc fail.");
vithyat 0:977e87915078 291 }
vithyat 0:977e87915078 292 else {
vithyat 0:977e87915078 293 ret = true;
vithyat 0:977e87915078 294 }
vithyat 0:977e87915078 295 }
vithyat 0:977e87915078 296 #endif
vithyat 0:977e87915078 297 return ret;
vithyat 0:977e87915078 298 }
vithyat 0:977e87915078 299
vithyat 0:977e87915078 300 void M2MConnectionHandlerPimpl::handle_dns_result(bool success)
vithyat 0:977e87915078 301 {
vithyat 0:977e87915078 302 #if (PAL_DNS_API_VERSION == 2)
vithyat 0:977e87915078 303 _handler_async_DNS = 0;
vithyat 0:977e87915078 304 #endif
vithyat 0:977e87915078 305 if (_socket_state != ESocketStateDNSResolving) {
vithyat 0:977e87915078 306 tr_warn("M2MConnectionHandlerPimpl::handle_dns_result() called, not in ESocketStateDNSResolving state!");
vithyat 0:977e87915078 307 return;
vithyat 0:977e87915078 308 }
vithyat 0:977e87915078 309
vithyat 0:977e87915078 310 if (success) {
vithyat 0:977e87915078 311 _socket_state = EsocketStateInitializeConnection;
vithyat 0:977e87915078 312 socket_connect_handler();
vithyat 0:977e87915078 313
vithyat 0:977e87915078 314 } else {
vithyat 0:977e87915078 315 _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
vithyat 0:977e87915078 316 }
vithyat 0:977e87915078 317 }
vithyat 0:977e87915078 318
vithyat 0:977e87915078 319 bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address,
vithyat 0:977e87915078 320 const uint16_t server_port,
vithyat 0:977e87915078 321 M2MConnectionObserver::ServerType server_type,
vithyat 0:977e87915078 322 const M2MSecurity* security)
vithyat 0:977e87915078 323 {
vithyat 0:977e87915078 324 #if (PAL_DNS_API_VERSION == 2)
vithyat 0:977e87915078 325 if ( _handler_async_DNS > 0) {
vithyat 0:977e87915078 326 if (pal_cancelAddressInfoAsync(_handler_async_DNS) != PAL_SUCCESS) {
vithyat 0:977e87915078 327 return false;
vithyat 0:977e87915078 328 }
vithyat 0:977e87915078 329 }
vithyat 0:977e87915078 330 #endif
vithyat 0:977e87915078 331 _socket_state = ESocketStateDNSResolving;
vithyat 0:977e87915078 332 _security = security;
vithyat 0:977e87915078 333
vithyat 0:977e87915078 334 int32_t security_instance_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
vithyat 0:977e87915078 335 if (server_type == M2MConnectionObserver::Bootstrap) {
vithyat 0:977e87915078 336 security_instance_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
vithyat 0:977e87915078 337 }
vithyat 0:977e87915078 338
vithyat 0:977e87915078 339 if (_security &&
vithyat 0:977e87915078 340 security_instance_id >= 0 &&
vithyat 0:977e87915078 341 (_security->resource_value_int(M2MSecurity::SecurityMode, security_instance_id) == M2MSecurity::Certificate ||
vithyat 0:977e87915078 342 _security->resource_value_int(M2MSecurity::SecurityMode, security_instance_id) == M2MSecurity::Psk)) {
vithyat 0:977e87915078 343 _secure_connection = true;
vithyat 0:977e87915078 344 }
vithyat 0:977e87915078 345
vithyat 0:977e87915078 346 _server_port = server_port;
vithyat 0:977e87915078 347 _server_type = server_type;
vithyat 0:977e87915078 348 _server_address = server_address;
vithyat 0:977e87915078 349
vithyat 0:977e87915078 350
vithyat 0:977e87915078 351 return address_resolver();
vithyat 0:977e87915078 352 }
vithyat 0:977e87915078 353
vithyat 0:977e87915078 354 void M2MConnectionHandlerPimpl::socket_connect_handler()
vithyat 0:977e87915078 355 {
vithyat 0:977e87915078 356 palStatus_t status;
vithyat 0:977e87915078 357 int32_t security_instance_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
vithyat 0:977e87915078 358 if (_server_type == M2MConnectionObserver::Bootstrap) {
vithyat 0:977e87915078 359 security_instance_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
vithyat 0:977e87915078 360 }
vithyat 0:977e87915078 361
vithyat 0:977e87915078 362 tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - _socket_state = %d", _socket_state);
vithyat 0:977e87915078 363
vithyat 0:977e87915078 364 switch (_socket_state) {
vithyat 0:977e87915078 365 case ESocketStateCloseBeingCalled:
vithyat 0:977e87915078 366 case ESocketStateDNSResolving:
vithyat 0:977e87915078 367 case ESocketStateDisconnected:
vithyat 0:977e87915078 368 case ESocketStateHandshaking:
vithyat 0:977e87915078 369 case ESocketStateUnsecureConnection:
vithyat 0:977e87915078 370 case ESocketStateSecureConnection:
vithyat 0:977e87915078 371 // Ignore these events
vithyat 0:977e87915078 372 break;
vithyat 0:977e87915078 373
vithyat 0:977e87915078 374 case EsocketStateInitializeConnection:
vithyat 0:977e87915078 375
vithyat 0:977e87915078 376 // Initialize the socket to stable state
vithyat 0:977e87915078 377 close_socket();
vithyat 0:977e87915078 378
vithyat 0:977e87915078 379 status = pal_setSockAddrPort((palSocketAddress_t*)&_socket_address, _server_port);
vithyat 0:977e87915078 380
vithyat 0:977e87915078 381 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 382 tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - setSockAddrPort err: %" PRIx32, status);
vithyat 0:977e87915078 383 } else {
vithyat 0:977e87915078 384 tr_debug("address family: %d", (int)_socket_address.addressType);
vithyat 0:977e87915078 385 }
vithyat 0:977e87915078 386
vithyat 0:977e87915078 387 if (_socket_address.addressType == PAL_AF_INET) {
vithyat 0:977e87915078 388 status = pal_getSockAddrIPV4Addr((palSocketAddress_t*)&_socket_address,_ipV4Addr);
vithyat 0:977e87915078 389 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 390 tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - sockAddr4, err: %" PRIx32, status);
vithyat 0:977e87915078 391 _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
vithyat 0:977e87915078 392 return;
vithyat 0:977e87915078 393 }
vithyat 0:977e87915078 394
vithyat 0:977e87915078 395 tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - IPv4 Address %d.%d.%d.%d",
vithyat 0:977e87915078 396 _ipV4Addr[0], _ipV4Addr[1], _ipV4Addr[2], _ipV4Addr[3]);
vithyat 0:977e87915078 397
vithyat 0:977e87915078 398 _address._address = (void*)_ipV4Addr;
vithyat 0:977e87915078 399 _address._length = PAL_IPV4_ADDRESS_SIZE;
vithyat 0:977e87915078 400 _address._port = _server_port;
vithyat 0:977e87915078 401 } else if (_socket_address.addressType == PAL_AF_INET6) {
vithyat 0:977e87915078 402 status = pal_getSockAddrIPV6Addr((palSocketAddress_t*)&_socket_address,_ipV6Addr);
vithyat 0:977e87915078 403 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 404 tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - sockAddr6, err: %" PRIx32, status);
vithyat 0:977e87915078 405 _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
vithyat 0:977e87915078 406 return;
vithyat 0:977e87915078 407 }
vithyat 0:977e87915078 408
vithyat 0:977e87915078 409 tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - IPv6 Address: %s", mbed_trace_ipv6(_ipV6Addr));
vithyat 0:977e87915078 410
vithyat 0:977e87915078 411 _address._address = (void*)_ipV6Addr;
vithyat 0:977e87915078 412 _address._length = PAL_IPV6_ADDRESS_SIZE;
vithyat 0:977e87915078 413 _address._port = _server_port;
vithyat 0:977e87915078 414 } else {
vithyat 0:977e87915078 415 tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - socket config error, stack: %d", (int)_socket_address.addressType);
vithyat 0:977e87915078 416 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
vithyat 0:977e87915078 417 return;
vithyat 0:977e87915078 418 }
vithyat 0:977e87915078 419
vithyat 0:977e87915078 420 if (!init_socket()) {
vithyat 0:977e87915078 421 tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - socket init error");
vithyat 0:977e87915078 422 // The init_socket() calls the socket_error() -callback directly, so it must not be
vithyat 0:977e87915078 423 // done here too.
vithyat 0:977e87915078 424 return;
vithyat 0:977e87915078 425 }
vithyat 0:977e87915078 426
vithyat 0:977e87915078 427 // This state was used to ignore the spurious events _during_ the call of non-blocking pal_connect().
vithyat 0:977e87915078 428 // Now that we just retry connect when it is not yet succeeded anyway this state might be removed completely.
vithyat 0:977e87915078 429 _socket_state = ESocketStateConnectBeingCalled;
vithyat 0:977e87915078 430
vithyat 0:977e87915078 431 // fall through is intentional
vithyat 0:977e87915078 432 case ESocketStateConnectBeingCalled:
vithyat 0:977e87915078 433 case ESocketStateConnecting:
vithyat 0:977e87915078 434 if (is_tcp_connection()) {
vithyat 0:977e87915078 435 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 436 tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - Using TCP");
vithyat 0:977e87915078 437
vithyat 0:977e87915078 438 status = pal_connect(_socket, (palSocketAddress_t*)&_socket_address, sizeof(_socket_address));
vithyat 0:977e87915078 439
vithyat 0:977e87915078 440 if ((status == PAL_ERR_SOCKET_IN_PROGRES) || (status == PAL_ERR_SOCKET_WOULD_BLOCK)) {
vithyat 0:977e87915078 441 // In this case the connect is done asynchronously, and the pal_socketMiniSelect()
vithyat 0:977e87915078 442 // will be used to detect the end of connect.
vithyat 0:977e87915078 443 tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - pal_connect(): %" PRIx32 ", async connect started", status);
vithyat 0:977e87915078 444 // we need to wait for the event
vithyat 0:977e87915078 445 _socket_state = ESocketStateConnecting;
vithyat 0:977e87915078 446 break;
vithyat 0:977e87915078 447
vithyat 0:977e87915078 448 } else if (status == PAL_SUCCESS || status == PAL_ERR_SOCKET_ALREADY_CONNECTED) {
vithyat 0:977e87915078 449
vithyat 0:977e87915078 450 tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - pal_connect(): success");
vithyat 0:977e87915078 451 _socket_state = ESocketStateConnected;
vithyat 0:977e87915078 452
vithyat 0:977e87915078 453 } else {
vithyat 0:977e87915078 454 tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - pal_connect(): failed: %" PRIx32, status);
vithyat 0:977e87915078 455 close_socket();
vithyat 0:977e87915078 456 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
vithyat 0:977e87915078 457 return;
vithyat 0:977e87915078 458 }
vithyat 0:977e87915078 459 #else
vithyat 0:977e87915078 460 tr_error("socket_connect_handler() - TCP not configured"
vithyat 0:977e87915078 461 #endif //PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 462 } else {
vithyat 0:977e87915078 463 tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - Using UDP");
vithyat 0:977e87915078 464 _socket_state = ESocketStateConnected;
vithyat 0:977e87915078 465 }
vithyat 0:977e87915078 466
vithyat 0:977e87915078 467 // fall through is a normal flow in case the UDP was used or pal_connect() happened to return immediately with PAL_SUCCESS
vithyat 0:977e87915078 468 case ESocketStateConnected:
vithyat 0:977e87915078 469 if (_security && security_instance_id >= 0) {
vithyat 0:977e87915078 470 if (_secure_connection) {
vithyat 0:977e87915078 471 if ( _security_impl != NULL ) {
vithyat 0:977e87915078 472 _security_impl->reset();
vithyat 0:977e87915078 473 int ret_code = _security_impl->init(_security, security_instance_id);
vithyat 0:977e87915078 474 if (ret_code == M2MConnectionHandler::ERROR_NONE) {
vithyat 0:977e87915078 475 // Initiate handshake. Perhaps there could be a separate event type for this?
vithyat 0:977e87915078 476 _socket_state = ESocketStateHandshaking;
vithyat 0:977e87915078 477 send_socket_event(ESocketCallback);
vithyat 0:977e87915078 478 } else {
vithyat 0:977e87915078 479 tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - init failed");
vithyat 0:977e87915078 480 close_socket();
vithyat 0:977e87915078 481
vithyat 0:977e87915078 482 if (ret_code == M2MConnectionHandler::FAILED_TO_READ_CREDENTIALS) {
vithyat 0:977e87915078 483 _observer.socket_error(M2MConnectionHandler::FAILED_TO_READ_CREDENTIALS, false);
vithyat 0:977e87915078 484 } else {
vithyat 0:977e87915078 485 _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, true);
vithyat 0:977e87915078 486 }
vithyat 0:977e87915078 487
vithyat 0:977e87915078 488 return;
vithyat 0:977e87915078 489 }
vithyat 0:977e87915078 490 } else {
vithyat 0:977e87915078 491 tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - sec is null");
vithyat 0:977e87915078 492 close_socket();
vithyat 0:977e87915078 493 _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, true);
vithyat 0:977e87915078 494 return;
vithyat 0:977e87915078 495 }
vithyat 0:977e87915078 496 }
vithyat 0:977e87915078 497 }
vithyat 0:977e87915078 498 if (_socket_state != ESocketStateHandshaking) {
vithyat 0:977e87915078 499 _socket_state = ESocketStateUnsecureConnection;
vithyat 0:977e87915078 500 _observer.address_ready(_address,
vithyat 0:977e87915078 501 _server_type,
vithyat 0:977e87915078 502 _address._port);
vithyat 0:977e87915078 503 }
vithyat 0:977e87915078 504 break;
vithyat 0:977e87915078 505
vithyat 0:977e87915078 506 }
vithyat 0:977e87915078 507 }
vithyat 0:977e87915078 508
vithyat 0:977e87915078 509 bool M2MConnectionHandlerPimpl::send_data(uint8_t *data,
vithyat 0:977e87915078 510 uint16_t data_len,
vithyat 0:977e87915078 511 sn_nsdl_addr_s *address)
vithyat 0:977e87915078 512 {
vithyat 0:977e87915078 513 if (address == NULL || data == NULL || !data_len || _socket_state < ESocketStateUnsecureConnection) {
vithyat 0:977e87915078 514 tr_warn("M2MConnectionHandlerPimpl::send_data() - too early");
vithyat 0:977e87915078 515 return false;
vithyat 0:977e87915078 516 }
vithyat 0:977e87915078 517
vithyat 0:977e87915078 518 send_data_queue_s* out_data = (send_data_queue_s*)malloc(sizeof(send_data_queue_s));
vithyat 0:977e87915078 519 if (!out_data) {
vithyat 0:977e87915078 520 return false;
vithyat 0:977e87915078 521 }
vithyat 0:977e87915078 522
vithyat 0:977e87915078 523 memset(out_data, 0, sizeof(send_data_queue_s));
vithyat 0:977e87915078 524
vithyat 0:977e87915078 525 uint8_t offset = 0;
vithyat 0:977e87915078 526 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 527 if (is_tcp_connection() && !_secure_connection ) {
vithyat 0:977e87915078 528 offset = 4;
vithyat 0:977e87915078 529 }
vithyat 0:977e87915078 530 #endif
vithyat 0:977e87915078 531
vithyat 0:977e87915078 532 out_data->data = (uint8_t*)malloc(data_len + offset);
vithyat 0:977e87915078 533 if (!out_data->data) {
vithyat 0:977e87915078 534 free(out_data);
vithyat 0:977e87915078 535 return false;
vithyat 0:977e87915078 536 }
vithyat 0:977e87915078 537
vithyat 0:977e87915078 538 // TCP non-secure
vithyat 0:977e87915078 539 // We need to "shim" the length in front
vithyat 0:977e87915078 540 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 541 if (is_tcp_connection() && !_secure_connection ) {
vithyat 0:977e87915078 542 out_data->data[0] = 0;
vithyat 0:977e87915078 543 out_data->data[1] = 0;
vithyat 0:977e87915078 544 out_data->data[2] = (data_len >> 8 ) & 0xff;
vithyat 0:977e87915078 545 out_data->data[3] = data_len & 0xff;
vithyat 0:977e87915078 546 }
vithyat 0:977e87915078 547 #endif //PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 548
vithyat 0:977e87915078 549 memcpy(out_data->data + offset, data, data_len);
vithyat 0:977e87915078 550 out_data->data_len = data_len + offset;
vithyat 0:977e87915078 551
vithyat 0:977e87915078 552 claim_mutex();
vithyat 0:977e87915078 553 ns_list_add_to_end(&_linked_list_send_data, out_data);
vithyat 0:977e87915078 554 release_mutex();
vithyat 0:977e87915078 555
vithyat 0:977e87915078 556 if (!send_event(ESocketSend)) {
vithyat 0:977e87915078 557 // Event push failed, free the buffer
vithyat 0:977e87915078 558 claim_mutex();
vithyat 0:977e87915078 559 ns_list_remove(&_linked_list_send_data, out_data);
vithyat 0:977e87915078 560 release_mutex();
vithyat 0:977e87915078 561 free(out_data->data);
vithyat 0:977e87915078 562 free(out_data);
vithyat 0:977e87915078 563 return false;
vithyat 0:977e87915078 564 }
vithyat 0:977e87915078 565
vithyat 0:977e87915078 566 return true;
vithyat 0:977e87915078 567 }
vithyat 0:977e87915078 568
vithyat 0:977e87915078 569 void M2MConnectionHandlerPimpl::send_socket_data()
vithyat 0:977e87915078 570 {
vithyat 0:977e87915078 571 tr_debug("M2MConnectionHandlerPimpl::send_socket_data()");
vithyat 0:977e87915078 572 int bytes_sent = 0;
vithyat 0:977e87915078 573 bool success = true;
vithyat 0:977e87915078 574
vithyat 0:977e87915078 575 send_data_queue_s* out_data = get_item_from_list();
vithyat 0:977e87915078 576 if (!out_data) {
vithyat 0:977e87915078 577 return;
vithyat 0:977e87915078 578 }
vithyat 0:977e87915078 579
vithyat 0:977e87915078 580 if (!out_data->data || !out_data->data_len || _socket_state < ESocketStateUnsecureConnection) {
vithyat 0:977e87915078 581 tr_warn("M2MConnectionHandlerPimpl::send_socket_data() - too early");
vithyat 0:977e87915078 582 add_item_to_list(out_data);
vithyat 0:977e87915078 583 return;
vithyat 0:977e87915078 584 }
vithyat 0:977e87915078 585
vithyat 0:977e87915078 586 // Loop until all the data is sent
vithyat 0:977e87915078 587 for (; out_data->offset < out_data->data_len; out_data->offset += bytes_sent) {
vithyat 0:977e87915078 588 // Secure send
vithyat 0:977e87915078 589 if (_socket_state == ESocketStateSecureConnection) {
vithyat 0:977e87915078 590 // TODO! Change the send_message API to take bytes_sent as a out param like the pal send API's.
vithyat 0:977e87915078 591 while ((bytes_sent = _security_impl->send_message(out_data->data + out_data->offset,
vithyat 0:977e87915078 592 out_data->data_len - out_data->offset)) <= 0) {
vithyat 0:977e87915078 593 if (bytes_sent == M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE) {
vithyat 0:977e87915078 594 // Return and wait the next event
vithyat 0:977e87915078 595 add_item_to_list(out_data);
vithyat 0:977e87915078 596 return;
vithyat 0:977e87915078 597 }
vithyat 0:977e87915078 598
vithyat 0:977e87915078 599 if (bytes_sent != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ) {
vithyat 0:977e87915078 600 tr_error("M2MConnectionHandlerPimpl::send_socket_data() - secure, failed %d", bytes_sent);
vithyat 0:977e87915078 601 success = false;
vithyat 0:977e87915078 602 break;
vithyat 0:977e87915078 603 }
vithyat 0:977e87915078 604 }
vithyat 0:977e87915078 605 if (!success) {
vithyat 0:977e87915078 606 break;
vithyat 0:977e87915078 607 }
vithyat 0:977e87915078 608 }
vithyat 0:977e87915078 609 // Unsecure send
vithyat 0:977e87915078 610 else {
vithyat 0:977e87915078 611 bytes_sent = 0;
vithyat 0:977e87915078 612 palStatus_t ret;
vithyat 0:977e87915078 613 if (is_tcp_connection()) {
vithyat 0:977e87915078 614 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 615 ret = pal_send(_socket,
vithyat 0:977e87915078 616 out_data->data + out_data->offset,
vithyat 0:977e87915078 617 out_data->data_len - out_data->offset,
vithyat 0:977e87915078 618 (size_t*)&bytes_sent);
vithyat 0:977e87915078 619 #endif
vithyat 0:977e87915078 620 } else {
vithyat 0:977e87915078 621 ret = pal_sendTo(_socket,
vithyat 0:977e87915078 622 out_data->data + out_data->offset,
vithyat 0:977e87915078 623 out_data->data_len - out_data->offset,
vithyat 0:977e87915078 624 (palSocketAddress_t*)&_socket_address,
vithyat 0:977e87915078 625 sizeof(_socket_address),
vithyat 0:977e87915078 626 (size_t*)&bytes_sent);
vithyat 0:977e87915078 627 }
vithyat 0:977e87915078 628 if (ret == PAL_ERR_SOCKET_WOULD_BLOCK) {
vithyat 0:977e87915078 629 // Return and wait next event
vithyat 0:977e87915078 630 add_item_to_list(out_data);
vithyat 0:977e87915078 631 return;
vithyat 0:977e87915078 632 }
vithyat 0:977e87915078 633 if (ret < 0) {
vithyat 0:977e87915078 634 tr_error("M2MConnectionHandlerPimpl::send_socket_data() - unsecure failed %" PRIx32, ret);
vithyat 0:977e87915078 635 success = false;
vithyat 0:977e87915078 636 break;
vithyat 0:977e87915078 637 }
vithyat 0:977e87915078 638 }
vithyat 0:977e87915078 639 }
vithyat 0:977e87915078 640
vithyat 0:977e87915078 641 free(out_data->data);
vithyat 0:977e87915078 642 free(out_data);
vithyat 0:977e87915078 643
vithyat 0:977e87915078 644 if (!success) {
vithyat 0:977e87915078 645 if (bytes_sent == M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY) {
vithyat 0:977e87915078 646 _observer.socket_error(M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY, true);
vithyat 0:977e87915078 647 } else if (bytes_sent == M2MConnectionHandler::MEMORY_ALLOCATION_FAILED) {
vithyat 0:977e87915078 648 tr_error("M2MConnectionHandlerPimpl::send_socket_data() - memory allocation failed!");
vithyat 0:977e87915078 649 _handshake_retry = 0;
vithyat 0:977e87915078 650 _observer.socket_error(M2MConnectionHandler::MEMORY_ALLOCATION_FAILED, false);
vithyat 0:977e87915078 651 } else {
vithyat 0:977e87915078 652 tr_error("M2MConnectionHandlerPimpl::send_socket_data() - SOCKET_SEND_ERROR");
vithyat 0:977e87915078 653 _observer.socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR, true);
vithyat 0:977e87915078 654 }
vithyat 0:977e87915078 655 close_socket();
vithyat 0:977e87915078 656 } else {
vithyat 0:977e87915078 657 _observer.data_sent();
vithyat 0:977e87915078 658 }
vithyat 0:977e87915078 659 }
vithyat 0:977e87915078 660
vithyat 0:977e87915078 661 bool M2MConnectionHandlerPimpl::start_listening_for_data()
vithyat 0:977e87915078 662 {
vithyat 0:977e87915078 663 return true;
vithyat 0:977e87915078 664 }
vithyat 0:977e87915078 665
vithyat 0:977e87915078 666 void M2MConnectionHandlerPimpl::stop_listening()
vithyat 0:977e87915078 667 {
vithyat 0:977e87915078 668 // Do not call close_socket() directly here.
vithyat 0:977e87915078 669 // This can be called from multiple locations.
vithyat 0:977e87915078 670 send_socket_event(ESocketClose);
vithyat 0:977e87915078 671 }
vithyat 0:977e87915078 672
vithyat 0:977e87915078 673 void M2MConnectionHandlerPimpl::handle_connection_error(int error)
vithyat 0:977e87915078 674 {
vithyat 0:977e87915078 675 tr_error("M2MConnectionHandlerPimpl::handle_connection_error - error %d", error);
vithyat 0:977e87915078 676 _observer.socket_error(error);
vithyat 0:977e87915078 677 }
vithyat 0:977e87915078 678
vithyat 0:977e87915078 679 void M2MConnectionHandlerPimpl::set_platform_network_handler(void *handler)
vithyat 0:977e87915078 680 {
vithyat 0:977e87915078 681 tr_debug("M2MConnectionHandlerPimpl::set_platform_network_handler");
vithyat 0:977e87915078 682
vithyat 0:977e87915078 683 if (PAL_SUCCESS != pal_registerNetworkInterface(handler, &_net_iface)) {
vithyat 0:977e87915078 684 tr_error("M2MConnectionHandlerPimpl::set_platform_network_handler - Interface registration failed.");
vithyat 0:977e87915078 685 }
vithyat 0:977e87915078 686 tr_debug("M2MConnectionHandlerPimpl::set_platform_network_handler - index = %d", _net_iface);
vithyat 0:977e87915078 687 }
vithyat 0:977e87915078 688
vithyat 0:977e87915078 689 void M2MConnectionHandlerPimpl::receive_handshake_handler()
vithyat 0:977e87915078 690 {
vithyat 0:977e87915078 691 int return_value;
vithyat 0:977e87915078 692 tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler()");
vithyat 0:977e87915078 693
vithyat 0:977e87915078 694 // assert(_socket_state == ESocketStateHandshaking);
vithyat 0:977e87915078 695
vithyat 0:977e87915078 696 return_value = _security_impl->connect(_base);
vithyat 0:977e87915078 697
vithyat 0:977e87915078 698 if (return_value == M2MConnectionHandler::ERROR_NONE) {
vithyat 0:977e87915078 699
vithyat 0:977e87915078 700 _handshake_retry = 0;
vithyat 0:977e87915078 701 _socket_state = ESocketStateSecureConnection;
vithyat 0:977e87915078 702 _observer.address_ready(_address,
vithyat 0:977e87915078 703 _server_type,
vithyat 0:977e87915078 704 _server_port);
vithyat 0:977e87915078 705
vithyat 0:977e87915078 706 } else if (return_value == M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY) {
vithyat 0:977e87915078 707 _handshake_retry = 0;
vithyat 0:977e87915078 708 _observer.socket_error(M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY, true);
vithyat 0:977e87915078 709 close_socket();
vithyat 0:977e87915078 710
vithyat 0:977e87915078 711 } else if (return_value == M2MConnectionHandler::MEMORY_ALLOCATION_FAILED) {
vithyat 0:977e87915078 712
vithyat 0:977e87915078 713 tr_error("M2MConnectionHandlerPimpl::receive_handshake_handler() - memory allocation failed");
vithyat 0:977e87915078 714 _handshake_retry = 0;
vithyat 0:977e87915078 715 _observer.socket_error(M2MConnectionHandler::MEMORY_ALLOCATION_FAILED, false);
vithyat 0:977e87915078 716 close_socket();
vithyat 0:977e87915078 717
vithyat 0:977e87915078 718 } else if (return_value != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ) {
vithyat 0:977e87915078 719
vithyat 0:977e87915078 720 tr_error("M2MConnectionHandlerPimpl::receive_handshake_handler() - SSL_HANDSHAKE_ERROR");
vithyat 0:977e87915078 721 _handshake_retry = 0;
vithyat 0:977e87915078 722 _observer.socket_error(M2MConnectionHandler::SSL_HANDSHAKE_ERROR, true);
vithyat 0:977e87915078 723 close_socket();
vithyat 0:977e87915078 724
vithyat 0:977e87915078 725 } else {
vithyat 0:977e87915078 726 // Comes here only if error is M2MConnectionHandler::ERROR_GENERIC
vithyat 0:977e87915078 727 if (_handshake_retry++ > MBED_CONF_MBED_CLIENT_TLS_MAX_RETRY) {
vithyat 0:977e87915078 728
vithyat 0:977e87915078 729 tr_error("M2MConnectionHandlerPimpl::receive_handshake_handler() - Max TLS retry fail");
vithyat 0:977e87915078 730 _handshake_retry = 0;
vithyat 0:977e87915078 731 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT, true);
vithyat 0:977e87915078 732 close_socket();
vithyat 0:977e87915078 733
vithyat 0:977e87915078 734 }
vithyat 0:977e87915078 735 eventOS_event_timer_cancel(ESocketTimerCallback, M2MConnectionHandlerPimpl::_tasklet_id);
vithyat 0:977e87915078 736
vithyat 0:977e87915078 737 // There is required to set event.data_ptr for eventloop_event_handler.
vithyat 0:977e87915078 738 arm_event_s event = {0};
vithyat 0:977e87915078 739 event.receiver = M2MConnectionHandlerPimpl::_tasklet_id;
vithyat 0:977e87915078 740 event.sender = 0;
vithyat 0:977e87915078 741 event.event_id = ESocketTimerCallback;
vithyat 0:977e87915078 742 event.event_type = ESocketTimerCallback;
vithyat 0:977e87915078 743 event.data_ptr = this;
vithyat 0:977e87915078 744 event.event_data = 0;
vithyat 0:977e87915078 745 event.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
vithyat 0:977e87915078 746 eventOS_event_timer_request_in(&event, eventOS_event_timer_ms_to_ticks(1000));
vithyat 0:977e87915078 747 }
vithyat 0:977e87915078 748 }
vithyat 0:977e87915078 749
vithyat 0:977e87915078 750 bool M2MConnectionHandlerPimpl::is_handshake_ongoing() const
vithyat 0:977e87915078 751 {
vithyat 0:977e87915078 752 return (_socket_state == ESocketStateHandshaking);
vithyat 0:977e87915078 753 }
vithyat 0:977e87915078 754
vithyat 0:977e87915078 755 void M2MConnectionHandlerPimpl::receive_handler()
vithyat 0:977e87915078 756 {
vithyat 0:977e87915078 757 // assert(_socket_state > ESocketStateHandshaking);
vithyat 0:977e87915078 758
vithyat 0:977e87915078 759 if (_socket_state == ESocketStateSecureConnection) {
vithyat 0:977e87915078 760
vithyat 0:977e87915078 761 int rcv_size;
vithyat 0:977e87915078 762 unsigned char recv_buffer[BUFFER_LENGTH];
vithyat 0:977e87915078 763
vithyat 0:977e87915078 764 // we need to read as much as there is data available as the events may or may not be suppressed
vithyat 0:977e87915078 765 do {
vithyat 0:977e87915078 766 tr_debug("M2MConnectionHandlerPimpl::receive_handler()..");
vithyat 0:977e87915078 767 rcv_size = _security_impl->read(recv_buffer, sizeof(recv_buffer));
vithyat 0:977e87915078 768 tr_debug("M2MConnectionHandlerPimpl::receive_handler() res: %d", rcv_size);
vithyat 0:977e87915078 769 if (rcv_size > 0) {
vithyat 0:977e87915078 770 _observer.data_available((uint8_t*)recv_buffer,
vithyat 0:977e87915078 771 rcv_size, _address);
vithyat 0:977e87915078 772
vithyat 0:977e87915078 773 } else if (M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY == rcv_size) {
vithyat 0:977e87915078 774 tr_error("M2MConnectionHandlerPimpl::receive_handler() - peer close notify!");
vithyat 0:977e87915078 775 _observer.socket_error(M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY, true);
vithyat 0:977e87915078 776 return;
vithyat 0:977e87915078 777
vithyat 0:977e87915078 778 } else if (M2MConnectionHandler::MEMORY_ALLOCATION_FAILED == rcv_size) {
vithyat 0:977e87915078 779 tr_error("M2MConnectionHandlerPimpl::receive_handler() - memory allocation failed!");
vithyat 0:977e87915078 780 _observer.socket_error(M2MConnectionHandler::MEMORY_ALLOCATION_FAILED, false);
vithyat 0:977e87915078 781 close_socket();
vithyat 0:977e87915078 782 return;
vithyat 0:977e87915078 783
vithyat 0:977e87915078 784 } else if (M2MConnectionHandler::ERROR_GENERIC == rcv_size) {
vithyat 0:977e87915078 785 tr_error("M2MConnectionHandlerPimpl::receive_handler() - secure ERROR_GENERIC");
vithyat 0:977e87915078 786 _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
vithyat 0:977e87915078 787 close_socket();
vithyat 0:977e87915078 788 return;
vithyat 0:977e87915078 789 }
vithyat 0:977e87915078 790 } while (rcv_size > 0 && _socket_state == ESocketStateSecureConnection);
vithyat 0:977e87915078 791
vithyat 0:977e87915078 792 } else {
vithyat 0:977e87915078 793 size_t recv;
vithyat 0:977e87915078 794 palStatus_t status;
vithyat 0:977e87915078 795 unsigned char recv_buffer[BUFFER_LENGTH];
vithyat 0:977e87915078 796 do {
vithyat 0:977e87915078 797 if (is_tcp_connection()) {
vithyat 0:977e87915078 798 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 799 status = pal_recv(_socket, recv_buffer, sizeof(recv_buffer), &recv);
vithyat 0:977e87915078 800 #endif //PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 801 } else {
vithyat 0:977e87915078 802 status = pal_receiveFrom(_socket, recv_buffer, sizeof(recv_buffer), NULL, NULL, &recv);
vithyat 0:977e87915078 803 }
vithyat 0:977e87915078 804
vithyat 0:977e87915078 805 if (status == PAL_ERR_SOCKET_WOULD_BLOCK) {
vithyat 0:977e87915078 806 return;
vithyat 0:977e87915078 807 } else if (status != PAL_SUCCESS) {
vithyat 0:977e87915078 808 tr_error("M2MConnectionHandlerPimpl::receive_handler() - SOCKET_READ_ERROR %" PRIx32, status);
vithyat 0:977e87915078 809 _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
vithyat 0:977e87915078 810 close_socket();
vithyat 0:977e87915078 811 return;
vithyat 0:977e87915078 812 }
vithyat 0:977e87915078 813
vithyat 0:977e87915078 814 tr_debug("M2MConnectionHandlerPimpl::receive_handler() - data received, len: %zu", recv);
vithyat 0:977e87915078 815
vithyat 0:977e87915078 816 if (!is_tcp_connection()) { // Observer for UDP plain mode
vithyat 0:977e87915078 817 _observer.data_available((uint8_t*)recv_buffer, recv, _address);
vithyat 0:977e87915078 818 } else {
vithyat 0:977e87915078 819 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 820 if ( recv < 4 ) {
vithyat 0:977e87915078 821 tr_error("M2MConnectionHandlerPimpl::receive_handler() - TCP SOCKET_READ_ERROR");
vithyat 0:977e87915078 822 _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
vithyat 0:977e87915078 823 close_socket();
vithyat 0:977e87915078 824 return;
vithyat 0:977e87915078 825 }
vithyat 0:977e87915078 826
vithyat 0:977e87915078 827 //We need to "shim" out the length from the front
vithyat 0:977e87915078 828 uint32_t len = (recv_buffer[0] << 24 & 0xFF000000) + (recv_buffer[1] << 16 & 0xFF0000);
vithyat 0:977e87915078 829 len += (recv_buffer[2] << 8 & 0xFF00) + (recv_buffer[3] & 0xFF);
vithyat 0:977e87915078 830 if (len > 0 && len <= recv - 4) {
vithyat 0:977e87915078 831 // Observer for TCP plain mode
vithyat 0:977e87915078 832 _observer.data_available(recv_buffer + 4, len, _address);
vithyat 0:977e87915078 833 }
vithyat 0:977e87915078 834 #endif //PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 835 }
vithyat 0:977e87915078 836 } while (recv > 0 && _socket_state == ESocketStateUnsecureConnection);
vithyat 0:977e87915078 837 }
vithyat 0:977e87915078 838 }
vithyat 0:977e87915078 839
vithyat 0:977e87915078 840 void M2MConnectionHandlerPimpl::claim_mutex()
vithyat 0:977e87915078 841 {
vithyat 0:977e87915078 842 eventOS_scheduler_mutex_wait();
vithyat 0:977e87915078 843 }
vithyat 0:977e87915078 844
vithyat 0:977e87915078 845 void M2MConnectionHandlerPimpl::release_mutex()
vithyat 0:977e87915078 846 {
vithyat 0:977e87915078 847 eventOS_scheduler_mutex_release();
vithyat 0:977e87915078 848 }
vithyat 0:977e87915078 849
vithyat 0:977e87915078 850 bool M2MConnectionHandlerPimpl::init_socket()
vithyat 0:977e87915078 851 {
vithyat 0:977e87915078 852 palSocketType_t socket_type = PAL_SOCK_DGRAM;
vithyat 0:977e87915078 853 palStatus_t status;
vithyat 0:977e87915078 854 palSocketAddress_t bind_address;
vithyat 0:977e87915078 855 palIpV4Addr_t interface_address4;
vithyat 0:977e87915078 856 palIpV6Addr_t interface_address6;
vithyat 0:977e87915078 857
vithyat 0:977e87915078 858 memset(&bind_address, 0, sizeof(palSocketAddress_t));
vithyat 0:977e87915078 859 memset(&interface_address4, 0, sizeof(interface_address4));
vithyat 0:977e87915078 860 memset(&interface_address6, 0, sizeof(interface_address6));
vithyat 0:977e87915078 861
vithyat 0:977e87915078 862 if (is_tcp_connection()) {
vithyat 0:977e87915078 863 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 864 socket_type = PAL_SOCK_STREAM;
vithyat 0:977e87915078 865 #else
vithyat 0:977e87915078 866 // Somebody has built code without TCP support but tries to use it.
vithyat 0:977e87915078 867 // Perhaps a "assert(false)" would be sufficient.
vithyat 0:977e87915078 868 tr_error("M2MConnectionHandlerPimpl::init_socket() - TCP config error");
vithyat 0:977e87915078 869 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
vithyat 0:977e87915078 870 return;
vithyat 0:977e87915078 871 #endif //PAL_NET_TCP_AND_TLS_SUPPORT
vithyat 0:977e87915078 872 }
vithyat 0:977e87915078 873 status = pal_asynchronousSocketWithArgument((palSocketDomain_t)_socket_address.addressType,
vithyat 0:977e87915078 874 socket_type, true, _net_iface, &socket_event_handler,
vithyat 0:977e87915078 875 this, &_socket);
vithyat 0:977e87915078 876
vithyat 0:977e87915078 877 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 878 tr_error("M2MConnectionHandlerPimpl::init_socket() - socket create error : %" PRIx32, status);
vithyat 0:977e87915078 879 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
vithyat 0:977e87915078 880 return false;
vithyat 0:977e87915078 881 }
vithyat 0:977e87915078 882
vithyat 0:977e87915078 883 if (_socket_address.addressType == PAL_AF_INET) {
vithyat 0:977e87915078 884 status = pal_setSockAddrIPV4Addr(&bind_address, interface_address4);
vithyat 0:977e87915078 885 } else if (_socket_address.addressType == PAL_AF_INET6) {
vithyat 0:977e87915078 886 status = pal_setSockAddrIPV6Addr(&bind_address, interface_address6);
vithyat 0:977e87915078 887 } else {
vithyat 0:977e87915078 888 tr_warn("M2MConnectionHandlerPimpl::init_socket() - stack type: %d", (int)_socket_address.addressType);
vithyat 0:977e87915078 889 }
vithyat 0:977e87915078 890 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 891 tr_error("M2MConnectionHandlerPimpl::init_socket - setSockAddrIPV err: %" PRIx32, status);
vithyat 0:977e87915078 892 return false;
vithyat 0:977e87915078 893 }
vithyat 0:977e87915078 894 status = pal_setSockAddrPort(&bind_address, _listen_port);
vithyat 0:977e87915078 895 if (PAL_SUCCESS != status) {
vithyat 0:977e87915078 896 tr_error("M2MConnectionHandlerPimpl::init_socket - setSockAddrPort err: %" PRIx32, status);
vithyat 0:977e87915078 897 return false;
vithyat 0:977e87915078 898 }
vithyat 0:977e87915078 899 pal_bind(_socket, &bind_address, sizeof(bind_address));
vithyat 0:977e87915078 900
vithyat 0:977e87915078 901 _security_impl->set_socket(_socket, (palSocketAddress_t*)&_socket_address);
vithyat 0:977e87915078 902
vithyat 0:977e87915078 903 return true;
vithyat 0:977e87915078 904 }
vithyat 0:977e87915078 905
vithyat 0:977e87915078 906 bool M2MConnectionHandlerPimpl::is_tcp_connection() const
vithyat 0:977e87915078 907 {
vithyat 0:977e87915078 908 return ( _binding_mode == M2MInterface::TCP ||
vithyat 0:977e87915078 909 _binding_mode == M2MInterface::TCP_QUEUE );
vithyat 0:977e87915078 910 }
vithyat 0:977e87915078 911
vithyat 0:977e87915078 912 void M2MConnectionHandlerPimpl::close_socket()
vithyat 0:977e87915078 913 {
vithyat 0:977e87915078 914 _suppressable_event_in_flight = false;
vithyat 0:977e87915078 915
vithyat 0:977e87915078 916 if (_socket) {
vithyat 0:977e87915078 917 // At least on mbed-os the pal_close() will perform callbacks even during it
vithyat 0:977e87915078 918 // is called, which we will ignore when this state is set.
vithyat 0:977e87915078 919 _socket_state = ESocketStateCloseBeingCalled;
vithyat 0:977e87915078 920 pal_close(&_socket);
vithyat 0:977e87915078 921 _socket = 0;
vithyat 0:977e87915078 922 }
vithyat 0:977e87915078 923
vithyat 0:977e87915078 924 // make sure the socket connection statemachine is reset too.
vithyat 0:977e87915078 925 _socket_state = ESocketStateDisconnected;
vithyat 0:977e87915078 926
vithyat 0:977e87915078 927 if (_security_impl) {
vithyat 0:977e87915078 928 _security_impl->reset();
vithyat 0:977e87915078 929 }
vithyat 0:977e87915078 930
vithyat 0:977e87915078 931 claim_mutex();
vithyat 0:977e87915078 932 /*ns_list_foreach_safe(M2MConnectionHandlerPimpl::send_data_queue_s, tmp, &_linked_list_send_data) {
vithyat 0:977e87915078 933 ns_list_remove(&_linked_list_send_data, tmp);
vithyat 0:977e87915078 934 free(tmp->data);
vithyat 0:977e87915078 935 free(tmp);
vithyat 0:977e87915078 936 }*/
vithyat 0:977e87915078 937 // Workaround for IAR compilation issue. ns_list_foreach does not compile with IAR.
vithyat 0:977e87915078 938 // Error[Pe144]: a value of type "void *" cannot be used to initialize an entity of type "M2MConnectionHandlerPimpl::send_data_queue *"
vithyat 0:977e87915078 939 while (!ns_list_is_empty(&_linked_list_send_data)) {
vithyat 0:977e87915078 940 send_data_queue_s* data = (send_data_queue_s*)ns_list_get_first(&_linked_list_send_data);
vithyat 0:977e87915078 941 ns_list_remove(&_linked_list_send_data, data);
vithyat 0:977e87915078 942 free(data->data);
vithyat 0:977e87915078 943 free(data);
vithyat 0:977e87915078 944 }
vithyat 0:977e87915078 945 release_mutex();
vithyat 0:977e87915078 946 }
vithyat 0:977e87915078 947
vithyat 0:977e87915078 948 M2MConnectionHandlerPimpl::send_data_queue_s* M2MConnectionHandlerPimpl::get_item_from_list()
vithyat 0:977e87915078 949 {
vithyat 0:977e87915078 950 claim_mutex();
vithyat 0:977e87915078 951 send_data_queue_s* out_data = (send_data_queue_s*)ns_list_get_first(&_linked_list_send_data);
vithyat 0:977e87915078 952 if (out_data) {
vithyat 0:977e87915078 953 ns_list_remove(&_linked_list_send_data, out_data);
vithyat 0:977e87915078 954 }
vithyat 0:977e87915078 955 release_mutex();
vithyat 0:977e87915078 956 return out_data;
vithyat 0:977e87915078 957 }
vithyat 0:977e87915078 958
vithyat 0:977e87915078 959 void M2MConnectionHandlerPimpl::add_item_to_list(M2MConnectionHandlerPimpl::send_data_queue_s *data)
vithyat 0:977e87915078 960 {
vithyat 0:977e87915078 961 claim_mutex();
vithyat 0:977e87915078 962 ns_list_add_to_start(&_linked_list_send_data, data);
vithyat 0:977e87915078 963 release_mutex();
vithyat 0:977e87915078 964 }
vithyat 0:977e87915078 965
vithyat 0:977e87915078 966 void M2MConnectionHandlerPimpl::force_close()
vithyat 0:977e87915078 967 {
vithyat 0:977e87915078 968 close_socket();
vithyat 0:977e87915078 969 }
vithyat 0:977e87915078 970
vithyat 0:977e87915078 971 void M2MConnectionHandlerPimpl::unregister_network_handler()
vithyat 0:977e87915078 972 {
vithyat 0:977e87915078 973 pal_unregisterNetworkInterface(_net_iface);
vithyat 0:977e87915078 974 }