From 40cb7397b0dfd1a0db2a171a634d04fe646f19fb Mon Sep 17 00:00:00 2001 From: migueldar Date: Sun, 19 Jan 2025 14:18:13 +0100 Subject: [PATCH] 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 --- http_server/code/index.html | 19 +++-- http_server/code/index.mjs | 125 ++++++++------------------------ http_server/code/screenshot.mjs | 62 ++++++++++++++++ http_server/code/utils.mjs | 3 + intraContainerCom.txt | 11 +++ start.mjs | 4 +- 6 files changed, 121 insertions(+), 103 deletions(-) create mode 100644 http_server/code/screenshot.mjs create mode 100644 http_server/code/utils.mjs create mode 100644 intraContainerCom.txt diff --git a/http_server/code/index.html b/http_server/code/index.html index e8053f7..0a73df8 100644 --- a/http_server/code/index.html +++ b/http_server/code/index.html @@ -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) { diff --git a/http_server/code/index.mjs b/http_server/code/index.mjs index 639917f..b519ae3 100644 --- a/http_server/code/index.mjs +++ b/http_server/code/index.mjs @@ -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); diff --git a/http_server/code/screenshot.mjs b/http_server/code/screenshot.mjs new file mode 100644 index 0000000..9c93e15 --- /dev/null +++ b/http_server/code/screenshot.mjs @@ -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); + } +}); \ No newline at end of file diff --git a/http_server/code/utils.mjs b/http_server/code/utils.mjs new file mode 100644 index 0000000..31e4abf --- /dev/null +++ b/http_server/code/utils.mjs @@ -0,0 +1,3 @@ +export async function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} \ No newline at end of file diff --git a/intraContainerCom.txt b/intraContainerCom.txt new file mode 100644 index 0000000..67d9d2d --- /dev/null +++ b/intraContainerCom.txt @@ -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) \ No newline at end of file diff --git a/start.mjs b/start.mjs index 12bc017..08d92b4 100644 --- a/start.mjs +++ b/start.mjs @@ -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" );