-
Notifications
You must be signed in to change notification settings - Fork 43
.,ruby: enable accept to be called as TsnetAccept & fix gem #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -39,8 +39,7 @@ module Libtailscale | |||||||||||||||||
| attach_function :TsnetSetLogFD, [:int, :int], :int | ||||||||||||||||||
| attach_function :TsnetDial, [:int, :string, :string, :pointer], :int, blocking: true | ||||||||||||||||||
| attach_function :TsnetListen, [:int, :string, :string, :pointer], :int | ||||||||||||||||||
| attach_function :close, [:int], :int | ||||||||||||||||||
| attach_function :tailscale_accept, [:int, :pointer], :int, blocking: true | ||||||||||||||||||
| attach_function :TsnetAccept, [:int, :pointer], :int, blocking: true | ||||||||||||||||||
| attach_function :TsnetErrmsg, [:int, :pointer, :size_t], :int | ||||||||||||||||||
| attach_function :TsnetLoopback, [:int, :pointer, :size_t, :pointer, :pointer], :int | ||||||||||||||||||
| end | ||||||||||||||||||
|
|
@@ -86,15 +85,19 @@ def initialize(ts, listener) | |||||||||||||||||
| # write. | ||||||||||||||||||
| def accept | ||||||||||||||||||
| @ts.assert_open | ||||||||||||||||||
| lio = IO.for_fd(@listener) | ||||||||||||||||||
| until IO.select([lio]).first.any? | ||||||||||||||||||
| @ts.assert_open | ||||||||||||||||||
|
Comment on lines
+89
to
+90
|
||||||||||||||||||
| until IO.select([lio]).first.any? | |
| @ts.assert_open | |
| loop do | |
| # Wait briefly for the listener to become readable so we can | |
| # periodically re-check that the server is still open. | |
| readable, = IO.select([lio], nil, nil, 0.1) | |
| @ts.assert_open | |
| break if readable && !readable.empty? |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,6 +23,7 @@ def test_that_it_has_a_version_number | |||||||||||||||||||
| def test_listen_sorta_works | ||||||||||||||||||||
| ts = newts | ||||||||||||||||||||
| ts.up | ||||||||||||||||||||
| wait_status_running ts | ||||||||||||||||||||
| s = ts.listen("tcp", ":1999") | ||||||||||||||||||||
| s.close | ||||||||||||||||||||
| ts.close | ||||||||||||||||||||
|
|
@@ -31,18 +32,41 @@ def test_listen_sorta_works | |||||||||||||||||||
| def test_dial_sorta_works | ||||||||||||||||||||
| ts = newts | ||||||||||||||||||||
| ts.up | ||||||||||||||||||||
| wait_status_running ts | ||||||||||||||||||||
| c = ts.dial("udp", "100.100.100.100:53") | ||||||||||||||||||||
| c.close | ||||||||||||||||||||
| ts.close | ||||||||||||||||||||
| end | ||||||||||||||||||||
|
|
||||||||||||||||||||
| def test_listen_accept_dial_close | ||||||||||||||||||||
| ts = newts | ||||||||||||||||||||
| ts.up | ||||||||||||||||||||
| wait_status_running ts | ||||||||||||||||||||
| hn = ts.local_api.status["Self"]["TailscaleIPs"][0] | ||||||||||||||||||||
| s = ts.listen "tcp", "#{hn}:1999" | ||||||||||||||||||||
| c = ts.dial "tcp", "#{hn}:1999" | ||||||||||||||||||||
| ss = s.accept | ||||||||||||||||||||
| c.write "hello" | ||||||||||||||||||||
| assert_equal "hello", ss.read(5) | ||||||||||||||||||||
| ss.write "world" | ||||||||||||||||||||
| assert_equal "world", c.read(5) | ||||||||||||||||||||
| ss.close | ||||||||||||||||||||
| c.close | ||||||||||||||||||||
| ts.close | ||||||||||||||||||||
| end | ||||||||||||||||||||
|
Comment on lines
+41
to
+56
|
||||||||||||||||||||
|
|
||||||||||||||||||||
| def wait_status_running ts | ||||||||||||||||||||
| while ts.local_api.status["BackendState"] != "Running" | ||||||||||||||||||||
|
||||||||||||||||||||
| while ts.local_api.status["BackendState"] != "Running" | |
| timeout_seconds = 30 | |
| deadline = Time.now + timeout_seconds | |
| loop do | |
| status = ts.local_api.status | |
| return if status["BackendState"] == "Running" | |
| if Time.now > deadline | |
| flunk "BackendState did not reach 'Running' within #{timeout_seconds} seconds. Last status: #{status.inspect}" | |
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ import ( | |
| "syscall" | ||
| "unsafe" | ||
|
|
||
| "golang.org/x/sys/unix" | ||
| "tailscale.com/hostinfo" | ||
| "tailscale.com/ipn" | ||
| "tailscale.com/tsnet" | ||
|
|
@@ -292,6 +293,41 @@ func TsnetListen(sd C.int, network, addr *C.char, listenerOut *C.int) C.int { | |
| return 0 | ||
| } | ||
|
|
||
| //export TsnetAccept | ||
| func TsnetAccept(listenerFd C.int, connOut *C.int) C.int { | ||
| listeners.mu.Lock() | ||
| ln := listeners.m[listenerFd] | ||
| listeners.mu.Unlock() | ||
|
|
||
| if ln == nil { | ||
| return C.EBADF | ||
| } | ||
|
|
||
| buf := make([]byte, unix.CmsgLen(int(unsafe.Sizeof((C.int)(0))))) | ||
| _, oobn, _, _, err := syscall.Recvmsg(int(listenerFd), nil, buf, 0) | ||
| if err != nil { | ||
| return ln.s.recErr(err) | ||
| } | ||
|
|
||
| scms, err := syscall.ParseSocketControlMessage(buf[:oobn]) | ||
| if err != nil { | ||
| return ln.s.recErr(err) | ||
| } | ||
| if len(scms) != 1 { | ||
| return ln.s.recErr(fmt.Errorf("libtailscale: got %d control messages, want 1", len(scms))) | ||
| } | ||
| fds, err := syscall.ParseUnixRights(&scms[0]) | ||
|
Comment on lines
+306
to
+319
|
||
| if err != nil { | ||
| return ln.s.recErr(err) | ||
| } | ||
| if len(fds) != 1 { | ||
| return ln.s.recErr(fmt.Errorf("libtailscale: got %d FDs, want 1", len(fds))) | ||
| } | ||
| *connOut = (C.int)(fds[0]) | ||
|
|
||
| return 0 | ||
| } | ||
|
|
||
| func newConn(s *server, netConn net.Conn, connOut *C.int) error { | ||
| fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0) | ||
| if err != nil { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IO.for_fd defaults to autoclose=true; the temporary
liocreated here can be garbage-collected afteracceptreturns, which would close the underlying listener FD unexpectedly. Use IO.for_fd(@Listener, autoclose: false) (or store a persistent IO wrapper on the Listener instance and close it in #close) so GC can’t close the listener.