@efffrida/rpc 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/frida/FridaRpcClient.d.ts +48 -0
  2. package/dist/frida/FridaRpcClient.d.ts.map +1 -0
  3. package/dist/frida/FridaRpcClient.js +116 -0
  4. package/dist/frida/FridaRpcClient.js.map +1 -0
  5. package/dist/frida/FridaRpcServer.d.ts +49 -0
  6. package/dist/frida/FridaRpcServer.d.ts.map +1 -0
  7. package/dist/frida/FridaRpcServer.js +121 -0
  8. package/dist/frida/FridaRpcServer.js.map +1 -0
  9. package/dist/frida/index.d.ts +18 -0
  10. package/dist/frida/index.d.ts.map +1 -0
  11. package/dist/{esm → frida}/index.js +5 -4
  12. package/dist/frida/index.js.map +1 -0
  13. package/dist/{dts → node}/FridaRpcClient.d.ts +16 -6
  14. package/dist/node/FridaRpcClient.d.ts.map +1 -0
  15. package/dist/node/FridaRpcClient.js +83 -0
  16. package/dist/node/FridaRpcClient.js.map +1 -0
  17. package/dist/node/FridaRpcServer.d.ts +16 -0
  18. package/dist/node/FridaRpcServer.d.ts.map +1 -0
  19. package/dist/node/FridaRpcServer.js +115 -0
  20. package/dist/node/FridaRpcServer.js.map +1 -0
  21. package/dist/node/index.d.ts +18 -0
  22. package/dist/node/index.d.ts.map +1 -0
  23. package/dist/{dts/index.d.ts → node/index.js} +6 -5
  24. package/dist/node/index.js.map +1 -0
  25. package/dist/shared/constants.d.ts +6 -0
  26. package/dist/shared/constants.d.ts.map +1 -0
  27. package/dist/shared/constants.js +7 -0
  28. package/dist/shared/constants.js.map +1 -0
  29. package/dist/shared/predicates.d.ts +10 -0
  30. package/dist/shared/predicates.d.ts.map +1 -0
  31. package/dist/shared/predicates.js +12 -0
  32. package/dist/shared/predicates.js.map +1 -0
  33. package/package.json +61 -45
  34. package/src/frida/FridaRpcClient.ts +182 -0
  35. package/src/frida/FridaRpcServer.ts +172 -0
  36. package/src/frida/index.ts +19 -0
  37. package/src/node/FridaRpcClient.ts +141 -0
  38. package/src/node/FridaRpcServer.ts +134 -0
  39. package/src/node/index.ts +19 -0
  40. package/src/shared/constants.ts +11 -0
  41. package/src/shared/predicates.ts +19 -0
  42. package/FridaRpcClient/package.json +0 -6
  43. package/FridaRpcServer/package.json +0 -6
  44. package/dist/cjs/FridaRpcClient.js +0 -77
  45. package/dist/cjs/FridaRpcClient.js.map +0 -1
  46. package/dist/cjs/FridaRpcServer.js +0 -135
  47. package/dist/cjs/FridaRpcServer.js.map +0 -1
  48. package/dist/cjs/index.js +0 -12
  49. package/dist/cjs/index.js.map +0 -1
  50. package/dist/dts/FridaRpcClient.d.ts.map +0 -1
  51. package/dist/dts/FridaRpcServer.d.ts +0 -36
  52. package/dist/dts/FridaRpcServer.d.ts.map +0 -1
  53. package/dist/dts/index.d.ts.map +0 -1
  54. package/dist/esm/FridaRpcClient.js +0 -67
  55. package/dist/esm/FridaRpcClient.js.map +0 -1
  56. package/dist/esm/FridaRpcServer.js +0 -125
  57. package/dist/esm/FridaRpcServer.js.map +0 -1
  58. package/dist/esm/index.js.map +0 -1
  59. package/dist/esm/package.json +0 -4
  60. package/index/package.json +0 -6
  61. package/src/FridaRpcClient.ts +0 -107
  62. package/src/FridaRpcServer.ts +0 -172
  63. package/src/index.ts +0 -17
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Implements a Frida RPC client protocol for effect using the frida script
3
+ * exports.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+ import "@efffrida/polyfills";
8
+ import type * as Duration from "effect/Duration";
9
+ import type * as Scope from "effect/Scope";
10
+ import * as RpcClient from "@effect/rpc/RpcClient";
11
+ import * as RpcSerialization from "@effect/rpc/RpcSerialization";
12
+ import * as Effect from "effect/Effect";
13
+ import * as Layer from "effect/Layer";
14
+ /**
15
+ * @since 1.0.0
16
+ * @category Protocol
17
+ */
18
+ export declare const makeProtocolFrida: (options?: {
19
+ readonly generateExportName?: (() => string) | undefined;
20
+ readonly receivingStreamShareOptions?: {
21
+ readonly capacity: "unbounded";
22
+ readonly replay?: number | undefined;
23
+ readonly idleTimeToLive?: Duration.DurationInput | undefined;
24
+ } | {
25
+ readonly capacity: number;
26
+ readonly strategy?: "sliding" | "dropping" | "suspend" | undefined;
27
+ readonly replay?: number | undefined;
28
+ readonly idleTimeToLive?: Duration.DurationInput | undefined;
29
+ } | undefined;
30
+ } | undefined) => Effect.Effect<RpcClient.Protocol["Type"], never, RpcSerialization.RpcSerialization | Scope.Scope>;
31
+ /**
32
+ * @since 1.0.0
33
+ * @category Layers
34
+ */
35
+ export declare const layerProtocolFrida: (options?: {
36
+ readonly generateExportName?: (() => string) | undefined;
37
+ readonly receivingStreamShareOptions?: {
38
+ readonly capacity: "unbounded";
39
+ readonly replay?: number | undefined;
40
+ readonly idleTimeToLive?: Duration.DurationInput | undefined;
41
+ } | {
42
+ readonly capacity: number;
43
+ readonly strategy?: "sliding" | "dropping" | "suspend" | undefined;
44
+ readonly replay?: number | undefined;
45
+ readonly idleTimeToLive?: Duration.DurationInput | undefined;
46
+ } | undefined;
47
+ } | undefined) => Layer.Layer<RpcClient.Protocol, never, RpcSerialization.RpcSerialization>;
48
+ //# sourceMappingURL=FridaRpcClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FridaRpcClient.d.ts","sourceRoot":"","sources":["../../src/frida/FridaRpcClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,qBAAqB,CAAC;AAG7B,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AAIjE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAUtC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC1B,UACM;IACI,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;IACzD,QAAQ,CAAC,2BAA2B,CAAC,EAC/B;QACI,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC;KAChE,GACD;QACI,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;QACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC;KAChE,GACD,SAAS,CAAC;CACnB,GACD,SAAS,KAChB,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAsG9F,CAAC;AAEN;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC3B,UACM;IACI,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;IACzD,QAAQ,CAAC,2BAA2B,CAAC,EAC/B;QACI,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC;KAChE,GACD;QACI,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;QACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC;KAChE,GACD,SAAS,CAAC;CACnB,GACD,SAAS,KAChB,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,gBAAgB,CAAC,gBAAgB,CACX,CAAC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Implements a Frida RPC client protocol for effect using the frida script
3
+ * exports.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+ import "@efffrida/polyfills";
8
+ import * as RpcClient from "@effect/rpc/RpcClient";
9
+ import * as RpcSerialization from "@effect/rpc/RpcSerialization";
10
+ import * as FridaStream from "@efffrida/platform/Stream";
11
+ import * as Cause from "effect/Cause";
12
+ import * as Deferred from "effect/Deferred";
13
+ import * as Effect from "effect/Effect";
14
+ import * as Function from "effect/Function";
15
+ import * as Layer from "effect/Layer";
16
+ import * as Option from "effect/Option";
17
+ import * as ParseResult from "effect/ParseResult";
18
+ import * as Predicate from "effect/Predicate";
19
+ import * as Schema from "effect/Schema";
20
+ import * as Stream from "effect/Stream";
21
+ import * as constants from "../shared/constants.js";
22
+ import * as sharedPredicates from "../shared/predicates.js";
23
+ /**
24
+ * @since 1.0.0
25
+ * @category Protocol
26
+ */
27
+ export const makeProtocolFrida = options => RpcClient.Protocol.make(Effect.fnUntraced(function* (writeResponse) {
28
+ const serialization = yield* RpcSerialization.RpcSerialization;
29
+ const encoder = new TextEncoder();
30
+ const parser = serialization.unsafeMake();
31
+ /**
32
+ * Once the server has acknowledged our initiation request and sent
33
+ * use a client id to identify ourselves, this deferred will
34
+ * complete.
35
+ */
36
+ const clientIdDeferred = yield* Deferred.make();
37
+ /**
38
+ * Setup the receiving handler for the client id. We receive the
39
+ * client id over a script export instead of over the receiving
40
+ * stream since there could be multiple clients in this frida script
41
+ * and multiple could request client ids at the same time. This
42
+ * could be mitigated with a nonce of some kind in the request
43
+ * message, but receiving over a script export is full-proof so long
44
+ * as the exports are unique.
45
+ */
46
+ const exportName = options?.generateExportName?.() ?? constants.generateClientCallbackExportNameForServer();
47
+ yield* Effect.addFinalizer(() => Effect.sync(() => delete rpc.exports[exportName]));
48
+ rpc.exports[exportName] = maybeIncomingClientId => {
49
+ const parsedClientId = Schema.decodeUnknown(Schema.Number)(maybeIncomingClientId);
50
+ Deferred.unsafeDone(clientIdDeferred, parsedClientId);
51
+ };
52
+ /**
53
+ * Request a client id from the node side and wait for the response,
54
+ * handling any transient errors that might occur by retrying with
55
+ * the retry policy.
56
+ */
57
+ const connectionRequest = constants.nodeRpcClientMakeConnectionRequestForServer(exportName);
58
+ const connectionRequestTimeout = "1 second";
59
+ const clientId = yield* Effect.sync(() => send(connectionRequest)).pipe(Effect.flatMap(() => Deferred.await(clientIdDeferred)), Effect.timeout(connectionRequestTimeout), Effect.catchIf(ParseResult.isParseError, () => Effect.dieMessage("Failed to parse client ID")), Effect.catchIf(Cause.isTimeoutException, () => Effect.dieMessage("Timed out too many times")));
60
+ /**
61
+ * Attach to the receiving stream, where all future messages will
62
+ * come in at, and filter for only our messages.
63
+ */
64
+ const receivingPredicate = sharedPredicates.isTaggedForClient(clientId);
65
+ const receiveStream = yield* FridaStream.receiveStream(options?.receivingStreamShareOptions ?? {
66
+ replay: 100,
67
+ capacity: "unbounded"
68
+ });
69
+ /**
70
+ * For every response message received, decode it and send it the
71
+ * response back to the implementation.
72
+ */
73
+ yield* receiveStream.pipe(Stream.filterMap(unfiltered => {
74
+ if (receivingPredicate(unfiltered.message)) return Option.fromNullable(unfiltered.data);else return Option.none();
75
+ }), Stream.runForEach(filtered => {
76
+ try {
77
+ const responses = parser.decode(filtered);
78
+ if (responses.length === 0) return Effect.void;
79
+ let i = 0;
80
+ return Effect.whileLoop({
81
+ while: () => i < responses.length,
82
+ body: () => writeResponse(responses[i++]),
83
+ step: Function.constVoid
84
+ });
85
+ } catch (defect) {
86
+ return writeResponse({
87
+ _tag: "Defect",
88
+ defect
89
+ });
90
+ }
91
+ }), Effect.interruptible, Effect.forkScoped);
92
+ /**
93
+ * Sending messages is as simple as encoding them, then sending them
94
+ * to the node side tagged with our client id so it knows where to
95
+ * send them back to.
96
+ */
97
+ const sendHelper = Effect.fnUntraced(function* (message) {
98
+ const encoded = parser.encode(message);
99
+ if (Predicate.isUndefined(encoded)) return;
100
+ const transformed = typeof encoded === "string" ? encoder.encode(encoded) : encoded;
101
+ send({
102
+ clientId
103
+ }, transformed.buffer);
104
+ });
105
+ return {
106
+ send: sendHelper,
107
+ supportsAck: true,
108
+ supportsTransferables: false
109
+ };
110
+ }));
111
+ /**
112
+ * @since 1.0.0
113
+ * @category Layers
114
+ */
115
+ export const layerProtocolFrida = options => Layer.scoped(RpcClient.Protocol, makeProtocolFrida(options));
116
+ //# sourceMappingURL=FridaRpcClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FridaRpcClient.js","names":["RpcClient","RpcSerialization","FridaStream","Cause","Deferred","Effect","Function","Layer","Option","ParseResult","Predicate","Schema","Stream","constants","sharedPredicates","makeProtocolFrida","options","Protocol","make","fnUntraced","writeResponse","serialization","encoder","TextEncoder","parser","unsafeMake","clientIdDeferred","exportName","generateExportName","generateClientCallbackExportNameForServer","addFinalizer","sync","rpc","exports","maybeIncomingClientId","parsedClientId","decodeUnknown","Number","unsafeDone","connectionRequest","nodeRpcClientMakeConnectionRequestForServer","connectionRequestTimeout","clientId","send","pipe","flatMap","await","timeout","catchIf","isParseError","dieMessage","isTimeoutException","receivingPredicate","isTaggedForClient","receiveStream","receivingStreamShareOptions","replay","capacity","filterMap","unfiltered","message","fromNullable","data","none","runForEach","filtered","responses","decode","length","void","i","whileLoop","while","body","step","constVoid","defect","_tag","interruptible","forkScoped","sendHelper","encoded","encode","isUndefined","transformed","buffer","supportsAck","supportsTransferables","layerProtocolFrida","scoped"],"sources":["../../src/frida/FridaRpcClient.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Implements a Frida RPC server protocol for effect using the frida script
3
+ * exports.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+ import "@efffrida/polyfills";
8
+ import * as RpcSerialization from "@effect/rpc/RpcSerialization";
9
+ import * as RpcServer from "@effect/rpc/RpcServer";
10
+ import * as Effect from "effect/Effect";
11
+ import * as Layer from "effect/Layer";
12
+ /**
13
+ * @since 1.0.0
14
+ * @category Protocol
15
+ */
16
+ export declare const makeProtocolFrida: (options?: {
17
+ /** Generates server listener rpc exports for individual clients. */
18
+ readonly generateExportName?: ((clientId: number) => string) | undefined;
19
+ } | undefined) => Effect.Effect<{
20
+ readonly protocol: RpcServer.Protocol["Type"];
21
+ readonly rpcExport: () => Promise<number>;
22
+ }, never, RpcSerialization.RpcSerialization>;
23
+ /**
24
+ * @since 1.0.0
25
+ * @category Protocol
26
+ */
27
+ export declare const makeProtocolFridaWithExport: (options?: {
28
+ /**
29
+ * Name for the main rpc export that all clients start by
30
+ * connecting to.
31
+ */
32
+ readonly exportName?: string | undefined;
33
+ /** Generates server listener rpc exports for individual clients. */
34
+ readonly generateExportName?: ((clientId: number) => string) | undefined;
35
+ } | undefined) => Effect.Effect<RpcServer.Protocol["Type"], never, RpcSerialization.RpcSerialization>;
36
+ /**
37
+ * @since 1.0.0
38
+ * @category Layer
39
+ */
40
+ export declare const layerProtocolFrida: (options?: {
41
+ /**
42
+ * Name for the main rpc export that all clients start by
43
+ * connecting to.
44
+ */
45
+ readonly exportName?: string | undefined;
46
+ /** Generates server listener rpc exports for individual clients. */
47
+ readonly generateExportName?: ((clientId: number) => string) | undefined;
48
+ } | undefined) => Layer.Layer<RpcServer.Protocol, never, RpcSerialization.RpcSerialization>;
49
+ //# sourceMappingURL=FridaRpcServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FridaRpcServer.d.ts","sourceRoot":"","sources":["../../src/frida/FridaRpcServer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,qBAAqB,CAAC;AAG7B,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAMtC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC1B,UACM;IACI,oEAAoE;IACpE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;CAC5E,GACD,SAAS,KAChB,MAAM,CAAC,MAAM,CACZ;IACI,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7C,EACD,KAAK,EACL,gBAAgB,CAAC,gBAAgB,CA0F/B,CAAC;AAEP;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GACpC,UACM;IACI;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzC,oEAAoE;IACpE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;CAC5E,GACD,SAAS,KAChB,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,gBAAgB,CAK/E,CAAC;AAEP;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC3B,UACM;IACI;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzC,oEAAoE;IACpE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;CAC5E,GACD,SAAS,KAChB,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,gBAAgB,CAAC,gBAAgB,CACD,CAAC"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Implements a Frida RPC server protocol for effect using the frida script
3
+ * exports.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+ import "@efffrida/polyfills";
8
+ import * as RpcMessage from "@effect/rpc/RpcMessage";
9
+ import * as RpcSerialization from "@effect/rpc/RpcSerialization";
10
+ import * as RpcServer from "@effect/rpc/RpcServer";
11
+ import * as Effect from "effect/Effect";
12
+ import * as Function from "effect/Function";
13
+ import * as Layer from "effect/Layer";
14
+ import * as Mailbox from "effect/Mailbox";
15
+ import * as Predicate from "effect/Predicate";
16
+ import * as constants from "../shared/constants.js";
17
+ /**
18
+ * @since 1.0.0
19
+ * @category Protocol
20
+ */
21
+ export const makeProtocolFrida = options => Effect.gen(function* () {
22
+ const encoder = new TextEncoder();
23
+ const disconnects = yield* Mailbox.make();
24
+ const serialization = yield* RpcSerialization.RpcSerialization;
25
+ let clientId = 0;
26
+ const clientIds = new Set();
27
+ const clients = new Map();
28
+ let writeRequest;
29
+ const makeExportName = options?.generateExportName ?? constants.generateServerExportNameForClient;
30
+ // Listen for new clients on the main rpc export
31
+ const rpcExport = Effect.gen(function* () {
32
+ const id = ++clientId;
33
+ const parser = serialization.unsafeMake();
34
+ const writeRaw = data => {
35
+ const transformed = typeof data === "string" ? encoder.encode(data) : data;
36
+ return send({
37
+ clientId: id
38
+ }, transformed.buffer);
39
+ };
40
+ const write = response => {
41
+ try {
42
+ const encoded = parser.encode(response);
43
+ if (Predicate.isNotUndefined(encoded)) return writeRaw(encoded);
44
+ } catch (cause) {
45
+ const encoded = parser.encode(RpcMessage.ResponseDefectEncoded(cause));
46
+ return writeRaw(encoded);
47
+ }
48
+ };
49
+ clientIds.add(id);
50
+ clients.set(id, {
51
+ write
52
+ });
53
+ const onMessage = input => {
54
+ const data = typeof input === "string" ? input : Uint8Array.from(Object.values(input));
55
+ try {
56
+ const decoded = parser.decode(data);
57
+ if (decoded.length === 0) return Effect.void;
58
+ let i = 0;
59
+ return Effect.whileLoop({
60
+ while: () => i < decoded.length,
61
+ body() {
62
+ const message = decoded[i++];
63
+ return writeRequest(id, message);
64
+ },
65
+ step: Function.constVoid
66
+ });
67
+ } catch (cause) {
68
+ return Effect.sync(() => writeRaw(parser.encode(RpcMessage.ResponseDefectEncoded(cause))));
69
+ }
70
+ };
71
+ rpc.exports[makeExportName(id)] = data => Effect.runPromise(onMessage(data));
72
+ return id;
73
+ });
74
+ const protocol = yield* RpcServer.Protocol.make(writeRequest_ => {
75
+ writeRequest = writeRequest_;
76
+ return Effect.succeed({
77
+ disconnects,
78
+ send: (clientId, response) => {
79
+ const client = clients.get(clientId);
80
+ if (!client) return Effect.void;
81
+ return Effect.sync(() => client.write(response));
82
+ },
83
+ end(clientId) {
84
+ clientIds.delete(clientId); // TODO: Is this required?
85
+ clients.delete(clientId); // TODO: Is this required?
86
+ const makeExportName = options?.generateExportName ?? constants.generateServerExportNameForClient;
87
+ delete rpc.exports[makeExportName(clientId)];
88
+ return Effect.void;
89
+ },
90
+ clientIds: Effect.sync(() => clientIds),
91
+ initialMessage: Effect.succeedNone,
92
+ supportsAck: true,
93
+ supportsTransferables: false,
94
+ supportsSpanPropagation: true
95
+ });
96
+ });
97
+ return {
98
+ protocol,
99
+ rpcExport: () => Effect.runPromise(rpcExport)
100
+ };
101
+ });
102
+ /**
103
+ * @since 1.0.0
104
+ * @category Protocol
105
+ */
106
+ export const makeProtocolFridaWithExport = options => Effect.gen(function* () {
107
+ const {
108
+ protocol,
109
+ rpcExport
110
+ } = yield* makeProtocolFrida({
111
+ generateExportName: options?.generateExportName
112
+ });
113
+ rpc.exports[options?.exportName ?? constants.defaultServerMainExportName] = rpcExport;
114
+ return protocol;
115
+ });
116
+ /**
117
+ * @since 1.0.0
118
+ * @category Layer
119
+ */
120
+ export const layerProtocolFrida = options => Layer.effect(RpcServer.Protocol, makeProtocolFridaWithExport(options));
121
+ //# sourceMappingURL=FridaRpcServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FridaRpcServer.js","names":["RpcMessage","RpcSerialization","RpcServer","Effect","Function","Layer","Mailbox","Predicate","constants","makeProtocolFrida","options","gen","encoder","TextEncoder","disconnects","make","serialization","clientId","clientIds","Set","clients","Map","writeRequest","makeExportName","generateExportName","generateServerExportNameForClient","rpcExport","id","parser","unsafeMake","writeRaw","data","transformed","encode","send","buffer","write","response","encoded","isNotUndefined","cause","ResponseDefectEncoded","add","set","onMessage","input","Uint8Array","from","Object","values","decoded","decode","length","void","i","whileLoop","while","body","message","step","constVoid","sync","rpc","exports","runPromise","protocol","Protocol","writeRequest_","succeed","client","get","end","delete","initialMessage","succeedNone","supportsAck","supportsTransferables","supportsSpanPropagation","makeProtocolFridaWithExport","exportName","defaultServerMainExportName","layerProtocolFrida","effect"],"sources":["../../src/frida/FridaRpcServer.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ /**
5
+ * Implements a Frida RPC client protocol for effect using the frida script
6
+ * exports.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ export * as FridaRpcClient from "./FridaRpcClient.ts";
11
+ /**
12
+ * Implements a Frida RPC server protocol for effect using the frida script
13
+ * exports.
14
+ *
15
+ * @since 1.0.0
16
+ */
17
+ export * as FridaRpcServer from "./FridaRpcServer.ts";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/frida/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;;;;GAKG;AACH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA"}
@@ -1,15 +1,16 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
1
4
  /**
2
5
  * Implements a Frida RPC client protocol for effect using the frida script
3
- * exports. The reason we don't use the send/recv script channels is because
4
- * those are shared channels by everybody.
6
+ * exports.
5
7
  *
6
8
  * @since 1.0.0
7
9
  */
