Add Wifi Direct Service Discovery
[platform/core/connectivity/wifi-direct-manager.git] / src / wifi-direct-group.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
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 /**
21  * This file implements wifi direct group functions.
22  *
23  * @file                wifi-direct-group.c
24  * @author      Gibyoung Kim (lastkgb.kim@samsung.com)
25  * @version     0.7
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <errno.h>
31
32 #include <glib.h>
33
34 #include <wifi-direct-internal.h>
35
36 #include "wifi-direct-manager.h"
37 #include "wifi-direct-peer.h"
38 #include "wifi-direct-oem.h"
39 #include "wifi-direct-group.h"
40 #include "wifi-direct-util.h"
41 #include "wifi-direct-session.h"
42 #include "wifi-direct-client.h"
43
44 // Check the group instance which has same interface name, before using this function
45 wfd_group_s *wfd_create_group(void *data, char *ifname, int role, unsigned char *go_dev_addr)
46 {
47         __WDS_LOG_FUNC_ENTER__;
48         wfd_group_s *group = NULL;
49         wfd_manager_s *manager = (wfd_manager_s*) data;
50
51         if (!manager || !ifname || !go_dev_addr) {
52                 WDS_LOGE("Invalid parameter");
53                 __WDS_LOG_FUNC_EXIT__;
54                 return NULL;
55         }
56
57         group = manager->group;
58         if (group) {
59                 WDS_LOGE("Group already exist");
60                 __WDS_LOG_FUNC_EXIT__;
61                 return NULL;
62         }
63
64         errno = 0;
65         group = (wfd_group_s*) calloc(1, sizeof(wfd_group_s));
66         if (!group) {
67                 WDS_LOGE("Failed to allocate memory for group. [%s]", strerror(errno));
68                 __WDS_LOG_FUNC_EXIT__;
69                 return NULL;
70         }
71
72         memcpy(group->ifname, ifname, IFACE_NAME_LEN);
73         group->ifname[IFACE_NAME_LEN] = '\0';
74         group->role = role;
75         memcpy(group->go_dev_addr, go_dev_addr, MACADDR_LEN);
76         group->pending = 0;
77
78         wfd_util_dhcps_start();
79         WDS_LOGD("Role is Group Owner. DHCP Server started");
80
81         __WDS_LOG_FUNC_EXIT__;
82         return group;
83 }
84
85 // Used for CTRL-EVENT_CONNECTED event that comes before group created
86 wfd_group_s *wfd_create_pending_group(void *data, unsigned char * bssid)
87 {
88         __WDS_LOG_FUNC_ENTER__;
89         wfd_group_s *group = NULL;
90         wfd_manager_s *manager = (wfd_manager_s*) data;
91
92         if (!manager || !bssid) {
93                 WDS_LOGE("Invalid parameter");
94                 __WDS_LOG_FUNC_EXIT__;
95                 return NULL;
96         }
97
98         group = manager->group;
99         if (group) {
100                 WDS_LOGE("Group already exist");
101                 __WDS_LOG_FUNC_EXIT__;
102                 return NULL;
103         }
104
105         errno = 0;
106         group = (wfd_group_s*) calloc(1, sizeof(wfd_group_s));
107         if (!group) {
108                 WDS_LOGE("Failed to allocate memory for group. [%s]", strerror(errno));
109                 __WDS_LOG_FUNC_EXIT__;
110                 return NULL;
111         }
112
113         memcpy(group->bssid, bssid, MACADDR_LEN);
114         group->pending = 1;
115
116         __WDS_LOG_FUNC_EXIT__;
117         return group;
118 }
119
120 int wfd_group_complete(void *data, char *ifname, int role, unsigned char *go_dev_addr)
121 {
122         __WDS_LOG_FUNC_ENTER__;
123         wfd_manager_s *manager = (wfd_manager_s*) data;
124         wfd_group_s *group = NULL;
125         wfd_device_s *peer = NULL;
126
127         if (!manager || !ifname || !go_dev_addr) {
128                 WDS_LOGE("Invalid parameter");
129                 __WDS_LOG_FUNC_EXIT__;
130                 return -1;
131         }
132
133         group = manager->group;
134         if (!group) {
135                 WDS_LOGE("Group not found");
136                 return -1;
137         }
138
139         if (!group->pending) {
140                 WDS_LOGE("This is not pending group");
141                 __WDS_LOG_FUNC_EXIT__;
142                 return -1;
143         }
144
145         memcpy(group->ifname, ifname, IFACE_NAME_LEN);
146         group->ifname[IFACE_NAME_LEN] = '\0';
147         group->role = role;
148         memcpy(group->go_dev_addr, go_dev_addr, MACADDR_LEN);
149         group->pending = 0;
150
151         peer = wfd_session_get_peer(manager->session);
152         if (!peer && !(group->flags & WFD_GROUP_FLAG_AUTONOMOUS)) {
153                 WDS_LOGE("Failed to find peer by device address[" MACSTR "]", go_dev_addr);
154                 return -1;
155         }
156         if (group->role == WFD_DEV_ROLE_GO) {
157                 wfd_util_dhcps_start();
158                 WDS_LOGD("Role is Group Owner. DHCP Server started");
159         } else {
160                 wfd_util_dhcpc_start(peer);
161         }
162
163         __WDS_LOG_FUNC_EXIT__;
164         return 0;
165 }
166
167 int wfd_destroy_group(void *data, char *ifname)
168 {
169         __WDS_LOG_FUNC_ENTER__;
170         wfd_group_s *group = NULL;
171         wfd_manager_s *manager = (wfd_manager_s*) data;
172         GList *temp = NULL;
173         wfd_device_s *member = NULL;
174         int count = 0;
175
176         if (!data || !ifname) {
177                 WDS_LOGE("Invalid parameter");
178                 __WDS_LOG_FUNC_EXIT__;
179                 return -1;
180         }
181
182         group = manager->group;
183         if (!group) {
184                 WDS_LOGE("Group not exist");
185                 __WDS_LOG_FUNC_EXIT__;
186                 return -1;
187         }
188         manager->group = NULL;
189
190         if (group->role == WFD_DEV_ROLE_GO)
191                 wfd_util_dhcps_stop();
192         else
193                 wfd_util_dhcpc_stop();
194
195         temp = g_list_first(group->members);
196         while(temp && count < group->member_count) {
197                 member = temp->data;
198                 WDS_LOGD("%dth member[%s] freed", count, member->dev_name);
199                 if (member)     // Temporary. Sometimes manager crashed
200                 {
201                         wfd_manager_init_service(member);
202                         free(member);
203                 }
204                 temp = g_list_next(temp);
205                 count++;
206         }
207         g_list_free(group->members);
208
209         free(group);
210
211         manager->local->dev_role = WFD_DEV_ROLE_NONE;
212         __WDS_LOG_FUNC_EXIT__;
213         return 0;
214 }
215
216 int wfd_group_get_channel(wfd_group_s *group)
217 {
218         __WDS_LOG_FUNC_ENTER__;
219
220         if (!group) {
221                 WDS_LOGE("Invalid parameter");
222                 __WDS_LOG_FUNC_EXIT__;
223                 return -1;
224         }
225
226         __WDS_LOG_FUNC_EXIT__;
227         return group->freq;
228 }
229
230 int wfd_group_is_autonomous(wfd_group_s *group)
231 {
232         __WDS_LOG_FUNC_ENTER__;
233
234         if (!group) {
235                 WDS_LOGE("Invalid parameter");
236                 __WDS_LOG_FUNC_EXIT__;
237                 return -1;
238         }
239
240         __WDS_LOG_FUNC_EXIT__;
241         return group->flags & WFD_GROUP_FLAG_AUTONOMOUS;;
242 }
243
244 int wfd_group_get_members()
245 {
246         __WDS_LOG_FUNC_ENTER__;
247
248         __WDS_LOG_FUNC_EXIT__;
249         return 0;
250 }
251
252 int wfd_group_make_persistent()
253 {
254         __WDS_LOG_FUNC_ENTER__;
255
256         __WDS_LOG_FUNC_EXIT__;
257         return 0;
258 }
259
260 int wfd_group_get_flags(wfd_group_s *group)
261 {
262         __WDS_LOG_FUNC_ENTER__;
263
264         if (!group) {
265                 WDS_LOGE("Invalid parameter");
266                 __WDS_LOG_FUNC_EXIT__;
267                 return -1;
268         }
269
270         __WDS_LOG_FUNC_EXIT__;
271         return group->flags;
272 }
273
274 wfd_device_s *wfd_group_find_member_by_addr(wfd_group_s *group, unsigned char *addr)
275 {
276         __WDS_LOG_FUNC_ENTER__;
277         GList *temp = NULL;
278         wfd_device_s *member = NULL;
279
280         if (!group || !addr) {
281                 WDS_LOGE("Invalid parameter");
282                 __WDS_LOG_FUNC_EXIT__;
283                 return NULL;
284         }
285
286         if (!group->member_count) {
287                 WDS_LOGE("There is no members");
288                 __WDS_LOG_FUNC_EXIT__;
289                 return NULL;
290         }
291
292         temp = g_list_first(group->members);
293         while (temp) {
294                 member = temp->data;
295                 if (!memcmp(member->intf_addr, addr, MACADDR_LEN) ||
296                                 !memcmp(member->dev_addr, addr, MACADDR_LEN)) {
297                         WDS_LOGD("Member found");
298                         break;
299                 }
300 next:
301                 temp = g_list_next(temp);
302                 member = NULL;
303         }
304
305         __WDS_LOG_FUNC_EXIT__;
306         return member;
307 }
308
309 int wfd_group_add_member(wfd_group_s *group, unsigned char *addr)
310 {
311         __WDS_LOG_FUNC_ENTER__;
312         wfd_device_s *member = NULL;
313         wfd_manager_s *manager = wfd_get_manager();
314
315         if (!group || !addr) {
316                 WDS_LOGE("Invalid parameter");
317                 __WDS_LOG_FUNC_EXIT__;
318                 return -1;
319         }
320
321         member = wfd_group_find_member_by_addr(group, addr);
322         if (member) {
323                 WDS_LOGE("Member already exist");
324                 return -1;
325         }
326
327         member = wfd_peer_find_by_addr(manager, addr);
328         if (!member) {
329                 WDS_LOGE("Peer not found");
330         }
331
332         group->members = g_list_prepend(group->members, member);
333         group->member_count++;
334
335         manager->peers = g_list_remove(manager->peers, member);
336         manager->peer_count--;
337
338         __WDS_LOG_FUNC_EXIT__;
339         return 0;
340 }
341
342 int wfd_group_remove_member(wfd_group_s *group, unsigned char *addr)
343 {
344         __WDS_LOG_FUNC_ENTER__;
345         wfd_device_s *member = NULL;
346
347         if (!group || !addr) {
348                 WDS_LOGE("Invalid parameter");
349                 __WDS_LOG_FUNC_EXIT__;
350                 return -1;
351         }
352
353         if (group->member_count == 0) {
354                 WDS_LOGE("There is no members");
355                 __WDS_LOG_FUNC_EXIT__;
356                 return -1;
357         }
358
359         member = wfd_group_find_member_by_addr(group, addr);
360         if (!member) {
361                 WDS_LOGE("Member not found [MAC: " MACSTR "]", addr);
362                 __WDS_LOG_FUNC_EXIT__;
363                 return -1;
364         }
365
366         group->members = g_list_remove(group->members, member);
367         free(member);
368         group->member_count--;
369
370         __WDS_LOG_FUNC_EXIT__;
371         return 0;
372 }