mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 03:21:08 +00:00
perf: network tables Android refuses are served from the synthesized copy without retrying the open (#1275)
This commit is contained in:
1 parent
e04727dbaf
commit
7fa8008944
1 file changed
+52
-11
@@ -506,19 +506,55 @@ static void write_table(FILE *out, const char *table, const struct link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
static const char *denied_table(const char *path) {
|
||||
static const char *const tables[] = { "route", "ipv6_route", "if_inet6", "dev", "arp" };
|
||||
#define CARRIER_TABLE 5
|
||||
|
||||
static const char *const net_tables[] = { "route", "ipv6_route", "if_inet6", "dev", "arp", "carrier" };
|
||||
static long long net_denied_at[sizeof(net_tables) / sizeof(net_tables[0])];
|
||||
|
||||
#define CARRIER_SLOTS 8
|
||||
|
||||
static struct { char path[64]; long long at; } carrier_denied[CARRIER_SLOTS];
|
||||
|
||||
static int denied_recently(int table, const char *path) {
|
||||
if (table != CARRIER_TABLE) return fresh(&net_denied_at[table]);
|
||||
int hit = 0;
|
||||
pthread_mutex_lock(&link_lock);
|
||||
for (int i = 0; i < CARRIER_SLOTS && !hit; i++) {
|
||||
hit = strcmp(carrier_denied[i].path, path) == 0 && fresh(&carrier_denied[i].at);
|
||||
}
|
||||
pthread_mutex_unlock(&link_lock);
|
||||
return hit;
|
||||
}
|
||||
|
||||
static void remember_denial(int table, const char *path) {
|
||||
if (table != CARRIER_TABLE) {
|
||||
__atomic_store_n(&net_denied_at[table], now_ns(), __ATOMIC_RELAXED);
|
||||
return;
|
||||
}
|
||||
if (strlen(path) >= sizeof(carrier_denied[0].path)) return;
|
||||
pthread_mutex_lock(&link_lock);
|
||||
int slot = 0;
|
||||
for (int i = 0; i < CARRIER_SLOTS; i++) {
|
||||
if (strcmp(carrier_denied[i].path, path) == 0) { slot = i; break; }
|
||||
if (carrier_denied[i].at < carrier_denied[slot].at) slot = i;
|
||||
}
|
||||
snprintf(carrier_denied[slot].path, sizeof(carrier_denied[slot].path), "%s", path);
|
||||
carrier_denied[slot].at = now_ns();
|
||||
pthread_mutex_unlock(&link_lock);
|
||||
}
|
||||
|
||||
static int denied_table(const char *path) {
|
||||
if (strncmp(path, "/proc/net/", 10) == 0) {
|
||||
for (size_t i = 0; i < sizeof(tables) / sizeof(tables[0]); i++) {
|
||||
if (strcmp(path + 10, tables[i]) == 0) return tables[i];
|
||||
for (int i = 0; i < CARRIER_TABLE; i++) {
|
||||
if (strcmp(path + 10, net_tables[i]) == 0) return i;
|
||||
}
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
size_t len = strlen(path);
|
||||
if (strncmp(path, "/sys/class/net/", 15) == 0 && len > 8 && strcmp(path + len - 8, "/carrier") == 0) {
|
||||
return "carrier";
|
||||
return CARRIER_TABLE;
|
||||
}
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static FILE *synthesize(const char *table) {
|
||||
@@ -550,11 +586,16 @@ static FILE *open_stream(fopen_fn real, const char *path, const char *mode, cons
|
||||
if (copy == NULL) close(status);
|
||||
return copy;
|
||||
}
|
||||
FILE *f = real(path, mode);
|
||||
if (f || path == NULL || mode == NULL || mode[0] != 'r') return f;
|
||||
int table = path && mode && mode[0] == 'r' ? denied_table(path) : -1;
|
||||
FILE *f;
|
||||
if (table >= 0 && denied_recently(table, path) && (f = synthesize(net_tables[table])) != NULL) return f;
|
||||
f = real(path, mode);
|
||||
if (f || table < 0) return f;
|
||||
int saved = errno;
|
||||
const char *table = denied_table(path);
|
||||
if (table && (f = synthesize(table)) != NULL) return f;
|
||||
if ((f = synthesize(net_tables[table])) != NULL) {
|
||||
if (saved == EACCES) remember_denial(table, path);
|
||||
return f;
|
||||
}
|
||||
errno = saved;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user