Coverity issue fixes for email service
[platform/core/messaging/email-service.git] / email-core / email-core-imap-idle.c
1 /*
2 *  email-service
3 *
4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5 *
6 * Contact: Kyuho Jo <kyuho.jo@samsung.com>, Sunghyun Kwon <sh0701.kwon@samsung.com>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21
22 /**
23  *
24  * This file contains functionality related to IMAP IDLE.
25  * to interact with email-service.
26  * @file                em_core-imap-idle.c
27  * @author
28  * @version     0.1
29  * @brief               This file contains functionality to provide IMAP IDLE support in email-service.
30  */
31
32 #include <email-internal-types.h>
33
34 #ifdef __FEATURE_IMAP_IDLE__
35 #include <glib.h>
36 #include <openssl/ssl.h>
37 #include "c-client.h"
38 #include <sys/epoll.h>
39 #include "lnx_inc.h"
40 #include "email-core-imap-idle.h"
41 #include "email-debug-log.h"
42 #include "email-storage.h"
43 #include "email-network.h"
44 #include "email-core-utils.h"
45 #include "email-core-mailbox.h"
46 #include "email-core-event.h"
47 #include "email-core-account.h"
48 #include "email-core-alarm.h"
49 #include "email-utilities.h"
50 #include "email-core-container.h"
51
52 /*Definitions copied temporarily from ssl_unix.c */
53 #define SSLBUFLEN 8192
54 #define MAX_EPOLL_EVENT 100
55
56 typedef struct ssl_stream {
57   TCPSTREAM *tcpstream; /* TCP stream */
58   SSL_CTX *context;     /* SSL context */
59   SSL *con;             /* SSL connection */
60   int ictr;             /* input counter */
61   char *iptr;           /* input pointer */
62   char ibuf[SSLBUFLEN]; /* input buffer */
63 } SSLSTREAM;
64 /*Definitions copied temporarily from ssl_unix.c - end*/
65
66 typedef struct _email_imap_idle_connection_info_t {
67         int          account_id;
68         int          mailbox_id;
69         MAILSTREAM  *mail_stream;
70         int          socket_fd;
71         char        *multi_user_name;
72 } email_imap_idle_connection_info_t;
73
74 int       imap_idle_pipe_fd[2];
75 thread_t  imap_idle_thread_id;
76
77 static int emcore_get_connection_info_by_socket_fd(GList *input_imap_idle_task_list,
78                                                                                                         int input_socket_fd,
79                                                                                                         email_imap_idle_connection_info_t **output_connection_info)
80 {
81         EM_DEBUG_FUNC_BEGIN("input_imap_idle_task_list[%p] input_socket_fd[%d] output_connection_info[%p]",
82                                                 input_imap_idle_task_list, input_socket_fd, output_connection_info);
83         int err = EMAIL_ERROR_NONE;
84         email_imap_idle_connection_info_t *connection_info = NULL;
85         GList *index = NULL;
86
87         if (input_imap_idle_task_list == NULL || output_connection_info == NULL) {
88                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
89                 err = EMAIL_ERROR_INVALID_PARAM;
90                 goto FINISH_OFF;
91         }
92
93         index = g_list_first(input_imap_idle_task_list);
94
95         while (index) {
96                 connection_info = index->data;
97                 if (connection_info && connection_info->socket_fd == input_socket_fd) {
98                         break;
99                 }
100                 index = g_list_next(index);
101         }
102
103         if (connection_info)
104                 *output_connection_info = connection_info;
105         else
106                 err = EMAIL_ERROR_DATA_NOT_FOUND;
107
108 FINISH_OFF:
109
110         EM_DEBUG_FUNC_END("err [%d]", err);
111         return err;
112 }
113
114 static int emcore_clear_old_connections(int input_epoll_fd, GList **input_imap_idle_task_list)
115 {
116         EM_DEBUG_FUNC_BEGIN("input_epoll_fd[%d] input_imap_idle_task_list[%p]", input_epoll_fd, input_imap_idle_task_list);
117
118         int err = EMAIL_ERROR_NONE;
119         email_imap_idle_connection_info_t *connection_info = NULL;
120         struct epoll_event ev = {0};
121         GList *index = NULL;
122         char errno_buf[ERRNO_BUF_SIZE] = {0};
123
124         if (input_imap_idle_task_list == NULL) {
125                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
126                 err = EMAIL_ERROR_INVALID_PARAM;
127                 goto FINISH_OFF;
128         }
129
130         index = *input_imap_idle_task_list;
131
132         while (index) {
133                 connection_info = index->data;
134                 if (connection_info) {
135                         /* Removes all fd from epoll_fd */
136                         ev.events  = EPOLLIN;
137                         ev.data.fd = connection_info->socket_fd;
138
139                         if (epoll_ctl(input_epoll_fd, EPOLL_CTL_DEL, connection_info->socket_fd, &ev) == -1) {
140                                 EM_DEBUG_LOG("epoll_ctl failed: %s[%d]", EM_STRERROR(errno_buf), errno);
141                         }
142
143                         /* Close connection */
144                         if (connection_info->mail_stream)
145                                 connection_info->mail_stream = mail_close(connection_info->mail_stream);
146
147                         g_free(connection_info->multi_user_name);
148                         g_free(connection_info);
149                 }
150
151                 EM_DEBUG_LOG("Delete the index list");
152                 *input_imap_idle_task_list = g_list_delete_link(*input_imap_idle_task_list, index);
153                 index = *input_imap_idle_task_list;
154         }
155
156         *input_imap_idle_task_list = NULL;
157
158 FINISH_OFF:
159
160         EM_DEBUG_FUNC_END("err [%d]", err);
161         return err;
162 }
163
164 static int emcore_imap_idle_insert_sync_event(char *multi_user_name,
165                                                                                                 int input_account_id,
166                                                                                                 int input_mailbox_id,
167                                                                                                 int *err_code)
168 {
169         EM_DEBUG_FUNC_BEGIN();
170
171         int ret = false;
172         int err = EMAIL_ERROR_NONE;
173         int handle;
174         email_event_t *event_data = NULL;
175
176         if (input_account_id <= 0) {
177                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
178                 err = EMAIL_ERROR_INVALID_PARAM;
179                 goto FINISH_OFF;
180         }
181
182         event_data = em_malloc(sizeof(email_event_t));
183         if (event_data == NULL) {
184                 EM_DEBUG_EXCEPTION("em_mallocfailed");
185                 err = EMAIL_ERROR_OUT_OF_MEMORY;
186                 goto FINISH_OFF;
187         }
188
189         event_data->type               = EMAIL_EVENT_SYNC_HEADER;
190         event_data->event_param_data_5 = input_mailbox_id;
191         event_data->account_id         = input_account_id;
192         event_data->multi_user_name    = EM_SAFE_STRDUP(multi_user_name);
193
194         if (!emcore_insert_event(event_data, &handle, &err)) {
195                 EM_DEBUG_EXCEPTION("emcore_insert_event failed [%d]", err);
196                 goto FINISH_OFF;
197         }
198
199         ret = true;
200
201 FINISH_OFF:
202
203         if (ret == false && event_data) {
204                 emcore_free_event(event_data);
205                 EM_SAFE_FREE(event_data);
206         }
207
208         if (err_code)
209                 *err_code = err;
210
211         EM_DEBUG_FUNC_END("ret [%d]", ret);
212         return ret;
213 }
214
215 static int emcore_parse_imap_idle_response(char *multi_user_name,
216                                                                                         int input_account_id,
217                                                                                         int input_mailbox_id,
218                                                                                         MAILSTREAM *input_mailstream,
219                                                                                         int input_socket_fd)
220 {
221         EM_DEBUG_FUNC_BEGIN("input_account_id[%d] input_mailbox_id [%d] input_mailstream[%p] input_socket_fd[%d]",
222                                                 input_account_id, input_mailbox_id, input_mailstream, input_socket_fd);
223
224         int err = EMAIL_ERROR_NONE;
225         char *p = NULL;
226         IMAPLOCAL *imap_local = NULL;
227
228         if (!input_mailstream) {
229                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
230                 err = EMAIL_ERROR_INVALID_PARAM;
231                 goto FINISH_OFF;
232         }
233
234         imap_local = input_mailstream->local;
235
236         if (!imap_local) {
237                 EM_DEBUG_EXCEPTION("imap_local is NULL");
238                 err = EMAIL_ERROR_INVALID_PARAM;
239                 goto FINISH_OFF;
240         }
241
242         while (imap_local->netstream) {
243                 p = net_getline(imap_local->netstream);
244                 if (p && !strncmp(p, "*", 1)) {
245                         EM_DEBUG_LOG("p is [%s]", p);
246                         if (p+1 && p+2 && p+3 && p+4 && !strncmp(p+2, "BYE", 3)) {
247                                 EM_DEBUG_LOG("BYE connection from server");
248                                 EM_SAFE_FREE(p);
249                                 err = EMAIL_ERROR_IMAP4_IDLE_FAILURE;
250                                 goto FINISH_OFF;
251                         } else {
252                                 if (strstr(p, "EXIST") != NULL) {
253                                         if (!emcore_imap_idle_insert_sync_event(multi_user_name, input_account_id, input_mailbox_id, &err))
254                                                 EM_DEBUG_EXCEPTION_SEC("Syncing mailbox[%d] failed with err_code [%d]", input_mailbox_id, err);
255                                         EM_SAFE_FREE(p);
256                                         break;
257                                 }
258                                 else {
259                                         EM_DEBUG_LOG("Skipped this message");
260                                         EM_SAFE_FREE(p);
261                                 }
262
263                         }
264                 } else if (p && (!strncmp(p, "+", 1))) {
265                         /* Bad response from server */
266                         EM_DEBUG_LOG("p is [%s]", p);
267                         EM_SAFE_FREE(p);
268                         break;
269                 } else {
270                         EM_DEBUG_LOG("In else part");
271                         break;
272                 }
273         }
274
275 FINISH_OFF:
276
277         EM_DEBUG_FUNC_END("err [%d]", err);
278         return err;
279 }
280
281 /* connects to given mailbox. send idle and returns socket id */
282 static int emcore_connect_and_idle_on_mailbox(char *multi_user_name,
283                                                                                                 GList **input_connection_list,
284                                                                                                 email_account_t *input_account,
285                                                                                                 email_mailbox_t *input_mailbox,
286                                                                                                 MAILSTREAM **output_mailstream,
287                                                                                                 int *output_socket_fd)
288 {
289         EM_DEBUG_FUNC_BEGIN("input_connection_list [%p] input_account [%p] input_mailbox[%p] "
290                                                 "output_mailstream [%p] output_socket_fd [%p]",
291                                                 input_connection_list, input_account, input_mailbox, output_mailstream, output_socket_fd);
292
293         void            *mail_stream = NULL;
294         char             cmd[128] = { 0, };
295         char             tag[32] = { 0, };
296         char            *p = NULL;
297         int              socket_fd = 0;
298         int              err = EMAIL_ERROR_NONE;
299         email_session_t *session = NULL;
300         IMAPLOCAL       *imap_local = NULL;
301         NETSTREAM       *net_stream = NULL;
302         TCPSTREAM       *tcp_stream = NULL;
303         GList           *imap_idle_connection_list = NULL;
304         email_imap_idle_connection_info_t *connection_info = NULL;
305
306         if (input_connection_list == NULL || input_account == NULL || input_mailbox == NULL ||
307                 output_mailstream == NULL || output_socket_fd == NULL) {
308                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
309                 err = EMAIL_ERROR_INVALID_PARAM;
310                 goto FINISH_OFF;
311         }
312
313         imap_idle_connection_list = *input_connection_list;
314
315         if (!emcore_get_empty_session(&session))
316                 EM_DEBUG_EXCEPTION("emcore_get_empty_session failed...");
317
318         /* Open connection to mailbox */
319         if (!emcore_connect_to_remote_mailbox(multi_user_name,
320                                                                                         input_mailbox->account_id,
321                                                                                         input_mailbox->mailbox_id,
322                                                                                         true,
323                                                                                         (void **)&mail_stream,
324                                                                                         &err) || !mail_stream) {
325                 EM_DEBUG_EXCEPTION("emcore_connect_to_remote_mailbox failed [%d]", err);
326                 goto FINISH_OFF;
327         }
328
329         imap_local = ((MAILSTREAM *)mail_stream)->local;
330         net_stream = imap_local->netstream;
331
332         /* check if ssl option is enabled on this account - shasikala.p */
333         if (input_account->incoming_server_secure_connection) {
334                 SSLSTREAM *ssl_stream = net_stream->stream;
335                 tcp_stream = ssl_stream->tcpstream;
336         } else
337                 tcp_stream = net_stream->stream;
338
339         /* Get Socket ID */
340         socket_fd = ((TCPSTREAM *)tcp_stream)->tcpsi;
341
342         snprintf(tag, sizeof(tag), "%08lx", 0xffffffff & (((MAILSTREAM *)mail_stream)->gensym++));
343         snprintf(cmd, sizeof(cmd), "%s IDLE\015\012", tag);
344
345         /* Send IDLE command */
346         if (!imap_local->netstream || !net_sout(imap_local->netstream, cmd, (int)EM_SAFE_STRLEN(cmd))) {
347                 EM_DEBUG_EXCEPTION("network error - failed to IDLE on Mailbox - [%d]", input_mailbox->mailbox_id);
348                 err = EMAIL_ERROR_IMAP4_IDLE_FAILURE;
349                 goto FINISH_OFF;
350         }
351
352         /* Get the response for IDLE command */
353         while (imap_local->netstream) {
354                 p = net_getline(imap_local->netstream);
355
356                 EM_DEBUG_LOG("IDLE command response: [%s]", p);
357
358                 if (p && '+' == *p) {
359                         EM_DEBUG_LOG("OK. Go.");
360                         break;
361                 } else if (p && '*' == *p) {
362                         EM_SAFE_FREE(p);
363                         continue;
364                 } else {
365                         EM_DEBUG_EXCEPTION("Unsuspected response: [%s]", p);
366                         err = EMAIL_ERROR_IMAP4_IDLE_FAILURE;
367                         break;
368                 }
369         }
370
371         EM_SAFE_FREE(p);
372
373         if (err == EMAIL_ERROR_NONE) {
374                 connection_info = em_malloc(sizeof(email_imap_idle_connection_info_t));
375                 if (connection_info == NULL) {
376                         EM_DEBUG_EXCEPTION("EMAIL_ERROR_OUT_OF_MEMORY");
377                         err = EMAIL_ERROR_OUT_OF_MEMORY;
378                         goto FINISH_OFF;
379                 }
380
381                 connection_info->account_id      = input_account->account_id;
382                 connection_info->mailbox_id      = input_mailbox->mailbox_id;
383                 connection_info->mail_stream     = mail_stream;
384                 connection_info->socket_fd       = socket_fd;
385                 connection_info->multi_user_name = EM_SAFE_STRDUP(multi_user_name);
386
387                 imap_idle_connection_list = g_list_append(imap_idle_connection_list, (gpointer)connection_info);
388         }
389
390 FINISH_OFF:
391
392         if (err == EMAIL_ERROR_NONE) {
393                 /* IMAP IDLE - SUCCESS */
394 //              *output_mailstream     = mail_stream;
395                 *output_socket_fd      = socket_fd;
396                 *input_connection_list = imap_idle_connection_list;
397         } else if (mail_stream)
398                 mail_stream = mail_close(mail_stream);
399
400         emcore_clear_session(session);
401
402         EM_DEBUG_FUNC_END("err [%d]", err);
403         return err;
404 }
405
406 static int emcore_imap_idle_cb(email_alarm_data_t *alarm_data, void *user_parameter)
407 {
408         EM_DEBUG_FUNC_BEGIN("alarm_data [%p] user_parameter [%p]", alarm_data, user_parameter);
409         int err = EMAIL_ERROR_NONE;
410
411         emcore_refresh_imap_idle_thread();
412
413         EM_DEBUG_FUNC_END("err [%d]", err);
414         return err;
415 }
416
417 static int emcore_refresh_alarm_for_imap_idle(char *multi_user_name)
418 {
419         EM_DEBUG_FUNC_BEGIN();
420         int err = EMAIL_ERROR_NONE;
421         int i = 0;
422         int account_count = 0;
423         int auto_sync_account_count = 0;
424         time_t current_time;
425         time_t trigger_at_time;
426         email_account_t *account_ref_list = NULL;
427
428         /* Check whether the alarm is already existing */
429         if (emcore_check_alarm_by_class_id(EMAIL_ALARM_CLASS_IMAP_IDLE) == EMAIL_ERROR_NONE) {
430                 EM_DEBUG_LOG("Already exist. Remove old one.");
431                 emcore_delete_alram_data_by_reference_id(EMAIL_ALARM_CLASS_IMAP_IDLE, 0);
432         }
433
434         if ((err = emcore_get_account_reference_list(multi_user_name,
435                                                                                                         &account_ref_list,
436                                                                                                         &account_count)) != EMAIL_ERROR_NONE) {
437                 EM_DEBUG_LOG("emcore_get_account_reference_list failed [%d]", err);
438                 goto FINISH_OFF;
439         }
440
441         for (i = 0; i < account_count; i++) {
442                 if (account_ref_list[i].incoming_server_type == EMAIL_SERVER_TYPE_IMAP4 &&
443                         (account_ref_list[i].check_interval == 0 || account_ref_list[i].peak_interval == 0)) {
444                         auto_sync_account_count++;
445                 }
446         }
447
448         if (account_ref_list)
449                 emcore_free_account_list(&account_ref_list, account_count, NULL);
450
451         if (auto_sync_account_count) {
452                 time(&current_time);
453                 trigger_at_time = current_time + (29 * 60);
454
455                 if ((err = emcore_add_alarm(multi_user_name,
456                                                                         trigger_at_time,
457                                                                         EMAIL_ALARM_CLASS_IMAP_IDLE,
458                                                                         0,
459                                                                         emcore_imap_idle_cb,
460                                                                         NULL)) != EMAIL_ERROR_NONE) {
461                         EM_DEBUG_EXCEPTION("emcore_add_alarm failed [%d]", err);
462                 }
463         }
464
465 FINISH_OFF:
466
467         EM_DEBUG_FUNC_END("err [%d]", err);
468         return err;
469 }
470
471 void* emcore_imap_idle_worker(void* thread_user_data)
472 {
473         EM_DEBUG_FUNC_BEGIN();
474         int err = EMAIL_ERROR_NONE;
475         int i = 0, j = 0;
476         int event_num = 0;
477         int epoll_fd = 0;
478         int socket_fd = 0;
479         int signal_from_pipe = 0;
480         int refresh_connection_flag = 1;
481         int account_count = 0;
482         char errno_buf[ERRNO_BUF_SIZE] = {0};
483         struct epoll_event ev = {0};
484         struct epoll_event events[MAX_EPOLL_EVENT] = {{0}, };
485         MAILSTREAM *mail_stream = NULL;
486         email_mailbox_t inbox_mailbox = {0};
487         email_account_t *account_ref_list = NULL;
488         GList *imap_idle_connection_list = NULL;
489         GList *zone_name_list = NULL;
490         GList *node = NULL;
491         email_imap_idle_connection_info_t *connection_info = NULL;
492
493         EM_DEBUG_LOG("emcore_imap_idle_worker start ");
494
495         if (pipe(imap_idle_pipe_fd) == -1) {
496                 EM_DEBUG_EXCEPTION("pipe failed");
497                 err = EMAIL_ERROR_UNKNOWN;
498                 goto FINISH_OFF;
499         }
500
501         epoll_fd = epoll_create(MAX_EPOLL_EVENT);
502
503         if (epoll_fd < 0) {
504                 EM_DEBUG_CRITICAL_EXCEPTION("epoll_create failed: [%d]", errno);
505                 err = EMAIL_ERROR_IMAP4_IDLE_FAILURE;
506                 goto FINISH_OFF;
507         }
508
509         ev.events  = EPOLLIN;
510         ev.data.fd = imap_idle_pipe_fd[0];
511
512         if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, imap_idle_pipe_fd[0], &ev) == -1) {
513                 EM_DEBUG_EXCEPTION("epoll_ctl failed: %s[%d]", EM_STRERROR(errno_buf), errno);
514         }
515
516         EM_DEBUG_LOG("Enter imap idle loop");
517         while (1) {
518                 if (refresh_connection_flag) {
519
520                         EM_DEBUG_LOG("Clear old connections");
521                         emcore_clear_old_connections(epoll_fd, &imap_idle_connection_list);
522
523                         EM_DEBUG_LOG("Getting account list");
524                         if ((err = emcore_get_zone_name_list(&zone_name_list)) != EMAIL_ERROR_NONE) {
525                                 EM_DEBUG_EXCEPTION("emcore_get_zone_name_list failed : err[%d]", err);
526                                 if (zone_name_list) g_list_free(zone_name_list);
527                                 continue;
528                         }
529
530                         if (g_list_length(zone_name_list) <= 1) {
531                                 if ((err = emcore_get_account_reference_list(NULL,
532                                                                                                                                 &account_ref_list,
533                                                                                                                                 &account_count)) != EMAIL_ERROR_NONE)
534                                         EM_DEBUG_LOG("emcore_get_account_reference_list failed [%d]", err);
535
536                                 for (i = 0; i < account_count; i++) {
537                                         if (account_ref_list[i].incoming_server_type != EMAIL_SERVER_TYPE_IMAP4 ||
538                                                 (account_ref_list[i].check_interval != 0 && account_ref_list[i].peak_interval != 0)) {
539                                                 EM_DEBUG_LOG("account_id[%d] is not for auto sync", account_ref_list[i].account_id);
540                                                 continue;
541                                         }
542
543                                         /* TODO: peak schedule handling */
544
545                                         memset(&inbox_mailbox, 0, sizeof(email_mailbox_t));
546
547                                         if (!emcore_get_mailbox_by_type(NULL,
548                                                                                                         account_ref_list[i].account_id,
549                                                                                                         EMAIL_MAILBOX_TYPE_INBOX,
550                                                                                                         &inbox_mailbox,
551                                                                                                         &err)) {
552                                                 EM_DEBUG_EXCEPTION("emcore_get_mailbox_by_type failed [%d]", err);
553                                                 continue;
554                                         }
555
556                                         EM_DEBUG_LOG("Connect to IMAP server");
557                                         err = emcore_connect_and_idle_on_mailbox(NULL,
558                                                                                                                                 &imap_idle_connection_list,
559                                                                                                                                 &(account_ref_list[i]),
560                                                                                                                                 &inbox_mailbox,
561                                                                                                                                 &mail_stream,
562                                                                                                                                 &socket_fd);
563
564                                         emcore_free_mailbox(&inbox_mailbox);
565
566                                         if (err != EMAIL_ERROR_NONE) {
567                                                 EM_DEBUG_EXCEPTION("emcore_connect_and_idle_on_mailbox failed [%d]", err);
568                                                 continue;
569                                         }
570
571                                         ev.events  = EPOLLIN;
572                                         ev.data.fd = socket_fd;
573
574                                         EM_DEBUG_LOG("Add listener for socket buffer");
575                                         if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &ev) == -1) {
576                                                 EM_DEBUG_EXCEPTION("epoll_ctl failed: %s[%d]", EM_STRERROR(errno_buf), errno);
577                                         }
578                                 }
579
580                                 if (account_ref_list)
581                                         emcore_free_account_list(&account_ref_list, account_count, NULL);
582
583                                 EM_DEBUG_LOG(" Delete old an alarm and add an alarm to refresh connections every 29min");
584                                 emcore_refresh_alarm_for_imap_idle(NULL);
585
586                                 refresh_connection_flag = 0;
587                         } else {
588                                 node = g_list_first(zone_name_list);
589
590                                 while (node != NULL) {
591                                         if (!node->data)
592                                                 node = g_list_next(node);
593
594                                         EM_DEBUG_LOG("Data name of node : [%p]", node->data);
595
596                                         if ((err = emcore_get_account_reference_list(node->data,
597                                                                                                                                         &account_ref_list,
598                                                                                                                                         &account_count)) != EMAIL_ERROR_NONE) {
599                                                 EM_DEBUG_LOG("emcore_get_account_reference_list failed [%d]", err);
600                                         }
601
602                                         for (i = 0; i < account_count; i++) {
603                                                 if (account_ref_list[i].incoming_server_type != EMAIL_SERVER_TYPE_IMAP4 ||
604                                                         (account_ref_list[i].check_interval != 0 && account_ref_list[i].peak_interval != 0)) {
605                                                         EM_DEBUG_LOG("account_id[%d] is not for auto sync", account_ref_list[i].account_id);
606                                                         continue;
607                                                 }
608
609                                                 /* TODO: peak schedule handling */
610
611                                                 memset(&inbox_mailbox, 0, sizeof(email_mailbox_t));
612
613                                                 if (!emcore_get_mailbox_by_type(node->data,
614                                                                                                                 account_ref_list[i].account_id,
615                                                                                                                 EMAIL_MAILBOX_TYPE_INBOX,
616                                                                                                                 &inbox_mailbox,
617                                                                                                                 &err)) {
618                                                         EM_DEBUG_EXCEPTION("emcore_get_mailbox_by_type failed [%d]", err);
619                                                         continue;
620                                                 }
621
622                                                 EM_DEBUG_LOG("Connect to IMAP server");
623                                                 err = emcore_connect_and_idle_on_mailbox(node->data,
624                                                                                                                                         &imap_idle_connection_list,
625                                                                                                                                         &(account_ref_list[i]),
626                                                                                                                                         &inbox_mailbox,
627                                                                                                                                         &mail_stream,
628                                                                                                                                         &socket_fd);
629
630                                                 emcore_free_mailbox(&inbox_mailbox);
631
632                                                 if (err != EMAIL_ERROR_NONE) {
633                                                         EM_DEBUG_EXCEPTION("emcore_connect_and_idle_on_mailbox failed [%d]", err);
634                                                         continue;
635                                                 }
636
637                                                 ev.events  = EPOLLIN;
638                                                 ev.data.fd = socket_fd;
639
640                                                 EM_DEBUG_LOG("Add listener for socket buffer");
641                                                 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &ev) == -1) {
642                                                         EM_DEBUG_EXCEPTION("epoll_ctl failed: %s[%d]", EM_STRERROR(errno_buf), errno);
643                                                 }
644                                         }
645
646                                         if (account_ref_list)
647                                                 emcore_free_account_list(&account_ref_list, account_count, NULL);
648
649                                         EM_DEBUG_LOG(" Delete old an alarm and add an alarm to refresh connections every 29min");
650                                         emcore_refresh_alarm_for_imap_idle(node->data);
651
652                                         EM_SAFE_FREE(node->data);
653                                         node = g_list_next(node);
654                                 }
655
656                                 refresh_connection_flag = 0;
657                         }
658
659                         if (zone_name_list)
660                                 g_list_free(zone_name_list);
661                 }
662
663                 EM_DEBUG_LOG("Waiting.......");
664                 event_num = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENT, -1);
665                 EM_DEBUG_LOG("epoll_wait returns [%d]", event_num);
666
667                 if (event_num > 0) {
668                         EM_DEBUG_LOG(">>>> Data coming from socket or pipe ");
669                         for (j = 0; j < event_num; j++) {
670                                 int event_fd = events[j].data.fd;
671
672                                 EM_DEBUG_LOG("event_fd [%d]", event_fd);
673
674                                 if (event_fd == imap_idle_pipe_fd[0]) {
675                                         EM_DEBUG_LOG(">>>> Data coming from pipe ");
676                                         if (read(imap_idle_pipe_fd[0], (void*)&signal_from_pipe, sizeof(signal_from_pipe)) != -1) {
677                                                 EM_DEBUG_LOG("Refresh IMAP connections");
678                                                 refresh_connection_flag = 1;
679                                                 continue;
680                                         }
681                                 } else {
682                                         if ((err = emcore_get_connection_info_by_socket_fd(imap_idle_connection_list,
683                                                                                                                                                 event_fd,
684                                                                                                                                                 &connection_info)) != EMAIL_ERROR_NONE) {
685                                                 EM_DEBUG_LOG("emcore_get_connection_info_by_socket_fd "
686                                                                                 "couldn't find proper connection info. [%d]", err);
687                                                 continue;
688                                         }
689
690                                         if ((err = emcore_parse_imap_idle_response(connection_info->multi_user_name,
691                                                                                                                         connection_info->account_id,
692                                                                                                                         connection_info->mailbox_id,
693                                                                                                                         connection_info->mail_stream,
694                                                                                                                         connection_info->socket_fd)) != EMAIL_ERROR_NONE) {
695                                                 EM_DEBUG_EXCEPTION("emcore_parse_imap_idle_response failed. [%d] ", err);
696                                                 refresh_connection_flag = 1;
697 //                                              mail_stream = mail_close(mail_stream);
698                                                 continue;
699                                         }
700                                 }
701                         }
702                 }
703         }
704
705         EM_DEBUG_LOG("Exit imap idle loop");
706
707 FINISH_OFF:
708         emcore_free_mailbox(&inbox_mailbox);
709
710         EM_DEBUG_LOG("Close pipes");
711
712         close(imap_idle_pipe_fd[0]);
713         close(imap_idle_pipe_fd[1]);
714
715         imap_idle_thread_id = 0;
716
717         EM_DEBUG_FUNC_END("err [%d]", err);
718         return NULL;
719 }
720
721
722 INTERNAL_FUNC int emcore_create_imap_idle_thread()
723 {
724         EM_DEBUG_FUNC_BEGIN();
725         int err = EMAIL_ERROR_NONE;
726         int thread_error;
727
728         if (imap_idle_thread_id) {
729                 EM_DEBUG_EXCEPTION("IMAP IDLE thread already exists.");
730                 err = EMAIL_ERROR_ALREADY_EXISTS;
731                 goto FINISH_OFF;
732
733         }
734
735         THREAD_CREATE(imap_idle_thread_id, emcore_imap_idle_worker, NULL, thread_error);
736
737         if (thread_error != 0) {
738                 EM_DEBUG_EXCEPTION("cannot make IMAP IDLE thread...");
739                 err = EMAIL_ERROR_UNKNOWN;
740                 goto FINISH_OFF;
741         }
742
743 FINISH_OFF:
744
745         EM_DEBUG_FUNC_END("err [%d]", err);
746         return err;
747 }
748
749 INTERNAL_FUNC int emcore_refresh_imap_idle_thread()
750 {
751         EM_DEBUG_FUNC_BEGIN();
752         int err = EMAIL_ERROR_NONE;
753         int signal = 1;
754
755         write(imap_idle_pipe_fd[1], (char *)&signal, sizeof(signal));
756
757         EM_DEBUG_FUNC_END("err [%d]", err);
758         return err;
759 }
760 #endif /*  __FEATURE_IMAP_IDLE__ */