mbed client on ethernet with LWIP
Dependencies: mbed Socket lwip-eth lwip-sys lwip
Fork of mbed-client-classic-example-lwip by
mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp@11:cada08fc8a70, 2016-06-09 (annotated)
- Committer:
- mbedAustin
- Date:
- Thu Jun 09 17:08:36 2016 +0000
- Revision:
- 11:cada08fc8a70
Commit for public Consumption
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mbedAustin | 11:cada08fc8a70 | 1 | /* |
mbedAustin | 11:cada08fc8a70 | 2 | * Copyright (c) 2015 ARM Limited. All rights reserved. |
mbedAustin | 11:cada08fc8a70 | 3 | * SPDX-License-Identifier: Apache-2.0 |
mbedAustin | 11:cada08fc8a70 | 4 | * Licensed under the Apache License, Version 2.0 (the License); you may |
mbedAustin | 11:cada08fc8a70 | 5 | * not use this file except in compliance with the License. |
mbedAustin | 11:cada08fc8a70 | 6 | * You may obtain a copy of the License at |
mbedAustin | 11:cada08fc8a70 | 7 | * |
mbedAustin | 11:cada08fc8a70 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
mbedAustin | 11:cada08fc8a70 | 9 | * |
mbedAustin | 11:cada08fc8a70 | 10 | * Unless required by applicable law or agreed to in writing, software |
mbedAustin | 11:cada08fc8a70 | 11 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
mbedAustin | 11:cada08fc8a70 | 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
mbedAustin | 11:cada08fc8a70 | 13 | * See the License for the specific language governing permissions and |
mbedAustin | 11:cada08fc8a70 | 14 | * limitations under the License. |
mbedAustin | 11:cada08fc8a70 | 15 | */ |
mbedAustin | 11:cada08fc8a70 | 16 | #include "mbed-client-classic/m2mconnectionhandlerpimpl.h" |
mbedAustin | 11:cada08fc8a70 | 17 | #include "mbed-client/m2mconnectionobserver.h" |
mbedAustin | 11:cada08fc8a70 | 18 | #include "mbed-client/m2mconstants.h" |
mbedAustin | 11:cada08fc8a70 | 19 | #include "mbed-client/m2msecurity.h" |
mbedAustin | 11:cada08fc8a70 | 20 | #include "mbed-client/m2mconnectionhandler.h" |
mbedAustin | 11:cada08fc8a70 | 21 | |
mbedAustin | 11:cada08fc8a70 | 22 | #include "Socket/TCPSocketConnection.h" |
mbedAustin | 11:cada08fc8a70 | 23 | #include "Socket/UDPSocket.h" |
mbedAustin | 11:cada08fc8a70 | 24 | #include "threadwrapper.h" |
mbedAustin | 11:cada08fc8a70 | 25 | #include "mbed_error.h" |
mbedAustin | 11:cada08fc8a70 | 26 | |
mbedAustin | 11:cada08fc8a70 | 27 | |
mbedAustin | 11:cada08fc8a70 | 28 | M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer, |
mbedAustin | 11:cada08fc8a70 | 29 | M2MConnectionSecurity* sec, |
mbedAustin | 11:cada08fc8a70 | 30 | M2MInterface::BindingMode mode, |
mbedAustin | 11:cada08fc8a70 | 31 | M2MInterface::NetworkStack stack) |
mbedAustin | 11:cada08fc8a70 | 32 | :_base(base), |
mbedAustin | 11:cada08fc8a70 | 33 | _observer(observer), |
mbedAustin | 11:cada08fc8a70 | 34 | _security_impl(sec), |
mbedAustin | 11:cada08fc8a70 | 35 | _use_secure_connection(false), |
mbedAustin | 11:cada08fc8a70 | 36 | _binding_mode(mode), |
mbedAustin | 11:cada08fc8a70 | 37 | _network_stack(stack), |
mbedAustin | 11:cada08fc8a70 | 38 | _resolved(true), |
mbedAustin | 11:cada08fc8a70 | 39 | _is_handshaking(false), |
mbedAustin | 11:cada08fc8a70 | 40 | _listening(false), |
mbedAustin | 11:cada08fc8a70 | 41 | _listen_thread(0), |
mbedAustin | 11:cada08fc8a70 | 42 | _recv_thread(0), |
mbedAustin | 11:cada08fc8a70 | 43 | _send_thread(0) |
mbedAustin | 11:cada08fc8a70 | 44 | { |
mbedAustin | 11:cada08fc8a70 | 45 | memset(&_address_buffer, 0, sizeof _address_buffer); |
mbedAustin | 11:cada08fc8a70 | 46 | memset(&_address, 0, sizeof _address); |
mbedAustin | 11:cada08fc8a70 | 47 | _address._address = _address_buffer; |
mbedAustin | 11:cada08fc8a70 | 48 | |
mbedAustin | 11:cada08fc8a70 | 49 | if (_network_stack != M2MInterface::LwIP_IPv4) { |
mbedAustin | 11:cada08fc8a70 | 50 | error("ConnectionHandler: Unsupported network stack, only IPv4 is currently supported"); |
mbedAustin | 11:cada08fc8a70 | 51 | } |
mbedAustin | 11:cada08fc8a70 | 52 | |
mbedAustin | 11:cada08fc8a70 | 53 | if (_binding_mode == M2MInterface::TCP || |
mbedAustin | 11:cada08fc8a70 | 54 | _binding_mode == M2MInterface::TCP_QUEUE) { |
mbedAustin | 11:cada08fc8a70 | 55 | error("ConnectionHandler: Unsupported binding mode, only UDP based modes are currently supported"); |
mbedAustin | 11:cada08fc8a70 | 56 | } |
mbedAustin | 11:cada08fc8a70 | 57 | |
mbedAustin | 11:cada08fc8a70 | 58 | _running = true; |
mbedAustin | 11:cada08fc8a70 | 59 | _recv_thread = rtos::create_thread< |
mbedAustin | 11:cada08fc8a70 | 60 | M2MConnectionHandlerPimpl, |
mbedAustin | 11:cada08fc8a70 | 61 | &M2MConnectionHandlerPimpl::recv_handler>(this, osPriorityAboveNormal); |
mbedAustin | 11:cada08fc8a70 | 62 | _send_thread = rtos::create_thread< |
mbedAustin | 11:cada08fc8a70 | 63 | M2MConnectionHandlerPimpl, |
mbedAustin | 11:cada08fc8a70 | 64 | &M2MConnectionHandlerPimpl::send_handler>(this); |
mbedAustin | 11:cada08fc8a70 | 65 | _listen_thread = rtos::create_thread< |
mbedAustin | 11:cada08fc8a70 | 66 | M2MConnectionHandlerPimpl, |
mbedAustin | 11:cada08fc8a70 | 67 | &M2MConnectionHandlerPimpl::listen_handler>(this); |
mbedAustin | 11:cada08fc8a70 | 68 | } |
mbedAustin | 11:cada08fc8a70 | 69 | |
mbedAustin | 11:cada08fc8a70 | 70 | M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl() |
mbedAustin | 11:cada08fc8a70 | 71 | { |
mbedAustin | 11:cada08fc8a70 | 72 | _listening = false; |
mbedAustin | 11:cada08fc8a70 | 73 | _running = false; |
mbedAustin | 11:cada08fc8a70 | 74 | |
mbedAustin | 11:cada08fc8a70 | 75 | if (_listen_thread) { |
mbedAustin | 11:cada08fc8a70 | 76 | delete _listen_thread; |
mbedAustin | 11:cada08fc8a70 | 77 | _listen_thread = 0; |
mbedAustin | 11:cada08fc8a70 | 78 | } |
mbedAustin | 11:cada08fc8a70 | 79 | |
mbedAustin | 11:cada08fc8a70 | 80 | if (_recv_thread) { |
mbedAustin | 11:cada08fc8a70 | 81 | delete _recv_thread; |
mbedAustin | 11:cada08fc8a70 | 82 | _recv_thread = 0; |
mbedAustin | 11:cada08fc8a70 | 83 | } |
mbedAustin | 11:cada08fc8a70 | 84 | |
mbedAustin | 11:cada08fc8a70 | 85 | if (_send_thread) { |
mbedAustin | 11:cada08fc8a70 | 86 | delete _send_thread; |
mbedAustin | 11:cada08fc8a70 | 87 | _send_thread = 0; |
mbedAustin | 11:cada08fc8a70 | 88 | } |
mbedAustin | 11:cada08fc8a70 | 89 | |
mbedAustin | 11:cada08fc8a70 | 90 | delete _security_impl; |
mbedAustin | 11:cada08fc8a70 | 91 | } |
mbedAustin | 11:cada08fc8a70 | 92 | |
mbedAustin | 11:cada08fc8a70 | 93 | bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port) |
mbedAustin | 11:cada08fc8a70 | 94 | { |
mbedAustin | 11:cada08fc8a70 | 95 | return !(_socket.bind(listen_port) < 0); |
mbedAustin | 11:cada08fc8a70 | 96 | } |
mbedAustin | 11:cada08fc8a70 | 97 | |
mbedAustin | 11:cada08fc8a70 | 98 | bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address, |
mbedAustin | 11:cada08fc8a70 | 99 | const uint16_t server_port, |
mbedAustin | 11:cada08fc8a70 | 100 | M2MConnectionObserver::ServerType server_type, |
mbedAustin | 11:cada08fc8a70 | 101 | const M2MSecurity* security) |
mbedAustin | 11:cada08fc8a70 | 102 | { |
mbedAustin | 11:cada08fc8a70 | 103 | if (_endpoint.set_address(server_address.c_str(), server_port) < 0) { |
mbedAustin | 11:cada08fc8a70 | 104 | return false; |
mbedAustin | 11:cada08fc8a70 | 105 | } |
mbedAustin | 11:cada08fc8a70 | 106 | |
mbedAustin | 11:cada08fc8a70 | 107 | inet_aton(_endpoint.get_address(), _address._address); |
mbedAustin | 11:cada08fc8a70 | 108 | _address._port = _endpoint.get_port(); |
mbedAustin | 11:cada08fc8a70 | 109 | _address._length = 4; |
mbedAustin | 11:cada08fc8a70 | 110 | _address._stack = _network_stack; |
mbedAustin | 11:cada08fc8a70 | 111 | |
mbedAustin | 11:cada08fc8a70 | 112 | if (security) { |
mbedAustin | 11:cada08fc8a70 | 113 | if (security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate || |
mbedAustin | 11:cada08fc8a70 | 114 | security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) { |
mbedAustin | 11:cada08fc8a70 | 115 | if (_security_impl != NULL) { |
mbedAustin | 11:cada08fc8a70 | 116 | _security_impl->reset(); |
mbedAustin | 11:cada08fc8a70 | 117 | _security_impl->init(security); |
mbedAustin | 11:cada08fc8a70 | 118 | |
mbedAustin | 11:cada08fc8a70 | 119 | if (_security_impl->connect(_base) < 0) { |
mbedAustin | 11:cada08fc8a70 | 120 | return false; |
mbedAustin | 11:cada08fc8a70 | 121 | } |
mbedAustin | 11:cada08fc8a70 | 122 | |
mbedAustin | 11:cada08fc8a70 | 123 | _use_secure_connection = true; |
mbedAustin | 11:cada08fc8a70 | 124 | } |
mbedAustin | 11:cada08fc8a70 | 125 | } |
mbedAustin | 11:cada08fc8a70 | 126 | } |
mbedAustin | 11:cada08fc8a70 | 127 | |
mbedAustin | 11:cada08fc8a70 | 128 | _observer.address_ready(_address, |
mbedAustin | 11:cada08fc8a70 | 129 | server_type, |
mbedAustin | 11:cada08fc8a70 | 130 | _address._port); |
mbedAustin | 11:cada08fc8a70 | 131 | |
mbedAustin | 11:cada08fc8a70 | 132 | return true; |
mbedAustin | 11:cada08fc8a70 | 133 | } |
mbedAustin | 11:cada08fc8a70 | 134 | |
mbedAustin | 11:cada08fc8a70 | 135 | |
mbedAustin | 11:cada08fc8a70 | 136 | void M2MConnectionHandlerPimpl::recv_handler() |
mbedAustin | 11:cada08fc8a70 | 137 | { |
mbedAustin | 11:cada08fc8a70 | 138 | while (_running) { |
mbedAustin | 11:cada08fc8a70 | 139 | Endpoint recv_endpoint; |
mbedAustin | 11:cada08fc8a70 | 140 | int size = _socket.receiveFrom(recv_endpoint, |
mbedAustin | 11:cada08fc8a70 | 141 | (char*)_recv_buffer, sizeof _recv_buffer); |
mbedAustin | 11:cada08fc8a70 | 142 | |
mbedAustin | 11:cada08fc8a70 | 143 | if (size > 0) { |
mbedAustin | 11:cada08fc8a70 | 144 | _recv_queue.put(new std::string(_recv_buffer, _recv_buffer+size)); |
mbedAustin | 11:cada08fc8a70 | 145 | } else { |
mbedAustin | 11:cada08fc8a70 | 146 | rtos::Thread::wait(1000); |
mbedAustin | 11:cada08fc8a70 | 147 | } |
mbedAustin | 11:cada08fc8a70 | 148 | } |
mbedAustin | 11:cada08fc8a70 | 149 | } |
mbedAustin | 11:cada08fc8a70 | 150 | |
mbedAustin | 11:cada08fc8a70 | 151 | void M2MConnectionHandlerPimpl::send_handler() |
mbedAustin | 11:cada08fc8a70 | 152 | { |
mbedAustin | 11:cada08fc8a70 | 153 | while (_running) { |
mbedAustin | 11:cada08fc8a70 | 154 | osEvent e = _send_queue.get(); |
mbedAustin | 11:cada08fc8a70 | 155 | if (e.status == osEventMessage) { |
mbedAustin | 11:cada08fc8a70 | 156 | std::string *packet = (std::string*)e.value.p; |
mbedAustin | 11:cada08fc8a70 | 157 | int size = _socket.sendTo(_endpoint, (char*)packet->data(), packet->size()); |
mbedAustin | 11:cada08fc8a70 | 158 | delete packet; |
mbedAustin | 11:cada08fc8a70 | 159 | } else { |
mbedAustin | 11:cada08fc8a70 | 160 | rtos::Thread::wait(1000); |
mbedAustin | 11:cada08fc8a70 | 161 | } |
mbedAustin | 11:cada08fc8a70 | 162 | } |
mbedAustin | 11:cada08fc8a70 | 163 | } |
mbedAustin | 11:cada08fc8a70 | 164 | |
mbedAustin | 11:cada08fc8a70 | 165 | bool M2MConnectionHandlerPimpl::send_data(uint8_t *data, |
mbedAustin | 11:cada08fc8a70 | 166 | uint16_t data_len, |
mbedAustin | 11:cada08fc8a70 | 167 | sn_nsdl_addr_s *address) |
mbedAustin | 11:cada08fc8a70 | 168 | { |
mbedAustin | 11:cada08fc8a70 | 169 | if (address == NULL || data == NULL) { |
mbedAustin | 11:cada08fc8a70 | 170 | return false; |
mbedAustin | 11:cada08fc8a70 | 171 | } |
mbedAustin | 11:cada08fc8a70 | 172 | |
mbedAustin | 11:cada08fc8a70 | 173 | if (_use_secure_connection) { |
mbedAustin | 11:cada08fc8a70 | 174 | if (_security_impl->send_message(data, data_len) < 0) { |
mbedAustin | 11:cada08fc8a70 | 175 | return false; |
mbedAustin | 11:cada08fc8a70 | 176 | } |
mbedAustin | 11:cada08fc8a70 | 177 | } else { |
mbedAustin | 11:cada08fc8a70 | 178 | if (send_to_socket(data, data_len) < 0) { |
mbedAustin | 11:cada08fc8a70 | 179 | return false; |
mbedAustin | 11:cada08fc8a70 | 180 | } |
mbedAustin | 11:cada08fc8a70 | 181 | } |
mbedAustin | 11:cada08fc8a70 | 182 | |
mbedAustin | 11:cada08fc8a70 | 183 | _observer.data_sent(); |
mbedAustin | 11:cada08fc8a70 | 184 | return true; |
mbedAustin | 11:cada08fc8a70 | 185 | } |
mbedAustin | 11:cada08fc8a70 | 186 | |
mbedAustin | 11:cada08fc8a70 | 187 | bool M2MConnectionHandlerPimpl::start_listening_for_data() |
mbedAustin | 11:cada08fc8a70 | 188 | { |
mbedAustin | 11:cada08fc8a70 | 189 | _listening = true; |
mbedAustin | 11:cada08fc8a70 | 190 | return true; |
mbedAustin | 11:cada08fc8a70 | 191 | } |
mbedAustin | 11:cada08fc8a70 | 192 | |
mbedAustin | 11:cada08fc8a70 | 193 | void M2MConnectionHandlerPimpl::stop_listening() |
mbedAustin | 11:cada08fc8a70 | 194 | { |
mbedAustin | 11:cada08fc8a70 | 195 | _listening = false; |
mbedAustin | 11:cada08fc8a70 | 196 | } |
mbedAustin | 11:cada08fc8a70 | 197 | |
mbedAustin | 11:cada08fc8a70 | 198 | void M2MConnectionHandlerPimpl::listen_handler() |
mbedAustin | 11:cada08fc8a70 | 199 | { |
mbedAustin | 11:cada08fc8a70 | 200 | while (_running) { |
mbedAustin | 11:cada08fc8a70 | 201 | if (_listening) { |
mbedAustin | 11:cada08fc8a70 | 202 | memset(_listen_buffer, 0, sizeof _listen_buffer); |
mbedAustin | 11:cada08fc8a70 | 203 | int size; |
mbedAustin | 11:cada08fc8a70 | 204 | |
mbedAustin | 11:cada08fc8a70 | 205 | if (_use_secure_connection) { |
mbedAustin | 11:cada08fc8a70 | 206 | size = _security_impl->read(_listen_buffer, sizeof _listen_buffer); |
mbedAustin | 11:cada08fc8a70 | 207 | } else { |
mbedAustin | 11:cada08fc8a70 | 208 | size = receive_from_socket(_listen_buffer, sizeof _listen_buffer); |
mbedAustin | 11:cada08fc8a70 | 209 | } |
mbedAustin | 11:cada08fc8a70 | 210 | |
mbedAustin | 11:cada08fc8a70 | 211 | if (size > 0) { |
mbedAustin | 11:cada08fc8a70 | 212 | _observer.data_available((uint8_t*)_listen_buffer, size, _address); |
mbedAustin | 11:cada08fc8a70 | 213 | } else if (size != 0) { |
mbedAustin | 11:cada08fc8a70 | 214 | _listening = false; |
mbedAustin | 11:cada08fc8a70 | 215 | _observer.socket_error(2); |
mbedAustin | 11:cada08fc8a70 | 216 | } |
mbedAustin | 11:cada08fc8a70 | 217 | } else { |
mbedAustin | 11:cada08fc8a70 | 218 | rtos::Thread::wait(1000); |
mbedAustin | 11:cada08fc8a70 | 219 | } |
mbedAustin | 11:cada08fc8a70 | 220 | } |
mbedAustin | 11:cada08fc8a70 | 221 | } |
mbedAustin | 11:cada08fc8a70 | 222 | |
mbedAustin | 11:cada08fc8a70 | 223 | |
mbedAustin | 11:cada08fc8a70 | 224 | int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len) |
mbedAustin | 11:cada08fc8a70 | 225 | { |
mbedAustin | 11:cada08fc8a70 | 226 | if (_send_queue.put(new std::string(buf, buf+len)) != osOK) { |
mbedAustin | 11:cada08fc8a70 | 227 | return M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE; |
mbedAustin | 11:cada08fc8a70 | 228 | } else { |
mbedAustin | 11:cada08fc8a70 | 229 | return len; |
mbedAustin | 11:cada08fc8a70 | 230 | } |
mbedAustin | 11:cada08fc8a70 | 231 | } |
mbedAustin | 11:cada08fc8a70 | 232 | |
mbedAustin | 11:cada08fc8a70 | 233 | int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len) |
mbedAustin | 11:cada08fc8a70 | 234 | { |
mbedAustin | 11:cada08fc8a70 | 235 | osEvent e = _recv_queue.get(); |
mbedAustin | 11:cada08fc8a70 | 236 | if (e.status == osEventMessage) { |
mbedAustin | 11:cada08fc8a70 | 237 | std::string *packet = (std::string*)e.value.p; |
mbedAustin | 11:cada08fc8a70 | 238 | int size = packet->size(); |
mbedAustin | 11:cada08fc8a70 | 239 | |
mbedAustin | 11:cada08fc8a70 | 240 | if (size <= len) { |
mbedAustin | 11:cada08fc8a70 | 241 | memcpy(buf, packet->data(), size); |
mbedAustin | 11:cada08fc8a70 | 242 | delete packet; |
mbedAustin | 11:cada08fc8a70 | 243 | return size; |
mbedAustin | 11:cada08fc8a70 | 244 | } |
mbedAustin | 11:cada08fc8a70 | 245 | } |
mbedAustin | 11:cada08fc8a70 | 246 | |
mbedAustin | 11:cada08fc8a70 | 247 | return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; |
mbedAustin | 11:cada08fc8a70 | 248 | } |
mbedAustin | 11:cada08fc8a70 | 249 | |
mbedAustin | 11:cada08fc8a70 | 250 | void M2MConnectionHandlerPimpl::handle_connection_error(int /*error*/) |
mbedAustin | 11:cada08fc8a70 | 251 | { |
mbedAustin | 11:cada08fc8a70 | 252 | _observer.socket_error(4); |
mbedAustin | 11:cada08fc8a70 | 253 | } |