Tizen 2.0 Release
[platform/core/messaging/email-service.git] / email-core / email-network / email-network.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 /******************************************************************************
25  * File: email-network.c
26  * Desc: Data network interface
27  *
28  * Auth:
29  *
30  * History:
31  *      2006.11.17 : created
32  *****************************************************************************/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/stat.h>
39 #include <signal.h>
40 #include <netdb.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <errno.h>
44 #include <email-storage.h> 
45 #include <vconf.h>
46 #include "glib.h"
47
48 #include "lnx_inc.h"
49 #include "utf8aux.h"
50 #include "c-client.h"
51 #include "email-debug-log.h"
52 #include "email-types.h"
53 #include "email-core-utils.h" 
54 #include "email-core-mailbox.h"
55
56 #ifdef __FEATURE_PARTIAL_BODY_DOWNLOAD__
57 #include "email-core-event.h"
58 #endif
59
60 /* _get_network_status - Get the data network status from vconf */
61 static int _get_network_status(int *network_status)
62 {
63         EM_DEBUG_FUNC_BEGIN("network_status [%p]", network_status);
64
65         int value = 0;
66
67         if(!network_status) {
68                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
69                 return EMAIL_ERROR_INVALID_PARAM;
70         }
71
72         if (vconf_get_int(VCONFKEY_NETWORK_STATUS, &value)) {
73                 EM_DEBUG_EXCEPTION("Failed vconf_get_int [VCONFKEY_NETWORK_STATUS]");
74                 return EMAIL_ERROR_SYSTEM_FAILURE;
75         }
76
77         *network_status = value;
78
79         EM_DEBUG_FUNC_END("network_status [%d]", value);
80         return EMAIL_ERROR_NONE;
81 }
82
83 /* Check code for SIM status */
84 static int  _get_sim_status(int *sim_status)
85 {
86         EM_DEBUG_FUNC_BEGIN();
87         int value;
88
89         if(!sim_status) {
90                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
91                 return EMAIL_ERROR_INVALID_PARAM;
92         }
93
94         if (vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &value)  != 0) {
95                 EM_DEBUG_EXCEPTION("Failed vconf_get_int [VCONFKEY_TELEPHONY_SIM_SLOT]");
96                 return EMAIL_ERROR_SYSTEM_FAILURE;
97         }
98
99         *sim_status = value;
100
101         EM_DEBUG_FUNC_END("status[%d]", value);
102         return EMAIL_ERROR_NONE;
103 }
104
105 static int _get_wifi_status(int *wifi_status)
106 {
107         EM_DEBUG_FUNC_BEGIN();
108
109         int value;
110
111         if(!wifi_status) {
112                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
113                 return EMAIL_ERROR_INVALID_PARAM;
114         }
115
116         if (vconf_get_int(VCONFKEY_WIFI_STATE, &value)  != 0) {
117                 EM_DEBUG_EXCEPTION("vconf_get_int failed");
118                 return EMAIL_ERROR_SYSTEM_FAILURE;
119         }
120
121         *wifi_status = value;
122
123         EM_DEBUG_FUNC_END("status[%d]", *wifi_status);
124         return EMAIL_ERROR_NONE;
125 }
126
127
128 INTERNAL_FUNC int emnetwork_check_network_status(int *err_code)
129 {
130         EM_DEBUG_FUNC_BEGIN();
131         int network_status = 0;
132         int sim_status     = VCONFKEY_TELEPHONY_SIM_UNKNOWN;
133         int wifi_status    = 0;
134         int err            = EMAIL_ERROR_NONE;
135         int ret            = false;
136
137         if ( (err = _get_network_status(&network_status)) != EMAIL_ERROR_NONE) {
138                 EM_DEBUG_EXCEPTION("_get_network_status failed [%d]", err);
139                 goto FINISH_OFF;
140         }
141
142         if(network_status == 0) {
143                 EM_DEBUG_LOG("VCONFKEY_NETWORK_STATUS is 0");
144
145                 if ( (err = _get_wifi_status(&wifi_status)) != EMAIL_ERROR_NONE) {
146                         EM_DEBUG_EXCEPTION("_get_wifi_status failed [%d]", err);
147                         goto FINISH_OFF;
148                 }
149
150                 if (wifi_status == 0) {
151                         EM_DEBUG_LOG("Furthermore, WIFI is off");
152
153                         if ( (err = _get_sim_status(&sim_status)) != EMAIL_ERROR_NONE) {
154                                 EM_DEBUG_EXCEPTION("_get_sim_status failed [%d]", err);
155                                 goto FINISH_OFF;
156                         }
157
158                         if (sim_status != VCONFKEY_TELEPHONY_SIM_INSERTED) {
159                                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_NO_SIM_INSERTED");
160                                 err = EMAIL_ERROR_NO_SIM_INSERTED;
161                                 goto FINISH_OFF;
162                         }
163
164                         EM_DEBUG_EXCEPTION("EMAIL_ERROR_NETWORK_NOT_AVAILABLE");
165                         err = EMAIL_ERROR_NETWORK_NOT_AVAILABLE;
166                         goto FINISH_OFF;
167                 }
168         }
169
170         EM_DEBUG_LOG("Data Network Mode is ON");
171         ret = true;
172
173 FINISH_OFF: 
174
175         emcore_set_network_error(err);
176
177         if (err_code)
178                 *err_code = err;
179
180         EM_DEBUG_FUNC_END();
181
182         return ret;
183 }
184
185 INTERNAL_FUNC long emnetwork_callback_ssl_cert_query(char *reason, char *host, char *cert)
186 {
187         EM_DEBUG_FUNC_BEGIN("reason[%s], host[%s], cert[%s]", reason, host, cert);
188         int ret = 1;
189
190         /*  FIXME : add user interface for Accept or Reject */
191         /*  1:Accept - ignore this certificate error */
192         /*  0:Reject - stop ssl connection */
193         ret = 1;
194
195         EM_DEBUG_FUNC_END("ret[%s]", ret ? "ignore error" : "stop connection");
196         return ret;
197 }
198
199 /* ------ socket read/write handle ---------------------------------------- */
200 int _g_canceled = 0;
201 /*  TCPSTREAM = SENDSTREAM->netstream->stream; socket-id = TCPSTREAM->tcpsi, tcpso; */
202 /*  sockid_in  = ((TCPSTREAM*)send_stream->netstream->stream)->tcpsi; */
203 /*  sockid_out = ((TCPSTREAM*)send_stream->netstream->stream)->tcpso; */
204
205 INTERNAL_FUNC long tcp_getbuffer_lnx(TCPSTREAM *stream, unsigned long size, char *s)
206 {
207         struct timeval tmout;
208         fd_set readfds;
209         int nleave, nread, sret, sockid, maxfd;
210         char *p = s;
211         int max_timeout = 0;
212         sockid = stream->tcpsi;
213         maxfd = sockid + 1;
214 /* EM_DEBUG_LOG("start sockid %d", sockid);     */
215         if (sockid < 0) return 0;
216
217         if (stream->ictr > 0) {
218                 int copy_sz;
219                 if (stream->ictr >= size) {
220                         memcpy(p, stream->iptr, size);
221                         copy_sz = size;
222                 }
223                 else {
224                         memcpy(p, stream->iptr, stream->ictr);
225                         copy_sz = stream->ictr;
226                 }
227                 p += copy_sz;
228                 nleave = size - copy_sz;
229                 stream->iptr += copy_sz;
230                 stream->ictr -= copy_sz;
231
232                 if (nleave <= 0) {
233                         *p = '\0';
234                         /* EM_DEBUG_LOG("end"); */
235                         return 1;
236                 }
237         }
238         else {
239                 nleave = size;
240         }
241
242         while (nleave > 0) {
243 #ifdef TEST_CANCEL_JOB
244                 if (!emcore_check_thread_status()) {
245                         EM_DEBUG_EXCEPTION("thread canceled");
246                         tcp_abort(stream);
247                         goto JOB_CANCEL;
248                 }
249 #endif
250                 /* if (_g_canceled){ */
251                 /*      EM_DEBUG_LOG1("thread canceled\n"); */
252                 /*      tcp_abort(stream); */
253                 /*      return 0; */
254                 /* } */
255
256                 tmout.tv_usec = 0;
257                 tmout.tv_sec = 1;
258                 FD_ZERO(&readfds);
259                 FD_SET(sockid, &readfds);
260
261                 sret = select(maxfd, &readfds, NULL, NULL, &tmout);
262                 if (sret < 0) {
263                         EM_DEBUG_EXCEPTION("select error[%d]\n", errno);
264                         tcp_abort(stream);
265                         return 0;
266                 }
267                 else if (!sret) {
268                         if (max_timeout >= 5) {
269                                 EM_DEBUG_EXCEPTION("max select timeout %d", max_timeout);
270                                 emcore_set_network_error(EMAIL_ERROR_NO_RESPONSE);
271                                 return 0;
272                         }
273                         EM_DEBUG_EXCEPTION("%d select timeout", max_timeout);
274                         ++max_timeout;
275                         continue;
276                 }
277
278                 nread = read(sockid, p, nleave);
279                 if (nread < 0) {
280                         EM_DEBUG_EXCEPTION("socket read error");
281 /*                      if (errno == EINTR) continue; */
282                         tcp_abort(stream);
283                         return 0;
284                 }
285
286                 if (!nread) {
287                         EM_DEBUG_EXCEPTION("socket read no data");
288                         tcp_abort(stream);
289                         return 0;
290                 }
291
292                 p += nread;
293                 nleave -= nread;
294         }
295
296         *p = '\0';
297
298         if (_g_canceled) {
299                 EM_DEBUG_EXCEPTION("thread canceled");
300                 tcp_abort(stream);
301                 return 0;
302         }
303
304         return 1;
305 /*      EM_DEBUG_LOG("end"); */
306 #ifdef TEST_CANCEL_JOB
307 JOB_CANCEL:
308         return 0;
309 #endif
310 }
311
312 long tcp_getdata_lnx(TCPSTREAM *stream)
313 {
314         struct timeval tmout;
315         fd_set readfds;
316         int nread, sret, sockid, maxfd;
317         int max_timeout = 0;
318         
319         sockid = stream->tcpsi;
320         maxfd = sockid + 1;
321         
322         /* EM_DEBUG_LOG("start sockid %d", sockid);     */
323         if (sockid < 0) return false;
324         
325         while (stream->ictr < 1)  {
326 #ifdef TEST_CANCEL_JOB
327                 if (!emcore_check_thread_status())  {
328                         EM_DEBUG_EXCEPTION("thread canceled...");
329                         tcp_abort(stream);
330                         goto JOB_CANCEL;
331                 }
332 #endif
333                 
334                 /* if (_g_canceled){ */
335                 /*      EM_DEBUG_LOG1("thread canceled\n"); */
336                 /*      tcp_abort(stream); */
337                 /*      return 0; */
338                 /* } */
339                 
340                 tmout.tv_usec = 0;/* 1000*10; */
341                 tmout.tv_sec = 1;
342                 
343                 FD_ZERO(&readfds);
344                 FD_SET(sockid, &readfds);
345                 
346                 sret = select(maxfd, &readfds, NULL, NULL, &tmout);
347                 
348                 if (sret < 0) {
349                         EM_DEBUG_LOG("select error[%d]", errno);
350                         
351                         tcp_abort(stream);
352                         return false;
353                 }
354                 else if (!sret) {
355                         if (max_timeout >= 50) {
356                                 EM_DEBUG_EXCEPTION("max select timeout %d", max_timeout);
357                                 
358                                 emcore_set_network_error(EMAIL_ERROR_NO_RESPONSE);
359                                 return false;
360                         }
361                         
362                         EM_DEBUG_EXCEPTION("%d select timeout", max_timeout);
363                         
364                         ++max_timeout;
365                         continue;
366                 }
367                 
368                 if ((nread = read(sockid, stream->ibuf, BUFLEN)) < 0) {
369                         EM_DEBUG_EXCEPTION("socket read failed...");
370                         
371                         emcore_set_network_error(EMAIL_ERROR_SOCKET_FAILURE);
372                         
373                         /* if (errno == EINTR) contine; */
374                         tcp_abort(stream);
375                         return false;
376                 }
377                 
378                 if (!nread) {
379                         EM_DEBUG_EXCEPTION("socket read no data...");
380                         
381                         emcore_set_network_error(EMAIL_ERROR_INVALID_RESPONSE);
382                         
383                         tcp_abort(stream);
384                         return false;
385                 }
386                 
387                 stream->ictr = nread;
388                 stream->iptr = stream->ibuf;
389         }
390         
391         if (_g_canceled) {
392                 EM_DEBUG_EXCEPTION("\t thread canceled...\n");
393                 
394                 tcp_abort(stream);
395                 return false;
396         }
397         
398         /* EM_DEBUG_LOG("end"); */
399         return true;
400         
401 #ifdef TEST_CANCEL_JOB
402 JOB_CANCEL:
403         return false;
404 #endif
405 }
406
407 INTERNAL_FUNC long tcp_sout_lnx(TCPSTREAM *stream, char *string, unsigned long size)
408 {
409         struct timeval tmout;
410         fd_set writefds;
411         int sret, nwrite, maxfd, sockid;
412         int max_timeout = 0;
413         
414         sockid = stream->tcpso;
415         maxfd = sockid + 1;
416 /* EM_DEBUG_LOG("start sockid %d", sockid); */
417         if (sockid < 0) return 0;
418
419         while (size > 0) {
420 #ifdef TEST_CANCEL_JOB
421                 if (!emcore_check_thread_status()) {
422                         EM_DEBUG_EXCEPTION("thread canceled");
423                         tcp_abort(stream);
424                         goto JOB_CANCEL;
425                 }
426 #endif
427                 /* if (_g_canceled){ */
428                 /*      EM_DEBUG_LOG1("thread canceled"); */
429                 /*      tcp_abort(stream); */
430                 /*      return 0; */
431                 /* } */
432
433                 tmout.tv_usec = 0;
434                 tmout.tv_sec = 1;
435                 FD_ZERO(&writefds);
436                 FD_SET(sockid, &writefds);
437
438                 sret = select(maxfd, NULL, &writefds, NULL, &tmout);
439                 if (sret < 0) {
440                         EM_DEBUG_LOG("select error[%d]", errno);
441                         tcp_abort(stream);
442                         return 0;
443                 }
444                 else if (!sret) {
445                         if (max_timeout >= 50) {
446                                 EM_DEBUG_EXCEPTION("max select timeout %d", max_timeout);
447                                 emcore_set_network_error(EMAIL_ERROR_NO_RESPONSE);
448                                 return 0;
449                         }
450                         EM_DEBUG_EXCEPTION("%d select timeout", max_timeout);
451                         ++max_timeout;
452                         continue;
453                 }
454
455                 if ((nwrite = write(sockid, string, size)) < 0) { /*prevent 22857*/
456                         EM_DEBUG_EXCEPTION("socket write error");
457 /*                      if (errno == EINTR) continue; */
458                         tcp_abort(stream);
459                         return 0;
460                 }
461
462                 if (!nwrite) {
463                         EM_DEBUG_EXCEPTION("socket write no data");
464                         tcp_abort(stream);
465                         return 0;
466                 }
467
468                 string += nwrite;
469                 size -= nwrite;
470         }
471
472         if (_g_canceled) {
473                 EM_DEBUG_EXCEPTION("thread canceled");
474                 tcp_abort(stream);
475                 return 0;
476         }
477 /* EM_DEBUG_LOG("end"); */
478         return 1;
479
480 #ifdef TEST_CANCEL_JOB
481 JOB_CANCEL:
482         return 0;
483 #endif
484 }
485
486 INTERNAL_FUNC long tcp_soutr_lnx(TCPSTREAM *stream, char *string)
487 {
488         return tcp_sout_lnx(stream, string, EM_SAFE_STRLEN(string));
489 }
490