From a38263b3c80371bb8e69a9e8aab0f0c8e26e8f2f Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sun, 10 Mar 2013 05:10:51 +0100 Subject: [PATCH] Implement livestatus commands. --- components/livestatus/livestatus.vcxproj | 32 ++++---- .../livestatus/livestatus.vcxproj.filters | 36 ++++++--- components/livestatus/livestatuscomponent.cpp | 8 +- .../livestatus/livestatusconnection.cpp | 22 +++++- components/livestatus/livestatusconnection.h | 2 + components/livestatus/livestatusquery.cpp | 49 +++++------- components/livestatus/livestatusquery.h | 6 +- icinga2.sln | 75 +++++++++++++++++++ lib/base/socket.cpp | 51 ++++++++----- lib/base/socket.h | 2 + lib/base/stream.cpp | 71 ++++++++++++++---- lib/base/stream.h | 9 ++- 12 files changed, 266 insertions(+), 97 deletions(-) diff --git a/components/livestatus/livestatus.vcxproj b/components/livestatus/livestatus.vcxproj index c48033fff..e7ef4b628 100644 --- a/components/livestatus/livestatus.vcxproj +++ b/components/livestatus/livestatus.vcxproj @@ -18,10 +18,23 @@ x64 + + + + + + + + + + + + + - {2E6C1133-730F-4875-A72C-B455B1DD4C5C} + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F} Win32Proj - demo + livestatus @@ -93,7 +106,7 @@ Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;DEMO_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;LIVESTATUS_EXPORTS;%(PreprocessorDefinitions) Level3 false true @@ -107,7 +120,7 @@ Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;DEMO_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;LIVESTATUS_EXPORTS;%(PreprocessorDefinitions) Level3 false true @@ -123,7 +136,7 @@ MaxSpeed true true - WIN32;NDEBUG;_WINDOWS;_USRDLL;DEMO_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;LIVESTATUS_EXPORTS;%(PreprocessorDefinitions) Level3 false true @@ -141,7 +154,7 @@ MaxSpeed true true - WIN32;NDEBUG;_WINDOWS;_USRDLL;DEMO_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;LIVESTATUS_EXPORTS;%(PreprocessorDefinitions) Level3 false true @@ -154,13 +167,6 @@ base.lib;remoting.lib;icinga.lib;%(AdditionalDependencies) - - - - - - - diff --git a/components/livestatus/livestatus.vcxproj.filters b/components/livestatus/livestatus.vcxproj.filters index e02ed2da9..533492f32 100644 --- a/components/livestatus/livestatus.vcxproj.filters +++ b/components/livestatus/livestatus.vcxproj.filters @@ -1,13 +1,5 @@  - - - Headerdateien - - - Headerdateien - - {11a495bf-a705-4766-b3d3-9b5db266a6ef} @@ -17,7 +9,33 @@ - + + Headerdateien + + + Headerdateien + + + Headerdateien + + + Headerdateien + + + Headerdateien + + + + + Quelldateien + + + Quelldateien + + + Quelldateien + + Quelldateien diff --git a/components/livestatus/livestatuscomponent.cpp b/components/livestatus/livestatuscomponent.cpp index e9337d1bd..5604e0b72 100644 --- a/components/livestatus/livestatuscomponent.cpp +++ b/components/livestatus/livestatuscomponent.cpp @@ -28,9 +28,15 @@ REGISTER_COMPONENT("livestatus", LivestatusComponent); */ void LivestatusComponent::Start(void) { +#ifndef _WIN32 UnixSocket::Ptr socket = boost::make_shared(); - socket->OnNewClient.connect(boost::bind(&LivestatusComponent::NewClientHandler, this, _2)); socket->Bind(GetSocketPath()); +#else /* _WIN32 */ + TcpSocket::Ptr socket = boost::make_shared(); + socket->Bind("6557", AF_INET); +#endif /* _WIN32 */ + + socket->OnNewClient.connect(boost::bind(&LivestatusComponent::NewClientHandler, this, _2)); socket->Listen(); socket->Start(); m_Listener = socket; diff --git a/components/livestatus/livestatusconnection.cpp b/components/livestatus/livestatusconnection.cpp index b3a2cbecd..29bc50240 100644 --- a/components/livestatus/livestatusconnection.cpp +++ b/components/livestatus/livestatusconnection.cpp @@ -27,10 +27,28 @@ LivestatusConnection::LivestatusConnection(const Stream::Ptr& stream) void LivestatusConnection::ProcessData(void) { - LivestatusQuery::Ptr query = LivestatusQuery::ParseQuery(GetStream()); + String line; + bool read_line = false; - if (!query) + while (GetStream()->ReadLine(&line)) { + read_line = true; + + if (line.GetLength() > 0) + m_Lines.push_back(line); + else + break; + } + + /* Return if we didn't at least read one line. */ + if (!read_line) return; + /* Return if we haven't found the end of the query. */ + if (line.GetLength() > 0 && !GetStream()->IsReadEOF()) + return; + + LivestatusQuery::Ptr query = boost::make_shared(m_Lines); + m_Lines.clear(); + query->Execute(GetStream()); } diff --git a/components/livestatus/livestatusconnection.h b/components/livestatus/livestatusconnection.h index c72cb4669..52e014402 100644 --- a/components/livestatus/livestatusconnection.h +++ b/components/livestatus/livestatusconnection.h @@ -32,6 +32,8 @@ public: LivestatusConnection(const Stream::Ptr& stream); protected: + vector m_Lines; + virtual void ProcessData(void); }; diff --git a/components/livestatus/livestatusquery.cpp b/components/livestatus/livestatusquery.cpp index 22720851b..8e89a6582 100644 --- a/components/livestatus/livestatusquery.cpp +++ b/components/livestatus/livestatusquery.cpp @@ -21,17 +21,12 @@ using namespace icinga; -LivestatusQuery::LivestatusQuery(void) + + +LivestatusQuery::LivestatusQuery(const vector& lines) : m_KeepAlive(false), m_ColumnHeaders(true), m_Limit(-1) -{ } - -LivestatusQuery::Ptr LivestatusQuery::ParseQuery(const Stream::Ptr& stream) { - LivestatusQuery::Ptr query = boost::make_shared(); - String line; - - if (!stream->ReadLine(&line)) - return LivestatusQuery::Ptr(); + String line = lines[0]; size_t sp_index = line.FindFirstOf(" "); @@ -41,40 +36,31 @@ LivestatusQuery::Ptr LivestatusQuery::ParseQuery(const Stream::Ptr& stream) String verb = line.SubStr(0, sp_index); String target = line.SubStr(sp_index + 1); - query->m_Verb = verb; + m_Verb = verb; - if (query->m_Verb == "COMMAND") { - query->m_Command = target; - } else if (query->m_Verb == "GET") { - query->m_Table = target; + if (m_Verb == "COMMAND") { + m_Command = target; + } else if (m_Verb == "GET") { + m_Table = target; } else { - BOOST_THROW_EXCEPTION(runtime_error("Unknown livestatus verb: " + query->m_Verb)); + BOOST_THROW_EXCEPTION(runtime_error("Unknown livestatus verb: " + m_Verb)); } - while (!stream->IsEOF() && stream->ReadLine(&line)) { - /* Empty line means we've reached the end of this query. */ - if (line.GetLength() == 0) - return query; + for (int i = 1; i < lines.size(); i++) { + line = lines[i]; size_t col_index = line.FindFirstOf(":"); String header = line.SubStr(0, col_index); String params = line.SubStr(col_index + 2); if (header == "ResponseHeader") - query->m_ResponseHeader = params; + m_ResponseHeader = params; } - - /* Check if we've reached EOF. */ - if (!stream->IsConnected()) - return query; - - /* Query isn't complete yet. */ - return LivestatusQuery::Ptr(); } void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream) { - + Logger::Write(LogInformation, "livestatus", "Table: " + m_Table); } void LivestatusQuery::ExecuteCommandHelper(const Stream::Ptr& stream) @@ -82,6 +68,7 @@ void LivestatusQuery::ExecuteCommandHelper(const Stream::Ptr& stream) try { Logger::Write(LogInformation, "livestatus", "Executing command: " + m_Command); ExternalCommandProcessor::Execute(m_Command); + SendResponse(stream, 200, ""); } catch (const std::exception& ex) { SendResponse(stream, 452, diagnostic_information(ex)); } @@ -96,7 +83,8 @@ void LivestatusQuery::SendResponse(const Stream::Ptr& stream, int code, const St { if (m_ResponseHeader == "fixed16") PrintFixed16(stream, code, data); - else if (code == 200) + + if (m_ResponseHeader == "fixed16" || code == 200) stream->Write(data.CStr(), data.GetLength()); } @@ -123,4 +111,7 @@ void LivestatusQuery::Execute(const Stream::Ptr& stream) ExecuteErrorHelper(stream); else BOOST_THROW_EXCEPTION(runtime_error("Invalid livestatus query verb.")); + + if (!m_KeepAlive) + stream->Close(); } diff --git a/components/livestatus/livestatusquery.h b/components/livestatus/livestatusquery.h index 9a163c816..22ee1c4b8 100644 --- a/components/livestatus/livestatusquery.h +++ b/components/livestatus/livestatusquery.h @@ -32,7 +32,7 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - static LivestatusQuery::Ptr ParseQuery(const Stream::Ptr& stream); + LivestatusQuery(const vector& lines); void Execute(const Stream::Ptr& stream); @@ -58,16 +58,12 @@ private: int m_ErrorCode; String m_ErrorMessage; - LivestatusQuery(void); - void ExecuteGetHelper(const Stream::Ptr& stream); void ExecuteCommandHelper(const Stream::Ptr& stream); void ExecuteErrorHelper(const Stream::Ptr& stream); void SendResponse(const Stream::Ptr& stream, int code, const String& data); void PrintFixed16(const Stream::Ptr& stream, int code, const String& data); - - friend Ptr boost::make_shared(void); }; } diff --git a/icinga2.sln b/icinga2.sln index 6bc2e55d8..eb8184757 100644 --- a/icinga2.sln +++ b/icinga2.sln @@ -6,6 +6,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icinga-app", "icinga-app\ic {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA} = {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA} {EBEA7D10-66FB-4760-8AA8-81CD500D899E} = {EBEA7D10-66FB-4760-8AA8-81CD500D899E} {2E6C1133-730F-4875-A72C-B455B1DD4C5C} = {2E6C1133-730F-4875-A72C-B455B1DD4C5C} + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F} = {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F} {17C93245-8C20-4316-9573-1AE41D918C10} = {17C93245-8C20-4316-9573-1AE41D918C10} {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C} = {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C} {38CE81CC-2660-4EF0-A936-4A337591DA3E} = {38CE81CC-2660-4EF0-A936-4A337591DA3E} @@ -81,126 +82,199 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", {BE412865-FEBA-4259-AD41-58950D1F5432} = {BE412865-FEBA-4259-AD41-58950D1F5432} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "livestatus", "components\livestatus\livestatus.vcxproj", "{950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}" + ProjectSection(ProjectDependencies) = postProject + {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} = {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|Win64 = Debug|Win64 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|Win64 = Release|Win64 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {BE412865-FEBA-4259-AD41-58950D1F5432}.Debug|Win32.ActiveCfg = Debug|Win32 {BE412865-FEBA-4259-AD41-58950D1F5432}.Debug|Win32.Build.0 = Debug|Win32 {BE412865-FEBA-4259-AD41-58950D1F5432}.Debug|Win64.ActiveCfg = Debug|x64 {BE412865-FEBA-4259-AD41-58950D1F5432}.Debug|Win64.Build.0 = Debug|x64 + {BE412865-FEBA-4259-AD41-58950D1F5432}.Debug|x64.ActiveCfg = Debug|x64 + {BE412865-FEBA-4259-AD41-58950D1F5432}.Debug|x64.Build.0 = Debug|x64 {BE412865-FEBA-4259-AD41-58950D1F5432}.Release|Win32.ActiveCfg = Release|Win32 {BE412865-FEBA-4259-AD41-58950D1F5432}.Release|Win32.Build.0 = Release|Win32 {BE412865-FEBA-4259-AD41-58950D1F5432}.Release|Win64.ActiveCfg = Release|x64 {BE412865-FEBA-4259-AD41-58950D1F5432}.Release|Win64.Build.0 = Release|x64 + {BE412865-FEBA-4259-AD41-58950D1F5432}.Release|x64.ActiveCfg = Release|x64 + {BE412865-FEBA-4259-AD41-58950D1F5432}.Release|x64.Build.0 = Release|x64 {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Debug|Win32.ActiveCfg = Debug|Win32 {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Debug|Win32.Build.0 = Debug|Win32 {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Debug|Win64.ActiveCfg = Debug|x64 {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Debug|Win64.Build.0 = Debug|x64 + {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Debug|x64.ActiveCfg = Debug|x64 + {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Debug|x64.Build.0 = Debug|x64 {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Release|Win32.ActiveCfg = Release|Win32 {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Release|Win32.Build.0 = Release|Win32 {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Release|Win64.ActiveCfg = Release|x64 {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Release|Win64.Build.0 = Release|x64 + {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Release|x64.ActiveCfg = Release|x64 + {2E6C1133-730F-4875-A72C-B455B1DD4C5C}.Release|x64.Build.0 = Release|x64 {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Debug|Win32.ActiveCfg = Debug|Win32 {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Debug|Win32.Build.0 = Debug|Win32 {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Debug|Win64.ActiveCfg = Debug|x64 {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Debug|Win64.Build.0 = Debug|x64 + {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Debug|x64.ActiveCfg = Debug|x64 + {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Debug|x64.Build.0 = Debug|x64 {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Release|Win32.ActiveCfg = Release|Win32 {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Release|Win32.Build.0 = Release|Win32 {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Release|Win64.ActiveCfg = Release|x64 {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Release|Win64.Build.0 = Release|x64 + {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Release|x64.ActiveCfg = Release|x64 + {EBEA7D10-66FB-4760-8AA8-81CD500D899E}.Release|x64.Build.0 = Release|x64 {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Debug|Win32.ActiveCfg = Debug|Win32 {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Debug|Win32.Build.0 = Debug|Win32 {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Debug|Win64.ActiveCfg = Debug|x64 {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Debug|Win64.Build.0 = Debug|x64 + {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Debug|x64.ActiveCfg = Debug|x64 + {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Debug|x64.Build.0 = Debug|x64 {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Release|Win32.ActiveCfg = Release|Win32 {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Release|Win32.Build.0 = Release|Win32 {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Release|Win64.ActiveCfg = Release|x64 {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Release|Win64.Build.0 = Release|x64 + {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Release|x64.ActiveCfg = Release|x64 + {66BED474-C33F-48F9-90BA-BBCFEDC006B8}.Release|x64.Build.0 = Release|x64 {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win32.ActiveCfg = Debug|Win32 {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win32.Build.0 = Debug|Win32 {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win64.ActiveCfg = Debug|x64 {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win64.Build.0 = Debug|x64 + {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|x64.ActiveCfg = Debug|x64 + {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|x64.Build.0 = Debug|x64 {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win32.ActiveCfg = Release|Win32 {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win32.Build.0 = Release|Win32 {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win64.ActiveCfg = Release|x64 {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win64.Build.0 = Release|x64 + {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|x64.ActiveCfg = Release|x64 + {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|x64.Build.0 = Release|x64 {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Debug|Win32.ActiveCfg = Debug|Win32 {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Debug|Win32.Build.0 = Debug|Win32 {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Debug|Win64.ActiveCfg = Debug|x64 {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Debug|Win64.Build.0 = Debug|x64 + {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Debug|x64.ActiveCfg = Debug|x64 + {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Debug|x64.Build.0 = Debug|x64 {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Release|Win32.ActiveCfg = Release|Win32 {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Release|Win32.Build.0 = Release|Win32 {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Release|Win64.ActiveCfg = Release|x64 {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Release|Win64.Build.0 = Release|x64 + {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Release|x64.ActiveCfg = Release|x64 + {38CE81CC-2660-4EF0-A936-4A337591DA3E}.Release|x64.Build.0 = Release|x64 {17C93245-8C20-4316-9573-1AE41D918C10}.Debug|Win32.ActiveCfg = Debug|Win32 {17C93245-8C20-4316-9573-1AE41D918C10}.Debug|Win32.Build.0 = Debug|Win32 {17C93245-8C20-4316-9573-1AE41D918C10}.Debug|Win64.ActiveCfg = Debug|x64 {17C93245-8C20-4316-9573-1AE41D918C10}.Debug|Win64.Build.0 = Debug|x64 + {17C93245-8C20-4316-9573-1AE41D918C10}.Debug|x64.ActiveCfg = Debug|x64 + {17C93245-8C20-4316-9573-1AE41D918C10}.Debug|x64.Build.0 = Debug|x64 {17C93245-8C20-4316-9573-1AE41D918C10}.Release|Win32.ActiveCfg = Release|Win32 {17C93245-8C20-4316-9573-1AE41D918C10}.Release|Win32.Build.0 = Release|Win32 {17C93245-8C20-4316-9573-1AE41D918C10}.Release|Win64.ActiveCfg = Release|x64 {17C93245-8C20-4316-9573-1AE41D918C10}.Release|Win64.Build.0 = Release|x64 + {17C93245-8C20-4316-9573-1AE41D918C10}.Release|x64.ActiveCfg = Release|x64 + {17C93245-8C20-4316-9573-1AE41D918C10}.Release|x64.Build.0 = Release|x64 {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Debug|Win32.ActiveCfg = Debug|Win32 {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Debug|Win32.Build.0 = Debug|Win32 {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Debug|Win64.ActiveCfg = Debug|x64 {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Debug|Win64.Build.0 = Debug|x64 + {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Debug|x64.ActiveCfg = Debug|x64 + {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Debug|x64.Build.0 = Debug|x64 {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Release|Win32.ActiveCfg = Release|Win32 {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Release|Win32.Build.0 = Release|Win32 {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Release|Win64.ActiveCfg = Release|x64 {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Release|Win64.Build.0 = Release|x64 + {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Release|x64.ActiveCfg = Release|x64 + {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}.Release|x64.Build.0 = Release|x64 {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Debug|Win32.ActiveCfg = Debug|Win32 {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Debug|Win32.Build.0 = Debug|Win32 {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Debug|Win64.ActiveCfg = Debug|x64 {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Debug|Win64.Build.0 = Debug|x64 + {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Debug|x64.ActiveCfg = Debug|x64 + {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Debug|x64.Build.0 = Debug|x64 {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Release|Win32.ActiveCfg = Release|Win32 {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Release|Win32.Build.0 = Release|Win32 {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Release|Win64.ActiveCfg = Release|x64 {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Release|Win64.Build.0 = Release|x64 + {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Release|x64.ActiveCfg = Release|x64 + {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}.Release|x64.Build.0 = Release|x64 {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Debug|Win32.ActiveCfg = Debug|Win32 {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Debug|Win32.Build.0 = Debug|Win32 {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Debug|Win64.ActiveCfg = Debug|x64 {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Debug|Win64.Build.0 = Debug|x64 + {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Debug|x64.ActiveCfg = Debug|x64 + {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Debug|x64.Build.0 = Debug|x64 {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Release|Win32.ActiveCfg = Release|Win32 {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Release|Win32.Build.0 = Release|Win32 {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Release|Win64.ActiveCfg = Release|x64 {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Release|Win64.Build.0 = Release|x64 + {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Release|x64.ActiveCfg = Release|x64 + {9C92DA90-FD53-43A9-A244-90F2E8AF9677}.Release|x64.Build.0 = Release|x64 {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Debug|Win32.ActiveCfg = Debug|Win32 {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Debug|Win32.Build.0 = Debug|Win32 {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Debug|Win64.ActiveCfg = Debug|x64 {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Debug|Win64.Build.0 = Debug|x64 + {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Debug|x64.ActiveCfg = Debug|x64 + {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Debug|x64.Build.0 = Debug|x64 {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Release|Win32.ActiveCfg = Release|Win32 {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Release|Win32.Build.0 = Release|Win32 {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Release|Win64.ActiveCfg = Release|x64 {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Release|Win64.Build.0 = Release|x64 + {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Release|x64.ActiveCfg = Release|x64 + {B26AFFA6-2BDF-42E6-A224-2591FFD9BFB7}.Release|x64.Build.0 = Release|x64 {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Debug|Win32.ActiveCfg = Debug|Win32 {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Debug|Win32.Build.0 = Debug|Win32 {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Debug|Win64.ActiveCfg = Debug|x64 {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Debug|Win64.Build.0 = Debug|x64 + {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Debug|x64.ActiveCfg = Debug|x64 + {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Debug|x64.Build.0 = Debug|x64 {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Release|Win32.ActiveCfg = Release|Win32 {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Release|Win32.Build.0 = Release|Win32 {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Release|Win64.ActiveCfg = Release|x64 {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Release|Win64.Build.0 = Release|x64 + {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Release|x64.ActiveCfg = Release|x64 + {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}.Release|x64.Build.0 = Release|x64 {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Debug|Win32.ActiveCfg = Debug|Win32 {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Debug|Win32.Build.0 = Debug|Win32 {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Debug|Win64.ActiveCfg = Debug|x64 {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Debug|Win64.Build.0 = Debug|x64 + {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Debug|x64.ActiveCfg = Debug|x64 + {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Debug|x64.Build.0 = Debug|x64 {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Release|Win32.ActiveCfg = Release|Win32 {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Release|Win32.Build.0 = Release|Win32 {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Release|Win64.ActiveCfg = Release|x64 {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Release|Win64.Build.0 = Release|x64 + {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Release|x64.ActiveCfg = Release|x64 + {8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}.Release|x64.Build.0 = Release|x64 {5163C576-6AA1-4769-8396-9639C45BE124}.Debug|Win32.ActiveCfg = Debug|Win32 {5163C576-6AA1-4769-8396-9639C45BE124}.Debug|Win32.Build.0 = Debug|Win32 {5163C576-6AA1-4769-8396-9639C45BE124}.Debug|Win64.ActiveCfg = Debug|x64 {5163C576-6AA1-4769-8396-9639C45BE124}.Debug|Win64.Build.0 = Debug|x64 + {5163C576-6AA1-4769-8396-9639C45BE124}.Debug|x64.ActiveCfg = Debug|x64 + {5163C576-6AA1-4769-8396-9639C45BE124}.Debug|x64.Build.0 = Debug|x64 {5163C576-6AA1-4769-8396-9639C45BE124}.Release|Win32.ActiveCfg = Release|Win32 {5163C576-6AA1-4769-8396-9639C45BE124}.Release|Win32.Build.0 = Release|Win32 {5163C576-6AA1-4769-8396-9639C45BE124}.Release|Win64.ActiveCfg = Release|x64 {5163C576-6AA1-4769-8396-9639C45BE124}.Release|Win64.Build.0 = Release|x64 + {5163C576-6AA1-4769-8396-9639C45BE124}.Release|x64.ActiveCfg = Release|x64 + {5163C576-6AA1-4769-8396-9639C45BE124}.Release|x64.Build.0 = Release|x64 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Debug|Win32.ActiveCfg = Debug|Win32 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Debug|Win32.Build.0 = Debug|Win32 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Debug|Win64.ActiveCfg = Debug|Win32 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Debug|x64.ActiveCfg = Debug|x64 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Debug|x64.Build.0 = Debug|x64 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Release|Win32.ActiveCfg = Release|Win32 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Release|Win32.Build.0 = Release|Win32 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Release|Win64.ActiveCfg = Release|Win32 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Release|x64.ActiveCfg = Release|x64 + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -212,6 +286,7 @@ Global {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C} = {4A1773FD-DDED-4952-8700-C898E890554A} {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA} = {4A1773FD-DDED-4952-8700-C898E890554A} {2E6C1133-730F-4875-A72C-B455B1DD4C5C} = {4A1773FD-DDED-4952-8700-C898E890554A} + {950E8743-BB34-4F8A-99EC-C87E8FC0EB3F} = {4A1773FD-DDED-4952-8700-C898E890554A} {19CBCE06-3F5C-479A-BD75-E2AB6215D345} = {3BE47C55-D74A-46E6-8F8B-470B3FD29FB7} {66BED474-C33F-48F9-90BA-BBCFEDC006B8} = {3BE47C55-D74A-46E6-8F8B-470B3FD29FB7} {9C92DA90-FD53-43A9-A244-90F2E8AF9677} = {BC82DE9C-42E2-4880-92DA-C2269D2F6416} diff --git a/lib/base/socket.cpp b/lib/base/socket.cpp index 8ccd97fd0..53bd08ee8 100644 --- a/lib/base/socket.cpp +++ b/lib/base/socket.cpp @@ -40,7 +40,7 @@ Socket::~Socket(void) m_SendQueue->Close(); m_RecvQueue->Close(); - Close(); + CloseInternal(); } /** @@ -96,21 +96,29 @@ SOCKET Socket::GetFD(void) const /** * Closes the socket. */ -void Socket::Close(void) +void Socket::CloseInternal(void) { { ObjectLock olock(this); - if (m_FD == INVALID_SOCKET) - return; - - closesocket(m_FD); - m_FD = INVALID_SOCKET; + if (m_FD != INVALID_SOCKET) { + closesocket(m_FD); + m_FD = INVALID_SOCKET; + } } Stream::Close(); } +/** + * Shuts down the socket. + */ +void Socket::Close(void) +{ + SetWriteEOF(true); +} + + /** * Retrieves the last error that occured for the socket. * @@ -275,7 +283,7 @@ void Socket::ReadThreadProc(void) } catch (...) { SetException(boost::current_exception()); - Close(); + CloseInternal(); break; } @@ -330,7 +338,7 @@ void Socket::WriteThreadProc(void) } catch (...) { SetException(boost::current_exception()); - Close(); + CloseInternal(); break; } @@ -392,13 +400,9 @@ size_t Socket::Read(void *buffer, size_t size) throw new logic_error("Socket does not support Read()."); } - if (m_RecvQueue->GetAvailableBytes() == 0) { + if (m_RecvQueue->GetAvailableBytes() == 0) CheckException(); - if (!IsConnected()) - SetEOF(true); - } - return m_RecvQueue->Read(buffer, size); } @@ -487,8 +491,12 @@ void Socket::HandleWritableClient(void) for (;;) { count = m_SendQueue->Peek(data, sizeof(data)); - if (count == 0) + if (count == 0) { + if (IsWriteEOF()) + CloseInternal(); + break; + } rc = send(GetFD(), data, count, 0); @@ -523,12 +531,15 @@ void Socket::HandleReadableClient(void) if (rc < 0) BOOST_THROW_EXCEPTION(SocketException("recv() failed", GetError())); - if (rc == 0) - SetEOF(true); + new_data = true; + + if (rc == 0) { + SetReadEOF(true); + + break; + } m_RecvQueue->Write(data, rc); - - new_data = true; } if (new_data) @@ -593,7 +604,7 @@ bool Socket::WantsToRead(void) const */ bool Socket::WantsToReadClient(void) const { - return !IsEOF(); + return !IsReadEOF(); } /** diff --git a/lib/base/socket.h b/lib/base/socket.h index d580bd7a9..e979ad1f4 100644 --- a/lib/base/socket.h +++ b/lib/base/socket.h @@ -82,6 +82,8 @@ private: static String GetAddressFromSockaddr(sockaddr *address, socklen_t len); + void CloseInternal(void); + FIFO::Ptr m_SendQueue; FIFO::Ptr m_RecvQueue; diff --git a/lib/base/stream.cpp b/lib/base/stream.cpp index 7a48da892..8b74a259c 100644 --- a/lib/base/stream.cpp +++ b/lib/base/stream.cpp @@ -22,7 +22,7 @@ using namespace icinga; Stream::Stream(void) - : m_Connected(false), m_EOF(false) + : m_Connected(false), m_ReadEOF(false), m_WriteEOF(false) { } Stream::~Stream(void) @@ -43,11 +43,21 @@ bool Stream::IsConnected(void) const /** * @threadsafety Always. */ -bool Stream::IsEOF(void) const +bool Stream::IsReadEOF(void) const { ObjectLock olock(this); - return m_EOF; + return m_ReadEOF; +} + +/** + * @threadsafety Always. + */ +bool Stream::IsWriteEOF(void) const +{ + ObjectLock olock(this); + + return m_WriteEOF; } /** @@ -55,26 +65,40 @@ bool Stream::IsEOF(void) const */ void Stream::SetConnected(bool connected) { + bool changed; + { ObjectLock olock(this); + changed = (m_Connected != connected); m_Connected = connected; } - if (connected) - OnConnected(GetSelf()); - else - OnClosed(GetSelf()); + if (changed) { + if (connected) + OnConnected(GetSelf()); + else + OnClosed(GetSelf()); + } } /** * @threadsafety Always. */ -void Stream::SetEOF(bool eof) +void Stream::SetReadEOF(bool eof) { - { - ObjectLock olock(this); - m_EOF = eof; - } + ObjectLock olock(this); + + m_ReadEOF = eof; +} + +/** + * @threadsafety Always. + */ +void Stream::SetWriteEOF(bool eof) +{ + ObjectLock olock(this); + + m_WriteEOF = eof; } /** @@ -127,7 +151,6 @@ void Stream::Close(void) { ObjectLock olock(this); - ASSERT(m_Running); m_Running = false; } @@ -136,20 +159,38 @@ void Stream::Close(void) bool Stream::ReadLine(String *line, size_t maxLength) { - char buffer[maxLength]; + char *buffer = new char[maxLength]; size_t rc = Peek(buffer, maxLength); + if (rc == 0) + return false; + for (size_t i = 0; i < rc; i++) { if (buffer[i] == '\n') { *line = String(buffer, &(buffer[i])); boost::algorithm::trim_right(*line); - Read(NULL, rc); + Read(NULL, i + 1); + + delete buffer; return true; } } + if (IsReadEOF()) { + *line = String(buffer, buffer + rc); + boost::algorithm::trim_right(*line); + + Read(NULL, rc); + + delete buffer; + + return true; + } + + delete buffer; + return false; } diff --git a/lib/base/stream.h b/lib/base/stream.h index 10eb647d8..6e3ea92ab 100644 --- a/lib/base/stream.h +++ b/lib/base/stream.h @@ -81,7 +81,8 @@ public: virtual void Close(void); bool IsConnected(void) const; - bool IsEOF(void) const; + bool IsReadEOF(void) const; + bool IsWriteEOF(void) const; bool ReadLine(String *line, size_t maxLength = 4096); @@ -94,14 +95,16 @@ public: protected: void SetConnected(bool connected); - void SetEOF(bool eof); + void SetReadEOF(bool eof); + void SetWriteEOF(bool eof); void SetException(boost::exception_ptr exception); private: bool m_Running; bool m_Connected; - bool m_EOF; + bool m_ReadEOF; + bool m_WriteEOF; boost::exception_ptr m_Exception; };