Created
February 25, 2022 19:33
-
-
Save kostix/87b94e938cf1c35a660e21bc5424f4c3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module sockint | |
go 1.15 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ GOOS=windows go build | |
$ wine sockint.exe | |
listening on: 127.0.0.1:53363 | |
Accepted from: 127.0.0.1:45079 | |
I'm a door with 184 | |
wrote: 7 <nil> | |
client: got: hello | |
door finished: <nil> | |
^C | |
$ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"io" | |
"log" | |
"net" | |
"os" | |
"os/exec" | |
"strconv" | |
"syscall" | |
) | |
func main() { | |
log.SetFlags(0) | |
var doorHandle uint64 | |
flag.Uint64Var(&doorHandle, "door", 0, "become a door with the specified handle") | |
flag.Parse() | |
if doorHandle != 0 { | |
serveAsDoor(doorHandle) | |
return | |
} | |
addr, err := net.ResolveTCPAddr("tcp", "localhost:0") | |
if err != nil { | |
log.Fatal(err) | |
} | |
conn, err := net.ListenTCP("tcp", addr) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println("listening on:", conn.Addr()) | |
go connectAsClient(conn.Addr().(*net.TCPAddr)) | |
for { | |
client, err := conn.AcceptTCP() | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println("Accepted from:", client.RemoteAddr()) | |
go serve(client) | |
} | |
} | |
func serve(conn *net.TCPConn) { | |
defer func() { | |
err := conn.Close() | |
if err != nil { | |
log.Println("warn, error closing ", conn.RemoteAddr(), ":", err) | |
} | |
}() | |
handle, err := getInheritedHandle(conn) | |
if err != nil { | |
log.Fatal(err) | |
} | |
cmd := exec.Command(os.Args[0], | |
"-door", strconv.FormatUint(uint64(handle), 10)) | |
cmd.Stdin = os.Stdin | |
cmd.Stdout = os.Stdout | |
cmd.Stderr = os.Stderr | |
err = cmd.Run() | |
log.Println("door finished:", err) | |
} | |
func getInheritedHandle(conn *net.TCPConn) (syscall.Handle, error) { | |
rc, err := conn.SyscallConn() | |
if err != nil { | |
return 0, fmt.Errorf("failed to get raw conn: %s", err) | |
} | |
var ( | |
handle syscall.Handle | |
ctrlErr error | |
) | |
err = rc.Control(func(fd uintptr) { | |
handle = syscall.Handle(fd) | |
ctrlErr = syscall.SetHandleInformation( | |
handle, syscall.HANDLE_FLAG_INHERIT, syscall.HANDLE_FLAG_INHERIT) | |
}) | |
if err != nil { | |
return 0, fmt.Errorf("failed to call Control: %s", err) | |
} | |
if ctrlErr != nil { | |
return 0, fmt.Errorf("failed to set inherited: %s", ctrlErr) | |
} | |
return handle, nil | |
} | |
func serveAsDoor(hval uint64) { | |
handle := syscall.Handle(uintptr(hval)) | |
log.Println("I'm a door with ", handle) | |
n, err := syscall.Write(handle, []byte("hello\r\n")) | |
log.Println("wrote:", n, err) | |
} | |
func connectAsClient(dst *net.TCPAddr) { | |
conn, err := net.DialTCP("tcp", nil, dst) | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer func() { | |
err := conn.Close() | |
if err != nil { | |
log.Println("warn, error closing client conn:", err) | |
} | |
}() | |
var data [10]byte | |
for { | |
n, err := conn.Read(data[:]) | |
if err == io.EOF { | |
break | |
} | |
if n > 0 { | |
log.Println("client: got: ", string(data[:n])) | |
} | |
if err != nil { | |
log.Println("client: error reading:", err) | |
break | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment