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>
44 #include <netinet/in.h>
49 #include <systemd/sd-daemon.h>
52 #define REQUEST_SERVER_PORT 10001
54 struct request_client {
57 struct thread *worker;
58 GHashTable *resource_table;
61 struct resource_instance {
67 static bool g_request_server_run;
68 static struct thread *g_server_thread;
71 register_resource_to_client(struct request_client *client, struct resource_instance *res_inst)
73 g_hash_table_insert(client->resource_table,
74 GINT_TO_POINTER(res_inst->id),
79 unregister_resource_from_client(struct request_client *client, int resource_id)
81 g_hash_table_remove(client->resource_table, GINT_TO_POINTER(resource_id));
84 static struct resource_instance *
85 get_resource_instance_by_id(struct request_client *client, int resource_id)
87 return g_hash_table_lookup(client->resource_table, GINT_TO_POINTER(resource_id));
90 static int handle_request_create_resource(struct request_client *client, char *args)
92 struct resource_instance *res_inst;
93 int resource_type, ret;
95 if (!client || !args) {
96 _E("Invalid parameter\n");
100 res_inst = calloc(1, sizeof(struct resource_instance));
105 * Format of REQUEST_CREATE_RESOURCE args:
108 resource_type = atoi(args);
110 ret = syscommon_resman_create_resource(&res_inst->id, resource_type);
112 _E("failed to create resource, res:type(%d)\n", resource_type);
117 register_resource_to_client(client, res_inst);
122 static int handle_request_delete_resource(struct request_client *client, char *args)
126 if (!client || !args) {
127 _E("Invalid parameter\n");
132 * Format of REQUEST_DELETE_RESOURCE args:
135 resource_id = atoi(args);
137 unregister_resource_from_client(client, resource_id);
142 inline __attribute__((always_inline)) int64_t get_time_now(void)
146 gettimeofday(&tv, NULL);
147 return (int64_t)tv.tv_sec * 1000000 + (int64_t)tv.tv_usec;
150 static int handle_request_update_resource(struct request_client *client, char *args)
152 struct resource_instance *res_inst;
156 if (!client || !args) {
157 _E("Invalid parameter\n");
162 * Format of REQUEST_UPDATE_RESOURCE args:
165 resource_id = atoi(args);
167 res_inst = get_resource_instance_by_id(client, resource_id);
169 _E("failed to get resource instance, res:id(%d)\n", resource_id);
173 res_inst->ts_start = get_time_now();
174 ret = syscommon_resman_update_resource_attrs(resource_id);
175 res_inst->ts_end = get_time_now();
177 res_inst->ts_start = res_inst->ts_end = 0;
178 _E("failed to update resource attributes, res:name(%s)id(%d)\n",
179 syscommon_resman_get_resource_name(resource_id), resource_id);
186 static int syscommon_resman_get_resource_count(int resource_type)
188 const struct syscommon_resman_resource_driver *driver;
189 int count = syscommon_resman_get_resource_device_count(resource_type);
194 driver = syscommon_resman_find_resource_driver(resource_type);
198 if (driver->flag & SYSCOMMON_RESMAN_RESOURCE_DRIVER_FLAG_COUNT_ONLY_ONE)
200 else if (driver->flag & SYSCOMMON_RESMAN_RESOURCE_DRIVER_FLAG_UNCOUNTABLE)
206 static int handle_request_get_resource_count(struct request_client *client, char *args, int *value)
211 if (!client || !args) {
212 _E("Invalid parameter\n");
217 * Format of REQUEST_GET_RESOURCE_COUNT args:
220 resource_type = atoi(args);
222 ret = syscommon_resman_get_resource_count(resource_type);
224 _E("failed to get resource device count, res:type(%d)\n", resource_type);
232 static void update_resource(gpointer key, gpointer value, gpointer user_data)
234 struct resource_instance *res_inst = value;
237 ret = syscommon_resman_update_resource_attrs(res_inst->id);
239 _E("failed to update resource attributes (name:%s,id:%d)\n",
240 syscommon_resman_get_resource_name(res_inst->id), res_inst->id);
244 static int handle_request_update_resource_all(struct request_client *client, char *args)
247 _E("Invalid parameter\n");
252 * Format of REQUEST_UPDATE_RESOURCE args:
255 if (client->resource_table)
256 g_hash_table_foreach(client->resource_table, (GHFunc)update_resource, NULL);
261 static int handle_request_set_resource_attr(struct request_client *client, char *args, int request_type)
263 int resource_id, ret;
264 u_int64_t interest_masks;
266 if (!client || !args) {
267 _E("Invalid parameter\n");
272 * Format of REQUEST_SET_RESOURCE_ATTR and REQUEST_UNSET_RESOURCE_ATTR args:
273 * - <RESOURCE_ID:INTEREST_MASK>
275 if (sscanf(args, "%d$%"PRIu64, &resource_id, &interest_masks) < 2) {
276 _E("failed to get resource and attribute id, client(%d)\n",
281 switch (request_type) {
282 case REQUEST_SET_RESOURCE_ATTR:
283 ret = syscommon_resman_set_resource_attr_interest(resource_id, interest_masks);
285 _E("failed to set attribute interest, client(%d) | res:name(%s)id(%d)\n",
287 syscommon_resman_get_resource_name(resource_id), resource_id);
289 case REQUEST_UNSET_RESOURCE_ATTR:
290 ret = syscommon_resman_unset_resource_attr_interest(resource_id, interest_masks);
292 _E("failed to unset attribute interest, client(%d) | res:name(%s)id(%d)\n",
294 syscommon_resman_get_resource_name(resource_id), resource_id);
296 case REQUEST_IS_RESOURCE_ATTR_SET:
297 ret = (int)syscommon_resman_is_resource_attr_interested(resource_id, interest_masks);
306 static int handle_request_set_resource_flag(struct request_client *client, char *args)
308 int resource_id, ret;
311 if (!client || !args) {
312 _E("Invalid parameter\n");
317 * Format of REQUEST_SET_RESOURCE_ATTR and REQUEST_UNSET_RESOURCE_ATTR args:
320 if (sscanf(args, "%d$%"PRIu64, &resource_id, &flag_mask) < 2) {
321 _E("failed to get resource and flag mask, client(%d)\n",
326 ret = syscommon_resman_set_resource_flag(resource_id, flag_mask);
328 _E("failed to set flag to %"PRIu64", client(%d) | res:name(%s)id(%d)\n",
329 flag_mask, client->socket_fd,
330 syscommon_resman_get_resource_name(resource_id), resource_id);
337 static int handle_request_is_resource_attr_supported(struct request_client *client, char *args, bool *supported)
342 if (!client || !args) {
343 _E("Invalid parameter\n");
348 * Format of REQUEST_IS_RESOURCE_ATTR_SUPPORTED args:
349 * - <RESOURCE_ID:RESOURCE_ATTR_ID>
351 if (sscanf(args, "%d$%"PRIu64"", &resource_id, &attr_id) < 2) {
352 _E("failed to get resource and attribute id, client(%d)\n",
357 return syscommon_resman_is_resource_attr_supported(resource_id, attr_id, supported);
360 static int handle_request_set_resource_ctrl(struct request_client *client, char *args)
362 int resource_id, value, ret;
365 if (!client || !args) {
366 _E("Invalid parameter\n");
371 * Format of REQUEST_SET_RESOURCE_CTRL args:
372 * - <RESOURCE_ID:CONTROL_ID:CONTROL_VALUE>
374 if (sscanf(args, "%d$%"PRIu64"$%d", &resource_id, &ctrl_id, &value) < 3) {
375 _E("failed to get resource and control id, client(%d)\n",
380 ret = syscommon_resman_set_resource_control(resource_id, ctrl_id, (void *)(intptr_t)value);
382 _E("failed to set resource control, client(%d) | res:name(%s)id(%d) | ctrl:name(%s)id(%"PRId64")val(%d)\n",
384 syscommon_resman_get_resource_name(resource_id), resource_id,
385 syscommon_resman_get_resource_control_name(resource_id, ctrl_id), ctrl_id, value);
393 handle_request_get_json(struct request_client *client, char *args,
394 int request_type, char **json_string)
400 _E("Invalid parameter\n");
405 * Format of REQUEST_GET_RESOURCE_JSON args:
407 * Format of REQUEST_GET_VALUE_JSON args:
408 * - <RESOURCE_ID>:<ATTR_ID>
409 * Format of REQUEST_GET_RESOURCE_LIST_JSON args:
412 switch (request_type) {
413 case REQUEST_GET_RESOURCE_JSON:
414 resource_id = atoi(args);
416 case REQUEST_GET_VALUE_JSON:
417 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2)
420 case REQUEST_GET_RESOURCE_LIST_JSON:
427 switch (request_type) {
428 case REQUEST_GET_RESOURCE_JSON:
429 return syscommon_resman_get_resource_attrs_json(resource_id, json_string);
430 case REQUEST_GET_VALUE_JSON:
431 return syscommon_resman_get_resource_attr_json(resource_id, attr_id, json_string);
432 case REQUEST_GET_RESOURCE_LIST_JSON:
433 return syscommon_resman_get_resource_list_json(json_string);
439 static int handle_request_get_value_int(struct request_client *client, char *args, int32_t *value)
441 int resource_id, ret;
444 if (!client || !args) {
445 _E("Invalid parameter\n");
450 * Format of REQUEST_GET_VALUE_INT args:
451 * - <RESOURCE_ID:ATTR_ID>
453 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
454 _E("failed to get resource and attribute id, client(%d)\n",
459 ret = syscommon_resman_get_resource_attr_int(resource_id, attr_id, value);
461 _E("failed to get int value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
463 syscommon_resman_get_resource_name(resource_id), resource_id,
464 syscommon_resman_get_resource_attr_name(resource_id, attr_id), attr_id);
471 static int handle_request_get_value_int64(struct request_client *client, char *args, int64_t *value)
473 int resource_id, ret;
476 if (!client || !args) {
477 _E("Invalid parameter\n");
482 * Format of REQUEST_GET_VALUE_INT64 args:
483 * - <RESOURCE_ID:ATTR_ID>
485 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
486 _E("failed to get resource and attribute id, client(%d)\n",
491 ret = syscommon_resman_get_resource_attr_int64(resource_id, attr_id, value);
493 _E("failed to get int64 value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
495 syscommon_resman_get_resource_name(resource_id), resource_id,
496 syscommon_resman_get_resource_attr_name(resource_id, attr_id), attr_id);
504 handle_request_get_value_uint(struct request_client *client, char *args, u_int32_t *value)
506 int resource_id, ret;
509 if (!client || !args) {
510 _E("Invalid parameter\n");
515 * Format of REQUEST_GET_VALUE_UINT args:
516 * - <RESOURCE_ID:ATTR_ID>
518 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
519 _E("failed to get resource and attribute id, client(%d)\n",
524 ret = syscommon_resman_get_resource_attr_uint(resource_id, attr_id, value);
526 _E("failed to get uint value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
528 syscommon_resman_get_resource_name(resource_id), resource_id,
529 syscommon_resman_get_resource_attr_name(resource_id, attr_id), attr_id);
537 handle_request_get_value_uint64(struct request_client *client, char *args, u_int64_t *value)
539 int resource_id, ret;
542 if (!client || !args) {
543 _E("Invalid parameter\n");
548 * Format of REQUEST_GET_VALUE_UINT64 args:
549 * - <RESOURCE_ID:ATTR_ID>
551 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
552 _E("failed to get resource and attribute id, client(%d)\n",
557 ret = syscommon_resman_get_resource_attr_uint64(resource_id, attr_id, value);
559 _E("failed to get uint64 value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
561 syscommon_resman_get_resource_name(resource_id), resource_id,
562 syscommon_resman_get_resource_attr_name(resource_id, attr_id), attr_id);
569 static int handle_request_get_value_double(struct request_client *client, char *args, double *value)
571 int resource_id, ret;
574 if (!client || !args) {
575 _E("Invalid parameter\n");
580 * Format of REQUEST_GET_VALUE_DOUBLE args:
581 * - <RESOURCE_ID:ATTR_ID>
583 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
584 _E("failed to get resource and attribute id, client(%d)\n",
589 ret = syscommon_resman_get_resource_attr_double(resource_id, attr_id, value);
591 _E("failed to get double value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
593 syscommon_resman_get_resource_name(resource_id), resource_id,
594 syscommon_resman_get_resource_attr_name(resource_id, attr_id), attr_id);
601 static int handle_request_get_value_string(struct request_client *client, char *args, char *value)
603 int resource_id, ret;
606 if (!client || !args) {
607 _E("Invalid parameter\n");
612 * Format of REQUEST_GET_VALUE_INT args:
613 * - <RESOURCE_ID:ATTR_ID>
615 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
616 _E("failed to get resource and attribute id, client(%d)\n",
621 ret = syscommon_resman_get_resource_attr_string(resource_id, attr_id, value);
623 _E("failed to get string value, client(%d) | res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
625 syscommon_resman_get_resource_name(resource_id), resource_id,
626 syscommon_resman_get_resource_attr_name(resource_id, attr_id), attr_id);
634 handle_request_get_value_array(struct request_client *client, char *args, struct syscommon_resman_array_value **arr)
636 int resource_id, ret;
639 if (!client || !args) {
640 _E("Invalid parameter\n");
645 * Format of REQUEST_GET_VALUE_ARRAY args:
646 * - <RESOURCE_ID:ATTR_ID>
648 if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) {
649 _E("failed to get resource and attribute id, client(%d)\n",
654 ret = syscommon_resman_get_resource_attr_array(resource_id, attr_id, arr);
656 _E("failed to get array value, client(%d) | (res:name(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
658 syscommon_resman_get_resource_name(resource_id), resource_id,
659 syscommon_resman_get_resource_attr_name(resource_id, attr_id), attr_id);
666 static int syscommon_resman_get_resource_ts(struct resource_instance *inst, int64_t *ts_start, int64_t *ts_end)
671 *ts_start = inst->ts_start;
672 *ts_end = inst->ts_end;
678 handle_request_get_resource_ts(struct request_client *client, char *args,
679 int64_t *start, int64_t *end)
681 struct resource_instance *res_inst;
682 int resource_id, ret;
684 if (!client || !args) {
685 _E("Invalid parameter\n");
690 * Format of REQUEST_GET_RESOURCE_TS args:
693 resource_id = atoi(args);
695 res_inst = get_resource_instance_by_id(client, resource_id);
697 _E("failed to get resource, client(%d) | res:id(%d)\n",
698 client->socket_fd, resource_id);
702 ret = syscommon_resman_get_resource_ts(res_inst, start, end);
704 _E("failed to get timestamp value, client(%d) | res:name(%s)id(%d)\n",
706 syscommon_resman_get_resource_name(res_inst->id), resource_id);
713 static int split_request_type_and_args(char *buffer, char **args)
715 char *request_type_str;
717 request_type_str = strsep(&buffer, "$");
721 return atoi(request_type_str);
724 #define ADD_RESPONSE(__buf__, __remain__, __format__, ...) { \
725 int __len__ = snprintf(__buf__, __remain__, __format__, __VA_ARGS__); \
726 __buf__ += __len__; \
727 __remain__ -= __len__; \
728 if (__remain__ < 0) \
729 _E("failed to add response"); \
732 static int handle_request(struct request_client *client, char *request)
734 char *response, *response_entry, *args;
735 int request_type, buffer_len, ret;
736 char err_buf[BUFF_MAX];
738 request_type = split_request_type_and_args(request, &args);
740 switch (request_type) {
741 case REQUEST_GET_RESOURCE_JSON:
742 case REQUEST_GET_VALUE_JSON:
743 case REQUEST_GET_VALUE_ARRAY:
744 case REQUEST_GET_RESOURCE_LIST_JSON:
745 buffer_len = HUGE_BUFF_MAX + 1;
748 buffer_len = GENERIC_BUFF_MAX + 1;
751 response_entry = response = malloc(buffer_len);
757 * - <REQUEST_TYPE[:REQUEST_RESULT_PAYLOAD]:REQUEST_RESULT_VALUE>
759 ADD_RESPONSE(response, buffer_len, "%d$", request_type);
761 switch (request_type) {
762 case REQUEST_CREATE_RESOURCE:
763 ret = handle_request_create_resource(client, args);
765 case REQUEST_DELETE_RESOURCE:
766 ret = handle_request_delete_resource(client, args);
768 case REQUEST_UPDATE_RESOURCE:
769 ret = handle_request_update_resource(client, args);
771 case REQUEST_SET_RESOURCE_FLAG:
772 ret = handle_request_set_resource_flag(client, args);
774 case REQUEST_GET_RESOURCE_COUNT:
778 ret = handle_request_get_resource_count(client, args, &value);
780 ADD_RESPONSE(response, buffer_len, "%d$", value);
783 case REQUEST_UPDATE_RESOURCE_ALL:
784 ret = handle_request_update_resource_all(client, args);
786 case REQUEST_SET_RESOURCE_CTRL:
787 ret = handle_request_set_resource_ctrl(client, args);
789 case REQUEST_SET_RESOURCE_ATTR:
790 case REQUEST_UNSET_RESOURCE_ATTR:
791 case REQUEST_IS_RESOURCE_ATTR_SET:
792 ret = handle_request_set_resource_attr(client, args, request_type);
794 case REQUEST_IS_RESOURCE_ATTR_SUPPORTED:
798 ret = handle_request_is_resource_attr_supported(client, args, &supported);
800 ADD_RESPONSE(response, buffer_len, "%u$", (u_int32_t)supported);
803 case REQUEST_GET_RESOURCE_JSON:
804 case REQUEST_GET_VALUE_JSON:
805 case REQUEST_GET_RESOURCE_LIST_JSON:
809 ret = handle_request_get_json(client, args, request_type, &json_string);
811 ADD_RESPONSE(response, buffer_len, "%s$", json_string);
816 case REQUEST_GET_VALUE_INT:
820 ret = handle_request_get_value_int(client, args, &value);
822 ADD_RESPONSE(response, buffer_len, "%d$", value);
825 case REQUEST_GET_VALUE_INT64:
829 ret = handle_request_get_value_int64(client, args, &value);
831 ADD_RESPONSE(response, buffer_len, "%"PRId64"$", value);
834 case REQUEST_GET_VALUE_UINT:
838 ret = handle_request_get_value_uint(client, args, &value);
840 ADD_RESPONSE(response, buffer_len, "%u$", value);
843 case REQUEST_GET_VALUE_UINT64:
847 ret = handle_request_get_value_uint64(client, args, &value);
849 ADD_RESPONSE(response, buffer_len, "%"PRIu64"$", value);
852 case REQUEST_GET_VALUE_DOUBLE:
856 ret = handle_request_get_value_double(client, args, &value);
858 ADD_RESPONSE(response, buffer_len, "%lf$", value);
861 case REQUEST_GET_VALUE_STRING:
863 char value[BUFF_MAX];
865 ret = handle_request_get_value_string(client, args, value);
867 ADD_RESPONSE(response, buffer_len, "%s$", value);
870 case REQUEST_GET_VALUE_ARRAY:
872 struct syscommon_resman_array_value *array;
875 ret = handle_request_get_value_array(client, args, &array);
877 if (array->length == 0) {
878 ADD_RESPONSE(response, buffer_len, "%d|%d|$",
879 array->type, array->length);
883 ADD_RESPONSE(response, buffer_len, "%d|%d|", array->type, array->length);
885 switch (array->type) {
886 case SYSCOMMON_RESMAN_DATA_TYPE_INT:
887 for (i = 0; i < array->length - 1; i++)
888 ADD_RESPONSE(response, buffer_len, "%d,",
889 ((int32_t *)array->data)[i]);
890 ADD_RESPONSE(response, buffer_len, "%d$",
891 ((int32_t *)array->data)[i]);
893 case SYSCOMMON_RESMAN_DATA_TYPE_INT64:
894 for (i = 0; i < array->length - 1; i++)
895 ADD_RESPONSE(response, buffer_len, "%"PRId64",",
896 ((int64_t *)array->data)[i]);
897 ADD_RESPONSE(response, buffer_len, "%"PRId64"$",
898 ((int64_t *)array->data)[i]);
900 case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
901 for (i = 0; i < array->length - 1; i++)
902 ADD_RESPONSE(response, buffer_len, "%u,",
903 ((u_int32_t *)array->data)[i]);
904 ADD_RESPONSE(response, buffer_len, "%u$",
905 ((u_int32_t *)array->data)[i]);
907 case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
908 for (i = 0; i < array->length - 1; i++)
909 ADD_RESPONSE(response, buffer_len, "%"PRIu64",",
910 ((u_int64_t *)array->data)[i]);
911 ADD_RESPONSE(response, buffer_len, "%"PRIu64"$",
912 ((u_int64_t *)array->data)[i]);
914 case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
915 for (i = 0; i < array->length - 1; i++)
916 ADD_RESPONSE(response, buffer_len, "%lf,",
917 ((double *)array->data)[i]);
918 ADD_RESPONSE(response, buffer_len, "%lf$",
919 ((double *)array->data)[i]);
921 case SYSCOMMON_RESMAN_DATA_TYPE_STRING:
922 for (i = 0; i < array->length - 1; i++)
923 ADD_RESPONSE(response, buffer_len, "%s,",
924 ((char **)array->data)[i]);
925 ADD_RESPONSE(response, buffer_len, "%s$",
926 ((char **)array->data)[i]);
929 _E("Not supported data type");
933 case REQUEST_GET_RESOURCE_TS:
937 ret = handle_request_get_resource_ts(client, args, &start, &end);
939 ADD_RESPONSE(response, buffer_len, "%"PRId64"$%"PRId64"$", start, end);
943 _E("Invliad request type: %d", request_type);
947 ADD_RESPONSE(response, buffer_len, "%d", ret);
949 if (send(client->socket_fd, response_entry, strlen(response_entry), 0) < 0) {
950 strerror_r(errno, err_buf, BUFF_MAX);
951 _E("Failed to send respones, errno: %d, error: %s", errno, err_buf);
954 free(response_entry);
959 static GList *g_request_client_head;
960 static GMutex g_server_lock;
962 static void add_client_to_list(struct request_client *client)
967 g_mutex_lock(&g_server_lock);
968 g_request_client_head =
969 g_list_append(g_request_client_head, (gpointer)client);
970 g_mutex_unlock(&g_server_lock);
973 static void remove_client_from_list(struct request_client *client)
978 g_mutex_lock(&g_server_lock);
979 g_request_client_head =
980 g_list_remove(g_request_client_head, (gpointer)client);
981 g_mutex_unlock(&g_server_lock);
984 static void destroy_request_client(struct request_client *client)
986 remove_client_from_list(client);
990 static int request_handler_func(void *data, void **result)
992 char request[GENERIC_BUFF_MAX + 1];
993 struct request_client *client = (struct request_client *)data;
995 char err_buf[BUFF_MAX];
997 _D("Client-%d is connected", client->socket_fd);
1000 len = recv(client->socket_fd, request, GENERIC_BUFF_MAX, 0);
1005 strerror_r(errno, err_buf, BUFF_MAX);
1006 _E("Error occurs while receiving request: errno: %d, error: %s",
1011 request[len] = '\0';
1012 ret = handle_request(client, request);
1017 _D("Client-%d is disconnected", client->socket_fd);
1018 g_hash_table_destroy(client->resource_table);
1019 close(client->socket_fd);
1020 destroy_request_client(client);
1022 return THREAD_RETURN_DONE;
1025 static void delete_resource_instance(struct resource_instance *res_inst)
1030 syscommon_resman_delete_resource(res_inst->id);
1035 static int create_request_client(int socket_fd)
1037 struct request_client *client;
1039 client = malloc(sizeof(struct request_client));
1041 _E("Failed to allocate memory of request_client");
1045 client->socket_fd = socket_fd;
1046 client->resource_table =
1047 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
1048 (GDestroyNotify)delete_resource_instance);
1050 create_daemon_thread(&client->worker, request_handler_func, client);
1052 add_client_to_list(client);
1057 static int init_unix_socket(int *sock, struct sockaddr_un *address, int *addrlen)
1059 const char *server_unix_socket_path = "/run/.pass-resource-monitor.socket";
1061 int n = sd_listen_fds(0);
1065 if (!sock || !address || !addrlen)
1068 bzero(address, sizeof(*address));
1069 address->sun_family = AF_UNIX;
1070 strncpy(address->sun_path, server_unix_socket_path, sizeof(address->sun_path));
1071 address->sun_path[sizeof(address->sun_path) - 1] = '\0';
1073 /* use the existing systemd unix socket */
1075 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
1076 if (sd_is_socket_unix(fd, SOCK_STREAM, 1, server_unix_socket_path, 0) > 0) {
1078 *addrlen = sizeof(*address);
1084 /* make a new unix socket */
1085 *sock = socket(AF_UNIX, SOCK_STREAM, 0);
1087 _E("Failed to initialize socket");
1091 if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR,
1092 (char *)&opt, sizeof(opt)) < 0) {
1093 _E("Failed to setsockopt");
1094 goto error_out_close;
1097 if (!access(server_unix_socket_path, F_OK))
1098 unlink(server_unix_socket_path);
1100 if (bind(*sock, (struct sockaddr *)address, sizeof(*address)) < 0) {
1101 _E("Failed to bind");
1102 goto error_out_close;
1105 file_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
1106 if (chmod(server_unix_socket_path, file_mode) < 0) {
1107 _E("Failed to change the file mode of %s", server_unix_socket_path);
1108 goto error_out_close;
1111 if (listen(*sock, PENDING_MAX) < 0) {
1112 _E("Failed to begin listenning");
1113 goto error_out_close;
1116 *addrlen = sizeof(*address);
1123 bzero(address, sizeof(*address));
1128 int init_ip_socket(int *sock, struct sockaddr_in *address, int *addrlen)
1132 if (!sock || !address || !addrlen)
1135 *sock = socket(AF_INET, SOCK_STREAM, 0);
1137 _E("Failed to initialize TCP/IP socket");
1141 if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR,
1142 (char *)&opt, sizeof(opt)) < 0) {
1143 _E("Failed to setsockopt for TCP/IP socket");
1144 goto error_out_close;
1147 bzero(address, sizeof(*address));
1148 address->sin_family = AF_INET;
1149 address->sin_addr.s_addr = INADDR_ANY;
1150 address->sin_port = htons(REQUEST_SERVER_PORT);
1152 if (bind(*sock, (struct sockaddr *)address, sizeof(*address)) < 0) {
1153 _E("Failed to bind for TCP/IP socket");
1154 goto error_out_close;
1157 if (listen(*sock, PENDING_MAX) < 0) {
1158 _E("Failed to begin listenning for TCP/IP socket");
1159 goto error_out_close;
1162 *addrlen = sizeof(*address);
1172 static int request_server_func(void *ctx, void **result)
1174 struct sockaddr_un unix_address;
1175 struct sockaddr_in ip_address;
1176 struct timeval wait;
1177 int server_unix_socket;
1178 int server_ip_socket = 0;
1184 if (!g_request_server_run)
1185 return THREAD_RETURN_DONE;
1187 /* 0. initialize server socket */
1188 ret = init_unix_socket(&server_unix_socket, &unix_address, &unix_addrlen);
1192 while (g_request_server_run) {
1194 FD_SET(server_unix_socket, &fds);
1195 if (server_ip_socket)
1196 FD_SET(server_ip_socket, &fds);
1201 ret = select(FD_SETSIZE, &fds, NULL, NULL, &wait);
1203 _E("failed to select");
1204 goto error_out_close;
1207 if (FD_ISSET(server_unix_socket, &fds)) {
1208 int new_socket = accept(server_unix_socket, (struct sockaddr *)&unix_address,
1209 (socklen_t *)&unix_addrlen);
1211 if (new_socket < 0) {
1212 _E("Failed to accept");
1213 goto error_out_close;
1216 create_request_client(new_socket);
1219 if (server_ip_socket && FD_ISSET(server_ip_socket, &fds)) {
1220 int new_socket = accept(server_ip_socket, (struct sockaddr *)&ip_address,
1221 (socklen_t *)&ip_addrlen);
1223 if (new_socket < 0) {
1224 _E("Failed to accept");
1225 goto error_out_close;
1228 create_request_client(new_socket);
1231 if (!server_ip_socket && (monitor_get_debug_mode() == TRUE)) {
1234 * server_ip_socket activation can be deferred since it
1235 * will be done after timeout of select is expired. So,
1236 * when the timeout is extended, this activation should be
1237 * done by other ways in order to prevent unacceptable
1240 ret = init_ip_socket(&server_ip_socket, &ip_address, &ip_addrlen);
1242 goto error_out_close_server_unix_socket;
1243 } else if (server_ip_socket && (monitor_get_debug_mode() == FALSE)) {
1244 close(server_ip_socket);
1245 server_ip_socket = 0;
1249 close(server_unix_socket);
1250 if (server_ip_socket)
1251 close(server_ip_socket);
1253 return THREAD_RETURN_DONE;
1256 if (server_ip_socket)
1257 close(server_ip_socket);
1258 error_out_close_server_unix_socket:
1259 close(server_unix_socket);
1262 return THREAD_RETURN_ERROR;
1265 int request_server_init(void)
1267 g_request_server_run = true;
1268 if (create_daemon_thread(&g_server_thread, request_server_func, NULL))
1269 _E("Failed to create request_server_thread ");
1274 void request_server_exit(void)
1276 g_request_server_run = false;
1277 destroy_thread(g_server_thread);