Modify DCM message structure and so on
[platform/core/multimedia/media-server.git] / src / server / media-server-dcm.c
1 /*
2  * media-server-dcm
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jiyong Min <jiyong.min@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 #define _GNU_SOURCE
22
23 #include <dirent.h>
24 #include <errno.h>
25
26 #include "media-util.h"
27 #include "media-common-utils.h"
28 #include "media-common-system.h"
29 #include "media-server-dbg.h"
30 #include "media-server-dcm.h"
31 #include <tzplatform_config.h>
32
33 #ifdef LOG_TAG
34 #undef LOG_TAG
35 #endif
36
37 #define LOG_TAG "MEDIA_SERVER_DCM"
38
39 #define DCM_SERVER_PATH tzplatform_mkpath(TZ_SYS_BIN, "dcm-svc")
40
41 static GMainLoop *g_dcm_agent_loop = NULL;
42 static GIOChannel *g_dcm_tcp_channel = NULL;
43 static gboolean g_folk_dcm_server = FALSE;
44 static gboolean g_dcm_server_extracting = FALSE;
45 static gboolean g_shutdowning_dcm_server = FALSE;
46 static gboolean g_dcm_server_queued_all_extracting_request = FALSE;
47 static int g_dcm_comm_sock = 0;
48 static int g_dcm_timer_id = 0;
49 static int g_dcm_service_pid = 0;
50
51 static GQueue *g_dcm_request_queue = NULL;
52 static int g_dcm_queue_work = 0;
53
54 typedef struct {
55         int client_sock;
56         dcmMsg *recv_msg;
57 } dcmRequest;
58
59 extern char MEDIA_IPC_PATH[][70];
60
61 gboolean _ms_dcm_agent_timer();
62 gboolean _ms_dcm_check_queued_request(gpointer data);
63 gboolean _ms_dcm_agent_prepare_tcp_socket(int *sock_fd, unsigned short serv_port);
64
65
66 int ms_dcm_get_server_pid()
67 {
68         return g_dcm_service_pid;
69 }
70
71 void ms_dcm_reset_server_status()
72 {
73         g_folk_dcm_server = FALSE;
74         g_shutdowning_dcm_server = FALSE;
75
76         if (g_dcm_timer_id > 0) {
77                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), g_dcm_timer_id));
78                 g_dcm_timer_id = 0;
79         }
80
81         if (g_dcm_server_extracting) {
82                 /* Need to inplement when crash happens */
83                 MS_DBG_ERR("DCM server is dead when processing all-dcm extraction");
84                 g_dcm_server_extracting = FALSE;
85                 MS_DBG("g_dcm_server_extracting is false");
86                 g_dcm_service_pid = 0;
87         } else {
88                 g_dcm_server_extracting = FALSE;
89                 MS_DBG("g_dcm_server_extracting is false");
90                 g_dcm_service_pid = 0;
91         }
92
93         return;
94 }
95
96 void _ms_dcm_create_timer(int id)
97 {
98         if (id > 0)
99                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), id));
100
101         GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_60);
102         g_source_set_callback(timer_src, _ms_dcm_agent_timer, NULL, NULL);
103         g_dcm_timer_id = g_source_attach(timer_src, g_main_context_get_thread_default());
104
105 }
106
107 int _media_dcm_get_error()
108 {
109         if (errno == EWOULDBLOCK) {
110                 MS_DBG_ERR("Timeout. Can't try any more");
111                 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
112         } else {
113                 MS_DBG_STRERROR("recvfrom failed");
114                 return MS_MEDIA_ERR_SOCKET_RECEIVE;
115         }
116 }
117
118 int _ms_dcm_recv_msg(int sock, dcmMsg *msg)
119 {
120         int recv_msg_len = 0;
121         unsigned char *buf = NULL;
122
123         MS_DBG("_ms_dcm_recv_msg in");
124
125         MS_MALLOC(buf, sizeof(dcmMsg));
126         if (buf == NULL) {
127                 MS_DBG_STRERROR("malloc failed");
128                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
129         }
130
131         if ((recv_msg_len = recv(sock, buf, sizeof(dcmMsg), 0)) < 0) {
132                 MS_DBG_STRERROR("recv failed");
133                 MS_SAFE_FREE(buf);
134                 return _media_dcm_get_error();
135         }
136         memcpy(msg, buf, sizeof(dcmMsg));
137
138         MS_SAFE_FREE(buf);
139
140         MS_DBG("_ms_dcm_recv_msg out %d", msg->msg_type);
141
142         return MS_MEDIA_ERR_NONE;
143 }
144
145 gboolean _ms_dcm_agent_recv_msg_from_server()
146 {
147         struct sockaddr_un serv_addr;
148         unsigned int serv_addr_len;
149
150         int sockfd = -1;
151         int retry = 10;
152         MS_DBG("_ms_dcm_agent_recv_msg_from_server in");
153
154         if (g_dcm_comm_sock <= 0)
155                 _ms_dcm_agent_prepare_tcp_socket(&g_dcm_comm_sock, MS_DCM_COMM_PORT);
156
157         serv_addr_len = sizeof(serv_addr);
158
159         if ((sockfd = accept(g_dcm_comm_sock, (struct sockaddr*)&serv_addr, &serv_addr_len)) < 0) {
160                 MS_DBG_STRERROR("accept failed");
161                 return FALSE;
162         }
163
164         dcmMsg recv_msg;
165         int recv_result = 0;
166
167 RETRY:
168         recv_result = _ms_dcm_recv_msg(sockfd, & recv_msg);
169         if (recv_result != MS_MEDIA_ERR_NONE) {
170                 MS_DBG_STRERROR("_ms_dcm_recv_msg failed");
171                 close(sockfd);
172                 return FALSE;
173         }
174
175         if (recv_msg.msg_type == MS_MSG_DCM_SERVER_READY) {
176                 MS_DBG("DCM service is ready");
177         } else {
178                 MS_DBG("DCM service is not ready retry=%d", retry);
179                 if (retry > 0) {
180                         retry--;
181                         usleep(200000);
182                         goto RETRY;
183                 }
184         }
185
186         MS_DBG("_ms_dcm_agent_recv_msg_from_server out %d", recv_msg.msg_type);
187
188         close(sockfd);
189         return TRUE;
190 }
191
192 gboolean _ms_dcm_agent_recv_dcm_done_from_server(GIOChannel *src, GIOCondition condition, gpointer data)
193 {
194         int ret = MS_MEDIA_ERR_NONE;
195         struct sockaddr_un dcm_serv_addr;
196         unsigned int dcm_serv_addr_len;
197
198         int sockfd = -1;
199         int dcm_serv_sockfd = -1;
200
201         /* Once all-dcm extraction is done, check if there is queued all-dcm request */
202         GSource *check_queued_all_dcm_request = NULL;
203         check_queued_all_dcm_request = g_idle_source_new();
204         g_source_set_callback(check_queued_all_dcm_request, _ms_dcm_check_queued_request, NULL, NULL);
205         g_source_attach(check_queued_all_dcm_request, g_main_context_get_thread_default());
206
207         if (g_dcm_server_extracting == FALSE) {
208                 MS_DBG_WARN("Recv DCM service extracting done already");
209                 return FALSE;
210         }
211
212         sockfd = g_io_channel_unix_get_fd(src);
213         if (sockfd < 0) {
214                 MS_DBG_ERR("sock fd is invalid!");
215                 return FALSE;
216         }
217
218         dcm_serv_addr_len = sizeof(dcm_serv_addr);
219
220         if ((dcm_serv_sockfd = accept(sockfd, (struct sockaddr*)&dcm_serv_addr, &dcm_serv_addr_len)) < 0) {
221                 MS_DBG_STRERROR("accept failed");
222                 return FALSE;
223         }
224
225         dcmMsg recv_msg;
226
227         MS_DBG_WARN("DCM service SOCKET %d", dcm_serv_sockfd);
228
229         ret = ms_ipc_receive_message(dcm_serv_sockfd, &recv_msg, sizeof(dcmMsg));
230         if (ret != MS_MEDIA_ERR_NONE) {
231                 MS_DBG_STRERROR("ms_ipc_receive_message failed");
232                 close(dcm_serv_sockfd);
233                 return FALSE;
234         }
235
236         close(dcm_serv_sockfd);
237
238         MS_DBG("Receive : %d", recv_msg.msg_type);
239         if (recv_msg.msg_type == MS_MSG_DCM_EXTRACT_ALL_DONE) {
240                 MS_DBG("DCM extracting done");
241                 g_dcm_server_extracting = FALSE;
242                 MS_DBG("g_dcm_server_extracting is false");
243
244                 return FALSE;
245         }
246
247         return FALSE;
248 }
249
250 gboolean _ms_dcm_agent_execute_server()
251 {
252         int pid;
253         pid = fork();
254
255         if (pid < 0) {
256                 return FALSE;
257         } else if (pid == 0) {
258                 execl(DCM_SERVER_PATH, "dcm-svc", NULL);
259         } else {
260                 MS_DBG("Child process for dcm is %d", pid);
261                 g_folk_dcm_server = TRUE;
262         }
263
264         g_dcm_service_pid = pid;
265
266         if (!_ms_dcm_agent_recv_msg_from_server()) {
267                 MS_DBG_ERR("_ms_dcm_agent_recv_msg_from_server is failed");
268                 return FALSE;
269         }
270
271         return TRUE;
272 }
273
274 gboolean _ms_dcm_agent_send_msg_to_dcm_server(dcmMsg *recv_msg, dcmMsg *res_msg)
275 {
276         int sock;
277         ms_sock_info_s sock_info;
278         struct sockaddr_un serv_addr;
279         int send_str_len = strlen(recv_msg->msg);
280
281         if (send_str_len > MAX_FILEPATH_LEN) {
282                 MS_DBG_ERR("original path's length exceeds %d(max packet size)", MAX_FILEPATH_LEN);
283                 return FALSE;
284         }
285
286         if (ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_60, &sock_info) < 0) {
287                 MS_DBG_ERR("ms_ipc_create_client_socket failed");
288                 return FALSE;
289         }
290
291         if (recv_msg->uid == 0)
292                 ms_sys_get_uid(&(recv_msg->uid));
293         memset(&serv_addr, 0, sizeof(serv_addr));
294         sock = sock_info.sock_fd;
295         serv_addr.sun_family = AF_UNIX;
296         strncpy(serv_addr.sun_path, tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[MS_DCM_DAEMON_PORT]), strlen(tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[MS_DCM_DAEMON_PORT])));
297
298         /* Connecting to the DCM service */
299         if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
300                 MS_DBG_STRERROR("connect");
301                 return MS_MEDIA_ERR_SOCKET_CONN;
302         }
303
304         if (send(sock, recv_msg, sizeof(dcmMsg), 0) != sizeof(dcmMsg)) {
305                 MS_DBG_STRERROR("send failed");
306                 ms_ipc_delete_client_socket(&sock_info);
307                 return FALSE;
308         }
309
310         MS_DBG_SLOG("Sending msg to DCM service is successful %d", recv_msg->msg_type);
311
312         if (_ms_dcm_recv_msg(sock, res_msg) < 0) {
313                 MS_DBG_ERR("_ms_dcm_recv_msg failed");
314                 ms_ipc_delete_client_socket(&sock_info);
315                 return FALSE;
316         }
317
318         MS_DBG_SLOG("recv %s(%d, %d) from DCM daemon is successful", res_msg->msg, res_msg->msg_type, res_msg->result);
319         ms_ipc_delete_client_socket(&sock_info);
320
321         if (res_msg->msg_type == DCM_REQUEST_MEDIA && g_dcm_comm_sock > 0) { /* DCM_REQUEST_ALL_MEDIA */
322                 GSource *source = NULL;
323                 if (g_dcm_tcp_channel == NULL)
324                         g_dcm_tcp_channel = g_io_channel_unix_new(g_dcm_comm_sock);
325                 source = g_io_create_watch(g_dcm_tcp_channel, G_IO_IN);
326
327                 /* Set callback to be called when socket is readable */
328                 g_source_set_callback(source, (GSourceFunc)_ms_dcm_agent_recv_dcm_done_from_server, NULL, NULL);
329                 g_source_attach(source, g_main_context_get_thread_default());
330
331                 g_dcm_server_extracting = TRUE;
332                 MS_DBG("g_dcm_server_extracting is true");
333         }
334
335         return TRUE;
336 }
337
338 gboolean _ms_dcm_check_queued_request(gpointer data)
339 {
340         if (g_dcm_server_queued_all_extracting_request) {
341                 MS_DBG_WARN("There is queued request");
342
343                 /* request all-DCM extraction to DCM service */
344                 dcmMsg msg;
345                 dcmMsg recv_msg;
346                 memset((void *)&msg, 0, sizeof(msg));
347                 memset((void *)&recv_msg, 0, sizeof(recv_msg));
348
349                 msg.msg_type = 1; /* DCM_REQUEST_ALL_MEDIA */
350                 ms_sys_get_uid(&(msg.uid));
351                 msg.msg[0] = '\0';
352                 msg.msg_size = 0;
353
354                 /* Command All-DCM extraction to DCM service */
355                 if (!_ms_dcm_agent_send_msg_to_dcm_server(&msg, &recv_msg))
356                         MS_DBG_ERR("_ms_dcm_agent_send_msg_to_dcm_server is failed");
357
358                 g_dcm_server_queued_all_extracting_request = FALSE;
359         } else {
360                 MS_DBG("There is no queued request");
361                 return FALSE;
362         }
363
364         return FALSE;
365 }
366
367 gboolean _ms_dcm_agent_timer()
368 {
369         if (g_dcm_server_extracting) {
370                 MS_DBG("Timer is called.. But dcm-service[%d] is busy.. so timer is recreated", g_dcm_service_pid);
371
372                 _ms_dcm_create_timer(g_dcm_timer_id);
373                 return FALSE;
374         }
375
376         g_dcm_timer_id = 0;
377         MS_DBG("Timer is called.. Now killing dcm-service[%d]", g_dcm_service_pid);
378
379         if (g_dcm_service_pid > 0) {
380                 /* Kill DCM service */
381                 dcmMsg msg;
382                 dcmMsg recv_msg;
383                 memset((void *)&msg, 0, sizeof(msg));
384                 memset((void *)&recv_msg, 0, sizeof(recv_msg));
385
386                 msg.msg_type = 4; /* DCM_REQUEST_KILL_SERVER */
387                 msg.msg[0] = '\0';
388                 msg.msg_size = 0;
389
390                 /* Command Kill to DCM service */
391                 g_shutdowning_dcm_server = TRUE;
392                 if (!_ms_dcm_agent_send_msg_to_dcm_server(&msg, &recv_msg)) {
393                         MS_DBG_ERR("_ms_dcm_agent_send_msg_to_dcm_server is failed");
394                         g_shutdowning_dcm_server = FALSE;
395                 }
396                 usleep(200000);
397         } else {
398                 MS_DBG_ERR("g_dcm_service_pid is %d. Maybe there's problem in dcm-service", g_dcm_service_pid);
399         }
400
401         return FALSE;
402 }
403
404 gboolean _ms_dcm_request_to_server(gpointer data)
405 {
406         int req_len = 0;
407
408         req_len = g_queue_get_length(g_dcm_request_queue);
409
410         MS_DBG("Queue length : %d", req_len);
411
412         if (req_len <= 0) {
413                 MS_DBG("There is no request job in the queue");
414                 g_dcm_queue_work = 0;
415                 return FALSE;
416         }
417
418         if (g_shutdowning_dcm_server) {
419                 MS_DBG_ERR("DCM service is shutting down... wait for complete");
420                 usleep(10000);
421                 return TRUE;
422         }
423
424         if (g_folk_dcm_server == FALSE && g_dcm_server_extracting == FALSE) {
425                 if (g_dcm_service_pid <= 0) { /* This logic is temporary */
426                         MS_DBG_WARN("DCM service is not running.. so start it");
427                         if (!_ms_dcm_agent_execute_server()) {
428                                 MS_DBG_ERR("_ms_dcm_agent_execute_server is failed");
429                                 g_dcm_queue_work = 0;
430                                 return FALSE;
431                         } else {
432                                 _ms_dcm_create_timer(g_dcm_timer_id);
433                         }
434                 }
435         } else {
436                 /* Timer is re-created*/
437                 _ms_dcm_create_timer(g_dcm_timer_id);
438         }
439
440         dcmRequest *req = NULL;
441         req = (dcmRequest *)g_queue_pop_head(g_dcm_request_queue);
442
443 //      MS_DBG("Pop request %d %p", req->recv_msg->msg_type);
444
445         if (req == NULL) {
446                 MS_DBG_ERR("Failed to get a request job from queue");
447                 return TRUE;
448         }
449
450         int client_sock = -1;
451         dcmMsg *recv_msg = NULL;
452         dcmMsg res_msg;
453         memset((void *)&res_msg, 0, sizeof(res_msg));
454
455         client_sock = req->client_sock;
456         recv_msg = req->recv_msg;
457
458         if (req->client_sock <= 0 || req->recv_msg == NULL) {
459                 MS_DBG_ERR("client sock is below 0 or recv msg is NULL");
460                 MS_SAFE_FREE(req->recv_msg);
461                 MS_SAFE_FREE(req);
462                 return TRUE;
463         }
464
465         if (recv_msg) {
466                 if (recv_msg->msg_type == 1 && g_dcm_server_extracting) {
467                         MS_DBG_WARN("DCM service is already extracting..This request is queued.");
468                         g_dcm_server_queued_all_extracting_request = TRUE;
469                 } else {
470                         if (!_ms_dcm_agent_send_msg_to_dcm_server(recv_msg, &res_msg)) {
471                                 MS_DBG_ERR("_ms_dcm_agent_send_msg_to_dcm_server is failed");
472
473                                 dcmMsg res_msg;
474                                 memset((void *)&res_msg, 0, sizeof(res_msg));
475
476                                 res_msg.msg_type = recv_msg->msg_type;
477                                 res_msg.msg_size = strlen(recv_msg->msg);
478                                 if (res_msg.msg_size > 0)
479                                         strncpy(res_msg.msg, recv_msg->msg, res_msg.msg_size);
480                                 res_msg.result = recv_msg->result;
481
482                                 if (send(client_sock, &res_msg, sizeof(res_msg), 0) != sizeof(res_msg))
483                                         MS_DBG_STRERROR("sendto failed");
484                                 else
485                                         MS_DBG("Sent Refuse msg from %s", recv_msg->msg);
486
487                                 close(client_sock);
488
489                                 MS_SAFE_FREE(req->recv_msg);
490                                 MS_SAFE_FREE(req);
491
492                                 return TRUE;
493                         }
494                 }
495         } else {
496                 MS_DBG_ERR("recv_msg is NULL from queue request");
497         }
498
499         strncpy(res_msg.msg, recv_msg->msg, recv_msg->msg_size);
500         res_msg.msg_size = recv_msg->msg_size;
501
502         if (send(client_sock, &res_msg, sizeof(res_msg), 0) != sizeof(res_msg))
503                 MS_DBG_STRERROR("sendto failed");
504
505         close(client_sock);
506         MS_SAFE_FREE(req->recv_msg);
507         MS_SAFE_FREE(req);
508
509         return TRUE;
510 }
511
512 gboolean _ms_dcm_agent_read_socket(GIOChannel *src,
513                                                                         GIOCondition condition,
514                                                                         gpointer data)
515 {
516         struct sockaddr_un client_addr;
517         unsigned int client_addr_len;
518         dcmMsg *recv_msg = NULL;
519         int sock = -1;
520         int client_sock = -1;
521
522         struct ucred cr;
523         int cl = sizeof(struct ucred);
524
525         sock = g_io_channel_unix_get_fd(src);
526         if (sock < 0) {
527                 MS_DBG_ERR("sock fd is invalid!");
528                 return TRUE;
529         }
530
531         client_addr_len = sizeof(client_addr);
532
533         if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
534                 MS_DBG_STRERROR("accept failed");
535                 return TRUE;
536         }
537
538         MS_DBG("Client[%d] is accepted", client_sock);
539
540         recv_msg = calloc(1, sizeof(dcmMsg));
541         if (recv_msg == NULL) {
542                 MS_DBG_ERR("Failed to allocate memory");
543                 close(client_sock);
544                 return TRUE;
545         }
546
547         if (_ms_dcm_recv_msg(client_sock, recv_msg) < 0) {
548                 MS_DBG_ERR("_ms_dcm_recv_msg failed ");
549                 close(client_sock);
550                 MS_SAFE_FREE(recv_msg);
551                 return TRUE;
552         }
553
554         if (getsockopt(client_sock, SOL_SOCKET, SO_PEERCRED, &cr, (socklen_t *) &cl) < 0) {
555                 MS_DBG_ERR("credential information error");
556         }
557
558         if (getuid() != cr.uid)
559                 recv_msg->uid = cr.uid;
560
561         dcmRequest *dcm_req = NULL;
562
563         MS_MALLOC(dcm_req, sizeof(dcmRequest));
564         if (dcm_req == NULL) {
565                 MS_DBG_ERR("Failed to create request element");
566                 close(client_sock);
567                 MS_SAFE_FREE(recv_msg);
568                 return TRUE;
569         }
570
571         dcm_req->client_sock = client_sock;
572         dcm_req->recv_msg = recv_msg;
573
574         if (g_dcm_request_queue == NULL) {
575                 MS_DBG_WARN("queue is init");
576                 g_dcm_request_queue = g_queue_new();
577         }
578
579         if (g_queue_get_length(g_dcm_request_queue) >= MAX_DCM_REQUEST) {
580                 MS_DBG_WARN("Request Queue is full");
581                 dcmMsg res_msg;
582                 memset((void *)&res_msg, 0, sizeof(res_msg));
583
584                 res_msg.msg_type = recv_msg->msg_type;
585                 if (res_msg.msg_size != 0) {
586                         res_msg.msg_size = recv_msg->msg_size;
587                         strncpy(res_msg.msg, recv_msg->msg, res_msg.msg_size);
588                 }
589
590                 if (send(client_sock, &res_msg, sizeof(dcmMsg), 0) != sizeof(dcmMsg))
591                         MS_DBG_STRERROR("sendto failed");
592                 else
593                         MS_DBG("Sent Refuse msg from %s", recv_msg->msg);
594
595                 close(client_sock);
596                 MS_SAFE_FREE(dcm_req->recv_msg);
597                 MS_SAFE_FREE(dcm_req);
598
599                 return TRUE;
600         }
601
602         MS_DBG_SLOG("%s is queued", recv_msg->msg);
603         g_queue_push_tail(g_dcm_request_queue, (gpointer)dcm_req);
604
605         if (!g_dcm_queue_work) {
606                 GSource *src_request = NULL;
607                 src_request = g_idle_source_new();
608                 g_source_set_callback(src_request, _ms_dcm_request_to_server, NULL, NULL);
609                 g_source_attach(src_request, g_main_context_get_thread_default());
610                 g_dcm_queue_work = 1;
611         }
612
613         return TRUE;
614 }
615
616 gboolean _ms_dcm_agent_prepare_tcp_socket(int *sock_fd, unsigned short serv_port)
617 {
618         int sock;
619
620         if (ms_ipc_create_server_socket(MS_PROTOCOL_TCP, serv_port, &sock) < 0) {
621                 MS_DBG_ERR("_ms_dcm_create_socket failed");
622                 return FALSE;
623         }
624
625         *sock_fd = sock;
626
627         return TRUE;
628 }
629
630 gpointer ms_dcm_agent_start_thread(gpointer data)
631 {
632         int sockfd = -1;
633         GSource *source = NULL;
634         GIOChannel *channel = NULL;
635         GMainContext *context = NULL;
636
637         MS_DBG_FENTER();
638
639         /* Create and bind new TCP socket */
640         if (!_ms_dcm_agent_prepare_tcp_socket(&sockfd, MS_DCM_CREATOR_PORT)) {
641                 MS_DBG_ERR("Failed to create socket");
642                 return NULL;
643         }
644
645         context = g_main_context_new();
646
647         if (context == NULL)
648                 MS_DBG_ERR("g_main_context_new failed");
649         else
650                 MS_DBG("g_main_context_new success");
651
652         g_dcm_agent_loop = g_main_loop_new(context, FALSE);
653         g_main_context_push_thread_default(context);
654
655         /* Create new channel to watch udp socket */
656         channel = g_io_channel_unix_new(sockfd);
657         source = g_io_create_watch(channel, G_IO_IN);
658
659         /* Set callback to be called when socket is readable */
660         g_source_set_callback(source, (GSourceFunc)_ms_dcm_agent_read_socket, NULL, NULL);
661         g_source_attach(source, context);
662
663         MS_DBG("************************************");
664         MS_DBG("*** DCM Agent thread is running ***");
665         MS_DBG("************************************");
666
667         g_main_loop_run(g_dcm_agent_loop);
668
669         MS_DBG("DCM Agent thread is shutting down...");
670
671         /*close an IO channel & remove resources */
672         g_io_channel_shutdown(channel, FALSE, NULL);
673         g_io_channel_shutdown(g_dcm_tcp_channel, FALSE, NULL);
674         g_io_channel_unref(channel);
675         close(g_dcm_comm_sock);
676
677         g_main_loop_unref(g_dcm_agent_loop);
678
679         close(sockfd);
680
681         return NULL;
682 }
683