@efffrida/rpc 0.0.26 → 0.0.28
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.
- package/dist/frida/FridaRpcClient.d.ts +4 -29
- package/dist/frida/FridaRpcClient.d.ts.map +1 -1
- package/dist/frida/FridaRpcClient.js +47 -83
- package/dist/frida/FridaRpcClient.js.map +1 -1
- package/dist/frida/FridaRpcServer.d.ts +7 -7
- package/dist/frida/FridaRpcServer.d.ts.map +1 -1
- package/dist/frida/FridaRpcServer.js +37 -49
- package/dist/frida/FridaRpcServer.js.map +1 -1
- package/dist/node/FridaRpcClient.d.ts +6 -10
- package/dist/node/FridaRpcClient.d.ts.map +1 -1
- package/dist/node/FridaRpcClient.js +67 -46
- package/dist/node/FridaRpcClient.js.map +1 -1
- package/dist/node/FridaRpcServer.d.ts +10 -3
- package/dist/node/FridaRpcServer.d.ts.map +1 -1
- package/dist/node/FridaRpcServer.js +63 -64
- package/dist/node/FridaRpcServer.js.map +1 -1
- package/dist/shared/{constants.d.ts → Constants.d.ts} +7 -3
- package/dist/shared/Constants.d.ts.map +1 -0
- package/dist/shared/Constants.js +10 -0
- package/dist/shared/Constants.js.map +1 -0
- package/dist/shared/index.d.ts +10 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +10 -0
- package/dist/shared/index.js.map +1 -0
- package/package.json +14 -21
- package/src/frida/FridaRpcClient.ts +61 -141
- package/src/frida/FridaRpcServer.ts +47 -54
- package/src/node/FridaRpcClient.ts +84 -71
- package/src/node/FridaRpcServer.ts +92 -80
- package/src/shared/Constants.ts +13 -0
- package/src/shared/index.ts +10 -0
- package/dist/shared/constants.d.ts.map +0 -1
- package/dist/shared/constants.js +0 -7
- package/dist/shared/constants.js.map +0 -1
- package/dist/shared/predicates.d.ts +0 -10
- package/dist/shared/predicates.d.ts.map +0 -1
- package/dist/shared/predicates.js +0 -12
- package/dist/shared/predicates.js.map +0 -1
- package/src/shared/constants.ts +0 -11
- package/src/shared/predicates.ts +0 -19
|
@@ -7,119 +7,121 @@
|
|
|
7
7
|
|
|
8
8
|
import type * as Scope from "effect/Scope";
|
|
9
9
|
|
|
10
|
-
import * as RpcMessage from "@effect/rpc/RpcMessage";
|
|
11
|
-
import * as RpcSerialization from "@effect/rpc/RpcSerialization";
|
|
12
|
-
import * as RpcServer from "@effect/rpc/RpcServer";
|
|
13
|
-
import * as FridaScript from "@efffrida/frida-tools/FridaScript";
|
|
14
|
-
import * as Console from "effect/Console";
|
|
15
10
|
import * as Effect from "effect/Effect";
|
|
16
11
|
import * as Function from "effect/Function";
|
|
17
|
-
import * as
|
|
12
|
+
import * as Layer from "effect/Layer";
|
|
18
13
|
import * as Option from "effect/Option";
|
|
19
14
|
import * as Predicate from "effect/Predicate";
|
|
20
|
-
import * as
|
|
15
|
+
import * as Queue from "effect/Queue";
|
|
21
16
|
import * as Stream from "effect/Stream";
|
|
22
17
|
import * as String from "effect/String";
|
|
23
|
-
import * as
|
|
18
|
+
import * as RpcMessage from "effect/unstable/rpc/RpcMessage";
|
|
19
|
+
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
20
|
+
import * as RpcServer from "effect/unstable/rpc/RpcServer";
|
|
21
|
+
|
|
22
|
+
import * as FridaScript from "@efffrida/frida-tools/FridaScript";
|
|
24
23
|
|
|
25
|
-
import * as constants from "../shared/
|
|
26
|
-
import * as predicates from "../shared/predicates.ts";
|
|
24
|
+
import * as constants from "../shared/Constants.ts";
|
|
27
25
|
|
|
28
26
|
/**
|
|
29
27
|
* @since 1.0.0
|
|
30
28
|
* @category Protocol
|
|
31
29
|
*/
|
|
32
30
|
export const makeProtocolFrida = (): Effect.Effect<
|
|
33
|
-
|
|
31
|
+
RpcServer.Protocol["Service"],
|
|
34
32
|
never,
|
|
35
33
|
FridaScript.FridaScript | RpcSerialization.RpcSerialization | Scope.Scope
|
|
36
34
|
> =>
|
|
37
35
|
Effect.gen(function* () {
|
|
38
|
-
const encoder = new TextEncoder();
|
|
39
|
-
const script = yield* FridaScript.FridaScript;
|
|
40
36
|
const serialization = yield* RpcSerialization.RpcSerialization;
|
|
37
|
+
const script = yield* FridaScript.FridaScript;
|
|
38
|
+
|
|
39
|
+
const disconnects = yield* Queue.unbounded<number>();
|
|
40
|
+
const parser = serialization.makeUnsafe();
|
|
41
|
+
const encoder = new TextEncoder();
|
|
41
42
|
|
|
42
43
|
let clientId = 0;
|
|
43
44
|
const clientIds = new Set<number>();
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
const clientIdsByExports = new Map<string, number>();
|
|
46
|
+
const clients = new Map<
|
|
47
|
+
number,
|
|
48
|
+
{
|
|
49
|
+
readonly write: (bytes: RpcMessage.FromServerEncoded) => void;
|
|
50
|
+
}
|
|
51
|
+
>();
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
}),
|
|
59
|
-
Stream.runForEach((exportName) => {
|
|
60
|
-
const id = clientId++;
|
|
61
|
-
clientIds.add(id);
|
|
62
|
-
return script.callExport(exportName, Schema.Void)(clientId++);
|
|
63
|
-
}),
|
|
64
|
-
Stream.tapError(Console.error),
|
|
65
|
-
Stream.runDrain,
|
|
66
|
-
Effect.forkScoped
|
|
53
|
+
const stripPrefix = String.replace(constants.nodeRpcClientConnectionRequestMessagePrefix, "");
|
|
54
|
+
const newClientPredicate: Predicate.Refinement<unknown, string> = Predicate.compose(
|
|
55
|
+
Predicate.isString,
|
|
56
|
+
String.startsWith(constants.nodeRpcClientConnectionRequestMessagePrefix)
|
|
57
|
+
);
|
|
58
|
+
const clientMessagePredicate: Predicate.Refinement<unknown, string> = Predicate.compose(
|
|
59
|
+
Predicate.isString,
|
|
60
|
+
(message) => clientIdsByExports.has(message)
|
|
67
61
|
);
|
|
68
62
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
63
|
+
let writeRequest!: (clientId: number, message: RpcMessage.FromClientEncoded) => Effect.Effect<void>;
|
|
64
|
+
const makeRawWriter =
|
|
65
|
+
(exportName: string) =>
|
|
66
|
+
(data: string | Uint8Array): Effect.Effect<void> => {
|
|
67
|
+
const transformed = typeof data === "string" ? encoder.encode(data) : data;
|
|
68
|
+
return script.callExport(exportName)(transformed).pipe(Effect.orDie);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const onClientConnect = (message: string): Effect.Effect<void> => {
|
|
72
|
+
const writeRaw = makeRawWriter(stripPrefix(message));
|
|
73
|
+
const write = (response: RpcMessage.FromServerEncoded): Effect.Effect<void> => {
|
|
79
74
|
try {
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
return Effect.whileLoop({
|
|
84
|
-
while: () => i < decoded.length,
|
|
85
|
-
body() {
|
|
86
|
-
const message = decoded[i++];
|
|
87
|
-
return writeRequest(clientId, message);
|
|
88
|
-
},
|
|
89
|
-
step: Function.constVoid,
|
|
90
|
-
});
|
|
75
|
+
const encoded = parser.encode(response);
|
|
76
|
+
if (encoded === undefined) return Effect.void;
|
|
77
|
+
return writeRaw(encoded);
|
|
91
78
|
} catch (cause) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const transformed = typeof encoded === "string" ? encoder.encode(encoded) : encoded;
|
|
95
|
-
script.script.post({ clientId }, Buffer.from(transformed));
|
|
96
|
-
});
|
|
79
|
+
const encoded = parser.encode(RpcMessage.ResponseDefectEncoded(cause))!;
|
|
80
|
+
return writeRaw(encoded);
|
|
97
81
|
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const id = ++clientId;
|
|
85
|
+
clientIdsByExports.set(stripPrefix(message), id);
|
|
86
|
+
clients.set(id, { write });
|
|
87
|
+
clientIds.add(id);
|
|
88
|
+
return Effect.void;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const onMessage = (exportName: string, data: Uint8Array): Effect.Effect<void> => {
|
|
92
|
+
try {
|
|
93
|
+
const id = clientIdsByExports.get(exportName)!;
|
|
94
|
+
const decoded = parser.decode(data) as ReadonlyArray<RpcMessage.FromClientEncoded>;
|
|
95
|
+
if (decoded.length === 0) return Effect.void;
|
|
96
|
+
let i = 0;
|
|
97
|
+
return Effect.whileLoop({
|
|
98
|
+
while: () => i < decoded.length,
|
|
99
|
+
step: Function.constVoid,
|
|
100
|
+
body() {
|
|
101
|
+
const message = decoded[i++];
|
|
102
|
+
return writeRequest(id, message);
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
} catch (cause) {
|
|
106
|
+
const writeRaw = makeRawWriter(exportName);
|
|
107
|
+
return writeRaw(parser.encode(RpcMessage.ResponseDefectEncoded(cause))!);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
yield* Stream.runForEach(script.stream, ({ message, data }) => {
|
|
112
|
+
if (newClientPredicate(message)) return onClientConnect(message);
|
|
113
|
+
if (clientMessagePredicate(message) && Option.isSome(data)) return onMessage(message, data.value);
|
|
114
|
+
return Effect.void;
|
|
115
|
+
}).pipe(Effect.forkScoped);
|
|
103
116
|
|
|
104
117
|
return yield* RpcServer.Protocol.make((_writeRequest) => {
|
|
105
118
|
writeRequest = _writeRequest;
|
|
106
119
|
return Effect.succeed({
|
|
107
120
|
disconnects,
|
|
108
121
|
send: (clientId, response) => {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return Effect.void;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
const encoded = parser.encode(response);
|
|
117
|
-
if (Predicate.isNotUndefined(encoded)) return writeRaw(encoded);
|
|
118
|
-
else return Effect.void;
|
|
119
|
-
} catch (cause) {
|
|
120
|
-
const encoded = parser.encode(RpcMessage.ResponseDefectEncoded(cause))!;
|
|
121
|
-
return writeRaw(encoded);
|
|
122
|
-
}
|
|
122
|
+
const client = clients.get(clientId);
|
|
123
|
+
if (!client) return Effect.void;
|
|
124
|
+
return Effect.sync(() => client.write(response));
|
|
123
125
|
},
|
|
124
126
|
end(_clientId) {
|
|
125
127
|
return Effect.void;
|
|
@@ -132,3 +134,13 @@ export const makeProtocolFrida = (): Effect.Effect<
|
|
|
132
134
|
});
|
|
133
135
|
});
|
|
134
136
|
});
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @since 1.0.0
|
|
140
|
+
* @category Layer
|
|
141
|
+
*/
|
|
142
|
+
export const layerProtocolFrida: Layer.Layer<
|
|
143
|
+
RpcServer.Protocol,
|
|
144
|
+
never,
|
|
145
|
+
FridaScript.FridaScript | RpcSerialization.RpcSerialization
|
|
146
|
+
> = Layer.effect(RpcServer.Protocol, makeProtocolFrida());
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for working with RPC servers and clients.
|
|
3
|
+
*
|
|
4
|
+
* @since 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const defaultServerMainExportName = "rpc";
|
|
8
|
+
export const generateServerExportNameForClient = (clientId: number): string =>
|
|
9
|
+
`@efffrida/rpc/FridaServerRpcListenerForClient/${clientId}`;
|
|
10
|
+
|
|
11
|
+
export const nodeRpcClientConnectionRequestMessagePrefix = "@efffrida/rpc/NodeRpcClientConnectionRequest/";
|
|
12
|
+
export const nodeRpcClientMakeConnectionRequestForServer = (exportName: string) =>
|
|
13
|
+
`${nodeRpcClientConnectionRequestMessagePrefix}${exportName}`;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AACjD,eAAO,MAAM,iCAAiC,GAAI,UAAU,MAAM,KAAG,MACN,CAAC;AAGhE,eAAO,MAAM,yCAAyC,QAAO,MACY,CAAC;AAE1E,eAAO,MAAM,2CAA2C,8BAA8B,CAAC;AACvF,eAAO,MAAM,2CAA2C,GAAI,YAAY,MAAM,WACZ,CAAC"}
|
package/dist/shared/constants.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export const defaultServerMainExportName = "rpc";
|
|
2
|
-
export const generateServerExportNameForClient = clientId => `@efffrida/rpc/FridaServerRpcListenerForClient/${clientId}`;
|
|
3
|
-
let exportIdForClientCallback = 0;
|
|
4
|
-
export const generateClientCallbackExportNameForServer = () => `@efffrida/rpc/FridaClientRpcCallback/${exportIdForClientCallback++}`;
|
|
5
|
-
export const nodeRpcClientConnectionRequestMessagePrefix = "client id request message";
|
|
6
|
-
export const nodeRpcClientMakeConnectionRequestForServer = exportName => `${nodeRpcClientConnectionRequestMessagePrefix}:${exportName}`;
|
|
7
|
-
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":["defaultServerMainExportName","generateServerExportNameForClient","clientId","exportIdForClientCallback","generateClientCallbackExportNameForServer","nodeRpcClientConnectionRequestMessagePrefix","nodeRpcClientMakeConnectionRequestForServer","exportName"],"sources":["../../src/shared/constants.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAO,MAAMA,2BAA2B,GAAG,KAAK;AAChD,OAAO,MAAMC,iCAAiC,GAAIC,QAAgB,IAC9D,iDAAiDA,QAAQ,EAAE;AAE/D,IAAIC,yBAAyB,GAAW,CAAC;AACzC,OAAO,MAAMC,yCAAyC,GAAGA,CAAA,KACrD,wCAAwCD,yBAAyB,EAAE,EAAE;AAEzE,OAAO,MAAME,2CAA2C,GAAG,2BAA2B;AACtF,OAAO,MAAMC,2CAA2C,GAAIC,UAAkB,IAC1E,GAAGF,2CAA2C,IAAIE,UAAU,EAAE","ignoreList":[]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import * as Predicate from "effect/Predicate";
|
|
2
|
-
export declare const isClientId: (clientId: number) => Predicate.Refinement<unknown, number>;
|
|
3
|
-
export declare const isTaggedForClient: (clientId: number) => Predicate.Refinement<unknown, {
|
|
4
|
-
readonly clientId: number;
|
|
5
|
-
}>;
|
|
6
|
-
export declare const isTaggedForAnyClient: Predicate.Refinement<unknown, {
|
|
7
|
-
readonly clientId: number;
|
|
8
|
-
}>;
|
|
9
|
-
export declare const newClientPredicate: Predicate.Refinement<unknown, string>;
|
|
10
|
-
//# sourceMappingURL=predicates.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"predicates.d.ts","sourceRoot":"","sources":["../../src/shared/predicates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAC;AAK9C,eAAO,MAAM,UAAU,GAAI,UAAU,MAAM,0CAAmE,CAAC;AAE/G,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM;;EAC8C,CAAC;AAEjG,eAAO,MAAM,oBAAoB;;EAGhC,CAAC;AAEF,eAAO,MAAM,kBAAkB,uCAG9B,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import * as Predicate from "effect/Predicate";
|
|
2
|
-
import * as String from "effect/String";
|
|
3
|
-
import * as constants from "./constants.js";
|
|
4
|
-
export const isClientId = clientId => Predicate.compose(Predicate.isNumber, id => id === clientId);
|
|
5
|
-
export const isTaggedForClient = clientId => Predicate.compose(Predicate.isUnknown, Predicate.struct({
|
|
6
|
-
clientId: isClientId(clientId)
|
|
7
|
-
}));
|
|
8
|
-
export const isTaggedForAnyClient = /*#__PURE__*/Predicate.compose(Predicate.isUnknown, /*#__PURE__*/Predicate.struct({
|
|
9
|
-
clientId: Predicate.isNumber
|
|
10
|
-
}));
|
|
11
|
-
export const newClientPredicate = /*#__PURE__*/Predicate.compose(Predicate.isString, /*#__PURE__*/String.startsWith(constants.nodeRpcClientConnectionRequestMessagePrefix));
|
|
12
|
-
//# sourceMappingURL=predicates.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"predicates.js","names":["Predicate","String","constants","isClientId","clientId","compose","isNumber","id","isTaggedForClient","isUnknown","struct","isTaggedForAnyClient","newClientPredicate","isString","startsWith","nodeRpcClientConnectionRequestMessagePrefix"],"sources":["../../src/shared/predicates.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAO,KAAKA,SAAS,MAAM,kBAAkB;AAC7C,OAAO,KAAKC,MAAM,MAAM,eAAe;AAEvC,OAAO,KAAKC,SAAS,MAAM,gBAAgB;AAE3C,OAAO,MAAMC,UAAU,GAAIC,QAAgB,IAAKJ,SAAS,CAACK,OAAO,CAACL,SAAS,CAACM,QAAQ,EAAGC,EAAE,IAAKA,EAAE,KAAKH,QAAQ,CAAC;AAE9G,OAAO,MAAMI,iBAAiB,GAAIJ,QAAgB,IAC9CJ,SAAS,CAACK,OAAO,CAACL,SAAS,CAACS,SAAS,EAAET,SAAS,CAACU,MAAM,CAAC;EAAEN,QAAQ,EAAED,UAAU,CAACC,QAAQ;AAAC,CAAE,CAAC,CAAC;AAEhG,OAAO,MAAMO,oBAAoB,gBAAGX,SAAS,CAACK,OAAO,CACjDL,SAAS,CAACS,SAAS,eACnBT,SAAS,CAACU,MAAM,CAAC;EAAEN,QAAQ,EAAEJ,SAAS,CAACM;AAAQ,CAAE,CAAC,CACrD;AAED,OAAO,MAAMM,kBAAkB,gBAAGZ,SAAS,CAACK,OAAO,CAC/CL,SAAS,CAACa,QAAQ,eAClBZ,MAAM,CAACa,UAAU,CAACZ,SAAS,CAACa,2CAA2C,CAAC,CAC3E","ignoreList":[]}
|
package/src/shared/constants.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const defaultServerMainExportName = "rpc";
|
|
2
|
-
export const generateServerExportNameForClient = (clientId: number): string =>
|
|
3
|
-
`@efffrida/rpc/FridaServerRpcListenerForClient/${clientId}`;
|
|
4
|
-
|
|
5
|
-
let exportIdForClientCallback: number = 0;
|
|
6
|
-
export const generateClientCallbackExportNameForServer = (): string =>
|
|
7
|
-
`@efffrida/rpc/FridaClientRpcCallback/${exportIdForClientCallback++}`;
|
|
8
|
-
|
|
9
|
-
export const nodeRpcClientConnectionRequestMessagePrefix = "client id request message";
|
|
10
|
-
export const nodeRpcClientMakeConnectionRequestForServer = (exportName: string) =>
|
|
11
|
-
`${nodeRpcClientConnectionRequestMessagePrefix}:${exportName}`;
|
package/src/shared/predicates.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import * as Predicate from "effect/Predicate";
|
|
2
|
-
import * as String from "effect/String";
|
|
3
|
-
|
|
4
|
-
import * as constants from "./constants.ts";
|
|
5
|
-
|
|
6
|
-
export const isClientId = (clientId: number) => Predicate.compose(Predicate.isNumber, (id) => id === clientId);
|
|
7
|
-
|
|
8
|
-
export const isTaggedForClient = (clientId: number) =>
|
|
9
|
-
Predicate.compose(Predicate.isUnknown, Predicate.struct({ clientId: isClientId(clientId) }));
|
|
10
|
-
|
|
11
|
-
export const isTaggedForAnyClient = Predicate.compose(
|
|
12
|
-
Predicate.isUnknown,
|
|
13
|
-
Predicate.struct({ clientId: Predicate.isNumber })
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
export const newClientPredicate = Predicate.compose(
|
|
17
|
-
Predicate.isString,
|
|
18
|
-
String.startsWith(constants.nodeRpcClientConnectionRequestMessagePrefix)
|
|
19
|
-
);
|