Skip to content
This repository has been archived by the owner on May 4, 2023. It is now read-only.

修复NAT模式下androd device都是局域网地址无法使用的问题 #98

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 56 additions & 20 deletions templates/remotecontrol_android.html
Original file line number Diff line number Diff line change
Expand Up @@ -399,14 +399,14 @@ <h4>增加快捷命令</h4>
</div>
</el-tab-pane>
<el-tab-pane label="截图" name="screenshot">
<a :href="screenshotUrl+'?download=screenshot.jpg'" download>下载截图</a>
<a :href="screenshotAtxAgentUrl" download>下载截图</a>
</el-tab-pane>
<el-tab-pane label="应用管理" name="packagemanager">
<el-button icon="el-icon-refresh" size="small" @click="loadPackages">刷新</el-button>
<el-table :data="packages" :default-sort="{prop: 'name'}">
<el-table-column sortable prop="label" label="应用">
<template slot-scope="scope">
<img :src="`${deviceUrl}/packages/${scope.row.name}/icon`" onerror="this.onerror='';this.src='/static/images/transparent.png'"
<img :src="`${formatAtxAgentUrl('/packages/'+scope.row.name+'/icon')}`" onerror="this.onerror='';this.src='/static/images/transparent.png'"
style="position: absolute; top: 50%; margin: -20px; height: 40px; left: 20px;" alt="icon" />
<span v-text=" scope.row.label" style="padding-left: 45px"></span>
</template>
Expand Down Expand Up @@ -527,7 +527,7 @@ <h4>增加快捷命令</h4>

