3#include "libxr_def.hpp"
4#if defined(HAVE_WPA_CLIENT)
6#include <NetworkManager.h>
16#include "net/wifi_client.hpp"
36 strncpy(ifname_cstr_, ifname,
sizeof(ifname_cstr_) - 1);
40 std::string iface = DetectWifiInterface();
43 XR_LOG_ERROR(
"Wi-Fi interface not found");
48 strncpy(ifname_cstr_, iface.c_str(),
sizeof(ifname_cstr_) - 1);
52 socket_path_ =
"/var/run/wpa_supplicant/" + std::string(ifname_cstr_);
63 wpa_ctrl_close(ctrl_);
73 ctrl_ = wpa_ctrl_open(socket_path_.c_str());
76 XR_LOG_PASS(
"Wi-Fi enabled: %s", socket_path_.c_str());
79 XR_LOG_ERROR(
"Wi-Fi enable failed: %s", socket_path_.c_str());
88 wpa_ctrl_close(ctrl_);
96 if (!SendCommand(
"STATUS", out))
100 return out.find(
"wpa_state=COMPLETED") != std::string::npos;
106 auto ans = snprintf(cmd,
sizeof(cmd),
"ip -4 addr show %s | grep inet", ifname_cstr_);
108 FILE* fp = popen(cmd,
"r");
116 if (fgets(buf,
sizeof(buf), fp))
118 char ip_str[32] = {};
119 auto ret = sscanf(buf,
" inet %[^/]", ip_str);
121 ip = IPAddressRaw::FromString(ip_str);
130 auto ans = snprintf(path,
sizeof(path),
"/sys/class/net/%s/address", ifname_cstr_);
132 FILE* fp = fopen(path,
"r");
138 char mac_str[32] = {};
139 if (!fgets(mac_str,
sizeof(mac_str), fp))
141 auto ans = fclose(fp);
145 auto ret = fclose(fp);
147 mac_str[strcspn(mac_str,
"\n")] = 0;
148 return MACAddressRaw::FromString(mac_str);
154 SendCommand(
"REMOVE_NETWORK all", out);
155 SendCommand(
"ADD_NETWORK", out);
156 int netid = atoi(out.c_str());
159 XR_LOG_ERROR(
"ADD_NETWORK failed: %s", out.c_str());
163 std::stringstream cmd;
164 cmd <<
"SET_NETWORK " << netid <<
" ssid \"" << config.
ssid <<
"\"";
165 if (!SendCommand(cmd.str().c_str(), out) || out.find(
"OK") == std::string::npos)
167 XR_LOG_ERROR(
"SET_NETWORK ssid failed: %s", out.c_str());
172 cmd <<
"SET_NETWORK " << netid <<
" psk \"" << config.
password <<
"\"";
173 if (!SendCommand(cmd.str().c_str(), out) || out.find(
"OK") == std::string::npos)
175 XR_LOG_ERROR(
"SET_NETWORK psk failed: %s", out.c_str());
179 std::vector<std::string> cleanup_cmds = {
180 "key_mgmt WPA-PSK",
"eap NONE",
"phase1 \"\"",
"identity \"\"",
"password \"\"",
182 for (
const auto& line : cleanup_cmds)
185 cmd <<
"SET_NETWORK " << netid <<
" " << line;
186 SendCommand(cmd.str().c_str(), out);
190 cmd <<
"ENABLE_NETWORK " << netid;
191 if (!SendCommand(cmd.str().c_str(), out) || out.find(
"OK") == std::string::npos)
193 XR_LOG_ERROR(
"ENABLE_NETWORK failed: %s", out.c_str());
198 cmd <<
"SELECT_NETWORK " << netid;
199 SendCommand(cmd.str().c_str(), out);
201 const int TIMEOUT_MS = 30000;
202 const int INTERVAL_MS = 300;
205 while (elapsed < TIMEOUT_MS)
208 SendCommand(
"STATUS", status);
210 if (status.find(
"wpa_state=COMPLETED") != std::string::npos)
212 XR_LOG_PASS(
"Wi-Fi Connected to SSID: %s", config.
ssid);
216 if (status.find(
"wpa_state=INACTIVE") != std::string::npos)
218 XR_LOG_ERROR(
"Wi-Fi Connection failed: %s", status.c_str());
223 elapsed += INTERVAL_MS;
226 XR_LOG_ERROR(
"Wi-Fi Connection timeout");
233 SendCommand(
"DISCONNECT", out);
234 SendCommand(
"REMOVE_NETWORK all", out);
245 SendCommand(
"SCAN", out);
247 SendCommand(
"SCAN_RESULTS", out);
249 std::istringstream ss(out);
252 std::getline(ss, line);
253 while (std::getline(ss, line) && out_found < max_count)
255 std::istringstream ls(line);
256 std::string bssid, freq, signal, flags, ssid;
257 ls >> bssid >> freq >> signal >> flags;
258 std::getline(ls, ssid);
259 if (!ssid.empty() && ssid[0] ==
'\t')
264 auto& r = out_list[out_found++];
265 strncpy(r.ssid, ssid.c_str(),
sizeof(r.ssid) - 1);
266 r.rssi = atoi(signal.c_str());
277 SendCommand(
"SIGNAL_POLL", out);
278 auto pos = out.find(
"RSSI=");
279 return pos != std::string::npos ? atoi(out.c_str() + pos + 5) : 0;
283 bool SendCommand(
const char* cmd, std::string& result)
const
290 size_t len =
sizeof(buf);
291 int ret = wpa_ctrl_request(ctrl_, cmd, strlen(cmd), buf, &len,
nullptr);
294 result.assign(buf, len);
297 XR_LOG_ERROR(
"wpa_ctrl_request failed: %s\n", strerror(errno));
301 std::string DetectWifiInterface()
303 GError* error =
nullptr;
304 NMClient* client = nm_client_new(
nullptr, &error);
307 auto ans = fprintf(stderr,
"Failed to create NMClient: %s\n",
308 error ? error->message :
"unknown error");
318 const GPtrArray* devices = nm_client_get_devices(client);
319 for (guint i = 0; i < devices->len; ++i)
321 NMDevice* dev = (NMDevice*)g_ptr_array_index(devices, i);
322 if (NM_IS_DEVICE_WIFI(dev))
324 const char* ifname = nm_device_get_iface(dev);
327 std::string iface_str(ifname);
328 g_object_unref(client);
334 g_object_unref(client);
338 char ifname_cstr_[32] = {};
339 std::string socket_path_;
340 wpa_ctrl* ctrl_ =
nullptr;
Linux Wi-Fi 客户端实现 / Linux Wi-Fi client implementation.
WifiError Connect(const Config &config) override
连接到指定 WiFi 网络 / Connect to a WiFi network
~LinuxWifiClient() override
析构函数 / Destructor
bool Enable() override
启用网络接口(WiFi) / Enable the network interface
IPAddressRaw GetIPAddress() const override
获取当前 IP 地址 / Get current IP address
bool IsConnected() const override
检查是否已连接 / Check if currently connected
MACAddressRaw GetMACAddress() const override
获取当前 MAC 地址 / Get MAC address
int GetRSSI() const override
获取当前 WiFi 信号强度(RSSI) / Get current signal strength
void Disable() override
禁用网络接口(WiFi) / Disable the network interface
WifiError Disconnect() override
断开当前 WiFi 连接 / Disconnect from the WiFi network
WifiError Scan(ScanResult *out_list, size_t max_count, size_t &out_found) override
扫描可用网络 / Scan for available WiFi networks
LinuxWifiClient(const char *ifname=nullptr)
构造客户端对象 / Construct client object
static void Sleep(uint32_t milliseconds)
让线程进入休眠状态 Puts the thread to sleep
WiFi 客户端接口 / WiFi Client Interface.
@ OPEN
开放网络 / Open network
WifiError
WiFi 错误码 / Enumeration of WiFi error codes.
@ AUTHENTICATION_FAILED
身份验证失败 / Authentication failed
@ UNKNOWN
未知错误 / Unknown error
@ HARDWARE_FAILURE
硬件故障 / Hardware failure
@ CONNECTION_TIMEOUT
连接超时 / Connection timeout
LibXR 命名空间 / LibXR namespace.
原始 IPv4 地址 / Raw IPv4 address
原始 MAC 地址 / Raw MAC address
WiFi 连接配置 / WiFi connection configuration.
char ssid[33]
SSID 名称 / SSID name.
char password[64]
密码 / Password
WiFi 扫描结果 / WiFi scan result.