From 7a3b901e16987f04cf3c24c62f33db03fcce2d58 Mon Sep 17 00:00:00 2001 From: Halim Qarroum Date: Tue, 14 Mar 2023 16:54:48 +0000 Subject: [PATCH] Optimized Android images and replaced redir by Socat --- Dockerfile | 29 +- Dockerfile.gpu | 29 +- deps/redir/redir.c | 1140 ------------------------------------- scripts/start-emulator.sh | 12 +- 4 files changed, 28 insertions(+), 1182 deletions(-) delete mode 100644 deps/redir/redir.c diff --git a/Dockerfile b/Dockerfile index 2497c73..2305767 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,28 +5,20 @@ LABEL maintainer "Halim Qarroum " LABEL description "A Docker image allowing to run an Android emulator" LABEL version "1.0.0" -# `redir.c` will be used to redirect -# localhost ADB ports to the container interface. -COPY deps/redir/redir.c /usr/src/redir.c - # Installing required packages. RUN apk update && \ apk upgrade && \ apk add --no-cache \ - alpine-sdk \ bash \ unzip \ wget \ libvirt-daemon \ dbus \ polkit \ + socat \ virt-manager && \ - # Compile `redir`. - gcc /usr/src/redir.c -o /usr/bin/redir && \ - strip /usr/bin/redir && \ # Cleanup APK. - apk del alpine-sdk && \ - rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /var/cache/apk/* + rm -rf /tmp/* /var/tmp/* /var/cache/apk/* # Arguments that can be overriden at build-time. ARG INSTALL_ANDROID_SDK=1 @@ -49,7 +41,7 @@ ENV ANDROID_SDK_ROOT=/opt/android \ QTWEBENGINE_DISABLE_SANDBOX=1 \ ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL=10 -# Exporting environment variables for keeping in the path +# Exporting environment variables to keep in the path # Android SDK binaries and shared libraries. ENV PATH "${PATH}:${ANDROID_SDK_ROOT}/platform-tools" ENV PATH "${PATH}:${ANDROID_SDK_ROOT}/emulator" @@ -70,16 +62,17 @@ RUN mkdir /root/.android/ && \ # Exporting ADB keys. COPY keys/* /root/.android/ -# Copy the startup scripts. -COPY scripts/* /opt/ - -# Make the scripts executable. -RUN chmod +x /opt/*.sh - -# This layer will download the Android command-line tools +# The following layers will download the Android command-line tools # to install the Android SDK, emulator and system images. # It will then install the Android SDK and emulator. +COPY scripts/install-sdk.sh /opt/ +RUN chmod +x /opt/install-sdk.sh RUN /opt/install-sdk.sh +# Copy the container scripts in the image. +COPY scripts/start-emulator.sh /opt/ +COPY scripts/emulator-monitoring.sh /opt/ +RUN chmod +x /opt/*.sh + # Set the entrypoint ENTRYPOINT ["/opt/start-emulator.sh"] \ No newline at end of file diff --git a/Dockerfile.gpu b/Dockerfile.gpu index 0be8255..2987139 100644 --- a/Dockerfile.gpu +++ b/Dockerfile.gpu @@ -1,34 +1,26 @@ -FROM nvidia/cuda:12.1.0-runtime-ubuntu22.04 +FROM nvidia/cuda:12.1.0-base-ubuntu22.04 # Docker labels. LABEL maintainer "Halim Qarroum " LABEL description "A Docker image allowing to run an Android emulator" LABEL version "1.1.0" -# `redir.c` will be used to redirect -# localhost ADB ports to the container interface. -COPY deps/redir/redir.c /usr/src/redir.c - # Installing required packages. RUN apt update -y && \ - apt install -y --no-install-recommends \ - build-essential \ + DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends \ bash \ unzip \ wget \ libvirt-daemon \ dbus \ openjdk-11-jdk \ - ca-certificates-java \ virt-manager \ libvulkan1 \ xvfb \ libgl1-mesa-glx \ libgl1-mesa-dri \ + socat \ iproute2 && \ - # Compile `redir`. - gcc /usr/src/redir.c -o /usr/bin/redir && \ - strip /usr/bin/redir && \ rm -rf /var/lib/apt/lists/* # Arguments that can be overriden at build-time. @@ -73,16 +65,17 @@ RUN mkdir /root/.android/ && \ # Exporting ADB keys. COPY keys/* /root/.android/ -# Copy the startup scripts. -COPY scripts/* /opt/ - -# Make the scripts executable. -RUN chmod +x /opt/*.sh - -# This layer will download the Android command-line tools +# The following layers will download the Android command-line tools # to install the Android SDK, emulator and system images. # It will then install the Android SDK and emulator. +COPY scripts/install-sdk.sh /opt/ +RUN chmod +x /opt/install-sdk.sh RUN /opt/install-sdk.sh +# Copy the container scripts in the image. +COPY scripts/start-emulator.sh /opt/ +COPY scripts/emulator-monitoring.sh /opt/ +RUN chmod +x /opt/*.sh + # Set the entrypoint ENTRYPOINT ["/opt/start-emulator.sh"] \ No newline at end of file diff --git a/deps/redir/redir.c b/deps/redir/redir.c deleted file mode 100644 index 0ea7214..0000000 --- a/deps/redir/redir.c +++ /dev/null @@ -1,1140 +0,0 @@ -/* $Id$ - * - * redir - a utility for redirecting tcp connections - * - * Author: Nigel Metheringham - * Nigel.Metheringham@ThePLAnet.net - * - * Based on, but much modified from, code originally written by - * sammy@freenet.akron.oh.us - original header is below. - * - * redir is released under the GNU General Public license, - * version 2, or at your discretion, any later version. - * - */ - -/* - * redir is currently maintained by Sam Creasey (sammy@oh.verio.com). - * Please send patches, etc. there. - * - */ - -/* 980601: dl9sau - * added some nice new features: - * - * --bind_addr=my.other.ip.address - * forces to use my.other.ip.address for the outgoing connection - * - * you can also specify, that redir listens not on all IP addresses of - * your system but only for the given one, i.e.: - * if my host has the addresses - * irc.thishost.my.domain and mail.thishost.my.domain - * but you want that your users do connect for the irc redir service - * only on irc.thishost.my.domain, then do it this way: - * redir irc.fu-berlin.de irc.thishost.mydomain:6667 6667 - * my need was that: - * addr1.first.domain 6667 redirects to irc.first.net port 6667 - * and addr2.second.domain 6667 redirects to irc.second.net port 6667 - * while addr1 and addr2 are the same maschine and the ports can be equal. - * - * enjoy it! - * - thomas , - * - * btw: i tried without success implementing code for the following scenario: - * redir --force_addr irc.fu-berlin.de 6667 6667 - * if "--force_addr" is given and a user connects to my system, that address - * of my system will be used on the outgoing connection that the user - * connected to. - * i was not successful to determine, to which of my addresses the user - * has connected. - */ - -/* 990320 added support for ftp connection done by the client, now this code - * should work for all ftp clients. - * - * - harald - */ - -/* 991221 added options to simulate a slow connection and to limit - * bandwidth. - * - * - Emmanuel Chantr�au - */ - -#define VERSION "2.2.1" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef USE_TCP_WRAPPERS -#include -#endif - -#define debug(x) if (dodebug) fprintf(stderr, x) -#define debug1(x,y) if (dodebug) fprintf(stderr, x, y) - -/* let's set up some globals... */ -int dodebug = 0; -int dosyslog = 0; -unsigned char reuse_addr = 1; -unsigned char linger_opt = 0; -char * bind_addr = NULL; -struct sockaddr_in addr_out; -int timeout = 0; - -#ifndef NO_FTP -int ftp = 0; -#endif - -int transproxy = 0; - -#ifndef NO_SHAPER -int max_bandwidth = 0; -int random_wait = 0; -int wait_in_out=3; /* bit 0: wait for "in", bit 1: wait for "out" */ -int wait_in=1; -int wait_out=1; -#endif - -unsigned int bufsize=4096; -char *connect_str = NULL; /* CONNECT string passed to proxy */ -char * ident = NULL; - -#ifndef NO_FTP -/* what ftp to redirect */ -#define FTP_PORT 1 -#define FTP_PASV 2 -#endif - -#ifdef USE_TCP_WRAPPERS -struct request_info request; -int allow_severity = LOG_INFO; -int deny_severity = LOG_WARNING; -#endif /* USE_TCP_WRAPPERS */ - -#ifdef NEED_STRRCHR -#define strrchr rindex -#endif /* NEED_STRRCHR */ - -#define REDIR_IN 1 -#define REDIR_OUT 0 - -/* prototype anything needing it */ -void do_accept(int servsock, struct sockaddr_in *target); -int bindsock(char *addr, int port, int fail); - -#ifndef NO_SHAPER -/* Used in this program to write something in a socket, it has the same - parameters and return value as "write", but with the flag "in": true if - it's the "in" socket and false if it's the "out" socket */ -static inline ssize_t redir_write (int fd, const void *buf, size_t size, int in) -{ - ssize_t result; - int wait; - - wait=in ? wait_in : wait_out; - if( random_wait > 0 && wait) { - fd_set empty; - struct timeval waitbw; /* for bandwidth */ - int rand_time; - - FD_ZERO(&empty); - - rand_time=rand()%(random_wait*2); - debug1("random wait: %u\n", rand_time); - waitbw.tv_sec=rand_time/1000; - waitbw.tv_usec=rand_time%1000; - - select (1, &empty, NULL, NULL, &waitbw); - } - - result=write(fd, buf, size); - - if( max_bandwidth > 0 && wait) { - fd_set empty; - unsigned long bits; - struct timeval waitbw; /* for bandwidth */ - - FD_ZERO(&empty); - - /* wait to be sure tu be below the allowed bandwidth */ - bits=size*8; - debug1("bandwidth wait: %lu\n", 1000*bits/max_bandwidth); - waitbw.tv_sec=bits/max_bandwidth; - waitbw.tv_usec=(1000*(bits%max_bandwidth))/max_bandwidth; - - select (1, &empty, NULL, NULL, &waitbw); - } - - return result; -} -#else -/* macro if traffic shaper is disabled */ -#define redir_write(fd, buf, size, in) write(fd, buf,size) -#endif - - -#ifdef NEED_STRDUP -char * -strdup(char * str) -{ - char * result; - - if (result = (char *) malloc(strlen(str) + 1)) - strcpy(result, str); - - return result; -} -#endif /* NEED_STRDUP */ - -void -redir_usage(char *name) -{ - fprintf(stderr,"usage:\n"); - fprintf(stderr, - "\t%s --lport= --cport= [options]\n", - name); - fprintf(stderr, "\t%s --inetd --cport=\n", name); - fprintf(stderr, "\n\tOptions are:-\n"); - fprintf(stderr, "\t\t--lport=\t\tport to listen on\n"); - fprintf(stderr, "\t\t--laddr=IP\t\taddress of interface to listen on\n"); - fprintf(stderr, "\t\t--cport=\t\tport to connect to\n"); - fprintf(stderr, "\t\t--caddr=\t\tremote host to connect to\n"); - fprintf(stderr, "\t\t--inetd\t\trun from inetd\n"); - fprintf(stderr, "\t\t--debug\t\toutput debugging info\n"); - fprintf(stderr, "\t\t--timeout=\tset timeout to n seconds\n"); - fprintf(stderr, "\t\t--syslog\tlog messages to syslog\n"); - fprintf(stderr, "\t\t--name=\ttag syslog messages with 'str'\n"); - fprintf(stderr, "\t\t--connect=\tCONNECT string passed to proxy server\n"); -#ifdef USE_TCP_WRAPPERS - fprintf(stderr, "\t\t \tAlso used as service name for TCP wrappers\n"); -#endif /* USE_TCP_WRAPPERS */ - fprintf(stderr, "\t\t--bind_addr=IP\tbind() outgoing IP to given addr\n"); - -#ifndef NO_FTP - fprintf(stderr, "\t\t--ftp=\t\tredirect ftp connections\n"); - fprintf(stderr, "\t\t\twhere type is either port, pasv, both\n"); -#endif - - fprintf(stderr, "\t\t--transproxy\trun in linux's transparent proxy mode\n"); -#ifndef NO_SHAPER - /* options for bandwidth */ - fprintf(stderr, "\t\t--bufsize=\tsize of the buffer\n"); - fprintf(stderr, "\t\t--maxbandwidth=\tlimit the bandwidth\n"); - fprintf(stderr, "\t\t--random_wait=\twait before each packet\n"); - fprintf(stderr, "\t\t--wait_in_out=\t1 wait for in, 2 out, 3 in&out\n"); - /* end options for bandwidth */ -#endif - fprintf(stderr, "\n\tVersion %s.\n", VERSION); - exit(2); -} - -void -parse_args(int argc, - char * argv[], - char ** target_addr, - int * target_port, - char ** local_addr, - int * local_port, - int * timeout, - int * dodebug, - int * inetd, - int * dosyslog, - char ** bind_addr, -#ifndef NO_FTP - int * ftp, -#endif - int *transproxy, -#ifndef NO_SHAPER - unsigned int * bufsize, - int * max_bandwidth, - int * random_wait, - int * wait_in_out, -#endif - char **connect_str) -{ - static struct option long_options[] = { - {"lport", required_argument, 0, 'l'}, - {"laddr", required_argument, 0, 'a'}, - {"cport", required_argument, 0, 'r'}, - {"caddr", required_argument, 0, 'c'}, - {"bind_addr", required_argument, 0, 'b'}, - {"debug", no_argument, 0, 'd'}, - {"timeout", required_argument, 0, 't'}, - {"inetd", no_argument, 0, 'i'}, - {"ident", required_argument, 0, 'n'}, - {"name", required_argument, 0, 'n'}, - {"syslog", no_argument, 0, 's'}, - {"ftp", required_argument, 0, 'f'}, - {"transproxy", no_argument, 0, 'p'}, - {"connect", required_argument, 0, 'x'}, - {"bufsize", required_argument, 0, 'z'}, - {"max_bandwidth", required_argument, 0, 'm'}, - {"random_wait", required_argument, 0, 'w'}, - {"wait_in_out", required_argument, 0, 'o'}, - {0,0,0,0} /* End marker */ - }; - - int option_index = 0; - extern int optind; - int opt; - struct servent *portdesc; - char *lport = NULL; - char *tport = NULL; -#ifndef NO_FTP - char *ftp_type = NULL; -#endif - - *local_addr = NULL; - *target_addr = NULL; - *target_port = 0; - *local_port = 0; - - while ((opt = getopt_long(argc, argv, "disfpn:t:b:a:l:r:c:x:z:m:w:o:", - long_options, &option_index)) != -1) { - switch (opt) { - case 'x': - *connect_str = optarg; - break; - case 'a': - *local_addr = optarg; - break; - - case 'l': - lport = optarg; - break; - - case 'r': - tport = optarg; - break; - - case 'c': - *target_addr = optarg; - break; - - case 'b': - *bind_addr = optarg; - break; - - case 'd': - (*dodebug)++; - break; - - case 't': - *timeout = atol(optarg); - break; - - case 'i': - (*inetd)++; - break; - - case 'n': - /* This is the ident which is added to syslog messages */ - ident = optarg; - break; - - case 's': - (*dosyslog)++; - break; - -#ifndef NO_FTP - case 'f': - ftp_type = optarg; - if(!ftp_type) { - redir_usage(argv[0]); - exit(1); - } - break; -#endif - - case 'p': - (*transproxy)++; - break; - -#ifndef NO_SHAPER - case 'z': - *bufsize = (unsigned int)atol(optarg); - break; - - case 'm': - *max_bandwidth = atol(optarg); - break; - - case 'w': - *random_wait = atol(optarg); - break; - - case 'o': - *wait_in_out = atol(optarg); - wait_in=*wait_in_out & 1; - wait_out=*wait_in_out & 2; - break; -#endif - default: - redir_usage(argv[0]); - exit(1); - break; - } - } - - if(tport == NULL) - { - redir_usage(argv[0]); - exit(1); - } - - if ((portdesc = getservbyname(tport, "tcp")) != NULL) { - *target_port = ntohs(portdesc->s_port); - } else { - *target_port = atol(tport); - } - - /* only check local port if not running from inetd */ - if(!(*inetd)) { - if(lport == NULL) - { - redir_usage(argv[0]); - exit(1); - } - - if ((portdesc = getservbyname(lport, "tcp")) != NULL) - *local_port = ntohs(portdesc->s_port); - else - *local_port = atol(lport); - } /* if *inetd */ - - if (!ident) { - if ((ident = (char *) strrchr(argv[0], '/'))) { - ident++; - } else { - ident = argv[0]; - } - } - -#ifndef NO_FTP - /* some kind of ftp being forwarded? */ - if(ftp_type) { - if(!strncasecmp(ftp_type, "port", 4)) - *ftp = FTP_PORT; - else if(!strncasecmp(ftp_type, "pasv", 4)) - *ftp = FTP_PASV; - else if(!strncasecmp(ftp_type, "both", 4)) - *ftp = FTP_PORT | FTP_PASV; - else { - redir_usage(argv[0]); - exit(1); - } - } -#endif - - openlog(ident, LOG_PID, LOG_DAEMON); - - return; -} - -#ifndef NO_FTP -/* with the --ftp option, this one changes passive mode replies from - the ftp server to point to a new redirector which we spawn, - now it also change the PORT commando when the client accept the - dataconnection */ - -void ftp_clean(int send, char *buf, unsigned long *bytes, int ftpsrv) -{ - - char *port_start; - int rporthi, lporthi; - int lportlo, rportlo; - int lport, rport; - int remip[4]; - int localsock; - int socksize = sizeof(struct sockaddr_in); - - struct sockaddr_in newsession; - struct sockaddr_in sockname; - - if (ftpsrv == 0) - { - /* is this a port commando ? */ - if(strncmp(buf, "PORT", 4)) { - redir_write(send, buf, (*bytes), REDIR_OUT); - return; - } - /* parse the old address out of the buffer */ - port_start = strchr(buf, ' '); - - sscanf(port_start, " %d,%d,%d,%d,%d,%d", &remip[0], &remip[1], - &remip[2], &remip[3], &rporthi, &rportlo); - } else { - /* is this a passive mode return ? */ - if(strncmp(buf, "227", 3)) { - redir_write(send, buf, (*bytes), REDIR_OUT); - return; - } - - /* parse the old address out of the buffer */ - port_start = strchr(buf, '('); - - sscanf(port_start, "(%d,%d,%d,%d,%d,%d", &remip[0], &remip[1], - &remip[2], &remip[3], &rporthi, &rportlo); - } - - /* get the outside interface so we can listen */ - if(getsockname(send, (struct sockaddr *)&sockname, &socksize) != 0) { - perror("getsockname"); - exit(1); - } - - rport = (rporthi << 8) | rportlo; - - /* we need to listen on a port for the incoming connection. - we will use the port 0, so let the system pick one. */ - - localsock = bindsock(inet_ntoa(sockname.sin_addr), 0, 1); - - - /* get the real info */ - if(getsockname(localsock, (struct sockaddr *)&sockname, &socksize) < 0) { - perror("getsockname"); - if (dosyslog) - syslog(LOG_ERR, "getsockname failed: %m"); - exit(1); - } - - lport = ntohs(sockname.sin_port); - - lporthi=(lport >> 8 ) & 0xff; - lportlo=lport & 0xff; - - /* check to see if we bound */ - if(localsock == -1) { - fprintf(stderr, "ftp: unable to bind new listening address\n"); - exit(1); - } - if (ftpsrv == 0) { - /* send the new port and ipaddress to the server */ - (*bytes) = sprintf(buf, "PORT %d,%d,%d,%d,%d,%d\n", - sockname.sin_addr.s_addr & 0xff, - (sockname.sin_addr.s_addr >> 8) & 0xff, - (sockname.sin_addr.s_addr >> 16) & 0xff, - sockname.sin_addr.s_addr >> 24, lporthi, lportlo); - } else { - /* send the new port and ipaddress to the client */ - (*bytes) = sprintf(buf, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\n", - sockname.sin_addr.s_addr & 0xff, - (sockname.sin_addr.s_addr >> 8) & 0xff, - (sockname.sin_addr.s_addr >> 16) & 0xff, - sockname.sin_addr.s_addr >> 24, lporthi, lportlo); - } - newsession.sin_port = htons(rport); - newsession.sin_family = AF_INET; - newsession.sin_addr.s_addr = remip[0] | (remip[1] << 8) - | (remip[2] << 16) | (remip[3] << 24); - - debug1("ftpdata server ip: %s\n", inet_ntoa(newsession.sin_addr)); - debug1("ftpdata server port: %d\n", rport); - debug1("listening for ftpdata on port %d\n", lport); - debug1("listening for ftpdata on addr %s\n", inet_ntoa(sockname.sin_addr)); - - - /* now that we're bound and listening, we can safely send the new - string without fear of them getting a connection refused. */ - redir_write(send, buf, (*bytes), REDIR_OUT); - - /* make a new process to handle the dataconnection correctly, - for the PASV mode this isn't a problem because after sending the - PASV command, the data connection, get active. For the PORT command - the server must send a success, if starting here with the copyloop - the success command never arrive the client.*/ - - switch(fork()) - { - case -1: /* Error */ - syslog(LOG_ERR, "Couldn't fork: %m"); - _exit(1); - case 0: /* Child */ - { - /* turn off ftp checking while the data connection is active */ - ftp = 0; - do_accept(localsock, &newsession); - close(localsock); - _exit(0); - } - default: /* Parent */ - { close(localsock); } - } - return; -} -#endif - - -void -copyloop(int insock, - int outsock, - int timeout_secs) -{ - fd_set iofds; - fd_set c_iofds; - int max_fd; /* Maximum numbered fd used */ - struct timeval timeout; - unsigned long bytes; - unsigned long bytes_in = 0; - unsigned long bytes_out = 0; - unsigned int start_time, end_time; - char buf[bufsize]; - - /* Record start time */ - start_time = (unsigned int) time(NULL); - - /* Set up timeout */ - timeout.tv_sec = timeout_secs; - timeout.tv_usec = 0; - - /* file descriptor bits */ - FD_ZERO(&iofds); - FD_SET(insock, &iofds); - FD_SET(outsock, &iofds); - - - if (insock > outsock) { - max_fd = insock; - } else { - max_fd = outsock; - } - - debug1("Entering copyloop() - timeout is %d\n", timeout_secs); - while(1) { - (void) memcpy(&c_iofds, &iofds, sizeof(iofds)); - - - if (select(max_fd + 1, - &c_iofds, - (fd_set *)0, - (fd_set *)0, - (timeout_secs ? &timeout : NULL)) <= 0) { - /* syslog(LLEV,"connection timeout: %d sec",timeout.tv_sec);*/ - break; - } - - if(FD_ISSET(insock, &c_iofds)) { - if((bytes = read(insock, buf, sizeof(buf))) <= 0) - break; -#ifndef NO_FTP - if (ftp & FTP_PORT) - /* if we're correcting FTP, lookup for a PORT commando - in the buffer, if yes change this and establish - a new redirector for the data */ - ftp_clean(outsock, buf, &bytes,0); - else -#endif - if(redir_write(outsock, buf, bytes, REDIR_OUT) != bytes) - break; - bytes_out += bytes; - } - if(FD_ISSET(outsock, &c_iofds)) { - if((bytes = read(outsock, buf, sizeof(buf))) <= 0) - break; - /* if we're correcting for PASV on ftp redirections, then - fix buf and bytes to have the new address, among other - things */ -#ifndef NO_FTP - if(ftp & FTP_PASV) - ftp_clean(insock, buf, &bytes,1); - else -#endif - if(redir_write(insock, buf, bytes, REDIR_IN) != bytes) - break; - bytes_in += bytes; - } - } - debug("Leaving main copyloop\n"); - -/* - setsockopt(insock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); - setsockopt(insock, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(SO_LINGER)); - setsockopt(outsock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); - setsockopt(outsock, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(SO_LINGER)); -*/ - - shutdown(insock,0); - shutdown(outsock,0); - close(insock); - close(outsock); - debug("copyloop - sockets shutdown and closed\n"); - end_time = (unsigned int) time(NULL); - debug1("copyloop - connect time: %8d seconds\n", end_time - start_time); - debug1("copyloop - transfer in: %8ld bytes\n", bytes_in); - debug1("copyloop - transfer out: %8ld bytes\n", bytes_out); - if (dosyslog) { - syslog(LOG_NOTICE, "disconnect %d secs, %ld in %ld out", - (end_time - start_time), bytes_in, bytes_out); - } - return; -} - -void doproxyconnect(int socket) -{ - char buf[128]; - int x; - /* write CONNECT string to proxy */ - sprintf((char *) &buf, "CONNECT %s HTTP/1.0\n\n", connect_str); - x = write(socket, (char *) &buf, strlen(buf)); - if (x < 1) { - perror("doproxyconnect: failed"); - exit(1); - } - /* now read result */ - x = read(socket, (char *) &buf, sizeof(buf)); - if (x < 1) { - perror("doproxyconnect: failed reading fra proxy"); - exit(1); - } - /* no more error checking for now -- something should be added later */ - /* HTTP/1.0 200 Connection established */ -} - - -/* lwait for a connection and move into copyloop... again, - ftp redir will call this, so we don't dupilcate it. */ - -void -do_accept(int servsock, struct sockaddr_in *target) -{ - - int clisock; - int targetsock; - struct sockaddr_in client; - int clientlen = sizeof(client); - int accept_errno; - - debug("top of accept loop\n"); - if ((clisock = accept(servsock, (struct sockaddr *) &client, - &clientlen)) < 0) { - - accept_errno = errno; - perror("server: accept"); - - if (dosyslog) - syslog(LOG_ERR, "accept failed: %m"); - - /* determine if this error is fatal */ - switch(accept_errno) { - /* non-fatal errors */ - case EHOSTUNREACH: - case ECONNRESET: - case ETIMEDOUT: - return; - - /* all other errors assumed fatal */ - default: - exit(1); - } - - } - - debug1("peer IP is %s\n", inet_ntoa(client.sin_addr)); - debug1("peer socket is %d\n", client.sin_port); - - /* - * Double fork here so we don't have to wait later - * This detaches us from our parent so that the parent - * does not need to pick up dead kids later. - * - * This needs to be done before the hosts_access stuff, because - * extended hosts_access options expect to be run from a child. - */ - switch(fork()) - { - case -1: /* Error */ - perror("(server) fork"); - - if (dosyslog) - syslog(LOG_ERR, "(server) fork failed: %m"); - - _exit(1); - case 0: /* Child */ - break; - default: /* Parent */ - { - int status; - - /* Wait for child (who has forked off grandchild) */ - (void) wait(&status); - - /* Close sockets to prevent confusion */ - close(clisock); - - return; - } - } - - /* We are now the first child. Fork again and exit */ - - switch(fork()) - { - case -1: /* Error */ - perror("(child) fork"); - - if (dosyslog) - syslog(LOG_ERR, "(child) fork failed: %m"); - - _exit(1); - case 0: /* Child */ - break; - default: /* Parent */ - _exit(0); - } - - /* We are now the grandchild */ - -#ifdef USE_TCP_WRAPPERS - request_init(&request, RQ_DAEMON, ident, RQ_FILE, clisock, 0); - sock_host(&request); - sock_hostname(&request); - sock_hostaddr(&request); - - if (!hosts_access(&request)) { - refuse(&request); - _exit(0); - } - - if (dosyslog) - syslog(LOG_INFO, "accepted connect from %s", eval_client(&request)); -#endif /* USE_TCP_WRAPPERS */ - - if ((targetsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - - perror("target: socket"); - - if (dosyslog) - syslog(LOG_ERR, "socket failed: %m"); - - _exit(1); - } - - if(transproxy) { - memcpy(&addr_out, &client, sizeof(struct sockaddr_in)); - addr_out.sin_port = 0; - } - - if (bind_addr || transproxy) { - /* this only makes sense if an outgoing IP addr has been forced; - * at this point, we have a valid targetsock to bind() to.. */ - /* also, if we're in transparent proxy mode, this option - never makes sense */ - - if (bind(targetsock, (struct sockaddr *) &addr_out, - sizeof(struct sockaddr_in)) < 0) { - perror("bind_addr: cannot bind to forcerd outgoing addr"); - -/* the port parameter fetch the really port we are listening, it should - only be different if the input value is 0 (let the system pick a - port) */ - if (dosyslog) - syslog(LOG_ERR, "bind failed: %m"); - - _exit(1); - } - debug1("outgoing IP is %s\n", inet_ntoa(addr_out.sin_addr)); - } - - if (connect(targetsock, (struct sockaddr *) target, - sizeof(struct sockaddr_in)) < 0) { - perror("target: connect"); - - if (dosyslog) - syslog(LOG_ERR, "bind failed: %m"); - - _exit(1); - } - - debug1("connected to %s\n", inet_ntoa(target->sin_addr)); - - /* thanks to Anders Vannman for the fix to make proper syslogging - happen here... */ - - if (dosyslog) { - char tmp1[20], tmp2[20]; - strcpy(tmp1, inet_ntoa(client.sin_addr)); - strcpy(tmp2, inet_ntoa(target->sin_addr)); - - syslog(LOG_NOTICE, "connecting %s/%d to %s/%d", - tmp1, client.sin_port, - tmp2, target->sin_port); - } - - /* do proxy stuff */ - if (connect_str) - doproxyconnect(targetsock); - -#ifndef NO_SHAPER - /* initialise random number if necessary */ - if( random_wait > 0 ) { - srand(getpid()); - } -#endif - - copyloop(clisock, targetsock, timeout); - exit(0); /* Exit after copy */ -} - -/* bind to a new socket, we do this out here because passive-fixups - are going to call it too, and there's no sense dupliciting the - code. */ -/* fail is true if we should just return a -1 on error, false if we - should bail. */ - -int bindsock(char *addr, int port, int fail) -{ - - int servsock; - struct sockaddr_in server; - - /* - * Get a socket to work with. This socket will - * be in the Internet domain, and will be a - * stream socket. - */ - - if ((servsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - if(fail) { - return -1; - } - else { - perror("server: socket"); - - if (dosyslog) - syslog(LOG_ERR, "socket failed: %m"); - - exit(1); - } - } - - memset(&server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons(port); - if (addr != NULL) { - struct hostent *hp; - - debug1("listening on %s\n", addr); - if ((hp = gethostbyname(addr)) == NULL) { - fprintf(stderr, "%s: cannot resolve hostname.\n", addr); - exit(1); - } - memcpy(&server.sin_addr, hp->h_addr, hp->h_length); - } else { - debug("local IP is default\n"); - server.sin_addr.s_addr = htonl(inet_addr("0.0.0.0")); - } - - setsockopt(servsock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); - setsockopt(servsock, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(SO_LINGER)); - - /* - * Try to bind the address to the socket. - */ - - if (bind(servsock, (struct sockaddr *) &server, - sizeof(server)) < 0) { - if(fail) { - close(servsock); - return -1; - } else { - perror("server: bind"); - - if (dosyslog) - syslog(LOG_ERR, "bind failed: %m"); - - exit(1); - } - } - - /* - * Listen on the socket. - */ - - if (listen(servsock, 10) < 0) { - if(fail) { - close(servsock); - return -1; - } else { - perror("server: listen"); - - if (dosyslog) - syslog(LOG_ERR, "listen failed: %m"); - - exit(1); - } - } - - return servsock; -} - -int -main(int argc, char *argv[]) -{ - - struct sockaddr_in target; - char *target_addr; - int target_port; - char *local_addr; - int local_port; - int inetd = 0; - char * target_ip; - char * ip_to_target; - - debug("parse args\n"); - parse_args(argc, argv, &target_addr, &target_port, &local_addr, - &local_port, &timeout, &dodebug, &inetd, &dosyslog, &bind_addr, -#ifndef NO_FTP - &ftp, -#endif - &transproxy, -#ifndef NO_SHAPER - &bufsize, &max_bandwidth, &random_wait, - &wait_in_out, -#endif - &connect_str); - - /* Set up target */ - target.sin_family = AF_INET; - target.sin_port = htons(target_port); - if (target_addr != NULL) { - struct hostent *hp; - - debug1("target is %s\n", target_addr); - if ((hp = gethostbyname(target_addr)) == NULL) { - fprintf(stderr, "%s: host unknown.\n", target_addr); - exit(1); - } - memcpy(&target.sin_addr, hp->h_addr, hp->h_length); - } else { - debug("target is default\n"); - target.sin_addr.s_addr = htonl(inet_addr("0.0.0.0")); - } - - target_ip = strdup(inet_ntoa(target.sin_addr)); - debug1("target IP address is %s\n", target_ip); - debug1("target port is %d\n", target_port); - - /* Set up outgoing IP addr (optional); - * we have to wait for bind until targetsock = socket() is done - */ - if (bind_addr && !transproxy) { - struct hostent *hp; - - fprintf(stderr, "bind_addr is %s\n", bind_addr); - addr_out.sin_family = AF_INET; - addr_out.sin_port = 0; - if ((hp = gethostbyname(bind_addr)) == NULL) { - fprintf(stderr, "%s: cannot resolve forced outgoing IP address.\n", bind_addr); - exit(1); - } - memcpy(&addr_out.sin_addr, hp->h_addr, hp->h_length); - - ip_to_target = strdup(inet_ntoa(addr_out.sin_addr)); - debug1("IP address for target is %s\n", ip_to_target); - } - - - if (inetd) { - int targetsock; - struct sockaddr_in client; - int client_size = sizeof(client); - -#ifdef USE_TCP_WRAPPERS - request_init(&request, RQ_DAEMON, ident, RQ_FILE, 0, 0); - sock_host(&request); - sock_hostname(&request); - sock_hostaddr(&request); - - if (!hosts_access(&request)) - refuse(&request); -#endif /* USE_TCP_WRAPPERS */ - - if (!getpeername(0, (struct sockaddr *) &client, &client_size)) { - debug1("peer IP is %s\n", inet_ntoa(client.sin_addr)); - debug1("peer socket is %d\n", client.sin_port); - } - if ((targetsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("target: socket"); - - if (dosyslog) - syslog(LOG_ERR, "targetsock failed: %m"); - - exit(1); - } - - if(transproxy) { - memcpy(&addr_out, &client, sizeof(struct sockaddr_in)); - addr_out.sin_port = 0; - } - - if (bind_addr || transproxy) { - /* this only makes sense if an outgoing IP addr has been forced; - * at this point, we have a valid targetsock to bind() to.. */ - if (bind(targetsock, (struct sockaddr *) &addr_out, - sizeof(addr_out)) < 0) { - perror("bind_addr: cannot bind to forcerd outgoing addr"); - - if (dosyslog) - syslog(LOG_ERR, "bind failed: %m"); - - exit(1); - } - debug1("outgoing IP is %s\n", inet_ntoa(addr_out.sin_addr)); - } - - if (connect(targetsock, (struct sockaddr *) &target, - sizeof(target)) < 0) { - perror("target: connect"); - - if (dosyslog) - syslog(LOG_ERR, "connect failed: %m"); - - exit(1); - } - - if (dosyslog) { - syslog(LOG_NOTICE, "connecting %s/%d to %s/%d", - inet_ntoa(client.sin_addr), client.sin_port, - target_ip, target.sin_port); - } - - /* Just start copying - one side of the loop is stdin - 0 */ - copyloop(0, targetsock, timeout); - } else { - int servsock; - - if(local_addr) - servsock = bindsock(local_addr, local_port, 0); - else - servsock = bindsock(NULL, local_port, 0); - - /* - * Accept connections. When we accept one, ns - * will be connected to the client. client will - * contain the address of the client. - */ - - while (1) - do_accept(servsock, &target); - } - - /* this should really never be reached */ - - exit(0); - -} \ No newline at end of file diff --git a/scripts/start-emulator.sh b/scripts/start-emulator.sh index 833bcac..49a928d 100644 --- a/scripts/start-emulator.sh +++ b/scripts/start-emulator.sh @@ -13,10 +13,11 @@ ADB_PORT=5555 echo "Starting the ADB server ..." adb -a -P 5037 server nodaemon & -# Detect ip and forward ADB ports outside to outside interface -ip=$(ip addr list eth0 | grep "inet " | cut -d' ' -f6 | cut -d/ -f1) -redir --laddr="$ip" --lport="$EMULATOR_CONSOLE_PORT" --caddr=127.0.0.1 --cport="$EMULATOR_CONSOLE_PORT" & -redir --laddr="$ip" --lport="$ADB_PORT" --caddr=127.0.0.1 --cport="$ADB_PORT" & +# Detect ip and forward ADB ports from the container's network +# interface to localhost. +LOCAL_IP=$(ip addr list eth0 | grep "inet " | cut -d' ' -f6 | cut -d/ -f1) +socat tcp-listen:"$EMULATOR_CONSOLE_PORT",bind="$LOCAL_IP",fork tcp:127.0.0.1:"$EMULATOR_CONSOLE_PORT" & +socat tcp-listen:"$ADB_PORT",bind="$LOCAL_IP",fork tcp:127.0.0.1:"$ADB_PORT" & export USER=root @@ -39,7 +40,7 @@ if [ "$GPU_ACCELERATED" == "true" ]; then export GPU_MODE="host" Xvfb "$DISPLAY" -screen 0 1920x1080x16 -nolisten tcp & else - export GPU_MODE="auto" + export GPU_MODE="swiftshader_indirect" fi # Asynchronously write updates on the standard output @@ -49,7 +50,6 @@ wait_for_boot & # Start the emulator with no audio, no GUI, and no snapshots. echo "Starting the emulator ..." emulator \ - -verbose \ -avd android \ -gpu "$GPU_MODE" \ -no-boot-anim \