Example

Dependencies:   FXAS21002 FXOS8700Q

Committer:
maygup01
Date:
Tue Nov 19 09:49:38 2019 +0000
Revision:
0:11cc2b7889af
Example

Who changed what in which revision?

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