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.
Network.cpp
00001 /************************************************************************************** 00002 * Copyright (c) 2016, Tomoaki Yamaguchi 00003 * 00004 * All rights reserved. This program and the accompanying materials 00005 * are made available under the terms of the Eclipse Public License v1.0 00006 * and Eclipse Distribution License v1.0 which accompany this distribution. 00007 * 00008 * The Eclipse Public License is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * and the Eclipse Distribution License is available at 00011 * http://www.eclipse.org/org/documents/edl-v10.php. 00012 * 00013 * Contributors: 00014 * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation 00015 **************************************************************************************/ 00016 00017 #include <string.h> 00018 #include <openssl/ssl.h> 00019 #include <openssl/err.h> 00020 #include <openssl/rand.h> 00021 #include <unistd.h> 00022 #include <fcntl.h> 00023 #include <sys/socket.h> 00024 #include <regex> 00025 00026 #include "Network.h" 00027 #include "MQTTSNGWDefines.h" 00028 #include "MQTTSNGWProcess.h" 00029 00030 using namespace std; 00031 using namespace MQTTSNGW; 00032 00033 #define SOCKET_MAXCONNECTIONS 5 00034 char* currentDateTime(); 00035 00036 /*======================================== 00037 Class TCPStack 00038 =======================================*/ 00039 TCPStack::TCPStack() 00040 { 00041 _addrinfo = 0; 00042 _sockfd = 0; 00043 } 00044 00045 TCPStack::~TCPStack() 00046 { 00047 if (_addrinfo) 00048 { 00049 freeaddrinfo(_addrinfo); 00050 } 00051 } 00052 00053 bool TCPStack::isValid() 00054 { 00055 return (_sockfd > 0); 00056 } 00057 00058 void TCPStack::close() 00059 { 00060 _mutex.lock(); 00061 if (_sockfd > 0) 00062 { 00063 ::close(_sockfd); 00064 _sockfd = 0; 00065 if (_addrinfo) 00066 { 00067 freeaddrinfo(_addrinfo); 00068 _addrinfo = 0; 00069 } 00070 } 00071 _mutex.unlock(); 00072 00073 } 00074 00075 bool TCPStack::bind(const char* service) 00076 { 00077 if (isValid()) 00078 { 00079 return false; 00080 } 00081 addrinfo hints; 00082 memset(&hints, 0, sizeof(addrinfo)); 00083 hints.ai_family = AF_INET; 00084 hints.ai_socktype = SOCK_STREAM; 00085 hints.ai_flags = AI_PASSIVE; 00086 00087 if (_addrinfo) 00088 { 00089 freeaddrinfo(_addrinfo); 00090 } 00091 int err = getaddrinfo(0, service, &hints, &_addrinfo); 00092 if (err) 00093 { 00094 WRITELOG("\n%s \x1b[0m\x1b[31merror:\x1b[0m\x1b[37mgetaddrinfo(): %s\n", currentDateTime(), 00095 gai_strerror(err)); 00096 return false; 00097 } 00098 00099 _sockfd = socket(_addrinfo->ai_family, _addrinfo->ai_socktype, _addrinfo->ai_protocol); 00100 if (_sockfd < 0) 00101 { 00102 return false; 00103 } 00104 int on = 1; 00105 if (setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(on)) == -1) 00106 { 00107 return false; 00108 } 00109 00110 if (::bind(_sockfd, _addrinfo->ai_addr, _addrinfo->ai_addrlen) < 0) 00111 { 00112 return false; 00113 } 00114 return true; 00115 } 00116 00117 bool TCPStack::listen() 00118 { 00119 if (!isValid()) 00120 { 00121 return false; 00122 } 00123 int listen_return = ::listen(_sockfd, SOCKET_MAXCONNECTIONS); 00124 if (listen_return == -1) 00125 { 00126 return false; 00127 } 00128 return true; 00129 } 00130 00131 bool TCPStack::accept(TCPStack& new_socket) 00132 { 00133 sockaddr_storage sa; 00134 socklen_t len = sizeof(sa); 00135 new_socket._sockfd = ::accept(_sockfd, (struct sockaddr*) &sa, &len); 00136 if (new_socket._sockfd <= 0) 00137 { 00138 return false; 00139 } 00140 else 00141 { 00142 return true; 00143 } 00144 } 00145 00146 int TCPStack::send(const uint8_t* buf, int length) 00147 { 00148 return ::send(_sockfd, buf, length, MSG_NOSIGNAL); 00149 } 00150 00151 int TCPStack::recv(uint8_t* buf, int len) 00152 { 00153 return ::recv(_sockfd, buf, len, 0); 00154 } 00155 00156 bool TCPStack::connect(const char* host, const char* service) 00157 { 00158 if (isValid()) 00159 { 00160 return true; 00161 } 00162 addrinfo hints; 00163 memset(&hints, 0, sizeof(addrinfo)); 00164 hints.ai_family = AF_INET; 00165 hints.ai_socktype = SOCK_STREAM; 00166 if (_addrinfo) 00167 { 00168 freeaddrinfo(_addrinfo); 00169 } 00170 00171 int err = getaddrinfo(host, service, &hints, &_addrinfo); 00172 if (err) 00173 { 00174 WRITELOG("\n%s \x1b[0m\x1b[31merror:\x1b[0m\x1b[37mgetaddrinfo(): %s\n", currentDateTime(), 00175 gai_strerror(err)); 00176 return false; 00177 } 00178 00179 int sockfd = socket(_addrinfo->ai_family, _addrinfo->ai_socktype, _addrinfo->ai_protocol); 00180 00181 if (sockfd < 0) 00182 { 00183 return false; 00184 } 00185 int on = 1; 00186 00187 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(on)) == -1) 00188 { 00189 return false; 00190 } 00191 00192 if (::connect(sockfd, _addrinfo->ai_addr, _addrinfo->ai_addrlen) < 0) 00193 { 00194 DEBUGLOG("Can not connect the socket. Check the PortNo! \n"); 00195 ::close(sockfd); 00196 return false; 00197 } 00198 00199 _sockfd = sockfd; 00200 return true; 00201 } 00202 00203 void TCPStack::setNonBlocking(const bool b) 00204 { 00205 int opts; 00206 00207 opts = fcntl(_sockfd, F_GETFL); 00208 00209 if (opts < 0) 00210 { 00211 return; 00212 } 00213 00214 if (b) 00215 { 00216 opts = (opts | O_NONBLOCK); 00217 } 00218 else 00219 { 00220 opts = (opts & ~O_NONBLOCK); 00221 } 00222 fcntl(_sockfd, F_SETFL, opts); 00223 } 00224 00225 int TCPStack::getSock() 00226 { 00227 return _sockfd; 00228 } 00229 00230 /*======================================== 00231 Class Network 00232 =======================================*/ 00233 int Network::_numOfInstance = 0; 00234 SSL_CTX* Network::_ctx = 0; 00235 SSL_SESSION* Network::_session = 0; 00236 00237 Network::Network(bool secure) : 00238 TCPStack() 00239 { 00240 _ssl = 0; 00241 _secureFlg = secure; 00242 _busy = false; 00243 _sslValid = false; 00244 } 00245 00246 Network::~Network() 00247 { 00248 close(); 00249 } 00250 00251 bool Network::connect(const char* host, const char* port) 00252 { 00253 bool rc = false; 00254 _mutex.lock(); 00255 if (_secureFlg) 00256 { 00257 goto exit; 00258 } 00259 00260 if (getSock() == 0) 00261 { 00262 if (!TCPStack::connect(host, port)) 00263 { 00264 goto exit; 00265 } 00266 } 00267 rc = true; 00268 exit: 00269 _mutex.unlock(); 00270 return rc; 00271 } 00272 00273 bool Network::connect(const char* host, const char* port, const char* caPath, const char* caFile, const char* certkey, const char* prvkey) 00274 { 00275 char errmsg[256]; 00276 char peer_CN[256]; 00277 bool rc; 00278 00279 _mutex.lock(); 00280 try 00281 { 00282 if (!_secureFlg) 00283 { 00284 WRITELOG("TLS is not required.\n"); 00285 throw false; 00286 } 00287 00288 if (_ctx == 0) 00289 { 00290 SSL_load_error_strings(); 00291 SSL_library_init(); 00292 00293 #if ( OPENSSL_VERSION_NUMBER >= 0x10100000L ) 00294 _ctx = SSL_CTX_new(TLS_client_method()); 00295 #elif ( OPENSSL_VERSION_NUMBER >= 0x10001000L ) 00296 _ctx = SSL_CTX_new(TLSv1_client_method()); 00297 #else 00298 _ctx = SSL_CTX_new(SSLv23_client_method()); 00299 #endif 00300 00301 if (_ctx == 0) 00302 { 00303 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00304 WRITELOG("SSL_CTX_new() %s\n", errmsg); 00305 throw false; 00306 } 00307 00308 00309 if (!SSL_CTX_load_verify_locations(_ctx, caFile, caPath)) 00310 { 00311 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00312 WRITELOG("SSL_CTX_load_verify_locations() %s\n", errmsg); 00313 throw false; 00314 } 00315 00316 if ( certkey ) 00317 { 00318 if ( SSL_CTX_use_certificate_file(_ctx, certkey, SSL_FILETYPE_PEM) != 1 ) 00319 { 00320 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00321 WRITELOG("SSL_CTX_use_certificate_file() %s %s\n", certkey, errmsg); 00322 throw false; 00323 } 00324 } 00325 if ( prvkey ) 00326 { 00327 if ( SSL_CTX_use_PrivateKey_file(_ctx, prvkey, SSL_FILETYPE_PEM) != 1 ) 00328 { 00329 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00330 WRITELOG("SSL_use_PrivateKey_file() %s %s\n", prvkey, errmsg); 00331 throw false; 00332 } 00333 } 00334 } 00335 00336 if (! TCPStack::isValid()) 00337 { 00338 if ( !TCPStack::connect(host, port) ) 00339 { 00340 throw false; 00341 } 00342 } 00343 00344 _ssl = SSL_new(_ctx); 00345 if (_ssl == 0) 00346 { 00347 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00348 WRITELOG("SSL_new() %s\n", errmsg); 00349 throw false; 00350 } 00351 00352 if (!SSL_set_fd(_ssl, TCPStack::getSock())) 00353 { 00354 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00355 WRITELOG("SSL_set_fd() %s\n", errmsg); 00356 SSL_free(_ssl); 00357 _ssl = 0; 00358 throw false; 00359 } 00360 00361 if (_session) 00362 { 00363 SSL_set_session(_ssl, _session); 00364 } 00365 00366 if (SSL_connect(_ssl) != 1) 00367 { 00368 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00369 WRITELOG("SSL_connect() %s\n", errmsg); 00370 SSL_free(_ssl); 00371 _ssl = 0; 00372 throw false; 00373 } 00374 00375 int result; 00376 if ( (result = SSL_get_verify_result(_ssl)) != X509_V_OK) 00377 { 00378 WRITELOG("SSL_get_verify_result() error: %s.\n", X509_verify_cert_error_string(result)); 00379 SSL_free(_ssl); 00380 _ssl = 0; 00381 throw false; 00382 } 00383 00384 X509* peer = SSL_get_peer_certificate(_ssl); 00385 X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, peer_CN, 256); 00386 char* pos = peer_CN; 00387 if ( *pos == '*') 00388 { 00389 while (*host++ != '.'); 00390 pos += 2; 00391 } 00392 if ( strcmp(host, pos)) 00393 { 00394 WRITELOG("SSL_get_peer_certificate() error: Broker %s dosen't match the host name %s\n", peer_CN, host); 00395 SSL_free(_ssl); 00396 _ssl = 0; 00397 throw false; 00398 } 00399 00400 if (_session == 0) 00401 { 00402 _session = SSL_get1_session(_ssl); 00403 } 00404 _numOfInstance++; 00405 _sslValid = true; 00406 rc = true; 00407 } 00408 catch (bool x) 00409 { 00410 rc = x; 00411 } 00412 _mutex.unlock(); 00413 return rc; 00414 } 00415 00416 int Network::send(const uint8_t* buf, uint16_t length) 00417 { 00418 char errmsg[256]; 00419 fd_set rset; 00420 fd_set wset; 00421 bool writeBlockedOnRead = false; 00422 int bpos = 0; 00423 00424 if (!_secureFlg) 00425 { 00426 return TCPStack::send(buf, length); 00427 } 00428 else 00429 { 00430 _mutex.lock(); 00431 00432 if ( !_ssl ) 00433 { 00434 _mutex.unlock(); 00435 return -1; 00436 } 00437 _busy = true; 00438 00439 while (true) 00440 { 00441 FD_ZERO(&rset); 00442 FD_ZERO(&wset); 00443 FD_SET(getSock(), &rset); 00444 FD_SET(getSock(), &wset); 00445 00446 int activity = select(getSock() + 1, &rset, &wset, 0, 0); 00447 if (activity > 0) 00448 { 00449 if (FD_ISSET(getSock(), &wset) || (writeBlockedOnRead && FD_ISSET(getSock(), &rset))) 00450 { 00451 00452 writeBlockedOnRead = false; 00453 int r = SSL_write(_ssl, buf + bpos, length); 00454 00455 switch (SSL_get_error(_ssl, r)) 00456 { 00457 case SSL_ERROR_NONE: 00458 length -= r; 00459 bpos += r; 00460 if (length == 0) 00461 { 00462 _busy = false; 00463 _mutex.unlock(); 00464 return bpos; 00465 } 00466 break; 00467 case SSL_ERROR_WANT_WRITE: 00468 break; 00469 case SSL_ERROR_WANT_READ: 00470 writeBlockedOnRead = true; 00471 break; 00472 default: 00473 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00474 WRITELOG("TLSStack::send() default %s\n", errmsg); 00475 _busy = false; 00476 _mutex.unlock(); 00477 return -1; 00478 } 00479 } 00480 } 00481 } 00482 } 00483 } 00484 00485 int Network::recv(uint8_t* buf, uint16_t len) 00486 { 00487 char errmsg[256]; 00488 bool writeBlockedOnRead = false; 00489 bool readBlockedOnWrite = false; 00490 bool readBlocked = false; 00491 int rlen = 0; 00492 int bpos = 0; 00493 fd_set rset; 00494 fd_set wset; 00495 00496 if (!_secureFlg) 00497 { 00498 return TCPStack::recv(buf, len); 00499 } 00500 00501 if (_busy) 00502 { 00503 return 0; 00504 } 00505 _mutex.lock(); 00506 00507 if ( !_ssl ) 00508 { 00509 _mutex.unlock(); 00510 return 0; 00511 } 00512 00513 _busy = true; 00514 loop: 00515 do 00516 { 00517 readBlockedOnWrite = false; 00518 readBlocked = false; 00519 00520 rlen = SSL_read(_ssl, buf + bpos, len - bpos); 00521 00522 switch (SSL_get_error(_ssl, rlen)) 00523 { 00524 case SSL_ERROR_NONE: 00525 _busy = false; 00526 _mutex.unlock(); 00527 return rlen + bpos; 00528 break; 00529 case SSL_ERROR_ZERO_RETURN: 00530 SSL_shutdown(_ssl); 00531 _ssl = 0; 00532 _numOfInstance--; 00533 //TCPStack::close(); 00534 _busy = false; 00535 _mutex.unlock(); 00536 return -1; 00537 break; 00538 case SSL_ERROR_WANT_READ: 00539 readBlocked = true; 00540 break; 00541 case SSL_ERROR_WANT_WRITE: 00542 readBlockedOnWrite = true; 00543 break; 00544 default: 00545 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00546 WRITELOG("Network::recv() %s\n", errmsg); 00547 _busy = false; 00548 _mutex.unlock(); 00549 return -1; 00550 } 00551 } while (SSL_pending(_ssl) && !readBlocked); 00552 00553 bpos += rlen; 00554 while (true) 00555 { 00556 FD_ZERO(&rset); 00557 FD_ZERO(&wset); 00558 FD_SET(getSock(), &rset); 00559 FD_SET(getSock(), &wset); 00560 00561 int activity = select(getSock() + 1, &rset, &wset, 0, 0); 00562 if (activity > 0) 00563 { 00564 if ((FD_ISSET(getSock(),&rset) && !writeBlockedOnRead) 00565 || (readBlockedOnWrite && FD_ISSET(getSock(), &wset))) 00566 { 00567 goto loop; 00568 } 00569 } 00570 else 00571 { 00572 ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); 00573 WRITELOG("TLSStack::recv() select %s\n", errmsg); 00574 _busy = false; 00575 _mutex.unlock(); 00576 return -1; 00577 } 00578 } 00579 } 00580 00581 void Network::close(void) 00582 { 00583 _mutex.lock(); 00584 if (_secureFlg) 00585 { 00586 if (_ssl) 00587 { 00588 SSL_shutdown(_ssl); 00589 SSL_free(_ssl); 00590 _numOfInstance--; 00591 _ssl = 0; 00592 _sslValid = false; 00593 _busy = false; 00594 } 00595 if (_session && _numOfInstance == 0) 00596 { 00597 SSL_SESSION_free(_session); 00598 _session = 0; 00599 } 00600 if (_ctx && _numOfInstance == 0) 00601 { 00602 SSL_CTX_free(_ctx); 00603 _ctx = 0; 00604 ERR_free_strings(); 00605 } 00606 } 00607 TCPStack::close(); 00608 _mutex.unlock(); 00609 } 00610 00611 bool Network::isValid() 00612 { 00613 if ( TCPStack::isValid() ) 00614 { 00615 if (_secureFlg) 00616 { 00617 if (_sslValid && !_busy) 00618 { 00619 return true; 00620 } 00621 } 00622 else 00623 { 00624 return true; 00625 } 00626 } 00627 return false; 00628 } 00629 00630 int Network::getSock() 00631 { 00632 return TCPStack::getSock(); 00633 } 00634 00635 bool Network::isSecure() 00636 { 00637 return _secureFlg; 00638 } 00639
Generated on Wed Jul 13 2022 10:46:03 by
1.7.2