From a55c8f370bd663ea1d31fed230987711aa1cf176 Mon Sep 17 00:00:00 2001 From: "Hoa V. DINH" Date: Thu, 3 Mar 2016 22:45:19 -0800 Subject: Thread safety on logger --- src/async/nntp/MCNNTPAsyncSession.cpp | 4 +- src/async/pop/MCPOPAsyncSession.cpp | 4 +- src/async/smtp/MCSMTPAsyncSession.cpp | 4 +- src/core/imap/MCIMAPSession.cpp | 11 +- src/core/imap/MCIMAPSession.h | 1 + src/core/nntp/MCNNTPSession.cpp | 436 +++++++++++++++++-------------- src/core/nntp/MCNNTPSession.h | 8 +- src/core/pop/MCPOPSession.cpp | 37 ++- src/core/pop/MCPOPSession.h | 8 +- src/core/provider/MCAccountValidator.cpp | 43 ++- src/core/provider/MCAccountValidator.h | 13 +- src/core/smtp/MCSMTPSession.cpp | 36 ++- src/core/smtp/MCSMTPSession.h | 8 +- src/objc/provider/MCOAccountValidator.h | 3 + src/objc/provider/MCOAccountValidator.mm | 47 +++- 15 files changed, 432 insertions(+), 231 deletions(-) diff --git a/src/async/nntp/MCNNTPAsyncSession.cpp b/src/async/nntp/MCNNTPAsyncSession.cpp index eeed1244..fdf1165c 100644 --- a/src/async/nntp/MCNNTPAsyncSession.cpp +++ b/src/async/nntp/MCNNTPAsyncSession.cpp @@ -285,13 +285,13 @@ void NNTPAsyncSession::setConnectionLogger(ConnectionLogger * logger) { pthread_mutex_lock(&mConnectionLoggerLock); mConnectionLogger = logger; - if (mConnectionLogger != NULL) { + pthread_mutex_unlock(&mConnectionLoggerLock); + if (logger != NULL) { mSession->setConnectionLogger(mInternalLogger); } else { mSession->setConnectionLogger(NULL); } - pthread_mutex_unlock(&mConnectionLoggerLock); } ConnectionLogger * NNTPAsyncSession::connectionLogger() diff --git a/src/async/pop/MCPOPAsyncSession.cpp b/src/async/pop/MCPOPAsyncSession.cpp index dead660f..f1897b84 100644 --- a/src/async/pop/MCPOPAsyncSession.cpp +++ b/src/async/pop/MCPOPAsyncSession.cpp @@ -240,13 +240,13 @@ void POPAsyncSession::setConnectionLogger(ConnectionLogger * logger) { pthread_mutex_lock(&mConnectionLoggerLock); mConnectionLogger = logger; - if (mConnectionLogger != NULL) { + pthread_mutex_unlock(&mConnectionLoggerLock); + if (logger != NULL) { mSession->setConnectionLogger(mInternalLogger); } else { mSession->setConnectionLogger(NULL); } - pthread_mutex_unlock(&mConnectionLoggerLock); } ConnectionLogger * POPAsyncSession::connectionLogger() diff --git a/src/async/smtp/MCSMTPAsyncSession.cpp b/src/async/smtp/MCSMTPAsyncSession.cpp index 46b25184..8ec8e2d4 100644 --- a/src/async/smtp/MCSMTPAsyncSession.cpp +++ b/src/async/smtp/MCSMTPAsyncSession.cpp @@ -277,13 +277,13 @@ void SMTPAsyncSession::setConnectionLogger(ConnectionLogger * logger) { pthread_mutex_lock(&mConnectionLoggerLock); mConnectionLogger = logger; - if (mConnectionLogger != NULL) { + pthread_mutex_unlock(&mConnectionLoggerLock); + if (logger != NULL) { mSession->setConnectionLogger(mInternalLogger); } else { mSession->setConnectionLogger(NULL); } - pthread_mutex_unlock(&mConnectionLoggerLock); } ConnectionLogger * SMTPAsyncSession::connectionLogger() diff --git a/src/core/imap/MCIMAPSession.cpp b/src/core/imap/MCIMAPSession.cpp index 96c618a7..8b8565d9 100755 --- a/src/core/imap/MCIMAPSession.cpp +++ b/src/core/imap/MCIMAPSession.cpp @@ -514,7 +514,7 @@ static void logger(mailimap * imap, int log_type, const char * buffer, size_t si IMAPSession * session = (IMAPSession *) context; session->lockConnectionLogger(); - if (session->connectionLogger() == NULL) { + if (session->connectionLoggerNoLock() == NULL) { session->unlockConnectionLogger(); return; } @@ -530,11 +530,11 @@ static void logger(mailimap * imap, int log_type, const char * buffer, size_t si if (isBuffer) { AutoreleasePool * pool = new AutoreleasePool(); Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->log(session, type, data); + session->connectionLoggerNoLock()->log(session, type, data); pool->release(); } else { - session->connectionLogger()->log(session, type, NULL); + session->connectionLoggerNoLock()->log(session, type, NULL); } session->unlockConnectionLogger(); } @@ -4015,6 +4015,11 @@ void IMAPSession::unlockConnectionLogger() pthread_mutex_unlock(&mConnectionLoggerLock); } +ConnectionLogger * IMAPSession::connectionLoggerNoLock() +{ + return mConnectionLogger; +} + String * IMAPSession::htmlRendering(IMAPMessage * message, String * folder, ErrorCode * pError) { HTMLRendererIMAPDataCallback * dataCallback = new HTMLRendererIMAPDataCallback(this, message->uid()); diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h index 5f516ff5..9c6ba95b 100755 --- a/src/core/imap/MCIMAPSession.h +++ b/src/core/imap/MCIMAPSession.h @@ -219,6 +219,7 @@ namespace mailcore { virtual IndexSet * storedCapabilities(); virtual void lockConnectionLogger(); virtual void unlockConnectionLogger(); + virtual ConnectionLogger * connectionLoggerNoLock(); private: String * mHostname; diff --git a/src/core/nntp/MCNNTPSession.cpp b/src/core/nntp/MCNNTPSession.cpp index e5004432..f3e485d0 100644 --- a/src/core/nntp/MCNNTPSession.cpp +++ b/src/core/nntp/MCNNTPSession.cpp @@ -49,6 +49,7 @@ void NNTPSession::init() mProgressCallback = NULL; mState = STATE_DISCONNECTED; mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); } NNTPSession::NNTPSession() @@ -58,6 +59,7 @@ NNTPSession::NNTPSession() NNTPSession::~NNTPSession() { + pthread_mutex_destroy(&mConnectionLoggerLock); MC_SAFE_RELEASE(mHostname); MC_SAFE_RELEASE(mUsername); MC_SAFE_RELEASE(mPassword); @@ -158,20 +160,24 @@ void NNTPSession::bodyProgress(unsigned int current, unsigned int maximum) static void logger(newsnntp * nntp, int log_type, const char * buffer, size_t size, void * context) { NNTPSession * session = (NNTPSession *) context; + session->lockConnectionLogger(); - if (session->connectionLogger() == NULL) + if (session->connectionLoggerNoLock() == NULL) { + session->unlockConnectionLogger(); return; + } ConnectionLogType type = getConnectionType(log_type); bool isBuffer = isBufferFromLogType(log_type); if (isBuffer) { Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->log(session, type, data); + session->connectionLoggerNoLock()->log(session, type, data); } else { - session->connectionLogger()->log(session, type, NULL); + session->connectionLoggerNoLock()->log(session, type, NULL); } + session->unlockConnectionLogger(); } @@ -622,169 +628,6 @@ Array * NNTPSession::fetchOverArticlesInRange(Range range, String * groupName, E return result; } -void NNTPSession::postMessage(Data * messageData, NNTPProgressCallback * callback, ErrorCode * pError) -{ - int r; - - messageData = dataWithFilteredBcc(messageData); - - mProgressCallback = callback; - bodyProgress(0, messageData->length()); - - MCLog("setup"); - - MCLog("connect"); - loginIfNeeded(pError); - if (* pError != ErrorNone) { - goto err; - } - - MCLog("send"); - r = newsnntp_post(mNNTP, messageData->bytes(), messageData->length()); - - String * response; - - response = NULL; - if (mNNTP->nntp_response != NULL) { - response = String::stringWithUTF8Characters(mNNTP->nntp_response); - } - - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - goto err; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorSendMessage; - goto err; - } - - bodyProgress(messageData->length(), messageData->length()); - * pError = ErrorNone; - -err: - mProgressCallback = NULL; -} - -void NNTPSession::postMessage(String * messagePath, NNTPProgressCallback * callback, ErrorCode * pError) -{ - Data * messageData = Data::dataWithContentsOfFile(messagePath); - if (!messageData) { - * pError = ErrorFile; - return; - } - - return postMessage(messageData, callback, pError); -} - -static void mmapStringDeallocator(char * bytes, unsigned int length) { - mmap_string_unref(bytes); -} - -Data * NNTPSession::dataWithFilteredBcc(Data * data) -{ - int r; - size_t idx; - struct mailimf_message * msg; - - idx = 0; - r = mailimf_message_parse(data->bytes(), data->length(), &idx, &msg); - if (r != MAILIMF_NO_ERROR) { - return Data::data(); - } - - struct mailimf_fields * fields = msg->msg_fields; - int col = 0; - - int hasRecipient = 0; - bool bccWasActuallyRemoved = false; - for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimf_field * field = (struct mailimf_field *) clist_content(cur); - if (field->fld_type == MAILIMF_FIELD_BCC) { - mailimf_field_free(field); - clist_delete(fields->fld_list, cur); - bccWasActuallyRemoved = true; - break; - } - else if ((field->fld_type == MAILIMF_FIELD_TO) || (field->fld_type == MAILIMF_FIELD_CC)) { - hasRecipient = 1; - } - } - if (!hasRecipient) { - struct mailimf_address_list * imfTo; - imfTo = mailimf_address_list_new_empty(); - mailimf_address_list_add_parse(imfTo, (char *) "Undisclosed recipients:;"); - struct mailimf_to * toField = mailimf_to_new(imfTo); - struct mailimf_field * field = mailimf_field_new(MAILIMF_FIELD_TO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, toField, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - mailimf_fields_add(fields, field); - } - - Data * result; - if (!hasRecipient || bccWasActuallyRemoved) { - MMAPString * str = mmap_string_new(""); - mailimf_fields_write_mem(str, &col, fields); - mmap_string_append(str, "\n"); - mmap_string_append_len(str, msg->msg_body->bd_text, msg->msg_body->bd_size); - - mmap_string_ref(str); - - result = Data::data(); - result->takeBytesOwnership(str->str, (unsigned int) str->len, mmapStringDeallocator); - } - else { - // filter Bcc and modify To: only if necessary. - result = data; - } - - mailimf_message_free(msg); - - return result; -} - -void NNTPSession::selectGroup(String * folder, ErrorCode * pError) -{ - int r; - struct newsnntp_group_info * info; - - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - - readerIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - - r = newsnntp_group(mNNTP, folder->UTF8Characters(), &info); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - MCLog("select error : %s %i", MCUTF8DESC(this), * pError); - return; - } - else if (r == NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP) { - * pError = ErrorNonExistantFolder; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - - mState = STATE_SELECTED; - * pError = ErrorNone; - MCLog("select ok"); -} - -void NNTPSession::setConnectionLogger(ConnectionLogger * logger) -{ - mConnectionLogger = logger; -} - -ConnectionLogger * NNTPSession::connectionLogger() -{ - return mConnectionLogger; -} - // Taken from nntp/nntpdriver.c static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct mailimf_fields ** result) { @@ -792,31 +635,31 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m clist * list; struct mailimf_fields * fields; int r; - + list = clist_new(); if (list == NULL) { r = MAIL_ERROR_MEMORY; goto err; } - + if (item->ovr_subject != NULL) { char * subject_str; struct mailimf_subject * subject; struct mailimf_field * field; - + subject_str = strdup(item->ovr_subject); if (subject_str == NULL) { r = MAIL_ERROR_MEMORY; goto free_list; } - + subject = mailimf_subject_new(subject_str); if (subject == NULL) { free(subject_str); r = MAIL_ERROR_MEMORY; goto free_list; } - + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -827,7 +670,7 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m r = MAIL_ERROR_MEMORY; goto free_list; } - + r = clist_append(list, field); if (r < 0) { mailimf_field_free(field); @@ -835,12 +678,12 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m goto free_list; } } - + if (item->ovr_author != NULL) { struct mailimf_mailbox_list * mb_list; struct mailimf_from * from; struct mailimf_field * field; - + cur_token = 0; r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author), &cur_token, &mb_list); @@ -852,7 +695,7 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m r = MAIL_ERROR_MEMORY; goto free_list; } - + field = mailimf_field_new(MAILIMF_FIELD_FROM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, from, @@ -863,7 +706,7 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m r = MAIL_ERROR_MEMORY; goto free_list; } - + r = clist_append(list, field); if (r < 0) { mailimf_field_free(field); @@ -871,20 +714,20 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m goto free_list; } break; - + case MAILIMF_ERROR_PARSE: break; - + default: goto free_list; } } - + if (item->ovr_date != NULL) { struct mailimf_date_time * date_time; struct mailimf_orig_date * orig_date; struct mailimf_field * field; - + cur_token = 0; r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date), &cur_token, &date_time); @@ -896,7 +739,7 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m r = MAIL_ERROR_MEMORY; goto free_list; } - + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, orig_date, NULL, @@ -907,7 +750,7 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m r = MAIL_ERROR_MEMORY; goto free_list; } - + r = clist_append(list, field); if (r < 0) { mailimf_field_free(field); @@ -915,24 +758,24 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m goto free_list; } break; - + case MAILIMF_ERROR_PARSE: break; - + default: goto free_list; } } - + if (item->ovr_message_id != NULL) { char * msgid_str; struct mailimf_message_id * msgid; struct mailimf_field * field; - + cur_token = 0; r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id), &cur_token, &msgid_str); - + switch (r) { case MAILIMF_NO_ERROR: msgid = mailimf_message_id_new(msgid_str); @@ -941,13 +784,13 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m r = MAIL_ERROR_MEMORY; goto free_list; } - + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, msgid, NULL, NULL, NULL, NULL, NULL, NULL); - + r = clist_append(list, field); if (r < 0) { mailimf_field_free(field); @@ -955,25 +798,25 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m goto free_list; } break; - + case MAILIMF_ERROR_PARSE: break; - + default: goto free_list; } } - + if (item->ovr_references != NULL) { clist * msgid_list; struct mailimf_references * references; struct mailimf_field * field; - + cur_token = 0; - + r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references), &cur_token, &msgid_list); - + switch (r) { case MAILIMF_NO_ERROR: references = mailimf_references_new(msgid_list); @@ -984,41 +827,228 @@ static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct m r = MAIL_ERROR_MEMORY; goto free_list; } - + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, references, NULL, NULL, NULL, NULL); - + r = clist_append(list, field); if (r < 0) { mailimf_field_free(field); r = MAIL_ERROR_MEMORY; goto free_list; } - + case MAILIMF_ERROR_PARSE: break; - + default: goto free_list; } } - + fields = mailimf_fields_new(list); if (fields == NULL) { r = MAIL_ERROR_MEMORY; goto free_list; } - + * result = fields; - + return MAIL_NO_ERROR; - + free_list: clist_foreach(list, (clist_func) mailimf_field_free, NULL); clist_free(list); err: return r; } + +void NNTPSession::postMessage(Data * messageData, NNTPProgressCallback * callback, ErrorCode * pError) +{ + int r; + + messageData = dataWithFilteredBcc(messageData); + + mProgressCallback = callback; + bodyProgress(0, messageData->length()); + + MCLog("setup"); + + MCLog("connect"); + loginIfNeeded(pError); + if (* pError != ErrorNone) { + goto err; + } + + MCLog("send"); + r = newsnntp_post(mNNTP, messageData->bytes(), messageData->length()); + + String * response; + + response = NULL; + if (mNNTP->nntp_response != NULL) { + response = String::stringWithUTF8Characters(mNNTP->nntp_response); + } + + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + goto err; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorSendMessage; + goto err; + } + + bodyProgress(messageData->length(), messageData->length()); + * pError = ErrorNone; + +err: + mProgressCallback = NULL; +} + +void NNTPSession::postMessage(String * messagePath, NNTPProgressCallback * callback, ErrorCode * pError) +{ + Data * messageData = Data::dataWithContentsOfFile(messagePath); + if (!messageData) { + * pError = ErrorFile; + return; + } + + return postMessage(messageData, callback, pError); +} + +static void mmapStringDeallocator(char * bytes, unsigned int length) { + mmap_string_unref(bytes); +} + +Data * NNTPSession::dataWithFilteredBcc(Data * data) +{ + int r; + size_t idx; + struct mailimf_message * msg; + + idx = 0; + r = mailimf_message_parse(data->bytes(), data->length(), &idx, &msg); + if (r != MAILIMF_NO_ERROR) { + return Data::data(); + } + + struct mailimf_fields * fields = msg->msg_fields; + int col = 0; + + int hasRecipient = 0; + bool bccWasActuallyRemoved = false; + for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimf_field * field = (struct mailimf_field *) clist_content(cur); + if (field->fld_type == MAILIMF_FIELD_BCC) { + mailimf_field_free(field); + clist_delete(fields->fld_list, cur); + bccWasActuallyRemoved = true; + break; + } + else if ((field->fld_type == MAILIMF_FIELD_TO) || (field->fld_type == MAILIMF_FIELD_CC)) { + hasRecipient = 1; + } + } + if (!hasRecipient) { + struct mailimf_address_list * imfTo; + imfTo = mailimf_address_list_new_empty(); + mailimf_address_list_add_parse(imfTo, (char *) "Undisclosed recipients:;"); + struct mailimf_to * toField = mailimf_to_new(imfTo); + struct mailimf_field * field = mailimf_field_new(MAILIMF_FIELD_TO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, toField, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + mailimf_fields_add(fields, field); + } + + Data * result; + if (!hasRecipient || bccWasActuallyRemoved) { + MMAPString * str = mmap_string_new(""); + mailimf_fields_write_mem(str, &col, fields); + mmap_string_append(str, "\n"); + mmap_string_append_len(str, msg->msg_body->bd_text, msg->msg_body->bd_size); + + mmap_string_ref(str); + + result = Data::data(); + result->takeBytesOwnership(str->str, (unsigned int) str->len, mmapStringDeallocator); + } + else { + // filter Bcc and modify To: only if necessary. + result = data; + } + + mailimf_message_free(msg); + + return result; +} + +void NNTPSession::selectGroup(String * folder, ErrorCode * pError) +{ + int r; + struct newsnntp_group_info * info; + + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + + readerIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + + r = newsnntp_group(mNNTP, folder->UTF8Characters(), &info); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + MCLog("select error : %s %i", MCUTF8DESC(this), * pError); + return; + } + else if (r == NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP) { + * pError = ErrorNonExistantFolder; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + + mState = STATE_SELECTED; + * pError = ErrorNone; + MCLog("select ok"); +} + +void NNTPSession::lockConnectionLogger() +{ + pthread_mutex_lock(&mConnectionLoggerLock); +} + +void NNTPSession::unlockConnectionLogger() +{ + pthread_mutex_unlock(&mConnectionLoggerLock); +} + +void NNTPSession::setConnectionLogger(ConnectionLogger * logger) +{ + lockConnectionLogger(); + mConnectionLogger = logger; + unlockConnectionLogger(); +} + +ConnectionLogger * NNTPSession::connectionLogger() +{ + ConnectionLogger * result; + + lockConnectionLogger(); + result = connectionLoggerNoLock(); + unlockConnectionLogger(); + + return result; +} + +ConnectionLogger * NNTPSession::connectionLoggerNoLock() +{ + return mConnectionLogger; +} + diff --git a/src/core/nntp/MCNNTPSession.h b/src/core/nntp/MCNNTPSession.h index 22734f2d..5e371eea 100644 --- a/src/core/nntp/MCNNTPSession.h +++ b/src/core/nntp/MCNNTPSession.h @@ -63,6 +63,11 @@ namespace mailcore { virtual void setConnectionLogger(ConnectionLogger * logger); virtual ConnectionLogger * connectionLogger(); + public: // private + virtual void lockConnectionLogger(); + virtual void unlockConnectionLogger(); + virtual ConnectionLogger * connectionLoggerNoLock(); + private: String * mHostname; unsigned int mPort; @@ -77,7 +82,8 @@ namespace mailcore { int mState; ConnectionLogger * mConnectionLogger; - + pthread_mutex_t mConnectionLoggerLock; + void init(); Data * dataWithFilteredBcc(Data * data); static void body_progress(size_t current, size_t maximum, void * context); diff --git a/src/core/pop/MCPOPSession.cpp b/src/core/pop/MCPOPSession.cpp index ab8975a6..77452515 100644 --- a/src/core/pop/MCPOPSession.cpp +++ b/src/core/pop/MCPOPSession.cpp @@ -36,6 +36,7 @@ void POPSession::init() mProgressCallback = NULL; mState = STATE_DISCONNECTED; mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); } POPSession::POPSession() @@ -45,6 +46,7 @@ POPSession::POPSession() POPSession::~POPSession() { + pthread_mutex_destroy(&mConnectionLoggerLock); MC_SAFE_RELEASE(mHostname); MC_SAFE_RELEASE(mUsername); MC_SAFE_RELEASE(mPassword); @@ -155,20 +157,24 @@ void POPSession::body_progress(size_t current, size_t maximum, void * context) static void logger(mailpop3 * pop3, int log_type, const char * buffer, size_t size, void * context) { POPSession * session = (POPSession *) context; - - if (session->connectionLogger() == NULL) + session->lockConnectionLogger(); + + if (session->connectionLoggerNoLock() == NULL) { + session->unlockConnectionLogger(); return; + } ConnectionLogType type = getConnectionType(log_type); bool isBuffer = isBufferFromLogType(log_type); if (isBuffer) { Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->log(session, type, data); + session->connectionLoggerNoLock()->log(session, type, data); } else { - session->connectionLogger()->log(session, type, NULL); + session->connectionLoggerNoLock()->log(session, type, NULL); } + session->unlockConnectionLogger(); } void POPSession::setup() @@ -592,12 +598,35 @@ void POPSession::noop(ErrorCode * pError) } } +void POPSession::lockConnectionLogger() +{ + pthread_mutex_lock(&mConnectionLoggerLock); +} + +void POPSession::unlockConnectionLogger() +{ + pthread_mutex_unlock(&mConnectionLoggerLock); +} + void POPSession::setConnectionLogger(ConnectionLogger * logger) { + lockConnectionLogger(); mConnectionLogger = logger; + unlockConnectionLogger(); } ConnectionLogger * POPSession::connectionLogger() +{ + ConnectionLogger * result; + + lockConnectionLogger(); + result = connectionLoggerNoLock(); + unlockConnectionLogger(); + + return result; +} + +ConnectionLogger * POPSession::connectionLoggerNoLock() { return mConnectionLogger; } diff --git a/src/core/pop/MCPOPSession.h b/src/core/pop/MCPOPSession.h index eda323c0..f32f9b18 100644 --- a/src/core/pop/MCPOPSession.h +++ b/src/core/pop/MCPOPSession.h @@ -64,7 +64,12 @@ namespace mailcore { virtual void setConnectionLogger(ConnectionLogger * logger); virtual ConnectionLogger * connectionLogger(); - + + public: // private + virtual void lockConnectionLogger(); + virtual void unlockConnectionLogger(); + virtual ConnectionLogger * connectionLoggerNoLock(); + private: String * mHostname; unsigned int mPort; @@ -81,6 +86,7 @@ namespace mailcore { int mState; ConnectionLogger * mConnectionLogger; + pthread_mutex_t mConnectionLoggerLock; void init(); void bodyProgress(unsigned int current, unsigned int maximum); diff --git a/src/core/provider/MCAccountValidator.cpp b/src/core/provider/MCAccountValidator.cpp index 59538c72..1e6ebdd9 100644 --- a/src/core/provider/MCAccountValidator.cpp +++ b/src/core/provider/MCAccountValidator.cpp @@ -64,6 +64,9 @@ void AccountValidator::init() mImapEnabled = false; mPopEnabled = false; mSmtpEnabled = false; + + mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); } AccountValidator::AccountValidator() @@ -73,6 +76,7 @@ AccountValidator::AccountValidator() AccountValidator::~AccountValidator() { + pthread_mutex_destroy(&mConnectionLoggerLock); MC_SAFE_RELEASE(mEmail); MC_SAFE_RELEASE(mUsername); MC_SAFE_RELEASE(mPassword); @@ -250,6 +254,7 @@ void AccountValidator::checkNextHost() mImapSession->setHostname(mImapServer->hostname()); mImapSession->setPort(mImapServer->port()); mImapSession->setConnectionType(mImapServer->connectionType()); + mImapSession->setConnectionLogger(this); mOperation = (IMAPOperation *)mImapSession->checkAccountOperation(); mOperation->retain(); @@ -271,12 +276,13 @@ void AccountValidator::checkNextHost() mPopSession = new POPAsyncSession(); mPopSession->setUsername(mUsername); mPopSession->setPassword(mPassword); - + mPopServer = (NetService *) mPopServices->objectAtIndex(mCurrentServiceIndex); mPopSession->setHostname(mPopServer->hostname()); mPopSession->setPort(mPopServer->port()); mPopSession->setConnectionType(mPopServer->connectionType()); - + mPopSession->setConnectionLogger(this); + mOperation = mPopSession->checkAccountOperation(); mOperation->retain(); mOperation->setCallback(this); @@ -306,7 +312,8 @@ void AccountValidator::checkNextHost() mSmtpSession->setHostname(mSmtpServer->hostname()); mSmtpSession->setPort(mSmtpServer->port()); mSmtpSession->setConnectionType(mSmtpServer->connectionType()); - + mSmtpSession->setConnectionLogger(this); + mOperation = mSmtpSession->checkAccountOperation(Address::addressWithMailbox(mEmail)); mOperation->retain(); mOperation->setCallback(this); @@ -334,16 +341,19 @@ void AccountValidator::checkNextHostDone() if (mCurrentServiceTested == SERVICE_IMAP) { mImapError = ((IMAPOperation *)mOperation)->error(); error = mImapError; + mImapSession->setConnectionLogger(NULL); MC_SAFE_RELEASE(mImapSession); } else if (mCurrentServiceTested == SERVICE_POP) { mPopError = ((POPOperation *)mOperation)->error(); error = mPopError; + mPopSession->setConnectionLogger(NULL); MC_SAFE_RELEASE(mPopSession); } else if (mCurrentServiceTested == SERVICE_SMTP) { mSmtpError = ((SMTPOperation *)mOperation)->error(); error = mSmtpError; + mSmtpSession->setConnectionLogger(NULL); MC_SAFE_RELEASE(mSmtpSession); } @@ -495,3 +505,30 @@ ErrorCode AccountValidator::smtpError() { return mSmtpError; } + +void AccountValidator::setConnectionLogger(ConnectionLogger * logger) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + mConnectionLogger = logger; + pthread_mutex_unlock(&mConnectionLoggerLock); +} + +ConnectionLogger * AccountValidator::connectionLogger() +{ + ConnectionLogger * result; + + pthread_mutex_lock(&mConnectionLoggerLock); + result = mConnectionLogger; + pthread_mutex_unlock(&mConnectionLoggerLock); + + return result; +} + +void AccountValidator::log(void * sender, ConnectionLogType logType, Data * buffer) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + if (mConnectionLogger != NULL) { + mConnectionLogger->log(this, logType, buffer); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} diff --git a/src/core/provider/MCAccountValidator.h b/src/core/provider/MCAccountValidator.h index 436317cf..788458b6 100644 --- a/src/core/provider/MCAccountValidator.h +++ b/src/core/provider/MCAccountValidator.h @@ -23,7 +23,7 @@ namespace mailcore { class POPAsyncSession; class SMTPAsyncSession; - class MAILCORE_EXPORT AccountValidator : public Operation, public OperationCallback { + class MAILCORE_EXPORT AccountValidator : public Operation, public OperationCallback, public ConnectionLogger { public: AccountValidator(); virtual ~AccountValidator(); @@ -53,6 +53,9 @@ namespace mailcore { virtual void setPopServices(Array * popServices); virtual Array * /* NetService */ popServices(); + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + // result virtual String * identifier(); virtual NetService * imapServer(); @@ -64,7 +67,10 @@ namespace mailcore { virtual void start(); virtual void cancel(); - + + public: // ConnectionLogger + virtual void log(void * sender, ConnectionLogType logType, Data * buffer); + private: String * mEmail; /* for SMTP */ String * mUsername; @@ -104,6 +110,9 @@ namespace mailcore { bool mPopEnabled; bool mSmtpEnabled; + pthread_mutex_t mConnectionLoggerLock; + ConnectionLogger * mConnectionLogger; + void init(); void setupServices(); void resolveMX(); diff --git a/src/core/smtp/MCSMTPSession.cpp b/src/core/smtp/MCSMTPSession.cpp index 8bcaefff..ebf94f43 100644 --- a/src/core/smtp/MCSMTPSession.cpp +++ b/src/core/smtp/MCSMTPSession.cpp @@ -42,6 +42,7 @@ void SMTPSession::init() mLastLibetpanError = 0; mLastSMTPResponseCode = 0; mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); } SMTPSession::SMTPSession() @@ -51,6 +52,7 @@ SMTPSession::SMTPSession() SMTPSession::~SMTPSession() { + pthread_mutex_destroy(&mConnectionLoggerLock); MC_SAFE_RELEASE(mLastSMTPResponse); MC_SAFE_RELEASE(mHostname); MC_SAFE_RELEASE(mUsername); @@ -184,24 +186,29 @@ void SMTPSession::bodyProgress(unsigned int current, unsigned int maximum) static void logger(mailsmtp * smtp, int log_type, const char * buffer, size_t size, void * context) { SMTPSession * session = (SMTPSession *) context; + session->lockConnectionLogger(); - if (session->connectionLogger() == NULL) + if (session->connectionLoggerNoLock() == NULL) { + session->unlockConnectionLogger(); return; + } ConnectionLogType type = getConnectionType(log_type); if ((int) type == -1) { // in case of MAILSTREAM_LOG_TYPE_INFO_RECEIVED or MAILSTREAM_LOG_TYPE_INFO_SENT. + session->unlockConnectionLogger(); return; } bool isBuffer = isBufferFromLogType(log_type); if (isBuffer) { Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->log(session, type, data); + session->connectionLoggerNoLock()->log(session, type, data); } else { - session->connectionLogger()->log(session, type, NULL); + session->connectionLoggerNoLock()->log(session, type, NULL); } + session->unlockConnectionLogger(); } @@ -862,12 +869,35 @@ bool SMTPSession::isDisconnected() return mState == STATE_DISCONNECTED; } +void SMTPSession::lockConnectionLogger() +{ + pthread_mutex_lock(&mConnectionLoggerLock); +} + +void SMTPSession::unlockConnectionLogger() +{ + pthread_mutex_unlock(&mConnectionLoggerLock); +} + void SMTPSession::setConnectionLogger(ConnectionLogger * logger) { + lockConnectionLogger(); mConnectionLogger = logger; + unlockConnectionLogger(); } ConnectionLogger * SMTPSession::connectionLogger() +{ + ConnectionLogger * result; + + lockConnectionLogger(); + result = connectionLoggerNoLock(); + unlockConnectionLogger(); + + return result; +} + +ConnectionLogger * SMTPSession::connectionLoggerNoLock() { return mConnectionLogger; } diff --git a/src/core/smtp/MCSMTPSession.h b/src/core/smtp/MCSMTPSession.h index 64ff30d0..7e899881 100644 --- a/src/core/smtp/MCSMTPSession.h +++ b/src/core/smtp/MCSMTPSession.h @@ -68,6 +68,11 @@ namespace mailcore { virtual void noop(ErrorCode * pError); + public: // private + virtual void lockConnectionLogger(); + virtual void unlockConnectionLogger(); + virtual ConnectionLogger * connectionLoggerNoLock(); + private: String * mHostname; unsigned int mPort; @@ -89,7 +94,8 @@ namespace mailcore { int mLastSMTPResponseCode; ConnectionLogger * mConnectionLogger; - + pthread_mutex_t mConnectionLoggerLock; + void init(); Data * dataWithFilteredBcc(Data * data); static void body_progress(size_t current, size_t maximum, void * context); diff --git a/src/objc/provider/MCOAccountValidator.h b/src/objc/provider/MCOAccountValidator.h index b5f09bc2..8d6676b1 100644 --- a/src/objc/provider/MCOAccountValidator.h +++ b/src/objc/provider/MCOAccountValidator.h @@ -8,6 +8,7 @@ #import #import +#import /** This class is used to validate an email provider and it's associated @@ -34,6 +35,8 @@ @property (nonatomic, assign, getter=isPopEnabled) BOOL popEnabled; @property (nonatomic, assign, getter=isSmtpEnabled) BOOL smtpEnabled; +@property (nonatomic, copy) MCOConnectionLogger connectionLogger; + // result @property (nonatomic, retain, readonly) NSString * identifier; @property (nonatomic, retain, readonly) MCONetService * imapServer; diff --git a/src/objc/provider/MCOAccountValidator.mm b/src/objc/provider/MCOAccountValidator.mm index 0aa9a393..ab240bf5 100644 --- a/src/objc/provider/MCOAccountValidator.mm +++ b/src/objc/provider/MCOAccountValidator.mm @@ -20,10 +20,11 @@ typedef void (^CompletionType)(void); @interface MCOAccountValidator () - (void) _operationCompleted; +- (void) _logWithSender:(void *)sender connectionType:(MCOConnectionLogType)logType data:(NSData *)data; @end -class MCOValidatorOperationCallback: public mailcore::Object, public mailcore::OperationCallback { +class MCOValidatorOperationCallback: public mailcore::Object, public mailcore::OperationCallback, public mailcore::ConnectionLogger { public: MCOValidatorOperationCallback(MCOAccountValidator * op) { @@ -35,6 +36,11 @@ public: [mOperation _operationCompleted]; } + virtual void log(void * sender, mailcore::ConnectionLogType logType, mailcore::Data * data) + { + [mOperation _logWithSender:sender connectionType:(MCOConnectionLogType)logType data:MCO_TO_OBJC(data)]; + } + private: MCOAccountValidator * mOperation; }; @@ -42,7 +48,8 @@ private: @implementation MCOAccountValidator{ CompletionType _completionBlock; mailcore::AccountValidator * _validator; - MCOValidatorOperationCallback * _imapCallback; + MCOValidatorOperationCallback * _callback; + MCOConnectionLogger _connectionLogger; } #define nativeType mailcore::AccountValidator @@ -84,13 +91,22 @@ MCO_OBJC_SYNTHESIZE_BOOL(setSmtpEnabled, isSmtpEnabled) self = [super initWithMCOperation:validator]; _validator = validator; - _imapCallback = new MCOValidatorOperationCallback(self); - _validator->setCallback(_imapCallback); + _callback = new MCOValidatorOperationCallback(self); + _validator->setCallback(_callback); _validator->retain(); return self; } +- (void) dealloc +{ + [_completionBlock release]; + MC_SAFE_RELEASE(_validator); + MC_SAFE_RELEASE(_callback); + [_connectionLogger release]; + [super dealloc]; +} + - (void) start:(void (^)(void))completionBlock { _completionBlock = [completionBlock copy]; @@ -150,4 +166,27 @@ MCO_OBJC_SYNTHESIZE_BOOL(setSmtpEnabled, isSmtpEnabled) return [NSError mco_errorWithErrorCode:_validator->smtpError()]; } +- (void) setConnectionLogger:(MCOConnectionLogger)connectionLogger +{ + [_connectionLogger release]; + _connectionLogger = [connectionLogger copy]; + + if (_connectionLogger != nil) { + _validator->setConnectionLogger(_callback); + } + else { + _validator->setConnectionLogger(NULL); + } +} + +- (MCOConnectionLogger) connectionLogger +{ + return _connectionLogger; +} + +- (void) _logWithSender:(void *)sender connectionType:(MCOConnectionLogType)logType data:(NSData *)data +{ + _connectionLogger(sender, logType, data); +} + @end -- cgit v1.2.3