/** * Creates a new JSON-RPC listener on the specified port. * * @param node The host the listener should be bound to. * @param service The port to listen on. */ bool ApiListener::AddListener(const String& node, const String& service) { ObjectLock olock(this); boost::shared_ptr<SSL_CTX> sslContext = m_SSLContext; if (!sslContext) { Log(LogCritical, "ApiListener", "SSL context is required for AddListener()"); return false; } Log(LogInformation, "ApiListener") << "Adding new listener on port '" << service << "'"; TcpSocket::Ptr server = new TcpSocket(); try { server->Bind(node, service, AF_UNSPEC); } catch (const std::exception&) { Log(LogCritical, "ApiListener") << "Cannot bind TCP socket for host '" << node << "' on port '" << service << "'."; return false; } boost::thread thread(boost::bind(&ApiListener::ListenerThreadProc, this, server)); thread.detach(); m_Servers.insert(server); return true; }
void HttpClientConnection::Reconnect() { if (m_Stream) m_Stream->Close(); m_Context.~StreamReadContext(); new (&m_Context) StreamReadContext(); m_Requests.clear(); m_CurrentResponse.reset(); TcpSocket::Ptr socket = new TcpSocket(); socket->Connect(m_Host, m_Port); if (m_Tls) m_Stream = new TlsStream(socket, m_Host, RoleClient); else ASSERT(!"Non-TLS HTTP connections not supported."); /* m_Stream = new NetworkStream(socket); * -- does not currently work because the NetworkStream class doesn't support async I/O */ /* the stream holds an owning reference to this object through the callback we're registering here */ m_Stream->RegisterDataHandler(std::bind(&HttpClientConnection::DataAvailableHandler, HttpClientConnection::Ptr(this), _1)); if (m_Stream->IsDataAvailable()) DataAvailableHandler(m_Stream); }
int PkiUtility::SaveCert(const String& host, const String& port, const String& keyfile, const String& certfile, const String& trustedfile) { TcpSocket::Ptr client = new TcpSocket(); client->Connect(host, port); boost::shared_ptr<SSL_CTX> sslContext = MakeSSLContext(certfile, keyfile); TlsStream::Ptr stream = new TlsStream(client, RoleClient, sslContext); try { stream->Handshake(); } catch (...) { } boost::shared_ptr<X509> cert = stream->GetPeerCertificate(); std::ofstream fpcert; fpcert.open(trustedfile.CStr()); fpcert << CertificateToString(cert); fpcert.close(); if (fpcert.fail()) { Log(LogCritical, "cli") << "Could not write certificate to file '" << trustedfile << "'."; return 1; } Log(LogInformation, "cli") << "Writing trusted certificate to file '" << trustedfile << "'."; return 0; }
void HttpClientConnection::Reconnect(void) { if (m_Stream) m_Stream->Close(); m_Context.~StreamReadContext(); new (&m_Context) StreamReadContext(); m_Requests.clear(); m_CurrentResponse.reset(); TcpSocket::Ptr socket = new TcpSocket(); socket->Connect(m_Host, m_Port); if (m_Tls) m_Stream = new TlsStream(socket, m_Host, RoleClient); else ASSERT(!"Non-TLS HTTP connections not supported."); /* m_Stream = new NetworkStream(socket); -- does not currently work because the NetworkStream class doesn't support async I/O */ m_Stream->RegisterDataHandler(boost::bind(&HttpClientConnection::DataAvailableHandler, this, _1)); if (m_Stream->IsDataAvailable()) DataAvailableHandler(m_Stream); }
int PkiUtility::SaveCert(const String& host, const String& port, const String& keyfile, const String& certfile, const String& trustedfile) { TcpSocket::Ptr client = new TcpSocket(); try { client->Connect(host, port); } catch (const std::exception& ex) { Log(LogCritical, "cli") << "Cannot connect to host '" << host << "' on port '" << port << "'"; Log(LogDebug, "cli") << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex); return 1; } boost::shared_ptr<SSL_CTX> sslContext; try { sslContext = MakeSSLContext(certfile, keyfile); } catch (const std::exception& ex) { Log(LogCritical, "cli") << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "'."; Log(LogDebug, "cli") << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "':\n" << DiagnosticInformation(ex); return 1; } TlsStream::Ptr stream = new TlsStream(client, String(), RoleClient, sslContext); try { stream->Handshake(); } catch (...) { } boost::shared_ptr<X509> cert = stream->GetPeerCertificate(); if (!cert) { Log(LogCritical, "cli", "Peer did not present a valid certificate."); return 1; } std::ofstream fpcert; fpcert.open(trustedfile.CStr()); fpcert << CertificateToString(cert); fpcert.close(); if (fpcert.fail()) { Log(LogCritical, "cli") << "Could not write certificate to file '" << trustedfile << "'."; return 1; } Log(LogInformation, "cli") << "Writing trusted certificate to file '" << trustedfile << "'."; return 0; }
ListenerES::ListenerES(TcpSocket::Ptr p_tcpSocket, int p_port) : SocketES(p_tcpSocket) { m_eventTypes.insert(Epoll::EventType::Error); m_eventTypes.insert(Epoll::EventType::In); m_eventTypes.insert(Epoll::EventType::Hup); m_eventTypes.insert(Epoll::EventType::RdHup); p_tcpSocket->setNonBlocking(); p_tcpSocket->bind(p_port); p_tcpSocket->listen(); }
/** * Creates a new JSON-RPC client and connects to the specified endpoint. * * @param endpoint The endpoint. */ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint) { { ObjectLock olock(this); std::shared_ptr<SSL_CTX> sslContext = m_SSLContext; if (!sslContext) { Log(LogCritical, "ApiListener", "SSL context is required for AddConnection()"); return; } } String host = endpoint->GetHost(); String port = endpoint->GetPort(); Log(LogInformation, "ApiListener") << "Reconnecting to endpoint '" << endpoint->GetName() << "' via host '" << host << "' and port '" << port << "'"; TcpSocket::Ptr client = new TcpSocket(); String serverName = endpoint->GetName(); String env = ScriptGlobal::Get("Environment", &Empty); if (env != "" && env != "production") serverName += ":" + env; try { endpoint->SetConnecting(true); client->Connect(host, port); NewClientHandler(client, serverName, RoleClient); endpoint->SetConnecting(false); } catch (const std::exception& ex) { endpoint->SetConnecting(false); client->Close(); std::ostringstream info; info << "Cannot connect to host '" << host << "' on port '" << port << "'"; Log(LogCritical, "ApiListener", info.str()); Log(LogDebug, "ApiListener") << info.str() << "\n" << DiagnosticInformation(ex); } Log(LogInformation, "ApiListener") << "Finished reconnecting to endpoint '" << endpoint->GetName() << "' via host '" << host << "' and port '" << port << "'"; }
void GraphiteWriter::ReconnectTimerHandler(void) { try { if (m_Stream) { m_Stream->Write("\n", 1); Log(LogWarning, "perfdata", "GraphiteWriter already connected on socket on host '" + GetHost() + "' port '" + GetPort() + "'."); return; } } catch (const std::exception& ex) { Log(LogWarning, "perfdata", "GraphiteWriter socket on host '" + GetHost() + "' port '" + GetPort() + "' gone. Attempting to reconnect."); } TcpSocket::Ptr socket = make_shared<TcpSocket>(); Log(LogDebug, "perfdata", "GraphiteWriter: Reconnect to tcp socket on host '" + GetHost() + "' port '" + GetPort() + "'."); socket->Connect(GetHost(), GetPort()); NetworkStream::Ptr net_stream = make_shared<NetworkStream>(socket); m_Stream = make_shared<BufferedStream>(net_stream); }
void GelfWriter::ReconnectTimerHandler(void) { if (m_Stream) return; TcpSocket::Ptr socket = new TcpSocket(); Log(LogNotice, "GelfWriter") << "Reconnecting to GELF endpoint '" << GetHost() << "' port '" << GetPort() << "'."; try { socket->Connect(GetHost(), GetPort()); } catch (std::exception&) { Log(LogCritical, "GelfWriter") << "Can't connect to GELF endpoint '" << GetHost() << "' port '" << GetPort() << "'."; return; } m_Stream = new NetworkStream(socket); }
void OpenTsdbWriter::ReconnectTimerHandler() { if (m_Stream) return; TcpSocket::Ptr socket = new TcpSocket(); Log(LogNotice, "OpenTsdbWriter") << "Reconnect to OpenTSDB TSD on host '" << GetHost() << "' port '" << GetPort() << "'."; try { socket->Connect(GetHost(), GetPort()); } catch (std::exception&) { Log(LogCritical, "OpenTsdbWriter") << "Can't connect to OpenTSDB TSD on host '" << GetHost() << "' port '" << GetPort() << "'."; return; } m_Stream = new NetworkStream(socket); }
Stream::Ptr InfluxdbWriter::Connect(void) { TcpSocket::Ptr socket = new TcpSocket(); Log(LogNotice, "InfluxdbWriter") << "Reconnecting to InfluxDB on host '" << GetHost() << "' port '" << GetPort() << "'."; try { socket->Connect(GetHost(), GetPort()); } catch (std::exception&) { Log(LogWarning, "InfluxdbWriter") << "Can't connect to InfluxDB on host '" << GetHost() << "' port '" << GetPort() << "'."; return Stream::Ptr(); } if (GetSslEnable()) { boost::shared_ptr<SSL_CTX> ssl_context; try { ssl_context = MakeSSLContext(GetSslCert(), GetSslKey(), GetSslCaCert()); } catch (std::exception&) { Log(LogWarning, "InfluxdbWriter") << "Unable to create SSL context."; return Stream::Ptr(); } TlsStream::Ptr tls_stream = new TlsStream(socket, GetHost(), RoleClient, ssl_context); try { tls_stream->Handshake(); } catch (std::exception&) { Log(LogWarning, "InfluxdbWriter") << "TLS handshake with host '" << GetHost() << "' failed."; return Stream::Ptr(); } return tls_stream; } else { return new NetworkStream(socket); } }
/** * Creates a new JSON-RPC client and connects to the specified endpoint. * * @param endpoint The endpoint. */ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint) { { ObjectLock olock(this); boost::shared_ptr<SSL_CTX> sslContext = m_SSLContext; if (!sslContext) { Log(LogCritical, "ApiListener", "SSL context is required for AddConnection()"); return; } } String host = endpoint->GetHost(); String port = endpoint->GetPort(); Log(LogInformation, "JsonRpcConnection") << "Reconnecting to API endpoint '" << endpoint->GetName() << "' via host '" << host << "' and port '" << port << "'"; TcpSocket::Ptr client = new TcpSocket(); try { endpoint->SetConnecting(true); client->Connect(host, port); NewClientHandler(client, endpoint->GetName(), RoleClient); endpoint->SetConnecting(false); } catch (const std::exception& ex) { endpoint->SetConnecting(false); client->Close(); std::ostringstream info; info << "Cannot connect to host '" << host << "' on port '" << port << "'"; Log(LogCritical, "ApiListener", info.str()); Log(LogDebug, "ApiListener") << info.str() << "\n" << DiagnosticInformation(ex); } }
boost::shared_ptr<X509> PkiUtility::FetchCert(const String& host, const String& port) { TcpSocket::Ptr client = new TcpSocket(); try { client->Connect(host, port); } catch (const std::exception& ex) { Log(LogCritical, "pki") << "Cannot connect to host '" << host << "' on port '" << port << "'"; Log(LogDebug, "pki") << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex); return boost::shared_ptr<X509>(); } boost::shared_ptr<SSL_CTX> sslContext; try { sslContext = MakeSSLContext(); } catch (const std::exception& ex) { Log(LogCritical, "pki") << "Cannot make SSL context."; Log(LogDebug, "pki") << "Cannot make SSL context:\n" << DiagnosticInformation(ex); return boost::shared_ptr<X509>(); } TlsStream::Ptr stream = new TlsStream(client, host, RoleClient, sslContext); try { stream->Handshake(); } catch (...) { } return stream->GetPeerCertificate(); }
int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile, const String& certfile, const String& cafile, const boost::shared_ptr<X509>& trustedCert, const String& ticket) { TcpSocket::Ptr client = new TcpSocket(); try { client->Connect(host, port); } catch (const std::exception& ex) { Log(LogCritical, "cli") << "Cannot connect to host '" << host << "' on port '" << port << "'"; Log(LogDebug, "cli") << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex); return 1; } boost::shared_ptr<SSL_CTX> sslContext; try { sslContext = MakeSSLContext(certfile, keyfile); } catch (const std::exception& ex) { Log(LogCritical, "cli") << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "'."; Log(LogDebug, "cli") << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "':\n" << DiagnosticInformation(ex); return 1; } TlsStream::Ptr stream = new TlsStream(client, host, RoleClient, sslContext); try { stream->Handshake(); } catch (const std::exception&) { Log(LogCritical, "cli", "Client TLS handshake failed."); return 1; } boost::shared_ptr<X509> peerCert = stream->GetPeerCertificate(); if (X509_cmp(peerCert.get(), trustedCert.get())) { Log(LogCritical, "cli", "Peer certificate does not match trusted certificate."); return 1; } Dictionary::Ptr request = new Dictionary(); String msgid = Utility::NewUniqueID(); request->Set("jsonrpc", "2.0"); request->Set("id", msgid); request->Set("method", "pki::RequestCertificate"); Dictionary::Ptr params = new Dictionary(); params->Set("ticket", String(ticket)); request->Set("params", params); JsonRpc::SendMessage(stream, request); String jsonString; Dictionary::Ptr response; StreamReadContext src; for (;;) { StreamReadStatus srs = JsonRpc::ReadMessage(stream, &jsonString, src); if (srs == StatusEof) break; if (srs != StatusNewItem) continue; response = JsonRpc::DecodeMessage(jsonString); if (response && response->Contains("error")) { Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log (notice or debug)."); #ifdef I2_DEBUG /* we shouldn't expose master errors to the user in production environments */ Log(LogCritical, "cli", response->Get("error")); #endif /* I2_DEBUG */ return 1; } if (response && (response->Get("id") != msgid)) continue; break; } if (!response) { Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log."); return 1; } Dictionary::Ptr result = response->Get("result"); if (result->Contains("error")) { Log(LogCritical, "cli", result->Get("error")); return 1; } std::ofstream fpcert; fpcert.open(certfile.CStr()); fpcert << result->Get("cert"); fpcert.close(); if (fpcert.fail()) { Log(LogCritical, "cli") << "Could not write certificate to file '" << certfile << "'."; return 1; } Log(LogInformation, "cli") << "Writing signed certificate to file '" << certfile << "'."; std::ofstream fpca; fpca.open(cafile.CStr()); fpca << result->Get("ca"); fpca.close(); if (fpca.fail()) { Log(LogCritical, "cli") << "Could not open CA certificate file '" << cafile << "' for writing."; return 1; } Log(LogInformation, "cli") << "Writing CA certificate to file '" << cafile << "'."; return 0; }
int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile, const String& certfile, const String& cafile, const String& trustedfile, const String& ticket) { TcpSocket::Ptr client = make_shared<TcpSocket>(); try { client->Connect(host, port); } catch (const std::exception& ex) { Log(LogCritical, "cli") << "Cannot connect to host '" << host << "' on port '" << port << "'"; Log(LogDebug, "cli") << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex); return 1; } shared_ptr<SSL_CTX> sslContext; try { sslContext = MakeSSLContext(certfile, keyfile); } catch (const std::exception& ex) { Log(LogCritical, "cli") << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "'."; return 1; } TlsStream::Ptr stream = make_shared<TlsStream>(client, RoleClient, sslContext); try { stream->Handshake(); } catch (const std::exception&) { Log(LogCritical, "cli", "Client TLS handshake failed."); return 1; } shared_ptr<X509> peerCert = stream->GetPeerCertificate(); shared_ptr<X509> trustedCert; try { trustedCert = GetX509Certificate(trustedfile); } catch (const std::exception&) { Log(LogCritical, "cli") << "Cannot get trusted from cert path: '" << trustedfile << "'."; return 1; } if (CertificateToString(peerCert) != CertificateToString(trustedCert)) { Log(LogCritical, "cli", "Peer certificate does not match trusted certificate."); return 1; } Dictionary::Ptr request = make_shared<Dictionary>(); String msgid = Utility::NewUniqueID(); request->Set("jsonrpc", "2.0"); request->Set("id", msgid); request->Set("method", "pki::RequestCertificate"); Dictionary::Ptr params = make_shared<Dictionary>(); params->Set("ticket", String(ticket)); request->Set("params", params); JsonRpc::SendMessage(stream, request); Dictionary::Ptr response; for (;;) { response = JsonRpc::ReadMessage(stream); if (response->Get("id") != msgid) continue; break; } if (!response->Contains("result")) { Log(LogCritical, "cli", "Request certificate did not return a valid result. Check the master log for details!"); return 1; } Dictionary::Ptr result = response->Get("result"); if (result->Contains("error")) { Log(LogCritical, "cli", result->Get("error")); return 1; } std::ofstream fpcert; fpcert.open(certfile.CStr()); fpcert << result->Get("cert"); fpcert.close(); if (fpcert.fail()) { Log(LogCritical, "cli") << "Could not write certificate to file '" << certfile << "'."; return 1; } Log(LogInformation, "cli") << "Writing signed certificate to file '" << certfile << "'."; std::ofstream fpca; fpca.open(cafile.CStr()); fpca << result->Get("ca"); fpca.close(); if (fpca.fail()) { Log(LogCritical, "cli") << "Could not open CA certificate file '" << cafile << "' for writing."; return 1; } Log(LogInformation, "cli") << "Writing CA certificate to file '" << cafile << "'."; return 0; }
MessageES::Ptr ListenerES::accept() const { TcpSocket::Ptr tcpSocket = boost::dynamic_pointer_cast<TcpSocket>(m_socket); TcpSocket::Ptr accepted = tcpSocket->accept(); return MessageES::Ptr(new MessageES(accepted)); }
bool TcpService::_addTcpConnection(TcpSocket::Ptr socket, const std::vector<AddSocketOption::AddSocketOptionFunc>& optionFuncs) { struct TcpService::AddSocketOption::Options options; for (const auto& v : optionFuncs) { if (v != nullptr) { v(options); } } if (options.maxRecvBufferSize <= 0) { throw std::runtime_error("buffer size is zero"); } EventLoop::Ptr eventLoop; if (options.forceSameThreadLoop) { eventLoop = getSameThreadEventLoop(); } else { eventLoop = getRandomEventLoop(); } if (eventLoop == nullptr) { return false; } auto wrapperEnterCallback = [options](const TcpConnection::Ptr& tcpConnection) { for (const auto& callback : options.enterCallback) { callback(tcpConnection); } }; const auto isServerSide = socket->isServerSide(); auto tcpConnection = TcpConnection::Create(std::move(socket), options.maxRecvBufferSize, wrapperEnterCallback, eventLoop); (void)isServerSide; #ifdef USE_OPENSSL if (options.useSSL) { if (isServerSide) { if (options.sslHelper == nullptr || options.sslHelper->getOpenSSLCTX() == nullptr || !tcpConnection->initAcceptSSL(options.sslHelper->getOpenSSLCTX())) { return false; } } else { if (!tcpConnection->initConnectSSL()) { return false; } } } #else if (options.useSSL) { return false; } #endif eventLoop->runAsyncFunctor([tcpConnection]() { tcpConnection->onEnterEventLoop(); }); return true; }