mirror of https://github.com/Icinga/icinga2.git
Refactored the socket classes.
This commit is contained in:
parent
482742f00e
commit
321d66023f
|
@ -4,11 +4,11 @@ pkglib_LTLIBRARIES = \
|
||||||
compatido.la
|
compatido.la
|
||||||
|
|
||||||
compatido_la_SOURCES = \
|
compatido_la_SOURCES = \
|
||||||
i2-compatido.h \
|
|
||||||
idosocket.cpp \
|
|
||||||
idosocket.h \
|
|
||||||
compatidocomponent.cpp \
|
compatidocomponent.cpp \
|
||||||
compatidocomponent.h
|
compatidocomponent.h \
|
||||||
|
i2-compatido.h \
|
||||||
|
idoconnection.cpp \
|
||||||
|
idoconnection.h
|
||||||
|
|
||||||
compatido_la_CPPFLAGS = \
|
compatido_la_CPPFLAGS = \
|
||||||
$(BOOST_CPPFLAGS) \
|
$(BOOST_CPPFLAGS) \
|
||||||
|
|
|
@ -151,12 +151,12 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="compatidocomponent.cpp" />
|
<ClCompile Include="compatidocomponent.cpp" />
|
||||||
<ClCompile Include="idosocket.cpp" />
|
<ClCompile Include="idoconnection.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="compatidocomponent.h" />
|
<ClInclude Include="compatidocomponent.h" />
|
||||||
<ClInclude Include="i2-compatido.h" />
|
<ClInclude Include="i2-compatido.h" />
|
||||||
<ClInclude Include="idosocket.h" />
|
<ClInclude Include="idoconnection.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<ClCompile Include="compatidocomponent.cpp">
|
<ClCompile Include="compatidocomponent.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="idosocket.cpp">
|
<ClCompile Include="idoconnection.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -25,8 +25,8 @@
|
||||||
<ClInclude Include="i2-compatido.h">
|
<ClInclude Include="i2-compatido.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="idosocket.h">
|
<ClInclude Include="idoconnection.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -38,13 +38,13 @@ const int CompatIdoComponent::DefaultReconnectInterval = 15;
|
||||||
String CompatIdoComponent::GetSocketAddress(void) const
|
String CompatIdoComponent::GetSocketAddress(void) const
|
||||||
{
|
{
|
||||||
Value address = GetConfig()->Get("socket_address");
|
Value address = GetConfig()->Get("socket_address");
|
||||||
if(address.IsEmpty())
|
|
||||||
|
if (address.IsEmpty())
|
||||||
return DefaultSocketAddress;
|
return DefaultSocketAddress;
|
||||||
else
|
else
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the socket port from the config
|
* Reads the socket port from the config
|
||||||
* @returns port The config option, or static default
|
* @returns port The config option, or static default
|
||||||
|
@ -52,7 +52,8 @@ String CompatIdoComponent::GetSocketAddress(void) const
|
||||||
String CompatIdoComponent::GetSocketPort(void) const
|
String CompatIdoComponent::GetSocketPort(void) const
|
||||||
{
|
{
|
||||||
Value port = GetConfig()->Get("socket_port");
|
Value port = GetConfig()->Get("socket_port");
|
||||||
if(port.IsEmpty())
|
|
||||||
|
if (port.IsEmpty())
|
||||||
return DefaultSocketPort;
|
return DefaultSocketPort;
|
||||||
else
|
else
|
||||||
return port;
|
return port;
|
||||||
|
@ -65,7 +66,8 @@ String CompatIdoComponent::GetSocketPort(void) const
|
||||||
String CompatIdoComponent::GetInstanceName(void) const
|
String CompatIdoComponent::GetInstanceName(void) const
|
||||||
{
|
{
|
||||||
Value instance = GetConfig()->Get("instance_name");
|
Value instance = GetConfig()->Get("instance_name");
|
||||||
if(instance.IsEmpty())
|
|
||||||
|
if (instance.IsEmpty())
|
||||||
return DefaultInstanceName;
|
return DefaultInstanceName;
|
||||||
else
|
else
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -75,34 +77,16 @@ String CompatIdoComponent::GetInstanceName(void) const
|
||||||
* Reads the reconnect interval from the config
|
* Reads the reconnect interval from the config
|
||||||
* @returns reconnect_interval The config option, or static default
|
* @returns reconnect_interval The config option, or static default
|
||||||
*/
|
*/
|
||||||
int CompatIdoComponent::GetReconnectInterval(void) const
|
double CompatIdoComponent::GetReconnectInterval(void) const
|
||||||
{
|
{
|
||||||
Value interval = GetConfig()->Get("reconnect_interval");
|
Value interval = GetConfig()->Get("reconnect_interval");
|
||||||
if(interval.IsEmpty())
|
|
||||||
return DefaultReconnectInterval;
|
|
||||||
else
|
|
||||||
return interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (interval.IsEmpty())
|
||||||
* Sets config dump in progress state
|
return DefaultReconnectInterval;
|
||||||
*/
|
else
|
||||||
void CompatIdoComponent::SetConfigDumpInProgress(bool state)
|
return interval;
|
||||||
{
|
|
||||||
m_ConfigDumpInProgress = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get state of config in progress
|
|
||||||
*
|
|
||||||
* @returns state bis config dump in progress.
|
|
||||||
*/
|
|
||||||
bool CompatIdoComponent::GetConfigDumpInProgress(void)
|
|
||||||
{
|
|
||||||
return m_ConfigDumpInProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the component.
|
* Starts the component.
|
||||||
*/
|
*/
|
||||||
|
@ -111,7 +95,7 @@ void CompatIdoComponent::Start(void)
|
||||||
const int StatusTimerInterval = 60;
|
const int StatusTimerInterval = 60;
|
||||||
const int ConfigTimerInterval = 3600;
|
const int ConfigTimerInterval = 3600;
|
||||||
const int ProgramStatusTimerInterval = 15;
|
const int ProgramStatusTimerInterval = 15;
|
||||||
const int ReconnectTimerInterval = GetReconnectInterval();
|
const double ReconnectTimerInterval = GetReconnectInterval();
|
||||||
|
|
||||||
/* FIXME - make this a config option when unix sockets are realdy */
|
/* FIXME - make this a config option when unix sockets are realdy */
|
||||||
|
|
||||||
|
@ -125,12 +109,7 @@ void CompatIdoComponent::Start(void)
|
||||||
/*
|
/*
|
||||||
* open ido socket once
|
* open ido socket once
|
||||||
*/
|
*/
|
||||||
OpenIdoSocket(IdoSocketType);
|
OpenIdoSocket();
|
||||||
|
|
||||||
/*
|
|
||||||
* tell ido2db that we just started
|
|
||||||
*/
|
|
||||||
SendStartProcess();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ddump the config later (can't do that within start of the component)
|
* ddump the config later (can't do that within start of the component)
|
||||||
|
@ -171,7 +150,6 @@ void CompatIdoComponent::Start(void)
|
||||||
m_ReconnectTimer->Start();
|
m_ReconnectTimer->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the component.
|
* Stops the component.
|
||||||
*/
|
*/
|
||||||
|
@ -180,24 +158,58 @@ void CompatIdoComponent::Stop(void)
|
||||||
CloseIdoSocket();
|
CloseIdoSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the ido socket, and sends hello to ido2db
|
* Opens the ido socket, and sends hello to ido2db
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::OpenIdoSocket(bool sockettype)
|
void CompatIdoComponent::OpenIdoSocket(void)
|
||||||
{
|
{
|
||||||
OpenSink(GetSocketAddress(), GetSocketPort());
|
TcpSocket::Ptr socket = boost::make_shared<TcpSocket>();
|
||||||
SendHello(GetInstanceName(), sockettype);
|
socket->Connect(GetSocketAddress(), GetSocketPort());
|
||||||
|
socket->Start();
|
||||||
|
|
||||||
m_IdoSocket->SetSocketType(sockettype);
|
m_IdoConnection = boost::make_shared<IdoConnection>(socket);
|
||||||
/*
|
m_IdoConnection->OnClosed.connect(boost::bind(&CompatIdoComponent::SocketDisconnectHandler, this));
|
||||||
* if we're connected, do not reconnecte
|
|
||||||
*/
|
/* FIXME */
|
||||||
if(m_IdoSocket->IsConnected()) {
|
#define COMPATIDO_PROTOCOL 2
|
||||||
m_IdoSocket->SetReconnect(false);
|
#define COMPATIDO_NAME "ICINGA2 COMPATIDO"
|
||||||
} else {
|
#define COMPATIDO_RELEASE_VERSION "2.0"
|
||||||
m_IdoSocket->SetReconnect(true);
|
|
||||||
}
|
/* connection is always TCP */
|
||||||
|
/* connecttype is always initial */
|
||||||
|
stringstream msgHello;
|
||||||
|
msgHello << "\n\n"
|
||||||
|
<< "HELLO" << "\n"
|
||||||
|
<< "PROTOCOL" << ": " << COMPATIDO_PROTOCOL<< "\n"
|
||||||
|
<< "AGENT" << ": " << COMPATIDO_NAME << "\n"
|
||||||
|
<< "AGENTVERSION" << ": " << VERSION << "\n"
|
||||||
|
<< "STARTTIME" << ": " << static_cast<int>(Utility::GetTime()) << "\n"
|
||||||
|
<< "DISPOSITION" << ": " << "REALTIME" << "\n"
|
||||||
|
<< "CONNECTION" << ": " << "TCPSOCKET" << "\n"
|
||||||
|
<< "INSTANCENAME" << ": " << GetInstanceName() << "\n"
|
||||||
|
<< "STARTDATADUMP"
|
||||||
|
<< "\n\n";
|
||||||
|
|
||||||
|
m_IdoConnection->SendMessage(msgHello.str());
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
#define PROGRAM_MODIFICATION_DATE "10-17-2012"
|
||||||
|
#define PROGRAM_RELEASE_VERSION "2.0"
|
||||||
|
|
||||||
|
stringstream msgProcessData;
|
||||||
|
msgProcessData << "\n"
|
||||||
|
<< 200 << "\n" /* processdata */
|
||||||
|
<< 1 << "=" << 104 << "\n" /* type = pprocess prelaunch */
|
||||||
|
<< 2 << "=" << "" << "\n" /* flags */
|
||||||
|
<< 3 << "=" << "" << "\n" /* attributes */
|
||||||
|
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
||||||
|
<< 105 << "=" << "Icinga2" << "\n" /* progranname */
|
||||||
|
<< 107 << "=" << PROGRAM_RELEASE_VERSION << "\n" /* programversion */
|
||||||
|
<< 104 << "=" << PROGRAM_MODIFICATION_DATE << "\n" /* programdata */
|
||||||
|
<< 102 << "=" << Utility::GetPid() << "\n" /* process id */
|
||||||
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
|
m_IdoConnection->SendMessage(msgProcessData.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -205,10 +217,20 @@ void CompatIdoComponent::OpenIdoSocket(bool sockettype)
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::CloseIdoSocket(void)
|
void CompatIdoComponent::CloseIdoSocket(void)
|
||||||
{
|
{
|
||||||
GoodByeSink();
|
stringstream message;
|
||||||
CloseSink();
|
message << "\n"
|
||||||
|
<< 1000 << "\n" /* enddatadump */
|
||||||
|
<< "ENDTIME" << ": " << static_cast<int>(Utility::GetTime()) << "\n" /* endtime */
|
||||||
|
<< "GOODBYE" /* goodbye */
|
||||||
|
<< "\n\n";
|
||||||
|
|
||||||
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompatIdoComponent::SocketDisconnectHandler(void)
|
||||||
|
{
|
||||||
|
m_IdoConnection.reset();
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
* subscribe to all status updates and checkresults and dump them
|
* subscribe to all status updates and checkresults and dump them
|
||||||
|
@ -225,7 +247,7 @@ void CompatIdoComponent::StatusTimerHandler(void)
|
||||||
Logger::Write(LogInformation, "compatido", "Writing compat ido status information");
|
Logger::Write(LogInformation, "compatido", "Writing compat ido status information");
|
||||||
|
|
||||||
DumpStatusData();
|
DumpStatusData();
|
||||||
DumpProgramStatusData();
|
DumpProgramStatusData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,10 +257,7 @@ void CompatIdoComponent::ConfigTimerHandler(void)
|
||||||
{
|
{
|
||||||
Logger::Write(LogInformation, "compatido", "Writing compat ido config information");
|
Logger::Write(LogInformation, "compatido", "Writing compat ido config information");
|
||||||
|
|
||||||
/* protect the dump of status update messages */
|
|
||||||
SetConfigDumpInProgress(true);
|
|
||||||
DumpConfigObjects();
|
DumpConfigObjects();
|
||||||
SetConfigDumpInProgress(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,13 +265,9 @@ void CompatIdoComponent::ConfigTimerHandler(void)
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::ProgramStatusTimerHandler(void)
|
void CompatIdoComponent::ProgramStatusTimerHandler(void)
|
||||||
{
|
{
|
||||||
/* do not dump any data if config dump is still in progress */
|
Logger::Write(LogInformation, "compatido", "Writing compat ido program status information");
|
||||||
if(GetConfigDumpInProgress())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Logger::Write(LogInformation, "compatido", "Writing compat ido program status information");
|
DumpProgramStatusData();
|
||||||
|
|
||||||
DumpProgramStatusData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,153 +275,11 @@ void CompatIdoComponent::ProgramStatusTimerHandler(void)
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::ReconnectTimerHandler(void)
|
void CompatIdoComponent::ReconnectTimerHandler(void)
|
||||||
{
|
{
|
||||||
Logger::Write(LogDebug, "compatido", "Checking if ido socket requires reconnect");
|
Logger::Write(LogDebug, "compatido", "Checking if ido socket requires reconnect");
|
||||||
|
|
||||||
if(m_IdoSocket->GetReconnect()) {
|
|
||||||
|
|
||||||
/* check if we aren't already connected */
|
|
||||||
if(m_IdoSocket->IsConnected()) {
|
|
||||||
Logger::Write(LogDebug, "compatido", "Already connected to ido socket ... no reconnect necessary");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!m_IdoConnection)
|
||||||
/* socket was disconnected, recconnect */
|
/* socket was disconnected, recconnect */
|
||||||
OpenIdoSocket(m_IdoSocket->GetSocketType());
|
OpenIdoSocket();
|
||||||
|
|
||||||
if(m_IdoSocket->IsConnected()) {
|
|
||||||
Logger::Write(LogInformation, "compatido", "Successfully reconnected to ido socket");
|
|
||||||
} else {
|
|
||||||
stringstream message;
|
|
||||||
message << "Unable to reconnect to ido socket. Trying again in " << GetReconnectInterval() << " sec";
|
|
||||||
Logger::Write(LogWarning, "compatido", message.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* opens a tcp connection to the ido socket
|
|
||||||
*/
|
|
||||||
void CompatIdoComponent::OpenSink(String node, String service)
|
|
||||||
{
|
|
||||||
m_IdoSocket = boost::make_shared<IdoSocket>(RoleOutbound);
|
|
||||||
m_IdoSocket->Connect(node, service);
|
|
||||||
m_IdoSocket->Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sends hello msg to ido2b
|
|
||||||
*/
|
|
||||||
void CompatIdoComponent::SendHello(String instancename, bool sockettype)
|
|
||||||
{
|
|
||||||
/* FIXME */
|
|
||||||
#define COMPATIDO_PROTOCOL 2
|
|
||||||
#define COMPATIDO_NAME "ICINGA2 COMPATIDO"
|
|
||||||
#define COMPATIDO_RELEASE_VERSION "2.0"
|
|
||||||
|
|
||||||
String connection;
|
|
||||||
if(sockettype)
|
|
||||||
connection = "TCPSOCKET";
|
|
||||||
else
|
|
||||||
connection = "UNIXSOCKET";
|
|
||||||
|
|
||||||
/* connection is always TCP */
|
|
||||||
/* connecttype is always initial */
|
|
||||||
stringstream message;
|
|
||||||
message << "\n\n"
|
|
||||||
<< "HELLO" << "\n"
|
|
||||||
<< "PROTOCOL" << ": " << COMPATIDO_PROTOCOL<< "\n"
|
|
||||||
<< "AGENT" << ": " << COMPATIDO_NAME << "\n"
|
|
||||||
<< "AGENTVERSION" << ": " << VERSION << "\n"
|
|
||||||
<< "STARTTIME" << ": " << static_cast<int>(Utility::GetTime()) << "\n"
|
|
||||||
<< "DISPOSITION" << ": " << "REALTIME" << "\n"
|
|
||||||
<< "CONNECTION" << ": " << connection << "\n"
|
|
||||||
<< "INSTANCENAME" << ": " << instancename << "\n"
|
|
||||||
<< "STARTDATADUMP"
|
|
||||||
<< "\n\n";
|
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sends goodbye msg to ido
|
|
||||||
*/
|
|
||||||
void CompatIdoComponent::GoodByeSink(void)
|
|
||||||
{
|
|
||||||
stringstream message;
|
|
||||||
message << "\n"
|
|
||||||
<< 1000 << "\n" /* enddatadump */
|
|
||||||
<< "ENDTIME" << ": " << static_cast<int>(Utility::GetTime()) << "\n" /* endtime */
|
|
||||||
<< "GOODBYE" /* goodbye */
|
|
||||||
<< "\n\n";
|
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* closes ido socket
|
|
||||||
*/
|
|
||||||
void CompatIdoComponent::CloseSink(void)
|
|
||||||
{
|
|
||||||
m_IdoSocket->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tell ido2db that we are starting up (must be called before config dump)
|
|
||||||
*/
|
|
||||||
void CompatIdoComponent::SendStartProcess(void)
|
|
||||||
{
|
|
||||||
/* TODO */
|
|
||||||
#define PROGRAM_MODIFICATION_DATE "10-17-2012"
|
|
||||||
#define PROGRAM_RELEASE_VERSION "2.0"
|
|
||||||
|
|
||||||
stringstream message;
|
|
||||||
message << "\n"
|
|
||||||
<< 200 << "\n" /* processdata */
|
|
||||||
<< 1 << "=" << 104 << "\n" /* type = pprocess prelaunch */
|
|
||||||
<< 2 << "=" << "" << "\n" /* flags */
|
|
||||||
<< 3 << "=" << "" << "\n" /* attributes */
|
|
||||||
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
|
||||||
<< 105 << "=" << "Icinga2" << "\n" /* progranname */
|
|
||||||
<< 107 << "=" << PROGRAM_RELEASE_VERSION << "\n" /* programversion */
|
|
||||||
<< 104 << "=" << PROGRAM_MODIFICATION_DATE << "\n" /* programdata */
|
|
||||||
<< 102 << "=" << Utility::GetPid() << "\n" /* process id */
|
|
||||||
<< 999 << "\n\n"; /* enddata */
|
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sends config dump start signal to ido
|
|
||||||
*/
|
|
||||||
void CompatIdoComponent::StartConfigDump(void)
|
|
||||||
{
|
|
||||||
/* configtype =1 (original), =2 (retained == default) */
|
|
||||||
stringstream message;
|
|
||||||
message << "\n\n"
|
|
||||||
<< 900 << ":" << "\n" /* startconfigdump */
|
|
||||||
<< 245 << "=" << "RETAINED" << "\n" /* configdumptype */
|
|
||||||
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
|
||||||
<< 999 /* enddata */
|
|
||||||
<< "\n\n";
|
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sends config dump end signal to ido
|
|
||||||
*/
|
|
||||||
void CompatIdoComponent::EndConfigDump(void)
|
|
||||||
{
|
|
||||||
stringstream message;
|
|
||||||
message << "\n\n"
|
|
||||||
<< 901 << ":" << "\n" /* endconfigdump */
|
|
||||||
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
|
||||||
<< 999 /* enddata */
|
|
||||||
<< "\n\n";
|
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -419,9 +292,9 @@ void CompatIdoComponent::EnableHostObject(const Host::Ptr& host)
|
||||||
<< 500 << ":" << "\n" /* enableobject */
|
<< 500 << ":" << "\n" /* enableobject */
|
||||||
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
||||||
<< 53 << "=" << host->GetName() << "\n" /* host */
|
<< 53 << "=" << host->GetName() << "\n" /* host */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -429,15 +302,15 @@ void CompatIdoComponent::EnableHostObject(const Host::Ptr& host)
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::EnableServiceObject(const Service::Ptr& service)
|
void CompatIdoComponent::EnableServiceObject(const Service::Ptr& service)
|
||||||
{
|
{
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
<< 500 << ":" << "\n" /* enableobject */
|
<< 500 << ":" << "\n" /* enableobject */
|
||||||
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
||||||
<< 53 << "=" << service->GetHost()->GetName() << "\n" /* host */
|
<< 53 << "=" << service->GetHost()->GetName() << "\n" /* host */
|
||||||
<< 114 << "=" << service->GetAlias() << "\n" /* service */
|
<< 114 << "=" << service->GetAlias() << "\n" /* service */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -445,14 +318,14 @@ void CompatIdoComponent::EnableServiceObject(const Service::Ptr& service)
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::DisableHostObject(const Host::Ptr& host)
|
void CompatIdoComponent::DisableHostObject(const Host::Ptr& host)
|
||||||
{
|
{
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
<< 501 << ":" << "\n" /* disableobject */
|
<< 501 << ":" << "\n" /* disableobject */
|
||||||
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
||||||
<< 53 << "=" << host->GetName() << "\n" /* host */
|
<< 53 << "=" << host->GetName() << "\n" /* host */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -460,20 +333,17 @@ void CompatIdoComponent::DisableHostObject(const Host::Ptr& host)
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::DisableServiceObject(const Service::Ptr& service)
|
void CompatIdoComponent::DisableServiceObject(const Service::Ptr& service)
|
||||||
{
|
{
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
<< 501 << ":" << "\n" /* disableobject */
|
<< 501 << ":" << "\n" /* disableobject */
|
||||||
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
||||||
<< 53 << "=" << service->GetHost()->GetName() << "\n" /* host */
|
<< 53 << "=" << service->GetHost()->GetName() << "\n" /* host */
|
||||||
<< 114 << "=" << service->GetAlias() << "\n" /* service */
|
<< 114 << "=" << service->GetAlias() << "\n" /* service */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dump host config to ido
|
* dump host config to ido
|
||||||
*
|
*
|
||||||
|
@ -483,7 +353,7 @@ void CompatIdoComponent::DumpHostObject(const Host::Ptr& host)
|
||||||
{
|
{
|
||||||
stringstream log;
|
stringstream log;
|
||||||
log << "Dumping Host Config: " << host->GetName();
|
log << "Dumping Host Config: " << host->GetName();
|
||||||
Logger::Write(LogDebug, "compatido", log.str());
|
Logger::Write(LogDebug, "compatido", log.str());
|
||||||
|
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
|
@ -550,10 +420,10 @@ void CompatIdoComponent::DumpHostObject(const Host::Ptr& host)
|
||||||
<< 200 << "=" << "i2_parent" << "\n" /* parenthost */
|
<< 200 << "=" << "i2_parent" << "\n" /* parenthost */
|
||||||
<< 130 << "=" << "i2_contactgroup" << "\n" /* contactgroup */
|
<< 130 << "=" << "i2_contactgroup" << "\n" /* contactgroup */
|
||||||
<< 264 << "=" << "i2_contact" << "\n" /* contact */
|
<< 264 << "=" << "i2_contact" << "\n" /* contact */
|
||||||
<< 262 << "=" << "i2_customvar" << ":" << 1 << ":" << "i2_custom_var_mod" << "\n" /* customvariable */
|
<< 262 << "=" << "i2_customvar" << ":" << 1 << ":" << "i2_custom_var_mod" << "\n" /* customvariable */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -563,21 +433,20 @@ void CompatIdoComponent::DumpHostObject(const Host::Ptr& host)
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::DumpHostStatus(const Host::Ptr& host)
|
void CompatIdoComponent::DumpHostStatus(const Host::Ptr& host)
|
||||||
{
|
{
|
||||||
|
|
||||||
stringstream log;
|
stringstream log;
|
||||||
log << "Dumping Host Status: " << host->GetName();
|
log << "Dumping Host Status: " << host->GetName();
|
||||||
Logger::Write(LogDebug, "compatido", log.str());
|
Logger::Write(LogDebug, "compatido", log.str());
|
||||||
|
|
||||||
int state;
|
int state;
|
||||||
if (!host->IsReachable())
|
if (!host->IsReachable())
|
||||||
state = 2; /* unreachable */
|
state = 2; /* unreachable */
|
||||||
else if (!host->IsUp())
|
else if (!host->IsUp())
|
||||||
state = 1; /* down */
|
state = 1; /* down */
|
||||||
else
|
else
|
||||||
state = 0; /* up */
|
state = 0; /* up */
|
||||||
|
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
<< 212 << ":" << "\n" /* hoststatusdata */
|
<< 212 << ":" << "\n" /* hoststatusdata */
|
||||||
<< 1 << "=" << "" << "\n" /* type */
|
<< 1 << "=" << "" << "\n" /* type */
|
||||||
<< 2 << "=" << "" << "\n" /* flags */
|
<< 2 << "=" << "" << "\n" /* flags */
|
||||||
|
@ -631,7 +500,7 @@ void CompatIdoComponent::DumpHostStatus(const Host::Ptr& host)
|
||||||
<< 262 << "=" << "i2_customvar" << ":" << "1" << ":" << "i2_customvarmod" << "\n" /* customvariable */
|
<< 262 << "=" << "i2_customvar" << ":" << "1" << ":" << "i2_customvarmod" << "\n" /* customvariable */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -643,7 +512,7 @@ void CompatIdoComponent::DumpServiceObject(const Service::Ptr& service)
|
||||||
{
|
{
|
||||||
stringstream log;
|
stringstream log;
|
||||||
log << "Dumping Service Config: " << service->GetHost()->GetName() << "->" << service->GetAlias();
|
log << "Dumping Service Config: " << service->GetHost()->GetName() << "->" << service->GetAlias();
|
||||||
Logger::Write(LogDebug, "compatido", log.str());
|
Logger::Write(LogDebug, "compatido", log.str());
|
||||||
|
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
|
@ -705,7 +574,7 @@ void CompatIdoComponent::DumpServiceObject(const Service::Ptr& service)
|
||||||
<< 262 << "=" << "i2_customvar" << ":" << 1 << ":" << "i2_custom_var_mod" << "\n" /* customvariable */
|
<< 262 << "=" << "i2_customvar" << ":" << 1 << ":" << "i2_custom_var_mod" << "\n" /* customvariable */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -717,35 +586,35 @@ void CompatIdoComponent::DumpServiceStatus(const Service::Ptr& service)
|
||||||
{
|
{
|
||||||
stringstream log;
|
stringstream log;
|
||||||
log << "Dumping Service Status: " << service->GetHost()->GetName() << "->" << service->GetAlias();
|
log << "Dumping Service Status: " << service->GetHost()->GetName() << "->" << service->GetAlias();
|
||||||
Logger::Write(LogDebug, "compatido", log.str());
|
Logger::Write(LogDebug, "compatido", log.str());
|
||||||
|
|
||||||
String output;
|
String output;
|
||||||
String perfdata;
|
String perfdata;
|
||||||
double schedule_start = -1, schedule_end = -1;
|
double schedule_start = -1, schedule_end = -1;
|
||||||
double execution_start = -1, execution_end = -1;
|
double execution_start = -1, execution_end = -1;
|
||||||
|
|
||||||
Dictionary::Ptr cr = service->GetLastCheckResult();
|
Dictionary::Ptr cr = service->GetLastCheckResult();
|
||||||
|
|
||||||
if (cr) {
|
if (cr) {
|
||||||
output = cr->Get("output");
|
output = cr->Get("output");
|
||||||
schedule_start = cr->Get("schedule_start");
|
schedule_start = cr->Get("schedule_start");
|
||||||
schedule_end = cr->Get("schedule_end");
|
schedule_end = cr->Get("schedule_end");
|
||||||
execution_start = cr->Get("execution_start");
|
execution_start = cr->Get("execution_start");
|
||||||
execution_end = cr->Get("execution_end");
|
execution_end = cr->Get("execution_end");
|
||||||
perfdata = cr->Get("performance_data_raw");
|
perfdata = cr->Get("performance_data_raw");
|
||||||
}
|
}
|
||||||
|
|
||||||
double execution_time = (execution_end - execution_start);
|
double execution_time = (execution_end - execution_start);
|
||||||
double latency = (schedule_end - schedule_start) - execution_time;
|
double latency = (schedule_end - schedule_start) - execution_time;
|
||||||
|
|
||||||
int state = service->GetState();
|
int state = service->GetState();
|
||||||
|
|
||||||
if (state > StateUnknown)
|
if (state > StateUnknown)
|
||||||
state = StateUnknown;
|
state = StateUnknown;
|
||||||
|
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
<< 213 << ":" << "\n" /* servicestatusdata */
|
<< 213 << ":" << "\n" /* servicestatusdata */
|
||||||
<< 1 << "=" << "" << "\n" /* type */
|
<< 1 << "=" << "" << "\n" /* type */
|
||||||
<< 2 << "=" << "" << "\n" /* flags */
|
<< 2 << "=" << "" << "\n" /* flags */
|
||||||
<< 3 << "=" << "" << "\n" /* attributes */
|
<< 3 << "=" << "" << "\n" /* attributes */
|
||||||
|
@ -800,7 +669,7 @@ void CompatIdoComponent::DumpServiceStatus(const Service::Ptr& service)
|
||||||
<< 262 << "=" << "i2_customvar" << ":" << "1" << ":" << "i2_customvarmod" << "\n" /* customvariable */
|
<< 262 << "=" << "i2_customvar" << ":" << "1" << ":" << "i2_customvarmod" << "\n" /* customvariable */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -811,9 +680,9 @@ void CompatIdoComponent::DumpProgramStatusData(void)
|
||||||
{
|
{
|
||||||
double start_time = IcingaApplication::GetInstance()->GetStartTime();
|
double start_time = IcingaApplication::GetInstance()->GetStartTime();
|
||||||
|
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
<< 211 << ":" << "\n" /* programstatusdata */
|
<< 211 << ":" << "\n" /* programstatusdata */
|
||||||
<< 1 << "=" << "" << "\n" /* type */
|
<< 1 << "=" << "" << "\n" /* type */
|
||||||
<< 2 << "=" << "" << "\n" /* flags */
|
<< 2 << "=" << "" << "\n" /* flags */
|
||||||
<< 3 << "=" << "" << "\n" /* attributes */
|
<< 3 << "=" << "" << "\n" /* attributes */
|
||||||
|
@ -839,9 +708,9 @@ void CompatIdoComponent::DumpProgramStatusData(void)
|
||||||
<< 49 << "=" << "" << "\n" /* globalhosteventhandler */
|
<< 49 << "=" << "" << "\n" /* globalhosteventhandler */
|
||||||
<< 50 << "=" << "" << "\n" /* globalserviceeventhandler */
|
<< 50 << "=" << "" << "\n" /* globalserviceeventhandler */
|
||||||
<< 270 << "=" << static_cast<int>(Utility::GetTime()) << "\n" /* disablednotificationsexpiretime - supported in 1.8 XXX */
|
<< 270 << "=" << static_cast<int>(Utility::GetTime()) << "\n" /* disablednotificationsexpiretime - supported in 1.8 XXX */
|
||||||
<< 999 << "\n\n"; /* enddata */
|
<< 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -856,7 +725,16 @@ void CompatIdoComponent::DumpConfigObjects(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* tell ido2db that we start now */
|
/* tell ido2db that we start now */
|
||||||
StartConfigDump();
|
/* configtype =1 (original), =2 (retained == default) */
|
||||||
|
stringstream msgStartConfigDump;
|
||||||
|
msgStartConfigDump << "\n\n"
|
||||||
|
<< 900 << ":" << "\n" /* startconfigdump */
|
||||||
|
<< 245 << "=" << "RETAINED" << "\n" /* configdumptype */
|
||||||
|
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
||||||
|
<< 999 /* enddata */
|
||||||
|
<< "\n\n";
|
||||||
|
|
||||||
|
m_IdoConnection->SendMessage(msgStartConfigDump.str());
|
||||||
|
|
||||||
/* hosts and hostgroups */
|
/* hosts and hostgroups */
|
||||||
map<String, vector<String> > hostgroups;
|
map<String, vector<String> > hostgroups;
|
||||||
|
@ -885,7 +763,7 @@ void CompatIdoComponent::DumpConfigObjects(void)
|
||||||
const String& name = hgt.first;
|
const String& name = hgt.first;
|
||||||
const vector<String>& hosts = hgt.second;
|
const vector<String>& hosts = hgt.second;
|
||||||
|
|
||||||
if(HostGroup::Exists(name)) {
|
if (HostGroup::Exists(name)) {
|
||||||
HostGroup::Ptr hg = HostGroup::GetByName(name);
|
HostGroup::Ptr hg = HostGroup::GetByName(name);
|
||||||
|
|
||||||
/* dump the hostgroup and its attributes/members to ido */
|
/* dump the hostgroup and its attributes/members to ido */
|
||||||
|
@ -896,11 +774,11 @@ void CompatIdoComponent::DumpConfigObjects(void)
|
||||||
<< 172 << "=" << name << "\n" /* hostgroupname */
|
<< 172 << "=" << name << "\n" /* hostgroupname */
|
||||||
<< 170 << "=" << hg->GetAlias() << "\n"; /* hostgroupalias */
|
<< 170 << "=" << hg->GetAlias() << "\n"; /* hostgroupalias */
|
||||||
|
|
||||||
CreateMessageList(message, hosts, 171); /* hostgroupmember */
|
SendMessageList(message, hosts, 171); /* hostgroupmember */
|
||||||
|
|
||||||
message << 999 << "\n\n"; /* enddata */
|
message << 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,12 +813,12 @@ void CompatIdoComponent::DumpConfigObjects(void)
|
||||||
ServiceGroup::Ptr sg = ServiceGroup::GetByName(name);
|
ServiceGroup::Ptr sg = ServiceGroup::GetByName(name);
|
||||||
|
|
||||||
/* dump the servicegroup and its attributes/members to ido */
|
/* dump the servicegroup and its attributes/members to ido */
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "\n"
|
message << "\n"
|
||||||
<< 403 << ":" << "\n" /* servicegroupdefinition */
|
<< 403 << ":" << "\n" /* servicegroupdefinition */
|
||||||
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
||||||
<< 220 << "=" << name << "\n" /* servicegroupname */
|
<< 220 << "=" << name << "\n" /* servicegroupname */
|
||||||
<< 218 << "=" << sg->GetAlias() << "\n"; /* servicegroupalias */
|
<< 218 << "=" << sg->GetAlias() << "\n"; /* servicegroupalias */
|
||||||
|
|
||||||
vector<String> sglist;
|
vector<String> sglist;
|
||||||
vector<Service::Ptr>::iterator vt;
|
vector<Service::Ptr>::iterator vt;
|
||||||
|
@ -950,16 +828,23 @@ void CompatIdoComponent::DumpConfigObjects(void)
|
||||||
sglist.push_back(service->GetAlias());
|
sglist.push_back(service->GetAlias());
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateMessageList(message, services, 219); /* servicegroupmember */
|
SendMessageList(message, services, 219); /* servicegroupmember */
|
||||||
|
|
||||||
message << 999 << "\n\n"; /* enddata */
|
message << 999 << "\n\n"; /* enddata */
|
||||||
|
|
||||||
m_IdoSocket->SendMessage(message.str());
|
m_IdoConnection->SendMessage(message.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tell ido2db that we ended dumping the config */
|
/* tell ido2db that we ended dumping the config */
|
||||||
EndConfigDump();
|
stringstream msgEndConfigDump;
|
||||||
|
msgEndConfigDump << "\n\n"
|
||||||
|
<< 901 << ":" << "\n" /* endconfigdump */
|
||||||
|
<< 4 << "=" << std::setprecision(17) << Utility::GetTime() << "\n" /* timestamp */
|
||||||
|
<< 999 /* enddata */
|
||||||
|
<< "\n\n";
|
||||||
|
|
||||||
|
m_IdoConnection->SendMessage(msgEndConfigDump.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -967,21 +852,21 @@ void CompatIdoComponent::DumpConfigObjects(void)
|
||||||
*/
|
*/
|
||||||
void CompatIdoComponent::DumpStatusData(void)
|
void CompatIdoComponent::DumpStatusData(void)
|
||||||
{
|
{
|
||||||
/* hosts */
|
/* hosts */
|
||||||
DynamicObject::Ptr object;
|
DynamicObject::Ptr object;
|
||||||
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
|
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
|
||||||
const Host::Ptr& host = static_pointer_cast<Host>(object);
|
const Host::Ptr& host = static_pointer_cast<Host>(object);
|
||||||
|
|
||||||
DumpHostStatus(host);
|
DumpHostStatus(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* services */
|
/* services */
|
||||||
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
|
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
|
||||||
Service::Ptr service = static_pointer_cast<Service>(object);
|
Service::Ptr service = static_pointer_cast<Service>(object);
|
||||||
|
|
||||||
DumpServiceStatus(service);
|
DumpServiceStatus(service);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,33 +38,24 @@ private:
|
||||||
Timer::Ptr m_ProgramStatusTimer;
|
Timer::Ptr m_ProgramStatusTimer;
|
||||||
Timer::Ptr m_ReconnectTimer;
|
Timer::Ptr m_ReconnectTimer;
|
||||||
|
|
||||||
IdoSocket::Ptr m_IdoSocket;
|
IdoConnection::Ptr m_IdoConnection;
|
||||||
|
|
||||||
bool m_ConfigDumpInProgress;
|
|
||||||
|
|
||||||
String GetSocketAddress(void) const;
|
String GetSocketAddress(void) const;
|
||||||
String GetSocketPort(void) const;
|
String GetSocketPort(void) const;
|
||||||
String GetInstanceName(void) const;
|
String GetInstanceName(void) const;
|
||||||
int GetReconnectInterval(void) const;
|
double GetReconnectInterval(void) const;
|
||||||
|
|
||||||
void SetConfigDumpInProgress(bool state);
|
void SocketDisconnectHandler(void);
|
||||||
bool GetConfigDumpInProgress(void);
|
|
||||||
|
|
||||||
void ConfigTimerHandler(void);
|
void ConfigTimerHandler(void);
|
||||||
void StatusTimerHandler(void);
|
void StatusTimerHandler(void);
|
||||||
void ProgramStatusTimerHandler(void);
|
void ProgramStatusTimerHandler(void);
|
||||||
void ReconnectTimerHandler(void);
|
void ReconnectTimerHandler(void);
|
||||||
|
|
||||||
void OpenIdoSocket(bool sockettype);
|
void OpenIdoSocket(void);
|
||||||
void CloseIdoSocket(void);
|
void CloseIdoSocket(void);
|
||||||
|
|
||||||
void OpenSink(String node, String service);
|
|
||||||
void SendHello(String instancename, bool sockettype);
|
|
||||||
void GoodByeSink(void);
|
|
||||||
void CloseSink(void);
|
|
||||||
void SendStartProcess(void);
|
void SendStartProcess(void);
|
||||||
void StartConfigDump(void);
|
|
||||||
void EndConfigDump(void);
|
|
||||||
|
|
||||||
void EnableHostObject(const Host::Ptr& host);
|
void EnableHostObject(const Host::Ptr& host);
|
||||||
void EnableServiceObject(const Service::Ptr& service);
|
void EnableServiceObject(const Service::Ptr& service);
|
||||||
|
@ -80,7 +71,7 @@ private:
|
||||||
void DumpProgramStatusData(void);
|
void DumpProgramStatusData(void);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void CreateMessageList(stringstream& msg, const T& list, int type)
|
void SendMessageList(stringstream& msg, const T& list, int type)
|
||||||
{
|
{
|
||||||
typename T::const_iterator it;
|
typename T::const_iterator it;
|
||||||
for (it = list.begin(); it != list.end(); it++) {
|
for (it = list.begin(); it != list.end(); it++) {
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
using std::stringstream;
|
using std::stringstream;
|
||||||
|
|
||||||
#include "idosocket.h"
|
#include "idoconnection.h"
|
||||||
#include "compatidocomponent.h"
|
#include "compatidocomponent.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "i2-compatido.h"
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the IdoSocket class.
|
||||||
|
*
|
||||||
|
* @param role The role of the underlying TCP client.
|
||||||
|
*/
|
||||||
|
IdoConnection::IdoConnection(const Stream::Ptr& stream)
|
||||||
|
: Connection(stream)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message to the ido socket
|
||||||
|
*
|
||||||
|
* @param message The message.
|
||||||
|
*/
|
||||||
|
void IdoConnection::SendMessage(const String& message)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* write our message to the send queue
|
||||||
|
* as we inherit all the functionality
|
||||||
|
* of the tcpclient class
|
||||||
|
*/
|
||||||
|
GetStream()->Write(message.CStr(), message.GetLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes inbound data.
|
||||||
|
* Currently not used, as we do not receive data from ido sockets
|
||||||
|
*/
|
||||||
|
void IdoConnection::ProcessData(void)
|
||||||
|
{
|
||||||
|
// Just ignore whatever data the other side is sending
|
||||||
|
GetStream()->Read(NULL, GetStream()->GetAvailableBytes());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -17,16 +17,31 @@
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "i2-remoting.h"
|
#ifndef IDOCONNECTION_H
|
||||||
|
#define IDOCONNECTION_H
|
||||||
|
|
||||||
using namespace icinga;
|
namespace icinga
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the JsonRpcServer class.
|
* An IDO socket client.
|
||||||
*
|
*
|
||||||
* @param sslContext SSL context that should be used for client connections.
|
* @ingroup compatido
|
||||||
*/
|
*/
|
||||||
JsonRpcServer::JsonRpcServer(shared_ptr<SSL_CTX> sslContext)
|
class IdoConnection : public Connection
|
||||||
{
|
{
|
||||||
SetClientFactory(boost::bind(&JsonRpcClientFactory, _1, RoleInbound, sslContext));
|
public:
|
||||||
|
typedef shared_ptr<IdoConnection> Ptr;
|
||||||
|
typedef weak_ptr<IdoConnection> WeakPtr;
|
||||||
|
|
||||||
|
IdoConnection(const Stream::Ptr& stream);
|
||||||
|
|
||||||
|
void SendMessage(const String& message);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void ProcessData(void);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* IDOCONNECTION_H */
|
|
@ -1,147 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* Icinga 2 *
|
|
||||||
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or *
|
|
||||||
* modify it under the terms of the GNU General Public License *
|
|
||||||
* as published by the Free Software Foundation; either version 2 *
|
|
||||||
* of the License, or (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program; if not, write to the Free Software Foundation *
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "i2-compatido.h"
|
|
||||||
|
|
||||||
using namespace icinga;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the IdoSocket class.
|
|
||||||
*
|
|
||||||
* @param role The role of the underlying TCP client.
|
|
||||||
*/
|
|
||||||
IdoSocket::IdoSocket(TcpClientRole role)
|
|
||||||
: TcpClient(role)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* we currently do not receive any data from the ido socket,
|
|
||||||
* this is just data output - so we do not need to bind
|
|
||||||
* a local instance of our datahandler in case of a new
|
|
||||||
* signal telling about new data
|
|
||||||
*/
|
|
||||||
OnDataAvailable.connect(boost::bind(&IdoSocket::DataAvailableHandler, this));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* what to do on disconnect
|
|
||||||
*/
|
|
||||||
OnClosed.connect(boost::bind(&IdoSocket::ClientClosedHandler, this));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* * Set the ido socket type
|
|
||||||
* *
|
|
||||||
* * @param type true=tcp, false=unix
|
|
||||||
* */
|
|
||||||
void IdoSocket::SetSocketType(bool type)
|
|
||||||
{
|
|
||||||
m_SocketType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* * Get the ido socket type
|
|
||||||
* *
|
|
||||||
* * @returns type true=tcp, false=unix
|
|
||||||
* */
|
|
||||||
bool IdoSocket::GetSocketType(void)
|
|
||||||
{
|
|
||||||
return m_SocketType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a message to the ido socket
|
|
||||||
*
|
|
||||||
* @param message The message.
|
|
||||||
*/
|
|
||||||
void IdoSocket::SendMessage(const String& message)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* write our message to the send queue
|
|
||||||
* as we inherit all the functionality
|
|
||||||
* of the tcpclient class
|
|
||||||
*/
|
|
||||||
Write(message.CStr(), message.GetLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles closed client connect
|
|
||||||
*/
|
|
||||||
void IdoSocket::ClientClosedHandler(void)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
CheckException();
|
|
||||||
} catch (const exception& ex) {
|
|
||||||
stringstream message;
|
|
||||||
message << "Error occured for ido socket: " << ex.what();
|
|
||||||
|
|
||||||
Logger::Write(LogWarning, "compatido", message.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::Write(LogWarning, "compatido", "Lost connection to ido socket");
|
|
||||||
|
|
||||||
SetReconnect(true);
|
|
||||||
|
|
||||||
OnDisconnected(GetSelf());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set reconnect vstate
|
|
||||||
*
|
|
||||||
* @aparam enable Enables the reconnect.
|
|
||||||
*/
|
|
||||||
void IdoSocket::SetReconnect(bool reconnect)
|
|
||||||
{
|
|
||||||
m_Reconnect = reconnect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get reconnect state
|
|
||||||
*
|
|
||||||
* @returns reconnect The reconnect variable
|
|
||||||
*/
|
|
||||||
bool IdoSocket::GetReconnect(void)
|
|
||||||
{
|
|
||||||
return m_Reconnect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes inbound data.
|
|
||||||
* Currently not used, as we do not receive data from ido sockets
|
|
||||||
*/
|
|
||||||
void IdoSocket::DataAvailableHandler(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory function for ido socket clients.
|
|
||||||
*
|
|
||||||
* @param fd The file descriptor.
|
|
||||||
* @param role The role of the underlying TCP client.
|
|
||||||
* @returns A new ido socket client.
|
|
||||||
*/
|
|
||||||
IdoSocket::Ptr icinga::IdoSocketFactory(SOCKET fd, TcpClientRole role)
|
|
||||||
{
|
|
||||||
IdoSocket::Ptr client = boost::make_shared<IdoSocket>(role);
|
|
||||||
client->SetFD(fd);
|
|
||||||
return client;
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* Icinga 2 *
|
|
||||||
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or *
|
|
||||||
* modify it under the terms of the GNU General Public License *
|
|
||||||
* as published by the Free Software Foundation; either version 2 *
|
|
||||||
* of the License, or (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program; if not, write to the Free Software Foundation *
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef IDOSOCKET_H
|
|
||||||
#define IDOSOCKET_H
|
|
||||||
|
|
||||||
#include "i2-compatido.h"
|
|
||||||
|
|
||||||
namespace icinga
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An IDO socket client.
|
|
||||||
*
|
|
||||||
* @ingroup compatido
|
|
||||||
*/
|
|
||||||
class IdoSocket : public TcpClient
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef shared_ptr<IdoSocket> Ptr;
|
|
||||||
typedef weak_ptr<IdoSocket> WeakPtr;
|
|
||||||
|
|
||||||
IdoSocket(TcpClientRole role);
|
|
||||||
|
|
||||||
void SetSocketType(bool);
|
|
||||||
bool GetSocketType(void);
|
|
||||||
|
|
||||||
void SendMessage(const String& message);
|
|
||||||
|
|
||||||
void SetReconnect(bool reconnect);
|
|
||||||
bool GetReconnect(void);
|
|
||||||
|
|
||||||
boost::signal<void (const IdoSocket::Ptr&, const stringstream&)> OnNewMessage;
|
|
||||||
|
|
||||||
boost::signal<void (const IdoSocket::Ptr&)> OnConnected;
|
|
||||||
boost::signal<void (const IdoSocket::Ptr&)> OnDisconnected;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void DataAvailableHandler(void);
|
|
||||||
void ClientClosedHandler(void);
|
|
||||||
|
|
||||||
bool m_Reconnect;
|
|
||||||
bool m_SocketType;
|
|
||||||
|
|
||||||
friend IdoSocket::Ptr IdoSocketFactory(SOCKET fd, TcpClientRole role);
|
|
||||||
};
|
|
||||||
|
|
||||||
IdoSocket::Ptr IdoSocketFactory(SOCKET fd, TcpClientRole role);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* JSONRPCCLIENT_H */
|
|
|
@ -68,8 +68,7 @@ void DemoComponent::DemoTimerHandler(void)
|
||||||
void DemoComponent::HelloWorldRequestHandler(const Endpoint::Ptr& sender,
|
void DemoComponent::HelloWorldRequestHandler(const Endpoint::Ptr& sender,
|
||||||
const RequestMessage& request)
|
const RequestMessage& request)
|
||||||
{
|
{
|
||||||
Logger::Write(LogInformation, "demo", "Got 'hello world' from"
|
Logger::Write(LogInformation, "demo", "Got 'hello world' from identity=" +
|
||||||
" address=" + sender->GetAddress() + ", identity=" +
|
|
||||||
sender->GetName());
|
sender->GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ libbase_la_SOURCES = \
|
||||||
asynctask.h \
|
asynctask.h \
|
||||||
component.cpp \
|
component.cpp \
|
||||||
component.h \
|
component.h \
|
||||||
|
connection.cpp \
|
||||||
|
connection.h \
|
||||||
dictionary.cpp \
|
dictionary.cpp \
|
||||||
dictionary.h \
|
dictionary.h \
|
||||||
dynamicobject.cpp \
|
dynamicobject.cpp \
|
||||||
|
@ -21,7 +23,6 @@ libbase_la_SOURCES = \
|
||||||
fifo.cpp \
|
fifo.cpp \
|
||||||
fifo.h \
|
fifo.h \
|
||||||
i2-base.h \
|
i2-base.h \
|
||||||
ioqueue.h \
|
|
||||||
logger.cpp \
|
logger.cpp \
|
||||||
logger.h \
|
logger.h \
|
||||||
netstring.cpp \
|
netstring.cpp \
|
||||||
|
@ -40,20 +41,20 @@ libbase_la_SOURCES = \
|
||||||
scripttask.h \
|
scripttask.h \
|
||||||
socket.cpp \
|
socket.cpp \
|
||||||
socket.h \
|
socket.h \
|
||||||
|
stream.cpp \
|
||||||
|
stream.h \
|
||||||
|
stream_bio.cpp \
|
||||||
|
stream_bio.h \
|
||||||
streamlogger.cpp \
|
streamlogger.cpp \
|
||||||
streamlogger.h \
|
streamlogger.h \
|
||||||
sysloglogger.cpp \
|
sysloglogger.cpp \
|
||||||
sysloglogger.h \
|
sysloglogger.h \
|
||||||
tcpclient.cpp \
|
|
||||||
tcpclient.h \
|
|
||||||
tcpserver.cpp \
|
|
||||||
tcpserver.h \
|
|
||||||
tcpsocket.cpp \
|
tcpsocket.cpp \
|
||||||
tcpsocket.h \
|
tcpsocket.h \
|
||||||
timer.cpp \
|
timer.cpp \
|
||||||
timer.h \
|
timer.h \
|
||||||
tlsclient.cpp \
|
tlsstream.cpp \
|
||||||
tlsclient.h \
|
tlsstream.h \
|
||||||
unix.h \
|
unix.h \
|
||||||
utility.cpp \
|
utility.cpp \
|
||||||
utility.h \
|
utility.h \
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="application.cpp" />
|
<ClCompile Include="application.cpp" />
|
||||||
<ClCompile Include="component.cpp" />
|
<ClCompile Include="component.cpp" />
|
||||||
|
<ClCompile Include="connection.cpp" />
|
||||||
<ClCompile Include="dynamicobject.cpp" />
|
<ClCompile Include="dynamicobject.cpp" />
|
||||||
<ClCompile Include="dictionary.cpp" />
|
<ClCompile Include="dictionary.cpp" />
|
||||||
<ClCompile Include="event.cpp" />
|
<ClCompile Include="event.cpp" />
|
||||||
|
@ -41,13 +42,13 @@
|
||||||
<ClCompile Include="scriptfunction.cpp" />
|
<ClCompile Include="scriptfunction.cpp" />
|
||||||
<ClCompile Include="scripttask.cpp" />
|
<ClCompile Include="scripttask.cpp" />
|
||||||
<ClCompile Include="socket.cpp" />
|
<ClCompile Include="socket.cpp" />
|
||||||
|
<ClCompile Include="stream.cpp" />
|
||||||
<ClCompile Include="streamlogger.cpp" />
|
<ClCompile Include="streamlogger.cpp" />
|
||||||
|
<ClCompile Include="stream_bio.cpp" />
|
||||||
<ClCompile Include="sysloglogger.cpp" />
|
<ClCompile Include="sysloglogger.cpp" />
|
||||||
<ClCompile Include="tcpclient.cpp" />
|
|
||||||
<ClCompile Include="tcpserver.cpp" />
|
|
||||||
<ClCompile Include="tcpsocket.cpp" />
|
<ClCompile Include="tcpsocket.cpp" />
|
||||||
<ClCompile Include="timer.cpp" />
|
<ClCompile Include="timer.cpp" />
|
||||||
<ClCompile Include="tlsclient.cpp" />
|
<ClCompile Include="tlsstream.cpp" />
|
||||||
<ClCompile Include="utility.cpp" />
|
<ClCompile Include="utility.cpp" />
|
||||||
<ClCompile Include="value.cpp" />
|
<ClCompile Include="value.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -55,11 +56,12 @@
|
||||||
<ClInclude Include="application.h" />
|
<ClInclude Include="application.h" />
|
||||||
<ClInclude Include="asynctask.h" />
|
<ClInclude Include="asynctask.h" />
|
||||||
<ClInclude Include="component.h" />
|
<ClInclude Include="component.h" />
|
||||||
|
<ClInclude Include="connection.h" />
|
||||||
<ClInclude Include="dynamicobject.h" />
|
<ClInclude Include="dynamicobject.h" />
|
||||||
<ClInclude Include="dictionary.h" />
|
<ClInclude Include="dictionary.h" />
|
||||||
<ClInclude Include="event.h" />
|
<ClInclude Include="event.h" />
|
||||||
<ClInclude Include="fifo.h" />
|
<ClInclude Include="fifo.h" />
|
||||||
<ClInclude Include="ioqueue.h" />
|
<ClInclude Include="stream.h" />
|
||||||
<ClInclude Include="netstring.h" />
|
<ClInclude Include="netstring.h" />
|
||||||
<ClInclude Include="qstring.h" />
|
<ClInclude Include="qstring.h" />
|
||||||
<ClInclude Include="scriptfunction.h" />
|
<ClInclude Include="scriptfunction.h" />
|
||||||
|
@ -72,12 +74,11 @@
|
||||||
<ClInclude Include="ringbuffer.h" />
|
<ClInclude Include="ringbuffer.h" />
|
||||||
<ClInclude Include="socket.h" />
|
<ClInclude Include="socket.h" />
|
||||||
<ClInclude Include="streamlogger.h" />
|
<ClInclude Include="streamlogger.h" />
|
||||||
|
<ClInclude Include="stream_bio.h" />
|
||||||
<ClInclude Include="sysloglogger.h" />
|
<ClInclude Include="sysloglogger.h" />
|
||||||
<ClInclude Include="tcpclient.h" />
|
|
||||||
<ClInclude Include="tcpserver.h" />
|
|
||||||
<ClInclude Include="tcpsocket.h" />
|
<ClInclude Include="tcpsocket.h" />
|
||||||
<ClInclude Include="timer.h" />
|
<ClInclude Include="timer.h" />
|
||||||
<ClInclude Include="tlsclient.h" />
|
<ClInclude Include="tlsstream.h" />
|
||||||
<ClInclude Include="unix.h" />
|
<ClInclude Include="unix.h" />
|
||||||
<ClInclude Include="utility.h" />
|
<ClInclude Include="utility.h" />
|
||||||
<ClInclude Include="value.h" />
|
<ClInclude Include="value.h" />
|
||||||
|
@ -240,4 +241,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -25,30 +25,15 @@
|
||||||
<ClCompile Include="socket.cpp">
|
<ClCompile Include="socket.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="tcpclient.cpp">
|
|
||||||
<Filter>Quelldateien</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="tcpserver.cpp">
|
|
||||||
<Filter>Quelldateien</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="tcpsocket.cpp">
|
<ClCompile Include="tcpsocket.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="timer.cpp">
|
<ClCompile Include="timer.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="tlsclient.cpp">
|
|
||||||
<Filter>Quelldateien</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="unix.cpp">
|
|
||||||
<Filter>Quelldateien</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="utility.cpp">
|
<ClCompile Include="utility.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="win32.cpp">
|
|
||||||
<Filter>Quelldateien</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="logger.cpp">
|
<ClCompile Include="logger.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -85,6 +70,18 @@
|
||||||
<ClCompile Include="qstring.cpp">
|
<ClCompile Include="qstring.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="tlsstream.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="stream.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="stream_bio.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="connection.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="application.h">
|
<ClInclude Include="application.h">
|
||||||
|
@ -117,21 +114,12 @@
|
||||||
<ClInclude Include="socket.h">
|
<ClInclude Include="socket.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="tcpclient.h">
|
|
||||||
<Filter>Headerdateien</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="tcpserver.h">
|
|
||||||
<Filter>Headerdateien</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="tcpsocket.h">
|
<ClInclude Include="tcpsocket.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="timer.h">
|
<ClInclude Include="timer.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="tlsclient.h">
|
|
||||||
<Filter>Headerdateien</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="unix.h">
|
<ClInclude Include="unix.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -159,9 +147,6 @@
|
||||||
<ClInclude Include="scriptfunction.h">
|
<ClInclude Include="scriptfunction.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="ioqueue.h">
|
|
||||||
<Filter>Headerdateien</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="fifo.h">
|
<ClInclude Include="fifo.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -177,6 +162,18 @@
|
||||||
<ClInclude Include="qstring.h">
|
<ClInclude Include="qstring.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="stream.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="tlsstream.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="stream_bio.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="connection.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Quelldateien">
|
<Filter Include="Quelldateien">
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "i2-base.h"
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
Connection::Connection(const Stream::Ptr& stream)
|
||||||
|
: m_Stream(stream)
|
||||||
|
{
|
||||||
|
m_Stream->OnDataAvailable.connect(boost::bind(&Connection::ProcessData, this));
|
||||||
|
m_Stream->OnClosed.connect(boost::bind(&Connection::ClosedHandler, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::Ptr Connection::GetStream(void) const
|
||||||
|
{
|
||||||
|
return m_Stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::ClosedHandler(void)
|
||||||
|
{
|
||||||
|
OnClosed(GetSelf());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::Close(void)
|
||||||
|
{
|
||||||
|
m_Stream->Close();
|
||||||
|
}
|
|
@ -17,44 +17,35 @@
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef TCPSERVER_H
|
#ifndef CONNECTION_H
|
||||||
#define TCPSERVER_H
|
#define CONNECTION_H
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
class I2_BASE_API Connection : public Object
|
||||||
* A TCP server that listens on a TCP port and accepts incoming
|
|
||||||
* client connections.
|
|
||||||
*
|
|
||||||
* @ingroup base
|
|
||||||
*/
|
|
||||||
class I2_BASE_API TcpServer : public TcpSocket
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef shared_ptr<TcpServer> Ptr;
|
typedef shared_ptr<Connection> Ptr;
|
||||||
typedef weak_ptr<TcpServer> WeakPtr;
|
typedef weak_ptr<Connection> WeakPtr;
|
||||||
|
|
||||||
typedef function<TcpClient::Ptr(SOCKET)> ClientFactory;
|
Connection(const Stream::Ptr& stream);
|
||||||
|
|
||||||
TcpServer(void);
|
Stream::Ptr GetStream(void) const;
|
||||||
|
|
||||||
void SetClientFactory(const ClientFactory& clientFactory);
|
void Close(void);
|
||||||
ClientFactory GetFactoryFunction(void) const;
|
|
||||||
|
|
||||||
void Listen(void);
|
boost::signal<void (const Connection::Ptr&)> OnClosed;
|
||||||
|
|
||||||
boost::signal<void (const TcpServer::Ptr&, const TcpClient::Ptr&)> OnNewClient;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool WantsToRead(void) const;
|
virtual void ProcessData(void) = 0;
|
||||||
|
|
||||||
virtual void HandleReadable(void);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClientFactory m_ClientFactory;
|
Stream::Ptr m_Stream;
|
||||||
|
|
||||||
|
void ClosedHandler(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* TCPSERVER_H */
|
#endif /* CONNECTION_H */
|
|
@ -368,6 +368,7 @@ void DynamicObject::DumpObjects(const String& filename)
|
||||||
throw_exception(runtime_error("Could not open '" + filename + "' file"));
|
throw_exception(runtime_error("Could not open '" + filename + "' file"));
|
||||||
|
|
||||||
FIFO::Ptr fifo = boost::make_shared<FIFO>();
|
FIFO::Ptr fifo = boost::make_shared<FIFO>();
|
||||||
|
fifo->Start();
|
||||||
|
|
||||||
DynamicObject::TypeMap::iterator tt;
|
DynamicObject::TypeMap::iterator tt;
|
||||||
for (tt = GetAllObjects().begin(); tt != GetAllObjects().end(); tt++) {
|
for (tt = GetAllObjects().begin(); tt != GetAllObjects().end(); tt++) {
|
||||||
|
@ -401,7 +402,7 @@ void DynamicObject::DumpObjects(const String& filename)
|
||||||
String json = value.Serialize();
|
String json = value.Serialize();
|
||||||
|
|
||||||
/* This is quite ugly, unfortunatelly NetString requires an IOQueue object */
|
/* This is quite ugly, unfortunatelly NetString requires an IOQueue object */
|
||||||
NetString::WriteStringToIOQueue(fifo.get(), json);
|
NetString::WriteStringToStream(fifo, json);
|
||||||
|
|
||||||
size_t count;
|
size_t count;
|
||||||
while ((count = fifo->GetAvailableBytes()) > 0) {
|
while ((count = fifo->GetAvailableBytes()) > 0) {
|
||||||
|
@ -416,6 +417,8 @@ void DynamicObject::DumpObjects(const String& filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fifo->Close();
|
||||||
|
|
||||||
fp.close();
|
fp.close();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -436,6 +439,8 @@ void DynamicObject::RestoreObjects(const String& filename)
|
||||||
/* TODO: Fix this horrible mess by implementing a class that provides
|
/* TODO: Fix this horrible mess by implementing a class that provides
|
||||||
* IOQueue functionality for files. */
|
* IOQueue functionality for files. */
|
||||||
FIFO::Ptr fifo = boost::make_shared<FIFO>();
|
FIFO::Ptr fifo = boost::make_shared<FIFO>();
|
||||||
|
fifo->Start();
|
||||||
|
|
||||||
while (fp) {
|
while (fp) {
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
|
||||||
|
@ -444,7 +449,7 @@ void DynamicObject::RestoreObjects(const String& filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
String message;
|
String message;
|
||||||
while (NetString::ReadStringFromIOQueue(fifo.get(), &message)) {
|
while (NetString::ReadStringFromStream(fifo, &message)) {
|
||||||
Dictionary::Ptr persistentObject = Value::Deserialize(message);
|
Dictionary::Ptr persistentObject = Value::Deserialize(message);
|
||||||
|
|
||||||
String type = persistentObject->Get("type");
|
String type = persistentObject->Get("type");
|
||||||
|
@ -462,6 +467,8 @@ void DynamicObject::RestoreObjects(const String& filename)
|
||||||
object->ApplyUpdate(update, Attribute_All);
|
object->ApplyUpdate(update, Attribute_All);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fifo->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicObject::DeactivateObjects(void)
|
void DynamicObject::DeactivateObjects(void)
|
||||||
|
|
|
@ -38,6 +38,13 @@ FIFO::~FIFO(void)
|
||||||
free(m_Buffer);
|
free(m_Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FIFO::Start(void)
|
||||||
|
{
|
||||||
|
SetConnected(true);
|
||||||
|
|
||||||
|
Stream::Start();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resizes the FIFO's buffer so that it is at least newSize bytes long.
|
* Resizes the FIFO's buffer so that it is at least newSize bytes long.
|
||||||
*
|
*
|
||||||
|
@ -109,25 +116,32 @@ size_t FIFO::GetAvailableBytes(void) const
|
||||||
/**
|
/**
|
||||||
* Implements IOQueue::Peek.
|
* Implements IOQueue::Peek.
|
||||||
*/
|
*/
|
||||||
void FIFO::Peek(void *buffer, size_t count)
|
size_t FIFO::Peek(void *buffer, size_t count)
|
||||||
{
|
{
|
||||||
assert(m_DataSize >= count);
|
assert(IsConnected());
|
||||||
|
|
||||||
|
if (count > m_DataSize)
|
||||||
|
count = m_DataSize;
|
||||||
|
|
||||||
if (buffer != NULL)
|
if (buffer != NULL)
|
||||||
memcpy(buffer, m_Buffer + m_Offset, count);
|
memcpy(buffer, m_Buffer + m_Offset, count);
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements IOQueue::Read.
|
* Implements IOQueue::Read.
|
||||||
*/
|
*/
|
||||||
void FIFO::Read(void *buffer, size_t count)
|
size_t FIFO::Read(void *buffer, size_t count)
|
||||||
{
|
{
|
||||||
Peek(buffer, count);
|
count = Peek(buffer, count);
|
||||||
|
|
||||||
m_DataSize -= count;
|
m_DataSize -= count;
|
||||||
m_Offset += count;
|
m_Offset += count;
|
||||||
|
|
||||||
Optimize();
|
Optimize();
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -135,6 +149,8 @@ void FIFO::Read(void *buffer, size_t count)
|
||||||
*/
|
*/
|
||||||
void FIFO::Write(const void *buffer, size_t count)
|
void FIFO::Write(const void *buffer, size_t count)
|
||||||
{
|
{
|
||||||
|
assert(IsConnected());
|
||||||
|
|
||||||
ResizeBuffer(m_Offset + m_DataSize + count);
|
ResizeBuffer(m_Offset + m_DataSize + count);
|
||||||
memcpy(m_Buffer + m_Offset + m_DataSize, buffer, count);
|
memcpy(m_Buffer + m_Offset + m_DataSize, buffer, count);
|
||||||
m_DataSize += count;
|
m_DataSize += count;
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace icinga
|
||||||
*
|
*
|
||||||
* @ingroup base
|
* @ingroup base
|
||||||
*/
|
*/
|
||||||
class I2_BASE_API FIFO : public Object, public IOQueue
|
class I2_BASE_API FIFO : public Stream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const size_t BlockSize = 16 * 1024;
|
static const size_t BlockSize = 16 * 1024;
|
||||||
|
@ -39,13 +39,15 @@ public:
|
||||||
FIFO(void);
|
FIFO(void);
|
||||||
~FIFO(void);
|
~FIFO(void);
|
||||||
|
|
||||||
|
void Start(void);
|
||||||
|
|
||||||
/*const void *GetReadBuffer(void) const;
|
/*const void *GetReadBuffer(void) const;
|
||||||
void *GetWriteBuffer(size_t *count);*/
|
void *GetWriteBuffer(size_t *count);*/
|
||||||
|
|
||||||
virtual size_t GetAvailableBytes(void) const;
|
size_t GetAvailableBytes(void) const;
|
||||||
virtual void Peek(void *buffer, size_t count);
|
size_t Peek(void *buffer, size_t count);
|
||||||
virtual void Read(void *buffer, size_t count);
|
size_t Read(void *buffer, size_t count);
|
||||||
virtual void Write(const void *buffer, size_t count);
|
void Write(const void *buffer, size_t count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *m_Buffer;
|
char *m_Buffer;
|
||||||
|
|
|
@ -175,14 +175,14 @@ namespace tuples = boost::tuples;
|
||||||
#include "dictionary.h"
|
#include "dictionary.h"
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "ioqueue.h"
|
#include "stream.h"
|
||||||
|
#include "stream_bio.h"
|
||||||
|
#include "connection.h"
|
||||||
#include "netstring.h"
|
#include "netstring.h"
|
||||||
#include "fifo.h"
|
#include "fifo.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "tcpsocket.h"
|
#include "tcpsocket.h"
|
||||||
#include "tcpclient.h"
|
#include "tlsstream.h"
|
||||||
#include "tcpserver.h"
|
|
||||||
#include "tlsclient.h"
|
|
||||||
#include "asynctask.h"
|
#include "asynctask.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "scriptfunction.h"
|
#include "scriptfunction.h"
|
||||||
|
|
|
@ -22,17 +22,17 @@
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from an IOQueue in netString format.
|
* Reads data from a stream in netString format.
|
||||||
*
|
*
|
||||||
* @param queue The IOQueue to read from.
|
* @param stream The stream to read from.
|
||||||
* @param[out] str The String that has been read from the IOQueue.
|
* @param[out] str The String that has been read from the IOQueue.
|
||||||
* @returns true if a complete String was read from the IOQueue, false otherwise.
|
* @returns true if a complete String was read from the IOQueue, false otherwise.
|
||||||
* @exception invalid_argument The input stream is invalid.
|
* @exception invalid_argument The input stream is invalid.
|
||||||
* @see https://github.com/PeterScott/netString-c/blob/master/netString.c
|
* @see https://github.com/PeterScott/netString-c/blob/master/netString.c
|
||||||
*/
|
*/
|
||||||
bool NetString::ReadStringFromIOQueue(IOQueue *queue, String *str)
|
bool NetString::ReadStringFromStream(const Stream::Ptr& stream, String *str)
|
||||||
{
|
{
|
||||||
size_t buffer_length = queue->GetAvailableBytes();
|
size_t buffer_length = stream->GetAvailableBytes();
|
||||||
|
|
||||||
/* minimum netString length is 3 */
|
/* minimum netString length is 3 */
|
||||||
if (buffer_length < 3)
|
if (buffer_length < 3)
|
||||||
|
@ -47,7 +47,7 @@ bool NetString::ReadStringFromIOQueue(IOQueue *queue, String *str)
|
||||||
if (buffer == NULL && buffer_length > 0)
|
if (buffer == NULL && buffer_length > 0)
|
||||||
throw_exception(bad_alloc());
|
throw_exception(bad_alloc());
|
||||||
|
|
||||||
queue->Peek(buffer, buffer_length);
|
stream->Peek(buffer, buffer_length);
|
||||||
|
|
||||||
/* no leading zeros allowed */
|
/* no leading zeros allowed */
|
||||||
if (buffer[0] == '0' && isdigit(buffer[1])) {
|
if (buffer[0] == '0' && isdigit(buffer[1])) {
|
||||||
|
@ -68,7 +68,7 @@ bool NetString::ReadStringFromIOQueue(IOQueue *queue, String *str)
|
||||||
len = len * 10 + (buffer[i] - '0');
|
len = len * 10 + (buffer[i] - '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_length = queue->GetAvailableBytes();
|
buffer_length = stream->GetAvailableBytes();
|
||||||
|
|
||||||
/* make sure the buffer is large enough */
|
/* make sure the buffer is large enough */
|
||||||
if (i + len + 1 >= buffer_length)
|
if (i + len + 1 >= buffer_length)
|
||||||
|
@ -86,7 +86,7 @@ bool NetString::ReadStringFromIOQueue(IOQueue *queue, String *str)
|
||||||
|
|
||||||
buffer = new_buffer;
|
buffer = new_buffer;
|
||||||
|
|
||||||
queue->Peek(buffer, buffer_length);
|
stream->Peek(buffer, buffer_length);
|
||||||
|
|
||||||
/* check for the colon delimiter */
|
/* check for the colon delimiter */
|
||||||
if (buffer[i] != ':') {
|
if (buffer[i] != ':') {
|
||||||
|
@ -104,25 +104,25 @@ bool NetString::ReadStringFromIOQueue(IOQueue *queue, String *str)
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
/* remove the data from the IOQueue */
|
/* remove the data from the stream */
|
||||||
queue->Read(NULL, buffer_length);
|
stream->Read(NULL, buffer_length);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes data into an IOQueue using the netString format.
|
* Writes data into a stream using the netString format.
|
||||||
*
|
*
|
||||||
* @param queue The IOQueue.
|
* @param stream The stream.
|
||||||
* @param str The String that is to be written.
|
* @param str The String that is to be written.
|
||||||
*/
|
*/
|
||||||
void NetString::WriteStringToIOQueue(IOQueue *queue, const String& str)
|
void NetString::WriteStringToStream(const Stream::Ptr& stream, const String& str)
|
||||||
{
|
{
|
||||||
stringstream prefixbuf;
|
stringstream prefixbuf;
|
||||||
prefixbuf << str.GetLength() << ":";
|
prefixbuf << str.GetLength() << ":";
|
||||||
|
|
||||||
String prefix = prefixbuf.str();
|
String prefix = prefixbuf.str();
|
||||||
queue->Write(prefix.CStr(), prefix.GetLength());
|
stream->Write(prefix.CStr(), prefix.GetLength());
|
||||||
queue->Write(str.CStr(), str.GetLength());
|
stream->Write(str.CStr(), str.GetLength());
|
||||||
queue->Write(",", 1);
|
stream->Write(",", 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,8 @@ namespace icinga
|
||||||
class I2_BASE_API NetString
|
class I2_BASE_API NetString
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool ReadStringFromIOQueue(IOQueue *queue, String *message);
|
static bool ReadStringFromStream(const Stream::Ptr& stream, String *message);
|
||||||
static void WriteStringToIOQueue(IOQueue *queue, const String& message);
|
static void WriteStringToStream(const Stream::Ptr& stream, const String& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetString(void);
|
NetString(void);
|
||||||
|
|
|
@ -25,16 +25,19 @@ using namespace icinga;
|
||||||
* Constructor for the Socket class.
|
* Constructor for the Socket class.
|
||||||
*/
|
*/
|
||||||
Socket::Socket(void)
|
Socket::Socket(void)
|
||||||
: m_FD(INVALID_SOCKET), m_Connected(false)
|
: m_FD(INVALID_SOCKET), m_Connected(false), m_Listening(false),
|
||||||
{ }
|
m_SendQueue(boost::make_shared<FIFO>()), m_RecvQueue(boost::make_shared<FIFO>())
|
||||||
|
{
|
||||||
|
m_SendQueue->Start();
|
||||||
|
m_RecvQueue->Start();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor for the Socket class.
|
* Destructor for the Socket class.
|
||||||
*/
|
*/
|
||||||
Socket::~Socket(void)
|
Socket::~Socket(void)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_SocketMutex);
|
Close();
|
||||||
CloseInternal(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,6 +53,8 @@ void Socket::Start(void)
|
||||||
|
|
||||||
m_WriteThread = thread(boost::bind(&Socket::WriteThreadProc, static_cast<Socket::Ptr>(GetSelf())));
|
m_WriteThread = thread(boost::bind(&Socket::WriteThreadProc, static_cast<Socket::Ptr>(GetSelf())));
|
||||||
m_WriteThread.detach();
|
m_WriteThread.detach();
|
||||||
|
|
||||||
|
Stream::Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,35 +93,24 @@ SOCKET Socket::GetFD(void) const
|
||||||
return m_FD;
|
return m_FD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Socket::CloseUnlocked(void)
|
||||||
|
{
|
||||||
|
if (m_FD == INVALID_SOCKET)
|
||||||
|
return;
|
||||||
|
|
||||||
|
closesocket(m_FD);
|
||||||
|
m_FD = INVALID_SOCKET;
|
||||||
|
|
||||||
|
Stream::Close();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the socket.
|
* Closes the socket.
|
||||||
*/
|
*/
|
||||||
void Socket::Close(void)
|
void Socket::Close(void)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_SocketMutex);
|
boost::mutex::scoped_lock lock(m_SocketMutex);
|
||||||
|
CloseUnlocked();
|
||||||
CloseInternal(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the socket.
|
|
||||||
*
|
|
||||||
* @param from_dtor Whether this method was called from the destructor.
|
|
||||||
*/
|
|
||||||
void Socket::CloseInternal(bool from_dtor)
|
|
||||||
{
|
|
||||||
if (m_FD == INVALID_SOCKET)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetConnected(false);
|
|
||||||
|
|
||||||
closesocket(m_FD);
|
|
||||||
m_FD = INVALID_SOCKET;
|
|
||||||
|
|
||||||
/* nobody can possibly have a valid event subscription when the
|
|
||||||
destructor has been called */
|
|
||||||
if (!from_dtor)
|
|
||||||
Event::Post(boost::bind(boost::ref(OnClosed), GetSelf()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -159,32 +153,6 @@ void Socket::HandleException(void)
|
||||||
throw_exception(SocketException("select() returned fd in except fdset", GetError()));
|
throw_exception(SocketException("select() returned fd in except fdset", GetError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether data should be read for this socket object.
|
|
||||||
*
|
|
||||||
* @returns true if the socket should be registered for reading, false otherwise.
|
|
||||||
*/
|
|
||||||
bool Socket::WantsToRead(void) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socket::HandleReadable(void)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether data should be written for this socket object.
|
|
||||||
*
|
|
||||||
* @returns true if the socket should be registered for writing, false otherwise.
|
|
||||||
*/
|
|
||||||
bool Socket::WantsToWrite(void) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socket::HandleWritable(void)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a sockaddr in a human-readable way.
|
* Formats a sockaddr in a human-readable way.
|
||||||
*
|
*
|
||||||
|
@ -305,9 +273,9 @@ void Socket::ReadThreadProc(void)
|
||||||
if (FD_ISSET(fd, &exceptfds))
|
if (FD_ISSET(fd, &exceptfds))
|
||||||
HandleException();
|
HandleException();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
m_Exception = boost::current_exception();
|
SetException(boost::current_exception());
|
||||||
|
|
||||||
CloseInternal(false);
|
CloseUnlocked();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -360,9 +328,9 @@ void Socket::WriteThreadProc(void)
|
||||||
if (FD_ISSET(fd, &writefds))
|
if (FD_ISSET(fd, &writefds))
|
||||||
HandleWritable();
|
HandleWritable();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
m_Exception = boost::current_exception();
|
SetException(boost::current_exception());
|
||||||
|
|
||||||
CloseInternal(false);
|
CloseUnlocked();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -390,11 +358,281 @@ bool Socket::IsConnected(void) const
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether an exception is available for this socket. Should be called
|
* Returns how much data is available for reading.
|
||||||
* by user-supplied handlers for the OnClosed signal.
|
*
|
||||||
|
* @returns The number of bytes available.
|
||||||
*/
|
*/
|
||||||
void Socket::CheckException(void)
|
size_t Socket::GetAvailableBytes(void) const
|
||||||
{
|
{
|
||||||
if (m_Exception)
|
if (m_Listening)
|
||||||
rethrow_exception(m_Exception);
|
throw new logic_error("Socket does not support GetAvailableBytes().");
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||||
|
|
||||||
|
return m_RecvQueue->GetAvailableBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads data from the socket.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer where the data should be stored.
|
||||||
|
* @param size The size of the buffer.
|
||||||
|
* @returns The number of bytes read.
|
||||||
|
*/
|
||||||
|
size_t Socket::Read(void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
if (m_Listening)
|
||||||
|
throw new logic_error("Socket does not support Read().");
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||||
|
|
||||||
|
if (m_RecvQueue->GetAvailableBytes() == 0)
|
||||||
|
CheckException();
|
||||||
|
|
||||||
|
return m_RecvQueue->Read(buffer, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peeks at data for the socket.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer where the data should be stored.
|
||||||
|
* @param size The size of the buffer.
|
||||||
|
* @returns The number of bytes read.
|
||||||
|
*/
|
||||||
|
size_t Socket::Peek(void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
if (m_Listening)
|
||||||
|
throw new logic_error("Socket does not support Peek().");
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||||
|
|
||||||
|
if (m_RecvQueue->GetAvailableBytes() == 0)
|
||||||
|
CheckException();
|
||||||
|
|
||||||
|
return m_RecvQueue->Peek(buffer, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes data to the socket.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer that should be sent.
|
||||||
|
* @param size The size of the buffer.
|
||||||
|
*/
|
||||||
|
void Socket::Write(const void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
if (m_Listening)
|
||||||
|
throw new logic_error("Socket does not support Write().");
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||||
|
|
||||||
|
m_SendQueue->Write(buffer, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts listening for incoming client connections.
|
||||||
|
*/
|
||||||
|
void Socket::Listen(void)
|
||||||
|
{
|
||||||
|
if (listen(GetFD(), SOMAXCONN) < 0)
|
||||||
|
throw_exception(SocketException("listen() failed", GetError()));
|
||||||
|
|
||||||
|
m_Listening = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::HandleWritable(void)
|
||||||
|
{
|
||||||
|
if (m_Listening)
|
||||||
|
HandleWritableServer();
|
||||||
|
else
|
||||||
|
HandleWritableClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::HandleReadable(void)
|
||||||
|
{
|
||||||
|
if (m_Listening)
|
||||||
|
HandleReadableServer();
|
||||||
|
else
|
||||||
|
HandleReadableClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes data that is available for this socket.
|
||||||
|
*/
|
||||||
|
void Socket::HandleWritableClient(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char data[1024];
|
||||||
|
size_t count;
|
||||||
|
|
||||||
|
if (!IsConnected())
|
||||||
|
SetConnected(true);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||||
|
|
||||||
|
count = m_SendQueue->GetAvailableBytes();
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (count > sizeof(data))
|
||||||
|
count = sizeof(data);
|
||||||
|
|
||||||
|
m_SendQueue->Peek(data, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = send(GetFD(), data, count, 0);
|
||||||
|
|
||||||
|
if (rc <= 0)
|
||||||
|
throw_exception(SocketException("send() failed", GetError()));
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||||
|
m_SendQueue->Read(NULL, rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes data that can be written for this socket.
|
||||||
|
*/
|
||||||
|
void Socket::HandleReadableClient(void)
|
||||||
|
{
|
||||||
|
if (!IsConnected())
|
||||||
|
SetConnected(true);
|
||||||
|
|
||||||
|
bool new_data = false;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
char data[1024];
|
||||||
|
int rc = recv(GetFD(), data, sizeof(data), 0);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (rc < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||||
|
#else /* _WIN32 */
|
||||||
|
if (rc < 0 && errno == EAGAIN)
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (rc <= 0)
|
||||||
|
throw_exception(SocketException("recv() failed", GetError()));
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||||
|
|
||||||
|
m_RecvQueue->Write(data, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_data)
|
||||||
|
Event::Post(boost::bind(boost::ref(OnDataAvailable), GetSelf()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::HandleWritableServer(void)
|
||||||
|
{
|
||||||
|
throw logic_error("This should never happen.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a new client and creates a new client object for it
|
||||||
|
* using the client factory function.
|
||||||
|
*/
|
||||||
|
void Socket::HandleReadableServer(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
sockaddr_storage addr;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
|
fd = accept(GetFD(), (sockaddr *)&addr, &addrlen);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
throw_exception(SocketException("accept() failed", GetError()));
|
||||||
|
|
||||||
|
TcpSocket::Ptr client = boost::make_shared<TcpSocket>();
|
||||||
|
client->SetFD(fd);
|
||||||
|
Event::Post(boost::bind(boost::ref(OnNewClient), GetSelf(), client));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether data should be written for this socket object.
|
||||||
|
*
|
||||||
|
* @returns true if the socket should be registered for writing, false otherwise.
|
||||||
|
*/
|
||||||
|
bool Socket::WantsToWrite(void) const
|
||||||
|
{
|
||||||
|
if (m_Listening)
|
||||||
|
return WantsToWriteServer();
|
||||||
|
else
|
||||||
|
return WantsToWriteClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether data should be read for this socket object.
|
||||||
|
*
|
||||||
|
* @returns true if the socket should be registered for reading, false otherwise.
|
||||||
|
*/
|
||||||
|
bool Socket::WantsToRead(void) const
|
||||||
|
{
|
||||||
|
if (m_Listening)
|
||||||
|
return WantsToReadServer();
|
||||||
|
else
|
||||||
|
return WantsToReadClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether data should be read for this socket.
|
||||||
|
*
|
||||||
|
* @returns true
|
||||||
|
*/
|
||||||
|
bool Socket::WantsToReadClient(void) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether data should be written for this socket.
|
||||||
|
*
|
||||||
|
* @returns true if data should be written, false otherwise.
|
||||||
|
*/
|
||||||
|
bool Socket::WantsToWriteClient(void) const
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||||
|
|
||||||
|
if (m_SendQueue->GetAvailableBytes() > 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (!IsConnected());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the TCP server wants to write.
|
||||||
|
*
|
||||||
|
* @returns false
|
||||||
|
*/
|
||||||
|
bool Socket::WantsToWriteServer(void) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the TCP server wants to read (i.e. accept new clients).
|
||||||
|
*
|
||||||
|
* @returns true
|
||||||
|
*/
|
||||||
|
bool Socket::WantsToReadServer(void) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,11 @@
|
||||||
namespace icinga {
|
namespace icinga {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for sockets.
|
* Base class for connection-oriented sockets.
|
||||||
*
|
*
|
||||||
* @ingroup base
|
* @ingroup base
|
||||||
*/
|
*/
|
||||||
class I2_BASE_API Socket : public Object
|
class I2_BASE_API Socket : public Stream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef shared_ptr<Socket> Ptr;
|
typedef shared_ptr<Socket> Ptr;
|
||||||
|
@ -35,18 +35,23 @@ public:
|
||||||
|
|
||||||
~Socket(void);
|
~Socket(void);
|
||||||
|
|
||||||
boost::signal<void (const Socket::Ptr&)> OnClosed;
|
|
||||||
|
|
||||||
virtual void Start(void);
|
virtual void Start(void);
|
||||||
|
|
||||||
void Close(void);
|
virtual void Close(void);
|
||||||
|
|
||||||
String GetClientAddress(void);
|
String GetClientAddress(void);
|
||||||
String GetPeerAddress(void);
|
String GetPeerAddress(void);
|
||||||
|
|
||||||
bool IsConnected(void) const;
|
bool IsConnected(void) const;
|
||||||
|
|
||||||
void CheckException(void);
|
size_t GetAvailableBytes(void) const;
|
||||||
|
size_t Read(void *buffer, size_t size);
|
||||||
|
size_t Peek(void *buffer, size_t size);
|
||||||
|
void Write(const void *buffer, size_t size);
|
||||||
|
|
||||||
|
void Listen(void);
|
||||||
|
|
||||||
|
boost::signal<void (const Socket::Ptr&, const Socket::Ptr&)> OnNewClient;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Socket(void);
|
Socket(void);
|
||||||
|
@ -59,34 +64,49 @@ protected:
|
||||||
int GetError(void) const;
|
int GetError(void) const;
|
||||||
static int GetLastSocketError(void);
|
static int GetLastSocketError(void);
|
||||||
|
|
||||||
virtual bool WantsToRead(void) const;
|
|
||||||
virtual bool WantsToWrite(void) const;
|
|
||||||
|
|
||||||
virtual void HandleReadable(void);
|
|
||||||
virtual void HandleWritable(void);
|
|
||||||
virtual void HandleException(void);
|
|
||||||
|
|
||||||
virtual void CloseInternal(bool from_dtor);
|
|
||||||
|
|
||||||
mutable boost::mutex m_SocketMutex;
|
mutable boost::mutex m_SocketMutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SOCKET m_FD; /**< The socket descriptor. */
|
SOCKET m_FD; /**< The socket descriptor. */
|
||||||
bool m_Connected;
|
bool m_Connected;
|
||||||
|
bool m_Listening;
|
||||||
|
|
||||||
thread m_ReadThread;
|
thread m_ReadThread;
|
||||||
thread m_WriteThread;
|
thread m_WriteThread;
|
||||||
|
|
||||||
condition_variable m_WriteCV;
|
condition_variable m_WriteCV;
|
||||||
|
|
||||||
boost::exception_ptr m_Exception;
|
|
||||||
|
|
||||||
void ReadThreadProc(void);
|
void ReadThreadProc(void);
|
||||||
void WriteThreadProc(void);
|
void WriteThreadProc(void);
|
||||||
|
|
||||||
void ExceptionEventHandler(void);
|
void ExceptionEventHandler(void);
|
||||||
|
|
||||||
static String GetAddressFromSockaddr(sockaddr *address, socklen_t len);
|
static String GetAddressFromSockaddr(sockaddr *address, socklen_t len);
|
||||||
|
|
||||||
|
mutable boost::mutex m_QueueMutex;
|
||||||
|
FIFO::Ptr m_SendQueue;
|
||||||
|
FIFO::Ptr m_RecvQueue;
|
||||||
|
|
||||||
|
void HandleWritableClient(void);
|
||||||
|
void HandleReadableClient(void);
|
||||||
|
|
||||||
|
void HandleWritableServer(void);
|
||||||
|
void HandleReadableServer(void);
|
||||||
|
|
||||||
|
void HandleReadable(void);
|
||||||
|
void HandleWritable(void);
|
||||||
|
void HandleException(void);
|
||||||
|
|
||||||
|
bool WantsToWriteClient(void) const;
|
||||||
|
bool WantsToReadClient(void) const;
|
||||||
|
|
||||||
|
bool WantsToWriteServer(void) const;
|
||||||
|
bool WantsToReadServer(void) const;
|
||||||
|
|
||||||
|
bool WantsToWrite(void) const;
|
||||||
|
bool WantsToRead(void) const;
|
||||||
|
|
||||||
|
void CloseUnlocked(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "i2-base.h"
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
Stream::Stream(void)
|
||||||
|
: m_Connected(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Stream::~Stream(void)
|
||||||
|
{
|
||||||
|
assert(!m_Running);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stream::IsConnected(void) const
|
||||||
|
{
|
||||||
|
return m_Connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::SetConnected(bool connected)
|
||||||
|
{
|
||||||
|
m_Connected = connected;
|
||||||
|
|
||||||
|
if (m_Connected)
|
||||||
|
Event::Post(boost::bind(boost::ref(OnConnected), GetSelf()));
|
||||||
|
else
|
||||||
|
Event::Post(boost::bind(boost::ref(OnClosed), GetSelf()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether an exception is available for this socket and re-throws
|
||||||
|
* the exception if there is one.
|
||||||
|
*/
|
||||||
|
void Stream::CheckException(void)
|
||||||
|
{
|
||||||
|
if (m_Exception)
|
||||||
|
rethrow_exception(m_Exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::SetException(boost::exception_ptr exception)
|
||||||
|
{
|
||||||
|
m_Exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::exception_ptr Stream::GetException(void)
|
||||||
|
{
|
||||||
|
return m_Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::Start(void)
|
||||||
|
{
|
||||||
|
m_Running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::Close(void)
|
||||||
|
{
|
||||||
|
assert(m_Running);
|
||||||
|
m_Running = false;
|
||||||
|
|
||||||
|
SetConnected(false);
|
||||||
|
}
|
|
@ -17,20 +17,28 @@
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef IOQUEUE_H
|
#ifndef STREAM_H
|
||||||
#define IOQUEUE_H
|
#define STREAM_H
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An I/O queue.
|
* A stream.
|
||||||
*
|
*
|
||||||
* @ingroup base
|
* @ingroup base
|
||||||
*/
|
*/
|
||||||
class IOQueue
|
class I2_BASE_API Stream : public Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef shared_ptr<Stream> Ptr;
|
||||||
|
typedef weak_ptr<Stream> WeakPtr;
|
||||||
|
|
||||||
|
Stream(void);
|
||||||
|
~Stream(void);
|
||||||
|
|
||||||
|
virtual void Start(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the number of bytes available for reading.
|
* Retrieves the number of bytes available for reading.
|
||||||
*
|
*
|
||||||
|
@ -39,37 +47,61 @@ public:
|
||||||
virtual size_t GetAvailableBytes(void) const = 0;
|
virtual size_t GetAvailableBytes(void) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from the queue without advancing the read pointer. Trying
|
* Reads data from the stream without advancing the read pointer.
|
||||||
* to read more data than is available in the queue is a programming error.
|
|
||||||
* Use GetBytesAvailable() to check how much data is available.
|
|
||||||
*
|
*
|
||||||
* @param buffer The buffer where data should be stored. May be NULL if
|
* @param buffer The buffer where data should be stored. May be NULL if
|
||||||
* you're not actually interested in the data.
|
* you're not actually interested in the data.
|
||||||
* @param count The number of bytes to read from the queue.
|
* @param count The number of bytes to read from the queue.
|
||||||
|
* @returns The number of bytes actually read.
|
||||||
*/
|
*/
|
||||||
virtual void Peek(void *buffer, size_t count) = 0;
|
virtual size_t Peek(void *buffer, size_t count) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from the queue. Trying to read more data than is
|
* Reads data from the stream.
|
||||||
* available in the queue is a programming error. Use GetBytesAvailable()
|
|
||||||
* to check how much data is available.
|
|
||||||
*
|
*
|
||||||
* @param buffer The buffer where data should be stored. May be NULL if you're
|
* @param buffer The buffer where data should be stored. May be NULL if you're
|
||||||
* not actually interested in the data.
|
* not actually interested in the data.
|
||||||
* @param count The number of bytes to read from the queue.
|
* @param count The number of bytes to read from the queue.
|
||||||
|
* @returns The number of bytes actually read.
|
||||||
*/
|
*/
|
||||||
virtual void Read(void *buffer, size_t count) = 0;
|
virtual size_t Read(void *buffer, size_t count) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes data to the queue.
|
* Writes data to the stream.
|
||||||
*
|
*
|
||||||
* @param buffer The data that is to be written.
|
* @param buffer The data that is to be written.
|
||||||
* @param count The number of bytes to write.
|
* @param count The number of bytes to write.
|
||||||
* @returns The number of bytes written
|
* @returns The number of bytes written
|
||||||
*/
|
*/
|
||||||
virtual void Write(const void *buffer, size_t count) = 0;
|
virtual void Write(const void *buffer, size_t count) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the stream and releases resources.
|
||||||
|
*/
|
||||||
|
virtual void Close(void);
|
||||||
|
|
||||||
|
bool IsConnected(void) const;
|
||||||
|
|
||||||
|
boost::exception_ptr GetException(void);
|
||||||
|
void CheckException(void);
|
||||||
|
|
||||||
|
boost::signal<void (const Stream::Ptr&)> OnConnected;
|
||||||
|
boost::signal<void (const Stream::Ptr&)> OnDataAvailable;
|
||||||
|
boost::signal<void (const Stream::Ptr&)> OnClosed;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetConnected(bool connected);
|
||||||
|
|
||||||
|
void SetException(boost::exception_ptr exception);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_Running;
|
||||||
|
bool m_Connected;
|
||||||
|
boost::exception_ptr m_Exception;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BIO *BIO_Stream_new(const Stream::Ptr& stream);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* IOQUEUE_H */
|
#endif /* STREAM_H */
|
|
@ -0,0 +1,121 @@
|
||||||
|
#include "i2-base.h"
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
int I2Stream_new(BIO *bi);
|
||||||
|
int I2Stream_free(BIO *bi);
|
||||||
|
int I2Stream_read(BIO *bi, char *out, int outl);
|
||||||
|
int I2Stream_write(BIO *bi, const char *in, int inl);
|
||||||
|
long I2Stream_ctrl(BIO *bi, int cmd, long num, void *ptr);
|
||||||
|
int I2Stream_gets(BIO *bi, char *buf, int size);
|
||||||
|
int I2Stream_puts(BIO *bi, const char *str);
|
||||||
|
|
||||||
|
#define BIO_TYPE_I2STREAM (99|0x0400|0x0100)
|
||||||
|
|
||||||
|
static BIO_METHOD I2Stream_method =
|
||||||
|
{
|
||||||
|
BIO_TYPE_I2STREAM,
|
||||||
|
"Icinga Stream",
|
||||||
|
I2Stream_write,
|
||||||
|
I2Stream_read,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
I2Stream_ctrl,
|
||||||
|
I2Stream_new,
|
||||||
|
I2Stream_free,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct I2Stream_bio_s
|
||||||
|
{
|
||||||
|
Stream::Ptr Stream;
|
||||||
|
boost::exception_ptr Exception;
|
||||||
|
} I2Stream_bio_t;
|
||||||
|
|
||||||
|
BIO_METHOD *BIO_s_I2Stream(void)
|
||||||
|
{
|
||||||
|
return &I2Stream_method;
|
||||||
|
}
|
||||||
|
|
||||||
|
BIO *icinga::BIO_new_I2Stream(const Stream::Ptr& stream)
|
||||||
|
{
|
||||||
|
BIO *bi = BIO_new(BIO_s_I2Stream());
|
||||||
|
|
||||||
|
if (bi == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||||
|
|
||||||
|
bp->Stream = stream;
|
||||||
|
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void icinga::I2Stream_check_exception(BIO *bi) {
|
||||||
|
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||||
|
|
||||||
|
if (bp->Exception) {
|
||||||
|
boost::exception_ptr ptr = bp->Exception;
|
||||||
|
bp->Exception = boost::exception_ptr();
|
||||||
|
rethrow_exception(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int I2Stream_new(BIO *bi)
|
||||||
|
{
|
||||||
|
bi->shutdown = 0;
|
||||||
|
bi->init = 1;
|
||||||
|
bi->num = -1;
|
||||||
|
bi->ptr = new I2Stream_bio_t;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int I2Stream_free(BIO *bi)
|
||||||
|
{
|
||||||
|
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||||
|
delete bp;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int I2Stream_read(BIO *bi, char *out, int outl)
|
||||||
|
{
|
||||||
|
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||||
|
|
||||||
|
size_t data_read;
|
||||||
|
|
||||||
|
BIO_clear_retry_flags(bi);
|
||||||
|
|
||||||
|
try {
|
||||||
|
data_read = bp->Stream->Read(out, outl);
|
||||||
|
} catch (...) {
|
||||||
|
bp->Exception = boost::current_exception();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_read == 0) {
|
||||||
|
BIO_set_retry_read(bi);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int I2Stream_write(BIO *bi, const char *in, int inl)
|
||||||
|
{
|
||||||
|
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||||
|
bp->Stream->Write(in, inl);
|
||||||
|
|
||||||
|
return inl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long I2Stream_ctrl(BIO *bi, int cmd, long num, void *ptr)
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
case BIO_CTRL_FLUSH:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,26 +17,15 @@
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef JSONRPCSERVER_H
|
#ifndef STREAMBIO_H
|
||||||
#define JSONRPCSERVER_H
|
#define STREAMBIO_H
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
BIO *BIO_new_I2Stream(const Stream::Ptr& stream);
|
||||||
* A JSON-RPC server.
|
void I2Stream_check_exception(BIO *bi);
|
||||||
*
|
|
||||||
* @ingroup remoting
|
|
||||||
*/
|
|
||||||
class I2_REMOTING_API JsonRpcServer : public TcpServer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef shared_ptr<JsonRpcServer> Ptr;
|
|
||||||
typedef weak_ptr<JsonRpcServer> WeakPtr;
|
|
||||||
|
|
||||||
JsonRpcServer(shared_ptr<SSL_CTX> sslContext);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* JSONRPCSERVER_H */
|
#endif /* STREAMBIO_H */
|
|
@ -1,256 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* Icinga 2 *
|
|
||||||
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or *
|
|
||||||
* modify it under the terms of the GNU General Public License *
|
|
||||||
* as published by the Free Software Foundation; either version 2 *
|
|
||||||
* of the License, or (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program; if not, write to the Free Software Foundation *
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "i2-base.h"
|
|
||||||
|
|
||||||
using namespace icinga;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the TcpClient class.
|
|
||||||
*
|
|
||||||
* @param role The role of the TCP client socket.
|
|
||||||
*/
|
|
||||||
TcpClient::TcpClient(TcpClientRole role)
|
|
||||||
: m_SendQueue(boost::make_shared<FIFO>()),
|
|
||||||
m_RecvQueue(boost::make_shared<FIFO>()),
|
|
||||||
m_Role(role)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the role of the socket.
|
|
||||||
*
|
|
||||||
* @returns The role.
|
|
||||||
*/
|
|
||||||
TcpClientRole TcpClient::GetRole(void) const
|
|
||||||
{
|
|
||||||
return m_Role;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a socket and connects to the specified node and service.
|
|
||||||
*
|
|
||||||
* @param node The node.
|
|
||||||
* @param service The service.
|
|
||||||
*/
|
|
||||||
void TcpClient::Connect(const String& node, const String& service)
|
|
||||||
{
|
|
||||||
m_Role = RoleOutbound;
|
|
||||||
|
|
||||||
addrinfo hints;
|
|
||||||
addrinfo *result;
|
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
|
||||||
|
|
||||||
int rc = getaddrinfo(node.CStr(), service.CStr(), &hints, &result);
|
|
||||||
|
|
||||||
if (rc < 0)
|
|
||||||
throw_exception(SocketException("getaddrinfo() failed", GetLastSocketError()));
|
|
||||||
|
|
||||||
int fd = INVALID_SOCKET;
|
|
||||||
|
|
||||||
for (addrinfo *info = result; info != NULL; info = info->ai_next) {
|
|
||||||
fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
|
|
||||||
|
|
||||||
if (fd == INVALID_SOCKET)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SetFD(fd);
|
|
||||||
|
|
||||||
rc = connect(fd, info->ai_addr, info->ai_addrlen);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (rc < 0 && WSAGetLastError() != WSAEWOULDBLOCK) {
|
|
||||||
#else /* _WIN32 */
|
|
||||||
if (rc < 0 && errno != EINPROGRESS) {
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
closesocket(fd);
|
|
||||||
SetFD(INVALID_SOCKET);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc >= 0) {
|
|
||||||
SetConnected(true);
|
|
||||||
OnConnected(GetSelf());
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
freeaddrinfo(result);
|
|
||||||
|
|
||||||
if (fd == INVALID_SOCKET)
|
|
||||||
throw_exception(runtime_error("Could not create a suitable socket."));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes data that is available for this socket.
|
|
||||||
*/
|
|
||||||
void TcpClient::HandleWritable(void)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char data[1024];
|
|
||||||
size_t count;
|
|
||||||
|
|
||||||
if (!IsConnected()) {
|
|
||||||
SetConnected(true);
|
|
||||||
Event::Post(boost::bind(boost::cref(OnConnected), GetSelf()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
count = m_SendQueue->GetAvailableBytes();
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (count > sizeof(data))
|
|
||||||
count = sizeof(data);
|
|
||||||
|
|
||||||
m_SendQueue->Peek(data, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = send(GetFD(), data, count, 0);
|
|
||||||
|
|
||||||
if (rc <= 0)
|
|
||||||
throw_exception(SocketException("send() failed", GetError()));
|
|
||||||
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
m_SendQueue->Read(NULL, rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements IOQueue::GetAvailableBytes.
|
|
||||||
*/
|
|
||||||
size_t TcpClient::GetAvailableBytes(void) const
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
return m_RecvQueue->GetAvailableBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements IOQueue::Peek.
|
|
||||||
*/
|
|
||||||
void TcpClient::Peek(void *buffer, size_t count)
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
m_RecvQueue->Peek(buffer, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements IOQueue::Read.
|
|
||||||
*/
|
|
||||||
void TcpClient::Read(void *buffer, size_t count)
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
m_RecvQueue->Read(buffer, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements IOQueue::Write.
|
|
||||||
*/
|
|
||||||
void TcpClient::Write(const void *buffer, size_t count)
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
m_SendQueue->Write(buffer, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes data that can be written for this socket.
|
|
||||||
*/
|
|
||||||
void TcpClient::HandleReadable(void)
|
|
||||||
{
|
|
||||||
if (!IsConnected()) {
|
|
||||||
SetConnected(true);
|
|
||||||
Event::Post(boost::bind(boost::cref(OnConnected), GetSelf()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
char data[1024];
|
|
||||||
int rc = recv(GetFD(), data, sizeof(data), 0);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (rc < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
|
||||||
#else /* _WIN32 */
|
|
||||||
if (rc < 0 && errno == EAGAIN)
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (rc <= 0)
|
|
||||||
throw_exception(SocketException("recv() failed", GetError()));
|
|
||||||
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
m_RecvQueue->Write(data, rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Event::Post(boost::bind(boost::ref(OnDataAvailable), GetSelf()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether data should be read for this socket.
|
|
||||||
*
|
|
||||||
* @returns true
|
|
||||||
*/
|
|
||||||
bool TcpClient::WantsToRead(void) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether data should be written for this socket.
|
|
||||||
*
|
|
||||||
* @returns true if data should be written, false otherwise.
|
|
||||||
*/
|
|
||||||
bool TcpClient::WantsToWrite(void) const
|
|
||||||
{
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
if (m_SendQueue->GetAvailableBytes() > 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (!IsConnected());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default factory function for TCP clients.
|
|
||||||
*
|
|
||||||
* @param role The role of the new client.
|
|
||||||
* @returns The new client.
|
|
||||||
*/
|
|
||||||
TcpClient::Ptr icinga::TcpClientFactory(TcpClientRole role)
|
|
||||||
{
|
|
||||||
return boost::make_shared<TcpClient>(role);
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* Icinga 2 *
|
|
||||||
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or *
|
|
||||||
* modify it under the terms of the GNU General Public License *
|
|
||||||
* as published by the Free Software Foundation; either version 2 *
|
|
||||||
* of the License, or (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program; if not, write to the Free Software Foundation *
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TCPCLIENT_H
|
|
||||||
#define TCPCLIENT_H
|
|
||||||
|
|
||||||
namespace icinga
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The role of a TCP client object.
|
|
||||||
*
|
|
||||||
* @ingroup base
|
|
||||||
*/
|
|
||||||
enum TcpClientRole
|
|
||||||
{
|
|
||||||
RoleInbound, /**< Inbound socket, i.e. one that was returned
|
|
||||||
from accept(). */
|
|
||||||
RoleOutbound /**< Outbound socket, i.e. one that is connect()'d to a
|
|
||||||
remote socket. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A TCP client connection.
|
|
||||||
*
|
|
||||||
* @ingroup base
|
|
||||||
*/
|
|
||||||
class I2_BASE_API TcpClient : public TcpSocket, public IOQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef shared_ptr<TcpClient> Ptr;
|
|
||||||
typedef weak_ptr<TcpClient> WeakPtr;
|
|
||||||
|
|
||||||
TcpClient(TcpClientRole role);
|
|
||||||
|
|
||||||
TcpClientRole GetRole(void) const;
|
|
||||||
|
|
||||||
void Connect(const String& node, const String& service);
|
|
||||||
|
|
||||||
boost::signal<void (const TcpClient::Ptr&)> OnConnected;
|
|
||||||
boost::signal<void (const TcpClient::Ptr&)> OnDataAvailable;
|
|
||||||
|
|
||||||
virtual size_t GetAvailableBytes(void) const;
|
|
||||||
virtual void Peek(void *buffer, size_t count);
|
|
||||||
virtual void Read(void *buffer, size_t count);
|
|
||||||
virtual void Write(const void *buffer, size_t count);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool WantsToRead(void) const;
|
|
||||||
virtual bool WantsToWrite(void) const;
|
|
||||||
|
|
||||||
virtual void HandleReadable(void);
|
|
||||||
virtual void HandleWritable(void);
|
|
||||||
|
|
||||||
mutable boost::mutex m_QueueMutex;
|
|
||||||
FIFO::Ptr m_SendQueue;
|
|
||||||
FIFO::Ptr m_RecvQueue;
|
|
||||||
|
|
||||||
private:
|
|
||||||
TcpClientRole m_Role;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new unconnected TcpClient object that has the specified
|
|
||||||
* connection role.
|
|
||||||
*
|
|
||||||
* @param role The role of the new object.
|
|
||||||
* @returns A new TcpClient object.
|
|
||||||
*/
|
|
||||||
TcpClient::Ptr TcpClientFactory(TcpClientRole role);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* TCPCLIENT_H */
|
|
|
@ -1,89 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* Icinga 2 *
|
|
||||||
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or *
|
|
||||||
* modify it under the terms of the GNU General Public License *
|
|
||||||
* as published by the Free Software Foundation; either version 2 *
|
|
||||||
* of the License, or (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program; if not, write to the Free Software Foundation *
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "i2-base.h"
|
|
||||||
|
|
||||||
using namespace icinga;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the TcpServer class.
|
|
||||||
*/
|
|
||||||
TcpServer::TcpServer(void)
|
|
||||||
: m_ClientFactory(boost::bind(&TcpClientFactory, RoleInbound))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the client factory.
|
|
||||||
*
|
|
||||||
* @param clientFactory The client factory function.
|
|
||||||
*/
|
|
||||||
void TcpServer::SetClientFactory(const TcpServer::ClientFactory& clientFactory)
|
|
||||||
{
|
|
||||||
m_ClientFactory = clientFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the client factory.
|
|
||||||
*
|
|
||||||
* @returns The client factory function.
|
|
||||||
*/
|
|
||||||
TcpServer::ClientFactory TcpServer::GetFactoryFunction(void) const
|
|
||||||
{
|
|
||||||
return m_ClientFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts listening for incoming client connections.
|
|
||||||
*/
|
|
||||||
void TcpServer::Listen(void)
|
|
||||||
{
|
|
||||||
if (listen(GetFD(), SOMAXCONN) < 0)
|
|
||||||
throw_exception(SocketException("listen() failed", GetError()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the TCP server wants to read (i.e. accept new clients).
|
|
||||||
*
|
|
||||||
* @returns true
|
|
||||||
*/
|
|
||||||
bool TcpServer::WantsToRead(void) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accepts a new client and creates a new client object for it
|
|
||||||
* using the client factory function.
|
|
||||||
*/
|
|
||||||
void TcpServer::HandleReadable(void)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
sockaddr_storage addr;
|
|
||||||
socklen_t addrlen = sizeof(addr);
|
|
||||||
|
|
||||||
fd = accept(GetFD(), (sockaddr *)&addr, &addrlen);
|
|
||||||
|
|
||||||
if (fd < 0)
|
|
||||||
throw_exception(SocketException("accept() failed", GetError()));
|
|
||||||
|
|
||||||
TcpClient::Ptr client = m_ClientFactory(fd);
|
|
||||||
|
|
||||||
Event::Post(boost::bind(boost::ref(OnNewClient), GetSelf(), client));
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,23 +21,6 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a socket.
|
|
||||||
*
|
|
||||||
* @param family The socket family for the new socket.
|
|
||||||
*/
|
|
||||||
void TcpSocket::MakeSocket(int family)
|
|
||||||
{
|
|
||||||
assert(GetFD() == INVALID_SOCKET);
|
|
||||||
|
|
||||||
int fd = socket(family, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
if (fd == INVALID_SOCKET)
|
|
||||||
throw_exception(SocketException("socket() failed", GetLastSocketError()));
|
|
||||||
|
|
||||||
SetFD(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a socket and binds it to the specified service.
|
* Creates a socket and binds it to the specified service.
|
||||||
*
|
*
|
||||||
|
@ -110,3 +93,61 @@ void TcpSocket::Bind(String node, String service, int family)
|
||||||
if (fd == INVALID_SOCKET)
|
if (fd == INVALID_SOCKET)
|
||||||
throw_exception(runtime_error("Could not create a suitable socket."));
|
throw_exception(runtime_error("Could not create a suitable socket."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a socket and connects to the specified node and service.
|
||||||
|
*
|
||||||
|
* @param node The node.
|
||||||
|
* @param service The service.
|
||||||
|
*/
|
||||||
|
void TcpSocket::Connect(const String& node, const String& service)
|
||||||
|
{
|
||||||
|
addrinfo hints;
|
||||||
|
addrinfo *result;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
|
|
||||||
|
int rc = getaddrinfo(node.CStr(), service.CStr(), &hints, &result);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
throw_exception(SocketException("getaddrinfo() failed", GetLastSocketError()));
|
||||||
|
|
||||||
|
int fd = INVALID_SOCKET;
|
||||||
|
|
||||||
|
for (addrinfo *info = result; info != NULL; info = info->ai_next) {
|
||||||
|
fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
|
||||||
|
|
||||||
|
if (fd == INVALID_SOCKET)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SetFD(fd);
|
||||||
|
|
||||||
|
rc = connect(fd, info->ai_addr, info->ai_addrlen);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (rc < 0 && WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||||
|
#else /* _WIN32 */
|
||||||
|
if (rc < 0 && errno != EINPROGRESS) {
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
closesocket(fd);
|
||||||
|
SetFD(INVALID_SOCKET);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc >= 0) {
|
||||||
|
SetConnected(true);
|
||||||
|
OnConnected(GetSelf());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(result);
|
||||||
|
|
||||||
|
if (fd == INVALID_SOCKET)
|
||||||
|
throw_exception(runtime_error("Could not create a suitable socket."));
|
||||||
|
}
|
||||||
|
|
|
@ -37,8 +37,7 @@ public:
|
||||||
void Bind(String service, int family);
|
void Bind(String service, int family);
|
||||||
void Bind(String node, String service, int family);
|
void Bind(String node, String service, int family);
|
||||||
|
|
||||||
private:
|
void Connect(const String& node, const String& service);
|
||||||
void MakeSocket(int family);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,21 +21,26 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
int I2_EXPORT TlsClient::m_SSLIndex;
|
int I2_EXPORT TlsStream::m_SSLIndex;
|
||||||
bool I2_EXPORT TlsClient::m_SSLIndexInitialized = false;
|
bool I2_EXPORT TlsStream::m_SSLIndexInitialized = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the TlsClient class.
|
* Constructor for the TlsStream class.
|
||||||
*
|
*
|
||||||
* @param role The role of the client.
|
* @param role The role of the client.
|
||||||
* @param sslContext The SSL context for the client.
|
* @param sslContext The SSL context for the client.
|
||||||
*/
|
*/
|
||||||
TlsClient::TlsClient(TcpClientRole role, shared_ptr<SSL_CTX> sslContext)
|
TlsStream::TlsStream(const Stream::Ptr& innerStream, TlsRole role, shared_ptr<SSL_CTX> sslContext)
|
||||||
: TcpClient(role), m_SSLContext(sslContext),
|
: m_InnerStream(innerStream), m_Role(role), m_SSLContext(sslContext),
|
||||||
m_BlockRead(false), m_BlockWrite(false)
|
m_SendQueue(boost::make_shared<FIFO>()), m_RecvQueue(boost::make_shared<FIFO>())
|
||||||
{ }
|
{
|
||||||
|
m_InnerStream->OnDataAvailable.connect(boost::bind(&TlsStream::DataAvailableHandler, this));
|
||||||
|
m_InnerStream->OnClosed.connect(boost::bind(&TlsStream::ClosedHandler, this));
|
||||||
|
m_SendQueue->Start();
|
||||||
|
m_RecvQueue->Start();
|
||||||
|
}
|
||||||
|
|
||||||
void TlsClient::Start(void)
|
void TlsStream::Start(void)
|
||||||
{
|
{
|
||||||
m_SSL = shared_ptr<SSL>(SSL_new(m_SSLContext.get()), SSL_free);
|
m_SSL = shared_ptr<SSL>(SSL_new(m_SSLContext.get()), SSL_free);
|
||||||
|
|
||||||
|
@ -48,7 +53,7 @@ void TlsClient::Start(void)
|
||||||
throw_exception(logic_error("No X509 client certificate was specified."));
|
throw_exception(logic_error("No X509 client certificate was specified."));
|
||||||
|
|
||||||
if (!m_SSLIndexInitialized) {
|
if (!m_SSLIndexInitialized) {
|
||||||
m_SSLIndex = SSL_get_ex_new_index(0, const_cast<char *>("TlsClient"), NULL, NULL, NULL);
|
m_SSLIndex = SSL_get_ex_new_index(0, const_cast<char *>("TlsStream"), NULL, NULL, NULL);
|
||||||
m_SSLIndexInitialized = true;
|
m_SSLIndexInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,21 +61,24 @@ void TlsClient::Start(void)
|
||||||
|
|
||||||
SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
|
SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
|
||||||
|
|
||||||
SSL_set_fd(m_SSL.get(), GetFD());
|
m_BIO = BIO_new_I2Stream(m_InnerStream);
|
||||||
|
SSL_set_bio(m_SSL.get(), m_BIO, m_BIO);
|
||||||
|
|
||||||
if (GetRole() == RoleInbound)
|
if (m_Role == TlsRoleServer)
|
||||||
SSL_set_accept_state(m_SSL.get());
|
SSL_set_accept_state(m_SSL.get());
|
||||||
else
|
else
|
||||||
SSL_set_connect_state(m_SSL.get());
|
SSL_set_connect_state(m_SSL.get());
|
||||||
|
|
||||||
int rc = SSL_do_handshake(m_SSL.get());
|
/*int rc = SSL_do_handshake(m_SSL.get());
|
||||||
|
|
||||||
if (rc == 1) {
|
if (rc == 1) {
|
||||||
SetConnected(true);
|
SetConnected(true);
|
||||||
OnConnected(GetSelf());
|
OnConnected(GetSelf());
|
||||||
}
|
}*/
|
||||||
|
|
||||||
Socket::Start();
|
Stream::Start();
|
||||||
|
|
||||||
|
HandleIO();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,10 +86,8 @@ void TlsClient::Start(void)
|
||||||
*
|
*
|
||||||
* @returns The X509 certificate.
|
* @returns The X509 certificate.
|
||||||
*/
|
*/
|
||||||
shared_ptr<X509> TlsClient::GetClientCertificate(void) const
|
shared_ptr<X509> TlsStream::GetClientCertificate(void) const
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_SocketMutex);
|
|
||||||
|
|
||||||
return shared_ptr<X509>(SSL_get_certificate(m_SSL.get()), &Utility::NullDeleter);
|
return shared_ptr<X509>(SSL_get_certificate(m_SSL.get()), &Utility::NullDeleter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,180 +96,146 @@ shared_ptr<X509> TlsClient::GetClientCertificate(void) const
|
||||||
*
|
*
|
||||||
* @returns The X509 certificate.
|
* @returns The X509 certificate.
|
||||||
*/
|
*/
|
||||||
shared_ptr<X509> TlsClient::GetPeerCertificate(void) const
|
shared_ptr<X509> TlsStream::GetPeerCertificate(void) const
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_SocketMutex);
|
|
||||||
|
|
||||||
return shared_ptr<X509>(SSL_get_peer_certificate(m_SSL.get()), X509_free);
|
return shared_ptr<X509>(SSL_get_peer_certificate(m_SSL.get()), X509_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void TlsStream::DataAvailableHandler(void)
|
||||||
* Processes data that is available for this socket.
|
|
||||||
*/
|
|
||||||
void TlsClient::HandleReadable(void)
|
|
||||||
{
|
{
|
||||||
m_BlockRead = false;
|
try {
|
||||||
m_BlockWrite = false;
|
HandleIO();
|
||||||
|
} catch (...) {
|
||||||
|
SetException(boost::current_exception());
|
||||||
|
|
||||||
for (;;) {
|
Close();
|
||||||
char data[1024];
|
}
|
||||||
int rc;
|
}
|
||||||
|
|
||||||
if (IsConnected()) {
|
void TlsStream::ClosedHandler(void)
|
||||||
rc = SSL_read(m_SSL.get(), data, sizeof(data));
|
{
|
||||||
|
SetException(m_InnerStream->GetException());
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes data for the stream.
|
||||||
|
*/
|
||||||
|
void TlsStream::HandleIO(void)
|
||||||
|
{
|
||||||
|
char data[16 * 1024];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!IsConnected()) {
|
||||||
|
rc = SSL_do_handshake(m_SSL.get());
|
||||||
|
|
||||||
|
if (rc == 1) {
|
||||||
|
SetConnected(true);
|
||||||
} else {
|
} else {
|
||||||
rc = SSL_do_handshake(m_SSL.get());
|
|
||||||
|
|
||||||
if (rc == 1) {
|
|
||||||
SetConnected(true);
|
|
||||||
Event::Post(boost::bind(boost::cref(OnConnected), GetSelf()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc <= 0) {
|
|
||||||
switch (SSL_get_error(m_SSL.get(), rc)) {
|
switch (SSL_get_error(m_SSL.get(), rc)) {
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
m_BlockRead = true;
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
goto post_event;
|
return;
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
CloseInternal(false);
|
Close();
|
||||||
goto post_event;
|
return;
|
||||||
default:
|
default:
|
||||||
|
I2Stream_check_exception(m_BIO);
|
||||||
|
throw_exception(OpenSSLException("SSL_do_handshake failed", ERR_get_error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool new_data = false, read_ok = true;
|
||||||
|
|
||||||
|
while (read_ok) {
|
||||||
|
rc = SSL_read(m_SSL.get(), data, sizeof(data));
|
||||||
|
|
||||||
|
if (rc > 0) {
|
||||||
|
m_RecvQueue->Write(data, rc);
|
||||||
|
new_data = true;
|
||||||
|
} else {
|
||||||
|
switch (SSL_get_error(m_SSL.get(), rc)) {
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
/* fall through */
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
read_ok = false;
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
I2Stream_check_exception(m_BIO);
|
||||||
throw_exception(OpenSSLException("SSL_read failed", ERR_get_error()));
|
throw_exception(OpenSSLException("SSL_read failed", ERR_get_error()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsConnected()) {
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
m_RecvQueue->Write(data, rc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
post_event:
|
if (new_data)
|
||||||
Event::Post(boost::bind(boost::ref(OnDataAvailable), GetSelf()));
|
OnDataAvailable(GetSelf());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
while (m_SendQueue->GetAvailableBytes() > 0) {
|
||||||
* Processes data that can be written for this socket.
|
size_t count = m_SendQueue->GetAvailableBytes();
|
||||||
*/
|
|
||||||
void TlsClient::HandleWritable(void)
|
|
||||||
{
|
|
||||||
m_BlockRead = false;
|
|
||||||
m_BlockWrite = false;
|
|
||||||
|
|
||||||
char data[1024];
|
if (count == 0)
|
||||||
size_t count;
|
break;
|
||||||
|
|
||||||
for (;;) {
|
if (count > sizeof(data))
|
||||||
int rc;
|
count = sizeof(data);
|
||||||
|
|
||||||
if (IsConnected()) {
|
m_SendQueue->Peek(data, count);
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
count = m_SendQueue->GetAvailableBytes();
|
rc = SSL_write(m_SSL.get(), (const char *)data, count);
|
||||||
|
|
||||||
if (count == 0)
|
if (rc > 0) {
|
||||||
break;
|
m_SendQueue->Read(NULL, rc);
|
||||||
|
|
||||||
if (count > sizeof(data))
|
|
||||||
count = sizeof(data);
|
|
||||||
|
|
||||||
m_SendQueue->Peek(data, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = SSL_write(m_SSL.get(), (const char *)data, count);
|
|
||||||
} else {
|
} else {
|
||||||
rc = SSL_do_handshake(m_SSL.get());
|
|
||||||
|
|
||||||
if (rc == 1) {
|
|
||||||
SetConnected(true);
|
|
||||||
Event::Post(boost::bind(boost::cref(OnConnected), GetSelf()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc <= 0) {
|
|
||||||
switch (SSL_get_error(m_SSL.get(), rc)) {
|
switch (SSL_get_error(m_SSL.get(), rc)) {
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
m_BlockWrite = true;
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
return;
|
return;
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
CloseInternal(false);
|
Close();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
I2Stream_check_exception(m_BIO);
|
||||||
throw_exception(OpenSSLException("SSL_write failed", ERR_get_error()));
|
throw_exception(OpenSSLException("SSL_write failed", ERR_get_error()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsConnected()) {
|
|
||||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
|
||||||
|
|
||||||
m_SendQueue->Read(NULL, rc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether data should be read for this socket.
|
* Closes the stream.
|
||||||
*
|
|
||||||
* @returns true if data should be read, false otherwise.
|
|
||||||
*/
|
*/
|
||||||
bool TlsClient::WantsToRead(void) const
|
void TlsStream::Close(void)
|
||||||
{
|
|
||||||
if (SSL_want_read(m_SSL.get()))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (m_BlockRead)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return TcpClient::WantsToRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether data should be written for this socket.
|
|
||||||
*
|
|
||||||
* @returns true if data should be written, false otherwise.
|
|
||||||
*/
|
|
||||||
bool TlsClient::WantsToWrite(void) const
|
|
||||||
{
|
|
||||||
if (SSL_want_write(m_SSL.get()))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (m_BlockWrite)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return TcpClient::WantsToWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the socket.
|
|
||||||
*
|
|
||||||
* @param from_dtor Whether this method was invoked from the destructor.
|
|
||||||
*/
|
|
||||||
void TlsClient::CloseInternal(bool from_dtor)
|
|
||||||
{
|
{
|
||||||
if (m_SSL)
|
if (m_SSL)
|
||||||
SSL_shutdown(m_SSL.get());
|
SSL_shutdown(m_SSL.get());
|
||||||
|
|
||||||
TcpClient::CloseInternal(from_dtor);
|
Stream::Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
size_t TlsStream::GetAvailableBytes(void) const
|
||||||
* Factory function for the TlsClient class.
|
|
||||||
*
|
|
||||||
* @param role The role of the TLS socket.
|
|
||||||
* @param sslContext The SSL context for the socket.
|
|
||||||
* @returns A new TLS socket.
|
|
||||||
*/
|
|
||||||
TcpClient::Ptr icinga::TlsClientFactory(TcpClientRole role, shared_ptr<SSL_CTX> sslContext)
|
|
||||||
{
|
{
|
||||||
return boost::make_shared<TlsClient>(role, sslContext);
|
return m_RecvQueue->GetAvailableBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t TlsStream::Peek(void *buffer, size_t count)
|
||||||
|
{
|
||||||
|
return m_RecvQueue->Peek(buffer, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t TlsStream::Read(void *buffer, size_t count)
|
||||||
|
{
|
||||||
|
return m_RecvQueue->Read(buffer, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TlsStream::Write(const void *buffer, size_t count)
|
||||||
|
{
|
||||||
|
m_SendQueue->Write(buffer, count);
|
||||||
|
|
||||||
|
HandleIO();
|
||||||
|
}
|
|
@ -17,53 +17,66 @@
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef TLSCLIENT_H
|
#ifndef TLSSTREAM_H
|
||||||
#define TLSCLIENT_H
|
#define TLSSTREAM_H
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TlsRoleClient,
|
||||||
|
TlsRoleServer
|
||||||
|
} TlsRole;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A TLS client connection.
|
* A TLS stream.
|
||||||
*
|
*
|
||||||
* @ingroup base
|
* @ingroup base
|
||||||
*/
|
*/
|
||||||
class I2_BASE_API TlsClient : public TcpClient
|
class I2_BASE_API TlsStream : public Stream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TlsClient(TcpClientRole role, shared_ptr<SSL_CTX> sslContext);
|
typedef shared_ptr<TlsStream> Ptr;
|
||||||
|
typedef weak_ptr<TlsStream> WeakPtr;
|
||||||
|
|
||||||
virtual void Start(void);
|
TlsStream(const Stream::Ptr& innerStream, TlsRole role, shared_ptr<SSL_CTX> sslContext);
|
||||||
|
|
||||||
shared_ptr<X509> GetClientCertificate(void) const;
|
shared_ptr<X509> GetClientCertificate(void) const;
|
||||||
shared_ptr<X509> GetPeerCertificate(void) const;
|
shared_ptr<X509> GetPeerCertificate(void) const;
|
||||||
|
|
||||||
|
void Start(void);
|
||||||
|
virtual void Close(void);
|
||||||
|
|
||||||
|
virtual size_t GetAvailableBytes(void) const;
|
||||||
|
virtual size_t Peek(void *buffer, size_t count);
|
||||||
|
virtual size_t Read(void *buffer, size_t count);
|
||||||
|
virtual void Write(const void *buffer, size_t count);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void HandleSSLError(void);
|
void DataAvailableHandler(void);
|
||||||
|
void ClosedHandler(void);
|
||||||
|
|
||||||
virtual bool WantsToRead(void) const;
|
void HandleIO(void);
|
||||||
virtual bool WantsToWrite(void) const;
|
|
||||||
|
|
||||||
virtual void HandleReadable(void);
|
|
||||||
virtual void HandleWritable(void);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<SSL_CTX> m_SSLContext;
|
shared_ptr<SSL_CTX> m_SSLContext;
|
||||||
shared_ptr<SSL> m_SSL;
|
shared_ptr<SSL> m_SSL;
|
||||||
|
BIO *m_BIO;
|
||||||
|
|
||||||
bool m_BlockRead;
|
FIFO::Ptr m_SendQueue;
|
||||||
bool m_BlockWrite;
|
FIFO::Ptr m_RecvQueue;
|
||||||
|
|
||||||
|
Stream::Ptr m_InnerStream;
|
||||||
|
TlsRole m_Role;
|
||||||
|
|
||||||
static int m_SSLIndex;
|
static int m_SSLIndex;
|
||||||
static bool m_SSLIndexInitialized;
|
static bool m_SSLIndexInitialized;
|
||||||
|
|
||||||
virtual void CloseInternal(bool from_dtor);
|
|
||||||
|
|
||||||
static void NullCertificateDeleter(X509 *certificate);
|
static void NullCertificateDeleter(X509 *certificate);
|
||||||
};
|
|
||||||
|
|
||||||
TcpClient::Ptr TlsClientFactory(TcpClientRole role, shared_ptr<SSL_CTX> sslContext);
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* TLSCLIENT_H */
|
#endif /* TLSSTREAM_H */
|
|
@ -10,10 +10,8 @@ libremoting_la_SOURCES = \
|
||||||
endpointmanager.cpp \
|
endpointmanager.cpp \
|
||||||
endpointmanager.h \
|
endpointmanager.h \
|
||||||
i2-remoting.h \
|
i2-remoting.h \
|
||||||
jsonrpcclient.cpp \
|
jsonrpcconnection.cpp \
|
||||||
jsonrpcclient.h \
|
jsonrpcconnection.h \
|
||||||
jsonrpcserver.cpp \
|
|
||||||
jsonrpcserver.h \
|
|
||||||
messagepart.cpp \
|
messagepart.cpp \
|
||||||
messagepart.h \
|
messagepart.h \
|
||||||
requestmessage.cpp \
|
requestmessage.cpp \
|
||||||
|
|
|
@ -111,37 +111,18 @@ bool Endpoint::IsConnected(void) const
|
||||||
if (IsLocalEndpoint()) {
|
if (IsLocalEndpoint()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
JsonRpcClient::Ptr client = GetClient();
|
JsonRpcConnection::Ptr client = GetClient();
|
||||||
|
|
||||||
return (client && client->IsConnected());
|
return (client && client->GetStream()->IsConnected());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JsonRpcConnection::Ptr Endpoint::GetClient(void) const
|
||||||
* Retrieves the address for the endpoint.
|
|
||||||
*
|
|
||||||
* @returns The endpoint's address.
|
|
||||||
*/
|
|
||||||
String Endpoint::GetAddress(void) const
|
|
||||||
{
|
|
||||||
if (IsLocalEndpoint()) {
|
|
||||||
return "local:" + GetName();
|
|
||||||
} else {
|
|
||||||
JsonRpcClient::Ptr client = GetClient();
|
|
||||||
|
|
||||||
if (!client || !client->IsConnected())
|
|
||||||
return "<disconnected endpoint>";
|
|
||||||
|
|
||||||
return client->GetPeerAddress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonRpcClient::Ptr Endpoint::GetClient(void) const
|
|
||||||
{
|
{
|
||||||
return Get("client");
|
return Get("client");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Endpoint::SetClient(const JsonRpcClient::Ptr& client)
|
void Endpoint::SetClient(const JsonRpcConnection::Ptr& client)
|
||||||
{
|
{
|
||||||
Set("client", client);
|
Set("client", client);
|
||||||
client->OnNewMessage.connect(boost::bind(&Endpoint::NewMessageHandler, this, _2));
|
client->OnNewMessage.connect(boost::bind(&Endpoint::NewMessageHandler, this, _2));
|
||||||
|
@ -337,14 +318,14 @@ void Endpoint::NewMessageHandler(const MessagePart& message)
|
||||||
|
|
||||||
void Endpoint::ClientClosedHandler(void)
|
void Endpoint::ClientClosedHandler(void)
|
||||||
{
|
{
|
||||||
try {
|
/*try {
|
||||||
GetClient()->CheckException();
|
GetClient()->CheckException();
|
||||||
} catch (const exception& ex) {
|
} catch (const exception& ex) {
|
||||||
stringstream message;
|
stringstream message;
|
||||||
message << "Error occured for JSON-RPC socket: Message=" << ex.what();
|
message << "Error occured for JSON-RPC socket: Message=" << ex.what();
|
||||||
|
|
||||||
Logger::Write(LogWarning, "jsonrpc", message.str());
|
Logger::Write(LogWarning, "jsonrpc", message.str());
|
||||||
}
|
}*/
|
||||||
|
|
||||||
Logger::Write(LogWarning, "jsonrpc", "Lost connection to endpoint: identity=" + GetName());
|
Logger::Write(LogWarning, "jsonrpc", "Lost connection to endpoint: identity=" + GetName());
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,8 @@ public:
|
||||||
static bool Exists(const String& name);
|
static bool Exists(const String& name);
|
||||||
static Endpoint::Ptr GetByName(const String& name);
|
static Endpoint::Ptr GetByName(const String& name);
|
||||||
|
|
||||||
String GetAddress(void) const;
|
JsonRpcConnection::Ptr GetClient(void) const;
|
||||||
|
void SetClient(const JsonRpcConnection::Ptr& client);
|
||||||
JsonRpcClient::Ptr GetClient(void) const;
|
|
||||||
void SetClient(const JsonRpcClient::Ptr& client);
|
|
||||||
|
|
||||||
void RegisterSubscription(const String& topic);
|
void RegisterSubscription(const String& topic);
|
||||||
void UnregisterSubscription(const String& topic);
|
void UnregisterSubscription(const String& topic);
|
||||||
|
|
|
@ -110,11 +110,11 @@ void EndpointManager::AddListener(const String& service)
|
||||||
s << "Adding new listener: port " << service;
|
s << "Adding new listener: port " << service;
|
||||||
Logger::Write(LogInformation, "icinga", s.str());
|
Logger::Write(LogInformation, "icinga", s.str());
|
||||||
|
|
||||||
JsonRpcServer::Ptr server = boost::make_shared<JsonRpcServer>(sslContext);
|
TcpSocket::Ptr server = boost::make_shared<TcpSocket>();
|
||||||
|
|
||||||
m_Servers.insert(server);
|
m_Servers.insert(server);
|
||||||
server->OnNewClient.connect(boost::bind(&EndpointManager::NewClientHandler,
|
server->OnNewClient.connect(boost::bind(&EndpointManager::NewClientHandler,
|
||||||
this, _2));
|
this, _2, TlsRoleServer));
|
||||||
|
|
||||||
server->Bind(service, AF_INET6);
|
server->Bind(service, AF_INET6);
|
||||||
server->Listen();
|
server->Listen();
|
||||||
|
@ -133,9 +133,9 @@ void EndpointManager::AddConnection(const String& node, const String& service) {
|
||||||
if (!sslContext)
|
if (!sslContext)
|
||||||
throw_exception(logic_error("SSL context is required for AddConnection()"));
|
throw_exception(logic_error("SSL context is required for AddConnection()"));
|
||||||
|
|
||||||
JsonRpcClient::Ptr client = boost::make_shared<JsonRpcClient>(RoleOutbound, sslContext);
|
TcpSocket::Ptr client = boost::make_shared<TcpSocket>();
|
||||||
client->Connect(node, service);
|
client->Connect(node, service);
|
||||||
NewClientHandler(client);
|
NewClientHandler(client, TlsRoleClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,27 +143,30 @@ void EndpointManager::AddConnection(const String& node, const String& service) {
|
||||||
*
|
*
|
||||||
* @param client The new client.
|
* @param client The new client.
|
||||||
*/
|
*/
|
||||||
void EndpointManager::NewClientHandler(const TcpClient::Ptr& client)
|
void EndpointManager::NewClientHandler(const Socket::Ptr& client, TlsRole role)
|
||||||
{
|
{
|
||||||
JsonRpcClient::Ptr jclient = static_pointer_cast<JsonRpcClient>(client);
|
String peerAddress = client->GetPeerAddress();
|
||||||
|
TlsStream::Ptr tlsStream = boost::make_shared<TlsStream>(client, role, GetSSLContext());
|
||||||
|
tlsStream->Start();
|
||||||
|
|
||||||
m_PendingClients.insert(jclient);
|
m_PendingClients.insert(tlsStream);
|
||||||
jclient->OnConnected.connect(boost::bind(&EndpointManager::ClientConnectedHandler, this, _1));
|
tlsStream->OnConnected.connect(boost::bind(&EndpointManager::ClientConnectedHandler, this, _1, peerAddress));
|
||||||
jclient->Start();
|
|
||||||
|
client->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndpointManager::ClientConnectedHandler(const TcpClient::Ptr& client)
|
void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client, const String& peerAddress)
|
||||||
{
|
{
|
||||||
JsonRpcClient::Ptr jclient = static_pointer_cast<JsonRpcClient>(client);
|
TlsStream::Ptr tlsStream = static_pointer_cast<TlsStream>(client);
|
||||||
|
JsonRpcConnection::Ptr jclient = boost::make_shared<JsonRpcConnection>(tlsStream);
|
||||||
|
|
||||||
Logger::Write(LogInformation, "icinga", "New client connection for " + jclient->GetPeerAddress());
|
m_PendingClients.erase(tlsStream);
|
||||||
|
|
||||||
m_PendingClients.erase(jclient);
|
|
||||||
|
|
||||||
shared_ptr<X509> cert = jclient->GetPeerCertificate();
|
|
||||||
|
|
||||||
|
shared_ptr<X509> cert = tlsStream->GetPeerCertificate();
|
||||||
String identity = Utility::GetCertificateCN(cert);
|
String identity = Utility::GetCertificateCN(cert);
|
||||||
|
|
||||||
|
Logger::Write(LogInformation, "icinga", "New client connection at " + peerAddress + " for identity '" + identity + "'");
|
||||||
|
|
||||||
Endpoint::Ptr endpoint;
|
Endpoint::Ptr endpoint;
|
||||||
|
|
||||||
if (Endpoint::Exists(identity))
|
if (Endpoint::Exists(identity))
|
||||||
|
|
|
@ -70,8 +70,8 @@ private:
|
||||||
|
|
||||||
Timer::Ptr m_ReconnectTimer;
|
Timer::Ptr m_ReconnectTimer;
|
||||||
|
|
||||||
set<JsonRpcServer::Ptr> m_Servers;
|
set<TcpSocket::Ptr> m_Servers;
|
||||||
set<JsonRpcClient::Ptr> m_PendingClients;
|
set<TlsStream::Ptr> m_PendingClients;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about a pending API request.
|
* Information about a pending API request.
|
||||||
|
@ -101,8 +101,8 @@ private:
|
||||||
|
|
||||||
void ReconnectTimerHandler(void);
|
void ReconnectTimerHandler(void);
|
||||||
|
|
||||||
void NewClientHandler(const TcpClient::Ptr& client);
|
void NewClientHandler(const Socket::Ptr& client, TlsRole rol);
|
||||||
void ClientConnectedHandler(const TcpClient::Ptr& client);
|
void ClientConnectedHandler(const Stream::Ptr& client, const String& peerAddress);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,7 @@
|
||||||
#include "messagepart.h"
|
#include "messagepart.h"
|
||||||
#include "requestmessage.h"
|
#include "requestmessage.h"
|
||||||
#include "responsemessage.h"
|
#include "responsemessage.h"
|
||||||
#include "jsonrpcclient.h"
|
#include "jsonrpcconnection.h"
|
||||||
#include "jsonrpcserver.h"
|
|
||||||
#include "endpoint.h"
|
#include "endpoint.h"
|
||||||
#include "endpointmanager.h"
|
#include "endpointmanager.h"
|
||||||
|
|
||||||
|
|
|
@ -22,39 +22,35 @@
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the JsonRpcClient class.
|
* Constructor for the JsonRpcConnection class.
|
||||||
*
|
*
|
||||||
* @param role The role of the underlying TCP client.
|
* @param stream The stream.
|
||||||
* @param sslContext SSL context for the TLS connection.
|
|
||||||
*/
|
*/
|
||||||
JsonRpcClient::JsonRpcClient(TcpClientRole role, shared_ptr<SSL_CTX> sslContext)
|
JsonRpcConnection::JsonRpcConnection(const Stream::Ptr& stream)
|
||||||
: TlsClient(role, sslContext)
|
: Connection(stream)
|
||||||
{
|
{ }
|
||||||
OnDataAvailable.connect(boost::bind(&JsonRpcClient::DataAvailableHandler,
|
|
||||||
this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to the connected peer.
|
* Sends a message to the connected peer.
|
||||||
*
|
*
|
||||||
* @param message The message.
|
* @param message The message.
|
||||||
*/
|
*/
|
||||||
void JsonRpcClient::SendMessage(const MessagePart& message)
|
void JsonRpcConnection::SendMessage(const MessagePart& message)
|
||||||
{
|
{
|
||||||
Value value = message.GetDictionary();
|
Value value = message.GetDictionary();
|
||||||
String json = value.Serialize();
|
String json = value.Serialize();
|
||||||
//std::cerr << ">> " << json << std::endl;
|
//std::cerr << ">> " << json << std::endl;
|
||||||
NetString::WriteStringToIOQueue(this, json);
|
NetString::WriteStringToStream(GetStream(), json);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes inbound data.
|
* Processes inbound data.
|
||||||
*/
|
*/
|
||||||
void JsonRpcClient::DataAvailableHandler(void)
|
void JsonRpcConnection::ProcessData(void)
|
||||||
{
|
{
|
||||||
String jsonString;
|
String jsonString;
|
||||||
|
|
||||||
while (NetString::ReadStringFromIOQueue(this, &jsonString)) {
|
while (NetString::ReadStringFromStream(GetStream(), &jsonString)) {
|
||||||
//std::cerr << "<< " << jsonString << std::endl;
|
//std::cerr << "<< " << jsonString << std::endl;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -73,20 +69,3 @@ void JsonRpcClient::DataAvailableHandler(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory function for JSON-RPC clients.
|
|
||||||
*
|
|
||||||
* @param fd The file descriptor.
|
|
||||||
* @param role The role of the underlying TCP client.
|
|
||||||
* @param sslContext SSL context for the TLS connection.
|
|
||||||
* @returns A new JSON-RPC client.
|
|
||||||
*/
|
|
||||||
JsonRpcClient::Ptr icinga::JsonRpcClientFactory(SOCKET fd, TcpClientRole role,
|
|
||||||
shared_ptr<SSL_CTX> sslContext)
|
|
||||||
{
|
|
||||||
JsonRpcClient::Ptr client = boost::make_shared<JsonRpcClient>(role,
|
|
||||||
sslContext);
|
|
||||||
client->SetFD(fd);
|
|
||||||
return client;
|
|
||||||
}
|
|
|
@ -17,37 +17,33 @@
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef JSONRPCCLIENT_H
|
#ifndef JSONRPCCONNECTION_H
|
||||||
#define JSONRPCCLIENT_H
|
#define JSONRPCCONNECTION_H
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSON-RPC client.
|
* A JSON-RPC connection.
|
||||||
*
|
*
|
||||||
* @ingroup remoting
|
* @ingroup remoting
|
||||||
*/
|
*/
|
||||||
class I2_REMOTING_API JsonRpcClient : public TlsClient
|
class I2_REMOTING_API JsonRpcConnection : public Connection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef shared_ptr<JsonRpcClient> Ptr;
|
typedef shared_ptr<JsonRpcConnection> Ptr;
|
||||||
typedef weak_ptr<JsonRpcClient> WeakPtr;
|
typedef weak_ptr<JsonRpcConnection> WeakPtr;
|
||||||
|
|
||||||
JsonRpcClient(TcpClientRole role, shared_ptr<SSL_CTX> sslContext);
|
JsonRpcConnection(const Stream::Ptr& stream);
|
||||||
|
|
||||||
void SendMessage(const MessagePart& message);
|
void SendMessage(const MessagePart& message);
|
||||||
|
|
||||||
boost::signal<void (const JsonRpcClient::Ptr&, const MessagePart&)> OnNewMessage;
|
boost::signal<void (const JsonRpcConnection::Ptr&, const MessagePart&)> OnNewMessage;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void DataAvailableHandler(void);
|
virtual void ProcessData(void);
|
||||||
|
|
||||||
friend JsonRpcClient::Ptr JsonRpcClientFactory(SOCKET fd, TcpClientRole role, shared_ptr<SSL_CTX> sslContext);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JsonRpcClient::Ptr JsonRpcClientFactory(SOCKET fd, TcpClientRole role, shared_ptr<SSL_CTX> sslContext);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* JSONRPCCLIENT_H */
|
#endif /* JSONRPCCONNECTION_H */
|
|
@ -22,10 +22,9 @@
|
||||||
<ClInclude Include="endpoint.h" />
|
<ClInclude Include="endpoint.h" />
|
||||||
<ClInclude Include="endpointmanager.h" />
|
<ClInclude Include="endpointmanager.h" />
|
||||||
<ClInclude Include="i2-remoting.h" />
|
<ClInclude Include="i2-remoting.h" />
|
||||||
<ClInclude Include="jsonrpcclient.h" />
|
<ClInclude Include="jsonrpcconnection.h" />
|
||||||
<ClInclude Include="requestmessage.h" />
|
<ClInclude Include="requestmessage.h" />
|
||||||
<ClInclude Include="responsemessage.h" />
|
<ClInclude Include="responsemessage.h" />
|
||||||
<ClInclude Include="jsonrpcserver.h" />
|
|
||||||
<ClInclude Include="messagepart.h" />
|
<ClInclude Include="messagepart.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -37,10 +36,9 @@
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="jsonrpcclient.cpp" />
|
<ClCompile Include="jsonrpcconnection.cpp" />
|
||||||
<ClCompile Include="requestmessage.cpp" />
|
<ClCompile Include="requestmessage.cpp" />
|
||||||
<ClCompile Include="responsemessage.cpp" />
|
<ClCompile Include="responsemessage.cpp" />
|
||||||
<ClCompile Include="jsonrpcserver.cpp" />
|
|
||||||
<ClCompile Include="messagepart.cpp" />
|
<ClCompile Include="messagepart.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="jsonrpcclient.cpp">
|
|
||||||
<Filter>Quelldateien</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="responsemessage.cpp">
|
<ClCompile Include="responsemessage.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="jsonrpcserver.cpp">
|
|
||||||
<Filter>Quelldateien</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="messagepart.cpp">
|
<ClCompile Include="messagepart.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -25,14 +19,11 @@
|
||||||
<ClCompile Include="endpointmanager.cpp">
|
<ClCompile Include="endpointmanager.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="jsonrpcconnection.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="jsonrpcclient.h">
|
|
||||||
<Filter>Headerdateien</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="jsonrpcserver.h">
|
|
||||||
<Filter>Headerdateien</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="messagepart.h">
|
<ClInclude Include="messagepart.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -51,6 +42,9 @@
|
||||||
<ClInclude Include="endpointmanager.h">
|
<ClInclude Include="endpointmanager.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="jsonrpcconnection.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Headerdateien">
|
<Filter Include="Headerdateien">
|
||||||
|
|
Loading…
Reference in New Issue