summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Harris <git@peter.is-a-geek.org>2010-12-21 09:19:52 -0500
committerPeter Harris <git@peter.is-a-geek.org>2010-12-21 09:19:52 -0500
commit6cd2ce317d8907f820efc17a17124d33f6fcdcf5 (patch)
tree973ab55c71d01026a1d0e5cc97f226d88acbdb79
Initial commit
Work in progress. Nothing actually works yet.
-rw-r--r--.gitignore5
-rw-r--r--test.go9
-rw-r--r--xgob.go199
3 files changed, 213 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..788ddc2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+6.out
+build
+*.6
+*.go
+*.xcodeproj
diff --git a/test.go b/test.go
new file mode 100644
index 0000000..03436bd
--- /dev/null
+++ b/test.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+ "xgob"
+ )
+
+func main () {
+ xgob.Connect("")
+}
diff --git a/xgob.go b/xgob.go
new file mode 100644
index 0000000..477b57e
--- /dev/null
+++ b/xgob.go
@@ -0,0 +1,199 @@
+package xgob
+
+import (
+ "bufio"
+ "bytes"
+ "io"
+ "net"
+ "os"
+ "strconv"
+ "strings"
+ )
+
+const X_TCP_PORT = 6000
+
+type Error struct {
+}
+
+type Connection struct {
+ conn io.ReadWriteCloser
+ in *bufio.Reader
+}
+
+func parse_display (name string) (host string, protocol string, display int, screen int) {
+ if len(name) == 0 {
+ name = os.Getenv("DISPLAY")
+ }
+ if len(name) == 0 {
+ return
+ }
+
+ if !strings.HasPrefix(name, "/tmp/launch") {
+ slash := strings.LastIndex(name, "/")
+ if slash >= 0 {
+ protocol = name[:slash]
+ name = name[slash+1:]
+ }
+ }
+
+ var err os.Error
+
+ dot := strings.LastIndex(name, ".");
+ if dot >= 0 {
+ screen,err = strconv.Atoi(name[dot+1:])
+ if err == nil {
+ name = name[:dot]
+ }
+ }
+ colon := strings.LastIndex(name, ":");
+ if colon < 0 {
+ return
+ }
+ display, err = strconv.Atoi(name[colon+1:])
+ if err != nil {
+ return
+ }
+ host = name[:colon]
+ return
+}
+
+func open(host string, protocol string, display int) io.ReadWriteCloser {
+ unix_base := "/tmp/.X11-unix/X";
+ base := unix_base
+
+ if strings.HasPrefix(host, "/tmp/launch") {
+ base = host
+ host = ""
+ protocol = ""
+ }
+
+ if(len(host) > 0 || len(protocol) > 0) {
+ if len(protocol) > 0 || "unix" == host { /* follow the old unix: rule */
+ /* display specifies TCP */
+ port := X_TCP_PORT + display;
+ return open_tcp(host, protocol, port);
+ }
+ }
+
+ var file string
+ /* display specifies Unix socket */
+ if strings.HasPrefix(base, "/tmp/launch") {
+ file = base + ":" + strconv.Itoa(display)
+ } else {
+ file = base + strconv.Itoa(display)
+ }
+
+ return open_unix(protocol, file)
+}
+
+func open_tcp(host string, protocol string, port int) io.ReadWriteCloser {
+ if len(protocol) > 0 && "tcp" != protocol && "inet" != protocol && "inet6" != protocol {
+ return nil;
+ }
+ proto := "tcp"
+ if protocol == "inet6" {
+ proto = "tcp6"
+ }
+
+ if len(host) == 0 {
+ host = "localhost"
+ }
+
+ conn, err := net.Dial(proto, "", host + ":" + strconv.Itoa(port))
+ // TODO - remove
+ if err != nil {
+ println("TCP error ", err.String())
+ }
+ return conn
+}
+
+func open_unix(protocol string, file string) io.ReadWriteCloser {
+ if len(protocol) > 0 && "unix" != protocol {
+ return nil
+ }
+
+ conn, err := net.Dial(protocol, "", file)
+ // TODO - remove
+ if err != nil {
+ println("Unix socket error ", err.String())
+ }
+ return conn
+}
+
+func Pad (i int) int {
+ return (-i) & 3
+}
+
+func (c *Connection)write_setup(name string, data string) {
+ buf := make([]byte, 0, 100)
+
+ buf = append(buf, 'B') // Big endian.
+ buf = append(buf, 'l')
+ buf = append(buf, 0, 11) // X11
+ buf = append(buf, 0, 0) // .0
+ buf = append(buf, byte((len(name) & 0xFF00) >> 8), byte(len(name) & 0xFF))
+ buf = append(buf, byte((len(data) & 0xFF00) >> 8), byte(len(data) & 0xFF))
+ buf = append(buf, 0, 0) // pad
+
+ if len(name) > 0 && len(data) > 0 {
+ n := bytes.NewBufferString(name)
+ buf = append(buf, n.Bytes()...)
+ for i := 0; i < Pad(len(name)); i++ {
+ buf = append(buf, 0)
+ }
+ n = bytes.NewBufferString(data)
+ buf = append(buf, n.Bytes()...)
+ for i := 0; i < Pad(len(data)); i++ {
+ buf = append(buf, 0)
+ }
+ }
+
+ c.conn.Write(buf)
+}
+
+func getUint16(in *bufio.Reader) uint16 {
+ var rv uint16
+ i, _ := in.ReadByte()
+ rv = uint16(i) << 8
+ i, _ = in.ReadByte()
+ rv |= uint16(i)
+ return rv
+}
+
+func (c *Connection)read_setup() {
+ // TODO
+ status, _ := c.in.ReadByte()
+ for i := 0; i < 5; i++ {
+ _, _ = c.in.ReadByte()
+ }
+ len := getUint16(c.in)
+ println("Status: " + strconv.Itoa(int(status)))
+ println("Connection block size: " + strconv.Itoa(int(len)))
+}
+
+func (c *Connection)connect_auth(name string, data string) {
+ c.write_setup(name, data)
+ c.in = bufio.NewReader(c.conn)
+ c.read_setup()
+}
+
+func Connect (dpy string) (conn *Connection, screen int) {
+ host, proto, display, screen := parse_display(dpy)
+
+ var c Connection
+ c.conn = open(host, proto, display);
+
+ if c.conn == nil {
+ return
+ }
+
+ // TODO: name, data := c.get_auth_info()
+ name, data := "", ""
+ c.connect_auth(name, data);
+ conn = &c
+ return
+}
+
+func (c *Connection) Disconnect () {
+ c.conn.Close()
+}