From 1639235a48dbed75c2563c9a497b41c31a2a1bae Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch Date: Mon, 8 Aug 2022 04:39:20 +0200 Subject: Start X11 and web frontends for xC For this, we needed a wire protocol. After surveying available options, it was decided to implement an XDR-like protocol code generator in portable AWK. It now has two backends, per each of: - xF, the X11 frontend, is in C, and is meant to be the primary user interface in the future. - xP, the web frontend, relies on a protocol proxy written in Go, and is meant for use on-the-go (no pun intended). They are very much work-in-progress proofs of concept right now, and the relay protocol is certain to change. --- xP/xP.go | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 xP/xP.go (limited to 'xP/xP.go') diff --git a/xP/xP.go b/xP/xP.go new file mode 100644 index 0000000..9b5df8f --- /dev/null +++ b/xP/xP.go @@ -0,0 +1,186 @@ +package main + +import ( + "context" + "encoding/binary" + "encoding/json" + "fmt" + "html/template" + "io" + "log" + "net" + "net/http" + "os" + "time" + + "golang.org/x/net/websocket" +) + +var ( + addressBind string + addressConnect string +) + +func clientToRelay( + ctx context.Context, ws *websocket.Conn, conn net.Conn) bool { + var j string + if err := websocket.Message.Receive(ws, &j); err != nil { + log.Println("Command receive failed: " + err.Error()) + return false + } + + log.Printf("?> %s\n", j) + + var m RelayCommandMessage + if err := json.Unmarshal([]byte(j), &m); err != nil { + log.Println("Command unmarshalling failed: " + err.Error()) + return false + } + + b, ok := m.AppendTo(make([]byte, 4)) + if !ok { + log.Println("Command serialization failed") + return false + } + binary.BigEndian.PutUint32(b[:4], uint32(len(b)-4)) + if _, err := conn.Write(b); err != nil { + log.Println("Command send failed: " + err.Error()) + return false + } + + log.Printf("-> %v\n", b) + return true +} + +func relayToClient( + ctx context.Context, ws *websocket.Conn, conn net.Conn) bool { + var length uint32 + if err := binary.Read(conn, binary.BigEndian, &length); err != nil { + log.Println("Event receive failed: " + err.Error()) + return false + } + b := make([]byte, length) + if _, err := io.ReadFull(conn, b); err != nil { + log.Println("Event receive failed: " + err.Error()) + return false + } + + log.Printf(" + + + xP + + + + + + + + +`)) + +func handleDefault(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + staticHandler.ServeHTTP(w, r) + return + } + + wsURI := fmt.Sprintf("ws://%s/ws", r.Host) + if err := page.Execute(w, wsURI); err != nil { + log.Println("Template execution failed: " + err.Error()) + } +} + +func main() { + if len(os.Args) != 3 { + log.Fatalf("usage: %s BIND CONNECT\n", os.Args[0]) + } + + addressBind, addressConnect = os.Args[1], os.Args[2] + + http.Handle("/ws", websocket.Handler(handleWebSocket)) + http.Handle("/", http.HandlerFunc(handleDefault)) + + s := &http.Server{ + Addr: addressBind, + ReadTimeout: 60 * time.Second, + WriteTimeout: 60 * time.Second, + MaxHeaderBytes: 32 << 10, + } + log.Fatal(s.ListenAndServe()) +} -- cgit v1.2.3-54-g00ecf