@ -7,119 +7,13 @@ package safesocket
import (
"context"
"fmt"
"net"
"os"
"syscall"
"time"
"golang.org/x/sys/plan9"
)
// Plan 9's devsrv srv(3) is a server registry and
// it is conventionally bound to "/srv" in the default
// namespace. It is "a one level directory for holding
// already open channels to services". Post one end of
// a pipe to "/srv/tailscale.sock" and use the other
// end for communication with a requestor. Plan 9 pipes
// are bidirectional.
type plan9SrvAddr string
func ( sl plan9SrvAddr ) Network ( ) string {
return "/srv"
}
func ( sl plan9SrvAddr ) String ( ) string {
return string ( sl )
}
// There is no net.FileListener for Plan 9 at this time
type plan9SrvListener struct {
name string
srvf * os . File
file * os . File
}
func ( sl * plan9SrvListener ) Accept ( ) ( net . Conn , error ) {
// sl.file is the server end of the pipe that's
// connected to /srv/tailscale.sock
return plan9FileConn { name : sl . name , file : sl . file } , nil
}
func ( sl * plan9SrvListener ) Close ( ) error {
sl . file . Close ( )
return sl . srvf . Close ( )
}
func ( sl * plan9SrvListener ) Addr ( ) net . Addr {
return plan9SrvAddr ( sl . name )
}
type plan9FileConn struct {
name string
file * os . File
}
func ( fc plan9FileConn ) Read ( b [ ] byte ) ( n int , err error ) {
return fc . file . Read ( b )
}
func ( fc plan9FileConn ) Write ( b [ ] byte ) ( n int , err error ) {
return fc . file . Write ( b )
}
func ( fc plan9FileConn ) Close ( ) error {
return fc . file . Close ( )
}
func ( fc plan9FileConn ) LocalAddr ( ) net . Addr {
return plan9SrvAddr ( fc . name )
}
func ( fc plan9FileConn ) RemoteAddr ( ) net . Addr {
return plan9SrvAddr ( fc . name )
}
func ( fc plan9FileConn ) SetDeadline ( t time . Time ) error {
return syscall . EPLAN9
}
func ( fc plan9FileConn ) SetReadDeadline ( t time . Time ) error {
return syscall . EPLAN9
}
func ( fc plan9FileConn ) SetWriteDeadline ( t time . Time ) error {
return syscall . EPLAN9
}
func connect ( _ context . Context , path string ) ( net . Conn , error ) {
f , err := os . OpenFile ( path , os . O_RDWR , 0666 )
if err != nil {
return nil , err
return net . Dial ( "tcp" , "localhost:5252" )
}
return plan9FileConn { name : path , file : f } , nil
}
// Create an entry in /srv, open a pipe, write the
// client end to the entry and return the server
// end of the pipe to the caller. When the server
// end of the pipe is closed, /srv name associated
// with it will be removed (controlled by ORCLOSE flag)
func listen ( path string ) ( net . Listener , error ) {
const O_RCLOSE = 64 // remove on close; should be in plan9 package
var pip [ 2 ] int
err := plan9 . Pipe ( pip [ : ] )
if err != nil {
return nil , err
}
defer plan9 . Close ( pip [ 1 ] )
srvfd , err := plan9 . Create ( path , plan9 . O_WRONLY | plan9 . O_CLOEXEC | O_RCLOSE , 0600 )
if err != nil {
return nil , err
}
srv := os . NewFile ( uintptr ( srvfd ) , path )
_ , err = fmt . Fprintf ( srv , "%d" , pip [ 1 ] )
if err != nil {
return nil , err
}
return & plan9SrvListener { name : path , srvf : srv , file : os . NewFile ( uintptr ( pip [ 0 ] ) , path ) } , nil
return net . Listen ( "tcp" , "localhost:5252" )
}