Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / Linux / PlatformManagerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2018 Nest Labs, Inc.
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
21  *          Provides an implementation of the PlatformManager object
22  *          for Linux platforms.
23  */
24
25 #include <platform/internal/CHIPDeviceLayerInternal.h>
26
27 #include <platform/PlatformManager.h>
28 #include <platform/internal/GenericPlatformManagerImpl_POSIX.cpp>
29 #include <support/CHIPMem.h>
30 #include <support/logging/CHIPLogging.h>
31
32 #include <thread>
33
34 #include <arpa/inet.h>
35 #include <linux/netlink.h>
36 #include <linux/rtnetlink.h>
37 #include <net/if.h>
38 #include <netinet/in.h>
39
40 namespace chip {
41 namespace DeviceLayer {
42
43 PlatformManagerImpl PlatformManagerImpl::sInstance;
44
45 #if CHIP_WITH_GIO
46 static void GDBus_Thread()
47 {
48     GMainLoop * loop = g_main_loop_new(nullptr, false);
49
50     g_main_loop_run(loop);
51     g_main_loop_unref(loop);
52 }
53 #endif
54
55 void PlatformManagerImpl::WiFIIPChangeListener()
56 {
57     int sock;
58     if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
59     {
60         ChipLogError(DeviceLayer, "Failed to init netlink socket for ip addresses.");
61         return;
62     }
63
64     struct sockaddr_nl addr;
65     memset(&addr, 0, sizeof(addr));
66     addr.nl_family = AF_NETLINK;
67     addr.nl_groups = RTMGRP_IPV4_IFADDR;
68
69     if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1)
70     {
71         ChipLogError(DeviceLayer, "Failed to bind netlink socket for ip addresses.");
72         return;
73     }
74
75     ssize_t len;
76     char buffer[4096];
77     for (struct nlmsghdr * header = reinterpret_cast<struct nlmsghdr *>(buffer); (len = recv(sock, header, sizeof(buffer), 0)) > 0;)
78     {
79         for (struct nlmsghdr * messageHeader = header;
80              (NLMSG_OK(messageHeader, static_cast<uint32_t>(len))) && (messageHeader->nlmsg_type != NLMSG_DONE);
81              messageHeader = NLMSG_NEXT(messageHeader, len))
82         {
83             if (header->nlmsg_type == RTM_NEWADDR)
84             {
85                 struct ifaddrmsg * addressMessage = (struct ifaddrmsg *) NLMSG_DATA(header);
86                 struct rtattr * routeInfo         = IFA_RTA(addressMessage);
87                 size_t rtl                        = IFA_PAYLOAD(header);
88
89                 while (rtl && RTA_OK(routeInfo, rtl))
90                 {
91                     if (routeInfo->rta_type == IFA_LOCAL)
92                     {
93                         char name[IFNAMSIZ];
94                         ChipDeviceEvent event;
95                         if_indextoname(addressMessage->ifa_index, name);
96                         if (strcmp(name, CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME) != 0)
97                         {
98                             continue;
99                         }
100
101                         event.Type                            = DeviceEventType::kInternetConnectivityChange;
102                         event.InternetConnectivityChange.IPv4 = kConnectivity_Established;
103                         event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
104                         inet_ntop(AF_INET, RTA_DATA(routeInfo), event.InternetConnectivityChange.address,
105                                   sizeof(event.InternetConnectivityChange.address));
106
107                         ChipLogDetail(DeviceLayer, "Got IP address on interface: %s IP: %s", name,
108                                       event.InternetConnectivityChange.address);
109
110                         PlatformMgr().LockChipStack();
111                         PlatformMgr().PostEvent(&event);
112                         PlatformMgr().UnlockChipStack();
113                     }
114                     routeInfo = RTA_NEXT(routeInfo, rtl);
115                 }
116             }
117         }
118     }
119 }
120
121 CHIP_ERROR PlatformManagerImpl::_InitChipStack()
122 {
123     CHIP_ERROR err;
124
125 #if CHIP_WITH_GIO
126     GError * error = nullptr;
127
128     this->mpGDBusConnection = UniqueGDBusConnection(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error));
129
130     std::thread gdbusThread(GDBus_Thread);
131     gdbusThread.detach();
132 #endif
133
134     std::thread wifiIPThread(WiFIIPChangeListener);
135     wifiIPThread.detach();
136
137     // Initialize the configuration system.
138     err = Internal::PosixConfig::Init();
139     SuccessOrExit(err);
140     // Call _InitChipStack() on the generic implementation base class
141     // to finish the initialization process.
142     err = Internal::GenericPlatformManagerImpl_POSIX<PlatformManagerImpl>::_InitChipStack();
143     SuccessOrExit(err);
144
145 exit:
146     return err;
147 }
148
149 #if CHIP_WITH_GIO
150 GDBusConnection * PlatformManagerImpl::GetGDBusConnection()
151 {
152     return this->mpGDBusConnection.get();
153 }
154 #endif
155
156 } // namespace DeviceLayer
157 } // namespace chip