ish-app / ish

Linux shell for iOS
https://ish.app
Other
17.02k stars 898 forks source link

accept tcp [::]:9999 function not implemented #1889

Open Aquarian-Age opened 2 years ago

Aquarian-Age commented 2 years ago

The file (web service) compiled with Golang on the PC Linux system cannot achieve tcp connection

None of the following three can be connected

http.ListenAndServe("127.0.0.1:9999", nil)
http.ListenAndServe("localhost:9999", nil)
http.ListenAndServe("0.0.0.0:9999", nil)

CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "-s -w" -trimpath -o sjqm-jqh-i386

thumbnail_image

Shihira commented 2 years ago

Upvote. Same problem occurs to me on the latest App Store version 1.2.3

I was trying to get a syncthing client with go 1.20 compiled along running on iSH, whose web-gui depends on net.http. And the server was just unable to accept any connections.

The syncthing in alpinelinux repo works just fine (which I don’t understand why, they should be all using the same net.http), despite some random deadlocks.

ljcucc commented 2 years ago

I have the same issue when I was using cloudflared access to host an access to tunnel...

and I'm using App Store version 1.2.3

$ ./cloudflared access tcp --host
name [some-private-domain] --url 0.0.0.0:2038
2022-10-15T04:54:15Z INF Start Websocket listener host=0.0.0.0: 2038
2022-10-15T04:54:15Z ERR Error on Websocket listener error="accept tcp [::]: 2038: accept: function not implemented"
accept tcp [::]: 2038: accept: function not implemented
birros commented 4 months ago

Update (2024-10-09): The following Go code replaces the default internal/poll.AcceptFunc and internal/poll.Accept4Func functions with a C binding to the native accept and accept4 functions to work around an implementation issue. Since Go v1.23, the linker no longer supports the go:linkname directive for referencing internal symbols out of the box, so -checklinkname=0 must be added to ldflags.

package main

/*
#cgo CFLAGS: -Wall
#include <arpa/inet.h>

int native_accept(int server_fd, struct sockaddr_in *address,
                  socklen_t *addrlen) {
  return accept(server_fd, (struct sockaddr *)address, addrlen);
}

int native_accept4(int server_fd, struct sockaddr_in * address,
                  socklen_t *addrlen, int flags) {
  return accept4(server_fd, (struct sockaddr *)address, addrlen, flags);
}
*/
import "C"

import (
    "fmt"
    "net"
    "net/http"
    "syscall"
    "unsafe"
)

//go:linkname pollAcceptFunc internal/poll.AcceptFunc
var pollAcceptFunc func(int) (int, syscall.Sockaddr, error)

//go:linkname pollAccept4Func internal/poll.Accept4Func
var pollAccept4Func func(int, int) (int, syscall.Sockaddr, error)

//go:linkname syscallAnyToSockaddr syscall.anyToSockaddr
func syscallAnyToSockaddr(rsa *syscall.RawSockaddrAny) (syscall.Sockaddr, error)

func init() {
    pollAcceptFunc = Accept
    pollAccept4Func = Accept4
}

// Replace [internal/poll.AcceptFunc] to fix `accept: function not implemented`
// error on iSH
func Accept(fd int) (nfd int, sa syscall.Sockaddr, err error) {
    var addr syscall.RawSockaddrAny
    var addrLen C.socklen_t = syscall.SizeofSockaddrAny

    newFd, err := C.native_accept(
        C.int(fd),
        (*C.struct_sockaddr_in)(unsafe.Pointer(&addr)),
        &addrLen,
    )
    if newFd < 0 {
        return -1, nil, err
    }

    sa, err = syscallAnyToSockaddr(&addr)
    if err != nil {
        return -1, nil, err
    }

    return int(newFd), sa, nil
}

// Replace [internal/poll.Accept4Func] to fix
// `accept4: function not implemented` error on iSH
func Accept4(fd, flags int) (nfd int, sa syscall.Sockaddr, err error) {
    var addr syscall.RawSockaddrAny
    var addrLen C.socklen_t = syscall.SizeofSockaddrAny

    newFd, err := C.native_accept4(
        C.int(fd),
        (*C.struct_sockaddr_in)(unsafe.Pointer(&addr)),
        &addrLen,
        C.int(flags),
    )
    if newFd < 0 {
        return -1, nil, err
    }

    sa, err = syscallAnyToSockaddr(&addr)
    if err != nil {
        return -1, nil, err
    }

    return int(newFd), sa, nil
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("Hello World!"))
    })

    l, err := net.Listen("tcp", "0.0.0.0:8080")
    if err != nil {
        panic(err)
    }

    fmt.Printf("Listening on %s\n", l.Addr())

    err = http.Serve(l, mux)
    if err != nil {
        panic(err)
    }
}
introspection3 commented 1 month ago

Upvote. Same problem occurs to me on the latest App Store version 1.2.3

introspection3 commented 1 week ago

anybody ?

birros commented 1 week ago

Upvote. Same problem occurs to me on the latest App Store version 1.2.3

I've updated my workaround to support Go 1.23 and tested it with the latest App Store version 1.3.2 of iSH. Theoretically, any Go program compiled with this workaround should no longer encounter an accept(4): function not implemented error.

Hope this will be useful.