At least with experimental cinnamon w/ xwayland there is a minor bug: DISPLAY may be set to :1, despite xwayland listening on :0 in this case connections to :1 will indicate not ready/retry in this case to mimic most X11 libraries try :0 if we get this on :1, or :1 if we are on :0 otherwise we will retry the current DISPLAY requested to be sure this is a valid approch we also check `xset q` this must return as working with the original display to try the other one
132 lines
3.0 KiB
Go
132 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
"x11proxy/x11probe"
|
|
)
|
|
|
|
const version = "0.1"
|
|
|
|
var (
|
|
overrideDisplay = flag.String("display", "", "Override DISPLAY")
|
|
overrideSocket = flag.String("proxy-socket", "/tmp/.X11-unix/X5", "Proxy socket path")
|
|
showVersion = flag.Bool("version", false, "Show version and exit")
|
|
)
|
|
|
|
func init() {
|
|
flag.Usage = func() {
|
|
fmt.Fprintf(os.Stderr, "Usage of %s:\n\n", os.Args[0])
|
|
flag.PrintDefaults()
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
if *showVersion {
|
|
fmt.Printf("X11Proxy version %s\n", version)
|
|
return
|
|
}
|
|
fmt.Printf("version %s\n", version)
|
|
|
|
display := os.Getenv("DISPLAY")
|
|
if *overrideDisplay != "" {
|
|
display = *overrideDisplay
|
|
}
|
|
|
|
if display == "" {
|
|
log.Fatalf("No DISPLAY environment variable set and no override provided. Please set DISPLAY or use --display.")
|
|
}
|
|
|
|
connType, target := resolveDisplay(display)
|
|
fmt.Printf("Proxying to %s (%s)\n", target, connTypeString(connType))
|
|
|
|
timeout := 10 * time.Second
|
|
status, err := x11probe.ProbeX11Socket(connType, target, timeout)
|
|
if err != nil {
|
|
log.Fatalf("Connection probe error: %v", err)
|
|
}
|
|
|
|
if status == x11probe.X11TemporarilyUnavailable {
|
|
//retry 1x, but change display if :0/:1 assuming wayland dead socket
|
|
if display == ":1" && x11probe.CheckDisplay(display) {
|
|
log.Printf("is wayland scoket wrong? try :0")
|
|
display = ":0"
|
|
connType, target = resolveDisplay(display)
|
|
fmt.Printf("Proxying to %s (%s)\n", target, connTypeString(connType))
|
|
} else {
|
|
if display == ":0" && x11probe.CheckDisplay(display) {
|
|
log.Printf("is wayland scoket wrong? try :1")
|
|
display = ":1"
|
|
connType, target = resolveDisplay(display)
|
|
fmt.Printf("Proxying to %s (%s)\n", target, connTypeString(connType))
|
|
}
|
|
}
|
|
status, err = x11probe.ProbeX11Socket(connType, target, timeout)
|
|
if err != nil {
|
|
log.Fatalf("Connection probe error: %v", err)
|
|
}
|
|
}
|
|
|
|
switch status {
|
|
case x11probe.X11TemporarilyUnavailable:
|
|
log.Fatalf("Target connection is temporarily unavalible, is X11 running?")
|
|
case x11probe.X11Live:
|
|
log.Println("X11 socket is live and accepting connections")
|
|
case x11probe.X11AuthRequired:
|
|
log.Println("X11 socket is live but requires authentication")
|
|
case x11probe.X11Dead:
|
|
log.Fatalf("Target connection is dead or unreachable")
|
|
}
|
|
|
|
err2 := StartProxy(*overrideSocket, target, connType, display)
|
|
if err2 != nil {
|
|
log.Fatalf("Proxy error: %v", err2)
|
|
}
|
|
}
|
|
|
|
func connTypeString(t x11probe.ConnType) string {
|
|
if t == x11probe.Unix {
|
|
return "Unix socket"
|
|
}
|
|
return "TCP"
|
|
}
|
|
|
|
func hexDump(buf []byte) string {
|
|
var out strings.Builder
|
|
for i := 0; i < len(buf); i += 16 {
|
|
line := fmt.Sprintf("%08x ", i)
|
|
|
|
for j := 0; j < 16; j++ {
|
|
if i+j < len(buf) {
|
|
line += fmt.Sprintf("%02x ", buf[i+j])
|
|
} else {
|
|
line += " "
|
|
}
|
|
if j == 7 {
|
|
line += " "
|
|
}
|
|
}
|
|
|
|
line += " |"
|
|
|
|
for j := 0; j < 16 && i+j < len(buf); j++ {
|
|
b := buf[i+j]
|
|
if b >= 32 && b <= 126 {
|
|
line += string(b)
|
|
} else {
|
|
line += "."
|
|
}
|
|
}
|
|
|
|
line += "|\n"
|
|
out.WriteString(line)
|
|
}
|
|
return out.String()
|
|
}
|