@expo/serve-sim 0.1.35-canary.0
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/LICENSE +202 -0
- package/README.md +279 -0
- package/Sources/SimAXSettings/build.sh +21 -0
- package/Sources/SimAXSettings/sim-ax-settings.m +273 -0
- package/Sources/SimCameraHelper/build.sh +33 -0
- package/Sources/SimCameraHelper/main.m +955 -0
- package/Sources/SimCameraInjector/SimCamFakes.h +88 -0
- package/Sources/SimCameraInjector/SimCamFakes.m +704 -0
- package/Sources/SimCameraInjector/SimCamFrameSource.h +26 -0
- package/Sources/SimCameraInjector/SimCamFrameSource.m +577 -0
- package/Sources/SimCameraInjector/SimCamLog.h +5 -0
- package/Sources/SimCameraInjector/SimCamLog.m +9 -0
- package/Sources/SimCameraInjector/SimCamSwizzles.h +3 -0
- package/Sources/SimCameraInjector/SimCamSwizzles.m +1338 -0
- package/Sources/SimCameraInjector/SimCameraInjector.m +19 -0
- package/Sources/SimCameraInjector/build.sh +39 -0
- package/Sources/SimCameraInjector/include/SimCamShared.h +79 -0
- package/dist/bin/LiveKitWebRTC.framework/LiveKitWebRTC +0 -0
- package/dist/bin/LiveKitWebRTC.framework/Resources/Info.plist +36 -0
- package/dist/bin/LiveKitWebRTC.framework/Resources/LICENSE.webrtc +29 -0
- package/dist/bin/LiveKitWebRTC.framework/Resources/PrivacyInfo.xcprivacy +32 -0
- package/dist/bin/LiveKitWebRTC.framework/_CodeSignature/CodeResources +150 -0
- package/dist/middleware.cjs +2 -0
- package/dist/middleware.js +123 -0
- package/dist/native/serve-sim-native.node +0 -0
- package/dist/serve-sim.js +218 -0
- package/dist/simax/serve-sim-ax-settings +0 -0
- package/dist/simcam/libSimCameraInjector.dylib +0 -0
- package/dist/simcam/serve-sim-camera-helper +0 -0
- package/dist/state.js +1 -0
- package/package.json +99 -0
- package/src/ax-shared.ts +25 -0
- package/src/ax.ts +258 -0
- package/src/camera-helper.ts +150 -0
- package/src/connect-to-fetch.ts +239 -0
- package/src/middleware.ts +2208 -0
- package/src/native.ts +294 -0
- package/src/state.ts +86 -0
- package/src/stream-settings.ts +202 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import type { IncomingMessage, ServerResponse } from "http";
|
|
3
|
+
import type { Socket } from "net";
|
|
4
|
+
|
|
5
|
+
type Next = (error?: unknown) => void | Promise<void>;
|
|
6
|
+
|
|
7
|
+
export type ConnectMiddleware = {
|
|
8
|
+
(req: IncomingMessage, res: ServerResponse, next?: Next): void | Promise<void>;
|
|
9
|
+
handleUpgrade?: (req: IncomingMessage, socket: Socket, head: Buffer) => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function headersFromRequest(request: Request): Record<string, string> {
|
|
13
|
+
const headers: Record<string, string> = {};
|
|
14
|
+
request.headers.forEach((value, key) => {
|
|
15
|
+
headers[key.toLowerCase()] = value;
|
|
16
|
+
});
|
|
17
|
+
if (!headers.host) headers.host = new URL(request.url).host;
|
|
18
|
+
return headers;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Adapt the package's Connect-style implementation to its public Fetch handler. */
|
|
22
|
+
export function connectToFetch(
|
|
23
|
+
handler: ConnectMiddleware,
|
|
24
|
+
request: Request,
|
|
25
|
+
): Promise<Response | undefined> {
|
|
26
|
+
const requestUrl = new URL(request.url);
|
|
27
|
+
const requestEvents = new EventEmitter();
|
|
28
|
+
const responseEvents = new EventEmitter();
|
|
29
|
+
const abortController = new AbortController();
|
|
30
|
+
let requestBodyReader: ReadableStreamDefaultReader<Uint8Array> | null = null;
|
|
31
|
+
let requestClosed = false;
|
|
32
|
+
const closeRequest = (aborted = false) => {
|
|
33
|
+
if (requestClosed) return;
|
|
34
|
+
requestClosed = true;
|
|
35
|
+
abortController.abort();
|
|
36
|
+
void requestBodyReader?.cancel().catch(() => {});
|
|
37
|
+
request.signal.removeEventListener("abort", handleRequestAbort);
|
|
38
|
+
if (aborted) requestEvents.emit("aborted");
|
|
39
|
+
requestEvents.emit("close");
|
|
40
|
+
};
|
|
41
|
+
const handleRequestAbort = () => closeRequest(true);
|
|
42
|
+
const requestWasAlreadyAborted = request.signal.aborted;
|
|
43
|
+
request.signal.addEventListener("abort", handleRequestAbort, { once: true });
|
|
44
|
+
const fakeReq = Object.assign(requestEvents, {
|
|
45
|
+
method: request.method,
|
|
46
|
+
url: `${requestUrl.pathname}${requestUrl.search}`,
|
|
47
|
+
headers: headersFromRequest(request),
|
|
48
|
+
socket: { localPort: Number(requestUrl.port) || undefined },
|
|
49
|
+
destroy() {
|
|
50
|
+
closeRequest();
|
|
51
|
+
},
|
|
52
|
+
}) as IncomingMessage;
|
|
53
|
+
|
|
54
|
+
let status = 200;
|
|
55
|
+
let responseHeaders = new Headers();
|
|
56
|
+
let headersSent = false;
|
|
57
|
+
let writableEnded = false;
|
|
58
|
+
let writableFinished = false;
|
|
59
|
+
let responseDestroyed = false;
|
|
60
|
+
let responseClosed = false;
|
|
61
|
+
let writableNeedDrain = false;
|
|
62
|
+
let controllerRef: ReadableStreamDefaultController<Uint8Array> | null = null;
|
|
63
|
+
let resolveResponse!: (response: Response | undefined) => void;
|
|
64
|
+
let rejectResponse!: (error: unknown) => void;
|
|
65
|
+
let resolved = false;
|
|
66
|
+
const encoder = new TextEncoder();
|
|
67
|
+
|
|
68
|
+
const emitResponseClose = () => {
|
|
69
|
+
if (responseClosed) return;
|
|
70
|
+
responseClosed = true;
|
|
71
|
+
responseEvents.emit("close");
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const body = new ReadableStream<Uint8Array>({
|
|
75
|
+
start(controller) {
|
|
76
|
+
controllerRef = controller;
|
|
77
|
+
},
|
|
78
|
+
cancel() {
|
|
79
|
+
responseDestroyed = true;
|
|
80
|
+
closeRequest();
|
|
81
|
+
emitResponseClose();
|
|
82
|
+
},
|
|
83
|
+
pull() {
|
|
84
|
+
if (!writableNeedDrain) return;
|
|
85
|
+
writableNeedDrain = false;
|
|
86
|
+
responseEvents.emit("drain");
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const resolveOnce = (response: Response | undefined) => {
|
|
91
|
+
if (resolved) return;
|
|
92
|
+
resolved = true;
|
|
93
|
+
resolveResponse(response);
|
|
94
|
+
};
|
|
95
|
+
const statusAllowsBody = () => status !== 101 && status !== 204 && status !== 205 && status !== 304;
|
|
96
|
+
const ensureResponse = () => {
|
|
97
|
+
if (headersSent) return;
|
|
98
|
+
headersSent = true;
|
|
99
|
+
resolveOnce(new Response(statusAllowsBody() ? body : null, { status, headers: responseHeaders }));
|
|
100
|
+
};
|
|
101
|
+
const writeChunk = (chunk: Buffer | string | Uint8Array) => {
|
|
102
|
+
ensureResponse();
|
|
103
|
+
if (!statusAllowsBody() || !controllerRef || writableEnded) return true;
|
|
104
|
+
// Native capture reuses its callback buffer after write() returns. Web
|
|
105
|
+
// streams retain enqueued arrays, so every non-string chunk needs owned
|
|
106
|
+
// storage before the producer is allowed to continue.
|
|
107
|
+
const data = typeof chunk === "string" ? encoder.encode(chunk) : new Uint8Array(chunk);
|
|
108
|
+
try {
|
|
109
|
+
controllerRef.enqueue(data);
|
|
110
|
+
} catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
writableNeedDrain = (controllerRef.desiredSize ?? 0) <= 0;
|
|
114
|
+
return !writableNeedDrain;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const fakeRes = {
|
|
118
|
+
get headersSent() { return headersSent; },
|
|
119
|
+
get writableEnded() { return writableEnded; },
|
|
120
|
+
get writableFinished() { return writableFinished; },
|
|
121
|
+
get destroyed() { return responseDestroyed; },
|
|
122
|
+
get writableNeedDrain() { return writableNeedDrain; },
|
|
123
|
+
get statusCode() { return status; },
|
|
124
|
+
set statusCode(nextStatus: number) { status = nextStatus; },
|
|
125
|
+
writeHead(nextStatus: number, headers?: Record<string, string | number | string[]>) {
|
|
126
|
+
status = nextStatus;
|
|
127
|
+
if (headers) {
|
|
128
|
+
responseHeaders = new Headers();
|
|
129
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
130
|
+
if (Array.isArray(value)) {
|
|
131
|
+
for (const item of value) responseHeaders.append(key, item);
|
|
132
|
+
} else {
|
|
133
|
+
responseHeaders.set(key, String(value));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
ensureResponse();
|
|
138
|
+
},
|
|
139
|
+
write(
|
|
140
|
+
chunk: Buffer | string | Uint8Array,
|
|
141
|
+
encodingOrCallback?: BufferEncoding | ((error?: Error | null) => void),
|
|
142
|
+
callback?: (error?: Error | null) => void,
|
|
143
|
+
) {
|
|
144
|
+
const accepted = writeChunk(chunk);
|
|
145
|
+
const done = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
|
|
146
|
+
done?.();
|
|
147
|
+
return accepted;
|
|
148
|
+
},
|
|
149
|
+
end(chunk?: Buffer | string | Uint8Array) {
|
|
150
|
+
if (chunk !== undefined) writeChunk(chunk);
|
|
151
|
+
ensureResponse();
|
|
152
|
+
writableEnded = true;
|
|
153
|
+
writableFinished = true;
|
|
154
|
+
try {
|
|
155
|
+
controllerRef?.close();
|
|
156
|
+
} catch {
|
|
157
|
+
// The consumer may already have cancelled the stream.
|
|
158
|
+
}
|
|
159
|
+
responseEvents.emit("finish");
|
|
160
|
+
emitResponseClose();
|
|
161
|
+
closeRequest();
|
|
162
|
+
},
|
|
163
|
+
destroy(error?: Error) {
|
|
164
|
+
if (responseDestroyed) return fakeRes;
|
|
165
|
+
ensureResponse();
|
|
166
|
+
responseDestroyed = true;
|
|
167
|
+
writableEnded = true;
|
|
168
|
+
try {
|
|
169
|
+
controllerRef?.error(error ?? new Error("Response destroyed"));
|
|
170
|
+
} catch {
|
|
171
|
+
// The consumer may already have cancelled the stream.
|
|
172
|
+
}
|
|
173
|
+
if (error && responseEvents.listenerCount("error") > 0) responseEvents.emit("error", error);
|
|
174
|
+
emitResponseClose();
|
|
175
|
+
closeRequest();
|
|
176
|
+
return fakeRes;
|
|
177
|
+
},
|
|
178
|
+
on(event: string, listener: (...args: unknown[]) => void) {
|
|
179
|
+
responseEvents.on(event, listener);
|
|
180
|
+
return fakeRes;
|
|
181
|
+
},
|
|
182
|
+
once(event: string, listener: (...args: unknown[]) => void) {
|
|
183
|
+
responseEvents.once(event, listener);
|
|
184
|
+
return fakeRes;
|
|
185
|
+
},
|
|
186
|
+
off(event: string, listener: (...args: unknown[]) => void) {
|
|
187
|
+
responseEvents.off(event, listener);
|
|
188
|
+
return fakeRes;
|
|
189
|
+
},
|
|
190
|
+
} as unknown as ServerResponse;
|
|
191
|
+
|
|
192
|
+
const responsePromise = new Promise<Response | undefined>((resolve, reject) => {
|
|
193
|
+
resolveResponse = resolve;
|
|
194
|
+
rejectResponse = reject;
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
let handling: Promise<void>;
|
|
198
|
+
try {
|
|
199
|
+
handling = Promise.resolve(handler(fakeReq, fakeRes, () => resolveOnce(undefined)));
|
|
200
|
+
} catch (error) {
|
|
201
|
+
handling = Promise.reject(error);
|
|
202
|
+
}
|
|
203
|
+
if (requestWasAlreadyAborted) handleRequestAbort();
|
|
204
|
+
void handling
|
|
205
|
+
.then(() => {
|
|
206
|
+
if (!resolved && writableEnded) {
|
|
207
|
+
resolveOnce(new Response(null, { status, headers: responseHeaders }));
|
|
208
|
+
}
|
|
209
|
+
}, (error) => {
|
|
210
|
+
if (resolved) fakeRes.destroy(error instanceof Error ? error : undefined);
|
|
211
|
+
else rejectResponse(error);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
void (async () => {
|
|
215
|
+
let reader: ReadableStreamDefaultReader<Uint8Array> | null = null;
|
|
216
|
+
try {
|
|
217
|
+
reader = request.body?.getReader() ?? null;
|
|
218
|
+
requestBodyReader = reader;
|
|
219
|
+
if (reader) {
|
|
220
|
+
while (!abortController.signal.aborted) {
|
|
221
|
+
const { done, value } = await reader.read();
|
|
222
|
+
if (done) break;
|
|
223
|
+
requestEvents.emit("data", Buffer.from(value));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!abortController.signal.aborted) requestEvents.emit("end");
|
|
227
|
+
} catch {
|
|
228
|
+
closeRequest(true);
|
|
229
|
+
} finally {
|
|
230
|
+
if (requestBodyReader === reader) requestBodyReader = null;
|
|
231
|
+
if (reader) {
|
|
232
|
+
if (abortController.signal.aborted) await reader.cancel().catch(() => {});
|
|
233
|
+
try { reader.releaseLock(); } catch {}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
})();
|
|
237
|
+
|
|
238
|
+
return responsePromise;
|
|
239
|
+
}
|