8
10
  export * as FridaRpcClient from "./FridaRpcClient.js";
9
11
  /**
10
12
  * Implements a Frida RPC server protocol for effect using the frida script
11
- * exports. The reason we don't use the send/recv script channels is because
12
- * those are shared channels by everybody.
13
+ * exports.
13
14
  *
14
15
  * @since 1.0.0
15
16
  */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["FridaRpcClient","FridaRpcServer"],"sources":["../../src/frida/index.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAIA;;;;;;AAMA,OAAO,KAAKA,cAAc,MAAM,qBAAqB;AAErD;;;;;;AAMA,OAAO,KAAKC,cAAc,MAAM,qBAAqB","ignoreList":[]}
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Implements a Frida RPC client protocol for effect using the frida script
3
- * exports. The reason we don't use the send/recv script channels is because
4
- * those are shared channels by everybody.
3
+ * exports.
5
4
  *
6
5
  * @since 1.0.0
7
6
  */
8
7
  import type * as FridaSessionError from "@efffrida/frida-tools/FridaSessionError";
8
+ import type * as Scope from "effect/Scope";
9
9
  import * as RpcClient from "@effect/rpc/RpcClient";
10
10
  import * as RpcSerialization from "@effect/rpc/RpcSerialization";
11
11
  import * as FridaScript from "@efffrida/frida-tools/FridaScript";
