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