monitor: request-handler: Add debug log to catch the correct fail point
[platform/core/system/pass.git] / src / monitor / request-handler.c
1 /*
2  * PASS (Power Aware System Service)
3  *
4  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 /**
20  * @file        request-handler-thread.c
21  * @brief       TBD
22  * @ingroup     TBD
23  */
24
25 #include <glib.h>
26
27 #include <util/common.h>
28 #include <util/log.h>
29 #include <util/resource.h>
30 #include <util/thread.h>
31 #include <util/device-notifier.h>
32 #include <util/devices.h>
33 #include <util/request.h>
34 #include <util/request-handler.h>
35
36 #include <string.h>
37 #include <arpa/inet.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <sys/time.h>
42 #include <assert.h>
43
44 static void update_resource(gpointer key, gpointer value, gpointer user_data)
45 {
46         struct resource *res = value;
47         int ret;
48
49         ret = update_resource_attrs(res);
50         if (ret < 0)
51                 _E("failed to update resource attributes (name:%s,id:%d)\n",
52                                         get_resource_name(res),
53                                         get_resource_id(res));
54 }
55
56 static void
57 register_resource_to_client(struct request_client *client, struct resource *res)
58 {
59         g_hash_table_insert(client->resource_table,
60                                         GINT_TO_POINTER(get_resource_id(res)),
61                                         (gpointer)res);
62 }
63
64 static void
65 unregister_resource_from_client(struct request_client *client, int resource_id)
66 {
67         g_hash_table_remove(client->resource_table, GINT_TO_POINTER(resource_id));
68 }
69
70 static struct resource *
71 get_resource_by_id(struct request_client *client, int resource_id)
72 {
73         return g_hash_table_lookup(client->resource_table, GINT_TO_POINTER(resource_id));
74 }
75
76 static int handle_request_create_resource(struct request_client *client, char *args)
77 {
78         struct resource *res;
79         int resource_type;
80
81         if (!client || !args) {
82                 _E("Invalid parameter\n");
83                 return -ENOENT;
84         }
85
86         /**
87          * Format of REQUEST_CREATE_RESOURCE args:
88          *  - <RESOURCE_TYPE>
89          */
90         resource_type = atoi(args);
91
92         res = create_resource(resource_type);
93         if (!res) {
94                 _E("failed to create resource, res:type(%d)\n", resource_type);
95                 return -EINVAL;
96         }
97
98         register_resource_to_client(client, res);
99
100         return get_resource_id(res);
101 }
102
103 static int handle_request_delete_resource(struct request_client *client, char *args)
104 {
105         int resource_id;
106
107         if (!client || !args) {
108                 _E("Invalid parameter\n");
109                 return -ENOENT;
110         }
111
112         /**
113          * Format of REQUEST_DELETE_RESOURCE args:
114          *  - <RESOURCE_ID>
115          */
116         resource_id = atoi(args);
117
118         unregister_resource_from_client(client, resource_id);
119
120         return 0;
121 }
122
123 static int handle_request_update_resource(struct request_client *client, char *args)
124 {
125         struct resource *res;
126         int resource_id;
127         int ret;
128
129         if (!client || !args) {
130                 _E("Invalid parameter\n");
131                 return -ENOENT;
132         }
133
134         /**
135          * Format of REQUEST_UPDATE_RESOURCE args:
136          *  - <RESOURCE_ID>
137          */
138         resource_id = atoi(args);
139
140         res = get_resource_by_id(client, resource_id);
141         if (!res) {
142                 _E("failed to get resource, res:id(%d)\n", resource_id);
143                 return -EINVAL;
144         }
145
146         ret = update_resource_attrs(res);
147         if (ret < 0) {
148                 _E("failed to update resource attributes, res:name(%s)id(%d)\n",
149                                 get_resource_name(res), resource_id);
150                 return ret;
151         }
152
153         return 0;
154 }
155
156 static int handle_request_get_resource_count(struct request_client *client, char *args)
157 {
158         int resource_type;
159         int ret;
160
161         if (!client || !args) {
162                 _E("Invalid parameter\n");
163                 return -ENOENT;
164         }
165
166         /**
167          * Format of REQUEST_GET_RESOURCE_COUNT args:
168          *  - <RESOURCE_TYPE>
169          */
170         resource_type = atoi(args);
171
172         ret = get_resource_device_count(resource_type);
173         if (ret < 0) {
174                 _E("failed to get resource device count, res:type(%d)\n", resource_type);
175                 return ret;
176         }
177
178         return ret;
179 }
180
181 static int handle_request_update_resource_all(struct request_client *client, char *args)
182 {
183         if (!client) {
184                 _E("Invalid parameter\n");
185                 return -ENOENT;
186         }
187
188         /**
189          * Format of REQUEST_UPDATE_RESOURCE args:
190          *  - NULL
191          */
192         if (client->resource_table)
193                 g_hash_table_foreach(client->resource_table, (GHFunc)update_resource, NULL);
194
195         return 0;
196 }
197
198 static int handle_request_set_resource_attr(struct request_client *client, char *args, int request_type)
199 {
200         struct resource *res;
201         int resource_id, ret;
202         u_int64_t interest_masks;
203
204         if (!client || !args) {
205                 _E("Invalid parameter\n");
206                 return -ENOENT;
207         }
208
209         /**
210          * Format of REQUEST_SET_RESOURCE_ATTR and REQUEST_UNSET_RESOURCE_ATTR args:
211          *  - <RESOURCE_ID:INTEREST_MASK>
212          */
213         if (sscanf(args, "%d$%"PRIu64, &resource_id, &interest_masks) < 2) {
214                 _E("failed to get resource and attribute id, client(%d)\n",
215                                         client->socket_fd);
216                 return -EINVAL;
217         }
218
219         res = get_resource_by_id(client, resource_id);
220         if (!res) {
221                 _E("failed to get resource, client(%d) | res:name(%s)id(%d)\n",
222                                         client->socket_fd,
223                                         get_resource_name(res), resource_id);
224                 return -EINVAL;
225         }
226
227         switch (request_type) {
228         case REQUEST_SET_RESOURCE_ATTR:
229                 ret = set_resource_attr_interest(res, interest_masks);
230                 if (ret < 0)
231                         _E("failed to set attribute interest, client(%d) | res:name(%s)id(%d)\n",
232                                         client->socket_fd,
233                                         get_resource_name(res), resource_id);
234                 break;
235         case REQUEST_UNSET_RESOURCE_ATTR:
236                 ret = unset_resource_attr_interest(res, interest_masks);
237                 if (ret < 0)
238                         _E("failed to unset attribute interest, client(%d) | res:name(%s)id(%d)\n",
239                                         client->socket_fd,
240                                         get_resource_name(res), resource_id);
241                 break;
242         default:
243                 return -EINVAL;
244         }
245
246         return ret;
247 }
248
249 static int handle_request_is_resource_attr_supported(struct request_client *client, char *args)
250 {
251         struct resource *res;
252         int resource_id;
253         u_int64_t attr_id;
254
255         if (!client || !args) {
256                 _E("Invalid parameter\n");
257                 return -ENOENT;
258         }
259
260         /**
261          * Format of REQUEST_IS_RESOURCE_ATTR_SUPPORTED args:
262          *  - <RESOURCE_ID:RESOURCE_ATTR_ID>
263          */
264         if (sscanf(args, "%d$%"PRIu64"", &resource_id, &attr_id) < 2) {
265                 _E("failed to get resource and attribute id, client(%d)\n",
266                                         client->socket_fd);
267                 return -EINVAL;
268         }
269
270         res = get_resource_by_id(client, resource_id);
271         if (!res) {
272                 _E("failed to get resource, client(%d) | res:id(%d)\n",
273                                         client->socket_fd, resource_id);
274                 return -EINVAL;
275         }
276
277         return (int)is_resource_attr_supported(res, attr_id);
278 }
279
280 static int handle_request_set_resource_ctrl(struct request_client *client, char *args)
281 {
282         struct resource *res;
283         int resource_id, value, ret;
284         u_int64_t ctrl_id;
285
286         if (!client || !args) {
287                 _E("Invalid parameter\n");
288                 return -ENOENT;
289         }
290
291         /**
292          * Format of REQUEST_SET_RESOURCE_CTRL args:
293          *  - <RESOURCE_ID:CONTROL_ID:CONTROL_VALUE>
294          */
295         if (sscanf(args, "%d$%"PRIu64"$%d", &resource_id, &ctrl_id, &value) < 3) {
296                 _E("failed to get resource and control id, client(%d)\n",
297                                         client->socket_fd);
298                 return -EINVAL;
299         }
300
301         res = get_resource_by_id(client, resource_id);
302         if (!res) {
303                 _E("failed to get resource, client(%d) | res:id(%d)\n",
304                                         client->socket_fd, resource_id);
305                 return -EINVAL;
306         }
307
308         ret = set_resource_control(res, ctrl_id, (void *)(intptr_t)value);
309         if (ret < 0) {
310                 _E("failed to set resource control, client(%d) | res:name(%s)id(%d) | ctrl:name(%s)id(%"PRId64")val(%d)\n",
311                                         client->socket_fd,
312                                         get_resource_name(res), resource_id,
313                                         get_resource_control_name(res, ctrl_id), ctrl_id, value);
314                 return ret;
315         }
316
317         return 0;
318 }
319
320 static int
321 handle_request_get_json(struct request_client *client, char *args,
322                                  int request_type, char **json_string)
323 {
324         struct resource *res;
325         u_int64_t attr_id;
326         int resource_id;
327
328         if (!client) {
329                 _E("Invalid parameter\n");
330                 return -ENOENT;
331         }
332
333         /**
334          * Format of REQUEST_GET_RESOURCE_JSON args:
335          *  - <RESOURCE_ID>
336          * Format of REQUEST_GET_VALUE_JSON args:
337          *  - <RESOURCE_ID>:<ATTR_ID>
338          * Format of REQUEST_GET_RESOURCE_LIST_JSON args:
339          *  - NO ARGUMENTS
340          */
341         switch (request_type) {
342         case REQUEST_GET_RESOURCE_JSON:
343                 resource_id = atoi(args);
344                 break;
345         case REQUEST_GET_VALUE_JSON:
346                 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2)
347                         return -EINVAL;
348                 break;
349         case REQUEST_GET_RESOURCE_LIST_JSON:
350                 goto skip_res;
351         default:
352                 return -EINVAL;
353         }
354
355         res = get_resource_by_id(client, resource_id);
356         if (!res) {
357                 _E("failed to get resource, res:id(%d)\n", resource_id);
358                 return -EINVAL;
359         }
360
361 skip_res:
362         switch (request_type) {
363         case REQUEST_GET_RESOURCE_JSON:
364                 return get_resource_attrs_json(res, json_string);
365         case REQUEST_GET_VALUE_JSON:
366                 return get_resource_attr_json(res, attr_id, json_string);
367         case REQUEST_GET_RESOURCE_LIST_JSON:
368                 return get_resource_list_json(json_string);
369         default:
370                 return -EINVAL;
371         }
372 }
373
374 static int handle_request_get_value_int(struct request_client *client, char *args, int32_t *value)
375 {
376         struct resource *res;
377         int resource_id, ret;
378         u_int64_t attr_id;
379
380         if (!client || !args) {
381                 _E("Invalid parameter\n");
382                 return -ENOENT;
383         }
384
385         /**
386          * Format of REQUEST_GET_VALUE_INT args:
387          *  - <RESOURCE_ID:ATTR_ID>
388          */
389         if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
390                 _E("failed to get resource and attribute id, client(%d)\n",
391                                         client->socket_fd);
392                 return -EINVAL;
393         }
394
395         res = get_resource_by_id(client, resource_id);
396         if (!res) {
397                 _E("failed to get resource, client(%d) | res:id(%d)\n",
398                                         client->socket_fd, resource_id);
399                 return -EINVAL;
400         }
401
402         ret = get_resource_attr_int(res, attr_id, value);
403         if (ret < 0) {
404                 _E("failed to get int value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
405                                 client->socket_fd,
406                                 get_resource_name(res), resource_id,
407                                 get_resource_attr_name(res, attr_id), attr_id);
408                 return ret;
409         }
410
411         return 0;
412 }
413
414 static int handle_request_get_value_int64(struct request_client *client, char *args, int64_t *value)
415 {
416         struct resource *res;
417         int resource_id, ret;
418         u_int64_t attr_id;
419
420         if (!client || !args) {
421                 _E("Invalid parameter\n");
422                 return -ENOENT;
423         }
424
425         /**
426          * Format of REQUEST_GET_VALUE_INT64 args:
427          *  - <RESOURCE_ID:ATTR_ID>
428          */
429         if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
430                 _E("failed to get resource and attribute id, client(%d)\n",
431                                 client->socket_fd);
432                 return -EINVAL;
433         }
434
435         res = get_resource_by_id(client, resource_id);
436         if (!res) {
437                 _E("failed to get resource, client(%d) | res:id(%d)\n",
438                                 client->socket_fd, resource_id);
439                 return -EINVAL;
440         }
441
442         ret = get_resource_attr_int64(res, attr_id, value);
443         if (ret < 0) {
444                 _E("failed to get int64 value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
445                                 client->socket_fd,
446                                 get_resource_name(res), resource_id,
447                                 get_resource_attr_name(res, attr_id), attr_id);
448                 return ret;
449         }
450
451         return 0;
452 }
453
454 static int
455 handle_request_get_value_uint(struct request_client *client, char *args, u_int32_t *value)
456 {
457         struct resource *res;
458         int resource_id, ret;
459         u_int64_t attr_id;
460
461         if (!client || !args) {
462                 _E("Invalid parameter\n");
463                 return -ENOENT;
464         }
465
466         /**
467          * Format of REQUEST_GET_VALUE_UINT args:
468          *  - <RESOURCE_ID:ATTR_ID>
469          */
470         if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
471                 _E("failed to get resource and attribute id, client(%d)\n",
472                                 client->socket_fd);
473                 return -EINVAL;
474         }
475
476         res = get_resource_by_id(client, resource_id);
477         if (!res) {
478                 _E("failed to get resource, client(%d) | res:id(%d)\n",
479                                 client->socket_fd, resource_id);
480                 return -EINVAL;
481         }
482
483         ret = get_resource_attr_uint(res, attr_id, value);
484         if (ret < 0) {
485                 _E("failed to get uint value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
486                                 client->socket_fd,
487                                 get_resource_name(res), resource_id,
488                                 get_resource_attr_name(res, attr_id), attr_id);
489                 return ret;
490         }
491
492         return 0;
493 }
494
495 static int
496 handle_request_get_value_uint64(struct request_client *client, char *args, u_int64_t *value)
497 {
498         struct resource *res;
499         int resource_id, ret;
500         u_int64_t attr_id;
501
502         if (!client || !args) {
503                 _E("Invalid parameter\n");
504                 return -ENOENT;
505         }
506
507         /**
508          * Format of REQUEST_GET_VALUE_UINT64 args:
509          *  - <RESOURCE_ID:ATTR_ID>
510          */
511         if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
512                 _E("failed to get resource and attribute id, client(%d)\n",
513                                 client->socket_fd);
514                 return -EINVAL;
515         }
516
517         res = get_resource_by_id(client, resource_id);
518         if (!res) {
519                 _E("failed to get resource, client(%d) | res:id(%d)\n",
520                                 client->socket_fd, resource_id);
521                 return -EINVAL;
522         }
523
524         ret = get_resource_attr_uint64(res, attr_id, value);
525         if (ret < 0) {
526                 _E("failed to get uint64 value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
527                                 client->socket_fd,
528                                 get_resource_name(res), resource_id,
529                                 get_resource_attr_name(res, attr_id), attr_id);
530                 return ret;
531         }
532
533         return 0;
534 }
535
536 static int handle_request_get_value_double(struct request_client *client, char *args, double *value)
537 {
538         struct resource *res;
539         int resource_id, ret;
540         u_int64_t attr_id;
541
542         if (!client || !args) {
543                 _E("Invalid parameter\n");
544                 return -ENOENT;
545         }
546
547         /**
548          * Format of REQUEST_GET_VALUE_DOUBLE args:
549          *  - <RESOURCE_ID:ATTR_ID>
550          */
551         if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
552                 _E("failed to get resource and attribute id, client(%d)\n",
553                                 client->socket_fd);
554                 return -EINVAL;
555         }
556
557         res = get_resource_by_id(client, resource_id);
558         if (!res) {
559                 _E("failed to get resource, client(%d) | res:id(%d)\n",
560                                 client->socket_fd, resource_id);
561                 return -EINVAL;
562         }
563
564         ret = get_resource_attr_double(res, attr_id, value);
565         if (ret < 0) {
566                 _E("failed to get double value,  client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
567                                 client->socket_fd,
568                                 get_resource_name(res), resource_id,
569                                 get_resource_attr_name(res, attr_id), attr_id);
570                 return ret;
571         }
572
573         return 0;
574 }
575
576 static int handle_request_get_value_string(struct request_client *client, char *args, char *value)
577 {
578         struct resource *res;
579         int resource_id, ret;
580         u_int64_t attr_id;
581
582         if (!client || !args) {
583                 _E("Invalid parameter\n");
584                 return -ENOENT;
585         }
586
587         /**
588          * Format of REQUEST_GET_VALUE_INT args:
589          *  - <RESOURCE_ID:ATTR_ID>
590          */
591         if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
592                 _E("failed to get resource and attribute id, client(%d)\n",
593                                 client->socket_fd);
594                 return -EINVAL;
595         }
596
597         res = get_resource_by_id(client, resource_id);
598         if (!res) {
599                 _E("failed to get resource, client(%d) | res:id(%d)\n",
600                                 client->socket_fd, resource_id);
601                 return -EINVAL;
602         }
603
604         ret = get_resource_attr_string(res, attr_id, value);
605         if (ret < 0) {
606                 _E("failed to get string value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
607                                 client->socket_fd,
608                                 get_resource_name(res), resource_id,
609                                 get_resource_attr_name(res, attr_id), attr_id);
610                 return ret;
611         }
612
613         return 0;
614 }
615
616 static int
617 handle_request_get_value_array(struct request_client *client, char *args, struct array_value **arr)
618 {
619         struct resource *res;
620         int resource_id, ret;
621         u_int64_t attr_id;
622
623         if (!client || !args) {
624                 _E("Invalid parameter\n");
625                 return -ENOENT;
626         }
627
628         /**
629          * Format of REQUEST_GET_VALUE_ARRAY args:
630          *  - <RESOURCE_ID:ATTR_ID>
631          */
632         if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
633                 _E("failed to get resource and attribute id, client(%d)\n",
634                                 client->socket_fd);
635                 return -EINVAL;
636         }
637
638         res = get_resource_by_id(client, resource_id);
639         if (!res) {
640                 _E("failed to get resource, client(%d) | res:id(%d)\n",
641                                 client->socket_fd, resource_id);
642                 return -EINVAL;
643         }
644
645         ret = get_resource_attr_array(res, attr_id, arr);
646         if (ret < 0) {
647                 _E("failed to get array value, client(%d) | (res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
648                                 client->socket_fd,
649                                 get_resource_name(res), resource_id,
650                                 get_resource_attr_name(res, attr_id), attr_id);
651                 return ret;
652         }
653
654         return 0;
655 }
656
657 static int
658 handle_request_get_resource_ts(struct request_client *client, char *args,
659                                int64_t *start, int64_t *end)
660 {
661         struct resource *res;
662         int resource_id, ret;
663
664         if (!client || !args) {
665                 _E("Invalid parameter\n");
666                 return -ENOENT;
667         }
668
669         /**
670          * Format of REQUEST_GET_RESOURCE_TS args:
671          *  - <RESOURCE_ID>
672          */
673         resource_id = atoi(args);
674
675         res = get_resource_by_id(client, resource_id);
676         if (!res) {
677                 _E("failed to get resource, client(%d) | res:id(%d)\n",
678                                 client->socket_fd, resource_id);
679                 return -EINVAL;
680         }
681
682         ret = get_resource_ts(res, start, end);
683         if (ret < 0) {
684                 _E("failed to get timestamp value, client(%d) | res:name(%s)id(%d)\n",
685                                 client->socket_fd,
686                                 get_resource_name(res), resource_id);
687                 return ret;
688         }
689
690         return 0;
691 }
692
693 static int split_request_type_and_args(char *buffer, char **args)
694 {
695         char *request_type_str;
696
697         request_type_str = strsep(&buffer, "$");
698
699         *args = buffer;
700
701         return atoi(request_type_str);
702 }
703
704 #define ADD_RESPONSE(__buf__, __remain__, __format__, ...)      { \
705         int __len__ = snprintf(__buf__, __remain__, __format__, __VA_ARGS__); \
706         __buf__ += __len__;  \
707         __remain__ -= __len__; \
708         if (__remain__ < 0) \
709                 _E("failed to add response"); \
710 } \
711
712 static int handle_request(struct request_client *client, char *request)
713 {
714         char *response, *response_entry, *args;
715         int request_type, buffer_len, ret;
716         char err_buf[BUFF_MAX];
717
718         request_type = split_request_type_and_args(request, &args);
719
720         switch (request_type) {
721         case REQUEST_GET_RESOURCE_JSON:
722         case REQUEST_GET_VALUE_JSON:
723         case REQUEST_GET_VALUE_ARRAY:
724         case REQUEST_GET_RESOURCE_LIST_JSON:
725                 buffer_len = HUGE_BUFF_MAX + 1;
726                 break;
727         default:
728                 buffer_len = GENERIC_BUFF_MAX + 1;
729         }
730
731         response_entry = response = malloc(buffer_len);
732         if (!response_entry)
733                 return -ENOMEM;
734
735         /**
736          * Format of response
737          *  - <REQUEST_TYPE[:REQUEST_RESULT_PAYLOAD]:REQUEST_RESULT_VALUE>
738          */
739         ADD_RESPONSE(response, buffer_len, "%d$", request_type);
740
741         switch (request_type) {
742         case REQUEST_CREATE_RESOURCE:
743                 ret = handle_request_create_resource(client, args);
744                 break;
745         case REQUEST_DELETE_RESOURCE:
746                 ret = handle_request_delete_resource(client, args);
747                 break;
748         case REQUEST_UPDATE_RESOURCE:
749                 ret = handle_request_update_resource(client, args);
750                 break;
751         case REQUEST_GET_RESOURCE_COUNT:
752                 ret = handle_request_get_resource_count(client, args);
753                 break;
754         case REQUEST_UPDATE_RESOURCE_ALL:
755                 ret = handle_request_update_resource_all(client, args);
756                 break;
757         case REQUEST_SET_RESOURCE_CTRL:
758                 ret = handle_request_set_resource_ctrl(client, args);
759                 break;
760         case REQUEST_SET_RESOURCE_ATTR:
761         case REQUEST_UNSET_RESOURCE_ATTR:
762                 ret = handle_request_set_resource_attr(client, args, request_type);
763                 break;
764         case REQUEST_IS_RESOURCE_ATTR_SUPPORTED:
765                 ret = handle_request_is_resource_attr_supported(client, args);
766                 break;
767         case REQUEST_GET_RESOURCE_JSON:
768         case REQUEST_GET_VALUE_JSON:
769         case REQUEST_GET_RESOURCE_LIST_JSON:
770                 {
771                         char *json_string;
772
773                         ret = handle_request_get_json(client, args, request_type, &json_string);
774
775                         ADD_RESPONSE(response, buffer_len, "%s$", json_string);
776
777                         free(json_string);
778                 }
779                 break;
780         case REQUEST_GET_VALUE_INT:
781                 {
782                         int32_t value;
783
784                         ret = handle_request_get_value_int(client, args, &value);
785
786                         ADD_RESPONSE(response, buffer_len, "%d$", value);
787                 }
788                 break;
789         case REQUEST_GET_VALUE_INT64:
790                 {
791                         int64_t value;
792
793                         ret = handle_request_get_value_int64(client, args, &value);
794
795                         ADD_RESPONSE(response, buffer_len, "%"PRId64"$", value);
796                 }
797                 break;
798         case REQUEST_GET_VALUE_UINT:
799                 {
800                         u_int32_t value;
801
802                         ret = handle_request_get_value_uint(client, args, &value);
803
804                         ADD_RESPONSE(response, buffer_len, "%u$", value);
805                 }
806                 break;
807         case REQUEST_GET_VALUE_UINT64:
808                 {
809                         u_int64_t value;
810
811                         ret = handle_request_get_value_uint64(client, args, &value);
812
813                         ADD_RESPONSE(response, buffer_len, "%"PRIu64"$", value);
814                 }
815                 break;
816         case REQUEST_GET_VALUE_DOUBLE:
817                 {
818                         double value;
819
820                         ret = handle_request_get_value_double(client, args, &value);
821
822                         ADD_RESPONSE(response, buffer_len, "%lf$", value);
823                 }
824                 break;
825         case REQUEST_GET_VALUE_STRING:
826                 {
827                         char value[BUFF_MAX];
828
829                         ret = handle_request_get_value_string(client, args, value);
830
831                         ADD_RESPONSE(response, buffer_len, "%s$", value);
832                 }
833                 break;
834         case REQUEST_GET_VALUE_ARRAY:
835                 {
836                         struct array_value *array;
837                         int i;
838
839                         ret = handle_request_get_value_array(client, args, &array);
840
841                         if (array->length == 0) {
842                                 ADD_RESPONSE(response, buffer_len, "%d|%d|$",
843                                                 array->type, array->length);
844                                 break;
845                         }
846
847                         ADD_RESPONSE(response, buffer_len, "%d|%d|", array->type, array->length);
848
849                         switch (array->type) {
850                         case DATA_TYPE_INT:
851                                 for (i = 0; i < array->length - 1; i++)
852                                         ADD_RESPONSE(response, buffer_len, "%d,",
853                                                         ((int32_t *)array->data)[i]);
854                                 ADD_RESPONSE(response, buffer_len, "%d$",
855                                                 ((int32_t *)array->data)[i]);
856                                 break;
857                         case DATA_TYPE_INT64:
858                                 for (i = 0; i < array->length - 1; i++)
859                                         ADD_RESPONSE(response, buffer_len, "%"PRId64",",
860                                                         ((int64_t *)array->data)[i]);
861                                 ADD_RESPONSE(response, buffer_len, "%"PRId64"$",
862                                                 ((int64_t *)array->data)[i]);
863                                 break;
864                         case DATA_TYPE_UINT:
865                                 for (i = 0; i < array->length - 1; i++)
866                                         ADD_RESPONSE(response, buffer_len, "%u,",
867                                                         ((u_int32_t *)array->data)[i]);
868                                 ADD_RESPONSE(response, buffer_len, "%u$",
869                                                 ((u_int32_t *)array->data)[i]);
870                                 break;
871                         case DATA_TYPE_UINT64:
872                                 for (i = 0; i < array->length - 1; i++)
873                                         ADD_RESPONSE(response, buffer_len, "%"PRIu64",",
874                                                         ((u_int64_t *)array->data)[i]);
875                                 ADD_RESPONSE(response, buffer_len, "%"PRIu64"$",
876                                                 ((u_int64_t *)array->data)[i]);
877                                 break;
878                         case DATA_TYPE_DOUBLE:
879                                 for (i = 0; i < array->length - 1; i++)
880                                         ADD_RESPONSE(response, buffer_len, "%lf,",
881                                                         ((double *)array->data)[i]);
882                                 ADD_RESPONSE(response, buffer_len, "%lf$",
883                                                 ((double *)array->data)[i]);
884                                 break;
885                         case DATA_TYPE_STRING:
886                                 for (i = 0; i < array->length - 1; i++)
887                                         ADD_RESPONSE(response, buffer_len, "%s,",
888                                                         ((char **)array->data)[i]);
889                                 ADD_RESPONSE(response, buffer_len, "%s$",
890                                                 ((char **)array->data)[i]);
891                                 break;
892                         default:
893                                 _E("Not supported data type");
894                         }
895                 }
896                 break;
897         case REQUEST_GET_RESOURCE_TS:
898                 {
899                         int64_t start, end;
900
901                         ret = handle_request_get_resource_ts(client, args, &start, &end);
902
903                         ADD_RESPONSE(response, buffer_len, "%"PRId64"$%"PRId64"$", start, end);
904                 }
905                 break;
906         default:
907                 _E("Invliad request type: %d", request_type);
908                 ret = -EINVAL;
909                 break;
910         }
911         ADD_RESPONSE(response, buffer_len, "%d", ret);
912
913         if (send(client->socket_fd, response_entry, strlen(response_entry), 0) < 0) {
914                 strerror_r(errno, err_buf, BUFF_MAX);
915                 _E("Failed to send respones, errno: %d, error: %s", errno, err_buf);
916         }
917
918         free(response_entry);
919
920         return 0;
921 }
922
923 static GList *g_request_client_head;
924 static GMutex g_server_lock;
925
926 static void add_client_to_list(struct request_client *client)
927 {
928         if (!client)
929                 return;
930
931         g_mutex_lock(&g_server_lock);
932         g_request_client_head =
933                         g_list_append(g_request_client_head, (gpointer)client);
934         g_mutex_unlock(&g_server_lock);
935 }
936
937 static void remove_client_from_list(struct request_client *client)
938 {
939         if (!client)
940                 return;
941
942         g_mutex_lock(&g_server_lock);
943         g_request_client_head =
944                         g_list_remove(g_request_client_head, (gpointer)client);
945         g_mutex_unlock(&g_server_lock);
946 }
947
948 static void destroy_request_client(struct request_client *client)
949 {
950         remove_client_from_list(client);
951         free(client);
952 }
953
954 static int request_handler_func(void *data, void **result)
955 {
956         char request[GENERIC_BUFF_MAX + 1];
957         struct request_client *client = (struct request_client *)data;
958         int len, ret;
959         char err_buf[BUFF_MAX];
960
961         _D("Client-%d is connected", client->socket_fd);
962
963         while (1) {
964                 len = recv(client->socket_fd, request, GENERIC_BUFF_MAX, 0);
965                 if (len == 0)
966                         break;
967
968                 if (len < 0) {
969                         strerror_r(errno, err_buf, BUFF_MAX);
970                         _E("Error occurs while receiving request: errno: %d, error: %s",
971                                         errno, err_buf);
972                         break;
973                 }
974
975                 request[len] = '\0';
976                 ret = handle_request(client, request);
977                 if (ret < 0)
978                         break;
979         }
980
981         _D("Client-%d is disconnected", client->socket_fd);
982         g_hash_table_destroy(client->resource_table);
983         close(client->socket_fd);
984         destroy_request_client(client);
985
986         return THREAD_RETURN_DONE;
987 }
988
989 int create_request_client(int socket_fd)
990 {
991         struct request_client *client;
992
993         client = malloc(sizeof(struct request_client));
994         if (!client) {
995                 _E("Failed to allocate memory of request_client");
996                 return -ENOMEM;
997         }
998
999         client->socket_fd = socket_fd;
1000         client->resource_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1001                                                        NULL, (GDestroyNotify)delete_resource);
1002
1003         create_daemon_thread(&client->worker, request_handler_func, client);
1004
1005         add_client_to_list(client);
1006
1007         return 0;
1008 }
1009