@@ -15,16 +15,26 @@ import * as Layer from "effect/Layer";
15
15
  * @since 1.0.0
16
16
  * @category Protocol
17
17
  */
18
- export declare const makeProtocolFrida: (script: FridaScript.FridaScript, options?: {
18
+ export declare const makeProtocolFrida: (options?: {
19
+ /**
20
+ * Name for the main rpc export that all clients start by
21
+ * connecting to.
22
+ */
19
23
  readonly exportName?: string | undefined;
20
- readonly rpcIsAvailableWhen?: ((message: string) => boolean) | undefined;
21
- } | undefined) => Effect.Effect<RpcClient.Protocol["Type"], FridaSessionError.FridaSessionError, RpcSerialization.RpcSerialization>;
24
+ /** Generates server listener rpc exports for individual clients. */
25
+ readonly generateExportName?: ((clientId: number) => string) | undefined;
26
+ } | undefined) => Effect.Effect<RpcClient.Protocol["Type"], FridaSessionError.FridaSessionError, RpcSerialization.RpcSerialization | FridaScript.FridaScript | Scope.Scope>;
22
27
  /**
23
28
  * @since 1.0.0
24
29
  * @category Layers
25
30
  */
26
31
  export declare const layerProtocolFrida: (options?: {
32
+ /**
33
+ * Name for the main rpc export that all clients start by
34
+ * connecting to.
35
+ */
27
36
  readonly exportName?: string | undefined;
28
- readonly rpcIsAvailableWhen?: ((message: string) => boolean) | undefined;
37
+ /** Generates server listener rpc exports for individual clients. */
38
+ readonly generateExportName?: ((clientId: number) => string) | undefined;
29
39
  } | undefined) => Layer.Layer<RpcClient.Protocol, FridaSessionError.FridaSessionError, RpcSerialization.RpcSerialization | FridaScript.FridaScript>;
