Skip to content

Commit

Permalink
Getting rid of network client
Browse files Browse the repository at this point in the history
  • Loading branch information
teclator committed Aug 1, 2024
1 parent 9fe32ae commit 9f88be2
Show file tree
Hide file tree
Showing 17 changed files with 429 additions and 557 deletions.
36 changes: 0 additions & 36 deletions rust/data.json

This file was deleted.

260 changes: 11 additions & 249 deletions web/src/client/network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,12 @@
*/

// @ts-check
//
// @import { AccessPoint, Device } from "~/types/network.ts";

import {
ConnectionState,
ConnectionTypes,
createAccessPoint,
createConnection,
DeviceState,
NetworkState,
securityFromFlags,
} from "./model";
import { formatIp, ipPrefixFor } from "./utils";
import { Connection, ConnectionState } from "~/types/network";
import { formatIp } from "~/utils/network";

const DeviceType = Object.freeze({
LOOPBACK: 0,
ETHERNET: 1,
WIRELESS: 2,
DUMMY: 3,
BOND: 4,
});

/**
* @typedef {import("./model").NetworkSettings} NetworkSettings
* @typedef {import("./model").Connection} Connection
* @typedef {import("./model").Connection} Device
* @typedef {import("./model").Connection} Route
* @typedef {import("./model").IPAddress} IPAddress
* @typedef {import("./model").AccessPoint} AccessPoint
*/

