aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/nntp/MCNNTPSession.cpp
diff options
context:
space:
mode:
authorGravatar Hoa V. DINH <dinh.viet.hoa@gmail.com>2016-03-03 22:45:19 -0800
committerGravatar Hoa V. DINH <dinh.viet.hoa@gmail.com>2016-03-03 22:45:19 -0800
commita55c8f370bd663ea1d31fed230987711aa1cf176 (patch)
tree567a995e2f0565d24aebff0fab959d3c95045670 /src/core/nntp/MCNNTPSession.cpp
parent886aae2ab94c74a4d4c644c446f67d37a333c1f9 (diff)
Thread safety on logger
Diffstat (limited to 'src/core/nntp/MCNNTPSession.cpp')
-rw-r--r--src/core/nntp/MCNNTPSession.cpp436
1 files changed, 233 insertions, 203 deletions
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;
+}
+