aboutsummaryrefslogtreecommitdiff
path: root/assets/src/network/channel
diff options
context:
space:
mode:
authorMelonai <einebeere@gmail.com>2021-05-31 01:47:38 +0200
committerMelonai <einebeere@gmail.com>2021-05-31 01:47:38 +0200
commit8f1f90c3e7d836a23f1cd09617c2a0fcfac3f3f4 (patch)
tree7359e054d13a054a661c1584dae20d0698fc4c84 /assets/src/network/channel
parente0cabfea7c7b442acd3636e7495958b87e253176 (diff)
downloadrook-8f1f90c3e7d836a23f1cd09617c2a0fcfac3f3f4.tar.zst
rook-8f1f90c3e7d836a23f1cd09617c2a0fcfac3f3f4.zip
Socket connection with managed state
Diffstat (limited to 'assets/src/network/channel')
-rw-r--r--assets/src/network/channel/connection.ts69
-rw-r--r--assets/src/network/channel/request.ts14
-rw-r--r--assets/src/network/channel/share.ts17
-rw-r--r--assets/src/network/channel/socket.ts59
4 files changed, 159 insertions, 0 deletions
diff --git a/assets/src/network/channel/connection.ts b/assets/src/network/channel/connection.ts
new file mode 100644
index 0000000..52d85d1
--- /dev/null
+++ b/assets/src/network/channel/connection.ts
@@ -0,0 +1,69 @@
+import { Channel, Push, Socket } from "phoenix";
+import { startRequest } from "./request";
+import { startShare } from "./share";
+import { connectSocket, fetchToken } from "./socket";
+
+export enum Type {
+ NONE,
+ REQUEST,
+ SHARE,
+}
+
+enum ConnectionState {
+ CONNECTING_SOCKET,
+ FETCHING_TOKEN,
+ CONNECTING_CHANNEL,
+
+ CONNECTED,
+}
+
+export type Connection = {
+ socket: Socket;
+ channel: Channel | null;
+ token: string | null;
+ state: ConnectionState;
+ type: Type;
+};
+
+const connection: Connection = {
+ socket: new Socket("/socket", {}),
+ channel: null,
+ token: null,
+ state: ConnectionState.CONNECTING_SOCKET,
+ type: Type.NONE,
+};
+
+export async function start(type: Type.REQUEST | Type.SHARE) {
+ connection.type = type;
+
+ await connectSocket(connection.socket);
+
+ updateState(ConnectionState.FETCHING_TOKEN);
+ connection.token = await fetchToken(connection.socket);
+
+ updateState(ConnectionState.CONNECTING_CHANNEL);
+ type === Type.SHARE
+ ? await startShare(connection)
+ : await startRequest(connection);
+}
+
+export function send(event: string, data: any): Push {
+ if (connection.state !== ConnectionState.CONNECTED) {
+ throw new Error("There is no connection yet.");
+ }
+
+ return connection.channel.push(event, data);
+}
+
+export function getOwnToken(): string {
+ if (connection.state <= ConnectionState.FETCHING_TOKEN) {
+ throw new Error("There is no token yet.");
+ }
+
+ return connection.token;
+}
+
+function updateState(state: ConnectionState) {
+ // TODO: Notify state listeners
+ connection.state = state;
+}
diff --git a/assets/src/network/channel/request.ts b/assets/src/network/channel/request.ts
new file mode 100644
index 0000000..801eee1
--- /dev/null
+++ b/assets/src/network/channel/request.ts
@@ -0,0 +1,14 @@
+import getShareToken from "../../utils/getShareToken";
+import type { Connection } from "./connection";
+import { joinRequestChannel } from "./socket";
+
+export async function startRequest(connection: Connection) {
+ const requestChannel = await joinRequestChannel(
+ connection.socket,
+ connection.token,
+ getShareToken()
+ );
+ connection.channel = requestChannel;
+
+ // TODO: Handle incoming messages from the request channel
+}
diff --git a/assets/src/network/channel/share.ts b/assets/src/network/channel/share.ts
new file mode 100644
index 0000000..10a34fa
--- /dev/null
+++ b/assets/src/network/channel/share.ts
@@ -0,0 +1,17 @@
+import requests from "../../stores/requests";
+import type { Connection } from "./connection";
+import { joinShareChannel } from "./socket";
+
+export async function startShare(connection: Connection) {
+ const shareChannel = await joinShareChannel(
+ connection.socket,
+ connection.token
+ );
+ connection.channel = shareChannel;
+
+ shareChannel.on("new_request", onNewRequest);
+}
+
+function onNewRequest(data) {
+ requests.addRequest(data);
+}
diff --git a/assets/src/network/channel/socket.ts b/assets/src/network/channel/socket.ts
new file mode 100644
index 0000000..7d14842
--- /dev/null
+++ b/assets/src/network/channel/socket.ts
@@ -0,0 +1,59 @@
+import type { Channel, Socket } from "phoenix";
+
+export function connectSocket(socket: Socket): Promise<void> {
+ return new Promise((resolve, _reject) => {
+ socket.connect();
+ socket.onOpen(() => {
+ resolve();
+ });
+ });
+}
+
+export function fetchToken(socket: Socket): Promise<string> {
+ let tokenChannel = socket.channel("token", {});
+ return new Promise((resolve, reject) => {
+ tokenChannel
+ .join()
+ .receive("ok", () => {
+ tokenChannel
+ .push("get_token", {}, 5000)
+ .receive("ok", ({ token }) => resolve(token))
+ .receive("error", err => reject(err))
+ .receive("timeout", err => reject(err));
+ })
+ .receive("error", err => reject(err));
+ });
+}
+
+export function joinShareChannel(
+ socket: Socket,
+ token: string
+): Promise<Channel> {
+ return joinChannel(socket, `share:${token}`);
+}
+
+export function joinRequestChannel(
+ socket: Socket,
+ request_token: string,
+ share_token: string
+): Promise<Channel> {
+ return joinChannel(socket, `request:${request_token}`, {
+ share: share_token,
+ });
+}
+
+function joinChannel(
+ socket: Socket,
+ topic: string,
+ opts?: object
+): Promise<Channel> {
+ let channel = socket.channel(topic, opts);
+
+ return new Promise((resolve, reject) => {
+ channel
+ .join()
+ .receive("ok", () => resolve(channel))
+ .receive("error", err => reject(err))
+ .receive("timeout", err => reject(err));
+ });
+}