From 52a21b415ad95b2c4649254447388cb329cee1a4 Mon Sep 17 00:00:00 2001 From: "Andrew Gallant (Ocelot)" Date: Sat, 28 Apr 2012 23:25:57 -0400 Subject: initial commit. not currently in a working state. --- nexgb/auth.go | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 nexgb/auth.go (limited to 'nexgb/auth.go') diff --git a/nexgb/auth.go b/nexgb/auth.go new file mode 100644 index 0000000..355afeb --- /dev/null +++ b/nexgb/auth.go @@ -0,0 +1,111 @@ +// Copyright 2009 The XGB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xgb + +import ( + "bufio" + "errors" + "io" + "os" +) + +func getU16BE(r io.Reader, b []byte) (uint16, error) { + _, err := io.ReadFull(r, b[0:2]) + if err != nil { + return 0, err + } + return uint16(b[0])<<8 + uint16(b[1]), nil +} + +func getBytes(r io.Reader, b []byte) ([]byte, error) { + n, err := getU16BE(r, b) + if err != nil { + return nil, err + } + if int(n) > len(b) { + return nil, errors.New("bytes too long for buffer") + } + _, err = io.ReadFull(r, b[0:n]) + if err != nil { + return nil, err + } + return b[0:n], nil +} + +func getString(r io.Reader, b []byte) (string, error) { + b, err := getBytes(r, b) + if err != nil { + return "", err + } + return string(b), nil +} + +// readAuthority reads the X authority file for the DISPLAY. +// If hostname == "" or hostname == "localhost", +// readAuthority uses the system's hostname (as returned by os.Hostname) instead. +func readAuthority(hostname, display string) (name string, data []byte, err error) { + // b is a scratch buffer to use and should be at least 256 bytes long + // (i.e. it should be able to hold a hostname). + var b [256]byte + + // As per /usr/include/X11/Xauth.h. + const familyLocal = 256 + + if len(hostname) == 0 || hostname == "localhost" { + hostname, err = os.Hostname() + if err != nil { + return "", nil, err + } + } + + fname := os.Getenv("XAUTHORITY") + if len(fname) == 0 { + home := os.Getenv("HOME") + if len(home) == 0 { + err = errors.New("Xauthority not found: $XAUTHORITY, $HOME not set") + return "", nil, err + } + fname = home + "/.Xauthority" + } + + r, err := os.Open(fname) + if err != nil { + return "", nil, err + } + defer r.Close() + + br := bufio.NewReader(r) + for { + family, err := getU16BE(br, b[0:2]) + if err != nil { + return "", nil, err + } + + addr, err := getString(br, b[0:]) + if err != nil { + return "", nil, err + } + + disp, err := getString(br, b[0:]) + if err != nil { + return "", nil, err + } + + name0, err := getString(br, b[0:]) + if err != nil { + return "", nil, err + } + + data0, err := getBytes(br, b[0:]) + if err != nil { + return "", nil, err + } + + if family == familyLocal && addr == hostname && disp == display { + return name0, data0, nil + } + } + panic("unreachable") +} -- cgit v1.2.3-70-g09d2 From a5d4ad6c9d763b3d3f797075038023756c38bb28 Mon Sep 17 00:00:00 2001 From: "Andrew Gallant (Ocelot)" Date: Thu, 3 May 2012 22:47:50 -0400 Subject: reworking xgb. cleaned up connection stuff a little. making new xid generation cleaner and use goroutines for it. --- nexgb/auth.go | 6 +- nexgb/conn.go | 161 ++++++++++++++++++++++++++++ nexgb/examples/atom.go | 27 +++++ nexgb/examples/property.go | 39 +++++++ nexgb/xgb.go | 259 +++++++++++++++------------------------------ 5 files changed, 317 insertions(+), 175 deletions(-) create mode 100644 nexgb/conn.go create mode 100644 nexgb/examples/atom.go create mode 100644 nexgb/examples/property.go (limited to 'nexgb/auth.go') diff --git a/nexgb/auth.go b/nexgb/auth.go index 355afeb..ac43e07 100644 --- a/nexgb/auth.go +++ b/nexgb/auth.go @@ -44,8 +44,10 @@ func getString(r io.Reader, b []byte) (string, error) { // readAuthority reads the X authority file for the DISPLAY. // If hostname == "" or hostname == "localhost", -// readAuthority uses the system's hostname (as returned by os.Hostname) instead. -func readAuthority(hostname, display string) (name string, data []byte, err error) { +// then use the system's hostname (as returned by os.Hostname) instead. +func readAuthority(hostname, display string) ( + name string, data []byte, err error) { + // b is a scratch buffer to use and should be at least 256 bytes long // (i.e. it should be able to hold a hostname). var b [256]byte diff --git a/nexgb/conn.go b/nexgb/conn.go new file mode 100644 index 0000000..235402d --- /dev/null +++ b/nexgb/conn.go @@ -0,0 +1,161 @@ +package xgb + +import ( + "errors" + "fmt" + "io" + "net" + "os" + "strconv" + "strings" +) + +// connect connects to the X server given in the 'display' string. +// If 'display' is empty it will be taken from os.Getenv("DISPLAY"). +// Note that you should read and understand the "Connection Setup" of the +// X Protocol Reference Manual before changing this function: +// http://goo.gl/4zGQg +func (c *Conn) connect(display string) error { + err := c.dial(display) + if err != nil { + return err + } + + // Get authentication data + authName, authData, err := readAuthority(c.host, c.display) + noauth := false + if err != nil { + fmt.Fprintf(os.Stderr, "Could not get authority info: %v\n", err) + fmt.Fprintf(os.Stderr, "Trying connection without authority info...\n") + authName = "" + authData = []byte{} + noauth = true + } + + // Assume that the authentication protocol is "MIT-MAGIC-COOKIE-1". + if !noauth && (authName != "MIT-MAGIC-COOKIE-1" || len(authData) != 16) { + return errors.New("unsupported auth protocol " + authName) + } + + buf := make([]byte, 12+pad(len(authName))+pad(len(authData))) + buf[0] = 0x6c + buf[1] = 0 + Put16(buf[2:], 11) + Put16(buf[4:], 0) + Put16(buf[6:], uint16(len(authName))) + Put16(buf[8:], uint16(len(authData))) + Put16(buf[10:], 0) + copy(buf[12:], []byte(authName)) + copy(buf[12+pad(len(authName)):], authData) + if _, err = c.conn.Write(buf); err != nil { + return err + } + + head := make([]byte, 8) + if _, err = io.ReadFull(c.conn, head[0:8]); err != nil { + return err + } + code := head[0] + reasonLen := head[1] + major := Get16(head[2:]) + minor := Get16(head[4:]) + dataLen := Get16(head[6:]) + + if major != 11 || minor != 0 { + return errors.New(fmt.Sprintf("x protocol version mismatch: %d.%d", + major, minor)) + } + + buf = make([]byte, int(dataLen)*4+8, int(dataLen)*4+8) + copy(buf, head) + if _, err = io.ReadFull(c.conn, buf[8:]); err != nil { + return err + } + + if code == 0 { + reason := buf[8 : 8+reasonLen] + return errors.New(fmt.Sprintf("x protocol authentication refused: %s", + string(reason))) + } + + ReadSetupInfo(buf, &c.Setup) + + if c.defaultScreen >= len(c.Setup.Roots) { + c.defaultScreen = 0 + } + + return nil +} + +func (c *Conn) dial(display string) error { + if len(display) == 0 { + display = os.Getenv("DISPLAY") + } + + display0 := display + if len(display) == 0 { + return errors.New("empty display string") + } + + colonIdx := strings.LastIndex(display, ":") + if colonIdx < 0 { + return errors.New("bad display string: " + display0) + } + + var protocol, socket string + + if display[0] == '/' { + socket = display[0:colonIdx] + } else { + slashIdx := strings.LastIndex(display, "/") + if slashIdx >= 0 { + protocol = display[0:slashIdx] + c.host = display[slashIdx+1 : colonIdx] + } else { + c.host = display[0:colonIdx] + } + } + + display = display[colonIdx+1 : len(display)] + if len(display) == 0 { + return errors.New("bad display string: " + display0) + } + + var scr string + dotIdx := strings.LastIndex(display, ".") + if dotIdx < 0 { + c.display = display[0:] + } else { + c.display = display[0:dotIdx] + scr = display[dotIdx+1:] + } + + dispnum, err := strconv.Atoi(c.display) + if err != nil || dispnum < 0 { + return errors.New("bad display string: " + display0) + } + + if len(scr) != 0 { + c.defaultScreen, err = strconv.Atoi(scr) + if err != nil { + return errors.New("bad display string: " + display0) + } + } + + // Connect to server + if len(socket) != 0 { + c.conn, err = net.Dial("unix", socket+":"+c.display) + } else if len(c.host) != 0 { + if protocol == "" { + protocol = "tcp" + } + c.conn, err = net.Dial(protocol, c.host+":"+strconv.Itoa(6000+dispnum)) + } else { + c.conn, err = net.Dial("unix", "/tmp/.X11-unix/X"+c.display) + } + + if err != nil { + return errors.New("cannot connect to " + display0 + ": " + err.Error()) + } + return nil +} diff --git a/nexgb/examples/atom.go b/nexgb/examples/atom.go new file mode 100644 index 0000000..c64acee --- /dev/null +++ b/nexgb/examples/atom.go @@ -0,0 +1,27 @@ +package main + +import ( + // "fmt" + "log" + + "github.com/BurntSushi/xgb" +) + +func init() { + log.SetFlags(0) +} + +func main() { + X, err := xgb.NewConn() + if err != nil { + log.Fatal(err) + } + + aname := "_NET_ACTIVE_WINDOW" + atom, err := X.InternAtom(true, uint16(len(aname)), aname) + if err != nil { + log.Fatal(err) + } + log.Printf("%d", atom.Atom) +} + diff --git a/nexgb/examples/property.go b/nexgb/examples/property.go new file mode 100644 index 0000000..2477df4 --- /dev/null +++ b/nexgb/examples/property.go @@ -0,0 +1,39 @@ +package main + +import ( + "log" + + "github.com/BurntSushi/xgb" +) + +func init() { + log.SetFlags(0) +} + +func get32(buf []byte) uint32 { + v := uint32(buf[0]) + v |= uint32(buf[1]) << 8 + v |= uint32(buf[2]) << 16 + v |= uint32(buf[3]) << 24 + return v +} + +func main() { + X, err := xgb.NewConn() + if err != nil { + log.Fatal(err) + } + + root := X.DefaultScreen().Root + + aname := "_NET_ACTIVE_WINDOW" + atom, err := X.InternAtom(true, uint16(len(aname)), aname) + if err != nil { + log.Fatal(err) + } + + reply, err := X.GetProperty(false, root, atom.Atom, xgb.GetPropertyTypeAny, + 0, (1<<32)-1) + log.Printf("%X", get32(reply.Value)) +} + diff --git a/nexgb/xgb.go b/nexgb/xgb.go index 0dd8163..1a4ada1 100644 --- a/nexgb/xgb.go +++ b/nexgb/xgb.go @@ -12,7 +12,6 @@ import ( "io" "net" "os" - "strconv" "strings" "sync" ) @@ -23,11 +22,9 @@ const ( ) // A Conn represents a connection to an X server. -// Only one goroutine should use a Conn's methods at a time. type Conn struct { host string conn net.Conn - nextId Id nextCookie uint16 cookies map[uint16]*Cookie events queue @@ -44,6 +41,7 @@ type Conn struct { eventChan chan bool errorChan chan bool + xidChan chan xid newIdLock sync.Mutex writeLock sync.Mutex dequeueLock sync.Mutex @@ -51,6 +49,51 @@ type Conn struct { extLock sync.Mutex } +// NewConn creates a new connection instance. It initializes locks, data +// structures, and performs the initial handshake. (The code for the handshake +// has been relegated to conn.go.) +func NewConn() (*Conn, error) { + return NewConnDisplay("") +} + +// NewConnDisplay is just like NewConn, but allows a specific DISPLAY +// string to be used. +// If 'display' is empty it will be taken from os.Getenv("DISPLAY"). +// +// Examples: +// NewConn(":1") -> net.Dial("unix", "", "/tmp/.X11-unix/X1") +// NewConn("/tmp/launch-123/:0") -> net.Dial("unix", "", "/tmp/launch-123/:0") +// NewConn("hostname:2.1") -> net.Dial("tcp", "", "hostname:6002") +// NewConn("tcp/hostname:1.0") -> net.Dial("tcp", "", "hostname:6001") +func NewConnDisplay(display string) (*Conn, error) { + conn := &Conn{} + + // First connect. This reads authority, checks DISPLAY environment + // variable, and loads the initial Setup info. + err := conn.connect(display) + if err != nil { + return nil, err + } + + conn.xidChan = make(chan xid, 5) + go conn.generateXids() + + conn.nextCookie = 1 + conn.cookies = make(map[uint16]*Cookie) + conn.events = queue{make([][]byte, 100), 0, 0} + conn.extensions = make(map[string]byte) + + conn.newReadChannels() + conn.newRequestChannels() + + return conn, nil +} + +// Close closes the connection to the X server. +func (c *Conn) Close() { + c.conn.Close() +} + // Id is used for all X identifiers, such as windows, pixmaps, and GCs. type Id uint32 @@ -111,14 +154,46 @@ type Error interface { var newErrorFuncs = map[int]func(buf []byte) Error{} // NewID generates a new unused ID for use with requests like CreateWindow. -func (c *Conn) NewId() Id { - c.newIdLock.Lock() - defer c.newIdLock.Unlock() - - id := c.nextId - // TODO: handle ID overflow - c.nextId++ - return id +// If no new ids can be generated, the id returned is 0 and error is non-nil. +func (c *Conn) NewId() (Id, error) { + xid := <-c.xidChan + if xid.err != nil { + return 0, xid.err + } + return xid.id, nil +} + +// xid encapsulates a resource identifier being sent over the Conn.xidChan +// channel. If no new resource id can be generated, id is set to -1 and a +// non-nil error is set in xid.err. +type xid struct { + id Id + err error +} + +// generateXids sends new Ids down the channel for NewId to use. +// This needs to be updated to use the XC Misc extension once we run out of +// new ids. +func (conn *Conn) generateXids() { + inc := conn.Setup.ResourceIdMask & -conn.Setup.ResourceIdMask + max := conn.Setup.ResourceIdMask + last := uint32(0) + for { + // TODO: Use the XC Misc extension to look for released ids. + if last > 0 && last >= max - inc + 1 { + conn.xidChan <- xid{ + id: Id(0), + err: errors.New("There are no more available resource" + + "identifiers."), + } + } + + last += inc + conn.xidChan <- xid{ + id: Id(last | conn.Setup.ResourceIdBase), + err: nil, + } + } } // RegisterExtension adds the respective extension's major op code to @@ -328,165 +403,3 @@ func (c *Conn) PollForEvent() (Event, error) { return nil, nil } -// Dial connects to the X server given in the 'display' string. -// If 'display' is empty it will be taken from os.Getenv("DISPLAY"). -// -// Examples: -// Dial(":1") // connect to net.Dial("unix", "", "/tmp/.X11-unix/X1") -// Dial("/tmp/launch-123/:0") // connect to net.Dial("unix", "", "/tmp/launch-123/:0") -// Dial("hostname:2.1") // connect to net.Dial("tcp", "", "hostname:6002") -// Dial("tcp/hostname:1.0") // connect to net.Dial("tcp", "", "hostname:6001") -func Dial(display string) (*Conn, error) { - c, err := connect(display) - if err != nil { - return nil, err - } - - // Get authentication data - authName, authData, err := readAuthority(c.host, c.display) - noauth := false - if err != nil { - fmt.Fprintf(os.Stderr, "Could not get authority info: %v\n", err) - fmt.Fprintf(os.Stderr, "Trying connection without authority info...\n") - authName = "" - authData = []byte{} - noauth = true - } - - // Assume that the authentication protocol is "MIT-MAGIC-COOKIE-1". - if !noauth && (authName != "MIT-MAGIC-COOKIE-1" || len(authData) != 16) { - return nil, errors.New("unsupported auth protocol " + authName) - } - - buf := make([]byte, 12+pad(len(authName))+pad(len(authData))) - buf[0] = 0x6c - buf[1] = 0 - Put16(buf[2:], 11) - Put16(buf[4:], 0) - Put16(buf[6:], uint16(len(authName))) - Put16(buf[8:], uint16(len(authData))) - Put16(buf[10:], 0) - copy(buf[12:], []byte(authName)) - copy(buf[12+pad(len(authName)):], authData) - if _, err = c.conn.Write(buf); err != nil { - return nil, err - } - - head := make([]byte, 8) - if _, err = io.ReadFull(c.conn, head[0:8]); err != nil { - return nil, err - } - code := head[0] - reasonLen := head[1] - major := Get16(head[2:]) - minor := Get16(head[4:]) - dataLen := Get16(head[6:]) - - if major != 11 || minor != 0 { - return nil, errors.New(fmt.Sprintf("x protocol version mismatch: %d.%d", major, minor)) - } - - buf = make([]byte, int(dataLen)*4+8, int(dataLen)*4+8) - copy(buf, head) - if _, err = io.ReadFull(c.conn, buf[8:]); err != nil { - return nil, err - } - - if code == 0 { - reason := buf[8 : 8+reasonLen] - return nil, errors.New(fmt.Sprintf("x protocol authentication refused: %s", string(reason))) - } - - ReadSetupInfo(buf, &c.Setup) - - if c.defaultScreen >= len(c.Setup.Roots) { - c.defaultScreen = 0 - } - - c.nextId = Id(c.Setup.ResourceIdBase) - c.nextCookie = 1 - c.cookies = make(map[uint16]*Cookie) - c.events = queue{make([][]byte, 100), 0, 0} - c.extensions = make(map[string]byte) - - c.newReadChannels() - c.newRequestChannels() - return c, nil -} - -// Close closes the connection to the X server. -func (c *Conn) Close() { c.conn.Close() } - -func connect(display string) (*Conn, error) { - if len(display) == 0 { - display = os.Getenv("DISPLAY") - } - - display0 := display - if len(display) == 0 { - return nil, errors.New("empty display string") - } - - colonIdx := strings.LastIndex(display, ":") - if colonIdx < 0 { - return nil, errors.New("bad display string: " + display0) - } - - var protocol, socket string - c := new(Conn) - - if display[0] == '/' { - socket = display[0:colonIdx] - } else { - slashIdx := strings.LastIndex(display, "/") - if slashIdx >= 0 { - protocol = display[0:slashIdx] - c.host = display[slashIdx+1 : colonIdx] - } else { - c.host = display[0:colonIdx] - } - } - - display = display[colonIdx+1 : len(display)] - if len(display) == 0 { - return nil, errors.New("bad display string: " + display0) - } - - var scr string - dotIdx := strings.LastIndex(display, ".") - if dotIdx < 0 { - c.display = display[0:] - } else { - c.display = display[0:dotIdx] - scr = display[dotIdx+1:] - } - - dispnum, err := strconv.Atoi(c.display) - if err != nil || dispnum < 0 { - return nil, errors.New("bad display string: " + display0) - } - - if len(scr) != 0 { - c.defaultScreen, err = strconv.Atoi(scr) - if err != nil { - return nil, errors.New("bad display string: " + display0) - } - } - - // Connect to server - if len(socket) != 0 { - c.conn, err = net.Dial("unix", socket+":"+c.display) - } else if len(c.host) != 0 { - if protocol == "" { - protocol = "tcp" - } - c.conn, err = net.Dial(protocol, c.host+":"+strconv.Itoa(6000+dispnum)) - } else { - c.conn, err = net.Dial("unix", "/tmp/.X11-unix/X"+c.display) - } - - if err != nil { - return nil, errors.New("cannot connect to " + display0 + ": " + err.Error()) - } - return c, nil -} -- cgit v1.2.3-70-g09d2 From daad54a5e114dcff9ef62abbbd18ea52929d01e5 Mon Sep 17 00:00:00 2001 From: "Andrew Gallant (Ocelot)" Date: Mon, 7 May 2012 04:17:11 -0400 Subject: important stuff first please --- nexgb/auth.go | 62 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'nexgb/auth.go') diff --git a/nexgb/auth.go b/nexgb/auth.go index ac43e07..85e2d56 100644 --- a/nexgb/auth.go +++ b/nexgb/auth.go @@ -11,37 +11,6 @@ import ( "os" ) -func getU16BE(r io.Reader, b []byte) (uint16, error) { - _, err := io.ReadFull(r, b[0:2]) - if err != nil { - return 0, err - } - return uint16(b[0])<<8 + uint16(b[1]), nil -} - -func getBytes(r io.Reader, b []byte) ([]byte, error) { - n, err := getU16BE(r, b) - if err != nil { - return nil, err - } - if int(n) > len(b) { - return nil, errors.New("bytes too long for buffer") - } - _, err = io.ReadFull(r, b[0:n]) - if err != nil { - return nil, err - } - return b[0:n], nil -} - -func getString(r io.Reader, b []byte) (string, error) { - b, err := getBytes(r, b) - if err != nil { - return "", err - } - return string(b), nil -} - // readAuthority reads the X authority file for the DISPLAY. // If hostname == "" or hostname == "localhost", // then use the system's hostname (as returned by os.Hostname) instead. @@ -111,3 +80,34 @@ func readAuthority(hostname, display string) ( } panic("unreachable") } + +func getU16BE(r io.Reader, b []byte) (uint16, error) { + _, err := io.ReadFull(r, b[0:2]) + if err != nil { + return 0, err + } + return uint16(b[0])<<8 + uint16(b[1]), nil +} + +func getBytes(r io.Reader, b []byte) ([]byte, error) { + n, err := getU16BE(r, b) + if err != nil { + return nil, err + } + if int(n) > len(b) { + return nil, errors.New("bytes too long for buffer") + } + _, err = io.ReadFull(r, b[0:n]) + if err != nil { + return nil, err + } + return b[0:n], nil +} + +func getString(r io.Reader, b []byte) (string, error) { + b, err := getBytes(r, b) + if err != nil { + return "", err + } + return string(b), nil +} -- cgit v1.2.3-70-g09d2 From 24fef4062ad441c935f5a87e908c5f293d8a2f42 Mon Sep 17 00:00:00 2001 From: "Andrew Gallant (Ocelot)" Date: Sat, 12 May 2012 21:36:31 -0400 Subject: docs --- nexgb/auth.go | 10 ++++++---- nexgb/conn.go | 7 +++++++ nexgb/help.go | 10 ++++++++++ nexgb/sync.go | 2 +- nexgb/xgb.go | 7 +++++-- 5 files changed, 29 insertions(+), 7 deletions(-) (limited to 'nexgb/auth.go') diff --git a/nexgb/auth.go b/nexgb/auth.go index 85e2d56..396e832 100644 --- a/nexgb/auth.go +++ b/nexgb/auth.go @@ -1,9 +1,11 @@ -// Copyright 2009 The XGB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - package xgb +/* +auth.go contains functions to facilitate the parsing of .Xauthority files. + +It is largely unmodified from the original XGB package that I forked. +*/ + import ( "bufio" "errors" diff --git a/nexgb/conn.go b/nexgb/conn.go index 662a059..9baf86c 100644 --- a/nexgb/conn.go +++ b/nexgb/conn.go @@ -1,5 +1,12 @@ package xgb +/* +conn.go contains a couple of functions that do some real dirty work related +to the initial connection handshake with X. + +This code is largely unmodified from the original XGB package that I forked. +*/ + import ( "errors" "fmt" diff --git a/nexgb/help.go b/nexgb/help.go index 36fe98b..5729917 100644 --- a/nexgb/help.go +++ b/nexgb/help.go @@ -1,5 +1,15 @@ package xgb +/* +help.go is meant to contain a rough hodge podge of functions that are mainly +used in the auto generated code. Indeed, several functions here are simple +wrappers so that the sub-packages don't need to be smart about which stdlib +packages to import. + +Also, the 'Get..' and 'Put..' functions are used through the core xgb package +too. (xgbutil uses them too.) +*/ + import ( "fmt" "strings" diff --git a/nexgb/sync.go b/nexgb/sync.go index d671e62..59d0de1 100644 --- a/nexgb/sync.go +++ b/nexgb/sync.go @@ -1,6 +1,6 @@ package xgb -// Sync sends a round trip request and wait for the response. +// Sync sends a round trip request and waits for the response. // This forces all pending cookies to be dealt with. // You actually shouldn't need to use this like you might with Xlib. Namely, // buffers are automatically flushed using Go's channels and round trip requests diff --git a/nexgb/xgb.go b/nexgb/xgb.go index 50cfdba..b2cf56c 100644 --- a/nexgb/xgb.go +++ b/nexgb/xgb.go @@ -166,8 +166,11 @@ type eventOrError interface{} // NewID generates a new unused ID for use with requests like CreateWindow. // If no new ids can be generated, the id returned is 0 and error is non-nil. -// Note that the value returned will need to be converted to the proper -// type. i.e., xproto.Window(id). +// This shouldn't be used directly, and is exported for use in the extension +// sub-packages. +// If you need identifiers, use the appropriate constructor. +// e.g., For a window id, use xproto.NewWindowId. For +// a new pixmap id, use xproto.NewPixmapId. And so on. func (c *Conn) NewId() (uint32, error) { xid := <-c.xidChan if xid.err != nil { -- cgit v1.2.3-70-g09d2 From cd22f99b20b3520f578bd146847ad5c8b0603d57 Mon Sep 17 00:00:00 2001 From: Paul Sbarra Date: Mon, 28 May 2012 17:04:02 -0500 Subject: auth: use encoding.binary --- nexgb/auth.go | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'nexgb/auth.go') diff --git a/nexgb/auth.go b/nexgb/auth.go index 396e832..a6fad90 100644 --- a/nexgb/auth.go +++ b/nexgb/auth.go @@ -7,7 +7,7 @@ It is largely unmodified from the original XGB package that I forked. */ import ( - "bufio" + "encoding/binary" "errors" "io" "os" @@ -21,7 +21,7 @@ func readAuthority(hostname, display string) ( // b is a scratch buffer to use and should be at least 256 bytes long // (i.e. it should be able to hold a hostname). - var b [256]byte + b := make([]byte, 256) // As per /usr/include/X11/Xauth.h. const familyLocal = 256 @@ -49,29 +49,28 @@ func readAuthority(hostname, display string) ( } defer r.Close() - br := bufio.NewReader(r) for { - family, err := getU16BE(br, b[0:2]) - if err != nil { + var family uint16 + if err := binary.Read(r, binary.BigEndian, &family); err != nil { return "", nil, err } - addr, err := getString(br, b[0:]) + addr, err := getString(r, b) if err != nil { return "", nil, err } - disp, err := getString(br, b[0:]) + disp, err := getString(r, b) if err != nil { return "", nil, err } - name0, err := getString(br, b[0:]) + name0, err := getString(r, b) if err != nil { return "", nil, err } - data0, err := getBytes(br, b[0:]) + data0, err := getBytes(r, b) if err != nil { return "", nil, err } @@ -83,24 +82,15 @@ func readAuthority(hostname, display string) ( panic("unreachable") } -func getU16BE(r io.Reader, b []byte) (uint16, error) { - _, err := io.ReadFull(r, b[0:2]) - if err != nil { - return 0, err - } - return uint16(b[0])<<8 + uint16(b[1]), nil -} - func getBytes(r io.Reader, b []byte) ([]byte, error) { - n, err := getU16BE(r, b) - if err != nil { + var n uint16 + if err := binary.Read(r, binary.BigEndian, &n); err != nil { return nil, err - } - if int(n) > len(b) { + } else if n > uint16(len(b)) { return nil, errors.New("bytes too long for buffer") } - _, err = io.ReadFull(r, b[0:n]) - if err != nil { + + if _, err := io.ReadFull(r, b[0:n]); err != nil { return nil, err } return b[0:n], nil -- cgit v1.2.3-70-g09d2 From 8d343cfd3a12d910d6a663f2d5f2cd4a41d88ce2 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 21 Mar 2016 18:50:49 +0100 Subject: Handle wildcard values in Xauthority file Some field values in the Xauthority file have special meanings: - a value of 65535 in the 'family' field means that the entry will match a connection of any family on any address - an empty string in the 'display number' field means that the entry will match a connection on any display number This behaviour is documented at: https://cgit.freedesktop.org/xorg/lib/libXau/tree/AuGetBest.c#n109 --- nexgb/auth.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'nexgb/auth.go') diff --git a/nexgb/auth.go b/nexgb/auth.go index a6fad90..62a9b35 100644 --- a/nexgb/auth.go +++ b/nexgb/auth.go @@ -25,6 +25,7 @@ func readAuthority(hostname, display string) ( // As per /usr/include/X11/Xauth.h. const familyLocal = 256 + const familyWild = 65535 if len(hostname) == 0 || hostname == "localhost" { hostname, err = os.Hostname() @@ -75,7 +76,10 @@ func readAuthority(hostname, display string) ( return "", nil, err } - if family == familyLocal && addr == hostname && disp == display { + addrmatch := (family == familyWild) || (family == familyLocal && addr == hostname) + dispmatch := (disp == "") || (disp == display) + + if addrmatch && dispmatch { return name0, data0, nil } } -- cgit v1.2.3-70-g09d2 From 1614b58c420f7875f92a5469c77fd7aeccc7a106 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Tue, 29 Mar 2016 16:23:18 -0400 Subject: fix structs with field name of 'Bytes' (it conflict with a method of the same name that is generated for all such structs) --- nexgb/auth.go | 3 ++- nexgb/res/res.go | 10 +++++----- nexgb/xgb.go | 2 +- nexgb/xgbgen/field.go | 3 +++ 4 files changed, 11 insertions(+), 7 deletions(-) (limited to 'nexgb/auth.go') diff --git a/nexgb/auth.go b/nexgb/auth.go index 62a9b35..ec51d10 100644 --- a/nexgb/auth.go +++ b/nexgb/auth.go @@ -76,7 +76,8 @@ func readAuthority(hostname, display string) ( return "", nil, err } - addrmatch := (family == familyWild) || (family == familyLocal && addr == hostname) + addrmatch := (family == familyWild) || + (family == familyLocal && addr == hostname) dispmatch := (disp == "") || (disp == display) if addrmatch && dispmatch { diff --git a/nexgb/res/res.go b/nexgb/res/res.go index e3d7b02..0ad0389 100644 --- a/nexgb/res/res.go +++ b/nexgb/res/res.go @@ -283,7 +283,7 @@ func ResourceIdSpecListBytes(buf []byte, list []ResourceIdSpec) int { type ResourceSizeSpec struct { Spec ResourceIdSpec - Bytes uint32 + Bytes_ uint32 RefCount uint32 UseCount uint32 } @@ -295,7 +295,7 @@ func ResourceSizeSpecRead(buf []byte, v *ResourceSizeSpec) int { v.Spec = ResourceIdSpec{} b += ResourceIdSpecRead(buf[b:], &v.Spec) - v.Bytes = xgb.Get32(buf[b:]) + v.Bytes_ = xgb.Get32(buf[b:]) b += 4 v.RefCount = xgb.Get32(buf[b:]) @@ -328,7 +328,7 @@ func (v ResourceSizeSpec) Bytes() []byte { b += len(structBytes) } - xgb.Put32(buf[b:], v.Bytes) + xgb.Put32(buf[b:], v.Bytes_) b += 4 xgb.Put32(buf[b:], v.RefCount) @@ -641,7 +641,7 @@ type QueryClientPixmapBytesReply struct { Sequence uint16 // sequence number of the request for this reply Length uint32 // number of bytes in this reply // padding: 1 bytes - Bytes uint32 + Bytes_ uint32 BytesOverflow uint32 } @@ -670,7 +670,7 @@ func queryClientPixmapBytesReply(buf []byte) *QueryClientPixmapBytesReply { v.Length = xgb.Get32(buf[b:]) // 4-byte units b += 4 - v.Bytes = xgb.Get32(buf[b:]) + v.Bytes_ = xgb.Get32(buf[b:]) b += 4 v.BytesOverflow = xgb.Get32(buf[b:]) diff --git a/nexgb/xgb.go b/nexgb/xgb.go index f49d19b..3d2c61f 100644 --- a/nexgb/xgb.go +++ b/nexgb/xgb.go @@ -61,7 +61,7 @@ type Conn struct { seqChan chan uint16 reqChan chan *request closing chan chan struct{} - + // ExtLock is a lock used whenever new extensions are initialized. // It should not be used. It is exported for use in the extension // sub-packages. diff --git a/nexgb/xgbgen/field.go b/nexgb/xgbgen/field.go index bf3b3be..2522a06 100644 --- a/nexgb/xgbgen/field.go +++ b/nexgb/xgbgen/field.go @@ -87,6 +87,9 @@ func (f *SingleField) Initialize(p *Protocol) { } func (f *SingleField) SrcName() string { + if f.srcName == "Bytes" { + return "Bytes_" + } return f.srcName } -- cgit v1.2.3-70-g09d2