metacubexd/src/signals/connections.ts

108 lines
2.8 KiB
TypeScript
Raw Normal View History

2023-09-08 13:39:51 +08:00
import { differenceWith, isNumber, unionWith } from 'lodash'
import { Accessor, createEffect, createSignal, untrack } from 'solid-js'
2023-09-08 13:39:51 +08:00
import { Connection, ConnectionRawMessage } from '~/types'
import { selectedEndpoint, useWsRequest } from './request'
type WsMsg = {
2023-09-08 13:39:51 +08:00
connections: ConnectionRawMessage[]
uploadTotal: number
downloadTotal: number
} | null
2023-09-08 11:55:22 +08:00
// we make connections global, so we can keep track of connections when user in proxy page
// when user selects proxy and close some connections they can back and check connections
// they closed
2023-09-08 13:39:51 +08:00
const [allConnections, setAllConnections] = createSignal<Connection[]>([])
2023-09-08 13:39:51 +08:00
export let latestConnectionMsg: Accessor<WsMsg> = () => ({
uploadTotal: 0,
downloadTotal: 0,
connections: [],
})
createEffect(() => {
if (selectedEndpoint()) {
2023-09-08 13:39:51 +08:00
setAllConnections([])
latestConnectionMsg = useWsRequest<WsMsg>('connections')
}
})
export const useConnections = () => {
2023-09-08 13:39:51 +08:00
const [closedConnections, setClosedConnections] = createSignal<Connection[]>(
[],
)
const [activeConnections, setActiveConnections] = createSignal<Connection[]>(
[],
)
const [paused, setPaused] = createSignal(false)
createEffect(() => {
2023-09-08 13:39:51 +08:00
const rawConns = latestConnectionMsg()?.connections
2023-09-08 13:39:51 +08:00
if (!rawConns) {
return
}
untrack(() => {
2023-09-08 13:39:51 +08:00
const activeConns = restructRawMsgToConnection(
rawConns,
activeConnections(),
)
const allConns = mergeAllConnections(activeConns)
if (!paused()) {
2023-09-08 13:39:51 +08:00
const closedConns = diffClosedConnections(activeConns, allConns)
setActiveConnections(activeConns.slice(-200))
setClosedConnections(closedConns.slice(-200))
}
setAllConnections(allConns.slice(-400))
})
})
return {
2023-09-08 13:39:51 +08:00
closedConnections,
activeConnections,
paused,
setPaused,
}
}
2023-09-08 13:39:51 +08:00
export function restructRawMsgToConnection(
2023-09-08 13:39:51 +08:00
connections: ConnectionRawMessage[],
prevActiveConnections: Connection[],
): Connection[] {
const prevMap = new Map<string, Connection>()
prevActiveConnections.forEach((prev) => prevMap.set(prev.id, prev))
return connections.map((connection) => {
const prevConn = prevMap.get(connection.id)
if (
!prevConn ||
!isNumber(prevConn.download) ||
!isNumber(prevConn.upload)
) {
return { ...connection, downloadSpeed: 0, uploadSpeed: 0 }
}
return {
...connection,
downloadSpeed: connection.download - prevConn.download,
uploadSpeed: connection.upload - prevConn.upload,
}
})
}
export function mergeAllConnections(activeConns: Connection[]) {
2023-09-08 13:39:51 +08:00
return unionWith(allConnections(), activeConns, (a, b) => a.id === b.id)
}
function diffClosedConnections(
activeConns: Connection[],
allConns: Connection[],
) {
return differenceWith(allConns, activeConns, (a, b) => a.id === b.id)
}