const NetworkEventTypes = Object.freeze({
DEVICE_ADDED: "deviceAdded",
Expand Down Expand Up @@ -99,130 +77,6 @@ class NetworkClient {
this.client = client;
}

/**
* Returns the devices running configuration
*
* @return {Promise<Device[]>}
*/
async devices() {
const response = await this.client.get("/network/devices");
if (!response.ok) {
return [];
}

const devices = await response.json();
return devices.map(this.fromApiDevice);
}

/**
* Returns the device settings
*
* @param {object} device - device settings from the API server
* @return {Device}
*/
fromApiDevice(device) {
const nameservers = device?.ipConfig?.nameservers || [];
const { ipConfig = {}, ...dev } = device;
const routes4 = (ipConfig.routes4 || []).map((route) => {
const [ip, netmask] = route.destination.split("/");
const destination =
netmask !== undefined ? { address: ip, prefix: ipPrefixFor(netmask) } : { address: ip };

return { ...route, destination };
});

const routes6 = (ipConfig.routes6 || []).map((route) => {
const [ip, netmask] = route.destination.split("/");
const destination =
netmask !== undefined ? { address: ip, prefix: ipPrefixFor(netmask) } : { address: ip };

return { ...route, destination };
});

const addresses = (ipConfig.addresses || []).map((address) => {
const [ip, netmask] = address.split("/");
if (netmask !== undefined) {
return { address: ip, prefix: ipPrefixFor(netmask) };
} else {
return { address: ip };
}
});

return { ...dev, ...ipConfig, addresses, nameservers, routes4, routes6 };
}

/**
* Returns the connection settings
*
* @return {Promise<Connection[]>}
*/
async connections() {
const response = await this.client.get("/network/connections");
if (!response.ok) {
console.error("Failed to get list of connections", response);
return [];
}

const connections = await response.json();
return connections.map(this.fromApiConnection);
}

fromApiConnection(connection) {
const nameservers = connection.nameservers || [];
const addresses = (connection.addresses || []).map((address) => {
const [ip, netmask] = address.split("/");
if (netmask !== undefined) {
return { address: ip, prefix: ipPrefixFor(netmask) };
} else {
return { address: ip };
}
});

return { ...connection, addresses, nameservers };
}

connectionType(connection) {
if (connection.wireless) return ConnectionTypes.WIFI;
if (connection.bond) return ConnectionTypes.BOND;
if (connection.vlan) return ConnectionTypes.VLAN;
if (connection.iface === "lo") return ConnectionTypes.LOOPBACK;

return ConnectionTypes.ETHERNET;
}

toApiConnection(connection) {
const addresses = (connection.addresses || []).map((addr) => formatIp(addr));
const { iface, gateway4, gateway6, ...conn } = connection;

if (gateway4?.trim() !== "") conn.gateway4 = gateway4;
if (gateway6?.trim() !== "") conn.gateway6 = gateway6;

return { ...conn, addresses, interface: iface };
}

/**
* Returns the list of available wireless access points (AP)
*
* @return {Promise<AccessPoint[]>}
*/
async accessPoints() {
const response = await this.client.get("/network/wifi");
if (!response.ok) {
console.error("Failed to get list of APs", response);
return [];
}
const access_points = await response.json();

return access_points.map((ap) => {
return createAccessPoint({
ssid: ap.ssid,
hwAddress: ap.hw_address,
strength: ap.strength,
security: securityFromFlags(ap.flags, ap.wpaFlags, ap.rsnFlags),
});
});
}

/**
* Connects to given Wireless network
*
Expand All @@ -241,113 +95,21 @@ class NetworkClient {
return this.client.get(`/network/connections/${connection.id}/disconnect`);
}

networkStateFor(state) {
switch (state) {
case DeviceState.CONFIG:
case DeviceState.IPCHECK:
// TRANSLATORS: Wifi network status
return NetworkState.CONNECTING;
case DeviceState.ACTIVATED:
// TRANSLATORS: Wifi network status
return NetworkState.CONNECTED;
case DeviceState.DEACTIVATING:
case DeviceState.FAILED:
case DeviceState.DISCONNECTED:
// TRANSLATORS: Wifi network status
return NetworkState.DISCONNECTED;
default:
return "";
}
}

loadNetworks(devices, connections, accessPoints) {
const knownSsids = [];

return accessPoints
.sort((a, b) => b.strength - a.strength)
.reduce(
(networks, ap) => {
// Do not include networks without SSID
if (!ap.ssid || ap.ssid === "") return networks;
// Do not include "duplicates"
if (knownSsids.includes(ap.ssid)) return networks;

const network = {
...ap,
settings: connections.find((c) => c.wireless?.ssid === ap.ssid),
device: devices.find((c) => c.connection === ap.ssid),
};

// Group networks
if (network.device) {
networks.connected.push(network);
} else if (network.settings) {
networks.configured.push(network);
} else {
networks.others.push(network);
}

knownSsids.push(network.ssid);

return networks;
},
{ connected: [], configured: [], others: [] },
);
}

/**
* Apply network changes
*/
async apply() {
return this.client.put("/network/system/apply", {});
}

/**
* Add the connection for the given Wireless network and activate it
*
* @param {string} ssid - Network id
* @param {object} options - connection options
*/
async addAndConnectTo(ssid, options) {
// duplicated code (see network manager adapter)
const wireless = { ssid, mode: "infrastructure" };
if (options.security) wireless.security = options.security;
if (options.password) wireless.password = options.password;
if (options.hidden) wireless.hidden = options.hidden;
if (options.mode) wireless.mode = options.mode;

const connection = createConnection({
id: ssid,
wireless,
});

const conn = await this.addConnection(connection);
await this.apply();

// the connection is automatically activated when written
return conn;
}
toApiConnection(connection) {
const addresses = (connection.addresses || []).map((addr) => formatIp(addr));
const { iface, gateway4, gateway6, ...conn } = connection;

/**
* Adds a new connection
*
* If a connection with the given ID already exists, it updates such a
* connection.
*
* @param {Connection} connection - Connection to add
* @return {Promise<Connection>} the added connection
*/
async addConnection(connection) {
const response = await this.client.post(
"/network/connections",
this.toApiConnection(connection),
);
if (!response.ok) {
console.error("Failed to post list of connections", response);
return null;
}
if (gateway4?.trim() !== "") conn.gateway4 = gateway4;
if (gateway6?.trim() !== "") conn.gateway6 = gateway6;

return response.json();
return { ...conn, addresses, interface: iface };
}

/**
Expand Down Expand Up @@ -439,4 +201,4 @@ class NetworkClient {
}
}

export { ConnectionState, ConnectionTypes, NetworkClient, NetworkEventTypes };
export { ConnectionState, NetworkClient, NetworkEventTypes };
Loading

0 comments on commit 9f88be2

Please sign in to comment.