diff options
author | Peter Harris <git@peter.is-a-geek.org> | 2010-12-21 09:19:52 -0500 |
---|---|---|
committer | Peter Harris <git@peter.is-a-geek.org> | 2010-12-21 09:19:52 -0500 |
commit | 6cd2ce317d8907f820efc17a17124d33f6fcdcf5 (patch) | |
tree | 973ab55c71d01026a1d0e5cc97f226d88acbdb79 |
Initial commit
Work in progress. Nothing actually works yet.
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | test.go | 9 | ||||
-rw-r--r-- | xgob.go | 199 |
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 @@ -0,0 +1,9 @@ +package main + +import ( + "xgob" + ) + +func main () { + xgob.Connect("") +} @@ -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() +} |