$.ajax({
method: "post",
url: this.source.url + "/app/install?udid=" + this.udid,
url: this.formatProviderUrl('/app/install') + "&udid=" + this.udid,
data: {
url: this.app.installUrl,
launch: this.app.launch,
Expand All @@ -546,9 +546,15 @@ <h4>增加快捷命令</h4>
this.app.finished = true
})
},
formatAtxAgentUrl(path) {
return `${this.deviceAtxAgentUrl}${path}?host=${this.deviceHost}&port=${this.devicePort}`
},
formatProviderUrl(path) {
return `${this.deviceProviderUrl}${path}?host=${this.providerHost}&port=${this.providerPort}`
},
appLaunch(packageName) {
$.ajax({
url: `${this.deviceUrl}/session/${packageName}`,
url: this.formatAtxAgentUrl(`/session/${packageName}`),
method: "post"
}).then(ret => {
console.log(ret)
Expand Down Expand Up @@ -593,9 +599,8 @@ <h4>增加快捷命令</h4>
})
},
loadWhatsinput(callback) {
console.log(this.whatsInputUrl)
let defer = $.Deferred()
let ws = new WebSocket(this.whatsInputUrl)
let ws = new WebSocket(this.whatsInputWSUrl)
this.websockets.winput = ws;
ws.onopen = (ev) => {
defer.resolve()
Expand Down Expand Up @@ -702,7 +707,7 @@ <h4>增加快捷命令</h4>
// })
$.ajax({
method: "get",
url: this.deviceUrl + "/info/rotation"
url: this.formatAtxAgentUrl("/info/rotation")
}).done(ret => {
this.$notify({
message: "Rotation updated",
Expand Down Expand Up @@ -730,7 +735,7 @@ <h4>增加快捷命令</h4>
runShell(command) {
return $.ajax({
method: "get",
url: this.deviceUrl + "/shell",
url: this.formatAtxAgentUrl("/shell"),
data: {
"command": command,
},
Expand Down Expand Up @@ -761,7 +766,7 @@ <h4>增加快捷命令</h4>
},
loadTerminal() {
let term;
let ws = new WebSocket("ws://" + this.address + "/term");
let ws = new WebSocket(this.deviceAtxAgentTermWSUrl);
ws.binaryType = "arraybuffer"

function ab2str(buf) {
Expand Down Expand Up @@ -858,7 +863,7 @@ <h4>增加快捷命令</h4>
versionName: "",
versionCode: "",
}
$.getJSON(`${this.deviceUrl}/packages/${packageName}/info`).then(ret => {
$.getJSON(this.formatAtxAgentUrl(`/packages/${packageName}/info`)).then(ret => {
if (ret.success && ret.data) {
item.label = ret.data.label
item.versionName = ret.data.versionName
Expand Down Expand Up @@ -892,7 +897,7 @@ <h4>增加快捷命令</h4>
this.closeSyncTouchpad()
},
mirrorDisplay() {
let ws = new WebSocket(this.deviceUrl.replace(/^http/, "ws") + '/minicap');
let ws = new WebSocket(`${this.deviceAtxAgentCapWSUrl}`);
this.websockets.screen = ws;

ws.onopen = (ev) => {
Expand Down Expand Up @@ -941,7 +946,7 @@ <h4>增加快捷命令</h4>
bounds: {}
}

let ws = new WebSocket("ws://" + this.address + "/minitouch")
let ws = new WebSocket(this.deviceAtxAgentTouchWSUrl)
this.websockets.touchpad = ws

ws.onopen = (ret) => {
Expand Down Expand Up @@ -1445,20 +1450,51 @@ <h4>增加快捷命令</h4>
address() {
return this.source.atxAgentAddress
},
deviceUrl() {
return "http://" + this.address
providerHost() {
return this.source.url.split('/')[2].split(':')[0]
},
providerPort() {
return this.source.url.split(':')[2]
},
deviceHost() {
return this.address.split(':')[0]
},
devicePort() {
return this.address.split(':')[1]
},
deviceWhatsInputPort() {
return this.source.whatsInputAddress.split(':')[1]
},
deviceAtxAgentCapWSUrl() {
var host = window.location.host;
return `ws://${host}/websocket/atxagent/minicap?host=${this.deviceHost}&port=${this.devicePort}`
},
deviceAtxAgentTouchWSUrl() {
var host = window.location.host;
return `ws://${host}/websocket/atxagent/minitouch?host=${this.deviceHost}&port=${this.devicePort}`
},
deviceAtxAgentTermWSUrl() {
var host = window.location.host;
return `ws://${host}/websocket/atxagent/term?host=${this.deviceHost}&port=${this.devicePort}`
},
deviceAtxAgentUrl() {
var host = window.location.host;
return "http://" + host + '/api/v1/atxagent'
},
remoteTerminal() {
return "http://" + this.address + "/term"
deviceProviderUrl() {
var host = window.location.host;
return `http://${host}/api/v1/provider`
},
screenshotUrl() {
return "http://" + this.address + "/screenshot/0"
screenshotAtxAgentUrl() {
var host = window.location.host;
return `http://${host}/api/v1/atxagent/screenshot/0?host=${this.deviceHost}&port=${this.devicePort}`
},
remoteConnectAddr() {
return "adb connect " + this.source.remoteConnectAddress
},
whatsInputUrl() {
return "ws://" + this.source.whatsInputAddress
whatsInputWSUrl() {
var host = window.location.host;
return `ws://${host}/websocket/whatsinput?host=${this.deviceHost}&port=${this.deviceWhatsInputPort}`
},
displayLinked() {
return this.websockets.screen !== null;
Expand Down
9 changes: 8 additions & 1 deletion web/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
APIDeviceListHandler, APIDevicePropertiesHandler,
APIUserDeviceActiveHandler, APIUserDeviceHandler,
AppleDeviceListHandler, DeviceChangesWSHandler,
DeviceItemHandler, DeviceListHandler)
DeviceItemHandler, DeviceListHandler, AndroidProviderProxyHandler,
AndroidDeviceWSProxyHandler, AndroidDeviceAtxAgentProxyHandler)
from .views.group import (APIGroupUserListHandler, APIUserGroupListHandler,
UserGroupCreateHandler)
from .views.provider import ProviderHeartbeatWSHandler
Expand All @@ -35,6 +36,9 @@

(r"/websocket/devicechanges", DeviceChangesWSHandler),
(r"/websocket/heartbeat", ProviderHeartbeatWSHandler),
(r"/websocket/atxagent/(minicap|term|minitouch)", AndroidDeviceWSProxyHandler),
(r"/websocket/whatsinput", AndroidDeviceWSProxyHandler),

# For compability of atx-server-1
(r"/list", make_redirect_handler("/api/v1/devices")),
# RESP API
Expand All @@ -47,6 +51,9 @@
(r"/api/v1/user/devices/([^/]+)/active", APIUserDeviceActiveHandler), # GET
(r"/api/v1/user/settings", APIUserSettingsHandler), # GET, PUT
(r"/api/v1/admins", APIAdminListHandler), # GET, POST
(r"/api/v1/atxagent/(.*)", AndroidDeviceAtxAgentProxyHandler),
(r"/api/v1/provider/(app/install|cold)", AndroidProviderProxyHandler),

## Group API
# (r"/api/v1/user/groups/([^/]+)", APIUserGroupHandler), # GET, POST, DELETE TODO(ssx)
(r"/api/v1/user/groups", APIUserGroupListHandler), # GET, POST
Expand Down
102 changes: 102 additions & 0 deletions web/views/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
import urllib
from functools import wraps
from typing import Union
from six.moves import http_cookies as Cookie
from urllib.parse import urlencode

import rethinkdb as rdb
import tornado.websocket
from logzero import logger
from rethinkdb import r
from tornado import gen
from tornado.platform.asyncio import to_asyncio_future
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.ioloop import IOLoop
from tornado.web import HTTPError, authenticated
Expand Down Expand Up @@ -523,3 +526,102 @@ async def open(self, udid):
return

self.write_message("device is yours")


class CheckMixin(object):
def check_host_port(self):
host = self.get_argument('host', None)
port = self.get_argument('port', None)
if not host or not port:
hcookie = self.request.headers.get('cookie')
if hcookie:
cookie = Cookie.SimpleCookie()
for hcookie_part in hcookie.split(';'):
hcookie_part = hcookie_part.lstrip()
try:
cookie.load(hcookie_part)
except Cookie.CookieError:
logger.warning('Found malformed cookie')
else:
if 'host' in cookie:
host = cookie['host'].value
if 'port' in cookie:
port = cookie['port'].value
return host, port


class AndroidDeviceAtxAgentProxyHandler(CheckMixin, AuthRequestHandler):
""" device atx agent proxy """
async def do_proxy(self, method, *args, **kwargs):
host, port = self.check_host_port()
if not host or not port:
self.set_status(400) # bad request
self.write_json({
"success": False,
"description": "Missing host and port"
})
arguments = self.request.query_arguments # 内部是List[bytes]格式
arguments.pop('host', None)
arguments.pop('port', None)
params = {name: self.get_argument(name) for name in arguments}
try:
if params:
url = f'http://{host}:{port}/{args[0]}?{urlencode(params)}'
else:
url = f'http://{host}:{port}/{args[0]}'
logger.info(f'Forward http {method} from {self.request.uri} <--> {url}')
headers = self.request.headers
response = await tornado.httpclient.AsyncHTTPClient().fetch(
url, method=method, headers=headers, body=self.request.body, allow_nonstandard_methods=True, **kwargs)
self.set_cookie("host", host)
self.set_cookie("port", port)
self.write(response.body)
except Exception as e:
print(e)
self.write_error(500)

async def get(self, *args, **kwargs):
await self.do_proxy('GET', *args, **kwargs)

async def post(self, *args, **kwargs):
await self.do_proxy('POST', *args, **kwargs)


AndroidProviderProxyHandler = AndroidDeviceAtxAgentProxyHandler


class AndroidDeviceWSProxyHandler(CheckMixin, tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
super(AndroidDeviceWSProxyHandler, self).__init__(*args, **kwargs)
self._client = None

def check_origin(self, origin):
return True

async def open(self, *args, **kwargs):
host, port = self.check_host_port()
if not host or not port:
self.write_message("Missing host and port")
self.close()
return

schema = {"http":"ws", "https":"wss"}[self.request.protocol]
if args:
target_url = f'{schema}://{host}:{port}/{args[0]}'
else:
target_url = f'{schema}://{host}:{port}/'
logger.info(f'Forward websocket from {self.request.uri} <--> {target_url}')
self._client = await to_asyncio_future(
tornado.websocket.websocket_connect(target_url, on_message_callback=self.on_target_message))

def on_message(self, message):
if self._client is not None:
self._client.write_message(message, binary=isinstance(message, bytes))

def on_target_message(self, message):
if message:
self.write_message(message, binary=isinstance(message, bytes))

def on_close(self):
if self._client is not None:
self._client.close()