4 * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
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: net_activity.h
22 * @desc Handler which get data from generic netlink (NET_ACTIVITY) family
26 #include "net-cls-cgroup.h"
27 #include "generic-netlink.h"
32 #include <data_usage.h>
37 #define NET_ACTIVITY_LISTEN_TIMEOUT 10
39 static pthread_t net_activity_worker;
41 struct net_activity_context {
43 uint32_t group_family_id;
48 static void set_socket_option(int sock)
51 int opts = fcntl(sock, F_GETFL);
53 ret_msg_if(opts < 0, "fcntl error");
54 opts = (opts | O_NONBLOCK);
56 ret = fcntl(sock, F_SETFL, opts);
57 ret_msg_if(ret < 0, "fcntl error");
61 * Convert the netlink multicast group id into a bit map
62 * (e.g. 4 => 16, 5 => 32)
64 static uint32_t convert_mcast_group_id(uint32_t group_id)
67 _E("Netlink: Use setsockopt for this group: %u\n", group_id);
70 return group_id ? (1 << (group_id - 1)) : 0;
73 static void *net_activity_func(void *user_data)
76 struct net_activity_context *context =
77 (struct net_activity_context *)user_data;
78 struct net_activity_info activity_info;
79 struct timeval timeout = {0};
82 max_fd = context->sock + 1;
85 timeout.tv_sec = NET_ACTIVITY_LISTEN_TIMEOUT;
87 FD_SET(context->sock, &rfd);
89 ret = select(max_fd, &rfd, NULL, NULL, &timeout);
92 _E("Failed to select on generic netlink socket");
93 goto stop_net_activity;
101 ret = recv_net_activity(context->sock, &activity_info,
104 if (ret == RESOURCED_NET_ACTIVITY_STOP)
105 goto stop_net_activity;
106 else if (ret == RESOURCED_NET_ACTIVITY_CONTINUE)
109 if (context->cb(&activity_info) == RESOURCED_CANCEL)
110 goto stop_net_activity;
115 close(context->sock);
121 API resourced_ret_c register_net_activity_cb(net_activity_cb activity_cb)
124 struct net_activity_context *context;
127 ret_value_msg_if(!activity_cb, RESOURCED_ERROR_INVALID_PARAMETER,
128 "Please provide valid callback function!");
130 context = (struct net_activity_context *)malloc(
131 sizeof(struct net_activity_context));
133 ret_value_if(!context, RESOURCED_ERROR_OUT_OF_MEMORY);
135 context->cb = activity_cb;
136 ret = update_classids();
137 if (ret != RESOURCED_ERROR_NONE) {
138 _E("Failed to update appid!");
142 context->sock = create_netlink(NETLINK_GENERIC, 0);
144 if (context->sock < 0) {
145 _E("Cant create socket");
149 set_socket_option(context->sock);
151 /* Initialize family id to communicate with NET_ACTIVITY chanel */
152 context->group_family_id = get_family_group_id(context->sock,
153 pid, "NET_ACTIVITY", "NET_ACT_MCAST", &context->family_id);
155 start_net_activity();
157 if (context->family_id == 0 || context->group_family_id == 0) {
158 _E("Cant get family id");
162 /* this one is no more needed */
163 close(context->sock);
165 /* New one subscribed to group_family_id */
166 context->sock = create_netlink(NETLINK_GENERIC,
167 convert_mcast_group_id(context->group_family_id));
169 if (context->sock < 0) {
170 _E("Failed to create multicast socket!");
175 pthread_create(&net_activity_worker, NULL, net_activity_func,
178 return RESOURCED_ERROR_NONE;
181 close(context->sock);
187 return RESOURCED_ERROR_FAIL;