mirror of
https://github.com/NoCrypt/migu.git
synced 2026-04-20 08:02:12 +00:00
wip: node-mobile
This commit is contained in:
parent
5cdcfda4a1
commit
65bd321f4a
14 changed files with 122 additions and 1765 deletions
|
|
@ -14,7 +14,8 @@ const config = {
|
|||
},
|
||||
plugins: {
|
||||
SplashScreen: { launchShowDuration: 0 },
|
||||
CapacitorHttp: { enabled: false }
|
||||
CapacitorHttp: { enabled: false },
|
||||
CapacitorNodeJS: { nodeDir: 'nodejs' }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
50
capacitor/config-node.sh
Normal file
50
capacitor/config-node.sh
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash
|
||||
|
||||
# instructions
|
||||
# Install Android NDK
|
||||
# Set $ANDROID_NDK_PATH (example: ~/Android/Sdk/ndk/26.1.10909125)
|
||||
# Download and extract android .zip for nodejs-mobile from https://github.com/nodejs-mobile/nodejs-mobile/releases/tag/v18.17.2
|
||||
# Update LIBNODE_PATH
|
||||
# npm install nodejs-mobile-gyp
|
||||
# install other npm packages like normal
|
||||
# run this script
|
||||
|
||||
toolchain_target_arch=aarch64
|
||||
node_target_arch=arm64
|
||||
android_api_level=22
|
||||
toolchain_folder=$ANDROID_NDK_PATH/toolchains/llvm/prebuilt/linux-x86_64/bin
|
||||
export LIBNODE_PATH=~/Downloads/nodejs-mobile
|
||||
|
||||
export PATH=$toolchain_folder:$PATH
|
||||
|
||||
export CC=$toolchain_folder/${toolchain_target_arch}-linux-android${android_api_level}-clang
|
||||
export CXX=$toolchain_folder/${toolchain_target_arch}-linux-android${android_api_level}-clang++
|
||||
export LINK=$toolchain_folder/${toolchain_target_arch}-linux-android${android_api_level}-clang++
|
||||
export AR=$toolchain_folder/llvm-ar
|
||||
|
||||
export npm_config_verbose=1
|
||||
export npm_config_nodedir=${LIBNODE_PATH}
|
||||
export npm_config_node_gyp=$(pwd)/node_modules/nodejs-mobile-gyp/bin/node-gyp.js
|
||||
export npm_config_arch=${node_target_arch}
|
||||
export npm_config_plaform=android
|
||||
export npm_config_format=make-android
|
||||
export npm_gyp_defines="target_arch=$node_target_arch v8_target_arch=$node_target_arch android_target_arch=$node_target_arch host_os=linux OS=android"
|
||||
|
||||
#mv node_modules ../node_modules.bak
|
||||
# --from-from-source is used by node-pre-gyp
|
||||
npm rebuild --build-from-source
|
||||
# Remove executable permissions from native node modules
|
||||
# find node_modules -iname '*.node' -exec chmod -x '{}' \;
|
||||
|
||||
# buildroot=$(pwd)/ncc
|
||||
# target=arm64-android
|
||||
|
||||
# buildpath="${buildroot}/${target}"
|
||||
# if [ ! -d "${buildpath}" ]; then
|
||||
# mkdir -p "${buildpath}"
|
||||
# fi
|
||||
|
||||
# ncc build --source-map -d --asset-builds --target es2022 -o ${buildpath} src/offline.ts
|
||||
|
||||
# rm -rf node_modules
|
||||
# mv ../node_modules.bak node_modules
|
||||
|
|
@ -42,14 +42,9 @@
|
|||
"@capacitor/core": "^5.5.1",
|
||||
"@capacitor/ios": "^5.5.1",
|
||||
"@capacitor/status-bar": "^5.0.6",
|
||||
"@superfrogbe/cordova-plugin-chrome-apps-sockets-udp": "github:superfrogbe/cordova-plugin-chrome-apps-sockets-udp",
|
||||
"capacitor-default-gateway": "github:funniray/capacitor-default-gateway",
|
||||
"capacitor-dns": "github:funniray/capacitor-dns",
|
||||
"capacitor-os-interfaces-hack": "github:funniray/capacitor-os-interfaces-hack",
|
||||
"capacitor-nodejs": "github:hampoelz/capacitor-nodejs",
|
||||
"capacitor-plugin-safe-area": "^2.0.5",
|
||||
"common": "workspace:*",
|
||||
"cordova-plugin-chrome-apps-common": "^1.0.7",
|
||||
"cordova-plugin-chrome-apps-sockets-tcp": "github:KoenLav/cordova-plugin-chrome-apps-sockets-tcp",
|
||||
"cordova-plugin-navigationbar": "^1.0.31",
|
||||
"cordova-plugin-screen-orientation": "^3.0.4",
|
||||
"es6-promise-plugin": "^4.2.2",
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import { StatusBar, Style } from '@capacitor/status-bar'
|
|||
import { SafeArea } from 'capacitor-plugin-safe-area'
|
||||
import { App } from '@capacitor/app'
|
||||
import { Browser } from '@capacitor/browser'
|
||||
import { ipcRendererUI, main } from './ipc.js'
|
||||
// import { ipcRendererUI, main } from './ipc.js'
|
||||
|
||||
main.on('open', url => Browser.open({ url }))
|
||||
// main.on('open', url => Browser.open({ url }))
|
||||
|
||||
App.addListener('appUrlOpen', ({ url }) => handleProtocol(url))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,466 +0,0 @@
|
|||
// @ts-nocheck
|
||||
/*! chrome-dgram. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
/* global chrome */
|
||||
|
||||
/**
|
||||
* UDP / Datagram Sockets
|
||||
* ======================
|
||||
*
|
||||
* Datagram sockets are available through require('chrome-dgram').
|
||||
*/
|
||||
const EventEmitter = require('events')
|
||||
const series = require('run-series')
|
||||
|
||||
const BIND_STATE_UNBOUND = 0
|
||||
const BIND_STATE_BINDING = 1
|
||||
const BIND_STATE_BOUND = 2
|
||||
|
||||
// Track open sockets to route incoming data (via onReceive) to the right handlers.
|
||||
const sockets = {}
|
||||
|
||||
const noop = () => {}
|
||||
|
||||
// Thorough check for Chrome App since both Edge and Chrome implement dummy chrome object
|
||||
if (typeof chrome?.sockets?.udp === 'object') {
|
||||
chrome.sockets.udp.onReceive.addListener(onReceive)
|
||||
chrome.sockets.udp.onReceiveError.addListener(onReceiveError)
|
||||
}
|
||||
|
||||
function onReceive (info) {
|
||||
if (info.socketId in sockets) {
|
||||
sockets[info.socketId]._onReceive(info)
|
||||
} else {
|
||||
console.error('Unknown socket id: ' + info.socketId)
|
||||
}
|
||||
}
|
||||
|
||||
function onReceiveError (info) {
|
||||
if (info.socketId in sockets) {
|
||||
sockets[info.socketId]._onReceiveError(info.resultCode)
|
||||
} else {
|
||||
console.error('Unknown socket id: ' + info.socketId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dgram.createSocket(type, [callback])
|
||||
*
|
||||
* Creates a datagram Socket of the specified types. Valid types are `udp4`
|
||||
* and `udp6`.
|
||||
*
|
||||
* Takes an optional callback which is added as a listener for message events.
|
||||
*
|
||||
* Call socket.bind if you want to receive datagrams. socket.bind() will bind
|
||||
* to the "all interfaces" address on a random port (it does the right thing
|
||||
* for both udp4 and udp6 sockets). You can then retrieve the address and port
|
||||
* with socket.address().address and socket.address().port.
|
||||
*
|
||||
* @param {string} type Either 'udp4' or 'udp6'
|
||||
* @param {function} listener Attached as a listener to message events.
|
||||
* Optional
|
||||
* @return {Socket} Socket object
|
||||
*/
|
||||
exports.createSocket = function (type, listener) {
|
||||
return new Socket(type, listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* Class: dgram.Socket
|
||||
*
|
||||
* The dgram Socket class encapsulates the datagram functionality. It should
|
||||
* be created via `dgram.createSocket(type, [callback])`.
|
||||
*
|
||||
* Event: 'message'
|
||||
* - msg Buffer object. The message
|
||||
* - rinfo Object. Remote address information
|
||||
* Emitted when a new datagram is available on a socket. msg is a Buffer and
|
||||
* rinfo is an object with the sender's address information and the number
|
||||
* of bytes in the datagram.
|
||||
*
|
||||
* Event: 'listening'
|
||||
* Emitted when a socket starts listening for datagrams. This happens as soon
|
||||
* as UDP sockets are created.
|
||||
*
|
||||
* Event: 'close'
|
||||
* Emitted when a socket is closed with close(). No new message events will
|
||||
* be emitted on this socket.
|
||||
*
|
||||
* Event: 'error'
|
||||
* - exception Error object
|
||||
* Emitted when an error occurs.
|
||||
*/
|
||||
class Socket extends EventEmitter {
|
||||
constructor (options, listener) {
|
||||
super()
|
||||
if (typeof options === 'string') options = { type: options }
|
||||
if (options.type !== 'udp4' && options.type !== 'udp6') throw new Error('Bad socket type specified. Valid types are: udp4')
|
||||
|
||||
if (typeof listener === 'function') this.on('message', listener)
|
||||
|
||||
this._destroyed = false
|
||||
this._bindState = BIND_STATE_UNBOUND
|
||||
this._bindTasks = []
|
||||
}
|
||||
|
||||
/**
|
||||
* socket.bind(port, [address], [callback])
|
||||
*
|
||||
* For UDP sockets, listen for datagrams on a named port and optional address.
|
||||
* If address is not specified, the OS will try to listen on all addresses.
|
||||
* After binding is done, a "listening" event is emitted and the callback(if
|
||||
* specified) is called. Specifying both a "listening" event listener and
|
||||
* callback is not harmful but not very useful.
|
||||
*
|
||||
* A bound datagram socket keeps the node process running to receive
|
||||
* datagrams.
|
||||
*
|
||||
* If binding fails, an "error" event is generated. In rare case (e.g. binding
|
||||
* a closed socket), an Error may be thrown by this method.
|
||||
*
|
||||
* @param {number} port
|
||||
* @param {string} address Optional
|
||||
* @param {function} callback Function with no parameters, Optional. Callback
|
||||
* when binding is done.
|
||||
*/
|
||||
bind (port, address, callback) {
|
||||
if (typeof address === 'function') {
|
||||
callback = address
|
||||
address = undefined
|
||||
}
|
||||
|
||||
if (!address) address = '0.0.0.0'
|
||||
|
||||
if (!port) port = 0
|
||||
|
||||
if (this._bindState !== BIND_STATE_UNBOUND) throw new Error('Socket is already bound')
|
||||
|
||||
this._bindState = BIND_STATE_BINDING
|
||||
|
||||
if (typeof callback === 'function') this.once('listening', callback)
|
||||
|
||||
chrome.sockets.udp.create(createInfo => {
|
||||
this.id = createInfo.socketId
|
||||
|
||||
sockets[this.id] = this
|
||||
|
||||
const bindFns = this._bindTasks.map(({ fn }) => fn)
|
||||
|
||||
series(bindFns, err => {
|
||||
if (err) return this.emit('error', err)
|
||||
chrome.sockets.udp.bind(this.id, address, port, result => {
|
||||
if (result < 0) {
|
||||
this.emit('error', new Error('Socket ' + this.id + ' failed to bind. ' +
|
||||
chrome.runtime.lastError.message))
|
||||
return
|
||||
}
|
||||
chrome.sockets.udp.getInfo(this.id, socketInfo => {
|
||||
if (!socketInfo.localPort || !socketInfo.localAddress) {
|
||||
this.emit('error', new Error('Cannot get local port/address for Socket ' + this.id))
|
||||
return
|
||||
}
|
||||
|
||||
this._port = socketInfo.localPort
|
||||
this._address = socketInfo.localAddress
|
||||
|
||||
this._bindState = BIND_STATE_BOUND
|
||||
this.emit('listening')
|
||||
|
||||
for (const t of this._bindTasks) {
|
||||
t.callback()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to receive new messages and emit `message` events.
|
||||
*/
|
||||
_onReceive (info) {
|
||||
const buf = Buffer.from(new Uint8Array(info.data))
|
||||
const rinfo = {
|
||||
address: info.remoteAddress,
|
||||
family: 'IPv4',
|
||||
port: info.remotePort,
|
||||
size: buf.length
|
||||
}
|
||||
this.emit('message', buf, rinfo)
|
||||
}
|
||||
|
||||
_onReceiveError (resultCode) {
|
||||
this.emit('error', new Error('Socket ' + this.id + ' receive error ' + resultCode))
|
||||
}
|
||||
|
||||
/**
|
||||
* socket.send(buf, offset, length, port, address, [callback])
|
||||
*
|
||||
* For UDP sockets, the destination port and IP address must be
|
||||
* specified. A string may be supplied for the address parameter, and it will
|
||||
* be resolved with DNS. An optional callback may be specified to detect any
|
||||
* DNS errors and when buf may be re-used. Note that DNS lookups will delay
|
||||
* the time that a send takes place, at least until the next tick. The only
|
||||
* way to know for sure that a send has taken place is to use the callback.
|
||||
*
|
||||
* If the socket has not been previously bound with a call to bind, it's
|
||||
* assigned a random port number and bound to the "all interfaces" address
|
||||
* (0.0.0.0 for udp4 sockets, ::0 for udp6 sockets).
|
||||
*
|
||||
* @param {Buffer|Arrayish|string} buf Message to be sent
|
||||
* @param {number} offset Offset in the buffer where the message starts. Optional.
|
||||
* @param {number} length Number of bytes in the message. Optional.
|
||||
* @param {number} port destination port
|
||||
* @param {string} address destination IP
|
||||
* @param {function} callback Callback when message is done being delivered.
|
||||
* Optional.
|
||||
*
|
||||
* Valid combinations:
|
||||
* send(buffer, offset, length, port, address, callback)
|
||||
* send(buffer, offset, length, port, address)
|
||||
* send(buffer, offset, length, port)
|
||||
* send(bufferOrList, port, address, callback)
|
||||
* send(bufferOrList, port, address)
|
||||
* send(bufferOrList, port)
|
||||
*
|
||||
*/
|
||||
send (buffer, offset, length, port, address, callback = noop) {
|
||||
let list
|
||||
const cb = callback || noop
|
||||
|
||||
if (address || (port && typeof port !== 'function')) {
|
||||
buffer = this.sliceBuffer(buffer, offset, length)
|
||||
} else {
|
||||
callback = port
|
||||
port = offset
|
||||
address = length
|
||||
}
|
||||
|
||||
if (!Array.isArray(buffer)) {
|
||||
if (typeof buffer === 'string') {
|
||||
list = [Buffer.from(buffer)]
|
||||
} else if (!(buffer instanceof Uint8Array)) {
|
||||
throw new TypeError('First argument must be a buffer or a string')
|
||||
} else {
|
||||
list = [Buffer.from(buffer)]
|
||||
}
|
||||
} else if (!(list = this.fixBufferList(buffer))) {
|
||||
throw new TypeError('Buffer list arguments must be buffers or strings')
|
||||
}
|
||||
|
||||
port = port >>> 0
|
||||
if (port === 0 || port > 65535) {
|
||||
throw new RangeError('Port should be > 0 and < 65536')
|
||||
}
|
||||
|
||||
if (this._bindState === BIND_STATE_UNBOUND) this.bind(0)
|
||||
|
||||
// If the socket hasn't been bound yet, push the outbound packet onto the
|
||||
// send queue and send after binding is complete.
|
||||
if (this._bindState !== BIND_STATE_BOUND) {
|
||||
// If the send queue hasn't been initialized yet, do it, and install an
|
||||
// event handler that flishes the send queue after binding is done.
|
||||
if (!this._sendQueue) {
|
||||
this._sendQueue = []
|
||||
this.once('listening', () => {
|
||||
// Flush the send queue.
|
||||
for (let i = 0; i < this._sendQueue.length; i++) {
|
||||
this.send.apply(this, this._sendQueue[i])
|
||||
}
|
||||
this._sendQueue = undefined
|
||||
})
|
||||
}
|
||||
this._sendQueue.push([buffer, offset, length, port, address, callback])
|
||||
return
|
||||
}
|
||||
|
||||
const ab = Buffer.concat(list).buffer
|
||||
|
||||
chrome.sockets.udp.send(this.id, ab, address, port, sendInfo => {
|
||||
if (sendInfo.resultCode < 0) {
|
||||
const err = new Error('Socket ' + this.id + ' send error ' + sendInfo.resultCode)
|
||||
cb(err)
|
||||
this.emit('error', err)
|
||||
} else {
|
||||
cb(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
sliceBuffer (buffer, offset, length) {
|
||||
buffer = Buffer.from(buffer)
|
||||
|
||||
offset = offset >>> 0
|
||||
length = length >>> 0
|
||||
|
||||
// assuming buffer is browser implementation (`buffer` package on npm)
|
||||
let buf = buffer.buffer
|
||||
if (buffer.byteOffset || buffer.byteLength !== buf.byteLength) {
|
||||
buf = buf.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength)
|
||||
}
|
||||
if (offset || length !== buffer.length) {
|
||||
buf = buf.slice(offset, length)
|
||||
}
|
||||
|
||||
return Buffer.from(buf)
|
||||
}
|
||||
|
||||
fixBufferList (list) {
|
||||
const newlist = new Array(list.length)
|
||||
|
||||
for (let i = 0, l = list.length; i < l; i++) {
|
||||
const buf = list[i]
|
||||
if (typeof buf === 'string') {
|
||||
newlist[i] = Buffer.from(buf)
|
||||
} else if (!(buf instanceof Uint8Array)) {
|
||||
return null
|
||||
} else {
|
||||
newlist[i] = Buffer.from(buf)
|
||||
}
|
||||
}
|
||||
|
||||
return newlist
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the underlying socket and stop listening for data on it.
|
||||
*/
|
||||
close () {
|
||||
if (this._destroyed) return
|
||||
|
||||
delete sockets[this.id]
|
||||
chrome.sockets.udp.close(this.id)
|
||||
this._destroyed = true
|
||||
|
||||
this.emit('close')
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object containing the address information for a socket. For UDP
|
||||
* sockets, this object will contain address, family and port.
|
||||
*
|
||||
* @return {Object} information
|
||||
*/
|
||||
address () {
|
||||
return {
|
||||
address: this._address,
|
||||
port: this._port,
|
||||
family: 'IPv4'
|
||||
}
|
||||
}
|
||||
|
||||
setBroadcast (flag) {
|
||||
// No chrome.sockets equivalent
|
||||
}
|
||||
|
||||
setTTL (ttl) {
|
||||
// No chrome.sockets equivalent
|
||||
}
|
||||
|
||||
// NOTE: Multicast code is untested. Pull requests accepted for bug fixes and to
|
||||
// add tests!
|
||||
/**
|
||||
* Sets the IP_MULTICAST_TTL socket option. TTL stands for "Time to Live," but
|
||||
* in this context it specifies the number of IP hops that a packet is allowed
|
||||
* to go through, specifically for multicast traffic. Each router or gateway
|
||||
* that forwards a packet decrements the TTL. If the TTL is decremented to 0
|
||||
* by a router, it will not be forwarded.
|
||||
*
|
||||
* The argument to setMulticastTTL() is a number of hops between 0 and 255.
|
||||
* The default on most systems is 1.
|
||||
*
|
||||
* NOTE: The Chrome version of this function is async, whereas the node
|
||||
* version is sync. Keep this in mind.
|
||||
*
|
||||
* @param {number} ttl
|
||||
* @param {function} callback CHROME-SPECIFIC: Called when the configuration
|
||||
* operation is done.
|
||||
*/
|
||||
setMulticastTTL (ttl, callback = noop) {
|
||||
const setMulticastTTL = callback => {
|
||||
chrome.sockets.udp.setMulticastTimeToLive(this.id, ttl, callback)
|
||||
}
|
||||
if (this._bindState === BIND_STATE_BOUND) {
|
||||
setMulticastTTL(callback)
|
||||
} else {
|
||||
this._bindTasks.push({
|
||||
fn: setMulticastTTL,
|
||||
callback
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or clears the IP_MULTICAST_LOOP socket option. When this option is
|
||||
* set, multicast packets will also be received on the local interface.
|
||||
*
|
||||
* NOTE: The Chrome version of this function is async, whereas the node
|
||||
* version is sync. Keep this in mind.
|
||||
*
|
||||
* @param {boolean} flag
|
||||
* @param {function} callback CHROME-SPECIFIC: Called when the configuration
|
||||
* operation is done.
|
||||
*/
|
||||
setMulticastLoopback (flag, callback = noop) {
|
||||
const setMulticastLoopback = callback => {
|
||||
chrome.sockets.udp.setMulticastLoopbackMode(this.id, flag, callback)
|
||||
}
|
||||
if (this._bindState === BIND_STATE_BOUND) {
|
||||
setMulticastLoopback(callback)
|
||||
} else {
|
||||
this._bindTasks.push({
|
||||
fn: setMulticastLoopback,
|
||||
callback
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the kernel to join a multicast group with IP_ADD_MEMBERSHIP socket
|
||||
* option.
|
||||
*
|
||||
* If multicastInterface is not specified, the OS will try to add membership
|
||||
* to all valid interfaces.
|
||||
*
|
||||
* NOTE: The Chrome version of this function is async, whereas the node
|
||||
* version is sync. Keep this in mind.
|
||||
*
|
||||
* @param {string} multicastAddress
|
||||
* @param {string} [multicastInterface] Optional
|
||||
* @param {function} callback CHROME-SPECIFIC: Called when the configuration
|
||||
* operation is done.
|
||||
*/
|
||||
addMembership (multicastAddress, multicastInterface, callback = noop) {
|
||||
chrome.sockets.udp.joinGroup(this.id, multicastAddress, callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Opposite of addMembership - tells the kernel to leave a multicast group
|
||||
* with IP_DROP_MEMBERSHIP socket option. This is automatically called by the
|
||||
* kernel when the socket is closed or process terminates, so most apps will
|
||||
* never need to call this.
|
||||
*
|
||||
* NOTE: The Chrome version of this function is async, whereas the node
|
||||
* version is sync. Keep this in mind.
|
||||
*
|
||||
* If multicastInterface is not specified, the OS will try to drop membership
|
||||
* to all valid interfaces.
|
||||
*
|
||||
* @param {[type]} multicastAddress
|
||||
* @param {[type]} multicastInterface Optional
|
||||
* @param {function} callback CHROME-SPECIFIC: Called when the configuration
|
||||
* operation is done.
|
||||
*/
|
||||
dropMembership (multicastAddress, multicastInterface, callback = noop) {
|
||||
chrome.sockets.udp.leaveGroup(this.id, multicastAddress, callback)
|
||||
}
|
||||
|
||||
unref () {
|
||||
// No chrome.sockets equivalent
|
||||
}
|
||||
|
||||
ref () {
|
||||
// No chrome.sockets equivalent
|
||||
}
|
||||
}
|
||||
|
||||
exports.Socket = Socket
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +0,0 @@
|
|||
import { gateway4async } from 'capacitor-default-gateway'
|
||||
|
||||
let v4Gateway
|
||||
|
||||
export const v4 = () => {}
|
||||
v4.sync = () => v4Gateway
|
||||
export const ready = gateway4async().then(gateway => {
|
||||
v4Gateway = gateway
|
||||
})
|
||||
|
|
@ -1,27 +1,27 @@
|
|||
import EventEmitter from 'events'
|
||||
import { ready } from './gateway.js'
|
||||
import { NodeJS } from 'capacitor-nodejs'
|
||||
|
||||
export const ipcRendererUI = new EventEmitter()
|
||||
|
||||
export const main = new EventEmitter()
|
||||
let portListener
|
||||
|
||||
export default {
|
||||
emit: (event, data) => {
|
||||
main.emit(event, data)
|
||||
if (event === 'portRequest') return portRequest()
|
||||
NodeJS.send({ eventName: event, args: [data] })
|
||||
},
|
||||
on: (event, callback) => {
|
||||
ipcRendererUI.on(event, (...args) => callback(...args))
|
||||
NodeJS.addListener(event, ({ args }) => callback(...args))
|
||||
if (event === 'port') portListener = callback
|
||||
},
|
||||
once: (event, callback) => {
|
||||
ipcRendererUI.once(event, (...args) => callback(...args))
|
||||
const handle = NodeJS.addListener(event, ({ args }) => {
|
||||
NodeJS.removeListener(handle)
|
||||
callback(...args)
|
||||
})
|
||||
},
|
||||
off: event => {
|
||||
ipcRendererUI.removeAllListeners(event)
|
||||
NodeJS.removeAllListeners(event)
|
||||
}
|
||||
}
|
||||
|
||||
main.on('portRequest', portRequest)
|
||||
|
||||
async function portRequest (data) {
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
globalThis.port = {
|
||||
|
|
@ -32,16 +32,12 @@ async function portRequest (data) {
|
|||
port2.postMessage(a, b)
|
||||
}
|
||||
}
|
||||
await globalThis.controller
|
||||
await globalThis.prefetchNetworkInterfaces
|
||||
await ready
|
||||
await NodeJS.whenReady()
|
||||
await new Promise(resolve => setTimeout(() => resolve(), 50))
|
||||
ipcRendererUI.emit('port', { ports: [port2] })
|
||||
ipcRendererWebTorrent.emit('port', { ports: [port1] })
|
||||
portListener({ ports: [port2] })
|
||||
NodeJS.send({ eventName: 'port', args: [{ ports: [port1] }] })
|
||||
}
|
||||
|
||||
export const ipcRendererWebTorrent = new EventEmitter()
|
||||
|
||||
const [_platform, arch] = navigator.platform.split(' ')
|
||||
|
||||
globalThis.version = {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,10 @@
|
|||
import './webtorrent.js'
|
||||
import './capacitor.js'
|
||||
import TorrentClient from 'common/modules/webtorrent.js'
|
||||
import { statfs } from 'fs/promises'
|
||||
import { channel } from 'bridge'
|
||||
|
||||
async function storageQuota (directory) {
|
||||
const { bsize, bavail } = await statfs(directory)
|
||||
return bsize * bavail
|
||||
}
|
||||
|
||||
globalThis.client = new TorrentClient(channel, storageQuota, 'browser')
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ export const SUPPORTS = {
|
|||
offscreenRender: false,
|
||||
update: false,
|
||||
angle: false,
|
||||
doh: false,
|
||||
doh: true,
|
||||
dht: true,
|
||||
discord: false,
|
||||
torrentPort: false,
|
||||
torrentPort: true,
|
||||
torrentPath: false,
|
||||
torrentPersist: false
|
||||
torrentPersist: true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
import TorrentClient from 'common/modules/webtorrent.js'
|
||||
import { ipcRendererWebTorrent } from './ipc.js'
|
||||
import { prefetchNetworkInterfaces } from 'os'
|
||||
import { ready } from './gateway.js'
|
||||
|
||||
globalThis.chrome.runtime = { lastError: false, id: 'something' }
|
||||
|
||||
const controller = (async () => {
|
||||
const reg = await navigator.serviceWorker.register(new URL('webtorrent/dist/sw.min.js', import.meta.url))
|
||||
|
||||
const worker = reg.active || reg.waiting || reg.installing
|
||||
if (!worker) throw new Error('No worker registration')
|
||||
return new Promise(resolve => {
|
||||
function checkState ({ state }) {
|
||||
if (state === 'activated') {
|
||||
resolve(reg)
|
||||
return true
|
||||
}
|
||||
}
|
||||
if (!checkState(worker)) worker.addEventListener('statechange', ({ target }) => checkState(target))
|
||||
})
|
||||
})()
|
||||
globalThis.prefetchNetworkInterfaces = await prefetchNetworkInterfaces()
|
||||
globalThis.controller = controller
|
||||
|
||||
async function storageQuota () {
|
||||
const { quota, usage } = await navigator.storage.estimate()
|
||||
return quota - usage
|
||||
}
|
||||
|
||||
await prefetchNetworkInterfaces
|
||||
await ready
|
||||
|
||||
globalThis.client = new TorrentClient(ipcRendererWebTorrent, storageQuota, 'browser', controller, { torrentPort: Math.floor(Math.random() * 65535 + 1) })
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
const webpack = require('webpack')
|
||||
const commonConfig = require('common/webpack.config.cjs')
|
||||
const { merge } = require('webpack-merge')
|
||||
const { join, resolve } = require('path')
|
||||
|
|
@ -7,57 +6,41 @@ const mode = process.env.NODE_ENV?.trim() || 'development'
|
|||
|
||||
/** @type {import('webpack').Configuration} */
|
||||
const capacitorConfig = {
|
||||
devtool: 'source-map',
|
||||
entry: [join(__dirname, 'src', 'main.js')],
|
||||
output: {
|
||||
path: join(__dirname, 'build', 'nodejs'),
|
||||
filename: 'index.js'
|
||||
},
|
||||
mode,
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
process: 'webtorrent/polyfills/process-fast.js',
|
||||
Buffer: ['buffer', 'Buffer']
|
||||
}),
|
||||
new webpack.DefinePlugin({ global: 'globalThis' })
|
||||
],
|
||||
externals: {
|
||||
'utp-native': 'require("utp-native")',
|
||||
bridge: 'require("bridge")'
|
||||
},
|
||||
resolve: {
|
||||
aliasFields: [],
|
||||
mainFields: ['module', 'main', 'node'],
|
||||
alias: {
|
||||
wrtc: false,
|
||||
'bittorrent-tracker/lib/client/http-tracker.js': resolve('../node_modules/bittorrent-tracker/lib/client/http-tracker.js')
|
||||
}
|
||||
},
|
||||
target: 'node',
|
||||
devServer: {
|
||||
devMiddleware: { writeToDisk: true },
|
||||
devMiddleware: {
|
||||
writeToDisk: true
|
||||
},
|
||||
hot: true,
|
||||
client: {
|
||||
overlay: { errors: true, warnings: false, runtimeErrors: false }
|
||||
},
|
||||
port: 5001
|
||||
port: 5000
|
||||
}
|
||||
}
|
||||
|
||||
const alias = {
|
||||
fs: false,
|
||||
ws: false,
|
||||
'default-gateway': join(__dirname, 'src', 'gateway.js'),
|
||||
'load-ip-set': false,
|
||||
'node-fetch': false,
|
||||
'webtorrent/lib/utp.cjs': false,
|
||||
'@/modules/ipc.js': join(__dirname, 'src', 'ipc.js'),
|
||||
'@/modules/support.js': join(__dirname, 'src', 'support.js'),
|
||||
net: join(__dirname, 'src', 'chrome-net.js'),
|
||||
dgram: join(__dirname, 'src', 'chrome-dgram.js'),
|
||||
os: 'capacitor-os-interfaces-hack',
|
||||
dns: 'capacitor-dns',
|
||||
http: 'stream-http',
|
||||
https: 'stream-http',
|
||||
'utp-native': false,
|
||||
socks: false,
|
||||
assert: 'assert',
|
||||
ut_pex: 'ut_pex',
|
||||
path: 'path-esm',
|
||||
'fs-chunk-store': 'hybrid-chunk-store',
|
||||
stream: 'stream-browserify',
|
||||
timers: 'timers-browserify',
|
||||
crypto: 'crypto-browserify',
|
||||
buffer: 'buffer',
|
||||
'@silentbot1/nat-api': '@silentbot1/nat-api',
|
||||
'bittorrent-tracker': 'bittorrent-tracker',
|
||||
querystring: 'querystring',
|
||||
zlib: 'webtorrent/polyfills/inflate-sync-web.js',
|
||||
'bittorrent-tracker/server.js': false,
|
||||
'cross-fetch-ponyfill': resolve('../node_modules/cross-fetch-ponyfill/browser.js'),
|
||||
'abort-controller': false,
|
||||
'bittorrent-tracker/lib/client/http-tracker.js': resolve('../node_modules/bittorrent-tracker/lib/client/http-tracker.js')
|
||||
'@/modules/support.js': join(__dirname, 'src', 'support.js')
|
||||
}
|
||||
|
||||
module.exports = merge(commonConfig(__dirname, alias, 'node', 'index'), capacitorConfig)
|
||||
module.exports = [capacitorConfig, merge(commonConfig(__dirname, alias, 'browser', 'index'), { entry: [join(__dirname, 'src', 'capacitor.js')] })]
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ try {
|
|||
export default class TorrentClient extends WebTorrent {
|
||||
static excludedErrorMessages = ['WebSocket', 'User-Initiated Abort, reason=', 'Connection failed.']
|
||||
|
||||
constructor (ipc, storageQuota, serverMode, controller, settingOverrides = {}) {
|
||||
constructor (ipc, storageQuota, serverMode, settingOverrides = {}, controller) {
|
||||
const settings = { ...defaults, ...storedSettings, ...settingOverrides }
|
||||
super({
|
||||
dht: !settings.torrentDHT,
|
||||
|
|
|
|||
|
|
@ -86,6 +86,9 @@ importers:
|
|||
capacitor-dns:
|
||||
specifier: github:funniray/capacitor-dns
|
||||
version: github.com/funniray/capacitor-dns/6362cd1ad0a6b9b5bdbdc9fee3fba4c8dae91e16(@capacitor/core@5.5.1)
|
||||
capacitor-nodejs:
|
||||
specifier: github:hampoelz/capacitor-nodejs
|
||||
version: github.com/hampoelz/capacitor-nodejs/3ee9d8d1d0266c228249005f73a2403d551d3aac(@capacitor/core@5.5.1)
|
||||
capacitor-os-interfaces-hack:
|
||||
specifier: github:funniray/capacitor-os-interfaces-hack
|
||||
version: github.com/funniray/capacitor-os-interfaces-hack/95a51afe9dee88b3ae8df4b1b96fd106c1655954(@capacitor/core@5.5.1)
|
||||
|
|
@ -9095,6 +9098,17 @@ packages:
|
|||
'@capacitor/core': 5.5.1
|
||||
dev: false
|
||||
|
||||
github.com/hampoelz/capacitor-nodejs/3ee9d8d1d0266c228249005f73a2403d551d3aac(@capacitor/core@5.5.1):
|
||||
resolution: {tarball: https://codeload.github.com/hampoelz/capacitor-nodejs/tar.gz/3ee9d8d1d0266c228249005f73a2403d551d3aac}
|
||||
id: github.com/hampoelz/capacitor-nodejs/3ee9d8d1d0266c228249005f73a2403d551d3aac
|
||||
name: capacitor-nodejs
|
||||
version: 1.0.0-beta.6
|
||||
peerDependencies:
|
||||
'@capacitor/core': ^5.0.0
|
||||
dependencies:
|
||||
'@capacitor/core': 5.5.1
|
||||
dev: false
|
||||
|
||||
github.com/superfrogbe/cordova-plugin-chrome-apps-sockets-udp/4b740017299c81cfc7d5b49c7d6122a6650b57d4:
|
||||
resolution: {tarball: https://codeload.github.com/superfrogbe/cordova-plugin-chrome-apps-sockets-udp/tar.gz/4b740017299c81cfc7d5b49c7d6122a6650b57d4}
|
||||
name: '@superfrogbe/cordova-plugin-chrome-apps-sockets-udp'
|
||||
|
|
|
|||
Loading…
Reference in a new issue