Compare commits
2 commits
8b3ef2c346
...
59861872f4
| Author | SHA1 | Date | |
|---|---|---|---|
| 59861872f4 | |||
| 0f34fe39e0 |
4 changed files with 82 additions and 10 deletions
|
|
@ -257,13 +257,24 @@ _rebuild_list(Popup *p)
|
|||
memcpy(ssid_buf + copy, "\xe2\x80\xa6", 4); /* "…" + NUL */
|
||||
raw_ssid = ssid_buf;
|
||||
}
|
||||
/* Connection marker: connecting (…) and failure (!) take priority
|
||||
* over Connected, which iwd may briefly assert mid-handshake. */
|
||||
const char *mark, *amark;
|
||||
switch (n->conn_status)
|
||||
{
|
||||
case IWD_CONN_CONNECTING: mark = " …"; amark = ", connecting"; break;
|
||||
case IWD_CONN_FAILED: mark = " !"; amark = ", failed"; break;
|
||||
default:
|
||||
mark = n->connected ? " ✔" : "";
|
||||
amark = n->connected ? ", connected" : "";
|
||||
}
|
||||
char label[256];
|
||||
snprintf(label, sizeof(label), "%s %s%s [%s]%s",
|
||||
_signal_bars(iwd_network_signal_tier(n)),
|
||||
n->known_path ? "★ " : " ",
|
||||
raw_ssid,
|
||||
iwd_security_label(n->security),
|
||||
n->connected ? " ✔" : "");
|
||||
mark);
|
||||
elm_object_text_set(btn, label);
|
||||
/* Spoken label: avoids the ▂▄▆█ glyphs and ★/✔ markers which
|
||||
* screen readers announce as raw Unicode. */
|
||||
|
|
@ -274,7 +285,7 @@ _rebuild_list(Popup *p)
|
|||
iwd_network_signal_tier(n),
|
||||
iwd_security_label(n->security),
|
||||
n->known_path ? ", saved" : "",
|
||||
n->connected ? ", connected" : "");
|
||||
amark);
|
||||
elm_object_access_info_set(btn, access);
|
||||
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0);
|
||||
evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, 0);
|
||||
|
|
|
|||
|
|
@ -245,6 +245,20 @@ _on_iface_removed(void *data, const char *path, const char *iface)
|
|||
{
|
||||
eina_hash_del(m->networks, path, NULL);
|
||||
}
|
||||
else if (!strcmp(iface, IWD_IFACE_KNOWN_NETWORK))
|
||||
{
|
||||
/* A saved network was forgotten: iwd removes the KnownNetwork object
|
||||
* but the matching Network.KnownNetwork change arrives only as an
|
||||
* invalidation, which our changed-only property handler drops. Clear
|
||||
* the back-reference here so the ★ marker and Forget (✕) button vanish
|
||||
* immediately instead of lingering until the next full repopulate. */
|
||||
Eina_Iterator *it = eina_hash_iterator_data_new(m->networks);
|
||||
Iwd_Network *n;
|
||||
EINA_ITERATOR_FOREACH(it, n)
|
||||
if (n->known_path && !strcmp(n->known_path, path))
|
||||
{ free(n->known_path); n->known_path = NULL; }
|
||||
eina_iterator_free(it);
|
||||
}
|
||||
else if (!strcmp(iface, IWD_IFACE_ADAPTER))
|
||||
{
|
||||
eina_hash_del(m->adapters, path, NULL);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,12 @@ _prop_cb(void *data, const char *key, Eldbus_Message_Iter *v)
|
|||
Iwd_Network *n = data;
|
||||
if (!strcmp(key, "Name")) { free(n->ssid); n->ssid = iwd_props_str_dup(v); }
|
||||
else if (!strcmp(key, "Type")) { char *s = iwd_props_str_dup(v); n->security = _sec_from_str(s); free(s); }
|
||||
else if (!strcmp(key, "Connected")) { n->connected = iwd_props_bool(v); }
|
||||
else if (!strcmp(key, "Connected")) {
|
||||
n->connected = iwd_props_bool(v);
|
||||
/* A confirmed connection clears any in-flight/failed marker so the
|
||||
* row settles on ✔ (and a stale ! from a prior attempt disappears). */
|
||||
if (n->connected) n->conn_status = IWD_CONN_IDLE;
|
||||
}
|
||||
else if (!strcmp(key, "Device")) { free(n->device_path); n->device_path = iwd_props_str_dup(v); }
|
||||
else if (!strcmp(key, "KnownNetwork")) { free(n->known_path); n->known_path = iwd_props_str_dup(v); }
|
||||
}
|
||||
|
|
@ -79,25 +84,50 @@ iwd_network_free(Iwd_Network *n)
|
|||
free(n);
|
||||
}
|
||||
|
||||
/* Reply context captures the *manager* (which outlives all sub-objects) and
|
||||
* a strdup'd SSID, never the Iwd_Network — the network may disappear from
|
||||
* the next scan before iwd's reply lands, and a raw back-ref would UAF. */
|
||||
/* Reply context captures the *manager* (which outlives all sub-objects) plus
|
||||
* a strdup'd SSID and object path, never the Iwd_Network — the network may
|
||||
* disappear from the next scan before iwd's reply lands, and a raw back-ref
|
||||
* would UAF. The path is re-resolved through the live hash at reply time. */
|
||||
typedef struct
|
||||
{
|
||||
Iwd_Manager *m;
|
||||
char *ssid;
|
||||
char *path;
|
||||
} _Net_Reply_Ctx;
|
||||
|
||||
static Iwd_Network *
|
||||
_ctx_resolve(const _Net_Reply_Ctx *ctx)
|
||||
{
|
||||
if (!ctx->m || !ctx->path) return NULL;
|
||||
const Eina_Hash *h = iwd_manager_networks(ctx->m);
|
||||
return h ? eina_hash_find(h, ctx->path) : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_on_connect_reply(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED)
|
||||
{
|
||||
_Net_Reply_Ctx *ctx = data;
|
||||
Iwd_Network *n = _ctx_resolve(ctx);
|
||||
const char *en, *em;
|
||||
if (eldbus_message_error_get(msg, &en, &em) && ctx->m)
|
||||
iwd_manager_report_error(ctx->m,
|
||||
"Connect to '%s' failed: %s",
|
||||
ctx->ssid ? ctx->ssid : "?", em ? em : en);
|
||||
if (eldbus_message_error_get(msg, &en, &em))
|
||||
{
|
||||
/* iwd only fails Connect() once the attempt is truly over — wrong
|
||||
* passphrase, out of range, etc. Mark the row failed (!) rather than
|
||||
* leaving a misleading ✔ behind. */
|
||||
if (n) n->conn_status = IWD_CONN_FAILED;
|
||||
if (ctx->m)
|
||||
iwd_manager_report_error(ctx->m,
|
||||
"Connect to '%s' failed: %s",
|
||||
ctx->ssid ? ctx->ssid : "?", em ? em : en);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n) n->conn_status = IWD_CONN_IDLE;
|
||||
/* report_error notifies on the failure path; do it here for success. */
|
||||
if (ctx->m) iwd_manager_notify(ctx->m);
|
||||
}
|
||||
free(ctx->ssid);
|
||||
free(ctx->path);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +141,7 @@ _on_forget_reply(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_U
|
|||
"Forget '%s' failed: %s",
|
||||
ctx->ssid ? ctx->ssid : "?", em ? em : en);
|
||||
free(ctx->ssid);
|
||||
free(ctx->path);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +165,7 @@ _reply_ctx_new(Iwd_Network *n)
|
|||
if (!ctx) return NULL;
|
||||
ctx->m = n->manager;
|
||||
ctx->ssid = n->ssid ? strdup(n->ssid) : NULL;
|
||||
ctx->path = n->path ? strdup(n->path) : NULL;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
@ -141,6 +173,10 @@ void
|
|||
iwd_network_connect(Iwd_Network *n)
|
||||
{
|
||||
if (!n || !n->proxy) return;
|
||||
/* Show progress immediately and clear any prior failure marker; the reply
|
||||
* (success/failure) and the Connected property settle the final state. */
|
||||
n->conn_status = IWD_CONN_CONNECTING;
|
||||
if (n->manager) iwd_manager_notify(n->manager);
|
||||
/* Network.Connect() takes no args; iwd will dial the registered Agent
|
||||
* for a passphrase if needed. */
|
||||
eldbus_proxy_call(n->proxy, "Connect", _on_connect_reply,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,16 @@ typedef enum {
|
|||
IWD_SEC_UNKNOWN,
|
||||
} Iwd_Security;
|
||||
|
||||
/* Connection attempt status, tracked locally from our own Connect() call so
|
||||
* the row can show progress and failure. iwd's Network.Connect() only returns
|
||||
* once the attempt concludes, so its reply is authoritative — Network.Connected
|
||||
* may flicker true mid-handshake and must not be trusted on its own. */
|
||||
typedef enum {
|
||||
IWD_CONN_IDLE, /* not attempting; ✔ iff Network.Connected */
|
||||
IWD_CONN_CONNECTING, /* Connect() in flight */
|
||||
IWD_CONN_FAILED, /* last Connect() returned an error (e.g. bad PSK) */
|
||||
} Iwd_Conn_Status;
|
||||
|
||||
typedef struct _Iwd_Network Iwd_Network;
|
||||
|
||||
struct _Iwd_Network
|
||||
|
|
@ -23,6 +33,7 @@ struct _Iwd_Network
|
|||
char *known_path;
|
||||
Iwd_Security security;
|
||||
Eina_Bool connected;
|
||||
Iwd_Conn_Status conn_status;
|
||||
|
||||
/* Signal strength in 100*dBm units (iwd convention). Valid iff have_signal. */
|
||||
int16_t signal_dbm;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue