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