]> granicus.if.org Git - icinga2/commitdiff
Implemented the StdioStream and UnixSocket classes.
authorGunnar Beutner <gunnar@beutner.name>
Fri, 23 Nov 2012 10:02:34 +0000 (11:02 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Fri, 23 Nov 2012 10:03:33 +0000 (11:03 +0100)
12 files changed:
lib/base/Makefile.am
lib/base/base.vcxproj
lib/base/base.vcxproj.filters
lib/base/dynamicobject.cpp
lib/base/i2-base.h
lib/base/netstring.cpp
lib/base/socket.h
lib/base/stdiostream.cpp [new file with mode: 0644]
lib/base/stdiostream.h [new file with mode: 0644]
lib/base/streamlogger.cpp
lib/base/unixsocket.cpp [new file with mode: 0644]
lib/base/unixsocket.h [new file with mode: 0644]

index 8fc1cc23d731968e3d9ee64d1eaa44374bc0359f..5df39cb42b86094ea9c438603c8a3d253584521f 100644 (file)
@@ -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 \
index c877fbfa91f49889bdf3cb25d0445fb101b1cc60..233c6bfeb38f25982bcf83d5f555a0d1c9865d34 100644 (file)
@@ -42,6 +42,7 @@
     <ClCompile Include="scriptfunction.cpp" />
     <ClCompile Include="scripttask.cpp" />
     <ClCompile Include="socket.cpp" />
+    <ClCompile Include="stdiostream.cpp" />
     <ClCompile Include="stream.cpp" />
     <ClCompile Include="streamlogger.cpp" />
     <ClCompile Include="stream_bio.cpp" />
@@ -49,6 +50,7 @@
     <ClCompile Include="tcpsocket.cpp" />
     <ClCompile Include="timer.cpp" />
     <ClCompile Include="tlsstream.cpp" />
+    <ClCompile Include="unixsocket.cpp" />
     <ClCompile Include="utility.cpp" />
     <ClCompile Include="value.cpp" />
   </ItemGroup>
@@ -61,6 +63,7 @@
     <ClInclude Include="dictionary.h" />
     <ClInclude Include="event.h" />
     <ClInclude Include="fifo.h" />
+    <ClInclude Include="stdiostream.h" />
     <ClInclude Include="stream.h" />
     <ClInclude Include="netstring.h" />
     <ClInclude Include="qstring.h" />
@@ -80,6 +83,7 @@
     <ClInclude Include="timer.h" />
     <ClInclude Include="tlsstream.h" />
     <ClInclude Include="unix.h" />
+    <ClInclude Include="unixsocket.h" />
     <ClInclude Include="utility.h" />
     <ClInclude Include="value.h" />
     <ClInclude Include="win32.h" />
index 0845ca949ddd0676e25fdf75b6fc04f05ff5d7de..912b4fe92e7f5b2e9a40427a9a682f684bedd218 100644 (file)
     <ClCompile Include="connection.cpp">
       <Filter>Quelldateien</Filter>
     </ClCompile>
+    <ClCompile Include="unixsocket.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="stdiostream.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="application.h">
     <ClInclude Include="connection.h">
       <Filter>Headerdateien</Filter>
     </ClInclude>
+    <ClInclude Include="unixsocket.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="stdiostream.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Quelldateien">
index 734b9e93cd9a3abd71dbdaa37fc601c7574735cc..7be1d424f826015159b933a5e3721457de0e886f 100644 (file)
@@ -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>();
-       fifo->Start();
+       StdioStream::Ptr sfp = boost::make_shared<StdioStream>(&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>();
-       fifo->Start();
-
-       while (fp) {
-               char buffer[1024];
-
-               fp.read(buffer, sizeof(buffer));
-               fifo->Write(buffer, fp.gcount());
-       }
+       StdioStream::Ptr sfp = boost::make_shared<StdioStream>(&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)
index 25940b0b71ad514332ef00e343fca6a91ad4144a..c529d2850bc3d3d54a37e76cb42786db2ceeddd8 100644 (file)
@@ -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"
index 546aa79c3f1abd1b69dd0adeaba10d269aa9d5bc..3522cad99cb8f46f10ba843e82e23fdb5e445c12 100644 (file)
@@ -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])) {
index 0dad5d507f55c9bc6a996282041120934a9191c6..7d495987ebd4c8bdb675a3945db2ce23ea83bbf1 100644 (file)
@@ -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 (file)
index 0000000..5cf4bd6
--- /dev/null
@@ -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<FIFO>())
+{
+       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<char *>(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<char *>(buffer) + peek_len, size - peek_len);
+       read_len = m_InnerStream->gcount();
+
+       m_ReadAheadBuffer->Write(static_cast<char *>(buffer) + peek_len, read_len);
+       return peek_len + read_len;
+}
+
+void StdioStream::Write(const void *buffer, size_t size)
+{
+       m_InnerStream->write(static_cast<const char *>(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 (file)
index 0000000..907073d
--- /dev/null
@@ -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<StdioStream> Ptr;
+       typedef weak_ptr<StdioStream> 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
index 51266b0e4b29c75d8ef54d6abd0646cddf0d42ac..f66e320a4ed6d9543f519e485100b7405255ce6d 100644 (file)
@@ -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 (file)
index 0000000..58d4916
--- /dev/null
@@ -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 (file)
index 0000000..5535d10
--- /dev/null
@@ -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<UnixSocket> Ptr;
+       typedef weak_ptr<UnixSocket> WeakPtr;
+
+       void Bind(const String& path);
+
+       void Connect(const String& path);
+};
+
+}
+#endif /* _WIN32 */
+
+#endif /* UNIXSOCKET_H */
\ No newline at end of file