30
40
  //# sourceMappingURL=FridaRpcClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FridaRpcClient.d.ts","sourceRoot":"","sources":["../../src/node/FridaRpcClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,KAAK,iBAAiB,MAAM,yCAAyC,CAAC;AAClF,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAC;AACjE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAStC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC1B,UACM;IACI;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzC,oEAAoE;IACpE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;CAC5E,GACD,SAAS,KAChB,MAAM,CAAC,MAAM,CACZ,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC1B,iBAAiB,CAAC,iBAAiB,EACnC,gBAAgB,CAAC,gBAAgB,GAAG,WAAW,CAAC,WAAW,GAAG,KAAK,CAAC,KAAK,CAwExE,CAAC;AAEN;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC3B,UACM;IACI;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzC,oEAAoE;IACpE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;CAC5E,GACD,SAAS,KAChB,KAAK,CAAC,KAAK,CACV,SAAS,CAAC,QAAQ,EAClB,iBAAiB,CAAC,iBAAiB,EACnC,gBAAgB,CAAC,gBAAgB,GAAG,WAAW,CAAC,WAAW,CACE,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Implements a Frida RPC client protocol for effect using the frida script
3
+ * exports.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+ import * as RpcClient from "@effect/rpc/RpcClient";
8
+ import * as RpcSerialization from "@effect/rpc/RpcSerialization";
9
+ import * as FridaScript from "@efffrida/frida-tools/FridaScript";
10
+ import * as Effect from "effect/Effect";
11
+ import * as Function from "effect/Function";
12
+ import * as Layer from "effect/Layer";
13
+ import * as Option from "effect/Option";
14
+ import * as ParseResult from "effect/ParseResult";
15
+ import * as Predicate from "effect/Predicate";
16
+ import * as Schema from "effect/Schema";
17
+ import * as Stream from "effect/Stream";
18
+ import * as constants from "../shared/constants.js";
19
+ /**
20
+ * @since 1.0.0
21
+ * @category Protocol
22
+ */
23
+ export const makeProtocolFrida = options => RpcClient.Protocol.make(Effect.fnUntraced(function* (writeResponse) {
24
+ const script = yield* FridaScript.FridaScript;
25
+ const serialization = yield* RpcSerialization.RpcSerialization;
26
+ const parser = serialization.unsafeMake();
27
+ const mainExportName = options?.exportName ?? constants.defaultServerMainExportName;
28
+ const makeExportName = options?.generateExportName ?? constants.generateServerExportNameForClient;
29
+ /**
30
+ * Obtain a client id from the frida script export, this will allow
31
+ * us to filter future messages for ours since the script channels
32
+ * are shared.
33
+ */
34
+ const clientId = yield* Effect.catchIf(script.callExport(mainExportName, Schema.Number)(), ParseResult.isParseError, () => Effect.dieMessage("Failed to obtain client ID from Frida script export"));
35
+ const isClientId = Predicate.compose(Predicate.isNumber, id => id === clientId);
36
+ const receivingPredicate = Predicate.compose(Predicate.isUnknown, Predicate.struct({
37
+ clientId: isClientId
38
+ }));
39
+ /**
40
+ * Start listening for responses to our requests, decode them, and
41
+ * send the responses back to the implementation.
42
+ */
43
+ yield* script.stream.pipe(Stream.filterMap(unfiltered => {
44
+ if (receivingPredicate(unfiltered.message)) return unfiltered.data;else return Option.none();
45
+ }), Stream.runForEach(filtered => {
46
+ try {
47
+ const responses = parser.decode(filtered);
48
+ if (responses.length === 0) return Effect.void;
49
+ let i = 0;
50
+ return Effect.whileLoop({
51
+ while: () => i < responses.length,
52
+ body: () => writeResponse(responses[i++]),
53
+ step: Function.constVoid
54
+ });
55
+ } catch (defect) {
56
+ return writeResponse({
57
+ _tag: "Defect",
58
+ defect
59
+ });
60
+ }
61
+ }), Effect.interruptible, Effect.forkScoped);
62
+ /**
63
+ * Sending messages is as simple as encoding them, then posting them
64
+ * to the frida side tagged with our client id so it knows where to
65
+ * send them back to.
66
+ */
67
+ const send = Effect.fnUntraced(function* (message) {
68
+ const encoded = parser.encode(message);
69
+ if (Predicate.isUndefined(encoded)) return;
70
+ yield* script.callExport(makeExportName(clientId), Schema.Void)(encoded).pipe(Effect.orDie);
71
+ });
72
+ return {
73
+ send,
74
+ supportsAck: true,
75
+ supportsTransferables: false
76
+ };
77
+ }));
78
+ /**
79
+ * @since 1.0.0
80
+ * @category Layers
81
+ */
82
+ export const layerProtocolFrida = options => Layer.scoped(RpcClient.Protocol, makeProtocolFrida(options));
83
+ //# sourceMappingURL=FridaRpcClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FridaRpcClient.js","names":["RpcClient","RpcSerialization","FridaScript","Effect","Function","Layer","Option","ParseResult","Predicate","Schema","Stream","constants","makeProtocolFrida","options","Protocol","make","fnUntraced","writeResponse","script","serialization","parser","unsafeMake","mainExportName","exportName","defaultServerMainExportName","makeExportName","generateExportName","generateServerExportNameForClient","clientId","catchIf","callExport","Number","isParseError","dieMessage","isClientId","compose","isNumber","id","receivingPredicate","isUnknown","struct","stream","pipe","filterMap","unfiltered","message","data","none","runForEach","filtered","responses","decode","length","void","i","whileLoop","while","body","step","constVoid","defect","_tag","interruptible","forkScoped","send","encoded","encode","isUndefined","Void","orDie","supportsAck","supportsTransferables","layerProtocolFrida","scoped"],"sources":["../../src/node/FridaRpcClient.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Implements a Frida RPC server protocol for effect using the frida script
3
+ * exports.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+ import type * as Scope from "effect/Scope";
8
+ import * as RpcSerialization from "@effect/rpc/RpcSerialization";
9
+ import * as FridaScript from "@efffrida/frida-tools/FridaScript";
10
+ import * as Effect from "effect/Effect";
11
+ /**
12
+ * @since 1.0.0
13
+ * @category Protocol
14
+ */
15
+ export declare const makeProtocolFrida: () => Effect.Effect<unknown, never, FridaScript.FridaScript | RpcSerialization.RpcSerialization | Scope.Scope>;
16
+ //# sourceMappingURL=FridaRpcServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FridaRpcServer.d.ts","sourceRoot":"","sources":["../../src/node/FridaRpcServer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAG3C,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AAEjE,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAC;AAEjE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAaxC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAAO,MAAM,CAAC,MAAM,CAC9C,OAAO,EACP,KAAK,EACL,WAAW,CAAC,WAAW,GAAG,gBAAgB,CAAC,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAmGvE,CAAC"}