leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Committer:
leothedragon
Date:
Tue May 04 08:55:12 2021 +0000
Revision:
0:8f0bb79ddd48
nmn

Who changed what in which revision?

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