Skip to content

Commit

Permalink
fix: don't crash in some secure contexts
Browse files Browse the repository at this point in the history
This uses a weaker implementation to generate conneciton IDs if crypto.randomUUID() isn't available in the browser (re: WICG/uuid#23) Fixes #53
  • Loading branch information
threepointone committed Jan 29, 2023
1 parent a3b172f commit 0d9cc52
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 6 deletions.
8 changes: 8 additions & 0 deletions .changeset/slow-coins-divide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"partysocket": patch
"y-partykit": patch
---

fix: don't crash in some secure contexts

This uses a weaker implementation to generate conneciton IDs if crypto.randomUUID() isn't available in the browser (re: https://github.com/WICG/uuid/issues/23) Fixes https://github.com/partykit/partykit/issues/53
4 changes: 3 additions & 1 deletion packages/partykit/facade/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,7 @@ wss.on("connection", (ws: WebSocket, request: IncomingMessage) => {
ws.addEventListener("close", closeOrErrorListener);
ws.addEventListener("error", closeOrErrorListener);

Worker.onConnect(ws, partyRoom);
Worker.onConnect(ws, partyRoom)?.catch((err) => {
console.error("failed to connect", err);
});
});
4 changes: 2 additions & 2 deletions packages/partykit/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ export type PartyKitRoom = {
};

export type PartyKitServer<Initial = unknown> = {
onConnect: (ws: WebSocket, room: PartyKitRoom) => void;
onBeforeConnect?: (req: Request) => Promise<Initial>;
onConnect: (ws: WebSocket, room: PartyKitRoom) => void | Promise<void>;
onBeforeConnect?: (req: Request) => Initial | Promise<Initial>;
};
28 changes: 27 additions & 1 deletion packages/partysocket/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,32 @@ export type PartySocketOptions = Omit<
// headers
};

function generateUUID(): string {
// Public Domain/MIT
if (crypto.randomUUID) {
return crypto.randomUUID();
}
let d = new Date().getTime(); //Timestamp
let d2 =
(typeof performance !== "undefined" &&
performance.now &&
performance.now() * 1000) ||
0; //Time in microseconds since page-load or 0 if unsupported
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
let r = Math.random() * 16; //random number between 0 and 16
if (d > 0) {
//Use timestamp until depleted
r = (d + r) % 16 | 0;
d = Math.floor(d / 16);
} else {
//Use microseconds since page-load if supported
r = (d2 + r) % 16 | 0;
d2 = Math.floor(d2 / 16);
}
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
});
}

// things that nathanboktae/robust-websocket claims are better:
// doesn't do anything in offline mode (?)
// "natively aware of error codes"
Expand All @@ -25,7 +51,7 @@ export default class PartySocket extends ReconnectingWebSocket {
constructor(readonly partySocketOptions: PartySocketOptions) {
const { host, room, protocol, query, protocols, ...socketOptions } =
partySocketOptions;
const _pk = crypto.randomUUID();
const _pk = generateUUID();
let url = `${
protocol ||
(host.startsWith("localhost:") || host.startsWith("127.0.0.1:")
Expand Down
30 changes: 28 additions & 2 deletions packages/y-partykit/src/provider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
import { WebsocketProvider } from "y-websocket";
import type * as Y from "yjs";

function generateUUID(): string {
// Public Domain/MIT
if (crypto.randomUUID) {
return crypto.randomUUID();
}
let d = new Date().getTime(); //Timestamp
let d2 =
(typeof performance !== "undefined" &&
performance.now &&
performance.now() * 1000) ||
0; //Time in microseconds since page-load or 0 if unsupported
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
let r = Math.random() * 16; //random number between 0 and 16
if (d > 0) {
//Use timestamp until depleted
r = (d + r) % 16 | 0;
d = Math.floor(d / 16);
} else {
//Use microseconds since page-load if supported
r = (d2 + r) % 16 | 0;
d2 = Math.floor(d2 / 16);
}
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
});
}

export default class YPartyKitProvider extends WebsocketProvider {
constructor(
host: string,
Expand All @@ -15,10 +41,10 @@ export default class YPartyKitProvider extends WebsocketProvider {
}://${host}/party`;
if (options.params === undefined) {
options.params = {
_pk: crypto.randomUUID(),
_pk: generateUUID(),
};
} else {
options.params._pk = crypto.randomUUID();
options.params._pk = generateUUID();
}
super(serverUrl, room, doc, options);
}
Expand Down

0 comments on commit 0d9cc52

Please sign in to comment.