diff --git a/packages/api/index.ts b/packages/api/index.ts
index 08286c9..ede3878 100644
--- a/packages/api/index.ts
+++ b/packages/api/index.ts
@@ -1,7 +1,9 @@
import express, { Application, Request, Response } from "express";
import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients";
+import InitializeWs from "./sockets";
import { NextFunction } from "express";
+import NirvanaResponse from "@nirvana/core/responses/nirvanaResponse";
import ReceiveSignal from "../core/sockets/receiveSignal";
import SendSignal from "@nirvana/core/sockets/sendSignal";
import SocketChannels from "@nirvana/core/sockets/channels";
@@ -26,14 +28,16 @@ app.get("/", (req: Request, res: Response) => {
res.send("hello world.");
});
+app.use("/api", (req: Request, res: Response) => {
+ res.json(new NirvanaResponse("wohoo, server is healthy"));
+});
+
app.use("/api/user", getUserRoutes());
app.use("/api/search", getSearchRoutes());
app.use("/api/lines", getLineRoutes());
const PORT = 5000;
-var server = app.listen(PORT, () => console.log("express running"));
-
-// socket IO stuff
+const server = app.listen(PORT, () => console.log("express running"));
const io = require("socket.io")(server, {
// todo: add authentication
@@ -42,118 +46,4 @@ const io = require("socket.io")(server, {
},
});
-io.on("connection", function (socket: any) {
- // add to map between between googleUserIds and socketId
-
- console.log("a user connected");
-
- // ===== JOIN ====
- /** User wants to subscribe to live emissions of a conversation */
- socket.on(SocketChannels.JOIN_ROOM, (relationshipId: string) => {
- // add this user to the room
-
- console.log(
- `${socket.id} user joined room for relationship ${relationshipId}`
- );
-
- socket.join(relationshipId);
-
- console.log(`${socket.id} now in rooms ${socket.rooms}`);
- });
-
- // ==== UPDATES ====
- // can be a change of:
- // 1. status...later...do short polling for this instead
- // 2. new content: audio clip or link
- // 3. someone is starting to speak
- // send message to everyone in room except sender...
-
- /** User wants to send some update to a particular room */
- socket.on(
- SocketChannels.SEND_AUDIO_CLIP,
- (relationshipId: string, audioChunks: any) => {
- console.log(`new audio chunks received..routing to appropriate room!`);
- console.log(relationshipId);
- console.log(audioChunks);
-
- io.in(relationshipId).emit(
- SocketChannels.SEND_AUDIO_CLIP,
- relationshipId,
- audioChunks
- );
- }
- );
-
- // tell everyone in a room when someone is starting to speak
- socket.on(SocketChannels.SEND_STARTED_SPEAKING, (relationshipId: string) => {
- console.log(`started speaking in ${relationshipId}`);
- io.in(relationshipId).emit(
- SocketChannels.SEND_STARTED_SPEAKING,
- relationshipId
- );
- });
-
- // tell everyone in a room when someone is stopping to speak
- socket.on(SocketChannels.SEND_STOPPED_SPEAKING, (relationshipId: string) => {
- console.log(`stopped speaking in ${relationshipId}`);
- io.in(relationshipId).emit(
- SocketChannels.SEND_STOPPED_SPEAKING,
- relationshipId
- );
- });
-
- // change of user status to all of users' rooms and db update
- socket.on(
- SocketChannels.SEND_USER_STATUS_UPDATE,
- async (userGoogleId: string, newStatus: UserStatus) => {
- console.log("new status for user");
-
- const resultUpdate = await UserService.updateUserStatus(
- userGoogleId,
- newStatus
- );
-
- // tell all rooms that the user is part of
- // that this user has updated their status
- if (resultUpdate?.modifiedCount) {
- socket.rooms.forEach((roomId: string) => {
- io.in(roomId).emit(
- SocketChannels.SEND_USER_STATUS_UPDATE,
- userGoogleId,
- newStatus
- );
- });
- }
- }
- );
-
- socket.on(SocketChannels.JOIN_LIVE_ROOM, async () => {
- // TODO: only get the socket ids of the relevant rooms for this user
- // return all Socket instances
- const allConnectedSockets = Array.from(await io.of("/").sockets.keys());
-
- io.to(socket.id).emit(SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS, {
- socketIds: allConnectedSockets,
- } as GetAllSocketClients);
- });
-
- socket.on(SocketChannels.SEND_SIGNAL, async (payload: SendSignal) => {
- console.log(payload);
-
- const sendingBackData: ReceiveSignal = {
- simplePeerSignal: payload.simplePeerSignal,
- senderUserSocketId: socket.id,
- isGoingBackToInitiator: payload.isAnswerer ? true : false,
- };
-
- io.to(payload.userSocketIdToSignal).emit(
- SocketChannels.RECEIVE_SIGNAL,
- sendingBackData
- );
- });
-
- // ==== DISCONNECT ====
- socket.on("disconnect", () => {
- console.log("user disconnected");
- });
-});
+InitializeWs(io);
diff --git a/packages/api/sockets/index.ts b/packages/api/sockets/index.ts
new file mode 100644
index 0000000..3485a04
--- /dev/null
+++ b/packages/api/sockets/index.ts
@@ -0,0 +1,170 @@
+import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients";
+import { JwtClaims } from "../middleware/auth";
+import ReceiveSignal from "@nirvana/core/sockets/receiveSignal";
+import SendSignal from "@nirvana/core/sockets/sendSignal";
+import SocketChannels from "@nirvana/core/sockets/channels";
+import { UserService } from "../services/user.service";
+import { UserStatus } from "@nirvana/core/models/user.model";
+import { loadConfig } from "../config";
+
+const jwt = require("jsonwebtoken");
+
+const config = loadConfig();
+
+export default function InitializeWs(io: any) {
+ console.log("initializing web sockets");
+
+ return io
+ .use(function (socket: any, next: any) {
+ console.log("authenticating user...");
+
+ try {
+ const { token } = socket.handshake.query;
+
+ // verify jwt token with our api secret
+ var decoded: JwtClaims = jwt.verify(token, config.JWT_TOKEN_SECRET);
+
+ socket.userInfo = decoded;
+
+ next();
+ } catch (error) {
+ console.error(error);
+ next(new Error("WS Authentication Error"));
+ }
+ })
+ .on("connection", function (socket: any) {
+ const userInfo: JwtClaims = socket.userInfo;
+
+ console.log(
+ `a user connected | user Id: ${userInfo.userId} and name: ${userInfo.name}`
+ );
+
+ socket.on("test", () => {
+ console.log("asdf");
+ });
+
+ // ?verification that user is in a particular line to be tuned into it or just generally in it?
+
+ // regular socket rooms for information for all clients in a specific line
+
+ // another namespace or so for clients tuned into certain lines
+
+ // ===== JOIN ====
+ /** User wants to subscribe to live emissions of a conversation */
+ socket.on(SocketChannels.JOIN_ROOM, (relationshipId: string) => {
+ // add this user to the room
+
+ console.log(
+ `${socket.id} user joined room for relationship ${relationshipId}`
+ );
+
+ socket.join(relationshipId);
+
+ console.log(`${socket.id} now in rooms ${socket.rooms}`);
+ });
+
+ // ==== UPDATES ====
+ // can be a change of:
+ // 1. status...later...do short polling for this instead
+ // 2. new content: audio clip or link
+ // 3. someone is starting to speak
+ // send message to everyone in room except sender...
+
+ /** User wants to send some update to a particular room */
+ socket.on(
+ SocketChannels.SEND_AUDIO_CLIP,
+ (relationshipId: string, audioChunks: any) => {
+ console.log(
+ `new audio chunks received..routing to appropriate room!`
+ );
+ console.log(relationshipId);
+ console.log(audioChunks);
+
+ io.in(relationshipId).emit(
+ SocketChannels.SEND_AUDIO_CLIP,
+ relationshipId,
+ audioChunks
+ );
+ }
+ );
+
+ // tell everyone in a room when someone is starting to speak
+ socket.on(
+ SocketChannels.SEND_STARTED_SPEAKING,
+ (relationshipId: string) => {
+ console.log(`started speaking in ${relationshipId}`);
+ io.in(relationshipId).emit(
+ SocketChannels.SEND_STARTED_SPEAKING,
+ relationshipId
+ );
+ }
+ );
+
+ // tell everyone in a room when someone is stopping to speak
+ socket.on(
+ SocketChannels.SEND_STOPPED_SPEAKING,
+ (relationshipId: string) => {
+ console.log(`stopped speaking in ${relationshipId}`);
+ io.in(relationshipId).emit(
+ SocketChannels.SEND_STOPPED_SPEAKING,
+ relationshipId
+ );
+ }
+ );
+
+ // change of user status to all of users' rooms and db update
+ socket.on(
+ SocketChannels.SEND_USER_STATUS_UPDATE,
+ async (userGoogleId: string, newStatus: UserStatus) => {
+ console.log("new status for user");
+
+ const resultUpdate = await UserService.updateUserStatus(
+ userGoogleId,
+ newStatus
+ );
+
+ // tell all rooms that the user is part of
+ // that this user has updated their status
+ if (resultUpdate?.modifiedCount) {
+ socket.rooms.forEach((roomId: string) => {
+ io.in(roomId).emit(
+ SocketChannels.SEND_USER_STATUS_UPDATE,
+ userGoogleId,
+ newStatus
+ );
+ });
+ }
+ }
+ );
+
+ socket.on(SocketChannels.JOIN_LIVE_ROOM, async () => {
+ // TODO: only get the socket ids of the relevant rooms for this user
+ // return all Socket instances
+ const allConnectedSockets = Array.from(await io.of("/").sockets.keys());
+
+ io.to(socket.id).emit(SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS, {
+ socketIds: allConnectedSockets,
+ } as GetAllSocketClients);
+ });
+
+ socket.on(SocketChannels.SEND_SIGNAL, async (payload: SendSignal) => {
+ console.log(payload);
+
+ const sendingBackData: ReceiveSignal = {
+ simplePeerSignal: payload.simplePeerSignal,
+ senderUserSocketId: socket.id,
+ isGoingBackToInitiator: payload.isAnswerer ? true : false,
+ };
+
+ io.to(payload.userSocketIdToSignal).emit(
+ SocketChannels.RECEIVE_SIGNAL,
+ sendingBackData
+ );
+ });
+
+ // ==== DISCONNECT ====
+ socket.on("disconnect", () => {
+ console.log("user disconnected");
+ });
+ });
+}
diff --git a/packages/desktop/src/components/ProtectedRoute/index.tsx b/packages/desktop/src/components/ProtectedRoute/index.tsx
index f7019f2..d3b0633 100644
--- a/packages/desktop/src/components/ProtectedRoute/index.tsx
+++ b/packages/desktop/src/components/ProtectedRoute/index.tsx
@@ -1,9 +1,10 @@
+import { useAuthCheck, useServerCheck } from "../../controller/index";
+
import { $jwtToken } from "../../controller/recoil";
import Login from "../../pages/Login";
import NirvanaApi from "../../controller/nirvanaApi";
import { STORE_ITEMS } from "../../electron/constants";
import SkeletonLoader from "../loading/skeleton";
-import { useAuthCheck } from "../../controller/index";
import { useEffect } from "react";
import { useRecoilState } from "recoil";
@@ -14,7 +15,17 @@ export default function ProtectedRoute({
}) {
const [jwtToken, setJwtToken] = useRecoilState($jwtToken);
- const { isLoading, isError, isFetching, isSuccess, refetch } = useAuthCheck();
+ const {
+ isError: serverFailure,
+ isLoading: serverLoading,
+ isSuccess: isServerHealthy,
+ error,
+ } = useServerCheck();
+
+ console.log(error);
+
+ const { isLoading, isError, isFetching, isSuccess, refetch } =
+ useAuthCheck(isServerHealthy);
useEffect(() => {
// on load of this, if we already have jwt tokens in store,
@@ -49,6 +60,15 @@ export default function ProtectedRoute({
refetch();
}, [jwtToken]);
+ if (serverLoading)
+ return (
+
+ Sorry...this is our bad. Our servers are loading. We are trying our best
+ to back up and running! :)
Please contact me for urgent concerns:
+ arjunpatel@berkeley.edu
+
+ );
+
if (isLoading) {
return (