2 * PASS (Power Aware System Service)
4 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * @file request-handler.c
27 #include <util/common.h>
28 #include <util/devices.h>
30 #include <util/thread.h>
31 #include <monitor/request.h>
32 #include <monitor/monitor.h>
34 #include <libsyscommon/resource-manager.h>
35 #include <libsyscommon/resource-type.h>
36 #include <libsyscommon/resource-device.h>
39 #include <arpa/inet.h>
40 #include <sys/types.h>
41 #include <sys/socket.h>
43 #include <netinet/in.h>
48 #include <systemd/sd-daemon.h>
51 #define REQUEST_SERVER_PORT 10001
53 struct request_client {
56 struct thread *worker;
57 GHashTable *resource_table;
60 struct resource_instance {
62 struct syscommon_resman_resource *res;
68 static int g_resource_id;
69 static bool g_request_server_run;
70 static struct thread *g_server_thread;
73 register_resource_to_client(struct request_client *client, struct resource_instance *res_inst)
75 g_hash_table_insert(client->resource_table,
76 GINT_TO_POINTER(res_inst->id),
81 unregister_resource_from_client(struct request_client *client, int resource_id)
83 g_hash_table_remove(client->resource_table, GINT_TO_POINTER(resource_id));
86 static struct resource_instance *
87 get_resource_instance_by_id(struct request_client *client, int resource_id)
89 return g_hash_table_lookup(client->resource_table, GINT_TO_POINTER(resource_id));
92 static struct syscommon_resman_resource *
93 get_resource_by_id(struct request_client *client, int resource_id)
95 struct resource_instance *res_inst = get_resource_instance_by_id(client, resource_id);
97 res_inst = get_resource_instance_by_id(client, resource_id);
101 return res_inst->res;
104 static int clear_sign_bit(unsigned int val)
106 return (int)((val << 1) >> 1);
109 static int handle_request_create_resource(struct request_client *client, char *args)
111 struct resource_instance *res_inst;
112 int resource_type, ret;
114 if (!client || !args) {
115 _E("Invalid parameter\n");
119 res_inst = calloc(1, sizeof(struct resource_instance));
124 * Format of REQUEST_CREATE_RESOURCE args:
127 resource_type = atoi(args);
129 ret = syscommon_resman_create_resource(&res_inst->res, resource_type);
131 _E("failed to create resource, res:type(%d)\n", resource_type);
136 res_inst->id = clear_sign_bit(
137 (unsigned int)__sync_fetch_and_add(&g_resource_id, 1));
139 register_resource_to_client(client, res_inst);
144 static int handle_request_delete_resource(struct request_client *client, char *args)
148 if (!client || !args) {
149 _E("Invalid parameter\n");
154 * Format of REQUEST_DELETE_RESOURCE args:
157 resource_id = atoi(args);
159 unregister_resource_from_client(client, resource_id);
164 inline __attribute__((always_inline)) int64_t get_time_now(void)
168 gettimeofday(&tv, NULL);
169 return (int64_t)tv.tv_sec * 1000000 + (int64_t)tv.tv_usec;
172 static int handle_request_update_resource(struct request_client *client, char *args)
174 struct resource_instance *res_inst;
175 struct syscommon_resman_resource *res;
179 if (!client || !args) {
180 _E("Invalid parameter\n");
185 * Format of REQUEST_UPDATE_RESOURCE args:
188 resource_id = atoi(args);
190 res_inst = get_resource_instance_by_id(client, resource_id);
192 _E("failed to get resource instance, res:id(%d)\n", resource_id);
198 res_inst->ts_start = get_time_now();
199 ret = syscommon_resman_update_resource_attrs(res);
200 res_inst->ts_end = get_time_now();
202 res_inst->ts_start = res_inst->ts_end = 0;
203 _E("failed to update resource attributes, res:name(%s)id(%d)\n",
204 syscommon_resman_get_resource_name(res), resource_id);
211 static int syscommon_resman_get_resource_count(int resource_type)
213 const struct syscommon_resman_resource_driver *driver;
214 int count = syscommon_resman_get_resource_device_count(resource_type);
219 driver = syscommon_resman_find_resource_driver(resource_type);
223 if (driver->flag & SYSCOMMON_RESMAN_RESOURCE_DRIVER_FLAG_COUNT_ONLY_ONE)
225 else if (driver->flag & SYSCOMMON_RESMAN_RESOURCE_DRIVER_FLAG_UNCOUNTABLE)
231 static int handle_request_get_resource_count(struct request_client *client, char *args, int *value)
236 if (!client || !args) {
237 _E("Invalid parameter\n");
242 * Format of REQUEST_GET_RESOURCE_COUNT args:
245 resource_type = atoi(args);
247 ret = syscommon_resman_get_resource_count(resource_type);
249 _E("failed to get resource device count, res:type(%d)\n", resource_type);
257 static void update_resource(gpointer key, gpointer value, gpointer user_data)
259 struct resource_instance *res_inst = value;
260 struct syscommon_resman_resource *res = res_inst->res;
263 ret = syscommon_resman_update_resource_attrs(res);
265 _E("failed to update resource attributes (name:%s,id:%d)\n",
266 syscommon_resman_get_resource_name(res), res_inst->id);
270 static int handle_request_update_resource_all(struct request_client *client, char *args)
273 _E("Invalid parameter\n");
278 * Format of REQUEST_UPDATE_RESOURCE args:
281 if (client->resource_table)
282 g_hash_table_foreach(client->resource_table, (GHFunc)update_resource, NULL);
287 static int handle_request_set_resource_attr(struct request_client *client, char *args, int request_type)
289 struct syscommon_resman_resource *res;
290 int resource_id, ret;
291 u_int64_t interest_masks;
293 if (!client || !args) {
294 _E("Invalid parameter\n");
299 * Format of REQUEST_SET_RESOURCE_ATTR and REQUEST_UNSET_RESOURCE_ATTR args:
300 * - <RESOURCE_ID:INTEREST_MASK>
302 if (sscanf(args, "%d$%"PRIu64, &resource_id, &interest_masks) < 2) {
303 _E("failed to get resource and attribute id, client(%d)\n",
308 res = get_resource_by_id(client, resource_id);
310 _E("failed to get resource, client(%d) | res:id(%d)\n",
311 client->socket_fd, resource_id);
315 switch (request_type) {
316 case REQUEST_SET_RESOURCE_ATTR:
317 ret = syscommon_resman_set_resource_attr_interest(res, interest_masks);
319 _E("failed to set attribute interest, client(%d) | res:name(%s)id(%d)\n",
321 syscommon_resman_get_resource_name(res), resource_id);
323 case REQUEST_UNSET_RESOURCE_ATTR:
324 ret = syscommon_resman_unset_resource_attr_interest(res, interest_masks);
326 _E("failed to unset attribute interest, client(%d) | res:name(%s)id(%d)\n",
328 syscommon_resman_get_resource_name(res), resource_id);
330 case REQUEST_IS_RESOURCE_ATTR_SET:
331 ret = (int)syscommon_resman_is_resource_attr_interested(res, interest_masks);
340 static int handle_request_set_resource_flag(struct request_client *client, char *args)
342 struct syscommon_resman_resource *res;
343 int resource_id, ret;
346 if (!client || !args) {
347 _E("Invalid parameter\n");
352 * Format of REQUEST_SET_RESOURCE_ATTR and REQUEST_UNSET_RESOURCE_ATTR args:
355 if (sscanf(args, "%d$%"PRIu64, &resource_id, &flag_mask) < 2) {
356 _E("failed to get resource and flag mask, client(%d)\n",
361 res = get_resource_by_id(client, resource_id);
363 _E("failed to get resource, client(%d) | res:id(%d)\n",
364 client->socket_fd, resource_id);
368 ret = syscommon_resman_set_resource_flag(res, flag_mask);
370 _E("failed to set flag to %"PRIu64", client(%d) | res:name(%s)id(%d)\n",
371 flag_mask, client->socket_fd,
372 syscommon_resman_get_resource_name(res), resource_id);
379 static int handle_request_is_resource_attr_supported(struct request_client *client, char *args, bool *supported)
381 struct resource *res;
385 if (!client || !args) {
386 _E("Invalid parameter\n");
391 * Format of REQUEST_IS_RESOURCE_ATTR_SUPPORTED args:
392 * - <RESOURCE_ID:RESOURCE_ATTR_ID>
394 if (sscanf(args, "%d$%"PRIu64"", &resource_id, &attr_id) < 2) {
395 _E("failed to get resource and attribute id, client(%d)\n",
400 res = get_resource_by_id(client, resource_id);
402 _E("failed to get resource, client(%d) | res:id(%d)\n",
403 client->socket_fd, resource_id);
407 return syscommon_resman_is_resource_attr_supported(res, attr_id, supported);
410 static int handle_request_set_resource_ctrl(struct request_client *client, char *args)
412 struct syscommon_resman_resource *res;
413 int resource_id, value, ret;
416 if (!client || !args) {
417 _E("Invalid parameter\n");
422 * Format of REQUEST_SET_RESOURCE_CTRL args:
423 * - <RESOURCE_ID:CONTROL_ID:CONTROL_VALUE>
425 if (sscanf(args, "%d$%"PRIu64"$%d", &resource_id, &ctrl_id, &value) < 3) {
426 _E("failed to get resource and control id, client(%d)\n",
431 res = get_resource_by_id(client, resource_id);
433 _E("failed to get resource, client(%d) | res:id(%d)\n",
434 client->socket_fd, resource_id);
438 ret = syscommon_resman_set_resource_control(res, ctrl_id, (void *)(intptr_t)value);
440 _E("failed to set resource control, client(%d) | res:name(%s)id(%d) | ctrl:name(%s)id(%"PRId64")val(%d)\n",
442 syscommon_resman_get_resource_name(res), resource_id,
443 syscommon_resman_get_resource_control_name(res, ctrl_id), ctrl_id, value);
451 handle_request_get_json(struct request_client *client, char *args,
452 int request_type, char **json_string)
454 struct syscommon_resman_resource *res;
459 _E("Invalid parameter\n");
464 * Format of REQUEST_GET_RESOURCE_JSON args:
466 * Format of REQUEST_GET_VALUE_JSON args:
467 * - <RESOURCE_ID>:<ATTR_ID>
468 * Format of REQUEST_GET_RESOURCE_LIST_JSON args:
471 switch (request_type) {
472 case REQUEST_GET_RESOURCE_JSON:
473 resource_id = atoi(args);
475 case REQUEST_GET_VALUE_JSON:
476 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2)
479 case REQUEST_GET_RESOURCE_LIST_JSON:
485 res = get_resource_by_id(client, resource_id);
487 _E("failed to get resource, res:id(%d)\n", resource_id);
492 switch (request_type) {
493 case REQUEST_GET_RESOURCE_JSON:
494 return syscommon_resman_get_resource_attrs_json(res, json_string);
495 case REQUEST_GET_VALUE_JSON:
496 return syscommon_resman_get_resource_attr_json(res, attr_id, json_string);
497 case REQUEST_GET_RESOURCE_LIST_JSON:
498 return syscommon_resman_get_resource_list_json(json_string);
504 static int handle_request_get_value_int(struct request_client *client, char *args, int32_t *value)
506 struct syscommon_resman_resource *res;
507 int resource_id, ret;
510 if (!client || !args) {
511 _E("Invalid parameter\n");
516 * Format of REQUEST_GET_VALUE_INT args:
517 * - <RESOURCE_ID:ATTR_ID>
519 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
520 _E("failed to get resource and attribute id, client(%d)\n",
525 res = get_resource_by_id(client, resource_id);
527 _E("failed to get resource, client(%d) | res:id(%d)\n",
528 client->socket_fd, resource_id);
532 ret = syscommon_resman_get_resource_attr_int(res, attr_id, value);
534 _E("failed to get int value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
536 syscommon_resman_get_resource_name(res), resource_id,
537 syscommon_resman_get_resource_attr_name(res, attr_id), attr_id);
544 static int handle_request_get_value_int64(struct request_client *client, char *args, int64_t *value)
546 struct syscommon_resman_resource *res;
547 int resource_id, ret;
550 if (!client || !args) {
551 _E("Invalid parameter\n");
556 * Format of REQUEST_GET_VALUE_INT64 args:
557 * - <RESOURCE_ID:ATTR_ID>
559 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
560 _E("failed to get resource and attribute id, client(%d)\n",
565 res = get_resource_by_id(client, resource_id);
567 _E("failed to get resource, client(%d) | res:id(%d)\n",
568 client->socket_fd, resource_id);
572 ret = syscommon_resman_get_resource_attr_int64(res, attr_id, value);
574 _E("failed to get int64 value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
576 syscommon_resman_get_resource_name(res), resource_id,
577 syscommon_resman_get_resource_attr_name(res, attr_id), attr_id);
585 handle_request_get_value_uint(struct request_client *client, char *args, u_int32_t *value)
587 struct syscommon_resman_resource *res;
588 int resource_id, ret;
591 if (!client || !args) {
592 _E("Invalid parameter\n");
597 * Format of REQUEST_GET_VALUE_UINT args:
598 * - <RESOURCE_ID:ATTR_ID>
600 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
601 _E("failed to get resource and attribute id, client(%d)\n",
606 res = get_resource_by_id(client, resource_id);
608 _E("failed to get resource, client(%d) | res:id(%d)\n",
609 client->socket_fd, resource_id);
613 ret = syscommon_resman_get_resource_attr_uint(res, attr_id, value);
615 _E("failed to get uint value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
617 syscommon_resman_get_resource_name(res), resource_id,
618 syscommon_resman_get_resource_attr_name(res, attr_id), attr_id);
626 handle_request_get_value_uint64(struct request_client *client, char *args, u_int64_t *value)
628 struct syscommon_resman_resource *res;
629 int resource_id, ret;
632 if (!client || !args) {
633 _E("Invalid parameter\n");
638 * Format of REQUEST_GET_VALUE_UINT64 args:
639 * - <RESOURCE_ID:ATTR_ID>
641 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
642 _E("failed to get resource and attribute id, client(%d)\n",
647 res = get_resource_by_id(client, resource_id);
649 _E("failed to get resource, client(%d) | res:id(%d)\n",
650 client->socket_fd, resource_id);
654 ret = syscommon_resman_get_resource_attr_uint64(res, attr_id, value);
656 _E("failed to get uint64 value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
658 syscommon_resman_get_resource_name(res), resource_id,
659 syscommon_resman_get_resource_attr_name(res, attr_id), attr_id);
666 static int handle_request_get_value_double(struct request_client *client, char *args, double *value)
668 struct syscommon_resman_resource *res;
669 int resource_id, ret;
672 if (!client || !args) {
673 _E("Invalid parameter\n");
678 * Format of REQUEST_GET_VALUE_DOUBLE args:
679 * - <RESOURCE_ID:ATTR_ID>
681 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
682 _E("failed to get resource and attribute id, client(%d)\n",
687 res = get_resource_by_id(client, resource_id);
689 _E("failed to get resource, client(%d) | res:id(%d)\n",
690 client->socket_fd, resource_id);
694 ret = syscommon_resman_get_resource_attr_double(res, attr_id, value);
696 _E("failed to get double value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
698 syscommon_resman_get_resource_name(res), resource_id,
699 syscommon_resman_get_resource_attr_name(res, attr_id), attr_id);
706 static int handle_request_get_value_string(struct request_client *client, char *args, char *value)
708 struct syscommon_resman_resource *res;
709 int resource_id, ret;
712 if (!client || !args) {
713 _E("Invalid parameter\n");
718 * Format of REQUEST_GET_VALUE_INT args:
719 * - <RESOURCE_ID:ATTR_ID>
721 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
722 _E("failed to get resource and attribute id, client(%d)\n",
727 res = get_resource_by_id(client, resource_id);
729 _E("failed to get resource, client(%d) | res:id(%d)\n",
730 client->socket_fd, resource_id);
734 ret = syscommon_resman_get_resource_attr_string(res, attr_id, value);
736 _E("failed to get string value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
738 syscommon_resman_get_resource_name(res), resource_id,
739 syscommon_resman_get_resource_attr_name(res, attr_id), attr_id);
747 handle_request_get_value_array(struct request_client *client, char *args, struct syscommon_resman_array_value **arr)
749 struct syscommon_resman_resource *res;
750 int resource_id, ret;
753 if (!client || !args) {
754 _E("Invalid parameter\n");
759 * Format of REQUEST_GET_VALUE_ARRAY args:
760 * - <RESOURCE_ID:ATTR_ID>
762 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
763 _E("failed to get resource and attribute id, client(%d)\n",
768 res = get_resource_by_id(client, resource_id);
770 _E("failed to get resource, client(%d) | res:id(%d)\n",
771 client->socket_fd, resource_id);
775 ret = syscommon_resman_get_resource_attr_array(res, attr_id, arr);
777 _E("failed to get array value, client(%d) | (res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
779 syscommon_resman_get_resource_name(res), resource_id,
780 syscommon_resman_get_resource_attr_name(res, attr_id), attr_id);
787 static int syscommon_resman_get_resource_ts(struct resource_instance *inst, int64_t *ts_start, int64_t *ts_end)
792 *ts_start = inst->ts_start;
793 *ts_end = inst->ts_end;
799 handle_request_get_resource_ts(struct request_client *client, char *args,
800 int64_t *start, int64_t *end)
802 struct resource_instance *res_inst;
803 int resource_id, ret;
805 if (!client || !args) {
806 _E("Invalid parameter\n");
811 * Format of REQUEST_GET_RESOURCE_TS args:
814 resource_id = atoi(args);
816 res_inst = get_resource_by_id(client, resource_id);
818 _E("failed to get resource, client(%d) | res:id(%d)\n",
819 client->socket_fd, resource_id);
823 ret = syscommon_resman_get_resource_ts(res_inst, start, end);
825 _E("failed to get timestamp value, client(%d) | res:name(%s)id(%d)\n",
827 syscommon_resman_get_resource_name(res_inst->res), resource_id);
834 static int split_request_type_and_args(char *buffer, char **args)
836 char *request_type_str;
838 request_type_str = strsep(&buffer, "$");
842 return atoi(request_type_str);
845 #define ADD_RESPONSE(__buf__, __remain__, __format__, ...) { \
846 int __len__ = snprintf(__buf__, __remain__, __format__, __VA_ARGS__); \
847 __buf__ += __len__; \
848 __remain__ -= __len__; \
849 if (__remain__ < 0) \
850 _E("failed to add response"); \
853 static int handle_request(struct request_client *client, char *request)
855 char *response, *response_entry, *args;
856 int request_type, buffer_len, ret;
857 char err_buf[BUFF_MAX];
859 request_type = split_request_type_and_args(request, &args);
861 switch (request_type) {
862 case REQUEST_GET_RESOURCE_JSON:
863 case REQUEST_GET_VALUE_JSON:
864 case REQUEST_GET_VALUE_ARRAY:
865 case REQUEST_GET_RESOURCE_LIST_JSON:
866 buffer_len = HUGE_BUFF_MAX + 1;
869 buffer_len = GENERIC_BUFF_MAX + 1;
872 response_entry = response = malloc(buffer_len);
878 * - <REQUEST_TYPE[:REQUEST_RESULT_PAYLOAD]:REQUEST_RESULT_VALUE>
880 ADD_RESPONSE(response, buffer_len, "%d$", request_type);
882 switch (request_type) {
883 case REQUEST_CREATE_RESOURCE:
884 ret = handle_request_create_resource(client, args);
886 case REQUEST_DELETE_RESOURCE:
887 ret = handle_request_delete_resource(client, args);
889 case REQUEST_UPDATE_RESOURCE:
890 ret = handle_request_update_resource(client, args);
892 case REQUEST_SET_RESOURCE_FLAG:
893 ret = handle_request_set_resource_flag(client, args);
895 case REQUEST_GET_RESOURCE_COUNT:
899 ret = handle_request_get_resource_count(client, args, &value);
901 ADD_RESPONSE(response, buffer_len, "%d$", value);
904 case REQUEST_UPDATE_RESOURCE_ALL:
905 ret = handle_request_update_resource_all(client, args);
907 case REQUEST_SET_RESOURCE_CTRL:
908 ret = handle_request_set_resource_ctrl(client, args);
910 case REQUEST_SET_RESOURCE_ATTR:
911 case REQUEST_UNSET_RESOURCE_ATTR:
912 case REQUEST_IS_RESOURCE_ATTR_SET:
913 ret = handle_request_set_resource_attr(client, args, request_type);
915 case REQUEST_IS_RESOURCE_ATTR_SUPPORTED:
919 ret = handle_request_is_resource_attr_supported(client, args, &supported);
921 ADD_RESPONSE(response, buffer_len, "%u$", (u_int32_t)supported);
924 case REQUEST_GET_RESOURCE_JSON:
925 case REQUEST_GET_VALUE_JSON:
926 case REQUEST_GET_RESOURCE_LIST_JSON:
930 ret = handle_request_get_json(client, args, request_type, &json_string);
932 ADD_RESPONSE(response, buffer_len, "%s$", json_string);
937 case REQUEST_GET_VALUE_INT:
941 ret = handle_request_get_value_int(client, args, &value);
943 ADD_RESPONSE(response, buffer_len, "%d$", value);
946 case REQUEST_GET_VALUE_INT64:
950 ret = handle_request_get_value_int64(client, args, &value);
952 ADD_RESPONSE(response, buffer_len, "%"PRId64"$", value);
955 case REQUEST_GET_VALUE_UINT:
959 ret = handle_request_get_value_uint(client, args, &value);
961 ADD_RESPONSE(response, buffer_len, "%u$", value);
964 case REQUEST_GET_VALUE_UINT64:
968 ret = handle_request_get_value_uint64(client, args, &value);
970 ADD_RESPONSE(response, buffer_len, "%"PRIu64"$", value);
973 case REQUEST_GET_VALUE_DOUBLE:
977 ret = handle_request_get_value_double(client, args, &value);
979 ADD_RESPONSE(response, buffer_len, "%lf$", value);
982 case REQUEST_GET_VALUE_STRING:
984 char value[BUFF_MAX];
986 ret = handle_request_get_value_string(client, args, value);
988 ADD_RESPONSE(response, buffer_len, "%s$", value);
991 case REQUEST_GET_VALUE_ARRAY:
993 struct syscommon_resman_array_value *array;
996 ret = handle_request_get_value_array(client, args, &array);
998 if (array->length == 0) {
999 ADD_RESPONSE(response, buffer_len, "%d|%d|$",
1000 array->type, array->length);
1004 ADD_RESPONSE(response, buffer_len, "%d|%d|", array->type, array->length);
1006 switch (array->type) {
1007 case SYSCOMMON_RESMAN_DATA_TYPE_INT:
1008 for (i = 0; i < array->length - 1; i++)
1009 ADD_RESPONSE(response, buffer_len, "%d,",
1010 ((int32_t *)array->data)[i]);
1011 ADD_RESPONSE(response, buffer_len, "%d$",
1012 ((int32_t *)array->data)[i]);
1014 case SYSCOMMON_RESMAN_DATA_TYPE_INT64:
1015 for (i = 0; i < array->length - 1; i++)
1016 ADD_RESPONSE(response, buffer_len, "%"PRId64",",
1017 ((int64_t *)array->data)[i]);
1018 ADD_RESPONSE(response, buffer_len, "%"PRId64"$",
1019 ((int64_t *)array->data)[i]);
1021 case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
1022 for (i = 0; i < array->length - 1; i++)
1023 ADD_RESPONSE(response, buffer_len, "%u,",
1024 ((u_int32_t *)array->data)[i]);
1025 ADD_RESPONSE(response, buffer_len, "%u$",
1026 ((u_int32_t *)array->data)[i]);
1028 case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
1029 for (i = 0; i < array->length - 1; i++)
1030 ADD_RESPONSE(response, buffer_len, "%"PRIu64",",
1031 ((u_int64_t *)array->data)[i]);
1032 ADD_RESPONSE(response, buffer_len, "%"PRIu64"$",
1033 ((u_int64_t *)array->data)[i]);
1035 case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
1036 for (i = 0; i < array->length - 1; i++)
1037 ADD_RESPONSE(response, buffer_len, "%lf,",
1038 ((double *)array->data)[i]);
1039 ADD_RESPONSE(response, buffer_len, "%lf$",
1040 ((double *)array->data)[i]);
1042 case SYSCOMMON_RESMAN_DATA_TYPE_STRING:
1043 for (i = 0; i < array->length - 1; i++)
1044 ADD_RESPONSE(response, buffer_len, "%s,",
1045 ((char **)array->data)[i]);
1046 ADD_RESPONSE(response, buffer_len, "%s$",
1047 ((char **)array->data)[i]);
1050 _E("Not supported data type");
1054 case REQUEST_GET_RESOURCE_TS:
1058 ret = handle_request_get_resource_ts(client, args, &start, &end);
1060 ADD_RESPONSE(response, buffer_len, "%"PRId64"$%"PRId64"$", start, end);
1064 _E("Invliad request type: %d", request_type);
1068 ADD_RESPONSE(response, buffer_len, "%d", ret);
1070 if (send(client->socket_fd, response_entry, strlen(response_entry), 0) < 0) {
1071 strerror_r(errno, err_buf, BUFF_MAX);
1072 _E("Failed to send respones, errno: %d, error: %s", errno, err_buf);
1075 free(response_entry);
1080 static GList *g_request_client_head;
1081 static GMutex g_server_lock;
1083 static void add_client_to_list(struct request_client *client)
1088 g_mutex_lock(&g_server_lock);
1089 g_request_client_head =
1090 g_list_append(g_request_client_head, (gpointer)client);
1091 g_mutex_unlock(&g_server_lock);
1094 static void remove_client_from_list(struct request_client *client)
1099 g_mutex_lock(&g_server_lock);
1100 g_request_client_head =
1101 g_list_remove(g_request_client_head, (gpointer)client);
1102 g_mutex_unlock(&g_server_lock);
1105 static void destroy_request_client(struct request_client *client)
1107 remove_client_from_list(client);
1111 static int request_handler_func(void *data, void **result)
1113 char request[GENERIC_BUFF_MAX + 1];
1114 struct request_client *client = (struct request_client *)data;
1116 char err_buf[BUFF_MAX];
1118 _D("Client-%d is connected", client->socket_fd);
1121 len = recv(client->socket_fd, request, GENERIC_BUFF_MAX, 0);
1126 strerror_r(errno, err_buf, BUFF_MAX);
1127 _E("Error occurs while receiving request: errno: %d, error: %s",
1132 request[len] = '\0';
1133 ret = handle_request(client, request);
1138 _D("Client-%d is disconnected", client->socket_fd);
1139 g_hash_table_destroy(client->resource_table);
1140 close(client->socket_fd);
1141 destroy_request_client(client);
1143 return THREAD_RETURN_DONE;
1146 static void delete_resource_instance(struct resource_instance *res_inst)
1151 syscommon_resman_delete_resource(res_inst->res);
1156 static int create_request_client(int socket_fd)
1158 struct request_client *client;
1160 client = malloc(sizeof(struct request_client));
1162 _E("Failed to allocate memory of request_client");
1166 client->socket_fd = socket_fd;
1167 client->resource_table =
1168 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
1169 (GDestroyNotify)delete_resource_instance);
1171 create_daemon_thread(&client->worker, request_handler_func, client);
1173 add_client_to_list(client);
1178 static int init_unix_socket(int *sock, struct sockaddr_un *address, int *addrlen)
1180 const char *server_unix_socket_path = "/run/.pass-resource-monitor.socket";
1182 int n = sd_listen_fds(0);
1186 if (!sock || !address || !addrlen)
1189 bzero(address, sizeof(*address));
1190 address->sun_family = AF_UNIX;
1191 strncpy(address->sun_path, server_unix_socket_path, sizeof(address->sun_path));
1192 address->sun_path[sizeof(address->sun_path) - 1] = '\0';
1194 /* use the existing systemd unix socket */
1196 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
1197 if (sd_is_socket_unix(fd, SOCK_STREAM, 1, server_unix_socket_path, 0) > 0) {
1199 *addrlen = sizeof(*address);
1205 /* make a new unix socket */
1206 *sock = socket(AF_UNIX, SOCK_STREAM, 0);
1208 _E("Failed to initialize socket");
1212 if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR,
1213 (char *)&opt, sizeof(opt)) < 0) {
1214 _E("Failed to setsockopt");
1215 goto error_out_close;
1218 if (!access(server_unix_socket_path, F_OK))
1219 unlink(server_unix_socket_path);
1221 if (bind(*sock, (struct sockaddr *)address, sizeof(*address)) < 0) {
1222 _E("Failed to bind");
1223 goto error_out_close;
1226 file_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
1227 if (chmod(server_unix_socket_path, file_mode) < 0) {
1228 _E("Failed to change the file mode of %s", server_unix_socket_path);
1229 goto error_out_close;
1232 if (listen(*sock, PENDING_MAX) < 0) {
1233 _E("Failed to begin listenning");
1234 goto error_out_close;
1237 *addrlen = sizeof(*address);
1244 bzero(address, sizeof(*address));
1249 int init_ip_socket(int *sock, struct sockaddr_in *address, int *addrlen)
1253 if (!sock || !address || !addrlen)
1256 *sock = socket(AF_INET, SOCK_STREAM, 0);
1258 _E("Failed to initialize TCP/IP socket");
1262 if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR,
1263 (char *)&opt, sizeof(opt)) < 0) {
1264 _E("Failed to setsockopt for TCP/IP socket");
1265 goto error_out_close;
1268 bzero(address, sizeof(*address));
1269 address->sin_family = AF_INET;
1270 address->sin_addr.s_addr = INADDR_ANY;
1271 address->sin_port = htons(REQUEST_SERVER_PORT);
1273 if (bind(*sock, (struct sockaddr *)address, sizeof(*address)) < 0) {
1274 _E("Failed to bind for TCP/IP socket");
1275 goto error_out_close;
1278 if (listen(*sock, PENDING_MAX) < 0) {
1279 _E("Failed to begin listenning for TCP/IP socket");
1280 goto error_out_close;
1283 *addrlen = sizeof(*address);
1293 static void init_resource_id(void)
1299 * Initial g_resource_id is set by a combination of
1300 * tv_sec and tv_usec values of gettimeofday().
1301 * It ensures that PASS assigns a unique resource id
1302 * for each create_resource request.
1304 * Even PASS is restarted, a newly initialized value
1305 * of g_resource_id reflects the current value of
1306 * gettimeofday(). Thus, the uniqueness in resource
1307 * id is kept unless the number of created resources
1308 * crosses the time consumed (in msecs) before
1311 gettimeofday(&tv, NULL);
1312 val = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1313 g_resource_id = clear_sign_bit(val);
1316 static int request_server_func(void *ctx, void **result)
1318 struct sockaddr_un unix_address;
1319 struct sockaddr_in ip_address;
1320 struct timeval wait;
1321 int server_unix_socket;
1322 int server_ip_socket = 0;
1328 if (!g_request_server_run)
1329 return THREAD_RETURN_DONE;
1333 /* 0. initialize server socket */
1334 ret = init_unix_socket(&server_unix_socket, &unix_address, &unix_addrlen);
1338 while (g_request_server_run) {
1340 FD_SET(server_unix_socket, &fds);
1341 if (server_ip_socket)
1342 FD_SET(server_ip_socket, &fds);
1347 ret = select(FD_SETSIZE, &fds, NULL, NULL, &wait);
1349 _E("failed to select");
1350 goto error_out_close;
1353 if (FD_ISSET(server_unix_socket, &fds)) {
1354 int new_socket = accept(server_unix_socket, (struct sockaddr *)&unix_address,
1355 (socklen_t *)&unix_addrlen);
1357 if (new_socket < 0) {
1358 _E("Failed to accept");
1359 goto error_out_close;
1362 create_request_client(new_socket);
1365 if (server_ip_socket && FD_ISSET(server_ip_socket, &fds)) {
1366 int new_socket = accept(server_ip_socket, (struct sockaddr *)&ip_address,
1367 (socklen_t *)&ip_addrlen);
1369 if (new_socket < 0) {
1370 _E("Failed to accept");
1371 goto error_out_close;
1374 create_request_client(new_socket);
1377 if (!server_ip_socket && (monitor_get_debug_mode() == TRUE)) {
1380 * server_ip_socket activation can be deferred since it
1381 * will be done after timeout of select is expired. So,
1382 * when the timeout is extended, this activation should be
1383 * done by other ways in order to prevent unacceptable
1386 ret = init_ip_socket(&server_ip_socket, &ip_address, &ip_addrlen);
1388 goto error_out_close_server_unix_socket;
1389 } else if (server_ip_socket && (monitor_get_debug_mode() == FALSE)) {
1390 close(server_ip_socket);
1391 server_ip_socket = 0;
1395 close(server_unix_socket);
1396 if (server_ip_socket)
1397 close(server_ip_socket);
1399 return THREAD_RETURN_DONE;
1402 if (server_ip_socket)
1403 close(server_ip_socket);
1404 error_out_close_server_unix_socket:
1405 close(server_unix_socket);
1408 return THREAD_RETURN_ERROR;
1411 int request_server_init(void)
1413 g_request_server_run = true;
1414 if (create_daemon_thread(&g_server_thread, request_server_func, NULL))
1415 _E("Failed to create request_server_thread ");
1420 void request_server_exit(void)
1422 g_request_server_run = false;
1423 destroy_thread(g_server_thread);