fixed mutiple issues, specified socket protocol and cleaned code

Summary:
Issues fixed:

- ipv6 in pre_android container
- frontend was detecting drags when clicking out of screen
- frontend was registering clicks when clicking out of screen

Reviewers: #testers, kuba-orlik

Reviewed By: #testers, kuba-orlik

Maniphest Tasks: T2976

Differential Revision: https://hub.sealcode.org/D1568
This commit is contained in:
migueldar 2025-01-19 14:18:13 +01:00
parent 0a6e04c5ba
commit 40cb7397b0
6 changed files with 121 additions and 103 deletions

View File

@ -131,6 +131,8 @@
let startDraggingPosY = 0;
let endDraggingPosY = 0;
const screenSize = [320, 640]
const handleDraggStart = (e) => {
e.preventDefault();
isDragging = true;
@ -144,24 +146,25 @@
endDraggingPosX = e.offsetX;
endDraggingPosY = e.offsetY;
if (
(isDragging && Math.abs(endDraggingPosY - startDraggingPosY) > 10) ||
Math.abs(endDraggingPosX - startDraggingPosX) > 10
isDragging && (Math.abs(endDraggingPosY - startDraggingPosY) > 10 ||
Math.abs(endDraggingPosX - startDraggingPosX) > 10)
) {
registerClick({
path: "drag",
logText: `await drag({x:${startDraggingPosX},y:${startDraggingPosY}},{x:${e.offsetX},y:${e.offsetY}});`,
body: `startX=${startDraggingPosX}&startY=${startDraggingPosY}&endX=${e.offsetX}&endY=${e.offsetY}`,
});
isDragging = false;
} else {
const phoneX = event.offsetX;
const phoneY = event.offsetY;
registerClick({
path: "touch",
logText: `await click(${phoneX}, ${phoneY});`,
body: `x=${phoneX}&y=${phoneY}`,
});
if (phoneX <= screenSize[0] && phoneY <= screenSize[1])
registerClick({
path: "touch",
logText: `await click(${phoneX}, ${phoneY});`,
body: `x=${phoneX}&y=${phoneY}`,
});
}
isDragging = false;
});
async function sleep(time) {

View File

@ -1,85 +1,18 @@
import express from "express";
import net from "net";
import fs from "fs";
import { readFile } from "node:fs/promises";
import { guardedScreenshot, socket_client, waitFullBoot } from "./screenshot.mjs";
const device_size_x = 320;
const device_size_y = 640;
const app = express();
app.use(express.urlencoded({ extended: false }));
const socket_client = net.createConnection({ port: 3000, host: "android" });
async function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
let doneWrite = 0;
let screenshotPromise = null;
async function screenshot() {
const time_start = Date.now();
socket_client.write("screenshot");
while (!doneWrite) {
await sleep(15);
if (Date.now() - time_start > 2000) {
console.error("Screenshot timed out after 2s");
break; // timeout
}
}
doneWrite = 0;
screenshotPromise = null;
}
async function guardedScreenshot() {
console.log("Requesting a screenshot");
if (!screenshotPromise) {
console.log("no ongoing promise, starting a new one");
screenshotPromise = screenshot();
}
return screenshotPromise;
}
async function waitFullBoot() {
var start = performance.now();
var counter = 0;
//will timeout after 10 min
while (performance.now() - start < 600 * 1000) {
var before = performance.now();
await screenshot();
var after = performance.now();
if (after - before < process.env.screenshotDelayMs) counter++;
else counter = 0;
if (counter === 10) return;
}
throw new Error("wait for screenshot time to be less than 0.5s timed out");
}
let fd;
socket_client.on("data", (dataBuf) => {
if (dataBuf.toString() === "start")
fd = fs.openSync("/code/screenshot.png", "w");
else {
if (dataBuf.toString().includes("ENDOFMSG")) {
fs.writeSync(fd, dataBuf);
fs.close(fd);
doneWrite = 1;
} else fs.writeSync(fd, dataBuf);
}
});
console.log("Waiting for full boot...");
await waitFullBoot();
console.log("Boot detected! activating endpoints");
app.get("/screen", async function (req, res) {
await guardedScreenshot();
res.sendFile("/code/screenshot.png");
});
//GET
app.get("/favicon.ico", function (req, res) {
res.sendFile("/code/favicon.ico");
});
@ -92,6 +25,36 @@ app.get("/trafficLog", async function (req, res) {
res.sendFile("/log/trafficLog");
});
app.get("/screen", async function (req, res) {
await guardedScreenshot();
res.sendFile("/code/screenshot.png");
});
app.get("/", async function (req, res) {
let fileData = (await readFile("/code/index.html")).toString();
fileData = fileData.replace(
"___screenshotDelayMs___",
process.env.screenshotDelayMs
);
res.setHeader("Content-Type", "text/html");
res.setHeader("Content-Disposition", "inline");
res.send(fileData);
});
//POST
app.post("/back", function (req, res) {
socket_client.write(`back`);
res.sendStatus(200);
});
app.post("/home", function (req, res) {
socket_client.write(`home`);
res.sendStatus(200);
});
app.post("/touch", function (req, res) {
const x = parseInt(req.body.x);
const y = parseInt(req.body.y);
@ -106,30 +69,6 @@ app.post("/touch", function (req, res) {
}
});
app.get("/", async function (req, res) {
let fileData = (await readFile("/code/index.html")).toString();
fileData = fileData.replace(
"___screenshotDelayMs___",
process.env.screenshotDelayMs
);
res.setHeader("Content-Type", "text/html");
res.setHeader("Content-Disposition", "inline");
res.send(fileData);
});
app.post("/back", function (req, res) {
socket_client.write(`back`);
res.sendStatus(200);
});
app.post("/home", function (req, res) {
socket_client.write(`home`);
res.sendStatus(200);
});
app.post("/drag", function (req, res) {
const body = req.body;
const startX = Number(body.startX);

View File

@ -0,0 +1,62 @@
import net from "net";
import fs from "fs";
import { sleep } from "./utils.mjs";
export const socket_client = net.createConnection({ port: 3000, host: "android" });
let doneWrite = 0;
let screenshotPromise = null;
async function screenshot() {
const time_start = Date.now();
socket_client.write("screenshot");
while (!doneWrite) {
await sleep(15);
if (Date.now() - time_start > 2000) {
console.error("Screenshot timed out after 2s");
break; // timeout
}
}
doneWrite = 0;
screenshotPromise = null;
}
export async function guardedScreenshot() {
console.log("Requesting a screenshot");
if (!screenshotPromise) {
console.log("no ongoing promise, starting a new one");
screenshotPromise = screenshot();
}
return screenshotPromise;
}
export async function waitFullBoot() {
var start = performance.now();
var counter = 0;
//will timeout after 10 min
while (performance.now() - start < 600 * 1000) {
var before = performance.now();
await screenshot();
var after = performance.now();
if (after - before < process.env.screenshotDelayMs) counter++;
else counter = 0;
if (counter === 10) return;
}
throw new Error("wait for screenshot time to be less than 0.5s timed out");
}
let fd;
socket_client.on("data", (dataBuf) => {
if (dataBuf.toString() === "start")
fd = fs.openSync("/code/screenshot.png", "w");
else {
if (dataBuf.toString().includes("ENDOFMSG")) {
fs.writeSync(fd, dataBuf);
fs.close(fd);
doneWrite = 1;
} else fs.writeSync(fd, dataBuf);
}
});

View File

@ -0,0 +1,3 @@
export async function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}

11
intraContainerCom.txt Normal file
View File

@ -0,0 +1,11 @@
INTRA CONTAINER COMMUNICATION
FROM HTTPSERVER TO ANDROID
- screenshot
- home
- back
- touch $x $y
- drag $startx $starty $endx $endy
FROM ANDROID TO HTTPSERVER
- start $screenshotdata ENDOFMSG (to send screenshot data)

View File

@ -43,7 +43,7 @@ async function generateCert() {
async function generatePreAndroid() {
await $`docker build -t pre_android pre_android`;
$`docker run --rm -v $PWD/certificates/mitmproxy-ca-cert.cer:/ca-cert.cer -v $PWD/pre_android/preconf:/preconf --device=/dev/kvm --name pre_android_cont pre_android &`;
$`docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 --rm -v $PWD/certificates/mitmproxy-ca-cert.cer:/ca-cert.cer -v $PWD/pre_android/preconf:/preconf --device=/dev/kvm --name pre_android_cont pre_android &`;
console.log(
"Installing tls certificate and culebra into the android pre-image..."
@ -90,5 +90,5 @@ else if (process.argv[3] === "generateCert") {
generatePreAndroid();
} else
throw new Error(
"expected [up | down | generateCert | generatePreAndroid ] as argument"
"expected [ up | down | generateCert | generatePreAndroid ] as argument"
);