Browse Source
Optimized slider captcha solver to avoid CPU/RAM-heavy image rendering. Added legacy TCP accept support specifically for iSH on linux/386 arch. Fixed 'accept4: function not implemented' error in VLESS mode on iSH.pull/162/head
4 changed files with 154 additions and 40 deletions
@ -0,0 +1,74 @@ |
|||
//go:build linux && 386
|
|||
package main |
|||
|
|||
import ( |
|||
"net" |
|||
"os" |
|||
"syscall" |
|||
"time" |
|||
"unsafe" |
|||
) |
|||
|
|||
type ishListener struct { |
|||
net.Listener |
|||
fd int |
|||
} |
|||
|
|||
// wrapISHListener overrides the standard net.Listener with a legacy syscall listener
|
|||
// designed specifically for the iSH simulator on iOS, which lacks modern `accept4`.
|
|||
func wrapISHListener(ln net.Listener) (net.Listener, error) { |
|||
tl, ok := ln.(*net.TCPListener) |
|||
if !ok { |
|||
return ln, nil |
|||
} |
|||
f, err := tl.File() |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return &ishListener{Listener: ln, fd: int(f.Fd())}, nil |
|||
} |
|||
|
|||
func (l *ishListener) Accept() (net.Conn, error) { |
|||
for { |
|||
addr := make([]byte, 128) |
|||
addrlen := uintptr(128) |
|||
|
|||
// i386 network syscalls are multiplexed via socketcall (102).
|
|||
// SYS_ACCEPT is subcall 5.
|
|||
args := [3]uintptr{uintptr(l.fd), uintptr(unsafe.Pointer(&addr[0])), uintptr(unsafe.Pointer(&addrlen))} |
|||
|
|||
r1, _, errno := syscall.Syscall(102, 5, uintptr(unsafe.Pointer(&args)), 0) |
|||
if errno != 0 { |
|||
if errno == syscall.EAGAIN || errno == syscall.EINTR || errno == syscall.EWOULDBLOCK { |
|||
time.Sleep(50 * time.Millisecond) // Just in case it's non-blocking somehow
|
|||
continue |
|||
} |
|||
return nil, errno |
|||
} |
|||
|
|||
nfd := int(r1) |
|||
|
|||
// Wrap raw FD into os.File, then into a net.Conn.
|
|||
// fileConn duplicates the fd again.
|
|||
f := os.NewFile(uintptr(nfd), "ish-conn") |
|||
conn, err := net.FileConn(f) |
|||
f.Close() |
|||
|
|||
if err != nil { |
|||
syscall.Close(nfd) |
|||
return nil, err |
|||
} |
|||
|
|||
return conn, nil |
|||
} |
|||
} |
|||
|
|||
func (l *ishListener) Close() error { |
|||
err1 := syscall.Close(l.fd) |
|||
err2 := l.Listener.Close() |
|||
if err1 != nil { |
|||
return err1 |
|||
} |
|||
return err2 |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
//go:build !(linux && 386)
|
|||
package main |
|||
|
|||
import "net" |
|||
|
|||
// wrapISHListener is a no-op for architectures that don't need the legacy socketcall accept bypass.
|
|||
func wrapISHListener(ln net.Listener) (net.Listener, error) { |
|||
return ln, nil |
|||
} |
|||
Loading…
Reference in new issue