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