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/core/nntp/MCNNTPSession.cpp | 436 +++++++++++++++++++++------------------- 1 file changed, 233 insertions(+), 203 deletions(-) (limited to 'src/core/nntp/MCNNTPSession.cpp') 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; +} + -- cgit v1.2.3