Dependencies:   MMA7660 LM75B

Committer:
MACRUM
Date:
Sat Jun 30 01:40:30 2018 +0000
Revision:
0:119624335925
Initial commit

Who changed what in which revision?

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