Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 "pal.h" 00023 #include "pal_rtos.h" 00024 #include "pal_errors.h" 00025 #include "pal_macros.h" 00026 #include "pal_network.h" 00027 00028 #include "eventOS_scheduler.h" 00029 #include "eventOS_event.h" 00030 00031 #include "mbed-trace/mbed_trace.h" 00032 #include "mbed.h" 00033 00034 #define TRACE_GROUP "mClt" 00035 00036 int8_t M2MConnectionHandlerPimpl::_tasklet_id = -1; 00037 00038 static M2MConnectionHandlerPimpl *connection_handler = NULL; 00039 00040 extern "C" void connection_event_handler(arm_event_s *event) 00041 { 00042 if(!connection_handler){ 00043 return; 00044 } 00045 00046 switch(event->event_type){ 00047 case M2MConnectionHandlerPimpl::ESocketReadytoRead: 00048 connection_handler->receive_handler(); 00049 break; 00050 00051 case M2MConnectionHandlerPimpl::ESocketSend: 00052 connection_handler->send_socket_data((uint8_t*)event->data_ptr, event->event_data); 00053 free(event->data_ptr); 00054 break; 00055 00056 case M2MConnectionHandlerPimpl::ESocketDnsHandler: 00057 connection_handler->dns_handler(); 00058 break; 00059 00060 default: 00061 break; 00062 } 00063 } 00064 00065 void M2MConnectionHandlerPimpl::send_receive_event(void) 00066 { 00067 arm_event_s event; 00068 event.receiver = M2MConnectionHandlerPimpl::_tasklet_id; 00069 event.sender = 0; 00070 event.event_type = ESocketReadytoRead; 00071 event.data_ptr = NULL; 00072 event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; 00073 eventOS_event_send(&event); 00074 } 00075 00076 extern "C" void socket_event_handler(void) 00077 { 00078 if(!connection_handler) { 00079 return; 00080 } 00081 connection_handler->send_receive_event(); 00082 } 00083 00084 M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer, 00085 M2MConnectionSecurity* sec, 00086 M2MInterface::BindingMode mode, 00087 M2MInterface::NetworkStack stack) 00088 :_base(base), 00089 _observer(observer), 00090 _security_impl(sec), 00091 _security(NULL), 00092 _use_secure_connection(false), 00093 _binding_mode(mode), 00094 _network_stack(stack), 00095 _socket(0), 00096 _is_handshaking(false), 00097 _listening(true), 00098 _server_type(M2MConnectionObserver::LWM2MServer), 00099 _server_port(0), 00100 _listen_port(0), 00101 _running(false), 00102 _net_iface(0) 00103 { 00104 #ifndef PAL_NET_TCP_AND_TLS_SUPPORT 00105 if (is_tcp_connection()) { 00106 tr_error("ConnectionHandler: TCP support not available."); 00107 return; 00108 } 00109 #endif 00110 00111 if(PAL_SUCCESS != pal_init()){ 00112 tr_error("PAL init failed."); 00113 } 00114 00115 memset(&_address, 0, sizeof _address); 00116 memset(&_socket_address, 0, sizeof _socket_address); 00117 connection_handler = this; 00118 eventOS_scheduler_mutex_wait(); 00119 if (M2MConnectionHandlerPimpl::_tasklet_id == -1) { 00120 M2MConnectionHandlerPimpl::_tasklet_id = eventOS_event_handler_create(&connection_event_handler, ESocketIdle); 00121 } 00122 eventOS_scheduler_mutex_release(); 00123 } 00124 00125 M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl() 00126 { 00127 tr_debug("~M2MConnectionHandlerPimpl()"); 00128 stop_listening(); 00129 00130 close_socket(); 00131 00132 delete _security_impl; 00133 tr_debug("~M2MConnectionHandlerPimpl() - OUT"); 00134 } 00135 00136 bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port) 00137 { 00138 _listen_port = listen_port; 00139 return true; 00140 } 00141 00142 bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address, 00143 const uint16_t server_port, 00144 M2MConnectionObserver::ServerType server_type, 00145 const M2MSecurity* security) 00146 { 00147 arm_event_s event; 00148 00149 tr_debug("resolve_server_address()"); 00150 00151 _security = security; 00152 _server_port = server_port; 00153 _server_type = server_type; 00154 _server_address = server_address; 00155 00156 event.receiver = M2MConnectionHandlerPimpl::_tasklet_id; 00157 event.sender = 0; 00158 event.event_type = ESocketDnsHandler; 00159 event.data_ptr = NULL; 00160 event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; 00161 00162 return !eventOS_event_send(&event); 00163 } 00164 00165 void M2MConnectionHandlerPimpl::dns_handler() 00166 { 00167 palStatus_t status; 00168 uint32_t interface_count; 00169 status = pal_getNumberOfNetInterfaces(&interface_count); 00170 if(PAL_SUCCESS != status ) { 00171 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00172 return; 00173 } 00174 if(interface_count <= 0) { 00175 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00176 return; 00177 } 00178 00179 palSocketLength_t _socket_address_len; 00180 00181 if(PAL_SUCCESS != pal_getAddressInfo(_server_address.c_str(), &_socket_address, &_socket_address_len)){ 00182 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00183 return; 00184 } 00185 pal_setSockAddrPort(&_socket_address, _server_port); 00186 00187 if(_network_stack == M2MInterface::LwIP_IPv4 || 00188 _network_stack == M2MInterface::ATWINC_IPv4){ 00189 if(PAL_SUCCESS != pal_getSockAddrIPV4Addr(&_socket_address,_ipV4Addr)){ 00190 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00191 return; 00192 } 00193 00194 tr_debug("IP Address %s",tr_array(_ipV4Addr, 4)); 00195 00196 _address._address = (void*)_ipV4Addr; 00197 _address._length = PAL_IPV4_ADDRESS_SIZE; 00198 _address._port = _server_port; 00199 _address._stack = _network_stack; 00200 } 00201 else if(_network_stack == M2MInterface::LwIP_IPv6 || 00202 _network_stack == M2MInterface::Nanostack_IPv6){ 00203 if(PAL_SUCCESS != pal_getSockAddrIPV6Addr(&_socket_address,_ipV6Addr)){ 00204 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00205 return; 00206 } 00207 00208 tr_debug("IP Address %s",tr_array(_ipV6Addr,sizeof(_ipV6Addr))); 00209 00210 _address._address = (void*)_ipV6Addr; 00211 _address._length = PAL_IPV6_ADDRESS_SIZE; 00212 _address._port = _server_port; 00213 _address._stack = _network_stack; 00214 } 00215 else { 00216 tr_error("socket config error, %d", (int)_network_stack); 00217 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00218 return; 00219 } 00220 00221 close_socket(); 00222 if(!init_socket()) { 00223 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00224 return; 00225 } 00226 00227 if(is_tcp_connection()) { 00228 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00229 tr_debug("resolve_server_address - Using TCP"); 00230 if (pal_connect(_socket, &_socket_address, sizeof(_socket_address)) != PAL_SUCCESS) { 00231 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00232 return; 00233 } 00234 #endif //PAL_NET_TCP_AND_TLS_SUPPORT 00235 } 00236 00237 _running = true; 00238 00239 if (_security) { 00240 if (_security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate || 00241 _security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) { 00242 if( _security_impl != NULL ){ 00243 _security_impl->reset(); 00244 if (_security_impl->init(_security) == 0) { 00245 _is_handshaking = true; 00246 tr_debug("resolve_server_address - connect DTLS"); 00247 if(_security_impl->start_connecting_non_blocking(_base) < 0 ){ 00248 tr_debug("dns_handler - handshake failed"); 00249 _is_handshaking = false; 00250 _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR); 00251 close_socket(); 00252 return; 00253 } 00254 } else { 00255 tr_error("resolve_server_address - init failed"); 00256 _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false); 00257 close_socket(); 00258 return; 00259 } 00260 } else { 00261 tr_error("dns_handler - sec is null"); 00262 _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false); 00263 close_socket(); 00264 return; 00265 } 00266 } 00267 } 00268 if(!_is_handshaking) { 00269 enable_keepalive(); 00270 _observer.address_ready(_address, 00271 _server_type, 00272 _address._port); 00273 } 00274 } 00275 00276 bool M2MConnectionHandlerPimpl::send_data(uint8_t *data, 00277 uint16_t data_len, 00278 sn_nsdl_addr_s *address) 00279 { 00280 arm_event_s event; 00281 00282 tr_debug("send_data()"); 00283 if (address == NULL || data == NULL || !data_len || !_running) { 00284 return false; 00285 } 00286 00287 event.data_ptr = (uint8_t*)malloc(data_len); 00288 if(!event.data_ptr) { 00289 return false; 00290 } 00291 memcpy(event.data_ptr, data, data_len); 00292 00293 event.receiver = M2MConnectionHandlerPimpl::_tasklet_id; 00294 event.sender = 0; 00295 event.event_type = ESocketSend; 00296 event.event_data = data_len; 00297 event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; 00298 00299 if (eventOS_event_send(&event) != 0) { 00300 // Event push failed, free the buffer 00301 free(event.data_ptr); 00302 return false; 00303 } 00304 00305 return true; 00306 } 00307 00308 void M2MConnectionHandlerPimpl::send_socket_data(uint8_t *data, uint16_t data_len) 00309 { 00310 size_t sent_len; 00311 bool success = false; 00312 palStatus_t ret = PAL_ERR_GENERIC_FAILURE; 00313 00314 if(!data || ! data_len || !_running) { 00315 return; 00316 } 00317 00318 tr_debug("send_handler()"); 00319 00320 if( _use_secure_connection ){ 00321 if( _security_impl->send_message(data, data_len) > 0){ 00322 success = true; 00323 } 00324 } else { 00325 if(is_tcp_connection()){ 00326 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00327 //We need to "shim" the length in front 00328 uint8_t* d = (uint8_t*)malloc(data_len+4); 00329 if(d){ 00330 d[0] = 0; 00331 d[1] = 0; 00332 d[2] = (data_len >> 8 )& 0xff; 00333 d[3] = data_len & 0xff; 00334 memcpy(d + 4, data, data_len); 00335 ret = pal_send(_socket, d, data_len+4, &sent_len); 00336 free(d); 00337 } 00338 #endif //PAL_NET_TCP_AND_TLS_SUPPORT 00339 } else { 00340 ret = pal_sendTo(_socket, data, data_len, &_socket_address, sizeof(_socket_address), &sent_len); 00341 } 00342 if (ret == PAL_SUCCESS) { 00343 success = true; 00344 } 00345 } 00346 00347 if (!success) { 00348 _observer.socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR, true); 00349 close_socket(); 00350 } 00351 else{ 00352 _observer.data_sent(); 00353 } 00354 } 00355 00356 bool M2MConnectionHandlerPimpl::start_listening_for_data() 00357 { 00358 tr_debug("start_listening_for_data()"); 00359 _listening = true; 00360 return true; 00361 } 00362 00363 void M2MConnectionHandlerPimpl::stop_listening() 00364 { 00365 tr_debug("stop_listening()"); 00366 _listening = false; 00367 00368 if(_security_impl) { 00369 _security_impl->reset(); 00370 } 00371 } 00372 00373 int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len) 00374 { 00375 size_t sent_len = 0; 00376 palStatus_t status = PAL_ERR_GENERIC_FAILURE; 00377 00378 if(!_running) { 00379 return (-1); 00380 } 00381 00382 tr_debug("send_to_socket len - %d", len); 00383 00384 if(is_tcp_connection()) { 00385 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00386 status = pal_send(_socket, buf, len, &sent_len); 00387 #endif //PAL_NET_TCP_AND_TLS_SUPPORT 00388 } else { 00389 status = pal_sendTo(_socket, buf, len, &_socket_address, sizeof(_socket_address), &sent_len); 00390 } 00391 00392 if(status == PAL_SUCCESS){ 00393 return sent_len; 00394 } 00395 00396 return (-1); 00397 } 00398 00399 int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len) 00400 { 00401 size_t recv_len; 00402 palStatus_t status = PAL_ERR_GENERIC_FAILURE; 00403 tr_debug("receive_from_socket"); 00404 00405 if(!_running) { 00406 return (-1); 00407 } 00408 00409 if(is_tcp_connection()) { 00410 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00411 status = pal_recv(_socket, buf, len, &recv_len); 00412 #endif //PAL_NET_TCP_AND_TLS_SUPPORT 00413 } else { 00414 status = pal_receiveFrom(_socket, buf, len, NULL, NULL, &recv_len); 00415 } 00416 00417 if(status == PAL_SUCCESS){ 00418 return recv_len; 00419 } 00420 else if(status == PAL_ERR_SOCKET_WOULD_BLOCK || status == (-65536)){ 00421 return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00422 } 00423 else { 00424 tr_info("PAL Socket returned: %d", status); 00425 } 00426 00427 return (-1); 00428 } 00429 00430 void M2MConnectionHandlerPimpl::handle_connection_error(int error) 00431 { 00432 tr_debug("handle_connection_error"); 00433 _observer.socket_error(error); 00434 } 00435 00436 void M2MConnectionHandlerPimpl::set_platform_network_handler(void *handler) 00437 { 00438 tr_debug("set_platform_network_handler"); 00439 if(PAL_SUCCESS != pal_registerNetworkInterface(handler, &_net_iface)) { 00440 tr_error("Interface registration failed."); 00441 } 00442 } 00443 00444 void M2MConnectionHandlerPimpl::receive_handshake_handler() 00445 { 00446 tr_debug("receive_handshake_handler()"); 00447 if( _is_handshaking ){ 00448 int ret = _security_impl->continue_connecting(); 00449 tr_debug("ret %d", ret); 00450 if( ret == M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ ){ //We wait for next readable event 00451 tr_debug("We wait for next readable event"); 00452 return; 00453 } else if( ret == 0 ){ 00454 _is_handshaking = false; 00455 _use_secure_connection = true; 00456 enable_keepalive(); 00457 _observer.address_ready(_address, 00458 _server_type, 00459 _server_port); 00460 } else if( ret < 0 ){ 00461 _is_handshaking = false; 00462 _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, true); 00463 close_socket(); 00464 } 00465 } 00466 } 00467 00468 bool M2MConnectionHandlerPimpl::is_handshake_ongoing() 00469 { 00470 return _is_handshaking; 00471 } 00472 00473 void M2MConnectionHandlerPimpl::receive_handler() 00474 { 00475 tr_debug("receive_handler()"); 00476 if(_is_handshaking){ 00477 receive_handshake_handler(); 00478 return; 00479 } 00480 00481 if(!_listening || !_running) { 00482 return; 00483 } 00484 00485 if( _use_secure_connection ){ 00486 int rcv_size; 00487 do{ 00488 rcv_size = _security_impl->read(_recv_buffer, sizeof(_recv_buffer)); 00489 if(rcv_size > 0){ 00490 _observer.data_available((uint8_t*)_recv_buffer, 00491 rcv_size, _address); 00492 } else if (M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ != rcv_size && rcv_size < 0) { 00493 _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true); 00494 close_socket(); 00495 return; 00496 } 00497 } while(M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ != rcv_size); 00498 } else{ 00499 size_t recv; 00500 palStatus_t status; 00501 do{ 00502 if(is_tcp_connection()){ 00503 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00504 status = pal_recv(_socket, _recv_buffer, sizeof(_recv_buffer), &recv); 00505 #endif //PAL_NET_TCP_AND_TLS_SUPPORT 00506 } else{ 00507 status = pal_receiveFrom(_socket, _recv_buffer, sizeof(_recv_buffer), NULL, NULL, &recv); 00508 } 00509 00510 if(status == PAL_ERR_SOCKET_WOULD_BLOCK){ 00511 return; 00512 } 00513 else if (status != PAL_SUCCESS) { 00514 _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true); 00515 close_socket(); 00516 return; 00517 } 00518 00519 tr_debug("data received, len: %zu", recv); 00520 00521 if(!is_tcp_connection()){ // Observer for UDP plain mode 00522 _observer.data_available((uint8_t*)_recv_buffer, recv, _address); 00523 } else { 00524 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00525 if( recv < 4 ){ 00526 _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true); 00527 close_socket(); 00528 return; 00529 } 00530 00531 //We need to "shim" out the length from the front 00532 uint32_t len = (_recv_buffer[0] << 24 & 0xFF000000) + (_recv_buffer[1] << 16 & 0xFF0000); 00533 len += (_recv_buffer[2] << 8 & 0xFF00) + (_recv_buffer[3] & 0xFF); 00534 if(len > 0 && len <= recv - 4) { 00535 // Observer for TCP plain mode 00536 _observer.data_available(_recv_buffer + 4, len, _address); 00537 } 00538 #endif //PAL_NET_TCP_AND_TLS_SUPPORT 00539 } 00540 } while(status != PAL_ERR_SOCKET_WOULD_BLOCK); 00541 } 00542 } 00543 00544 void M2MConnectionHandlerPimpl::claim_mutex() 00545 { 00546 eventOS_scheduler_mutex_wait(); 00547 } 00548 00549 void M2MConnectionHandlerPimpl::release_mutex() 00550 { 00551 eventOS_scheduler_mutex_release(); 00552 } 00553 00554 static palNetInterfaceInfo_t interface_info; 00555 static palIpV4Addr_t interface_address4 = {0,0,0,0}; 00556 static palIpV6Addr_t interface_address6 = {0}; 00557 00558 bool M2MConnectionHandlerPimpl::init_socket() 00559 { 00560 tr_debug("init_socket - IN"); 00561 _is_handshaking = false; 00562 _running = true; 00563 palSocketType_t socket_type = PAL_SOCK_DGRAM; 00564 palStatus_t status; 00565 palSocketDomain_t domain; 00566 palSocketAddress_t bind_address; 00567 00568 if(is_tcp_connection()) { 00569 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00570 socket_type = PAL_SOCK_STREAM; 00571 #else 00572 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00573 return; 00574 #endif //PAL_NET_TCP_AND_TLS_SUPPORT 00575 } 00576 00577 if(_network_stack == M2MInterface::LwIP_IPv4){ 00578 domain = PAL_AF_INET; 00579 } else if(_network_stack == M2MInterface::LwIP_IPv6){ 00580 domain = PAL_AF_INET6; 00581 } else { 00582 domain = PAL_AF_UNSPEC; 00583 } 00584 00585 uint32_t interface_count; 00586 pal_getNumberOfNetInterfaces(&interface_count); 00587 tr_debug("Interface count: %d",interface_count); 00588 pal_getNetInterfaceInfo(_net_iface, &interface_info); 00589 tr_debug("Interface name: %s",interface_info.interfaceName); 00590 tr_debug("Interface no: %d", _net_iface); 00591 00592 tr_debug("init_socket - port %d", _listen_port); 00593 00594 status = pal_asynchronousSocket(domain, socket_type, 1, _net_iface, &socket_event_handler, &_socket); 00595 00596 if(PAL_SUCCESS != status) { 00597 _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); 00598 return false; 00599 } 00600 00601 if(_network_stack == M2MInterface::LwIP_IPv4){ 00602 pal_setSockAddrIPV4Addr(&bind_address, interface_address4); 00603 } else if(_network_stack == M2MInterface::LwIP_IPv6){ 00604 pal_setSockAddrIPV6Addr(&bind_address, interface_address6); 00605 } 00606 00607 pal_setSockAddrPort(&bind_address, _listen_port); 00608 pal_bind(_socket, &bind_address, sizeof(bind_address)); 00609 00610 tr_debug("init_socket - OUT"); 00611 return true; 00612 } 00613 00614 bool M2MConnectionHandlerPimpl::is_tcp_connection() 00615 { 00616 return ( _binding_mode == M2MInterface::TCP || 00617 _binding_mode == M2MInterface::TCP_QUEUE ); 00618 } 00619 00620 void M2MConnectionHandlerPimpl::close_socket() 00621 { 00622 tr_debug("close_socket() - IN"); 00623 if(_running) { 00624 _running = false; 00625 pal_close(&_socket); 00626 } 00627 tr_debug("close_socket() - OUT"); 00628 } 00629 00630 void M2MConnectionHandlerPimpl::enable_keepalive() 00631 { 00632 #if MBED_CLIENT_TCP_KEEPALIVE_TIME 00633 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00634 if(is_tcp_connection()) { 00635 int enable = 1; 00636 pal_setSocketOptions(_socket, PAL_SO_KEEPALIVE, &enable, sizeof(enable)); 00637 } 00638 #endif 00639 #endif 00640 }
Generated on Tue Jul 12 2022 21:20:26 by
