Tizen 2.0 Release
[platform/core/messaging/email-service.git] / email-ipc / email-proxy / email-proxy-socket.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 #include <unistd.h>
25 #include <sys/select.h>
26
27 #include "email-ipc-build.h"
28 #include "email-proxy-socket.h"
29 #include "email-ipc-socket.h"
30
31 #include "email-debug-log.h"
32 #include "email-internal-types.h"
33 #include "email-utilities.h"
34 #include <errno.h>
35 #include <glib.h>
36 #include <pthread.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39
40 typedef struct {
41         pid_t pid;
42         pthread_t tid;
43         int socket_fd;
44 } thread_socket_t;
45
46 GList *socket_head = NULL;
47 pthread_mutex_t proxy_mutex = PTHREAD_MUTEX_INITIALIZER;
48
49 EXPORT_API bool emipc_start_proxy_socket()
50 {
51         EM_DEBUG_FUNC_BEGIN();
52         int ret = true;
53         int socket_fd = 0;
54
55         ret = emipc_init_email_socket(&socket_fd);
56         if (!ret) {
57                 EM_DEBUG_EXCEPTION("emipc_init_email_socket failed");
58                 return false;
59         }
60
61         ret = emipc_connect_email_socket(socket_fd);
62         if( !ret ) {
63                 EM_DEBUG_EXCEPTION("emipc_connect_email_socket failed");
64                 return false;
65         }
66
67         thread_socket_t* cur = (thread_socket_t*) em_malloc(sizeof(thread_socket_t));
68         if(!cur) {
69                 EM_DEBUG_EXCEPTION("em_malloc failed");
70                 return false;
71         }
72
73         /* add a socket */
74         cur->pid = getpid();
75         cur->tid = pthread_self();
76         cur->socket_fd = socket_fd;
77
78         ENTER_CRITICAL_SECTION(proxy_mutex);
79         socket_head = g_list_prepend(socket_head, cur);
80         LEAVE_CRITICAL_SECTION(proxy_mutex);
81
82         return true;
83 }
84
85 EXPORT_API bool emipc_end_proxy_socket()
86 {
87         EM_DEBUG_FUNC_BEGIN();
88         EM_DEBUG_LOG("[IPCLib] emipc_end_proxy_socket_fd");
89
90         pid_t pid = getpid();
91
92         ENTER_CRITICAL_SECTION(proxy_mutex);
93         GList *cur = socket_head;
94         while( cur ) {
95                 thread_socket_t* cur_socket = g_list_nth_data(cur,0);
96
97                 /* close all sockets of the pid */
98                 if( pid == cur_socket->pid ) {
99                         emipc_close_email_socket(&cur_socket->socket_fd);
100                         EM_SAFE_FREE(cur_socket);
101                         GList *del = cur;
102                         cur = g_list_next(cur);
103                         socket_head = g_list_remove_link(socket_head, del);
104                         continue;
105                 }
106
107                 cur = g_list_next(cur);
108         }
109         LEAVE_CRITICAL_SECTION(proxy_mutex);
110
111         return true;
112 }
113
114 /* return result of emipc_send_email_socket
115  * EMAIL_ERROR_IPC_SOCKET_FAILURE, when no IPC connection */
116 EXPORT_API int emipc_send_proxy_socket(unsigned char *data, int len)
117 {
118         EM_DEBUG_FUNC_BEGIN();
119         int socket_fd = emipc_get_proxy_socket_id();
120
121         /* if thread socket is not created */
122         if (!socket_fd) {
123                 int ret = emipc_start_proxy_socket();
124                 if(!ret ) {
125                         EM_DEBUG_EXCEPTION("[IPCLib] emipc_send_proxy_socket not connected");
126                         return EMAIL_ERROR_IPC_SOCKET_FAILURE;
127                 }
128                 socket_fd = emipc_get_proxy_socket_id();
129         }
130
131         int send_len = emipc_send_email_socket(socket_fd, data, len);
132         if (send_len == 0) {
133                 EM_DEBUG_EXCEPTION("[IPCLib] server closed connection %x", socket_fd);
134                 emipc_end_proxy_socket();
135         }
136
137         return send_len;
138 }
139
140 EXPORT_API int emipc_get_proxy_socket_id()
141 {
142         EM_DEBUG_FUNC_BEGIN();
143         pthread_t tid = pthread_self();
144         int socket_fd = 0;
145
146         ENTER_CRITICAL_SECTION(proxy_mutex);
147         GList *cur = socket_head;
148         /* need to acquire lock */
149         for( ; cur ; cur = g_list_next(cur) ) {
150                 thread_socket_t* cur_socket = g_list_nth_data(cur,0);
151                 if( pthread_equal(tid, cur_socket->tid) ) {
152                         socket_fd = cur_socket->socket_fd;
153                         break;
154                 }
155         }
156         LEAVE_CRITICAL_SECTION(proxy_mutex);
157         EM_DEBUG_LOG("tid %d, socket_fd %d", tid, socket_fd);
158         return socket_fd;
159 }
160
161 /* return true, when event occurred
162  * false, when select error
163  */
164 static bool wait_for_reply (int fd)
165 {
166         fd_set fds;
167
168         if (fd == 0) {
169                 EM_DEBUG_EXCEPTION("Invalid file description : [%d]", fd);
170                 return false;
171         }
172
173         FD_ZERO(&fds);
174         FD_SET(fd, &fds);
175
176         if (select(fd + 1, &fds, NULL, NULL, NULL) == -1) {
177                 EM_DEBUG_EXCEPTION("[IPCLib] select: %s", strerror(errno) );
178                 return false;
179         }
180
181         if (FD_ISSET(fd, &fds)) return true;
182
183         return false;
184 }
185
186
187 /* return result of emipc_recv_email_socket
188  * EMAIL_ERROR_IPC_SOCKET_FAILURE, when no IPC connection, or wrong fd */
189 EXPORT_API int emipc_recv_proxy_socket(char **data)
190 {
191         EM_DEBUG_FUNC_BEGIN();
192         int socket_fd = emipc_get_proxy_socket_id();
193         if (!socket_fd) {
194                 EM_DEBUG_EXCEPTION("[IPCLib] proxy_socket_fd[%p] is not available or disconnected", socket_fd);
195                 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
196         }
197
198         if( !wait_for_reply(socket_fd) ) {
199                 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
200         }
201
202         int recv_len = emipc_recv_email_socket(socket_fd, data);
203         if (recv_len == 0) {
204                 EM_DEBUG_EXCEPTION("[IPCLib] server closed connection %x", socket_fd);
205                 emipc_end_proxy_socket();
206         }
207
208         return recv_len;
209 }
210