Skip to content

Instantly share code, notes, and snippets.

@kostix
Created February 25, 2022 19:33
Show Gist options
  • Save kostix/87b94e938cf1c35a660e21bc5424f4c3 to your computer and use it in GitHub Desktop.
Save kostix/87b94e938cf1c35a660e21bc5424f4c3 to your computer and use it in GitHub Desktop.
module sockint
go 1.15
$ 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
$
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