aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/vmime/net/imap/IMAPCommand.cpp2
-rw-r--r--src/vmime/net/imap/IMAPCommand.hpp2
-rw-r--r--src/vmime/net/imap/IMAPConnection.cpp26
-rw-r--r--src/vmime/net/imap/IMAPConnection.hpp5
-rw-r--r--src/vmime/net/imap/IMAPFolder.cpp3
-rw-r--r--src/vmime/net/imap/IMAPParser.hpp21
-rw-r--r--src/vmime/net/pop3/POP3Command.cpp33
-rw-r--r--src/vmime/net/pop3/POP3Command.hpp13
-rw-r--r--src/vmime/net/pop3/POP3Connection.cpp19
-rw-r--r--src/vmime/net/pop3/POP3Connection.hpp3
-rw-r--r--src/vmime/net/pop3/POP3Message.cpp2
-rw-r--r--src/vmime/net/pop3/POP3Response.cpp40
-rw-r--r--src/vmime/net/pop3/POP3Response.hpp6
-rw-r--r--src/vmime/net/service.cpp12
-rw-r--r--src/vmime/net/service.hpp8
-rw-r--r--src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp6
-rw-r--r--src/vmime/net/smtp/SMTPCommand.cpp23
-rw-r--r--src/vmime/net/smtp/SMTPCommand.hpp16
-rw-r--r--src/vmime/net/smtp/SMTPCommandSet.cpp23
-rw-r--r--src/vmime/net/smtp/SMTPCommandSet.hpp3
-rw-r--r--src/vmime/net/smtp/SMTPConnection.cpp23
-rw-r--r--src/vmime/net/smtp/SMTPConnection.hpp3
-rw-r--r--src/vmime/net/smtp/SMTPResponse.cpp16
-rw-r--r--src/vmime/net/smtp/SMTPResponse.hpp9
-rw-r--r--src/vmime/net/smtp/SMTPTransport.cpp14
-rw-r--r--src/vmime/net/tracer.cpp72
-rw-r--r--src/vmime/net/tracer.hpp109
27 files changed, 463 insertions, 49 deletions
diff --git a/src/vmime/net/imap/IMAPCommand.cpp b/src/vmime/net/imap/IMAPCommand.cpp
index 19c3b723..b1840d8d 100644
--- a/src/vmime/net/imap/IMAPCommand.cpp
+++ b/src/vmime/net/imap/IMAPCommand.cpp
@@ -56,7 +56,7 @@ shared_ptr <IMAPCommand> IMAPCommand::LOGIN(const string& username, const string
std::ostringstream trace;
trace.imbue(std::locale::classic());
- trace << "LOGIN <username> <password>";
+ trace << "LOGIN {username} {password}";
return createCommand(cmd.str(), trace.str());
}
diff --git a/src/vmime/net/imap/IMAPCommand.hpp b/src/vmime/net/imap/IMAPCommand.hpp
index c0a0d9b1..6003c227 100644
--- a/src/vmime/net/imap/IMAPCommand.hpp
+++ b/src/vmime/net/imap/IMAPCommand.hpp
@@ -98,7 +98,7 @@ public:
/** Returns the full text of the command, suitable for outputing
* to the tracer.
*
- * @return trace text (eg. "LOGIN myusername ***")
+ * @return trace text (eg. "LOGIN {username} {password}")
*/
virtual const string getTraceText() const;
diff --git a/src/vmime/net/imap/IMAPConnection.cpp b/src/vmime/net/imap/IMAPConnection.cpp
index 57f2ff5e..28a71662 100644
--- a/src/vmime/net/imap/IMAPConnection.cpp
+++ b/src/vmime/net/imap/IMAPConnection.cpp
@@ -71,10 +71,16 @@ IMAPConnection::IMAPConnection(shared_ptr <IMAPStore> store, shared_ptr <securit
m_hierarchySeparator('\0'), m_state(STATE_NONE), m_timeoutHandler(null),
m_secured(false), m_firstTag(true), m_capabilitiesFetched(false), m_noModSeq(false)
{
+ static int connectionId = 0;
+
m_tag = make_shared <IMAPTag>();
+ if (store->getTracerFactory())
+ m_tracer = store->getTracerFactory()->create(store, ++connectionId);
+
m_parser = make_shared <IMAPParser>();
m_parser->setTag(m_tag);
+ m_parser->setTracer(m_tracer);
}
@@ -439,6 +445,9 @@ void IMAPConnection::authenticateSASL()
const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n";
sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length());
+ if (m_tracer)
+ m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange");
+
// Server capabilities may change when logged in
invalidateCapabilities();
}
@@ -458,6 +467,9 @@ void IMAPConnection::authenticateSASL()
// Cancel SASL exchange
sendRaw(utility::stringUtils::bytesFromString("*\r\n"), 3);
+
+ if (m_tracer)
+ m_tracer->traceSend("*");
}
catch (...)
{
@@ -752,6 +764,14 @@ void IMAPConnection::sendCommand(shared_ptr <IMAPCommand> cmd)
m_socket->send("\r\n");
m_firstTag = false;
+
+ if (m_tracer)
+ {
+ std::ostringstream oss;
+ oss << string(*m_tag) << " " << cmd->getText();
+
+ m_tracer->traceSend(oss.str());
+ }
}
@@ -816,6 +836,12 @@ void IMAPConnection::setSocket(shared_ptr <socket> sok)
}
+shared_ptr <tracer> IMAPConnection::getTracer()
+{
+ return m_tracer;
+}
+
+
shared_ptr <IMAPTag> IMAPConnection::getTag()
{
return m_tag;
diff --git a/src/vmime/net/imap/IMAPConnection.hpp b/src/vmime/net/imap/IMAPConnection.hpp
index da1b9ba4..b863ce33 100644
--- a/src/vmime/net/imap/IMAPConnection.hpp
+++ b/src/vmime/net/imap/IMAPConnection.hpp
@@ -33,6 +33,7 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/tracer.hpp"
#include "vmime/net/session.hpp"
#include "vmime/net/connectionInfos.hpp"
@@ -105,6 +106,8 @@ public:
shared_ptr <const socket> getSocket() const;
void setSocket(shared_ptr <socket> sok);
+ shared_ptr <tracer> getTracer();
+
shared_ptr <IMAPTag> getTag();
bool isMODSEQDisabled() const;
@@ -151,6 +154,8 @@ private:
bool m_noModSeq;
+ shared_ptr <tracer> m_tracer;
+
void internalDisconnect();
diff --git a/src/vmime/net/imap/IMAPFolder.cpp b/src/vmime/net/imap/IMAPFolder.cpp
index e602ea6e..00fee93c 100644
--- a/src/vmime/net/imap/IMAPFolder.cpp
+++ b/src/vmime/net/imap/IMAPFolder.cpp
@@ -1124,6 +1124,9 @@ messageSet IMAPFolder::addMessage
m_connection->sendRaw(utility::stringUtils::bytesFromString("\r\n"), 2);
+ if (m_connection->getTracer())
+ m_connection->getTracer()->traceSendBytes(current);
+
if (progress)
progress->stop(total);
diff --git a/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp
index ba0ea195..d38ac14a 100644
--- a/src/vmime/net/imap/IMAPParser.hpp
+++ b/src/vmime/net/imap/IMAPParser.hpp
@@ -49,6 +49,7 @@
#include "vmime/net/timeoutHandler.hpp"
#include "vmime/net/socket.hpp"
+#include "vmime/net/tracer.hpp"
#include "vmime/net/imap/IMAPTag.hpp"
@@ -281,6 +282,15 @@ public:
m_timeoutHandler = toh;
}
+ /** Set the tracer currently used by this parser.
+ *
+ * @param tr tracer
+ */
+ void setTracer(shared_ptr <tracer> tr)
+ {
+ m_tracer = tr;
+ }
+
/** Set whether we operate in strict mode (this may not work
* with some servers which are not fully standard-compliant).
*
@@ -5687,6 +5697,7 @@ private:
weak_ptr <IMAPTag> m_tag;
weak_ptr <socket> m_socket;
+ shared_ptr <tracer> m_tracer;
utility::progressListener* m_progress;
@@ -5731,6 +5742,13 @@ public:
std::cout << std::endl << "Read line:" << std::endl << line << std::endl;
#endif
+ if (m_tracer)
+ {
+ string::size_type len = line.length();
+ while (len != 0 && (line[len - 1] == '\r' || line[len - 1] == '\n')) --len;
+ m_tracer->traceReceive(line.substr(0, len));
+ }
+
return (line);
}
@@ -5860,6 +5878,9 @@ public:
m_progress->progress(len, count);
}
+ if (m_tracer)
+ m_tracer->traceReceiveBytes(count);
+
if (m_progress)
m_progress->stop(count);
}
diff --git a/src/vmime/net/pop3/POP3Command.cpp b/src/vmime/net/pop3/POP3Command.cpp
index 3c544fc0..9dfaf17a 100644
--- a/src/vmime/net/pop3/POP3Command.cpp
+++ b/src/vmime/net/pop3/POP3Command.cpp
@@ -42,8 +42,8 @@ namespace net {
namespace pop3 {
-POP3Command::POP3Command(const string& text)
- : m_text(text)
+POP3Command::POP3Command(const string& text, const string& traceText)
+ : m_text(text), m_traceText(traceText)
{
}
@@ -109,7 +109,11 @@ shared_ptr <POP3Command> POP3Command::USER(const string& username)
cmd.imbue(std::locale::classic());
cmd << "USER " << username;
- return createCommand(cmd.str());
+ std::ostringstream trace;
+ trace.imbue(std::locale::classic());
+ trace << "USER {username}";
+
+ return createCommand(cmd.str(), trace.str());
}
@@ -120,7 +124,11 @@ shared_ptr <POP3Command> POP3Command::PASS(const string& password)
cmd.imbue(std::locale::classic());
cmd << "PASS " << password;
- return createCommand(cmd.str());
+ std::ostringstream trace;
+ trace.imbue(std::locale::classic());
+ trace << "PASS {password}";
+
+ return createCommand(cmd.str(), trace.str());
}
@@ -215,9 +223,13 @@ shared_ptr <POP3Command> POP3Command::QUIT()
// static
-shared_ptr <POP3Command> POP3Command::createCommand(const string& text)
+shared_ptr <POP3Command> POP3Command::createCommand
+ (const string& text, const string& traceText)
{
- return shared_ptr <POP3Command>(new POP3Command(text));
+ if (traceText.empty())
+ return shared_ptr <POP3Command>(new POP3Command(text, text));
+ else
+ return shared_ptr <POP3Command>(new POP3Command(text, traceText));
}
@@ -227,9 +239,18 @@ const string POP3Command::getText() const
}
+const string POP3Command::getTraceText() const
+{
+ return m_traceText;
+}
+
+
void POP3Command::send(shared_ptr <POP3Connection> conn)
{
conn->getSocket()->send(m_text + "\r\n");
+
+ if (conn->getTracer())
+ conn->getTracer()->traceSend(m_traceText);
}
diff --git a/src/vmime/net/pop3/POP3Command.hpp b/src/vmime/net/pop3/POP3Command.hpp
index e34e4e2b..45aff661 100644
--- a/src/vmime/net/pop3/POP3Command.hpp
+++ b/src/vmime/net/pop3/POP3Command.hpp
@@ -76,9 +76,10 @@ public:
/** Creates a new POP3 command with the specified text.
*
* @param text command text
+ * @param traceText trace text (if empty, command text is used)
* @return a new POP3Command object
*/
- static shared_ptr <POP3Command> createCommand(const string& text);
+ static shared_ptr <POP3Command> createCommand(const string& text, const string& traceText = "");
/** Sends this command over the specified connection.
*
@@ -93,14 +94,22 @@ public:
*/
virtual const string getText() const;
+ /** Returns the full text of the command, suitable for outputing
+ * to the tracer.
+ *
+ * @return trace text (eg. "USER myusername")
+ */
+ virtual const string getTraceText() const;
+
protected:
- POP3Command(const string& text);
+ POP3Command(const string& text, const string& traceText);
POP3Command(const POP3Command&);
private:
string m_text;
+ string m_traceText;
};
diff --git a/src/vmime/net/pop3/POP3Connection.cpp b/src/vmime/net/pop3/POP3Connection.cpp
index 45c668f5..0fd7e7ee 100644
--- a/src/vmime/net/pop3/POP3Connection.cpp
+++ b/src/vmime/net/pop3/POP3Connection.cpp
@@ -67,6 +67,10 @@ POP3Connection::POP3Connection(shared_ptr <POP3Store> store, shared_ptr <securit
: m_store(store), m_auth(auth), m_socket(null), m_timeoutHandler(null),
m_authenticated(false), m_secured(false), m_capabilitiesFetched(false)
{
+ static int connectionId = 0;
+
+ if (store->getTracerFactory())
+ m_tracer = store->getTracerFactory()->create(store, ++connectionId);
}
@@ -500,7 +504,11 @@ void POP3Connection::authenticateSASL()
(challenge, challengeLen, &resp, &respLen);
// Send response
- m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n");
+ const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n";
+ m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length());
+
+ if (m_tracer)
+ m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange");
}
catch (exceptions::sasl_exception& e)
{
@@ -518,6 +526,9 @@ void POP3Connection::authenticateSASL()
// Cancel SASL exchange
m_socket->send("*\r\n");
+
+ if (m_tracer)
+ m_tracer->traceSend("*");
}
catch (...)
{
@@ -677,6 +688,12 @@ shared_ptr <socket> POP3Connection::getSocket()
}
+shared_ptr <tracer> POP3Connection::getTracer()
+{
+ return m_tracer;
+}
+
+
shared_ptr <timeoutHandler> POP3Connection::getTimeoutHandler()
{
return m_timeoutHandler;
diff --git a/src/vmime/net/pop3/POP3Connection.hpp b/src/vmime/net/pop3/POP3Connection.hpp
index 3622f745..f40f9562 100644
--- a/src/vmime/net/pop3/POP3Connection.hpp
+++ b/src/vmime/net/pop3/POP3Connection.hpp
@@ -37,6 +37,7 @@
#include "vmime/net/timeoutHandler.hpp"
#include "vmime/net/session.hpp"
#include "vmime/net/connectionInfos.hpp"
+#include "vmime/net/tracer.hpp"
#include "vmime/net/pop3/POP3Command.hpp"
#include "vmime/net/pop3/POP3Response.hpp"
@@ -80,6 +81,7 @@ public:
virtual shared_ptr <timeoutHandler> getTimeoutHandler();
virtual shared_ptr <security::authenticator> getAuthenticator();
virtual shared_ptr <session> getSession();
+ virtual shared_ptr <tracer> getTracer();
private:
@@ -104,6 +106,7 @@ private:
shared_ptr <security::authenticator> m_auth;
shared_ptr <socket> m_socket;
shared_ptr <timeoutHandler> m_timeoutHandler;
+ shared_ptr <tracer> m_tracer;
bool m_authenticated;
bool m_secured;
diff --git a/src/vmime/net/pop3/POP3Message.cpp b/src/vmime/net/pop3/POP3Message.cpp
index ff1aa88f..0b7e6d37 100644
--- a/src/vmime/net/pop3/POP3Message.cpp
+++ b/src/vmime/net/pop3/POP3Message.cpp
@@ -149,7 +149,7 @@ void POP3Message::extract
try
{
POP3Response::readLargeResponse
- (store->getConnection(), os, progress, m_size);
+ (store->getConnection(), os, progress, m_size == -1 ? 0 : m_size);
}
catch (exceptions::command_error& e)
{
diff --git a/src/vmime/net/pop3/POP3Response.cpp b/src/vmime/net/pop3/POP3Response.cpp
index bdbfb23c..de3c2cf3 100644
--- a/src/vmime/net/pop3/POP3Response.cpp
+++ b/src/vmime/net/pop3/POP3Response.cpp
@@ -46,8 +46,8 @@ namespace net {
namespace pop3 {
-POP3Response::POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh)
- : m_socket(sok), m_timeoutHandler(toh)
+POP3Response::POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, shared_ptr <tracer> tracer)
+ : m_socket(sok), m_timeoutHandler(toh), m_tracer(tracer)
{
}
@@ -56,7 +56,7 @@ POP3Response::POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler>
shared_ptr <POP3Response> POP3Response::readResponse(shared_ptr <POP3Connection> conn)
{
shared_ptr <POP3Response> resp = shared_ptr <POP3Response>
- (new POP3Response(conn->getSocket(), conn->getTimeoutHandler()));
+ (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()));
string buffer;
resp->readResponseImpl(buffer, /* multiLine */ false);
@@ -65,6 +65,9 @@ shared_ptr <POP3Response> POP3Response::readResponse(shared_ptr <POP3Connection>
resp->m_code = getResponseCode(buffer);
stripResponseCode(buffer, resp->m_text);
+ if (resp->m_tracer)
+ resp->m_tracer->traceReceive(buffer);
+
return resp;
}
@@ -73,7 +76,7 @@ shared_ptr <POP3Response> POP3Response::readResponse(shared_ptr <POP3Connection>
shared_ptr <POP3Response> POP3Response::readMultilineResponse(shared_ptr <POP3Connection> conn)
{
shared_ptr <POP3Response> resp = shared_ptr <POP3Response>
- (new POP3Response(conn->getSocket(), conn->getTimeoutHandler()));
+ (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()));
string buffer;
resp->readResponseImpl(buffer, /* multiLine */ true);
@@ -88,8 +91,20 @@ shared_ptr <POP3Response> POP3Response::readMultilineResponse(shared_ptr <POP3Co
std::istringstream iss(nextLines);
string line;
+ if (resp->m_tracer)
+ resp->m_tracer->traceReceive(firstLine);
+
while (std::getline(iss, line, '\n'))
- resp->m_lines.push_back(utility::stringUtils::trim(line));
+ {
+ line = utility::stringUtils::trim(line);
+ resp->m_lines.push_back(line);
+
+ if (resp->m_tracer)
+ resp->m_tracer->traceReceive(line);
+ }
+
+ if (resp->m_tracer)
+ resp->m_tracer->traceReceive(".");
return resp;
}
@@ -101,15 +116,22 @@ shared_ptr <POP3Response> POP3Response::readLargeResponse
utility::progressListener* progress, const size_t predictedSize)
{
shared_ptr <POP3Response> resp = shared_ptr <POP3Response>
- (new POP3Response(conn->getSocket(), conn->getTimeoutHandler()));
+ (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()));
string firstLine;
- resp->readResponseImpl(firstLine, os, progress, predictedSize);
+ const size_t length = resp->readResponseImpl(firstLine, os, progress, predictedSize);
resp->m_firstLine = firstLine;
resp->m_code = getResponseCode(firstLine);
stripResponseCode(firstLine, resp->m_text);
+ if (resp->m_tracer)
+ {
+ resp->m_tracer->traceReceive(firstLine);
+ resp->m_tracer->traceReceiveBytes(length - firstLine.length());
+ resp->m_tracer->traceReceive(".");
+ }
+
return resp;
}
@@ -230,7 +252,7 @@ void POP3Response::readResponseImpl(string& buffer, const bool multiLine)
}
-void POP3Response::readResponseImpl
+size_t POP3Response::readResponseImpl
(string& firstLine, utility::outputStream& os,
utility::progressListener* progress, const size_t predictedSize)
{
@@ -327,6 +349,8 @@ void POP3Response::readResponseImpl
if (progress)
progress->stop(total);
+
+ return current;
}
diff --git a/src/vmime/net/pop3/POP3Response.hpp b/src/vmime/net/pop3/POP3Response.hpp
index 20477b5e..d85b5405 100644
--- a/src/vmime/net/pop3/POP3Response.hpp
+++ b/src/vmime/net/pop3/POP3Response.hpp
@@ -38,6 +38,7 @@
#include "vmime/utility/progressListener.hpp"
#include "vmime/net/socket.hpp"
+#include "vmime/net/tracer.hpp"
namespace vmime {
@@ -143,10 +144,10 @@ public:
private:
- POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh);
+ POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, shared_ptr <tracer> tracer);
void readResponseImpl(string& buffer, const bool multiLine);
- void readResponseImpl
+ size_t readResponseImpl
(string& firstLine, utility::outputStream& os,
utility::progressListener* progress, const size_t predictedSize);
@@ -163,6 +164,7 @@ private:
shared_ptr <socket> m_socket;
shared_ptr <timeoutHandler> m_timeoutHandler;
+ shared_ptr <tracer> m_tracer;
string m_firstLine;
ResponseCode m_code;
diff --git a/src/vmime/net/service.cpp b/src/vmime/net/service.cpp
index 482b141c..3cf94d5e 100644
--- a/src/vmime/net/service.cpp
+++ b/src/vmime/net/service.cpp
@@ -136,6 +136,18 @@ shared_ptr <socketFactory> service::getSocketFactory()
}
+void service::setTracerFactory(shared_ptr <tracerFactory> tf)
+{
+ m_tracerFactory = tf;
+}
+
+
+shared_ptr <tracerFactory> service::getTracerFactory()
+{
+ return m_tracerFactory;
+}
+
+
void service::setTimeoutHandlerFactory(shared_ptr <timeoutHandlerFactory> thf)
{
m_toHandlerFactory = thf;
diff --git a/src/vmime/net/service.hpp b/src/vmime/net/service.hpp
index 59352dea..b00d15ac 100644
--- a/src/vmime/net/service.hpp
+++ b/src/vmime/net/service.hpp
@@ -40,6 +40,7 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/tracer.hpp"
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/security/cert/certificateVerifier.hpp"
@@ -183,6 +184,11 @@ public:
*/
shared_ptr <timeoutHandlerFactory> getTimeoutHandlerFactory();
+
+ void setTracerFactory(shared_ptr <tracerFactory> tf);
+
+ shared_ptr <tracerFactory> getTracerFactory();
+
/** Set a property for this service (service prefix is added automatically).
*
* WARNING: this sets the property on the session object, so all service
@@ -219,8 +225,8 @@ private:
#endif // VMIME_HAVE_TLS_SUPPORT
shared_ptr <socketFactory> m_socketFactory;
-
shared_ptr <timeoutHandlerFactory> m_toHandlerFactory;
+ shared_ptr <tracerFactory> m_tracerFactory;
};
diff --git a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp
index 35ff4e0d..15e24cf1 100644
--- a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp
+++ b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp
@@ -73,6 +73,9 @@ void SMTPChunkingOutputStreamAdapter::sendChunk
m_progress->progress(m_totalSent, m_totalSize);
}
+ if (m_connection->getTracer())
+ m_connection->getTracer()->traceSendBytes(count);
+
// If PIPELINING is not supported, read one response for this BDAT command
if (!m_connection->hasExtension("PIPELINING"))
{
@@ -143,6 +146,9 @@ void SMTPChunkingOutputStreamAdapter::flush()
if (m_progress)
m_progress->stop(m_totalSize);
+
+ if (m_connection->getTracer())
+ m_connection->getTracer()->traceSendBytes(m_bufferSize);
}
diff --git a/src/vmime/net/smtp/SMTPCommand.cpp b/src/vmime/net/smtp/SMTPCommand.cpp
index 2120caf5..27c8ec1b 100644
--- a/src/vmime/net/smtp/SMTPCommand.cpp
+++ b/src/vmime/net/smtp/SMTPCommand.cpp
@@ -30,6 +30,7 @@
#include "vmime/net/smtp/SMTPCommand.hpp"
#include "vmime/net/socket.hpp"
+#include "vmime/net/tracer.hpp"
#include "vmime/mailbox.hpp"
#include "vmime/utility/outputStreamAdapter.hpp"
@@ -40,8 +41,8 @@ namespace net {
namespace smtp {
-SMTPCommand::SMTPCommand(const string& text)
- : m_text(text)
+SMTPCommand::SMTPCommand(const string& text, const string& traceText)
+ : m_text(text), m_traceText(traceText)
{
}
@@ -199,9 +200,12 @@ shared_ptr <SMTPCommand> SMTPCommand::QUIT()
// static
-shared_ptr <SMTPCommand> SMTPCommand::createCommand(const string& text)
+shared_ptr <SMTPCommand> SMTPCommand::createCommand(const string& text, const string& traceText)
{
- return shared_ptr <SMTPCommand>(new SMTPCommand(text));
+ if (traceText.empty())
+ return shared_ptr <SMTPCommand>(new SMTPCommand(text, text));
+ else
+ return shared_ptr <SMTPCommand>(new SMTPCommand(text, traceText));
}
@@ -211,9 +215,18 @@ const string SMTPCommand::getText() const
}
-void SMTPCommand::writeToSocket(shared_ptr <socket> sok)
+const string SMTPCommand::getTraceText() const
+{
+ return m_traceText;
+}
+
+
+void SMTPCommand::writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr)
{
sok->send(m_text + "\r\n");
+
+ if (tr)
+ tr->traceSend(m_traceText);
}
diff --git a/src/vmime/net/smtp/SMTPCommand.hpp b/src/vmime/net/smtp/SMTPCommand.hpp
index a5b8cca5..7c00d156 100644
--- a/src/vmime/net/smtp/SMTPCommand.hpp
+++ b/src/vmime/net/smtp/SMTPCommand.hpp
@@ -46,6 +46,7 @@ namespace net {
class socket;
class timeoutHandler;
+class tracer;
namespace smtp {
@@ -76,13 +77,14 @@ public:
* @param text command text
* @return a new SMTPCommand object
*/
- static shared_ptr <SMTPCommand> createCommand(const string& text);
+ static shared_ptr <SMTPCommand> createCommand(const string& text, const string& traceText = "");
/** Sends this command to the specified socket.
*
* @param sok socket to which the command will be written
+ * @param tr tracer
*/
- virtual void writeToSocket(shared_ptr <socket> sok);
+ virtual void writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr);
/** Returns the full text of the command, including command name
* and parameters (if any).
@@ -91,14 +93,22 @@ public:
*/
virtual const string getText() const;
+ /** Returns the full text of the command, suitable for outputing
+ * to the tracer.
+ *
+ * @return trace text (eg. "LOGIN myusername ***")
+ */
+ virtual const string getTraceText() const;
+
protected:
- SMTPCommand(const string& text);
+ SMTPCommand(const string& text, const string& traceText);
SMTPCommand(const SMTPCommand&);
private:
string m_text;
+ string m_traceText;
};
diff --git a/src/vmime/net/smtp/SMTPCommandSet.cpp b/src/vmime/net/smtp/SMTPCommandSet.cpp
index 3e03427c..85f58fed 100644
--- a/src/vmime/net/smtp/SMTPCommandSet.cpp
+++ b/src/vmime/net/smtp/SMTPCommandSet.cpp
@@ -42,7 +42,7 @@ namespace smtp {
SMTPCommandSet::SMTPCommandSet(const bool pipeline)
- : SMTPCommand(""), m_pipeline(pipeline),
+ : SMTPCommand("", ""), m_pipeline(pipeline),
m_started(false), m_lastCommandSent()
{
}
@@ -67,7 +67,7 @@ void SMTPCommandSet::addCommand(shared_ptr <SMTPCommand> cmd)
}
-void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok)
+void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr)
{
if (m_pipeline)
{
@@ -78,7 +78,7 @@ void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok)
it != m_commands.end() ; ++it)
{
shared_ptr <SMTPCommand> cmd = *it;
- cmd->writeToSocket(sok);
+ cmd->writeToSocket(sok, tr);
}
}
@@ -99,7 +99,7 @@ void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok)
shared_ptr <SMTPCommand> cmd = m_commands.front();
m_commands.pop_front();
- cmd->writeToSocket(sok);
+ cmd->writeToSocket(sok, tr);
m_lastCommandSent = cmd;
}
@@ -124,6 +124,21 @@ const string SMTPCommandSet::getText() const
}
+const string SMTPCommandSet::getTraceText() const
+{
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+
+ for (std::list <shared_ptr <SMTPCommand> >::const_iterator it = m_commands.begin() ;
+ it != m_commands.end() ; ++it)
+ {
+ cmd << (*it)->getTraceText() << "\r\n";
+ }
+
+ return cmd.str();
+}
+
+
bool SMTPCommandSet::isFinished() const
{
return (m_pipeline && m_started) || (m_commands.size() == 0 && m_started);
diff --git a/src/vmime/net/smtp/SMTPCommandSet.hpp b/src/vmime/net/smtp/SMTPCommandSet.hpp
index 8e744c2b..83c7fe46 100644
--- a/src/vmime/net/smtp/SMTPCommandSet.hpp
+++ b/src/vmime/net/smtp/SMTPCommandSet.hpp
@@ -78,9 +78,10 @@ public:
shared_ptr <SMTPCommand> getLastCommandSent() const;
- void writeToSocket(shared_ptr <socket> sok);
+ void writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr);
const string getText() const;
+ const string getTraceText() const;
private:
diff --git a/src/vmime/net/smtp/SMTPConnection.cpp b/src/vmime/net/smtp/SMTPConnection.cpp
index 4985b563..99a8e8f5 100644
--- a/src/vmime/net/smtp/SMTPConnection.cpp
+++ b/src/vmime/net/smtp/SMTPConnection.cpp
@@ -68,6 +68,10 @@ SMTPConnection::SMTPConnection(shared_ptr <SMTPTransport> transport, shared_ptr
: m_transport(transport), m_auth(auth), m_socket(null), m_timeoutHandler(null),
m_authenticated(false), m_secured(false), m_extendedSMTP(false)
{
+ static int connectionId = 0;
+
+ if (transport->getTracerFactory())
+ m_tracer = transport->getTracerFactory()->create(transport, ++connectionId);
}
@@ -416,7 +420,11 @@ void SMTPConnection::authenticateSASL()
(challenge, challengeLen, &resp, &respLen);
// Send response
- m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n");
+ const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n";
+ m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length());
+
+ if (m_tracer)
+ m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange");
}
catch (exceptions::sasl_exception& e)
{
@@ -434,6 +442,9 @@ void SMTPConnection::authenticateSASL()
// Cancel SASL exchange
m_socket->send("*\r\n");
+
+ if (m_tracer)
+ m_tracer->traceSend("*");
}
catch (...)
{
@@ -557,14 +568,14 @@ void SMTPConnection::internalDisconnect()
void SMTPConnection::sendRequest(shared_ptr <SMTPCommand> cmd)
{
- cmd->writeToSocket(m_socket);
+ cmd->writeToSocket(m_socket, m_tracer);
}
shared_ptr <SMTPResponse> SMTPConnection::readResponse()
{
shared_ptr <SMTPResponse> resp = SMTPResponse::readResponse
- (m_socket, m_timeoutHandler, m_responseState);
+ (m_tracer, m_socket, m_timeoutHandler, m_responseState);
m_responseState = resp->getCurrentState();
@@ -608,6 +619,12 @@ shared_ptr <socket> SMTPConnection::getSocket()
}
+shared_ptr <tracer> SMTPConnection::getTracer()
+{
+ return m_tracer;
+}
+
+
shared_ptr <timeoutHandler> SMTPConnection::getTimeoutHandler()
{
return m_timeoutHandler;
diff --git a/src/vmime/net/smtp/SMTPConnection.hpp b/src/vmime/net/smtp/SMTPConnection.hpp
index cc59ef34..c7614920 100644
--- a/src/vmime/net/smtp/SMTPConnection.hpp
+++ b/src/vmime/net/smtp/SMTPConnection.hpp
@@ -37,6 +37,7 @@
#include "vmime/net/timeoutHandler.hpp"
#include "vmime/net/session.hpp"
#include "vmime/net/connectionInfos.hpp"
+#include "vmime/net/tracer.hpp"
#include "vmime/net/smtp/SMTPCommand.hpp"
#include "vmime/net/smtp/SMTPResponse.hpp"
@@ -80,6 +81,7 @@ public:
virtual shared_ptr <timeoutHandler> getTimeoutHandler();
virtual shared_ptr <security::authenticator> getAuthenticator();
virtual shared_ptr <session> getSession();
+ virtual shared_ptr <tracer> getTracer();
void sendRequest(shared_ptr <SMTPCommand> cmd);
shared_ptr <SMTPResponse> readResponse();
@@ -106,6 +108,7 @@ private:
shared_ptr <security::authenticator> m_auth;
shared_ptr <socket> m_socket;
shared_ptr <timeoutHandler> m_timeoutHandler;
+ shared_ptr <tracer> m_tracer;
SMTPResponse::state m_responseState;
diff --git a/src/vmime/net/smtp/SMTPResponse.cpp b/src/vmime/net/smtp/SMTPResponse.cpp
index 3d8bf15c..75dbbf6b 100644
--- a/src/vmime/net/smtp/SMTPResponse.cpp
+++ b/src/vmime/net/smtp/SMTPResponse.cpp
@@ -34,6 +34,7 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/tracer.hpp"
#include <cctype>
@@ -43,8 +44,10 @@ namespace net {
namespace smtp {
-SMTPResponse::SMTPResponse(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st)
- : m_socket(sok), m_timeoutHandler(toh),
+SMTPResponse::SMTPResponse
+ (shared_ptr <tracer> tr, shared_ptr <socket> sok,
+ shared_ptr <timeoutHandler> toh, const state& st)
+ : m_socket(sok), m_timeoutHandler(toh), m_tracer(tr),
m_responseBuffer(st.responseBuffer), m_responseContinues(false)
{
}
@@ -95,9 +98,11 @@ const string SMTPResponse::getText() const
// static
shared_ptr <SMTPResponse> SMTPResponse::readResponse
- (shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st)
+ (shared_ptr <tracer> tr, shared_ptr <socket> sok,
+ shared_ptr <timeoutHandler> toh, const state& st)
{
- shared_ptr <SMTPResponse> resp = shared_ptr <SMTPResponse>(new SMTPResponse(sok, toh, st));
+ shared_ptr <SMTPResponse> resp =
+ shared_ptr <SMTPResponse>(new SMTPResponse(tr, sok, toh, st));
resp->readResponse();
@@ -142,6 +147,9 @@ const string SMTPResponse::readResponseLine()
currentBuffer.erase(currentBuffer.begin(), currentBuffer.begin() + lineEnd + 1);
m_responseBuffer = currentBuffer;
+ if (m_tracer)
+ m_tracer->traceReceive(line);
+
return line;
}
diff --git a/src/vmime/net/smtp/SMTPResponse.hpp b/src/vmime/net/smtp/SMTPResponse.hpp
index 000448ac..4d88b6b5 100644
--- a/src/vmime/net/smtp/SMTPResponse.hpp
+++ b/src/vmime/net/smtp/SMTPResponse.hpp
@@ -41,6 +41,7 @@ namespace net {
class socket;
class timeoutHandler;
+class tracer;
namespace smtp {
@@ -95,6 +96,7 @@ public:
/** Receive and parse a new SMTP response from the
* specified socket.
*
+ * @param tr tracer
* @param sok socket from which to read
* @param toh time-out handler
* @param st previous state of response parser for the specified socket
@@ -102,7 +104,9 @@ public:
* @throws exceptions::operation_timed_out if no data
* has been received within the granted time
*/
- static shared_ptr <SMTPResponse> readResponse(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st);
+ static shared_ptr <SMTPResponse> readResponse
+ (shared_ptr <tracer> tr, shared_ptr <socket> sok,
+ shared_ptr <timeoutHandler> toh, const state& st);
/** Return the SMTP response code.
*
@@ -150,7 +154,7 @@ public:
private:
- SMTPResponse(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st);
+ SMTPResponse(shared_ptr <tracer> tr, shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st);
SMTPResponse(const SMTPResponse&);
void readResponse();
@@ -166,6 +170,7 @@ private:
shared_ptr <socket> m_socket;
shared_ptr <timeoutHandler> m_timeoutHandler;
+ shared_ptr <tracer> m_tracer;
string m_responseBuffer;
bool m_responseContinues;
diff --git a/src/vmime/net/smtp/SMTPTransport.cpp b/src/vmime/net/smtp/SMTPTransport.cpp
index 56adfa21..ed775442 100644
--- a/src/vmime/net/smtp/SMTPTransport.cpp
+++ b/src/vmime/net/smtp/SMTPTransport.cpp
@@ -210,7 +210,7 @@ void SMTPTransport::sendEnvelope
// Read response for "RSET" command
if (needReset)
{
- commands->writeToSocket(m_connection->getSocket());
+ commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
resp = m_connection->readResponse();
@@ -227,7 +227,7 @@ void SMTPTransport::sendEnvelope
}
// Read response for "MAIL" command
- commands->writeToSocket(m_connection->getSocket());
+ commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
if ((resp = m_connection->readResponse())->getCode() != 250)
{
@@ -257,7 +257,7 @@ void SMTPTransport::sendEnvelope
// Read responses for "RCPT TO" commands
for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i)
{
- commands->writeToSocket(m_connection->getSocket());
+ commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
resp = m_connection->readResponse();
@@ -291,7 +291,7 @@ void SMTPTransport::sendEnvelope
// Read response for "DATA" command
if (sendDATACommand)
{
- commands->writeToSocket(m_connection->getSocket());
+ commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
if ((resp = m_connection->readResponse())->getCode() != 354)
{
@@ -326,6 +326,12 @@ void SMTPTransport::send
// Send end-of-data delimiter
m_connection->getSocket()->send("\r\n.\r\n");
+ if (m_connection->getTracer())
+ {
+ m_connection->getTracer()->traceSendBytes(size);
+ m_connection->getTracer()->traceSend(".");
+ }
+
shared_ptr <SMTPResponse> resp;
if ((resp = m_connection->readResponse())->getCode() != 250)
diff --git a/src/vmime/net/tracer.cpp b/src/vmime/net/tracer.cpp
new file mode 100644
index 00000000..b3610cdd
--- /dev/null
+++ b/src/vmime/net/tracer.cpp
@@ -0,0 +1,72 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2014 Vincent Richard <[email protected]>
+//
+// 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 3 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "tracer.hpp"
+
+
+#include <sstream>
+
+
+namespace vmime {
+namespace net {
+
+
+void tracer::traceReceiveBytes(const size_t count, const string& state)
+{
+ std::ostringstream oss;
+ oss << "{...";
+
+ if (!state.empty())
+ oss << state << ": ";
+
+ oss << count << " bytes of data...}";
+
+ traceReceive(oss.str());
+}
+
+
+void tracer::traceSendBytes(const size_t count, const string& state)
+{
+ std::ostringstream oss;
+ oss << "{...";
+
+ if (!state.empty())
+ oss << state << ": ";
+
+ oss << count << " bytes of data...}";
+
+ traceSend(oss.str());
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
diff --git a/src/vmime/net/tracer.hpp b/src/vmime/net/tracer.hpp
new file mode 100644
index 00000000..e30c823c
--- /dev/null
+++ b/src/vmime/net/tracer.hpp
@@ -0,0 +1,109 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2014 Vincent Richard <[email protected]>
+//
+// 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 3 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#ifndef VMIME_NET_TRACER_HPP_INCLUDED
+#define VMIME_NET_TRACER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/base.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class service;
+
+
+/** Base class for an object used to trace network communication
+ * between the client and the server.
+ */
+
+class VMIME_EXPORT tracer : public object
+{
+public:
+
+ virtual ~tracer() { }
+
+ /** Trace raw bytes which have been received.
+ *
+ * @param count number of bytes
+ * @param state protocol state (eg. "SASL exchange"), or empty
+ */
+ virtual void traceReceiveBytes(const size_t count, const string& state = "");
+
+ /** Trace raw bytes which have been sent.
+ *
+ * @param count number of bytes
+ * @param state protocol state (eg. "SASL exchange"), or empty
+ */
+ virtual void traceSendBytes(const size_t count, const string& state = "");
+
+ /** Trace a command line which has been sent.
+ *
+ * @param line command line
+ */
+ virtual void traceSend(const string& line) = 0;
+
+ /** Trace a response line which has been received.
+ *
+ * @param line response line
+ */
+ virtual void traceReceive(const string& line) = 0;
+};
+
+
+
+/** A class to create 'tracer' objects.
+ */
+
+class VMIME_EXPORT tracerFactory : public object
+{
+public:
+
+ virtual ~tracerFactory() { }
+
+ /** Creates a tracer for the specified service.
+ *
+ * @param serv messaging service
+ * @param connectionId an identifier for the connection to distinguate between
+ * different connections used by a service
+ * @return a new tracer
+ */
+ virtual shared_ptr <tracer> create(shared_ptr <service> serv, const int connectionId) = 0;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_TRACER_HPP_INCLUDED