Timothy Beight / Mbed 2 deprecated 6_songs-from-the-cloud

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of 6_songs-from-the-cloud by MakingMusicWorkshop

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mconnectionhandlerpimpl.cpp Source File

m2mconnectionhandlerpimpl.cpp

00001 /*
00002  * Copyright (c) 2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "mbed-client-classic/m2mconnectionhandlerpimpl.h"
00017 #include "mbed-client/m2mconnectionobserver.h"
00018 #include "mbed-client/m2mconstants.h"
00019 #include "mbed-client/m2msecurity.h"
00020 #include "mbed-client/m2mconnectionhandler.h"
00021 
00022 #include "Socket/TCPSocketConnection.h"
00023 #include "Socket/UDPSocket.h"
00024 #include "threadwrapper.h"
00025 #include "mbed_error.h"
00026 
00027 
00028 M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
00029                                                      M2MConnectionSecurity* sec,
00030                                                      M2MInterface::BindingMode mode,
00031                                                      M2MInterface::NetworkStack stack)
00032 :_base(base),
00033  _observer(observer),
00034  _security_impl(sec),
00035  _use_secure_connection(false),
00036  _binding_mode(mode),
00037  _network_stack(stack),
00038  _resolved(true),
00039  _is_handshaking(false),
00040  _listening(false),
00041  _listen_thread(0),
00042  _recv_thread(0),
00043  _send_thread(0)
00044 {
00045     memset(&_address_buffer, 0, sizeof _address_buffer);
00046     memset(&_address, 0, sizeof _address);
00047     _address._address = _address_buffer;
00048 
00049     if (_network_stack != M2MInterface::LwIP_IPv4) {
00050         error("ConnectionHandler: Unsupported network stack, only IPv4 is currently supported");
00051     }
00052     
00053     if (_binding_mode == M2MInterface::TCP ||
00054         _binding_mode == M2MInterface::TCP_QUEUE) {
00055         error("ConnectionHandler: Unsupported binding mode, only UDP based modes are currently supported");
00056     }
00057     
00058     _running = true;
00059     _recv_thread = rtos::create_thread<
00060         M2MConnectionHandlerPimpl,
00061         &M2MConnectionHandlerPimpl::recv_handler>(this, osPriorityAboveNormal);
00062     _send_thread = rtos::create_thread<
00063         M2MConnectionHandlerPimpl,
00064         &M2MConnectionHandlerPimpl::send_handler>(this);
00065     _listen_thread = rtos::create_thread<
00066         M2MConnectionHandlerPimpl,
00067         &M2MConnectionHandlerPimpl::listen_handler>(this);    
00068 }
00069 
00070 M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()
00071 {
00072     _listening = false;
00073     _running = false;
00074     
00075     if (_listen_thread) {
00076         delete _listen_thread;
00077         _listen_thread = 0;
00078     }
00079     
00080     if (_recv_thread) {
00081         delete _recv_thread;
00082         _recv_thread = 0;
00083     }
00084     
00085     if (_send_thread) {
00086         delete _send_thread;
00087         _send_thread = 0;
00088     }
00089     
00090     delete _security_impl;
00091 }
00092 
00093 bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port)
00094 {
00095     return !(_socket.bind(listen_port) < 0);
00096 }
00097 
00098 bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address,
00099                                                        const uint16_t server_port,
00100                                                        M2MConnectionObserver::ServerType server_type,
00101                                                        const M2MSecurity* security)
00102 {
00103     if (_endpoint.set_address(server_address.c_str(), server_port) < 0) {
00104         return false;
00105     }
00106 
00107     inet_aton(_endpoint.get_address(), _address._address);
00108     _address._port = _endpoint.get_port();
00109     _address._length = 4;
00110     _address._stack = _network_stack;
00111 
00112     if (security) {
00113         if (security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate ||
00114             security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) {
00115             if (_security_impl != NULL) {
00116                 _security_impl->reset();
00117                 _security_impl->init(security);
00118                 
00119                 if (_security_impl->connect(_base) < 0) {
00120                     return false;
00121                 }
00122                 
00123                 _use_secure_connection = true;
00124             }
00125         }
00126     }
00127     
00128     _observer.address_ready(_address,
00129                             server_type,
00130                             _address._port);
00131     
00132     return true;
00133 }
00134 
00135 
00136 void M2MConnectionHandlerPimpl::recv_handler()
00137 {
00138     while (_running) {
00139         Endpoint recv_endpoint;
00140         int size = _socket.receiveFrom(recv_endpoint,
00141             (char*)_recv_buffer, sizeof _recv_buffer);
00142     
00143         if (size > 0) {
00144             _recv_queue.put(new std::string(_recv_buffer, _recv_buffer+size));
00145         } else {
00146             rtos::Thread::wait(1000);
00147         }
00148     }
00149 }
00150 
00151 void M2MConnectionHandlerPimpl::send_handler()
00152 {    
00153     while (_running) {
00154         osEvent e = _send_queue.get();
00155         if (e.status == osEventMessage) {
00156             std::string *packet = (std::string*)e.value.p;
00157             int size = _socket.sendTo(_endpoint, (char*)packet->data(), packet->size());
00158             delete packet;
00159         } else {
00160             rtos::Thread::wait(1000);
00161         }
00162     }
00163 }
00164 
00165 bool M2MConnectionHandlerPimpl::send_data(uint8_t *data,
00166                                           uint16_t data_len,
00167                                           sn_nsdl_addr_s *address)
00168 {
00169     if (address == NULL || data == NULL) {
00170         return false;
00171     }
00172     
00173     if (_use_secure_connection) {
00174         if (_security_impl->send_message(data, data_len) < 0) {
00175             return false;
00176         }
00177     } else {
00178         if (send_to_socket(data, data_len) < 0) {
00179             return false;
00180         }
00181     }
00182     
00183     _observer.data_sent();
00184     return true;
00185 }
00186 
00187 bool M2MConnectionHandlerPimpl::start_listening_for_data()
00188 {
00189     _listening = true;
00190     return true;
00191 }
00192 
00193 void M2MConnectionHandlerPimpl::stop_listening()
00194 {
00195     _listening = false;
00196 }
00197 
00198 void M2MConnectionHandlerPimpl::listen_handler()
00199 {
00200     while (_running) {
00201         if (_listening) {
00202             memset(_listen_buffer, 0, sizeof _listen_buffer);
00203             int size;
00204             
00205             if (_use_secure_connection) {
00206                 size = _security_impl->read(_listen_buffer, sizeof _listen_buffer);
00207             } else {
00208                 size = receive_from_socket(_listen_buffer, sizeof _listen_buffer);
00209             }
00210             
00211             if (size > 0) {
00212                 _observer.data_available((uint8_t*)_listen_buffer, size, _address);
00213             } else if (size != 0) {
00214                 _listening = false;
00215                 _observer.socket_error(2);
00216             }
00217         } else {
00218             rtos::Thread::wait(1000);
00219         }
00220     }
00221 }
00222 
00223 
00224 int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len)
00225 {
00226     if (_send_queue.put(new std::string(buf, buf+len)) != osOK) {
00227         return M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE;
00228     } else {
00229         return len;
00230     }
00231 }
00232 
00233 int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len)
00234 {
00235     osEvent e = _recv_queue.get();
00236     if (e.status == osEventMessage) {
00237         std::string *packet = (std::string*)e.value.p;
00238         int size = packet->size();
00239         
00240         if (size <= len) {
00241             memcpy(buf, packet->data(), size);
00242             delete packet;
00243             return size;
00244         }
00245     }
00246     
00247     return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
00248 }
00249 
00250 void M2MConnectionHandlerPimpl::handle_connection_error(int /*error*/)
00251 {
00252     _observer.socket_error(4);
00253 }