Note: If DoIfwNetIo returns due to an error, the plugin output of the specified CheckResult (cr) will always be set, and if it was successful, the cr exit status, plugin state and performance data (if any) will also be overridden. Therefore, you have to take care yourself of setting all the other necessary fields for the check result.
| 49 | // and if it was successful, the cr exit status, plugin state and performance data (if any) will also be overridden. |
| 50 | // Therefore, you have to take care yourself of setting all the other necessary fields for the check result. |
| 51 | static void DoIfwNetIo( |
| 52 | boost::asio::yield_context yc, const CheckResult::Ptr& cr, const String& psCommand, const String& psHost, const String& san, |
| 53 | const String& psPort, AsioTlsStream& conn, boost::beast::http::request<boost::beast::http::string_body>& req |
| 54 | ) |
| 55 | { |
| 56 | namespace http = boost::beast::http; |
| 57 | |
| 58 | boost::beast::flat_buffer buf; |
| 59 | http::response<http::string_body> resp; |
| 60 | |
| 61 | try { |
| 62 | Connect(conn.lowest_layer(), psHost, psPort, yc); |
| 63 | } catch (const std::exception& ex) { |
| 64 | cr->SetOutput("Can't connect to IfW API on host '" + psHost + "' port '" + psPort + "': " + GetUnderstandableError(ex)); |
| 65 | return; |
| 66 | } |
| 67 | |
| 68 | auto& sslConn (conn.next_layer()); |
| 69 | |
| 70 | try { |
| 71 | sslConn.async_handshake(conn.next_layer().client, yc); |
| 72 | } catch (const std::exception& ex) { |
| 73 | cr->SetOutput("TLS handshake with IfW API on host '" + psHost + "' (SNI: '" + san+ "') port '" + psPort + "' failed: " + GetUnderstandableError(ex)); |
| 74 | return; |
| 75 | } |
| 76 | |
| 77 | if (!sslConn.IsVerifyOK()) { |
| 78 | auto cert (sslConn.GetPeerCertificate()); |
| 79 | Value cn; |
| 80 | |
| 81 | try { |
| 82 | cn = GetCertificateCN(cert); |
| 83 | } catch (const std::exception&) { } |
| 84 | |
| 85 | cr->SetOutput("Certificate validation failed for IfW API on host '" + psHost + "' (SNI: '" + san + "'; CN: " |
| 86 | + (cn.IsString() ? "'" + cn + "'" : "N/A") + ") port '" + psPort + "': " + sslConn.GetVerifyError()); |
| 87 | return; |
| 88 | } |
| 89 | |
| 90 | try { |
| 91 | http::async_write(conn, req, yc); |
| 92 | conn.async_flush(yc); |
| 93 | } catch (const std::exception& ex) { |
| 94 | cr->SetOutput("Can't send HTTP request to IfW API on host '" + psHost + "' port '" + psPort + "': " + GetUnderstandableError(ex)); |
| 95 | return; |
| 96 | } |
| 97 | |
| 98 | try { |
| 99 | http::async_read(conn, buf, resp, yc); |
| 100 | } catch (const std::exception& ex) { |
| 101 | cr->SetOutput("Can't read HTTP response from IfW API on host '" + psHost + "' port '" + psPort + "': " + GetUnderstandableError(ex)); |
| 102 | return; |
| 103 | } |
| 104 | |
| 105 | { |
| 106 | // Using async_shutdown() instead of AsioTlsStream::GracefulDisconnect() as this whole function |
| 107 | // is already guarded by a timeout based on the check timeout. |
| 108 | boost::system::error_code ec; |
no test coverage detected