Skip to content

Commit

Permalink
Add @xmpp/events procedure to simplify code (#1041)
Browse files Browse the repository at this point in the history
  • Loading branch information
sonnyp authored Jan 1, 2025
1 parent 499b718 commit 16cec58
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 86 deletions.
4 changes: 4 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion packages/events/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,14 @@ import delay from "./lib/delay.js";
import TimeoutError from "./lib/TimeoutError.js";
import promise from "./lib/promise.js";
import Deferred from "./lib/Deferred.js";
import procedure from "./lib/procedure.js";

export { EventEmitter, timeout, delay, TimeoutError, promise, Deferred };
export {
EventEmitter,
timeout,
delay,
TimeoutError,
promise,
Deferred,
procedure,
};
24 changes: 24 additions & 0 deletions packages/events/lib/procedure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export default function procedure(entity, stanza = null, handler) {
return new Promise((resolve, reject) => {
function onError(err) {
entity.removeListener("nonza", listener);
reject(err);
}

function done(...args) {
entity.removeListener("nonza", listener);
resolve(...args);
}

async function listener(element) {
try {
await handler(element, done);
} catch (err) {
onError(err);
}
}

stanza && entity.send(stanza).catch(onError);
entity.on("nonza", listener);
});
}
42 changes: 18 additions & 24 deletions packages/sasl/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { encode, decode } from "@xmpp/base64";
import SASLError from "./lib/SASLError.js";
import xml from "@xmpp/xml";
import { procedure } from "@xmpp/events";

// https://xmpp.org/rfcs/rfc6120.html#sasl

Expand Down Expand Up @@ -28,16 +29,21 @@ async function authenticate({ saslFactory, entity, mechanism, credentials }) {
...credentials,
};

return new Promise((resolve, reject) => {
const handler = (element) => {
if (element.attrs.xmlns !== NS) {
return;
}
await procedure(
entity,
mech.clientFirst &&
xml(
"auth",
{ xmlns: NS, mechanism: mech.name },
encode(mech.response(creds)),
),
async (element, done) => {
if (element.getNS() !== NS) return;

if (element.name === "challenge") {
mech.challenge(decode(element.text()));
const resp = mech.response(creds);
entity.send(
await entity.send(
xml(
"response",
{ xmlns: NS, mechanism: mech.name },
Expand All @@ -48,26 +54,14 @@ async function authenticate({ saslFactory, entity, mechanism, credentials }) {
}

if (element.name === "failure") {
reject(SASLError.fromElement(element));
} else if (element.name === "success") {
resolve();
throw SASLError.fromElement(element);
}

entity.removeListener("nonza", handler);
};

entity.on("nonza", handler);

if (mech.clientFirst) {
entity.send(
xml(
"auth",
{ xmlns: NS, mechanism: mech.name },
encode(mech.response(creds)),
),
);
}
});
if (element.name === "success") {
return done();
}
},
);
}

export default function sasl({ streamFeatures, saslFactory }, onAuthenticate) {
Expand Down
1 change: 1 addition & 0 deletions packages/sasl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"dependencies": {
"@xmpp/base64": "^0.14.0",
"@xmpp/error": "^0.14.0",
"@xmpp/events": "^0.14.0",
"@xmpp/xml": "^0.14.0"
},
"engines": {
Expand Down
45 changes: 17 additions & 28 deletions packages/sasl2/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { encode, decode } from "@xmpp/base64";
import SASLError from "@xmpp/sasl/lib/SASLError.js";
import xml from "@xmpp/xml";
import { procedure } from "@xmpp/events";

// https://xmpp.org/extensions/xep-0388.html

Expand Down Expand Up @@ -36,16 +37,21 @@ async function authenticate({
...credentials,
};

return new Promise((resolve, reject) => {
const handler = (element) => {
if (element.getNS() !== NS) {
return;
}
await procedure(
entity,
xml("authenticate", { xmlns: NS, mechanism: mech.name }, [
mech.clientFirst &&
xml("initial-response", {}, encode(mech.response(creds))),
userAgent,
...streamFeatures,
]),
async (element, done) => {
if (element.getNS() !== NS) return;

if (element.name === "challenge") {
mech.challenge(decode(element.text()));
const resp = mech.response(creds);
entity.send(
await entity.send(
xml(
"response",
{ xmlns: NS, mechanism: mech.name },
Expand All @@ -56,13 +62,11 @@ async function authenticate({
}

if (element.name === "failure") {
reject(SASLError.fromElement(element));
return;
throw SASLError.fromElement(element);
}

if (element.name === "continue") {
reject(new Error("continue is not supported yet"));
return;
throw new Error("SASL continue is not supported yet");
}

if (element.name === "success") {
Expand All @@ -83,25 +87,10 @@ async function authenticate({
feature?.[1]?.(child);
}

resolve(element);
return done();
}

entity.removeListener("nonza", handler);
};

entity.on("nonza", handler);

entity
.send(
xml("authenticate", { xmlns: NS, mechanism: mech.name }, [
mech.clientFirst &&
xml("initial-response", {}, encode(mech.response(creds))),
userAgent,
...streamFeatures,
]),
)
.catch(reject);
});
},
);
}

export default function sasl2({ streamFeatures, saslFactory }, onAuthenticate) {
Expand Down
1 change: 1 addition & 0 deletions packages/sasl2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"dependencies": {
"@xmpp/base64": "^0.14.0",
"@xmpp/error": "^0.14.0",
"@xmpp/events": "^0.14.0",
"@xmpp/jid": "^0.14.0",
"@xmpp/sasl": "^0.14.0",
"@xmpp/xml": "^0.14.0"
Expand Down
38 changes: 15 additions & 23 deletions packages/stream-management/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import XMPPError from "@xmpp/error";
import { procedure } from "@xmpp/events";
import xml from "@xmpp/xml";

// https://xmpp.org/extensions/xep-0198.html
Expand All @@ -16,34 +18,24 @@ function makeResumeElement({ sm }) {
return xml("resume", { xmlns: NS, h: sm.inbound, previd: sm.id });
}

async function enable(entity, sm) {
await entity.send(makeEnableElement({ sm }));

return new Promise((resolve, reject) => {
function listener(nonza) {
if (nonza.is("enabled", NS)) {
resolve(nonza);
} else if (nonza.is("failed", NS)) {
reject(nonza);
} else {
return;
}

entity.removeListener("nonza", listener);
function enable(entity, sm) {
return procedure(entity, makeEnableElement({ sm }), (element, done) => {
if (element.is("enabled", NS)) {
return done(element);
} else if (element.is("failed", NS)) {
throw XMPPError.fromElement(element);
}

entity.on("nonza", listener);
});
}

async function resume(entity, sm) {
const response = await entity.sendReceive(makeResumeElement({ sm }));

if (!response.is("resumed", NS)) {
throw response;
}

return response;
return procedure(entity, makeResumeElement({ sm }), (element, done) => {
if (element.is("resumed", NS)) {
return done(element);
} else if (element.is("failed", NS)) {
throw XMPPError.fromElement(element);
}
});
}

export default function streamManagement({
Expand Down
2 changes: 2 additions & 0 deletions packages/stream-management/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"management"
],
"dependencies": {
"@xmpp/error": "^0.14.0",
"@xmpp/events": "^0.14.0",
"@xmpp/xml": "^0.14.0"
},
"engines": {
Expand Down
20 changes: 10 additions & 10 deletions packages/stream-management/stream-features.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ test("enable - enabled", async () => {
<enable xmlns="urn:xmpp:sm:3" resume="true" />,
);

await tick();

expect(entity.streamManagement.outbound).toBe(0);
expect(entity.streamManagement.enabled).toBe(false);
expect(entity.streamManagement.id).toBe("");
Expand Down Expand Up @@ -56,8 +54,6 @@ test("enable - send rejects", async () => {
/>,
);

await tick();

expect(entity.streamManagement.enabled).toBe(false);
});

Expand All @@ -80,8 +76,6 @@ test("enable - message - enabled", async () => {
expect(entity.streamManagement.enabled).toBe(false);
expect(entity.streamManagement.id).toBe("");

await tick();

entity.mockInput(<message />);

expect(entity.streamManagement.enabled).toBe(false);
Expand Down Expand Up @@ -120,9 +114,11 @@ test("enable - failed", async () => {
expect(entity.streamManagement.outbound).toBe(0);
entity.streamManagement.enabled = true;

await tick();

entity.mockInput(<failed xmlns="urn:xmpp:sm:3" />);
entity.mockInput(
<failed xmlns="urn:xmpp:sm:3">
<unexpected-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
</failed>,
);

await tick();

Expand Down Expand Up @@ -177,7 +173,11 @@ test("resume - failed", async () => {
<resume xmlns="urn:xmpp:sm:3" previd="bar" h="0" />,
);

entity.mockInput(<failed xmlns="urn:xmpp:sm:3" />);
entity.mockInput(
<failed xmlns="urn:xmpp:sm:3">
<unexpected-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
</failed>,
);

await tick();

Expand Down

0 comments on commit 16cec58

Please sign in to comment.