diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am
index 8fc1cc23d..5df39cb42 100644
--- a/lib/base/Makefile.am
+++ b/lib/base/Makefile.am
@@ -41,6 +41,8 @@ libbase_la_SOURCES = \
scripttask.h \
socket.cpp \
socket.h \
+ stdiostream.cpp \
+ stdiostream.h \
stream.cpp \
stream.h \
stream_bio.cpp \
@@ -56,6 +58,8 @@ libbase_la_SOURCES = \
tlsstream.cpp \
tlsstream.h \
unix.h \
+ unixsocket.cpp \
+ unixsocket.h \
utility.cpp \
utility.h \
value.cpp \
diff --git a/lib/base/base.vcxproj b/lib/base/base.vcxproj
index c877fbfa9..233c6bfeb 100644
--- a/lib/base/base.vcxproj
+++ b/lib/base/base.vcxproj
@@ -42,6 +42,7 @@
+
@@ -49,6 +50,7 @@
+
@@ -61,6 +63,7 @@
+
@@ -80,6 +83,7 @@
+
diff --git a/lib/base/base.vcxproj.filters b/lib/base/base.vcxproj.filters
index 0845ca949..912b4fe92 100644
--- a/lib/base/base.vcxproj.filters
+++ b/lib/base/base.vcxproj.filters
@@ -82,6 +82,12 @@
Quelldateien
+
+ Quelldateien
+
+
+ Quelldateien
+
@@ -174,6 +180,12 @@
Headerdateien
+
+ Headerdateien
+
+
+ Headerdateien
+
diff --git a/lib/base/dynamicobject.cpp b/lib/base/dynamicobject.cpp
index 734b9e93c..7be1d424f 100644
--- a/lib/base/dynamicobject.cpp
+++ b/lib/base/dynamicobject.cpp
@@ -361,14 +361,14 @@ void DynamicObject::DumpObjects(const String& filename)
String tempFilename = filename + ".tmp";
- ofstream fp;
- fp.open(tempFilename.CStr());
+ fstream fp;
+ fp.open(tempFilename.CStr(), std::ios_base::out);
if (!fp)
throw_exception(runtime_error("Could not open '" + filename + "' file"));
- FIFO::Ptr fifo = boost::make_shared();
- fifo->Start();
+ StdioStream::Ptr sfp = boost::make_shared(&fp, false);
+ sfp->Start();
DynamicObject::TypeMap::iterator tt;
for (tt = GetAllObjects().begin(); tt != GetAllObjects().end(); tt++) {
@@ -402,22 +402,22 @@ void DynamicObject::DumpObjects(const String& filename)
String json = value.Serialize();
/* This is quite ugly, unfortunatelly NetString requires an IOQueue object */
- NetString::WriteStringToStream(fifo, json);
+ NetString::WriteStringToStream(sfp, json);
size_t count;
- while ((count = fifo->GetAvailableBytes()) > 0) {
+ while ((count = sfp->GetAvailableBytes()) > 0) {
char buffer[1024];
if (count > sizeof(buffer))
count = sizeof(buffer);
- fifo->Read(buffer, count);
+ sfp->Read(buffer, count);
fp.write(buffer, count);
}
}
}
- fifo->Close();
+ sfp->Close();
fp.close();
@@ -433,23 +433,14 @@ void DynamicObject::RestoreObjects(const String& filename)
{
Logger::Write(LogInformation, "base", "Restoring program state from file '" + filename + "'");
- std::ifstream fp;
- fp.open(filename.CStr());
+ std::fstream fp;
+ fp.open(filename.CStr(), std::ios_base::in);
- /* TODO: Fix this horrible mess by implementing a class that provides
- * IOQueue functionality for files. */
- FIFO::Ptr fifo = boost::make_shared();
- fifo->Start();
-
- while (fp) {
- char buffer[1024];
-
- fp.read(buffer, sizeof(buffer));
- fifo->Write(buffer, fp.gcount());
- }
+ StdioStream::Ptr sfp = boost::make_shared(&fp, false);
+ sfp->Start();
String message;
- while (NetString::ReadStringFromStream(fifo, &message)) {
+ while (NetString::ReadStringFromStream(sfp, &message)) {
Dictionary::Ptr persistentObject = Value::Deserialize(message);
String type = persistentObject->Get("type");
@@ -468,7 +459,7 @@ void DynamicObject::RestoreObjects(const String& filename)
}
}
- fifo->Close();
+ sfp->Close();
}
void DynamicObject::DeactivateObjects(void)
diff --git a/lib/base/i2-base.h b/lib/base/i2-base.h
index 25940b0b7..c529d2850 100644
--- a/lib/base/i2-base.h
+++ b/lib/base/i2-base.h
@@ -103,8 +103,10 @@ using std::make_pair;
using std::stringstream;
using std::istream;
using std::ostream;
+using std::fstream;
using std::ifstream;
using std::ofstream;
+using std::iostream;
using std::exception;
using std::bad_alloc;
@@ -180,8 +182,10 @@ namespace tuples = boost::tuples;
#include "connection.h"
#include "netstring.h"
#include "fifo.h"
+#include "stdiostream.h"
#include "socket.h"
#include "tcpsocket.h"
+#include "unixsocket.h"
#include "tlsstream.h"
#include "asynctask.h"
#include "process.h"
diff --git a/lib/base/netstring.cpp b/lib/base/netstring.cpp
index 546aa79c3..3522cad99 100644
--- a/lib/base/netstring.cpp
+++ b/lib/base/netstring.cpp
@@ -47,7 +47,12 @@ bool NetString::ReadStringFromStream(const Stream::Ptr& stream, String *str)
if (buffer == NULL && buffer_length > 0)
throw_exception(bad_alloc());
- stream->Peek(buffer, buffer_length);
+ buffer_length = stream->Peek(buffer, buffer_length);
+
+ if (buffer_length < 3) {
+ free(buffer);
+ return false;
+ }
/* no leading zeros allowed */
if (buffer[0] == '0' && isdigit(buffer[1])) {
diff --git a/lib/base/socket.h b/lib/base/socket.h
index 0dad5d507..7d495987e 100644
--- a/lib/base/socket.h
+++ b/lib/base/socket.h
@@ -44,10 +44,10 @@ public:
bool IsConnected(void) const;
- 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);
+ virtual size_t GetAvailableBytes(void) const;
+ virtual size_t Read(void *buffer, size_t size);
+ virtual size_t Peek(void *buffer, size_t size);
+ virtual void Write(const void *buffer, size_t size);
void Listen(void);
diff --git a/lib/base/stdiostream.cpp b/lib/base/stdiostream.cpp
new file mode 100644
index 000000000..5cf4bd661
--- /dev/null
+++ b/lib/base/stdiostream.cpp
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * 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;
+
+StdioStream::StdioStream(iostream *innerStream, bool ownsStream)
+ : m_InnerStream(innerStream), m_OwnsStream(ownsStream),
+ m_ReadAheadBuffer(boost::make_shared())
+{
+ m_ReadAheadBuffer->Start();
+}
+
+StdioStream::~StdioStream(void)
+{
+ m_ReadAheadBuffer->Close();
+}
+
+void StdioStream::Start(void)
+{
+ SetConnected(true);
+
+ Stream::Start();
+}
+
+size_t StdioStream::GetAvailableBytes(void) const
+{
+ if (m_InnerStream->eof() && m_ReadAheadBuffer->GetAvailableBytes() == 0)
+ return 0;
+ else
+ return 1024; /* doesn't have to be accurate */
+}
+
+size_t StdioStream::Read(void *buffer, size_t size)
+{
+ size_t peek_len, read_len;
+
+ peek_len = m_ReadAheadBuffer->GetAvailableBytes();
+ peek_len = m_ReadAheadBuffer->Read(buffer, peek_len);
+
+ m_InnerStream->read(static_cast(buffer) + peek_len, size - peek_len);
+ read_len = m_InnerStream->gcount();
+
+ return peek_len + read_len;
+}
+
+size_t StdioStream::Peek(void *buffer, size_t size)
+{
+ size_t peek_len, read_len;
+
+ peek_len = m_ReadAheadBuffer->GetAvailableBytes();
+ peek_len = m_ReadAheadBuffer->Peek(buffer, peek_len);
+
+ m_InnerStream->read(static_cast(buffer) + peek_len, size - peek_len);
+ read_len = m_InnerStream->gcount();
+
+ m_ReadAheadBuffer->Write(static_cast(buffer) + peek_len, read_len);
+ return peek_len + read_len;
+}
+
+void StdioStream::Write(const void *buffer, size_t size)
+{
+ m_InnerStream->write(static_cast(buffer), size);
+}
+
+void StdioStream::Close(void)
+{
+ if (m_OwnsStream)
+ delete *m_InnerStream;
+
+ Stream::Close();
+}
diff --git a/lib/base/stdiostream.h b/lib/base/stdiostream.h
new file mode 100644
index 000000000..907073d1e
--- /dev/null
+++ b/lib/base/stdiostream.h
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * 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 STDIOSTREAM_H
+#define STDIOSTREAM_H
+
+namespace icinga {
+
+class StdioStream : public Stream
+{
+public:
+ typedef shared_ptr Ptr;
+ typedef weak_ptr WeakPtr;
+
+ StdioStream(iostream *innerStream, bool ownsStream);
+ ~StdioStream(void);
+
+ virtual void Start(void);
+
+ virtual size_t GetAvailableBytes(void) const;
+ virtual size_t Read(void *buffer, size_t size);
+ virtual size_t Peek(void *buffer, size_t size);
+ virtual void Write(const void *buffer, size_t size);
+
+ virtual void Close(void);
+
+private:
+ iostream *m_InnerStream;
+ bool m_OwnsStream;
+ FIFO::Ptr m_ReadAheadBuffer;
+};
+
+}
+
+#endif /* STDIOSTREAM_H */
\ No newline at end of file
diff --git a/lib/base/streamlogger.cpp b/lib/base/streamlogger.cpp
index 51266b0e4..f66e320a4 100644
--- a/lib/base/streamlogger.cpp
+++ b/lib/base/streamlogger.cpp
@@ -51,7 +51,7 @@ void StreamLogger::OpenFile(const String& filename)
ofstream *stream = new ofstream();
try {
- stream->open(filename.CStr(), ofstream::out | ofstream::trunc);
+ stream->open(filename.CStr(), fstream::out | fstream::trunc);
if (!stream->good())
throw_exception(runtime_error("Could not open logfile '" + filename + "'"));
diff --git a/lib/base/unixsocket.cpp b/lib/base/unixsocket.cpp
new file mode 100644
index 000000000..58d491620
--- /dev/null
+++ b/lib/base/unixsocket.cpp
@@ -0,0 +1,58 @@
+/******************************************************************************
+ * 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"
+
+#ifndef _WIN32
+using namespace icinga;
+
+UnixSocket::UnixSocket(void)
+{
+ int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+
+ if (fd < 0)
+ throw_exception(PosixException("socket() failed", errno));
+
+ SetFD(fd);
+}
+
+void UnixSocket::Bind(const String& path)
+{
+ unlink(path.CStr());
+
+ sockaddr_un sun = {};
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, path.CStr(), sizeof(sun.sun_path));
+ sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
+
+ if (bind(GetFD(), (sockaddr *)&sun, SUN_LEN(sun)) < 0)
+ throw_exception(PosixException("bind() failed", errno);
+}
+
+void UnixSocket::Connect(const String& path)
+{
+ sockaddr_un sun = {};
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, path.CStr(), sizeof(sun.sun_path));
+ sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
+
+ if (connect(GetFD(), (sockaddr *)&sun, SUN_LEN(sun)) < 0 && errno != EINPROGRESS)
+ throw_exception(PosixException("connect() failed", errno);
+}
+#endif /* _WIN32 */
\ No newline at end of file
diff --git a/lib/base/unixsocket.h b/lib/base/unixsocket.h
new file mode 100644
index 000000000..5535d1001
--- /dev/null
+++ b/lib/base/unixsocket.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ * 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 UNIXSOCKET_H
+#define UNIXSOCKET_H
+
+#ifndef _WIN32
+namespace icinga
+{
+
+class UnixSocket : public Socket
+{
+public:
+ typedef shared_ptr Ptr;
+ typedef weak_ptr WeakPtr;
+
+ void Bind(const String& path);
+
+ void Connect(const String& path);
+};
+
+}
+#endif /* _WIN32 */
+
+#endif /* UNIXSOCKET_H */
\ No newline at end of file