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