aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar AlexKar <aleksander.karimov@gmail.com>2016-04-02 08:36:38 +0400
committerGravatar HoĆ  V. DINH <dinh.viet.hoa@gmail.com>2016-04-01 21:36:38 -0700
commit811b8ac5057f0c77e3db388088c61e0763282fd9 (patch)
tree63b3cbcbb85482dc9e237fb60f5dea8d53d81642
parent8bdb50e6f1e823e9394ff83eb66684b88497afb2 (diff)
Added ability of canceling for active sending operation
Added ability of canceling for active sending operation
-rw-r--r--src/async/smtp/MCSMTPSendWithDataOperation.cpp6
-rw-r--r--src/async/smtp/MCSMTPSendWithDataOperation.h2
-rw-r--r--src/core/smtp/MCSMTPSession.cpp73
-rw-r--r--src/core/smtp/MCSMTPSession.h9
4 files changed, 85 insertions, 5 deletions
diff --git a/src/async/smtp/MCSMTPSendWithDataOperation.cpp b/src/async/smtp/MCSMTPSendWithDataOperation.cpp
index 4561b5d8..28cc02bf 100644
--- a/src/async/smtp/MCSMTPSendWithDataOperation.cpp
+++ b/src/async/smtp/MCSMTPSendWithDataOperation.cpp
@@ -84,3 +84,9 @@ void SMTPSendWithDataOperation::main()
}
setError(error);
}
+
+void SMTPSendWithDataOperation::cancel()
+{
+ SMTPOperation::cancel();
+ session()->session()->cancelMessageSending();
+}
diff --git a/src/async/smtp/MCSMTPSendWithDataOperation.h b/src/async/smtp/MCSMTPSendWithDataOperation.h
index 768adda9..25685148 100644
--- a/src/async/smtp/MCSMTPSendWithDataOperation.h
+++ b/src/async/smtp/MCSMTPSendWithDataOperation.h
@@ -37,7 +37,7 @@ namespace mailcore {
public: // subclass behavior
virtual void main();
-
+ virtual void cancel();
private:
Data * mMessageData;
String * mMessageFilepath;
diff --git a/src/core/smtp/MCSMTPSession.cpp b/src/core/smtp/MCSMTPSession.cpp
index ebf94f43..dfd55176 100644
--- a/src/core/smtp/MCSMTPSession.cpp
+++ b/src/core/smtp/MCSMTPSession.cpp
@@ -21,6 +21,12 @@ enum {
STATE_LOGGEDIN,
};
+#define CANCEL_LOCK() pthread_mutex_lock(&mCancelLock)
+#define CANCEL_UNLOCK() pthread_mutex_unlock(&mCancelLock)
+
+#define CAN_CANCEL_LOCK() pthread_mutex_lock(&mCanCancelLock)
+#define CAN_CANCEL_UNLOCK() pthread_mutex_unlock(&mCanCancelLock)
+
void SMTPSession::init()
{
mHostname = NULL;
@@ -34,6 +40,8 @@ void SMTPSession::init()
mCheckCertificateEnabled = true;
mUseHeloIPEnabled = false;
mShouldDisconnect = false;
+ mSendingCancelled = false;
+ mCanCancel = false;
mSmtp = NULL;
mProgressCallback = NULL;
@@ -43,6 +51,8 @@ void SMTPSession::init()
mLastSMTPResponseCode = 0;
mConnectionLogger = NULL;
pthread_mutex_init(&mConnectionLoggerLock, NULL);
+ pthread_mutex_init(&mCancelLock, NULL);
+ pthread_mutex_init(&mCanCancelLock, NULL);
}
SMTPSession::SMTPSession()
@@ -53,6 +63,8 @@ SMTPSession::SMTPSession()
SMTPSession::~SMTPSession()
{
pthread_mutex_destroy(&mConnectionLoggerLock);
+ pthread_mutex_destroy(&mCancelLock);
+ pthread_mutex_destroy(&mCanCancelLock);
MC_SAFE_RELEASE(mLastSMTPResponse);
MC_SAFE_RELEASE(mHostname);
MC_SAFE_RELEASE(mUsername);
@@ -157,6 +169,12 @@ bool SMTPSession::checkCertificate()
return mailcore::checkCertificate(mSmtp->stream, hostname());
}
+void SMTPSession::setSendingCancelled(bool isCancelled) {
+ CANCEL_LOCK();
+ mSendingCancelled = isCancelled;
+ CANCEL_UNLOCK();
+}
+
void SMTPSession::setUseHeloIPEnabled(bool enabled)
{
mUseHeloIPEnabled = enabled;
@@ -609,10 +627,18 @@ void SMTPSession::checkAccount(Address * from, ErrorCode * pError)
}
void SMTPSession::sendMessage(Address * from, Array * recipients, Data * messageData,
+ SMTPProgressCallback * callback, ErrorCode * pError)
+{
+ setSendingCancelled(false);
+ internalSendMessage(from, recipients, messageData, callback, pError);
+}
+
+void SMTPSession::internalSendMessage(Address * from, Array * recipients, Data * messageData,
SMTPProgressCallback * callback, ErrorCode * pError)
{
clist * address_list;
int r;
+ bool sendingCancelled;
if (from == NULL) {
* pError = ErrorNoSender;
@@ -635,6 +661,17 @@ void SMTPSession::sendMessage(Address * from, Array * recipients, Data * message
if (* pError != ErrorNone) {
goto err;
}
+
+ CANCEL_LOCK();
+ sendingCancelled = mSendingCancelled;
+ CANCEL_UNLOCK();
+ if (sendingCancelled) {
+ goto err;
+ }
+
+ CAN_CANCEL_LOCK();
+ mCanCancel = true;
+ CAN_CANCEL_UNLOCK();
// disable DSN feature for more compatibility
mSmtp->esmtp &= ~MAILSMTP_ESMTP_DSN;
@@ -646,15 +683,25 @@ void SMTPSession::sendMessage(Address * from, Array * recipients, Data * message
}
MCLog("send");
if ((mSmtp->esmtp & MAILSMTP_ESMTP_PIPELINING) != 0) {
- r = mailesmtp_send_quit(mSmtp, MCUTF8(from->mailbox()), 0, NULL,
- address_list,
- messageData->bytes(), messageData->length());
+ r = mailesmtp_send_quit_no_disconnect(mSmtp, MCUTF8(from->mailbox()), 0, NULL,
+ address_list,
+ messageData->bytes(), messageData->length());
+ CAN_CANCEL_LOCK();
+ mCanCancel = false;
+ CAN_CANCEL_UNLOCK();
+ if (mSmtp->stream != NULL) {
+ mailstream_close(mSmtp->stream);
+ mSmtp->stream = NULL;
+ }
mShouldDisconnect = true;
}
else {
r = mailesmtp_send(mSmtp, MCUTF8(from->mailbox()), 0, NULL,
address_list,
messageData->bytes(), messageData->length());
+ CAN_CANCEL_LOCK();
+ mCanCancel = false;
+ CAN_CANCEL_UNLOCK();
mailsmtp_quit(mSmtp);
}
esmtp_address_list_free(address_list);
@@ -727,13 +774,14 @@ void SMTPSession::sendMessage(Address * from, Array * recipients, Data * message
void SMTPSession::sendMessage(Address * from, Array * recipients, String * messagePath,
SMTPProgressCallback * callback, ErrorCode * pError)
{
+ setSendingCancelled(false);
Data * messageData = Data::dataWithContentsOfFile(messagePath);
if (!messageData) {
* pError = ErrorFile;
return;
}
- return sendMessage(from, recipients, messageData, callback, pError);
+ return internalSendMessage(from, recipients, messageData, callback, pError);
}
static void mmapStringDeallocator(char * bytes, unsigned int length) {
@@ -802,6 +850,7 @@ Data * SMTPSession::dataWithFilteredBcc(Data * data)
void SMTPSession::sendMessage(Data * messageData, SMTPProgressCallback * callback, ErrorCode * pError)
{
+ setSendingCancelled(false);
AutoreleasePool * pool = new AutoreleasePool();
MessageParser * parser = new MessageParser(messageData);
Array * recipients = new Array();
@@ -826,6 +875,7 @@ void SMTPSession::sendMessage(Data * messageData, SMTPProgressCallback * callbac
void SMTPSession::sendMessage(MessageBuilder * msg, SMTPProgressCallback * callback, ErrorCode * pError)
{
+ setSendingCancelled(false);
Array * recipients = new Array();
if (msg->header()->to() != NULL) {
recipients->addObjectsFromArray(msg->header()->to());
@@ -864,6 +914,21 @@ void SMTPSession::noop(ErrorCode * pError)
}
}
+void SMTPSession::cancelMessageSending()
+{
+ // main thread
+
+ setSendingCancelled(true);
+
+ CAN_CANCEL_LOCK();
+ if (mCanCancel) {
+ if (mSmtp != NULL && mSmtp->stream != NULL) {
+ mailstream_cancel(mSmtp->stream);
+ }
+ }
+ CAN_CANCEL_UNLOCK();
+}
+
bool SMTPSession::isDisconnected()
{
return mState == STATE_DISCONNECTED;
diff --git a/src/core/smtp/MCSMTPSession.h b/src/core/smtp/MCSMTPSession.h
index 7e899881..e54673c5 100644
--- a/src/core/smtp/MCSMTPSession.h
+++ b/src/core/smtp/MCSMTPSession.h
@@ -63,6 +63,8 @@ namespace mailcore {
virtual void sendMessage(Address * from, Array * /* Address */ recipients, String * messagePath,
SMTPProgressCallback * callback, ErrorCode * pError);
+ virtual void cancelMessageSending();
+
virtual void setConnectionLogger(ConnectionLogger * logger);
virtual ConnectionLogger * connectionLogger();
@@ -85,6 +87,8 @@ namespace mailcore {
bool mCheckCertificateEnabled;
bool mUseHeloIPEnabled;
bool mShouldDisconnect;
+ bool mSendingCancelled;
+ bool mCanCancel;
mailsmtp * mSmtp;
SMTPProgressCallback * mProgressCallback;
@@ -92,6 +96,8 @@ namespace mailcore {
String * mLastSMTPResponse;
int mLastLibetpanError;
int mLastSMTPResponseCode;
+ pthread_mutex_t mCancelLock;
+ pthread_mutex_t mCanCancelLock;
ConnectionLogger * mConnectionLogger;
pthread_mutex_t mConnectionLoggerLock;
@@ -104,8 +110,11 @@ namespace mailcore {
void unsetup();
void connectIfNeeded(ErrorCode * pError);
bool checkCertificate();
+ void setSendingCancelled(bool isCancelled);
void sendMessage(MessageBuilder * msg, SMTPProgressCallback * callback, ErrorCode * pError);
+ void internalSendMessage(Address * from, Array * /* Address */ recipients, Data * messageData,
+ SMTPProgressCallback * callback, ErrorCode * pError);
public: // private
virtual bool isDisconnected();