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