summaryrefslogtreecommitdiff
path: root/src/iodevice.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/iodevice.cc')
-rw-r--r--src/iodevice.cc283
1 files changed, 283 insertions, 0 deletions
diff --git a/src/iodevice.cc b/src/iodevice.cc
new file mode 100644
index 0000000..7197354
--- /dev/null
+++ b/src/iodevice.cc
@@ -0,0 +1,283 @@
+/** --------------------------------------------------------------------
+ * @file iodevice.cc
+ * @brief Implementation of the IODevice class.
+ * @author Andreas Aardal Hanssen
+ * @date 2002, 2003
+ * ----------------------------------------------------------------- **/
+#include "iodevice.h"
+#include "convert.h" // BincStream
+#include "session.h" // getEnv/hasEnv
+
+#include <stdlib.h>
+#include <unistd.h>
+
+using namespace ::std;
+using namespace ::Binc;
+
+//------------------------------------------------------------------------
+IODevice::IODevice(int f) : flags(f | IsEnabled),
+ maxInputBufferSize(0),
+ maxOutputBufferSize(0),
+ timeout(0),
+ readCount(0), writeCount(0),
+ outputLevel(ErrorLevel),
+ outputLevelLimit(ErrorLevel),
+ error(Unknown), errorString("Unknown device error"),
+ dumpfd(0)
+{
+}
+
+//------------------------------------------------------------------------
+IODevice::~IODevice(void)
+{
+}
+
+//------------------------------------------------------------------------
+IODevice &IODevice::operator <<(ostream &(*source)(ostream &))
+{
+ if (!(flags & IsEnabled) || outputLevel > outputLevelLimit)
+ return *this;
+
+ static std::ostream &(*endl_funcptr)(ostream &) = endl;
+
+ if (source != endl_funcptr) return *this;
+
+ outputBuffer << "\r\n";
+
+ if (dumpfd) ::write(dumpfd, "\r\n", 2);
+
+ if (flags & FlushesOnEndl)
+ flush();
+ else if (flags & HasOutputLimit)
+ if (outputBuffer.getSize() > maxOutputBufferSize)
+ flush();
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+bool IODevice::canRead(void) const
+{
+ return false;
+}
+
+//------------------------------------------------------------------------
+void IODevice::clear()
+{
+ if (!(flags & IsEnabled)) return;
+
+ inputBuffer.clear();
+ outputBuffer.clear();
+}
+
+//------------------------------------------------------------------------
+bool IODevice::flush()
+{
+ if (!(flags & IsEnabled)) return true;
+
+ WriteResult writeResult = WriteWait;
+ do {
+ unsigned int s = outputBuffer.getSize();
+ if (s == 0) break;
+ if (!waitForWrite()) return false;
+ writeResult = write();
+ if (writeResult == WriteError) return false;
+ writeCount += s - outputBuffer.getSize();
+ } while (outputBuffer.getSize() > 0 && writeResult == WriteWait);
+
+ outputBuffer.clear();
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+void IODevice::setFlags(unsigned int f)
+{
+ flags |= f;
+}
+
+//------------------------------------------------------------------------
+void IODevice::clearFlags(unsigned int f)
+{
+ flags &= ~f;
+}
+
+//------------------------------------------------------------------------
+void IODevice::setMaxInputBufferSize(unsigned int max)
+{
+ maxInputBufferSize = max;
+}
+
+//------------------------------------------------------------------------
+void IODevice::setMaxOutputBufferSize(unsigned int max)
+{
+ maxOutputBufferSize = max;
+}
+
+//------------------------------------------------------------------------
+void IODevice::setTimeout(unsigned int t)
+{
+ timeout = t;
+
+ if (t)
+ flags |= HasTimeout;
+ else
+ flags &= ~HasTimeout;
+}
+
+//------------------------------------------------------------------------
+unsigned int IODevice::getTimeout(void) const
+{
+ return timeout;
+}
+
+//------------------------------------------------------------------------
+void IODevice::setOutputLevel(LogLevel level)
+{
+ outputLevel = level;
+}
+
+//------------------------------------------------------------------------
+IODevice::LogLevel IODevice::getOutputLevel(void) const
+{
+ return outputLevel;
+}
+
+//------------------------------------------------------------------------
+void IODevice::setOutputLevelLimit(LogLevel level)
+{
+ outputLevelLimit = level;
+}
+
+//------------------------------------------------------------------------
+IODevice::LogLevel IODevice::getOutputLevelLimit(void) const
+{
+ return outputLevelLimit;
+}
+
+//------------------------------------------------------------------------
+bool IODevice::readStr(string *dest, unsigned int max)
+{
+ // If max is 0, fill the input buffer once only if it's empty.
+ if (!max && inputBuffer.getSize() == 0 && !fillInputBuffer()) return false;
+
+ // If max is != 0, wait until we have max.
+ while (max && inputBuffer.getSize() < max) {
+ if (!fillInputBuffer()) return false;
+ }
+
+ unsigned int bytesToRead = max ? max : inputBuffer.getSize();
+ *dest += inputBuffer.str().substr(0, bytesToRead);
+ if (dumpfd) {
+ ::write(dumpfd, inputBuffer.str().substr(0, bytesToRead).c_str(), bytesToRead);
+ }
+
+ inputBuffer.popString(bytesToRead);
+ readCount += bytesToRead;
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool IODevice::readChar(char *dest)
+{
+ if (inputBuffer.getSize() == 0 && !fillInputBuffer()) return false;
+
+ char c = inputBuffer.popChar();
+ if (dest) *dest = c;
+ if (dumpfd) ::write(dumpfd, &c, 1);
+
+ ++readCount;
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+void IODevice::unreadChar(char c)
+{
+ inputBuffer.unpopChar(c);
+}
+
+//------------------------------------------------------------------------
+void IODevice::unreadStr(const string &s)
+{
+ inputBuffer.unpopStr(s);
+}
+
+//------------------------------------------------------------------------
+bool IODevice::skipTo(char c)
+{
+ char dest = '\0';
+ do {
+ if (!readChar(&dest)) return false;
+ if (dumpfd) ::write(dumpfd, &dest, 1);
+ } while (c != dest);
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+string IODevice::service(void) const
+{
+ return "nul";
+}
+
+//------------------------------------------------------------------------
+bool IODevice::waitForWrite(void) const
+{
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool IODevice::waitForRead(void) const
+{
+ return false;
+}
+
+//------------------------------------------------------------------------
+IODevice::WriteResult IODevice::write(void)
+{
+ return WriteError;
+}
+
+//------------------------------------------------------------------------
+bool IODevice::fillInputBuffer(void)
+{
+ return false;
+}
+
+//------------------------------------------------------------------------
+IODevice::Error IODevice::getLastError(void) const
+{
+ return error;
+}
+
+//------------------------------------------------------------------------
+string IODevice::getLastErrorString(void) const
+{
+ return errorString;
+}
+
+//------------------------------------------------------------------------
+unsigned int IODevice::getReadCount(void) const
+{
+ return readCount;
+}
+
+//------------------------------------------------------------------------
+unsigned int IODevice::getWriteCount(void) const
+{
+ return writeCount;
+}
+
+//------------------------------------------------------------------------
+void IODevice::enableProtocolDumping(void)
+{
+ BincStream ss;
+ ss << "/tmp/bincimap-dump-" << (int) time(0) << "-"
+ << Session::getInstance().getIP() << "-XXXXXX";
+ char *safename = strdup(ss.str().c_str());
+ dumpfd = mkstemp(safename);
+ if (dumpfd == -1) dumpfd = 0;
+ delete[] safename;
+}