WIP: Save agent roles integration work before CHORUS rebrand
- Agent roles and coordination features - Chat API integration testing - New configuration and workspace management 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		
							
								
								
									
										50
									
								
								vendor/github.com/godbus/dbus/v5/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								vendor/github.com/godbus/dbus/v5/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| # How to Contribute | ||||
|  | ||||
| ## Getting Started | ||||
|  | ||||
| - Fork the repository on GitHub | ||||
| - Read the [README](README.markdown) for build and test instructions | ||||
| - Play with the project, submit bugs, submit patches! | ||||
|  | ||||
| ## Contribution Flow | ||||
|  | ||||
| This is a rough outline of what a contributor's workflow looks like: | ||||
|  | ||||
| - Create a topic branch from where you want to base your work (usually master). | ||||
| - Make commits of logical units. | ||||
| - Make sure your commit messages are in the proper format (see below). | ||||
| - Push your changes to a topic branch in your fork of the repository. | ||||
| - Make sure the tests pass, and add any new tests as appropriate. | ||||
| - Submit a pull request to the original repository. | ||||
|  | ||||
| Thanks for your contributions! | ||||
|  | ||||
| ### Format of the Commit Message | ||||
|  | ||||
| We follow a rough convention for commit messages that is designed to answer two | ||||
| questions: what changed and why. The subject line should feature the what and | ||||
| the body of the commit should describe the why. | ||||
|  | ||||
| ``` | ||||
| scripts: add the test-cluster command | ||||
|  | ||||
| this uses tmux to setup a test cluster that you can easily kill and | ||||
| start for debugging. | ||||
|  | ||||
| Fixes #38 | ||||
| ``` | ||||
|  | ||||
| The format can be described more formally as follows: | ||||
|  | ||||
| ``` | ||||
| <subsystem>: <what changed> | ||||
| <BLANK LINE> | ||||
| <why this change was made> | ||||
| <BLANK LINE> | ||||
| <footer> | ||||
| ``` | ||||
|  | ||||
| The first line is the subject and should be no longer than 70 characters, the | ||||
| second line is always blank, and other lines should be wrapped at 80 characters. | ||||
| This allows the message to be easier to read on GitHub as well as in various | ||||
| git tools. | ||||
							
								
								
									
										25
									
								
								vendor/github.com/godbus/dbus/v5/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/godbus/dbus/v5/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| Copyright (c) 2013, Georg Reinke (<guelfey at gmail dot com>), Google | ||||
| All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions | ||||
| are met: | ||||
|  | ||||
| 1. Redistributions of source code must retain the above copyright notice, | ||||
| this list of conditions and the following disclaimer. | ||||
|  | ||||
| 2. Redistributions in binary form must reproduce the above copyright | ||||
| notice, this list of conditions and the following disclaimer in the | ||||
| documentation and/or other materials provided with the distribution. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
| HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
| TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
| PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										3
									
								
								vendor/github.com/godbus/dbus/v5/MAINTAINERS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/godbus/dbus/v5/MAINTAINERS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| Brandon Philips <brandon@ifup.org> (@philips) | ||||
| Brian Waldon <brian@waldon.cc> (@bcwaldon) | ||||
| John Southworth <jsouthwo@brocade.com> (@jsouthworth) | ||||
							
								
								
									
										46
									
								
								vendor/github.com/godbus/dbus/v5/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/godbus/dbus/v5/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
|  | ||||
|  | ||||
| dbus | ||||
| ---- | ||||
|  | ||||
| dbus is a simple library that implements native Go client bindings for the | ||||
| D-Bus message bus system. | ||||
|  | ||||
| ### Features | ||||
|  | ||||
| * Complete native implementation of the D-Bus message protocol | ||||
| * Go-like API (channels for signals / asynchronous method calls, Goroutine-safe connections) | ||||
| * Subpackages that help with the introspection / property interfaces | ||||
|  | ||||
| ### Installation | ||||
|  | ||||
| This packages requires Go 1.12 or later. It can be installed by running the command below: | ||||
|  | ||||
| ``` | ||||
| go get github.com/godbus/dbus/v5 | ||||
| ``` | ||||
|  | ||||
| ### Usage | ||||
|  | ||||
| The complete package documentation and some simple examples are available at | ||||
| [godoc.org](http://godoc.org/github.com/godbus/dbus). Also, the | ||||
| [_examples](https://github.com/godbus/dbus/tree/master/_examples) directory | ||||
| gives a short overview over the basic usage.  | ||||
|  | ||||
| #### Projects using godbus | ||||
| - [fyne](https://github.com/fyne-io/fyne) a cross platform GUI in Go inspired by Material Design. | ||||
| - [fynedesk](https://github.com/fyne-io/fynedesk) a full desktop environment for Linux/Unix using Fyne. | ||||
| - [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API. | ||||
| - [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd". | ||||
| - [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library. | ||||
| - [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players. | ||||
|  | ||||
| Please note that the API is considered unstable for now and may change without | ||||
| further notice. | ||||
|  | ||||
| ### License | ||||
|  | ||||
| go.dbus is available under the Simplified BSD License; see LICENSE for the full | ||||
| text. | ||||
|  | ||||
| Nearly all of the credit for this library goes to github.com/guelfey/go.dbus. | ||||
							
								
								
									
										257
									
								
								vendor/github.com/godbus/dbus/v5/auth.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								vendor/github.com/godbus/dbus/v5/auth.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,257 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| ) | ||||
|  | ||||
| // AuthStatus represents the Status of an authentication mechanism. | ||||
| type AuthStatus byte | ||||
|  | ||||
| const ( | ||||
| 	// AuthOk signals that authentication is finished; the next command | ||||
| 	// from the server should be an OK. | ||||
| 	AuthOk AuthStatus = iota | ||||
|  | ||||
| 	// AuthContinue signals that additional data is needed; the next command | ||||
| 	// from the server should be a DATA. | ||||
| 	AuthContinue | ||||
|  | ||||
| 	// AuthError signals an error; the server sent invalid data or some | ||||
| 	// other unexpected thing happened and the current authentication | ||||
| 	// process should be aborted. | ||||
| 	AuthError | ||||
| ) | ||||
|  | ||||
| type authState byte | ||||
|  | ||||
| const ( | ||||
| 	waitingForData authState = iota | ||||
| 	waitingForOk | ||||
| 	waitingForReject | ||||
| ) | ||||
|  | ||||
| // Auth defines the behaviour of an authentication mechanism. | ||||
| type Auth interface { | ||||
| 	// Return the name of the mechanism, the argument to the first AUTH command | ||||
| 	// and the next status. | ||||
| 	FirstData() (name, resp []byte, status AuthStatus) | ||||
|  | ||||
| 	// Process the given DATA command, and return the argument to the DATA | ||||
| 	// command and the next status. If len(resp) == 0, no DATA command is sent. | ||||
| 	HandleData(data []byte) (resp []byte, status AuthStatus) | ||||
| } | ||||
|  | ||||
| // Auth authenticates the connection, trying the given list of authentication | ||||
| // mechanisms (in that order). If nil is passed, the EXTERNAL and | ||||
| // DBUS_COOKIE_SHA1 mechanisms are tried for the current user. For private | ||||
| // connections, this method must be called before sending any messages to the | ||||
| // bus. Auth must not be called on shared connections. | ||||
| func (conn *Conn) Auth(methods []Auth) error { | ||||
| 	if methods == nil { | ||||
| 		uid := strconv.Itoa(os.Geteuid()) | ||||
| 		methods = []Auth{AuthExternal(uid), AuthCookieSha1(uid, getHomeDir())} | ||||
| 	} | ||||
| 	in := bufio.NewReader(conn.transport) | ||||
| 	err := conn.transport.SendNullByte() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	err = authWriteLine(conn.transport, []byte("AUTH")) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	s, err := authReadLine(in) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if len(s) < 2 || !bytes.Equal(s[0], []byte("REJECTED")) { | ||||
| 		return errors.New("dbus: authentication protocol error") | ||||
| 	} | ||||
| 	s = s[1:] | ||||
| 	for _, v := range s { | ||||
| 		for _, m := range methods { | ||||
| 			if name, _, status := m.FirstData(); bytes.Equal(v, name) { | ||||
| 				var ok bool | ||||
| 				err = authWriteLine(conn.transport, []byte("AUTH"), v) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				switch status { | ||||
| 				case AuthOk: | ||||
| 					err, ok = conn.tryAuth(m, waitingForOk, in) | ||||
| 				case AuthContinue: | ||||
| 					err, ok = conn.tryAuth(m, waitingForData, in) | ||||
| 				default: | ||||
| 					panic("dbus: invalid authentication status") | ||||
| 				} | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				if ok { | ||||
| 					if conn.transport.SupportsUnixFDs() { | ||||
| 						err = authWriteLine(conn, []byte("NEGOTIATE_UNIX_FD")) | ||||
| 						if err != nil { | ||||
| 							return err | ||||
| 						} | ||||
| 						line, err := authReadLine(in) | ||||
| 						if err != nil { | ||||
| 							return err | ||||
| 						} | ||||
| 						switch { | ||||
| 						case bytes.Equal(line[0], []byte("AGREE_UNIX_FD")): | ||||
| 							conn.EnableUnixFDs() | ||||
| 							conn.unixFD = true | ||||
| 						case bytes.Equal(line[0], []byte("ERROR")): | ||||
| 						default: | ||||
| 							return errors.New("dbus: authentication protocol error") | ||||
| 						} | ||||
| 					} | ||||
| 					err = authWriteLine(conn.transport, []byte("BEGIN")) | ||||
| 					if err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					go conn.inWorker() | ||||
| 					return nil | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return errors.New("dbus: authentication failed") | ||||
| } | ||||
|  | ||||
| // tryAuth tries to authenticate with m as the mechanism, using state as the | ||||
| // initial authState and in for reading input. It returns (nil, true) on | ||||
| // success, (nil, false) on a REJECTED and (someErr, false) if some other | ||||
| // error occurred. | ||||
| func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, bool) { | ||||
| 	for { | ||||
| 		s, err := authReadLine(in) | ||||
| 		if err != nil { | ||||
| 			return err, false | ||||
| 		} | ||||
| 		switch { | ||||
| 		case state == waitingForData && string(s[0]) == "DATA": | ||||
| 			if len(s) != 2 { | ||||
| 				err = authWriteLine(conn.transport, []byte("ERROR")) | ||||
| 				if err != nil { | ||||
| 					return err, false | ||||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 			data, status := m.HandleData(s[1]) | ||||
| 			switch status { | ||||
| 			case AuthOk, AuthContinue: | ||||
| 				if len(data) != 0 { | ||||
| 					err = authWriteLine(conn.transport, []byte("DATA"), data) | ||||
| 					if err != nil { | ||||
| 						return err, false | ||||
| 					} | ||||
| 				} | ||||
| 				if status == AuthOk { | ||||
| 					state = waitingForOk | ||||
| 				} | ||||
| 			case AuthError: | ||||
| 				err = authWriteLine(conn.transport, []byte("ERROR")) | ||||
| 				if err != nil { | ||||
| 					return err, false | ||||
| 				} | ||||
| 			} | ||||
| 		case state == waitingForData && string(s[0]) == "REJECTED": | ||||
| 			return nil, false | ||||
| 		case state == waitingForData && string(s[0]) == "ERROR": | ||||
| 			err = authWriteLine(conn.transport, []byte("CANCEL")) | ||||
| 			if err != nil { | ||||
| 				return err, false | ||||
| 			} | ||||
| 			state = waitingForReject | ||||
| 		case state == waitingForData && string(s[0]) == "OK": | ||||
| 			if len(s) != 2 { | ||||
| 				err = authWriteLine(conn.transport, []byte("CANCEL")) | ||||
| 				if err != nil { | ||||
| 					return err, false | ||||
| 				} | ||||
| 				state = waitingForReject | ||||
| 			} else { | ||||
| 				conn.uuid = string(s[1]) | ||||
| 				return nil, true | ||||
| 			} | ||||
| 		case state == waitingForData: | ||||
| 			err = authWriteLine(conn.transport, []byte("ERROR")) | ||||
| 			if err != nil { | ||||
| 				return err, false | ||||
| 			} | ||||
| 		case state == waitingForOk && string(s[0]) == "OK": | ||||
| 			if len(s) != 2 { | ||||
| 				err = authWriteLine(conn.transport, []byte("CANCEL")) | ||||
| 				if err != nil { | ||||
| 					return err, false | ||||
| 				} | ||||
| 				state = waitingForReject | ||||
| 			} else { | ||||
| 				conn.uuid = string(s[1]) | ||||
| 				return nil, true | ||||
| 			} | ||||
| 		case state == waitingForOk && string(s[0]) == "DATA": | ||||
| 			err = authWriteLine(conn.transport, []byte("DATA")) | ||||
| 			if err != nil { | ||||
| 				return err, false | ||||
| 			} | ||||
| 		case state == waitingForOk && string(s[0]) == "REJECTED": | ||||
| 			return nil, false | ||||
| 		case state == waitingForOk && string(s[0]) == "ERROR": | ||||
| 			err = authWriteLine(conn.transport, []byte("CANCEL")) | ||||
| 			if err != nil { | ||||
| 				return err, false | ||||
| 			} | ||||
| 			state = waitingForReject | ||||
| 		case state == waitingForOk: | ||||
| 			err = authWriteLine(conn.transport, []byte("ERROR")) | ||||
| 			if err != nil { | ||||
| 				return err, false | ||||
| 			} | ||||
| 		case state == waitingForReject && string(s[0]) == "REJECTED": | ||||
| 			return nil, false | ||||
| 		case state == waitingForReject: | ||||
| 			return errors.New("dbus: authentication protocol error"), false | ||||
| 		default: | ||||
| 			panic("dbus: invalid auth state") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // authReadLine reads a line and separates it into its fields. | ||||
| func authReadLine(in *bufio.Reader) ([][]byte, error) { | ||||
| 	data, err := in.ReadBytes('\n') | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	data = bytes.TrimSuffix(data, []byte("\r\n")) | ||||
| 	return bytes.Split(data, []byte{' '}), nil | ||||
| } | ||||
|  | ||||
| // authWriteLine writes the given line in the authentication protocol format | ||||
| // (elements of data separated by a " " and terminated by "\r\n"). | ||||
| func authWriteLine(out io.Writer, data ...[]byte) error { | ||||
| 	buf := make([]byte, 0) | ||||
| 	for i, v := range data { | ||||
| 		buf = append(buf, v...) | ||||
| 		if i != len(data)-1 { | ||||
| 			buf = append(buf, ' ') | ||||
| 		} | ||||
| 	} | ||||
| 	buf = append(buf, '\r') | ||||
| 	buf = append(buf, '\n') | ||||
| 	n, err := out.Write(buf) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if n != len(buf) { | ||||
| 		return io.ErrUnexpectedEOF | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										16
									
								
								vendor/github.com/godbus/dbus/v5/auth_anonymous.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/godbus/dbus/v5/auth_anonymous.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| package dbus | ||||
|  | ||||
| // AuthAnonymous returns an Auth that uses the ANONYMOUS mechanism. | ||||
| func AuthAnonymous() Auth { | ||||
| 	return &authAnonymous{} | ||||
| } | ||||
|  | ||||
| type authAnonymous struct{} | ||||
|  | ||||
| func (a *authAnonymous) FirstData() (name, resp []byte, status AuthStatus) { | ||||
| 	return []byte("ANONYMOUS"), nil, AuthOk | ||||
| } | ||||
|  | ||||
| func (a *authAnonymous) HandleData(data []byte) (resp []byte, status AuthStatus) { | ||||
| 	return nil, AuthError | ||||
| } | ||||
							
								
								
									
										26
									
								
								vendor/github.com/godbus/dbus/v5/auth_external.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/godbus/dbus/v5/auth_external.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| ) | ||||
|  | ||||
| // AuthExternal returns an Auth that authenticates as the given user with the | ||||
| // EXTERNAL mechanism. | ||||
| func AuthExternal(user string) Auth { | ||||
| 	return authExternal{user} | ||||
| } | ||||
|  | ||||
| // AuthExternal implements the EXTERNAL authentication mechanism. | ||||
| type authExternal struct { | ||||
| 	user string | ||||
| } | ||||
|  | ||||
| func (a authExternal) FirstData() ([]byte, []byte, AuthStatus) { | ||||
| 	b := make([]byte, 2*len(a.user)) | ||||
| 	hex.Encode(b, []byte(a.user)) | ||||
| 	return []byte("EXTERNAL"), b, AuthOk | ||||
| } | ||||
|  | ||||
| func (a authExternal) HandleData(b []byte) ([]byte, AuthStatus) { | ||||
| 	return nil, AuthError | ||||
| } | ||||
							
								
								
									
										102
									
								
								vendor/github.com/godbus/dbus/v5/auth_sha1.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/godbus/dbus/v5/auth_sha1.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/sha1" | ||||
| 	"encoding/hex" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| // AuthCookieSha1 returns an Auth that authenticates as the given user with the | ||||
| // DBUS_COOKIE_SHA1 mechanism. The home parameter should specify the home | ||||
| // directory of the user. | ||||
| func AuthCookieSha1(user, home string) Auth { | ||||
| 	return authCookieSha1{user, home} | ||||
| } | ||||
|  | ||||
| type authCookieSha1 struct { | ||||
| 	user, home string | ||||
| } | ||||
|  | ||||
| func (a authCookieSha1) FirstData() ([]byte, []byte, AuthStatus) { | ||||
| 	b := make([]byte, 2*len(a.user)) | ||||
| 	hex.Encode(b, []byte(a.user)) | ||||
| 	return []byte("DBUS_COOKIE_SHA1"), b, AuthContinue | ||||
| } | ||||
|  | ||||
| func (a authCookieSha1) HandleData(data []byte) ([]byte, AuthStatus) { | ||||
| 	challenge := make([]byte, len(data)/2) | ||||
| 	_, err := hex.Decode(challenge, data) | ||||
| 	if err != nil { | ||||
| 		return nil, AuthError | ||||
| 	} | ||||
| 	b := bytes.Split(challenge, []byte{' '}) | ||||
| 	if len(b) != 3 { | ||||
| 		return nil, AuthError | ||||
| 	} | ||||
| 	context := b[0] | ||||
| 	id := b[1] | ||||
| 	svchallenge := b[2] | ||||
| 	cookie := a.getCookie(context, id) | ||||
| 	if cookie == nil { | ||||
| 		return nil, AuthError | ||||
| 	} | ||||
| 	clchallenge := a.generateChallenge() | ||||
| 	if clchallenge == nil { | ||||
| 		return nil, AuthError | ||||
| 	} | ||||
| 	hash := sha1.New() | ||||
| 	hash.Write(bytes.Join([][]byte{svchallenge, clchallenge, cookie}, []byte{':'})) | ||||
| 	hexhash := make([]byte, 2*hash.Size()) | ||||
| 	hex.Encode(hexhash, hash.Sum(nil)) | ||||
| 	data = append(clchallenge, ' ') | ||||
| 	data = append(data, hexhash...) | ||||
| 	resp := make([]byte, 2*len(data)) | ||||
| 	hex.Encode(resp, data) | ||||
| 	return resp, AuthOk | ||||
| } | ||||
|  | ||||
| // getCookie searches for the cookie identified by id in context and returns | ||||
| // the cookie content or nil. (Since HandleData can't return a specific error, | ||||
| // but only whether an error occurred, this function also doesn't bother to | ||||
| // return an error.) | ||||
| func (a authCookieSha1) getCookie(context, id []byte) []byte { | ||||
| 	file, err := os.Open(a.home + "/.dbus-keyrings/" + string(context)) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	defer file.Close() | ||||
| 	rd := bufio.NewReader(file) | ||||
| 	for { | ||||
| 		line, err := rd.ReadBytes('\n') | ||||
| 		if err != nil { | ||||
| 			return nil | ||||
| 		} | ||||
| 		line = line[:len(line)-1] | ||||
| 		b := bytes.Split(line, []byte{' '}) | ||||
| 		if len(b) != 3 { | ||||
| 			return nil | ||||
| 		} | ||||
| 		if bytes.Equal(b[0], id) { | ||||
| 			return b[2] | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // generateChallenge returns a random, hex-encoded challenge, or nil on error | ||||
| // (see above). | ||||
| func (a authCookieSha1) generateChallenge() []byte { | ||||
| 	b := make([]byte, 16) | ||||
| 	n, err := rand.Read(b) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if n != 16 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	enc := make([]byte, 32) | ||||
| 	hex.Encode(enc, b) | ||||
| 	return enc | ||||
| } | ||||
							
								
								
									
										69
									
								
								vendor/github.com/godbus/dbus/v5/call.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/godbus/dbus/v5/call.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| ) | ||||
|  | ||||
| var errSignature = errors.New("dbus: mismatched signature") | ||||
|  | ||||
| // Call represents a pending or completed method call. | ||||
| type Call struct { | ||||
| 	Destination string | ||||
| 	Path        ObjectPath | ||||
| 	Method      string | ||||
| 	Args        []interface{} | ||||
|  | ||||
| 	// Strobes when the call is complete. | ||||
| 	Done chan *Call | ||||
|  | ||||
| 	// After completion, the error status. If this is non-nil, it may be an | ||||
| 	// error message from the peer (with Error as its type) or some other error. | ||||
| 	Err error | ||||
|  | ||||
| 	// Holds the response once the call is done. | ||||
| 	Body []interface{} | ||||
|  | ||||
| 	// ResponseSequence stores the sequence number of the DBus message containing | ||||
| 	// the call response (or error). This can be compared to the sequence number | ||||
| 	// of other call responses and signals on this connection to determine their | ||||
| 	// relative ordering on the underlying DBus connection. | ||||
| 	// For errors, ResponseSequence is populated only if the error came from a | ||||
| 	// DBusMessage that was received or if there was an error receiving. In case of | ||||
| 	// failure to make the call, ResponseSequence will be NoSequence. | ||||
| 	ResponseSequence Sequence | ||||
|  | ||||
| 	// tracks context and canceler | ||||
| 	ctx         context.Context | ||||
| 	ctxCanceler context.CancelFunc | ||||
| } | ||||
|  | ||||
| func (c *Call) Context() context.Context { | ||||
| 	if c.ctx == nil { | ||||
| 		return context.Background() | ||||
| 	} | ||||
|  | ||||
| 	return c.ctx | ||||
| } | ||||
|  | ||||
| func (c *Call) ContextCancel() { | ||||
| 	if c.ctxCanceler != nil { | ||||
| 		c.ctxCanceler() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Store stores the body of the reply into the provided pointers. It returns | ||||
| // an error if the signatures of the body and retvalues don't match, or if | ||||
| // the error status is not nil. | ||||
| func (c *Call) Store(retvalues ...interface{}) error { | ||||
| 	if c.Err != nil { | ||||
| 		return c.Err | ||||
| 	} | ||||
|  | ||||
| 	return Store(c.Body, retvalues...) | ||||
| } | ||||
|  | ||||
| func (c *Call) done() { | ||||
| 	c.Done <- c | ||||
| 	c.ContextCancel() | ||||
| } | ||||
							
								
								
									
										996
									
								
								vendor/github.com/godbus/dbus/v5/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										996
									
								
								vendor/github.com/godbus/dbus/v5/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,996 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	systemBus     *Conn | ||||
| 	systemBusLck  sync.Mutex | ||||
| 	sessionBus    *Conn | ||||
| 	sessionBusLck sync.Mutex | ||||
| ) | ||||
|  | ||||
| // ErrClosed is the error returned by calls on a closed connection. | ||||
| var ErrClosed = errors.New("dbus: connection closed by user") | ||||
|  | ||||
| // Conn represents a connection to a message bus (usually, the system or | ||||
| // session bus). | ||||
| // | ||||
| // Connections are either shared or private. Shared connections | ||||
| // are shared between calls to the functions that return them. As a result, | ||||
| // the methods Close, Auth and Hello must not be called on them. | ||||
| // | ||||
| // Multiple goroutines may invoke methods on a connection simultaneously. | ||||
| type Conn struct { | ||||
| 	transport | ||||
|  | ||||
| 	ctx       context.Context | ||||
| 	cancelCtx context.CancelFunc | ||||
|  | ||||
| 	closeOnce sync.Once | ||||
| 	closeErr  error | ||||
|  | ||||
| 	busObj BusObject | ||||
| 	unixFD bool | ||||
| 	uuid   string | ||||
|  | ||||
| 	handler       Handler | ||||
| 	signalHandler SignalHandler | ||||
| 	serialGen     SerialGenerator | ||||
| 	inInt         Interceptor | ||||
| 	outInt        Interceptor | ||||
| 	auth          []Auth | ||||
|  | ||||
| 	names      *nameTracker | ||||
| 	calls      *callTracker | ||||
| 	outHandler *outputHandler | ||||
|  | ||||
| 	eavesdropped    chan<- *Message | ||||
| 	eavesdroppedLck sync.Mutex | ||||
| } | ||||
|  | ||||
| // SessionBus returns a shared connection to the session bus, connecting to it | ||||
| // if not already done. | ||||
| func SessionBus() (conn *Conn, err error) { | ||||
| 	sessionBusLck.Lock() | ||||
| 	defer sessionBusLck.Unlock() | ||||
| 	if sessionBus != nil && | ||||
| 		sessionBus.Connected() { | ||||
| 		return sessionBus, nil | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if conn != nil { | ||||
| 			sessionBus = conn | ||||
| 		} | ||||
| 	}() | ||||
| 	conn, err = ConnectSessionBus() | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func getSessionBusAddress(autolaunch bool) (string, error) { | ||||
| 	if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" { | ||||
| 		return address, nil | ||||
|  | ||||
| 	} else if address := tryDiscoverDbusSessionBusAddress(); address != "" { | ||||
| 		os.Setenv("DBUS_SESSION_BUS_ADDRESS", address) | ||||
| 		return address, nil | ||||
| 	} | ||||
| 	if !autolaunch { | ||||
| 		return "", errors.New("dbus: couldn't determine address of session bus") | ||||
| 	} | ||||
| 	return getSessionBusPlatformAddress() | ||||
| } | ||||
|  | ||||
| // SessionBusPrivate returns a new private connection to the session bus. | ||||
| func SessionBusPrivate(opts ...ConnOption) (*Conn, error) { | ||||
| 	address, err := getSessionBusAddress(true) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return Dial(address, opts...) | ||||
| } | ||||
|  | ||||
| // SessionBusPrivate returns a new private connection to the session bus.  If | ||||
| // the session bus is not already open, do not attempt to launch it. | ||||
| func SessionBusPrivateNoAutoStartup(opts ...ConnOption) (*Conn, error) { | ||||
| 	address, err := getSessionBusAddress(false) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return Dial(address, opts...) | ||||
| } | ||||
|  | ||||
| // SessionBusPrivate returns a new private connection to the session bus. | ||||
| // | ||||
| // Deprecated: use SessionBusPrivate with options instead. | ||||
| func SessionBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) { | ||||
| 	return SessionBusPrivate(WithHandler(handler), WithSignalHandler(signalHandler)) | ||||
| } | ||||
|  | ||||
| // SystemBus returns a shared connection to the system bus, connecting to it if | ||||
| // not already done. | ||||
| func SystemBus() (conn *Conn, err error) { | ||||
| 	systemBusLck.Lock() | ||||
| 	defer systemBusLck.Unlock() | ||||
| 	if systemBus != nil && | ||||
| 		systemBus.Connected() { | ||||
| 		return systemBus, nil | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if conn != nil { | ||||
| 			systemBus = conn | ||||
| 		} | ||||
| 	}() | ||||
| 	conn, err = ConnectSystemBus() | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // ConnectSessionBus connects to the session bus. | ||||
| func ConnectSessionBus(opts ...ConnOption) (*Conn, error) { | ||||
| 	address, err := getSessionBusAddress(true) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return Connect(address, opts...) | ||||
| } | ||||
|  | ||||
| // ConnectSystemBus connects to the system bus. | ||||
| func ConnectSystemBus(opts ...ConnOption) (*Conn, error) { | ||||
| 	return Connect(getSystemBusPlatformAddress(), opts...) | ||||
| } | ||||
|  | ||||
| // Connect connects to the given address. | ||||
| // | ||||
| // Returned connection is ready to use and doesn't require calling | ||||
| // Auth and Hello methods to make it usable. | ||||
| func Connect(address string, opts ...ConnOption) (*Conn, error) { | ||||
| 	conn, err := Dial(address, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err = conn.Auth(conn.auth); err != nil { | ||||
| 		_ = conn.Close() | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err = conn.Hello(); err != nil { | ||||
| 		_ = conn.Close() | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return conn, nil | ||||
| } | ||||
|  | ||||
| // SystemBusPrivate returns a new private connection to the system bus. | ||||
| // Note: this connection is not ready to use. One must perform Auth and Hello | ||||
| // on the connection before it is usable. | ||||
| func SystemBusPrivate(opts ...ConnOption) (*Conn, error) { | ||||
| 	return Dial(getSystemBusPlatformAddress(), opts...) | ||||
| } | ||||
|  | ||||
| // SystemBusPrivateHandler returns a new private connection to the system bus, using the provided handlers. | ||||
| // | ||||
| // Deprecated: use SystemBusPrivate with options instead. | ||||
| func SystemBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) { | ||||
| 	return SystemBusPrivate(WithHandler(handler), WithSignalHandler(signalHandler)) | ||||
| } | ||||
|  | ||||
| // Dial establishes a new private connection to the message bus specified by address. | ||||
| func Dial(address string, opts ...ConnOption) (*Conn, error) { | ||||
| 	tr, err := getTransport(address) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return newConn(tr, opts...) | ||||
| } | ||||
|  | ||||
| // DialHandler establishes a new private connection to the message bus specified by address, using the supplied handlers. | ||||
| // | ||||
| // Deprecated: use Dial with options instead. | ||||
| func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) { | ||||
| 	return Dial(address, WithHandler(handler), WithSignalHandler(signalHandler)) | ||||
| } | ||||
|  | ||||
| // ConnOption is a connection option. | ||||
| type ConnOption func(conn *Conn) error | ||||
|  | ||||
| // WithHandler overrides the default handler. | ||||
| func WithHandler(handler Handler) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.handler = handler | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithSignalHandler overrides the default signal handler. | ||||
| func WithSignalHandler(handler SignalHandler) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.signalHandler = handler | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithSerialGenerator overrides the default signals generator. | ||||
| func WithSerialGenerator(gen SerialGenerator) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.serialGen = gen | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithAuth sets authentication methods for the auth conversation. | ||||
| func WithAuth(methods ...Auth) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.auth = methods | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Interceptor intercepts incoming and outgoing messages. | ||||
| type Interceptor func(msg *Message) | ||||
|  | ||||
| // WithIncomingInterceptor sets the given interceptor for incoming messages. | ||||
| func WithIncomingInterceptor(interceptor Interceptor) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.inInt = interceptor | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithOutgoingInterceptor sets the given interceptor for outgoing messages. | ||||
| func WithOutgoingInterceptor(interceptor Interceptor) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.outInt = interceptor | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithContext overrides  the default context for the connection. | ||||
| func WithContext(ctx context.Context) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.ctx = ctx | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewConn creates a new private *Conn from an already established connection. | ||||
| func NewConn(conn io.ReadWriteCloser, opts ...ConnOption) (*Conn, error) { | ||||
| 	return newConn(genericTransport{conn}, opts...) | ||||
| } | ||||
|  | ||||
| // NewConnHandler creates a new private *Conn from an already established connection, using the supplied handlers. | ||||
| // | ||||
| // Deprecated: use NewConn with options instead. | ||||
| func NewConnHandler(conn io.ReadWriteCloser, handler Handler, signalHandler SignalHandler) (*Conn, error) { | ||||
| 	return NewConn(genericTransport{conn}, WithHandler(handler), WithSignalHandler(signalHandler)) | ||||
| } | ||||
|  | ||||
| // newConn creates a new *Conn from a transport. | ||||
| func newConn(tr transport, opts ...ConnOption) (*Conn, error) { | ||||
| 	conn := new(Conn) | ||||
| 	conn.transport = tr | ||||
| 	for _, opt := range opts { | ||||
| 		if err := opt(conn); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	if conn.ctx == nil { | ||||
| 		conn.ctx = context.Background() | ||||
| 	} | ||||
| 	conn.ctx, conn.cancelCtx = context.WithCancel(conn.ctx) | ||||
|  | ||||
| 	conn.calls = newCallTracker() | ||||
| 	if conn.handler == nil { | ||||
| 		conn.handler = NewDefaultHandler() | ||||
| 	} | ||||
| 	if conn.signalHandler == nil { | ||||
| 		conn.signalHandler = NewDefaultSignalHandler() | ||||
| 	} | ||||
| 	if conn.serialGen == nil { | ||||
| 		conn.serialGen = newSerialGenerator() | ||||
| 	} | ||||
| 	conn.outHandler = &outputHandler{conn: conn} | ||||
| 	conn.names = newNameTracker() | ||||
| 	conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus") | ||||
|  | ||||
| 	go func() { | ||||
| 		<-conn.ctx.Done() | ||||
| 		conn.Close() | ||||
| 	}() | ||||
| 	return conn, nil | ||||
| } | ||||
|  | ||||
| // BusObject returns the object owned by the bus daemon which handles | ||||
| // administrative requests. | ||||
| func (conn *Conn) BusObject() BusObject { | ||||
| 	return conn.busObj | ||||
| } | ||||
|  | ||||
| // Close closes the connection. Any blocked operations will return with errors | ||||
| // and the channels passed to Eavesdrop and Signal are closed. This method must | ||||
| // not be called on shared connections. | ||||
| func (conn *Conn) Close() error { | ||||
| 	conn.closeOnce.Do(func() { | ||||
| 		conn.outHandler.close() | ||||
| 		if term, ok := conn.signalHandler.(Terminator); ok { | ||||
| 			term.Terminate() | ||||
| 		} | ||||
|  | ||||
| 		if term, ok := conn.handler.(Terminator); ok { | ||||
| 			term.Terminate() | ||||
| 		} | ||||
|  | ||||
| 		conn.eavesdroppedLck.Lock() | ||||
| 		if conn.eavesdropped != nil { | ||||
| 			close(conn.eavesdropped) | ||||
| 		} | ||||
| 		conn.eavesdroppedLck.Unlock() | ||||
|  | ||||
| 		conn.cancelCtx() | ||||
|  | ||||
| 		conn.closeErr = conn.transport.Close() | ||||
| 	}) | ||||
| 	return conn.closeErr | ||||
| } | ||||
|  | ||||
| // Context returns the context associated with the connection.  The | ||||
| // context will be cancelled when the connection is closed. | ||||
| func (conn *Conn) Context() context.Context { | ||||
| 	return conn.ctx | ||||
| } | ||||
|  | ||||
| // Connected returns whether conn is connected | ||||
| func (conn *Conn) Connected() bool { | ||||
| 	return conn.ctx.Err() == nil | ||||
| } | ||||
|  | ||||
| // Eavesdrop causes conn to send all incoming messages to the given channel | ||||
| // without further processing. Method replies, errors and signals will not be | ||||
| // sent to the appropriate channels and method calls will not be handled. If nil | ||||
| // is passed, the normal behaviour is restored. | ||||
| // | ||||
| // The caller has to make sure that ch is sufficiently buffered; | ||||
| // if a message arrives when a write to ch is not possible, the message is | ||||
| // discarded. | ||||
| func (conn *Conn) Eavesdrop(ch chan<- *Message) { | ||||
| 	conn.eavesdroppedLck.Lock() | ||||
| 	conn.eavesdropped = ch | ||||
| 	conn.eavesdroppedLck.Unlock() | ||||
| } | ||||
|  | ||||
| // getSerial returns an unused serial. | ||||
| func (conn *Conn) getSerial() uint32 { | ||||
| 	return conn.serialGen.GetSerial() | ||||
| } | ||||
|  | ||||
| // Hello sends the initial org.freedesktop.DBus.Hello call. This method must be | ||||
| // called after authentication, but before sending any other messages to the | ||||
| // bus. Hello must not be called for shared connections. | ||||
| func (conn *Conn) Hello() error { | ||||
| 	var s string | ||||
| 	err := conn.busObj.Call("org.freedesktop.DBus.Hello", 0).Store(&s) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	conn.names.acquireUniqueConnectionName(s) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // inWorker runs in an own goroutine, reading incoming messages from the | ||||
| // transport and dispatching them appropriately. | ||||
| func (conn *Conn) inWorker() { | ||||
| 	sequenceGen := newSequenceGenerator() | ||||
| 	for { | ||||
| 		msg, err := conn.ReadMessage() | ||||
| 		if err != nil { | ||||
| 			if _, ok := err.(InvalidMessageError); !ok { | ||||
| 				// Some read error occurred (usually EOF); we can't really do | ||||
| 				// anything but to shut down all stuff and returns errors to all | ||||
| 				// pending replies. | ||||
| 				conn.Close() | ||||
| 				conn.calls.finalizeAllWithError(sequenceGen, err) | ||||
| 				return | ||||
| 			} | ||||
| 			// invalid messages are ignored | ||||
| 			continue | ||||
| 		} | ||||
| 		conn.eavesdroppedLck.Lock() | ||||
| 		if conn.eavesdropped != nil { | ||||
| 			select { | ||||
| 			case conn.eavesdropped <- msg: | ||||
| 			default: | ||||
| 			} | ||||
| 			conn.eavesdroppedLck.Unlock() | ||||
| 			continue | ||||
| 		} | ||||
| 		conn.eavesdroppedLck.Unlock() | ||||
| 		dest, _ := msg.Headers[FieldDestination].value.(string) | ||||
| 		found := dest == "" || | ||||
| 			!conn.names.uniqueNameIsKnown() || | ||||
| 			conn.names.isKnownName(dest) | ||||
| 		if !found { | ||||
| 			// Eavesdropped a message, but no channel for it is registered. | ||||
| 			// Ignore it. | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if conn.inInt != nil { | ||||
| 			conn.inInt(msg) | ||||
| 		} | ||||
| 		sequence := sequenceGen.next() | ||||
| 		switch msg.Type { | ||||
| 		case TypeError: | ||||
| 			conn.serialGen.RetireSerial(conn.calls.handleDBusError(sequence, msg)) | ||||
| 		case TypeMethodReply: | ||||
| 			conn.serialGen.RetireSerial(conn.calls.handleReply(sequence, msg)) | ||||
| 		case TypeSignal: | ||||
| 			conn.handleSignal(sequence, msg) | ||||
| 		case TypeMethodCall: | ||||
| 			go conn.handleCall(msg) | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (conn *Conn) handleSignal(sequence Sequence, msg *Message) { | ||||
| 	iface := msg.Headers[FieldInterface].value.(string) | ||||
| 	member := msg.Headers[FieldMember].value.(string) | ||||
| 	// as per http://dbus.freedesktop.org/doc/dbus-specification.html , | ||||
| 	// sender is optional for signals. | ||||
| 	sender, _ := msg.Headers[FieldSender].value.(string) | ||||
| 	if iface == "org.freedesktop.DBus" && sender == "org.freedesktop.DBus" { | ||||
| 		if member == "NameLost" { | ||||
| 			// If we lost the name on the bus, remove it from our | ||||
| 			// tracking list. | ||||
| 			name, ok := msg.Body[0].(string) | ||||
| 			if !ok { | ||||
| 				panic("Unable to read the lost name") | ||||
| 			} | ||||
| 			conn.names.loseName(name) | ||||
| 		} else if member == "NameAcquired" { | ||||
| 			// If we acquired the name on the bus, add it to our | ||||
| 			// tracking list. | ||||
| 			name, ok := msg.Body[0].(string) | ||||
| 			if !ok { | ||||
| 				panic("Unable to read the acquired name") | ||||
| 			} | ||||
| 			conn.names.acquireName(name) | ||||
| 		} | ||||
| 	} | ||||
| 	signal := &Signal{ | ||||
| 		Sender:   sender, | ||||
| 		Path:     msg.Headers[FieldPath].value.(ObjectPath), | ||||
| 		Name:     iface + "." + member, | ||||
| 		Body:     msg.Body, | ||||
| 		Sequence: sequence, | ||||
| 	} | ||||
| 	conn.signalHandler.DeliverSignal(iface, member, signal) | ||||
| } | ||||
|  | ||||
| // Names returns the list of all names that are currently owned by this | ||||
| // connection. The slice is always at least one element long, the first element | ||||
| // being the unique name of the connection. | ||||
| func (conn *Conn) Names() []string { | ||||
| 	return conn.names.listKnownNames() | ||||
| } | ||||
|  | ||||
| // Object returns the object identified by the given destination name and path. | ||||
| func (conn *Conn) Object(dest string, path ObjectPath) BusObject { | ||||
| 	return &Object{conn, dest, path} | ||||
| } | ||||
|  | ||||
| func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) { | ||||
| 	if msg.serial == 0 { | ||||
| 		msg.serial = conn.getSerial() | ||||
| 	} | ||||
| 	if conn.outInt != nil { | ||||
| 		conn.outInt(msg) | ||||
| 	} | ||||
| 	err := conn.outHandler.sendAndIfClosed(msg, ifClosed) | ||||
| 	if err != nil { | ||||
| 		conn.handleSendError(msg, err) | ||||
| 	} else if msg.Type != TypeMethodCall { | ||||
| 		conn.serialGen.RetireSerial(msg.serial) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (conn *Conn) handleSendError(msg *Message, err error) { | ||||
| 	if msg.Type == TypeMethodCall { | ||||
| 		conn.calls.handleSendError(msg, err) | ||||
| 	} else if msg.Type == TypeMethodReply { | ||||
| 		if _, ok := err.(FormatError); ok { | ||||
| 			conn.sendError(err, msg.Headers[FieldDestination].value.(string), msg.Headers[FieldReplySerial].value.(uint32)) | ||||
| 		} | ||||
| 	} | ||||
| 	conn.serialGen.RetireSerial(msg.serial) | ||||
| } | ||||
|  | ||||
| // Send sends the given message to the message bus. You usually don't need to | ||||
| // use this; use the higher-level equivalents (Call / Go, Emit and Export) | ||||
| // instead. If msg is a method call and NoReplyExpected is not set, a non-nil | ||||
| // call is returned and the same value is sent to ch (which must be buffered) | ||||
| // once the call is complete. Otherwise, ch is ignored and a Call structure is | ||||
| // returned of which only the Err member is valid. | ||||
| func (conn *Conn) Send(msg *Message, ch chan *Call) *Call { | ||||
| 	return conn.send(context.Background(), msg, ch) | ||||
| } | ||||
|  | ||||
| // SendWithContext acts like Send but takes a context | ||||
| func (conn *Conn) SendWithContext(ctx context.Context, msg *Message, ch chan *Call) *Call { | ||||
| 	return conn.send(ctx, msg, ch) | ||||
| } | ||||
|  | ||||
| func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call { | ||||
| 	if ctx == nil { | ||||
| 		panic("nil context") | ||||
| 	} | ||||
| 	if ch == nil { | ||||
| 		ch = make(chan *Call, 1) | ||||
| 	} else if cap(ch) == 0 { | ||||
| 		panic("dbus: unbuffered channel passed to (*Conn).Send") | ||||
| 	} | ||||
|  | ||||
| 	var call *Call | ||||
| 	ctx, canceler := context.WithCancel(ctx) | ||||
| 	msg.serial = conn.getSerial() | ||||
| 	if msg.Type == TypeMethodCall && msg.Flags&FlagNoReplyExpected == 0 { | ||||
| 		call = new(Call) | ||||
| 		call.Destination, _ = msg.Headers[FieldDestination].value.(string) | ||||
| 		call.Path, _ = msg.Headers[FieldPath].value.(ObjectPath) | ||||
| 		iface, _ := msg.Headers[FieldInterface].value.(string) | ||||
| 		member, _ := msg.Headers[FieldMember].value.(string) | ||||
| 		call.Method = iface + "." + member | ||||
| 		call.Args = msg.Body | ||||
| 		call.Done = ch | ||||
| 		call.ctx = ctx | ||||
| 		call.ctxCanceler = canceler | ||||
| 		conn.calls.track(msg.serial, call) | ||||
| 		if ctx.Err() != nil { | ||||
| 			// short path: don't even send the message if context already cancelled | ||||
| 			conn.calls.handleSendError(msg, ctx.Err()) | ||||
| 			return call | ||||
| 		} | ||||
| 		go func() { | ||||
| 			<-ctx.Done() | ||||
| 			conn.calls.handleSendError(msg, ctx.Err()) | ||||
| 		}() | ||||
| 		conn.sendMessageAndIfClosed(msg, func() { | ||||
| 			conn.calls.handleSendError(msg, ErrClosed) | ||||
| 			canceler() | ||||
| 		}) | ||||
| 	} else { | ||||
| 		canceler() | ||||
| 		call = &Call{Err: nil, Done: ch} | ||||
| 		ch <- call | ||||
| 		conn.sendMessageAndIfClosed(msg, func() { | ||||
| 			call = &Call{Err: ErrClosed} | ||||
| 		}) | ||||
| 	} | ||||
| 	return call | ||||
| } | ||||
|  | ||||
| // sendError creates an error message corresponding to the parameters and sends | ||||
| // it to conn.out. | ||||
| func (conn *Conn) sendError(err error, dest string, serial uint32) { | ||||
| 	var e *Error | ||||
| 	switch em := err.(type) { | ||||
| 	case Error: | ||||
| 		e = &em | ||||
| 	case *Error: | ||||
| 		e = em | ||||
| 	case DBusError: | ||||
| 		name, body := em.DBusError() | ||||
| 		e = NewError(name, body) | ||||
| 	default: | ||||
| 		e = MakeFailedError(err) | ||||
| 	} | ||||
| 	msg := new(Message) | ||||
| 	msg.Type = TypeError | ||||
| 	msg.Headers = make(map[HeaderField]Variant) | ||||
| 	if dest != "" { | ||||
| 		msg.Headers[FieldDestination] = MakeVariant(dest) | ||||
| 	} | ||||
| 	msg.Headers[FieldErrorName] = MakeVariant(e.Name) | ||||
| 	msg.Headers[FieldReplySerial] = MakeVariant(serial) | ||||
| 	msg.Body = e.Body | ||||
| 	if len(e.Body) > 0 { | ||||
| 		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(e.Body...)) | ||||
| 	} | ||||
| 	conn.sendMessageAndIfClosed(msg, nil) | ||||
| } | ||||
|  | ||||
| // sendReply creates a method reply message corresponding to the parameters and | ||||
| // sends it to conn.out. | ||||
| func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) { | ||||
| 	msg := new(Message) | ||||
| 	msg.Type = TypeMethodReply | ||||
| 	msg.Headers = make(map[HeaderField]Variant) | ||||
| 	if dest != "" { | ||||
| 		msg.Headers[FieldDestination] = MakeVariant(dest) | ||||
| 	} | ||||
| 	msg.Headers[FieldReplySerial] = MakeVariant(serial) | ||||
| 	msg.Body = values | ||||
| 	if len(values) > 0 { | ||||
| 		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...)) | ||||
| 	} | ||||
| 	conn.sendMessageAndIfClosed(msg, nil) | ||||
| } | ||||
|  | ||||
| // AddMatchSignal registers the given match rule to receive broadcast | ||||
| // signals based on their contents. | ||||
| func (conn *Conn) AddMatchSignal(options ...MatchOption) error { | ||||
| 	return conn.AddMatchSignalContext(context.Background(), options...) | ||||
| } | ||||
|  | ||||
| // AddMatchSignalContext acts like AddMatchSignal but takes a context. | ||||
| func (conn *Conn) AddMatchSignalContext(ctx context.Context, options ...MatchOption) error { | ||||
| 	options = append([]MatchOption{withMatchType("signal")}, options...) | ||||
| 	return conn.busObj.CallWithContext( | ||||
| 		ctx, | ||||
| 		"org.freedesktop.DBus.AddMatch", 0, | ||||
| 		formatMatchOptions(options), | ||||
| 	).Store() | ||||
| } | ||||
|  | ||||
| // RemoveMatchSignal removes the first rule that matches previously registered with AddMatchSignal. | ||||
| func (conn *Conn) RemoveMatchSignal(options ...MatchOption) error { | ||||
| 	return conn.RemoveMatchSignalContext(context.Background(), options...) | ||||
| } | ||||
|  | ||||
| // RemoveMatchSignalContext acts like RemoveMatchSignal but takes a context. | ||||
| func (conn *Conn) RemoveMatchSignalContext(ctx context.Context, options ...MatchOption) error { | ||||
| 	options = append([]MatchOption{withMatchType("signal")}, options...) | ||||
| 	return conn.busObj.CallWithContext( | ||||
| 		ctx, | ||||
| 		"org.freedesktop.DBus.RemoveMatch", 0, | ||||
| 		formatMatchOptions(options), | ||||
| 	).Store() | ||||
| } | ||||
|  | ||||
| // Signal registers the given channel to be passed all received signal messages. | ||||
| // | ||||
| // Multiple of these channels can be registered at the same time. The channel is | ||||
| // closed if the Conn is closed; it should not be closed by the caller before | ||||
| // RemoveSignal was called on it. | ||||
| // | ||||
| // These channels are "overwritten" by Eavesdrop; i.e., if there currently is a | ||||
| // channel for eavesdropped messages, this channel receives all signals, and | ||||
| // none of the channels passed to Signal will receive any signals. | ||||
| // | ||||
| // Panics if the signal handler is not a `SignalRegistrar`. | ||||
| func (conn *Conn) Signal(ch chan<- *Signal) { | ||||
| 	handler, ok := conn.signalHandler.(SignalRegistrar) | ||||
| 	if !ok { | ||||
| 		panic("cannot use this method with a non SignalRegistrar handler") | ||||
| 	} | ||||
| 	handler.AddSignal(ch) | ||||
| } | ||||
|  | ||||
| // RemoveSignal removes the given channel from the list of the registered channels. | ||||
| // | ||||
| // Panics if the signal handler is not a `SignalRegistrar`. | ||||
| func (conn *Conn) RemoveSignal(ch chan<- *Signal) { | ||||
| 	handler, ok := conn.signalHandler.(SignalRegistrar) | ||||
| 	if !ok { | ||||
| 		panic("cannot use this method with a non SignalRegistrar handler") | ||||
| 	} | ||||
| 	handler.RemoveSignal(ch) | ||||
| } | ||||
|  | ||||
| // SupportsUnixFDs returns whether the underlying transport supports passing of | ||||
| // unix file descriptors. If this is false, method calls containing unix file | ||||
| // descriptors will return an error and emitted signals containing them will | ||||
| // not be sent. | ||||
| func (conn *Conn) SupportsUnixFDs() bool { | ||||
| 	return conn.unixFD | ||||
| } | ||||
|  | ||||
| // Error represents a D-Bus message of type Error. | ||||
| type Error struct { | ||||
| 	Name string | ||||
| 	Body []interface{} | ||||
| } | ||||
|  | ||||
| func NewError(name string, body []interface{}) *Error { | ||||
| 	return &Error{name, body} | ||||
| } | ||||
|  | ||||
| func (e Error) Error() string { | ||||
| 	if len(e.Body) >= 1 { | ||||
| 		s, ok := e.Body[0].(string) | ||||
| 		if ok { | ||||
| 			return s | ||||
| 		} | ||||
| 	} | ||||
| 	return e.Name | ||||
| } | ||||
|  | ||||
| // Signal represents a D-Bus message of type Signal. The name member is given in | ||||
| // "interface.member" notation, e.g. org.freedesktop.D-Bus.NameLost. | ||||
| type Signal struct { | ||||
| 	Sender   string | ||||
| 	Path     ObjectPath | ||||
| 	Name     string | ||||
| 	Body     []interface{} | ||||
| 	Sequence Sequence | ||||
| } | ||||
|  | ||||
| // transport is a D-Bus transport. | ||||
| type transport interface { | ||||
| 	// Read and Write raw data (for example, for the authentication protocol). | ||||
| 	io.ReadWriteCloser | ||||
|  | ||||
| 	// Send the initial null byte used for the EXTERNAL mechanism. | ||||
| 	SendNullByte() error | ||||
|  | ||||
| 	// Returns whether this transport supports passing Unix FDs. | ||||
| 	SupportsUnixFDs() bool | ||||
|  | ||||
| 	// Signal the transport that Unix FD passing is enabled for this connection. | ||||
| 	EnableUnixFDs() | ||||
|  | ||||
| 	// Read / send a message, handling things like Unix FDs. | ||||
| 	ReadMessage() (*Message, error) | ||||
| 	SendMessage(*Message) error | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	transports = make(map[string]func(string) (transport, error)) | ||||
| ) | ||||
|  | ||||
| func getTransport(address string) (transport, error) { | ||||
| 	var err error | ||||
| 	var t transport | ||||
|  | ||||
| 	addresses := strings.Split(address, ";") | ||||
| 	for _, v := range addresses { | ||||
| 		i := strings.IndexRune(v, ':') | ||||
| 		if i == -1 { | ||||
| 			err = errors.New("dbus: invalid bus address (no transport)") | ||||
| 			continue | ||||
| 		} | ||||
| 		f := transports[v[:i]] | ||||
| 		if f == nil { | ||||
| 			err = errors.New("dbus: invalid bus address (invalid or unsupported transport)") | ||||
| 			continue | ||||
| 		} | ||||
| 		t, err = f(v[i+1:]) | ||||
| 		if err == nil { | ||||
| 			return t, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, err | ||||
| } | ||||
|  | ||||
| // getKey gets a key from a the list of keys. Returns "" on error / not found... | ||||
| func getKey(s, key string) string { | ||||
| 	for _, keyEqualsValue := range strings.Split(s, ",") { | ||||
| 		keyValue := strings.SplitN(keyEqualsValue, "=", 2) | ||||
| 		if len(keyValue) == 2 && keyValue[0] == key { | ||||
| 			val, err := UnescapeBusAddressValue(keyValue[1]) | ||||
| 			if err != nil { | ||||
| 				// No way to return an error. | ||||
| 				return "" | ||||
| 			} | ||||
| 			return val | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type outputHandler struct { | ||||
| 	conn    *Conn | ||||
| 	sendLck sync.Mutex | ||||
| 	closed  struct { | ||||
| 		isClosed bool | ||||
| 		lck      sync.RWMutex | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *outputHandler) sendAndIfClosed(msg *Message, ifClosed func()) error { | ||||
| 	h.closed.lck.RLock() | ||||
| 	defer h.closed.lck.RUnlock() | ||||
| 	if h.closed.isClosed { | ||||
| 		if ifClosed != nil { | ||||
| 			ifClosed() | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| 	h.sendLck.Lock() | ||||
| 	defer h.sendLck.Unlock() | ||||
| 	return h.conn.SendMessage(msg) | ||||
| } | ||||
|  | ||||
| func (h *outputHandler) close() { | ||||
| 	h.closed.lck.Lock() | ||||
| 	defer h.closed.lck.Unlock() | ||||
| 	h.closed.isClosed = true | ||||
| } | ||||
|  | ||||
| type serialGenerator struct { | ||||
| 	lck        sync.Mutex | ||||
| 	nextSerial uint32 | ||||
| 	serialUsed map[uint32]bool | ||||
| } | ||||
|  | ||||
| func newSerialGenerator() *serialGenerator { | ||||
| 	return &serialGenerator{ | ||||
| 		serialUsed: map[uint32]bool{0: true}, | ||||
| 		nextSerial: 1, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (gen *serialGenerator) GetSerial() uint32 { | ||||
| 	gen.lck.Lock() | ||||
| 	defer gen.lck.Unlock() | ||||
| 	n := gen.nextSerial | ||||
| 	for gen.serialUsed[n] { | ||||
| 		n++ | ||||
| 	} | ||||
| 	gen.serialUsed[n] = true | ||||
| 	gen.nextSerial = n + 1 | ||||
| 	return n | ||||
| } | ||||
|  | ||||
| func (gen *serialGenerator) RetireSerial(serial uint32) { | ||||
| 	gen.lck.Lock() | ||||
| 	defer gen.lck.Unlock() | ||||
| 	delete(gen.serialUsed, serial) | ||||
| } | ||||
|  | ||||
| type nameTracker struct { | ||||
| 	lck    sync.RWMutex | ||||
| 	unique string | ||||
| 	names  map[string]struct{} | ||||
| } | ||||
|  | ||||
| func newNameTracker() *nameTracker { | ||||
| 	return &nameTracker{names: map[string]struct{}{}} | ||||
| } | ||||
| func (tracker *nameTracker) acquireUniqueConnectionName(name string) { | ||||
| 	tracker.lck.Lock() | ||||
| 	defer tracker.lck.Unlock() | ||||
| 	tracker.unique = name | ||||
| } | ||||
| func (tracker *nameTracker) acquireName(name string) { | ||||
| 	tracker.lck.Lock() | ||||
| 	defer tracker.lck.Unlock() | ||||
| 	tracker.names[name] = struct{}{} | ||||
| } | ||||
| func (tracker *nameTracker) loseName(name string) { | ||||
| 	tracker.lck.Lock() | ||||
| 	defer tracker.lck.Unlock() | ||||
| 	delete(tracker.names, name) | ||||
| } | ||||
|  | ||||
| func (tracker *nameTracker) uniqueNameIsKnown() bool { | ||||
| 	tracker.lck.RLock() | ||||
| 	defer tracker.lck.RUnlock() | ||||
| 	return tracker.unique != "" | ||||
| } | ||||
| func (tracker *nameTracker) isKnownName(name string) bool { | ||||
| 	tracker.lck.RLock() | ||||
| 	defer tracker.lck.RUnlock() | ||||
| 	_, ok := tracker.names[name] | ||||
| 	return ok || name == tracker.unique | ||||
| } | ||||
| func (tracker *nameTracker) listKnownNames() []string { | ||||
| 	tracker.lck.RLock() | ||||
| 	defer tracker.lck.RUnlock() | ||||
| 	out := make([]string, 0, len(tracker.names)+1) | ||||
| 	out = append(out, tracker.unique) | ||||
| 	for k := range tracker.names { | ||||
| 		out = append(out, k) | ||||
| 	} | ||||
| 	return out | ||||
| } | ||||
|  | ||||
| type callTracker struct { | ||||
| 	calls map[uint32]*Call | ||||
| 	lck   sync.RWMutex | ||||
| } | ||||
|  | ||||
| func newCallTracker() *callTracker { | ||||
| 	return &callTracker{calls: map[uint32]*Call{}} | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) track(sn uint32, call *Call) { | ||||
| 	tracker.lck.Lock() | ||||
| 	tracker.calls[sn] = call | ||||
| 	tracker.lck.Unlock() | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) handleReply(sequence Sequence, msg *Message) uint32 { | ||||
| 	serial := msg.Headers[FieldReplySerial].value.(uint32) | ||||
| 	tracker.lck.RLock() | ||||
| 	_, ok := tracker.calls[serial] | ||||
| 	tracker.lck.RUnlock() | ||||
| 	if ok { | ||||
| 		tracker.finalizeWithBody(serial, sequence, msg.Body) | ||||
| 	} | ||||
| 	return serial | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) handleDBusError(sequence Sequence, msg *Message) uint32 { | ||||
| 	serial := msg.Headers[FieldReplySerial].value.(uint32) | ||||
| 	tracker.lck.RLock() | ||||
| 	_, ok := tracker.calls[serial] | ||||
| 	tracker.lck.RUnlock() | ||||
| 	if ok { | ||||
| 		name, _ := msg.Headers[FieldErrorName].value.(string) | ||||
| 		tracker.finalizeWithError(serial, sequence, Error{name, msg.Body}) | ||||
| 	} | ||||
| 	return serial | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) handleSendError(msg *Message, err error) { | ||||
| 	if err == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	tracker.lck.RLock() | ||||
| 	_, ok := tracker.calls[msg.serial] | ||||
| 	tracker.lck.RUnlock() | ||||
| 	if ok { | ||||
| 		tracker.finalizeWithError(msg.serial, NoSequence, err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // finalize was the only func that did not strobe Done | ||||
| func (tracker *callTracker) finalize(sn uint32) { | ||||
| 	tracker.lck.Lock() | ||||
| 	defer tracker.lck.Unlock() | ||||
| 	c, ok := tracker.calls[sn] | ||||
| 	if ok { | ||||
| 		delete(tracker.calls, sn) | ||||
| 		c.ContextCancel() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) finalizeWithBody(sn uint32, sequence Sequence, body []interface{}) { | ||||
| 	tracker.lck.Lock() | ||||
| 	c, ok := tracker.calls[sn] | ||||
| 	if ok { | ||||
| 		delete(tracker.calls, sn) | ||||
| 	} | ||||
| 	tracker.lck.Unlock() | ||||
| 	if ok { | ||||
| 		c.Body = body | ||||
| 		c.ResponseSequence = sequence | ||||
| 		c.done() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) finalizeWithError(sn uint32, sequence Sequence, err error) { | ||||
| 	tracker.lck.Lock() | ||||
| 	c, ok := tracker.calls[sn] | ||||
| 	if ok { | ||||
| 		delete(tracker.calls, sn) | ||||
| 	} | ||||
| 	tracker.lck.Unlock() | ||||
| 	if ok { | ||||
| 		c.Err = err | ||||
| 		c.ResponseSequence = sequence | ||||
| 		c.done() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) finalizeAllWithError(sequenceGen *sequenceGenerator, err error) { | ||||
| 	tracker.lck.Lock() | ||||
| 	closedCalls := make([]*Call, 0, len(tracker.calls)) | ||||
| 	for sn := range tracker.calls { | ||||
| 		closedCalls = append(closedCalls, tracker.calls[sn]) | ||||
| 	} | ||||
| 	tracker.calls = map[uint32]*Call{} | ||||
| 	tracker.lck.Unlock() | ||||
| 	for _, call := range closedCalls { | ||||
| 		call.Err = err | ||||
| 		call.ResponseSequence = sequenceGen.next() | ||||
| 		call.done() | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										37
									
								
								vendor/github.com/godbus/dbus/v5/conn_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/godbus/dbus/v5/conn_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| ) | ||||
|  | ||||
| const defaultSystemBusAddress = "unix:path=/opt/local/var/run/dbus/system_bus_socket" | ||||
|  | ||||
| func getSessionBusPlatformAddress() (string, error) { | ||||
| 	cmd := exec.Command("launchctl", "getenv", "DBUS_LAUNCHD_SESSION_BUS_SOCKET") | ||||
| 	b, err := cmd.CombinedOutput() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	if len(b) == 0 { | ||||
| 		return "", errors.New("dbus: couldn't determine address of session bus") | ||||
| 	} | ||||
|  | ||||
| 	return "unix:path=" + string(b[:len(b)-1]), nil | ||||
| } | ||||
|  | ||||
| func getSystemBusPlatformAddress() string { | ||||
| 	address := os.Getenv("DBUS_LAUNCHD_SESSION_BUS_SOCKET") | ||||
| 	if address != "" { | ||||
| 		return fmt.Sprintf("unix:path=%s", address) | ||||
| 	} | ||||
| 	return defaultSystemBusAddress | ||||
| } | ||||
|  | ||||
| func tryDiscoverDbusSessionBusAddress() string { | ||||
| 	return "" | ||||
| } | ||||
							
								
								
									
										90
									
								
								vendor/github.com/godbus/dbus/v5/conn_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								vendor/github.com/godbus/dbus/v5/conn_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| // +build !darwin | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"os/user" | ||||
| 	"path" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| var execCommand = exec.Command | ||||
|  | ||||
| func getSessionBusPlatformAddress() (string, error) { | ||||
| 	cmd := execCommand("dbus-launch") | ||||
| 	b, err := cmd.CombinedOutput() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	i := bytes.IndexByte(b, '=') | ||||
| 	j := bytes.IndexByte(b, '\n') | ||||
|  | ||||
| 	if i == -1 || j == -1 || i > j { | ||||
| 		return "", errors.New("dbus: couldn't determine address of session bus") | ||||
| 	} | ||||
|  | ||||
| 	env, addr := string(b[0:i]), string(b[i+1:j]) | ||||
| 	os.Setenv(env, addr) | ||||
|  | ||||
| 	return addr, nil | ||||
| } | ||||
|  | ||||
| // tryDiscoverDbusSessionBusAddress tries to discover an existing dbus session | ||||
| // and return the value of its DBUS_SESSION_BUS_ADDRESS. | ||||
| // It tries different techniques employed by different operating systems, | ||||
| // returning the first valid address it finds, or an empty string. | ||||
| // | ||||
| // * /run/user/<uid>/bus           if this exists, it *is* the bus socket. present on | ||||
| //                                 Ubuntu 18.04 | ||||
| // * /run/user/<uid>/dbus-session: if this exists, it can be parsed for the bus | ||||
| //                                 address. present on Ubuntu 16.04 | ||||
| // | ||||
| // See https://dbus.freedesktop.org/doc/dbus-launch.1.html | ||||
| func tryDiscoverDbusSessionBusAddress() string { | ||||
| 	if runtimeDirectory, err := getRuntimeDirectory(); err == nil { | ||||
|  | ||||
| 		if runUserBusFile := path.Join(runtimeDirectory, "bus"); fileExists(runUserBusFile) { | ||||
| 			// if /run/user/<uid>/bus exists, that file itself | ||||
| 			// *is* the unix socket, so return its path | ||||
| 			return fmt.Sprintf("unix:path=%s", EscapeBusAddressValue(runUserBusFile)) | ||||
| 		} | ||||
| 		if runUserSessionDbusFile := path.Join(runtimeDirectory, "dbus-session"); fileExists(runUserSessionDbusFile) { | ||||
| 			// if /run/user/<uid>/dbus-session exists, it's a | ||||
| 			// text file // containing the address of the socket, e.g.: | ||||
| 			// DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-E1c73yNqrG | ||||
|  | ||||
| 			if f, err := ioutil.ReadFile(runUserSessionDbusFile); err == nil { | ||||
| 				fileContent := string(f) | ||||
|  | ||||
| 				prefix := "DBUS_SESSION_BUS_ADDRESS=" | ||||
|  | ||||
| 				if strings.HasPrefix(fileContent, prefix) { | ||||
| 					address := strings.TrimRight(strings.TrimPrefix(fileContent, prefix), "\n\r") | ||||
| 					return address | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func getRuntimeDirectory() (string, error) { | ||||
| 	if currentUser, err := user.Current(); err != nil { | ||||
| 		return "", err | ||||
| 	} else { | ||||
| 		return fmt.Sprintf("/run/user/%s", currentUser.Uid), nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func fileExists(filename string) bool { | ||||
| 	_, err := os.Stat(filename) | ||||
| 	return !os.IsNotExist(err) | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/github.com/godbus/dbus/v5/conn_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/godbus/dbus/v5/conn_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| //+build !windows,!solaris,!darwin | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| const defaultSystemBusAddress = "unix:path=/var/run/dbus/system_bus_socket" | ||||
|  | ||||
| func getSystemBusPlatformAddress() string { | ||||
| 	address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS") | ||||
| 	if address != "" { | ||||
| 		return address | ||||
| 	} | ||||
| 	return defaultSystemBusAddress | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/github.com/godbus/dbus/v5/conn_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/godbus/dbus/v5/conn_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| //+build windows | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import "os" | ||||
|  | ||||
| const defaultSystemBusAddress = "tcp:host=127.0.0.1,port=12434" | ||||
|  | ||||
| func getSystemBusPlatformAddress() string { | ||||
| 	address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS") | ||||
| 	if address != "" { | ||||
| 		return address | ||||
| 	} | ||||
| 	return defaultSystemBusAddress | ||||
| } | ||||
							
								
								
									
										430
									
								
								vendor/github.com/godbus/dbus/v5/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										430
									
								
								vendor/github.com/godbus/dbus/v5/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,430 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	byteType        = reflect.TypeOf(byte(0)) | ||||
| 	boolType        = reflect.TypeOf(false) | ||||
| 	uint8Type       = reflect.TypeOf(uint8(0)) | ||||
| 	int16Type       = reflect.TypeOf(int16(0)) | ||||
| 	uint16Type      = reflect.TypeOf(uint16(0)) | ||||
| 	intType         = reflect.TypeOf(int(0)) | ||||
| 	uintType        = reflect.TypeOf(uint(0)) | ||||
| 	int32Type       = reflect.TypeOf(int32(0)) | ||||
| 	uint32Type      = reflect.TypeOf(uint32(0)) | ||||
| 	int64Type       = reflect.TypeOf(int64(0)) | ||||
| 	uint64Type      = reflect.TypeOf(uint64(0)) | ||||
| 	float64Type     = reflect.TypeOf(float64(0)) | ||||
| 	stringType      = reflect.TypeOf("") | ||||
| 	signatureType   = reflect.TypeOf(Signature{""}) | ||||
| 	objectPathType  = reflect.TypeOf(ObjectPath("")) | ||||
| 	variantType     = reflect.TypeOf(Variant{Signature{""}, nil}) | ||||
| 	interfacesType  = reflect.TypeOf([]interface{}{}) | ||||
| 	interfaceType   = reflect.TypeOf((*interface{})(nil)).Elem() | ||||
| 	unixFDType      = reflect.TypeOf(UnixFD(0)) | ||||
| 	unixFDIndexType = reflect.TypeOf(UnixFDIndex(0)) | ||||
| 	errType         = reflect.TypeOf((*error)(nil)).Elem() | ||||
| ) | ||||
|  | ||||
| // An InvalidTypeError signals that a value which cannot be represented in the | ||||
| // D-Bus wire format was passed to a function. | ||||
| type InvalidTypeError struct { | ||||
| 	Type reflect.Type | ||||
| } | ||||
|  | ||||
| func (e InvalidTypeError) Error() string { | ||||
| 	return "dbus: invalid type " + e.Type.String() | ||||
| } | ||||
|  | ||||
| // Store copies the values contained in src to dest, which must be a slice of | ||||
| // pointers. It converts slices of interfaces from src to corresponding structs | ||||
| // in dest. An error is returned if the lengths of src and dest or the types of | ||||
| // their elements don't match. | ||||
| func Store(src []interface{}, dest ...interface{}) error { | ||||
| 	if len(src) != len(dest) { | ||||
| 		return errors.New("dbus.Store: length mismatch") | ||||
| 	} | ||||
|  | ||||
| 	for i := range src { | ||||
| 		if err := storeInterfaces(src[i], dest[i]); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func storeInterfaces(src, dest interface{}) error { | ||||
| 	return store(reflect.ValueOf(dest), reflect.ValueOf(src)) | ||||
| } | ||||
|  | ||||
| func store(dest, src reflect.Value) error { | ||||
| 	if dest.Kind() == reflect.Ptr { | ||||
| 		if dest.IsNil() { | ||||
| 			dest.Set(reflect.New(dest.Type().Elem())) | ||||
| 		} | ||||
| 		return store(dest.Elem(), src) | ||||
| 	} | ||||
| 	switch src.Kind() { | ||||
| 	case reflect.Slice: | ||||
| 		return storeSlice(dest, src) | ||||
| 	case reflect.Map: | ||||
| 		return storeMap(dest, src) | ||||
| 	default: | ||||
| 		return storeBase(dest, src) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func storeBase(dest, src reflect.Value) error { | ||||
| 	return setDest(dest, src) | ||||
| } | ||||
|  | ||||
| func setDest(dest, src reflect.Value) error { | ||||
| 	if !isVariant(src.Type()) && isVariant(dest.Type()) { | ||||
| 		//special conversion for dbus.Variant | ||||
| 		dest.Set(reflect.ValueOf(MakeVariant(src.Interface()))) | ||||
| 		return nil | ||||
| 	} | ||||
| 	if isVariant(src.Type()) && !isVariant(dest.Type()) { | ||||
| 		src = getVariantValue(src) | ||||
| 		return store(dest, src) | ||||
| 	} | ||||
| 	if !src.Type().ConvertibleTo(dest.Type()) { | ||||
| 		return fmt.Errorf( | ||||
| 			"dbus.Store: type mismatch: cannot convert %s to %s", | ||||
| 			src.Type(), dest.Type()) | ||||
| 	} | ||||
| 	dest.Set(src.Convert(dest.Type())) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func kindsAreCompatible(dest, src reflect.Type) bool { | ||||
| 	switch { | ||||
| 	case isVariant(dest): | ||||
| 		return true | ||||
| 	case dest.Kind() == reflect.Interface: | ||||
| 		return true | ||||
| 	default: | ||||
| 		return dest.Kind() == src.Kind() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func isConvertibleTo(dest, src reflect.Type) bool { | ||||
| 	switch { | ||||
| 	case isVariant(dest): | ||||
| 		return true | ||||
| 	case dest.Kind() == reflect.Interface: | ||||
| 		return true | ||||
| 	case dest.Kind() == reflect.Slice: | ||||
| 		return src.Kind() == reflect.Slice && | ||||
| 			isConvertibleTo(dest.Elem(), src.Elem()) | ||||
| 	case dest.Kind() == reflect.Ptr: | ||||
| 		dest = dest.Elem() | ||||
| 		return isConvertibleTo(dest, src) | ||||
| 	case dest.Kind() == reflect.Struct: | ||||
| 		return src == interfacesType || dest.Kind() == src.Kind() | ||||
| 	default: | ||||
| 		return src.ConvertibleTo(dest) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func storeMap(dest, src reflect.Value) error { | ||||
| 	switch { | ||||
| 	case !kindsAreCompatible(dest.Type(), src.Type()): | ||||
| 		return fmt.Errorf( | ||||
| 			"dbus.Store: type mismatch: "+ | ||||
| 				"map: cannot store a value of %s into %s", | ||||
| 			src.Type(), dest.Type()) | ||||
| 	case isVariant(dest.Type()): | ||||
| 		return storeMapIntoVariant(dest, src) | ||||
| 	case dest.Kind() == reflect.Interface: | ||||
| 		return storeMapIntoInterface(dest, src) | ||||
| 	case isConvertibleTo(dest.Type().Key(), src.Type().Key()) && | ||||
| 		isConvertibleTo(dest.Type().Elem(), src.Type().Elem()): | ||||
| 		return storeMapIntoMap(dest, src) | ||||
| 	default: | ||||
| 		return fmt.Errorf( | ||||
| 			"dbus.Store: type mismatch: "+ | ||||
| 				"map: cannot convert a value of %s into %s", | ||||
| 			src.Type(), dest.Type()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func storeMapIntoVariant(dest, src reflect.Value) error { | ||||
| 	dv := reflect.MakeMap(src.Type()) | ||||
| 	err := store(dv, src) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return storeBase(dest, dv) | ||||
| } | ||||
|  | ||||
| func storeMapIntoInterface(dest, src reflect.Value) error { | ||||
| 	var dv reflect.Value | ||||
| 	if isVariant(src.Type().Elem()) { | ||||
| 		//Convert variants to interface{} recursively when converting | ||||
| 		//to interface{} | ||||
| 		dv = reflect.MakeMap( | ||||
| 			reflect.MapOf(src.Type().Key(), interfaceType)) | ||||
| 	} else { | ||||
| 		dv = reflect.MakeMap(src.Type()) | ||||
| 	} | ||||
| 	err := store(dv, src) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return storeBase(dest, dv) | ||||
| } | ||||
|  | ||||
| func storeMapIntoMap(dest, src reflect.Value) error { | ||||
| 	if dest.IsNil() { | ||||
| 		dest.Set(reflect.MakeMap(dest.Type())) | ||||
| 	} | ||||
| 	keys := src.MapKeys() | ||||
| 	for _, key := range keys { | ||||
| 		dkey := key.Convert(dest.Type().Key()) | ||||
| 		dval := reflect.New(dest.Type().Elem()).Elem() | ||||
| 		err := store(dval, getVariantValue(src.MapIndex(key))) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		dest.SetMapIndex(dkey, dval) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func storeSlice(dest, src reflect.Value) error { | ||||
| 	switch { | ||||
| 	case src.Type() == interfacesType && dest.Kind() == reflect.Struct: | ||||
| 		//The decoder always decodes structs as slices of interface{} | ||||
| 		return storeStruct(dest, src) | ||||
| 	case !kindsAreCompatible(dest.Type(), src.Type()): | ||||
| 		return fmt.Errorf( | ||||
| 			"dbus.Store: type mismatch: "+ | ||||
| 				"slice: cannot store a value of %s into %s", | ||||
| 			src.Type(), dest.Type()) | ||||
| 	case isVariant(dest.Type()): | ||||
| 		return storeSliceIntoVariant(dest, src) | ||||
| 	case dest.Kind() == reflect.Interface: | ||||
| 		return storeSliceIntoInterface(dest, src) | ||||
| 	case isConvertibleTo(dest.Type().Elem(), src.Type().Elem()): | ||||
| 		return storeSliceIntoSlice(dest, src) | ||||
| 	default: | ||||
| 		return fmt.Errorf( | ||||
| 			"dbus.Store: type mismatch: "+ | ||||
| 				"slice: cannot convert a value of %s into %s", | ||||
| 			src.Type(), dest.Type()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func storeStruct(dest, src reflect.Value) error { | ||||
| 	if isVariant(dest.Type()) { | ||||
| 		return storeBase(dest, src) | ||||
| 	} | ||||
| 	dval := make([]interface{}, 0, dest.NumField()) | ||||
| 	dtype := dest.Type() | ||||
| 	for i := 0; i < dest.NumField(); i++ { | ||||
| 		field := dest.Field(i) | ||||
| 		ftype := dtype.Field(i) | ||||
| 		if ftype.PkgPath != "" { | ||||
| 			continue | ||||
| 		} | ||||
| 		if ftype.Tag.Get("dbus") == "-" { | ||||
| 			continue | ||||
| 		} | ||||
| 		dval = append(dval, field.Addr().Interface()) | ||||
| 	} | ||||
| 	if src.Len() != len(dval) { | ||||
| 		return fmt.Errorf( | ||||
| 			"dbus.Store: type mismatch: "+ | ||||
| 				"destination struct does not have "+ | ||||
| 				"enough fields need: %d have: %d", | ||||
| 			src.Len(), len(dval)) | ||||
| 	} | ||||
| 	return Store(src.Interface().([]interface{}), dval...) | ||||
| } | ||||
|  | ||||
| func storeSliceIntoVariant(dest, src reflect.Value) error { | ||||
| 	dv := reflect.MakeSlice(src.Type(), src.Len(), src.Cap()) | ||||
| 	err := store(dv, src) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return storeBase(dest, dv) | ||||
| } | ||||
|  | ||||
| func storeSliceIntoInterface(dest, src reflect.Value) error { | ||||
| 	var dv reflect.Value | ||||
| 	if isVariant(src.Type().Elem()) { | ||||
| 		//Convert variants to interface{} recursively when converting | ||||
| 		//to interface{} | ||||
| 		dv = reflect.MakeSlice(reflect.SliceOf(interfaceType), | ||||
| 			src.Len(), src.Cap()) | ||||
| 	} else { | ||||
| 		dv = reflect.MakeSlice(src.Type(), src.Len(), src.Cap()) | ||||
| 	} | ||||
| 	err := store(dv, src) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return storeBase(dest, dv) | ||||
| } | ||||
|  | ||||
| func storeSliceIntoSlice(dest, src reflect.Value) error { | ||||
| 	if dest.IsNil() || dest.Len() < src.Len() { | ||||
| 		dest.Set(reflect.MakeSlice(dest.Type(), src.Len(), src.Cap())) | ||||
| 	} else if dest.Len() > src.Len() { | ||||
| 		dest.Set(dest.Slice(0, src.Len())) | ||||
| 	} | ||||
| 	for i := 0; i < src.Len(); i++ { | ||||
| 		err := store(dest.Index(i), getVariantValue(src.Index(i))) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func getVariantValue(in reflect.Value) reflect.Value { | ||||
| 	if isVariant(in.Type()) { | ||||
| 		return reflect.ValueOf(in.Interface().(Variant).Value()) | ||||
| 	} | ||||
| 	return in | ||||
| } | ||||
|  | ||||
| func isVariant(t reflect.Type) bool { | ||||
| 	return t == variantType | ||||
| } | ||||
|  | ||||
| // An ObjectPath is an object path as defined by the D-Bus spec. | ||||
| type ObjectPath string | ||||
|  | ||||
| // IsValid returns whether the object path is valid. | ||||
| func (o ObjectPath) IsValid() bool { | ||||
| 	s := string(o) | ||||
| 	if len(s) == 0 { | ||||
| 		return false | ||||
| 	} | ||||
| 	if s[0] != '/' { | ||||
| 		return false | ||||
| 	} | ||||
| 	if s[len(s)-1] == '/' && len(s) != 1 { | ||||
| 		return false | ||||
| 	} | ||||
| 	// probably not used, but technically possible | ||||
| 	if s == "/" { | ||||
| 		return true | ||||
| 	} | ||||
| 	split := strings.Split(s[1:], "/") | ||||
| 	for _, v := range split { | ||||
| 		if len(v) == 0 { | ||||
| 			return false | ||||
| 		} | ||||
| 		for _, c := range v { | ||||
| 			if !isMemberChar(c) { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // A UnixFD is a Unix file descriptor sent over the wire. See the package-level | ||||
| // documentation for more information about Unix file descriptor passsing. | ||||
| type UnixFD int32 | ||||
|  | ||||
| // A UnixFDIndex is the representation of a Unix file descriptor in a message. | ||||
| type UnixFDIndex uint32 | ||||
|  | ||||
| // alignment returns the alignment of values of type t. | ||||
| func alignment(t reflect.Type) int { | ||||
| 	switch t { | ||||
| 	case variantType: | ||||
| 		return 1 | ||||
| 	case objectPathType: | ||||
| 		return 4 | ||||
| 	case signatureType: | ||||
| 		return 1 | ||||
| 	case interfacesType: | ||||
| 		return 4 | ||||
| 	} | ||||
| 	switch t.Kind() { | ||||
| 	case reflect.Uint8: | ||||
| 		return 1 | ||||
| 	case reflect.Uint16, reflect.Int16: | ||||
| 		return 2 | ||||
| 	case reflect.Uint, reflect.Int, reflect.Uint32, reflect.Int32, reflect.String, reflect.Array, reflect.Slice, reflect.Map: | ||||
| 		return 4 | ||||
| 	case reflect.Uint64, reflect.Int64, reflect.Float64, reflect.Struct: | ||||
| 		return 8 | ||||
| 	case reflect.Ptr: | ||||
| 		return alignment(t.Elem()) | ||||
| 	} | ||||
| 	return 1 | ||||
| } | ||||
|  | ||||
| // isKeyType returns whether t is a valid type for a D-Bus dict. | ||||
| func isKeyType(t reflect.Type) bool { | ||||
| 	switch t.Kind() { | ||||
| 	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, | ||||
| 		reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64, | ||||
| 		reflect.String, reflect.Uint, reflect.Int: | ||||
|  | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // isValidInterface returns whether s is a valid name for an interface. | ||||
| func isValidInterface(s string) bool { | ||||
| 	if len(s) == 0 || len(s) > 255 || s[0] == '.' { | ||||
| 		return false | ||||
| 	} | ||||
| 	elem := strings.Split(s, ".") | ||||
| 	if len(elem) < 2 { | ||||
| 		return false | ||||
| 	} | ||||
| 	for _, v := range elem { | ||||
| 		if len(v) == 0 { | ||||
| 			return false | ||||
| 		} | ||||
| 		if v[0] >= '0' && v[0] <= '9' { | ||||
| 			return false | ||||
| 		} | ||||
| 		for _, c := range v { | ||||
| 			if !isMemberChar(c) { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // isValidMember returns whether s is a valid name for a member. | ||||
| func isValidMember(s string) bool { | ||||
| 	if len(s) == 0 || len(s) > 255 { | ||||
| 		return false | ||||
| 	} | ||||
| 	i := strings.Index(s, ".") | ||||
| 	if i != -1 { | ||||
| 		return false | ||||
| 	} | ||||
| 	if s[0] >= '0' && s[0] <= '9' { | ||||
| 		return false | ||||
| 	} | ||||
| 	for _, c := range s { | ||||
| 		if !isMemberChar(c) { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func isMemberChar(c rune) bool { | ||||
| 	return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || | ||||
| 		(c >= 'a' && c <= 'z') || c == '_' | ||||
| } | ||||
							
								
								
									
										292
									
								
								vendor/github.com/godbus/dbus/v5/decoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								vendor/github.com/godbus/dbus/v5/decoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,292 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"io" | ||||
| 	"reflect" | ||||
| ) | ||||
|  | ||||
| type decoder struct { | ||||
| 	in    io.Reader | ||||
| 	order binary.ByteOrder | ||||
| 	pos   int | ||||
| 	fds   []int | ||||
| } | ||||
|  | ||||
| // newDecoder returns a new decoder that reads values from in. The input is | ||||
| // expected to be in the given byte order. | ||||
| func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder { | ||||
| 	dec := new(decoder) | ||||
| 	dec.in = in | ||||
| 	dec.order = order | ||||
| 	dec.fds = fds | ||||
| 	return dec | ||||
| } | ||||
|  | ||||
| // align aligns the input to the given boundary and panics on error. | ||||
| func (dec *decoder) align(n int) { | ||||
| 	if dec.pos%n != 0 { | ||||
| 		newpos := (dec.pos + n - 1) & ^(n - 1) | ||||
| 		empty := make([]byte, newpos-dec.pos) | ||||
| 		if _, err := io.ReadFull(dec.in, empty); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		dec.pos = newpos | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Calls binary.Read(dec.in, dec.order, v) and panics on read errors. | ||||
| func (dec *decoder) binread(v interface{}) { | ||||
| 	if err := binary.Read(dec.in, dec.order, v); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) { | ||||
| 	defer func() { | ||||
| 		var ok bool | ||||
| 		v := recover() | ||||
| 		if err, ok = v.(error); ok { | ||||
| 			if err == io.EOF || err == io.ErrUnexpectedEOF { | ||||
| 				err = FormatError("unexpected EOF") | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	vs = make([]interface{}, 0) | ||||
| 	s := sig.str | ||||
| 	for s != "" { | ||||
| 		err, rem := validSingle(s, &depthCounter{}) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		v := dec.decode(s[:len(s)-len(rem)], 0) | ||||
| 		vs = append(vs, v) | ||||
| 		s = rem | ||||
| 	} | ||||
| 	return vs, nil | ||||
| } | ||||
|  | ||||
| func (dec *decoder) decode(s string, depth int) interface{} { | ||||
| 	dec.align(alignment(typeFor(s))) | ||||
| 	switch s[0] { | ||||
| 	case 'y': | ||||
| 		var b [1]byte | ||||
| 		if _, err := dec.in.Read(b[:]); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		dec.pos++ | ||||
| 		return b[0] | ||||
| 	case 'b': | ||||
| 		i := dec.decode("u", depth).(uint32) | ||||
| 		switch { | ||||
| 		case i == 0: | ||||
| 			return false | ||||
| 		case i == 1: | ||||
| 			return true | ||||
| 		default: | ||||
| 			panic(FormatError("invalid value for boolean")) | ||||
| 		} | ||||
| 	case 'n': | ||||
| 		var i int16 | ||||
| 		dec.binread(&i) | ||||
| 		dec.pos += 2 | ||||
| 		return i | ||||
| 	case 'i': | ||||
| 		var i int32 | ||||
| 		dec.binread(&i) | ||||
| 		dec.pos += 4 | ||||
| 		return i | ||||
| 	case 'x': | ||||
| 		var i int64 | ||||
| 		dec.binread(&i) | ||||
| 		dec.pos += 8 | ||||
| 		return i | ||||
| 	case 'q': | ||||
| 		var i uint16 | ||||
| 		dec.binread(&i) | ||||
| 		dec.pos += 2 | ||||
| 		return i | ||||
| 	case 'u': | ||||
| 		var i uint32 | ||||
| 		dec.binread(&i) | ||||
| 		dec.pos += 4 | ||||
| 		return i | ||||
| 	case 't': | ||||
| 		var i uint64 | ||||
| 		dec.binread(&i) | ||||
| 		dec.pos += 8 | ||||
| 		return i | ||||
| 	case 'd': | ||||
| 		var f float64 | ||||
| 		dec.binread(&f) | ||||
| 		dec.pos += 8 | ||||
| 		return f | ||||
| 	case 's': | ||||
| 		length := dec.decode("u", depth).(uint32) | ||||
| 		b := make([]byte, int(length)+1) | ||||
| 		if _, err := io.ReadFull(dec.in, b); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		dec.pos += int(length) + 1 | ||||
| 		return string(b[:len(b)-1]) | ||||
| 	case 'o': | ||||
| 		return ObjectPath(dec.decode("s", depth).(string)) | ||||
| 	case 'g': | ||||
| 		length := dec.decode("y", depth).(byte) | ||||
| 		b := make([]byte, int(length)+1) | ||||
| 		if _, err := io.ReadFull(dec.in, b); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		dec.pos += int(length) + 1 | ||||
| 		sig, err := ParseSignature(string(b[:len(b)-1])) | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		return sig | ||||
| 	case 'v': | ||||
| 		if depth >= 64 { | ||||
| 			panic(FormatError("input exceeds container depth limit")) | ||||
| 		} | ||||
| 		var variant Variant | ||||
| 		sig := dec.decode("g", depth).(Signature) | ||||
| 		if len(sig.str) == 0 { | ||||
| 			panic(FormatError("variant signature is empty")) | ||||
| 		} | ||||
| 		err, rem := validSingle(sig.str, &depthCounter{}) | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		if rem != "" { | ||||
| 			panic(FormatError("variant signature has multiple types")) | ||||
| 		} | ||||
| 		variant.sig = sig | ||||
| 		variant.value = dec.decode(sig.str, depth+1) | ||||
| 		return variant | ||||
| 	case 'h': | ||||
| 		idx := dec.decode("u", depth).(uint32) | ||||
| 		if int(idx) < len(dec.fds) { | ||||
| 			return UnixFD(dec.fds[idx]) | ||||
| 		} | ||||
| 		return UnixFDIndex(idx) | ||||
| 	case 'a': | ||||
| 		if len(s) > 1 && s[1] == '{' { | ||||
| 			ksig := s[2:3] | ||||
| 			vsig := s[3 : len(s)-1] | ||||
| 			v := reflect.MakeMap(reflect.MapOf(typeFor(ksig), typeFor(vsig))) | ||||
| 			if depth >= 63 { | ||||
| 				panic(FormatError("input exceeds container depth limit")) | ||||
| 			} | ||||
| 			length := dec.decode("u", depth).(uint32) | ||||
| 			// Even for empty maps, the correct padding must be included | ||||
| 			dec.align(8) | ||||
| 			spos := dec.pos | ||||
| 			for dec.pos < spos+int(length) { | ||||
| 				dec.align(8) | ||||
| 				if !isKeyType(v.Type().Key()) { | ||||
| 					panic(InvalidTypeError{v.Type()}) | ||||
| 				} | ||||
| 				kv := dec.decode(ksig, depth+2) | ||||
| 				vv := dec.decode(vsig, depth+2) | ||||
| 				v.SetMapIndex(reflect.ValueOf(kv), reflect.ValueOf(vv)) | ||||
| 			} | ||||
| 			return v.Interface() | ||||
| 		} | ||||
| 		if depth >= 64 { | ||||
| 			panic(FormatError("input exceeds container depth limit")) | ||||
| 		} | ||||
| 		sig := s[1:] | ||||
| 		length := dec.decode("u", depth).(uint32) | ||||
| 		// capacity can be determined only for fixed-size element types | ||||
| 		var capacity int | ||||
| 		if s := sigByteSize(sig); s != 0 { | ||||
| 			capacity = int(length) / s | ||||
| 		} | ||||
| 		v := reflect.MakeSlice(reflect.SliceOf(typeFor(sig)), 0, capacity) | ||||
| 		// Even for empty arrays, the correct padding must be included | ||||
| 		align := alignment(typeFor(s[1:])) | ||||
| 		if len(s) > 1 && s[1] == '(' { | ||||
| 			//Special case for arrays of structs | ||||
| 			//structs decode as a slice of interface{} values | ||||
| 			//but the dbus alignment does not match this | ||||
| 			align = 8 | ||||
| 		} | ||||
| 		dec.align(align) | ||||
| 		spos := dec.pos | ||||
| 		for dec.pos < spos+int(length) { | ||||
| 			ev := dec.decode(s[1:], depth+1) | ||||
| 			v = reflect.Append(v, reflect.ValueOf(ev)) | ||||
| 		} | ||||
| 		return v.Interface() | ||||
| 	case '(': | ||||
| 		if depth >= 64 { | ||||
| 			panic(FormatError("input exceeds container depth limit")) | ||||
| 		} | ||||
| 		dec.align(8) | ||||
| 		v := make([]interface{}, 0) | ||||
| 		s = s[1 : len(s)-1] | ||||
| 		for s != "" { | ||||
| 			err, rem := validSingle(s, &depthCounter{}) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 			ev := dec.decode(s[:len(s)-len(rem)], depth+1) | ||||
| 			v = append(v, ev) | ||||
| 			s = rem | ||||
| 		} | ||||
| 		return v | ||||
| 	default: | ||||
| 		panic(SignatureError{Sig: s}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // sigByteSize tries to calculates size of the given signature in bytes. | ||||
| // | ||||
| // It returns zero when it can't, for example when it contains non-fixed size | ||||
| // types such as strings, maps and arrays that require reading of the transmitted | ||||
| // data, for that we would need to implement the unread method for Decoder first. | ||||
| func sigByteSize(sig string) int { | ||||
| 	var total int | ||||
| 	for offset := 0; offset < len(sig); { | ||||
| 		switch sig[offset] { | ||||
| 		case 'y': | ||||
| 			total += 1 | ||||
| 			offset += 1 | ||||
| 		case 'n', 'q': | ||||
| 			total += 2 | ||||
| 			offset += 1 | ||||
| 		case 'b', 'i', 'u', 'h': | ||||
| 			total += 4 | ||||
| 			offset += 1 | ||||
| 		case 'x', 't', 'd': | ||||
| 			total += 8 | ||||
| 			offset += 1 | ||||
| 		case '(': | ||||
| 			i := 1 | ||||
| 			depth := 1 | ||||
| 			for i < len(sig[offset:]) && depth != 0 { | ||||
| 				if sig[offset+i] == '(' { | ||||
| 					depth++ | ||||
| 				} else if sig[offset+i] == ')' { | ||||
| 					depth-- | ||||
| 				} | ||||
| 				i++ | ||||
| 			} | ||||
| 			s := sigByteSize(sig[offset+1 : offset+i-1]) | ||||
| 			if s == 0 { | ||||
| 				return 0 | ||||
| 			} | ||||
| 			total += s | ||||
| 			offset += i | ||||
| 		default: | ||||
| 			return 0 | ||||
| 		} | ||||
| 	} | ||||
| 	return total | ||||
| } | ||||
|  | ||||
| // A FormatError is an error in the wire format. | ||||
| type FormatError string | ||||
|  | ||||
| func (e FormatError) Error() string { | ||||
| 	return "dbus: wire format error: " + string(e) | ||||
| } | ||||
							
								
								
									
										342
									
								
								vendor/github.com/godbus/dbus/v5/default_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								vendor/github.com/godbus/dbus/v5/default_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,342 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| func newIntrospectIntf(h *defaultHandler) *exportedIntf { | ||||
| 	methods := make(map[string]Method) | ||||
| 	methods["Introspect"] = exportedMethod{ | ||||
| 		reflect.ValueOf(func(msg Message) (string, *Error) { | ||||
| 			path := msg.Headers[FieldPath].value.(ObjectPath) | ||||
| 			return h.introspectPath(path), nil | ||||
| 		}), | ||||
| 	} | ||||
| 	return newExportedIntf(methods, true) | ||||
| } | ||||
|  | ||||
| //NewDefaultHandler returns an instance of the default | ||||
| //call handler. This is useful if you want to implement only | ||||
| //one of the two handlers but not both. | ||||
| // | ||||
| // Deprecated: this is the default value, don't use it, it will be unexported. | ||||
| func NewDefaultHandler() *defaultHandler { | ||||
| 	h := &defaultHandler{ | ||||
| 		objects:     make(map[ObjectPath]*exportedObj), | ||||
| 		defaultIntf: make(map[string]*exportedIntf), | ||||
| 	} | ||||
| 	h.defaultIntf["org.freedesktop.DBus.Introspectable"] = newIntrospectIntf(h) | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| type defaultHandler struct { | ||||
| 	sync.RWMutex | ||||
| 	objects     map[ObjectPath]*exportedObj | ||||
| 	defaultIntf map[string]*exportedIntf | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) PathExists(path ObjectPath) bool { | ||||
| 	_, ok := h.objects[path] | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) introspectPath(path ObjectPath) string { | ||||
| 	subpath := make(map[string]struct{}) | ||||
| 	var xml bytes.Buffer | ||||
| 	xml.WriteString("<node>") | ||||
| 	for obj := range h.objects { | ||||
| 		p := string(path) | ||||
| 		if p != "/" { | ||||
| 			p += "/" | ||||
| 		} | ||||
| 		if strings.HasPrefix(string(obj), p) { | ||||
| 			node_name := strings.Split(string(obj[len(p):]), "/")[0] | ||||
| 			subpath[node_name] = struct{}{} | ||||
| 		} | ||||
| 	} | ||||
| 	for s := range subpath { | ||||
| 		xml.WriteString("\n\t<node name=\"" + s + "\"/>") | ||||
| 	} | ||||
| 	xml.WriteString("\n</node>") | ||||
| 	return xml.String() | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) LookupObject(path ObjectPath) (ServerObject, bool) { | ||||
| 	h.RLock() | ||||
| 	defer h.RUnlock() | ||||
| 	object, ok := h.objects[path] | ||||
| 	if ok { | ||||
| 		return object, ok | ||||
| 	} | ||||
|  | ||||
| 	// If an object wasn't found for this exact path, | ||||
| 	// look for a matching subtree registration | ||||
| 	subtreeObject := newExportedObject() | ||||
| 	path = path[:strings.LastIndex(string(path), "/")] | ||||
| 	for len(path) > 0 { | ||||
| 		object, ok = h.objects[path] | ||||
| 		if ok { | ||||
| 			for name, iface := range object.interfaces { | ||||
| 				// Only include this handler if it registered for the subtree | ||||
| 				if iface.isFallbackInterface() { | ||||
| 					subtreeObject.interfaces[name] = iface | ||||
| 				} | ||||
| 			} | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		path = path[:strings.LastIndex(string(path), "/")] | ||||
| 	} | ||||
|  | ||||
| 	for name, intf := range h.defaultIntf { | ||||
| 		if _, exists := subtreeObject.interfaces[name]; exists { | ||||
| 			continue | ||||
| 		} | ||||
| 		subtreeObject.interfaces[name] = intf | ||||
| 	} | ||||
|  | ||||
| 	return subtreeObject, true | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) AddObject(path ObjectPath, object *exportedObj) { | ||||
| 	h.Lock() | ||||
| 	h.objects[path] = object | ||||
| 	h.Unlock() | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) DeleteObject(path ObjectPath) { | ||||
| 	h.Lock() | ||||
| 	delete(h.objects, path) | ||||
| 	h.Unlock() | ||||
| } | ||||
|  | ||||
| type exportedMethod struct { | ||||
| 	reflect.Value | ||||
| } | ||||
|  | ||||
| func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) { | ||||
| 	t := m.Type() | ||||
|  | ||||
| 	params := make([]reflect.Value, len(args)) | ||||
| 	for i := 0; i < len(args); i++ { | ||||
| 		params[i] = reflect.ValueOf(args[i]).Elem() | ||||
| 	} | ||||
|  | ||||
| 	ret := m.Value.Call(params) | ||||
| 	var err error | ||||
| 	nilErr := false // The reflection will find almost-nils, let's only pass back clean ones! | ||||
| 	if t.NumOut() > 0 { | ||||
| 		if e, ok := ret[t.NumOut()-1].Interface().(*Error); ok { // godbus *Error | ||||
| 			nilErr = ret[t.NumOut()-1].IsNil() | ||||
| 			ret = ret[:t.NumOut()-1] | ||||
| 			err = e | ||||
| 		} else if ret[t.NumOut()-1].Type().Implements(errType) { // Go error | ||||
| 			i := ret[t.NumOut()-1].Interface() | ||||
| 			if i == nil { | ||||
| 				nilErr = ret[t.NumOut()-1].IsNil() | ||||
| 			} else { | ||||
| 				err = i.(error) | ||||
| 			} | ||||
| 			ret = ret[:t.NumOut()-1] | ||||
| 		} | ||||
| 	} | ||||
| 	out := make([]interface{}, len(ret)) | ||||
| 	for i, val := range ret { | ||||
| 		out[i] = val.Interface() | ||||
| 	} | ||||
| 	if nilErr || err == nil { | ||||
| 		//concrete type to interface nil is a special case | ||||
| 		return out, nil | ||||
| 	} | ||||
| 	return out, err | ||||
| } | ||||
|  | ||||
| func (m exportedMethod) NumArguments() int { | ||||
| 	return m.Value.Type().NumIn() | ||||
| } | ||||
|  | ||||
| func (m exportedMethod) ArgumentValue(i int) interface{} { | ||||
| 	return reflect.Zero(m.Type().In(i)).Interface() | ||||
| } | ||||
|  | ||||
| func (m exportedMethod) NumReturns() int { | ||||
| 	return m.Value.Type().NumOut() | ||||
| } | ||||
|  | ||||
| func (m exportedMethod) ReturnValue(i int) interface{} { | ||||
| 	return reflect.Zero(m.Type().Out(i)).Interface() | ||||
| } | ||||
|  | ||||
| func newExportedObject() *exportedObj { | ||||
| 	return &exportedObj{ | ||||
| 		interfaces: make(map[string]*exportedIntf), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type exportedObj struct { | ||||
| 	mu         sync.RWMutex | ||||
| 	interfaces map[string]*exportedIntf | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) LookupInterface(name string) (Interface, bool) { | ||||
| 	if name == "" { | ||||
| 		return obj, true | ||||
| 	} | ||||
| 	obj.mu.RLock() | ||||
| 	defer obj.mu.RUnlock() | ||||
| 	intf, exists := obj.interfaces[name] | ||||
| 	return intf, exists | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) AddInterface(name string, iface *exportedIntf) { | ||||
| 	obj.mu.Lock() | ||||
| 	defer obj.mu.Unlock() | ||||
| 	obj.interfaces[name] = iface | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) DeleteInterface(name string) { | ||||
| 	obj.mu.Lock() | ||||
| 	defer obj.mu.Unlock() | ||||
| 	delete(obj.interfaces, name) | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) LookupMethod(name string) (Method, bool) { | ||||
| 	obj.mu.RLock() | ||||
| 	defer obj.mu.RUnlock() | ||||
| 	for _, intf := range obj.interfaces { | ||||
| 		method, exists := intf.LookupMethod(name) | ||||
| 		if exists { | ||||
| 			return method, exists | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, false | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) isFallbackInterface() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func newExportedIntf(methods map[string]Method, includeSubtree bool) *exportedIntf { | ||||
| 	return &exportedIntf{ | ||||
| 		methods:        methods, | ||||
| 		includeSubtree: includeSubtree, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type exportedIntf struct { | ||||
| 	methods map[string]Method | ||||
|  | ||||
| 	// Whether or not this export is for the entire subtree | ||||
| 	includeSubtree bool | ||||
| } | ||||
|  | ||||
| func (obj *exportedIntf) LookupMethod(name string) (Method, bool) { | ||||
| 	out, exists := obj.methods[name] | ||||
| 	return out, exists | ||||
| } | ||||
|  | ||||
| func (obj *exportedIntf) isFallbackInterface() bool { | ||||
| 	return obj.includeSubtree | ||||
| } | ||||
|  | ||||
| //NewDefaultSignalHandler returns an instance of the default | ||||
| //signal handler. This is useful if you want to implement only | ||||
| //one of the two handlers but not both. | ||||
| // | ||||
| // Deprecated: this is the default value, don't use it, it will be unexported. | ||||
| func NewDefaultSignalHandler() *defaultSignalHandler { | ||||
| 	return &defaultSignalHandler{} | ||||
| } | ||||
|  | ||||
| type defaultSignalHandler struct { | ||||
| 	mu      sync.RWMutex | ||||
| 	closed  bool | ||||
| 	signals []*signalChannelData | ||||
| } | ||||
|  | ||||
| func (sh *defaultSignalHandler) DeliverSignal(intf, name string, signal *Signal) { | ||||
| 	sh.mu.RLock() | ||||
| 	defer sh.mu.RUnlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	for _, scd := range sh.signals { | ||||
| 		scd.deliver(signal) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (sh *defaultSignalHandler) Terminate() { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for _, scd := range sh.signals { | ||||
| 		scd.close() | ||||
| 		close(scd.ch) | ||||
| 	} | ||||
| 	sh.closed = true | ||||
| 	sh.signals = nil | ||||
| } | ||||
|  | ||||
| func (sh *defaultSignalHandler) AddSignal(ch chan<- *Signal) { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	sh.signals = append(sh.signals, &signalChannelData{ | ||||
| 		ch:   ch, | ||||
| 		done: make(chan struct{}), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (sh *defaultSignalHandler) RemoveSignal(ch chan<- *Signal) { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	for i := len(sh.signals) - 1; i >= 0; i-- { | ||||
| 		if ch == sh.signals[i].ch { | ||||
| 			sh.signals[i].close() | ||||
| 			copy(sh.signals[i:], sh.signals[i+1:]) | ||||
| 			sh.signals[len(sh.signals)-1] = nil | ||||
| 			sh.signals = sh.signals[:len(sh.signals)-1] | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type signalChannelData struct { | ||||
| 	wg   sync.WaitGroup | ||||
| 	ch   chan<- *Signal | ||||
| 	done chan struct{} | ||||
| } | ||||
|  | ||||
| func (scd *signalChannelData) deliver(signal *Signal) { | ||||
| 	select { | ||||
| 	case scd.ch <- signal: | ||||
| 	case <-scd.done: | ||||
| 		return | ||||
| 	default: | ||||
| 		scd.wg.Add(1) | ||||
| 		go scd.deferredDeliver(signal) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (scd *signalChannelData) deferredDeliver(signal *Signal) { | ||||
| 	select { | ||||
| 	case scd.ch <- signal: | ||||
| 	case <-scd.done: | ||||
| 	} | ||||
| 	scd.wg.Done() | ||||
| } | ||||
|  | ||||
| func (scd *signalChannelData) close() { | ||||
| 	close(scd.done) | ||||
| 	scd.wg.Wait() // wait until all spawned goroutines return | ||||
| } | ||||
							
								
								
									
										71
									
								
								vendor/github.com/godbus/dbus/v5/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								vendor/github.com/godbus/dbus/v5/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| /* | ||||
| Package dbus implements bindings to the D-Bus message bus system. | ||||
|  | ||||
| To use the message bus API, you first need to connect to a bus (usually the | ||||
| session or system bus). The acquired connection then can be used to call methods | ||||
| on remote objects and emit or receive signals. Using the Export method, you can | ||||
| arrange D-Bus methods calls to be directly translated to method calls on a Go | ||||
| value. | ||||
|  | ||||
| Conversion Rules | ||||
|  | ||||
| For outgoing messages, Go types are automatically converted to the | ||||
| corresponding D-Bus types. See the official specification at | ||||
| https://dbus.freedesktop.org/doc/dbus-specification.html#type-system for more | ||||
| information on the D-Bus type system. The following types are directly encoded | ||||
| as their respective D-Bus equivalents: | ||||
|  | ||||
|      Go type     | D-Bus type | ||||
|      ------------+----------- | ||||
|      byte        | BYTE | ||||
|      bool        | BOOLEAN | ||||
|      int16       | INT16 | ||||
|      uint16      | UINT16 | ||||
|      int         | INT32 | ||||
|      uint        | UINT32 | ||||
|      int32       | INT32 | ||||
|      uint32      | UINT32 | ||||
|      int64       | INT64 | ||||
|      uint64      | UINT64 | ||||
|      float64     | DOUBLE | ||||
|      string      | STRING | ||||
|      ObjectPath  | OBJECT_PATH | ||||
|      Signature   | SIGNATURE | ||||
|      Variant     | VARIANT | ||||
|      interface{} | VARIANT | ||||
|      UnixFDIndex | UNIX_FD | ||||
|  | ||||
| Slices and arrays encode as ARRAYs of their element type. | ||||
|  | ||||
| Maps encode as DICTs, provided that their key type can be used as a key for | ||||
| a DICT. | ||||
|  | ||||
| Structs other than Variant and Signature encode as a STRUCT containing their | ||||
| exported fields in order. Fields whose tags contain `dbus:"-"` and unexported | ||||
| fields will be skipped. | ||||
|  | ||||
| Pointers encode as the value they're pointed to. | ||||
|  | ||||
| Types convertible to one of the base types above will be mapped as the | ||||
| base type. | ||||
|  | ||||
| Trying to encode any other type or a slice, map or struct containing an | ||||
| unsupported type will result in an InvalidTypeError. | ||||
|  | ||||
| For incoming messages, the inverse of these rules are used, with the exception | ||||
| of STRUCTs. Incoming STRUCTS are represented as a slice of empty interfaces | ||||
| containing the struct fields in the correct order. The Store function can be | ||||
| used to convert such values to Go structs. | ||||
|  | ||||
| Unix FD passing | ||||
|  | ||||
| Handling Unix file descriptors deserves special mention. To use them, you should | ||||
| first check that they are supported on a connection by calling SupportsUnixFDs. | ||||
| If it returns true, all method of Connection will translate messages containing | ||||
| UnixFD's to messages that are accompanied by the given file descriptors with the | ||||
| UnixFD values being substituted by the correct indices. Similarly, the indices | ||||
| of incoming messages are automatically resolved. It shouldn't be necessary to use | ||||
| UnixFDIndex. | ||||
|  | ||||
| */ | ||||
| package dbus | ||||
							
								
								
									
										235
									
								
								vendor/github.com/godbus/dbus/v5/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								vendor/github.com/godbus/dbus/v5/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,235 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"io" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"unicode/utf8" | ||||
| ) | ||||
|  | ||||
| // An encoder encodes values to the D-Bus wire format. | ||||
| type encoder struct { | ||||
| 	out   io.Writer | ||||
| 	fds   []int | ||||
| 	order binary.ByteOrder | ||||
| 	pos   int | ||||
| } | ||||
|  | ||||
| // NewEncoder returns a new encoder that writes to out in the given byte order. | ||||
| func newEncoder(out io.Writer, order binary.ByteOrder, fds []int) *encoder { | ||||
| 	enc := newEncoderAtOffset(out, 0, order, fds) | ||||
| 	return enc | ||||
| } | ||||
|  | ||||
| // newEncoderAtOffset returns a new encoder that writes to out in the given | ||||
| // byte order. Specify the offset to initialize pos for proper alignment | ||||
| // computation. | ||||
| func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder, fds []int) *encoder { | ||||
| 	enc := new(encoder) | ||||
| 	enc.out = out | ||||
| 	enc.order = order | ||||
| 	enc.pos = offset | ||||
| 	enc.fds = fds | ||||
| 	return enc | ||||
| } | ||||
|  | ||||
| // Aligns the next output to be on a multiple of n. Panics on write errors. | ||||
| func (enc *encoder) align(n int) { | ||||
| 	pad := enc.padding(0, n) | ||||
| 	if pad > 0 { | ||||
| 		empty := make([]byte, pad) | ||||
| 		if _, err := enc.out.Write(empty); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		enc.pos += pad | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // pad returns the number of bytes of padding, based on current position and additional offset. | ||||
| // and alignment. | ||||
| func (enc *encoder) padding(offset, algn int) int { | ||||
| 	abs := enc.pos + offset | ||||
| 	if abs%algn != 0 { | ||||
| 		newabs := (abs + algn - 1) & ^(algn - 1) | ||||
| 		return newabs - abs | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| // Calls binary.Write(enc.out, enc.order, v) and panics on write errors. | ||||
| func (enc *encoder) binwrite(v interface{}) { | ||||
| 	if err := binary.Write(enc.out, enc.order, v); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Encode encodes the given values to the underlying reader. All written values | ||||
| // are aligned properly as required by the D-Bus spec. | ||||
| func (enc *encoder) Encode(vs ...interface{}) (err error) { | ||||
| 	defer func() { | ||||
| 		err, _ = recover().(error) | ||||
| 	}() | ||||
| 	for _, v := range vs { | ||||
| 		enc.encode(reflect.ValueOf(v), 0) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // encode encodes the given value to the writer and panics on error. depth holds | ||||
| // the depth of the container nesting. | ||||
| func (enc *encoder) encode(v reflect.Value, depth int) { | ||||
| 	if depth > 64 { | ||||
| 		panic(FormatError("input exceeds depth limitation")) | ||||
| 	} | ||||
| 	enc.align(alignment(v.Type())) | ||||
| 	switch v.Kind() { | ||||
| 	case reflect.Uint8: | ||||
| 		var b [1]byte | ||||
| 		b[0] = byte(v.Uint()) | ||||
| 		if _, err := enc.out.Write(b[:]); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		enc.pos++ | ||||
| 	case reflect.Bool: | ||||
| 		if v.Bool() { | ||||
| 			enc.encode(reflect.ValueOf(uint32(1)), depth) | ||||
| 		} else { | ||||
| 			enc.encode(reflect.ValueOf(uint32(0)), depth) | ||||
| 		} | ||||
| 	case reflect.Int16: | ||||
| 		enc.binwrite(int16(v.Int())) | ||||
| 		enc.pos += 2 | ||||
| 	case reflect.Uint16: | ||||
| 		enc.binwrite(uint16(v.Uint())) | ||||
| 		enc.pos += 2 | ||||
| 	case reflect.Int, reflect.Int32: | ||||
| 		if v.Type() == unixFDType { | ||||
| 			fd := v.Int() | ||||
| 			idx := len(enc.fds) | ||||
| 			enc.fds = append(enc.fds, int(fd)) | ||||
| 			enc.binwrite(uint32(idx)) | ||||
| 		} else { | ||||
| 			enc.binwrite(int32(v.Int())) | ||||
| 		} | ||||
| 		enc.pos += 4 | ||||
| 	case reflect.Uint, reflect.Uint32: | ||||
| 		enc.binwrite(uint32(v.Uint())) | ||||
| 		enc.pos += 4 | ||||
| 	case reflect.Int64: | ||||
| 		enc.binwrite(v.Int()) | ||||
| 		enc.pos += 8 | ||||
| 	case reflect.Uint64: | ||||
| 		enc.binwrite(v.Uint()) | ||||
| 		enc.pos += 8 | ||||
| 	case reflect.Float64: | ||||
| 		enc.binwrite(v.Float()) | ||||
| 		enc.pos += 8 | ||||
| 	case reflect.String: | ||||
| 		str := v.String() | ||||
| 		if !utf8.ValidString(str) { | ||||
| 			panic(FormatError("input has a not-utf8 char in string")) | ||||
| 		} | ||||
| 		if strings.IndexByte(str, byte(0)) != -1 { | ||||
| 			panic(FormatError("input has a null char('\\000') in string")) | ||||
| 		} | ||||
| 		if v.Type() == objectPathType { | ||||
| 			if !ObjectPath(str).IsValid() { | ||||
| 				panic(FormatError("invalid object path")) | ||||
| 			} | ||||
| 		} | ||||
| 		enc.encode(reflect.ValueOf(uint32(len(str))), depth) | ||||
| 		b := make([]byte, v.Len()+1) | ||||
| 		copy(b, str) | ||||
| 		b[len(b)-1] = 0 | ||||
| 		n, err := enc.out.Write(b) | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		enc.pos += n | ||||
| 	case reflect.Ptr: | ||||
| 		enc.encode(v.Elem(), depth) | ||||
| 	case reflect.Slice, reflect.Array: | ||||
| 		// Lookahead offset: 4 bytes for uint32 length (with alignment), | ||||
| 		// plus alignment for elements. | ||||
| 		n := enc.padding(0, 4) + 4 | ||||
| 		offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem())) | ||||
|  | ||||
| 		var buf bytes.Buffer | ||||
| 		bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds) | ||||
|  | ||||
| 		for i := 0; i < v.Len(); i++ { | ||||
| 			bufenc.encode(v.Index(i), depth+1) | ||||
| 		} | ||||
|  | ||||
| 		if buf.Len() > 1<<26 { | ||||
| 			panic(FormatError("input exceeds array size limitation")) | ||||
| 		} | ||||
|  | ||||
| 		enc.fds = bufenc.fds | ||||
| 		enc.encode(reflect.ValueOf(uint32(buf.Len())), depth) | ||||
| 		length := buf.Len() | ||||
| 		enc.align(alignment(v.Type().Elem())) | ||||
| 		if _, err := buf.WriteTo(enc.out); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		enc.pos += length | ||||
| 	case reflect.Struct: | ||||
| 		switch t := v.Type(); t { | ||||
| 		case signatureType: | ||||
| 			str := v.Field(0) | ||||
| 			enc.encode(reflect.ValueOf(byte(str.Len())), depth) | ||||
| 			b := make([]byte, str.Len()+1) | ||||
| 			copy(b, str.String()) | ||||
| 			b[len(b)-1] = 0 | ||||
| 			n, err := enc.out.Write(b) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 			enc.pos += n | ||||
| 		case variantType: | ||||
| 			variant := v.Interface().(Variant) | ||||
| 			enc.encode(reflect.ValueOf(variant.sig), depth+1) | ||||
| 			enc.encode(reflect.ValueOf(variant.value), depth+1) | ||||
| 		default: | ||||
| 			for i := 0; i < v.Type().NumField(); i++ { | ||||
| 				field := t.Field(i) | ||||
| 				if field.PkgPath == "" && field.Tag.Get("dbus") != "-" { | ||||
| 					enc.encode(v.Field(i), depth+1) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	case reflect.Map: | ||||
| 		// Maps are arrays of structures, so they actually increase the depth by | ||||
| 		// 2. | ||||
| 		if !isKeyType(v.Type().Key()) { | ||||
| 			panic(InvalidTypeError{v.Type()}) | ||||
| 		} | ||||
| 		keys := v.MapKeys() | ||||
| 		// Lookahead offset: 4 bytes for uint32 length (with alignment), | ||||
| 		// plus 8-byte alignment | ||||
| 		n := enc.padding(0, 4) + 4 | ||||
| 		offset := enc.pos + n + enc.padding(n, 8) | ||||
|  | ||||
| 		var buf bytes.Buffer | ||||
| 		bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds) | ||||
| 		for _, k := range keys { | ||||
| 			bufenc.align(8) | ||||
| 			bufenc.encode(k, depth+2) | ||||
| 			bufenc.encode(v.MapIndex(k), depth+2) | ||||
| 		} | ||||
| 		enc.fds = bufenc.fds | ||||
| 		enc.encode(reflect.ValueOf(uint32(buf.Len())), depth) | ||||
| 		length := buf.Len() | ||||
| 		enc.align(8) | ||||
| 		if _, err := buf.WriteTo(enc.out); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		enc.pos += length | ||||
| 	case reflect.Interface: | ||||
| 		enc.encode(reflect.ValueOf(MakeVariant(v.Interface())), depth) | ||||
| 	default: | ||||
| 		panic(InvalidTypeError{v.Type()}) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										84
									
								
								vendor/github.com/godbus/dbus/v5/escape.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/godbus/dbus/v5/escape.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| package dbus | ||||
|  | ||||
| import "net/url" | ||||
|  | ||||
| // EscapeBusAddressValue implements a requirement to escape the values | ||||
| // in D-Bus server addresses, as defined by the D-Bus specification at | ||||
| // https://dbus.freedesktop.org/doc/dbus-specification.html#addresses. | ||||
| func EscapeBusAddressValue(val string) string { | ||||
| 	toEsc := strNeedsEscape(val) | ||||
| 	if toEsc == 0 { | ||||
| 		// Avoid unneeded allocation/copying. | ||||
| 		return val | ||||
| 	} | ||||
|  | ||||
| 	// Avoid allocation for short paths. | ||||
| 	var buf [64]byte | ||||
| 	var out []byte | ||||
| 	// Every to-be-escaped byte needs 2 extra bytes. | ||||
| 	required := len(val) + 2*toEsc | ||||
| 	if required <= len(buf) { | ||||
| 		out = buf[:required] | ||||
| 	} else { | ||||
| 		out = make([]byte, required) | ||||
| 	} | ||||
|  | ||||
| 	j := 0 | ||||
| 	for i := 0; i < len(val); i++ { | ||||
| 		if ch := val[i]; needsEscape(ch) { | ||||
| 			// Convert ch to %xx, where xx is hex value. | ||||
| 			out[j] = '%' | ||||
| 			out[j+1] = hexchar(ch >> 4) | ||||
| 			out[j+2] = hexchar(ch & 0x0F) | ||||
| 			j += 3 | ||||
| 		} else { | ||||
| 			out[j] = ch | ||||
| 			j++ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return string(out) | ||||
| } | ||||
|  | ||||
| // UnescapeBusAddressValue unescapes values in D-Bus server addresses, | ||||
| // as defined by the D-Bus specification at | ||||
| // https://dbus.freedesktop.org/doc/dbus-specification.html#addresses. | ||||
| func UnescapeBusAddressValue(val string) (string, error) { | ||||
| 	// Looks like url.PathUnescape does exactly what is required. | ||||
| 	return url.PathUnescape(val) | ||||
| } | ||||
|  | ||||
| // hexchar returns an octal representation of a n, where n < 16. | ||||
| // For invalid values of n, the function panics. | ||||
| func hexchar(n byte) byte { | ||||
| 	const hex = "0123456789abcdef" | ||||
|  | ||||
| 	// For n >= len(hex), runtime will panic. | ||||
| 	return hex[n] | ||||
| } | ||||
|  | ||||
| // needsEscape tells if a byte is NOT one of optionally-escaped bytes. | ||||
| func needsEscape(c byte) bool { | ||||
| 	if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' { | ||||
| 		return false | ||||
| 	} | ||||
| 	switch c { | ||||
| 	case '-', '_', '/', '\\', '.', '*': | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // strNeedsEscape tells how many bytes in the string need escaping. | ||||
| func strNeedsEscape(val string) int { | ||||
| 	count := 0 | ||||
|  | ||||
| 	for i := 0; i < len(val); i++ { | ||||
| 		if needsEscape(val[i]) { | ||||
| 			count++ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return count | ||||
| } | ||||
							
								
								
									
										463
									
								
								vendor/github.com/godbus/dbus/v5/export.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										463
									
								
								vendor/github.com/godbus/dbus/v5/export.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,463 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	ErrMsgInvalidArg = Error{ | ||||
| 		"org.freedesktop.DBus.Error.InvalidArgs", | ||||
| 		[]interface{}{"Invalid type / number of args"}, | ||||
| 	} | ||||
| 	ErrMsgNoObject = Error{ | ||||
| 		"org.freedesktop.DBus.Error.NoSuchObject", | ||||
| 		[]interface{}{"No such object"}, | ||||
| 	} | ||||
| 	ErrMsgUnknownMethod = Error{ | ||||
| 		"org.freedesktop.DBus.Error.UnknownMethod", | ||||
| 		[]interface{}{"Unknown / invalid method"}, | ||||
| 	} | ||||
| 	ErrMsgUnknownInterface = Error{ | ||||
| 		"org.freedesktop.DBus.Error.UnknownInterface", | ||||
| 		[]interface{}{"Object does not implement the interface"}, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| func MakeNoObjectError(path ObjectPath) Error { | ||||
| 	return Error{ | ||||
| 		"org.freedesktop.DBus.Error.NoSuchObject", | ||||
| 		[]interface{}{fmt.Sprintf("No such object '%s'", string(path))}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func MakeUnknownMethodError(methodName string) Error { | ||||
| 	return Error{ | ||||
| 		"org.freedesktop.DBus.Error.UnknownMethod", | ||||
| 		[]interface{}{fmt.Sprintf("Unknown / invalid method '%s'", methodName)}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func MakeUnknownInterfaceError(ifaceName string) Error { | ||||
| 	return Error{ | ||||
| 		"org.freedesktop.DBus.Error.UnknownInterface", | ||||
| 		[]interface{}{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func MakeFailedError(err error) *Error { | ||||
| 	return &Error{ | ||||
| 		"org.freedesktop.DBus.Error.Failed", | ||||
| 		[]interface{}{err.Error()}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Sender is a type which can be used in exported methods to receive the message | ||||
| // sender. | ||||
| type Sender string | ||||
|  | ||||
| func computeMethodName(name string, mapping map[string]string) string { | ||||
| 	newname, ok := mapping[name] | ||||
| 	if ok { | ||||
| 		name = newname | ||||
| 	} | ||||
| 	return name | ||||
| } | ||||
|  | ||||
| func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Value { | ||||
| 	if in == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	methods := make(map[string]reflect.Value) | ||||
| 	val := reflect.ValueOf(in) | ||||
| 	typ := val.Type() | ||||
| 	for i := 0; i < typ.NumMethod(); i++ { | ||||
| 		methtype := typ.Method(i) | ||||
| 		method := val.Method(i) | ||||
| 		t := method.Type() | ||||
| 		// only track valid methods must return *Error as last arg | ||||
| 		// and must be exported | ||||
| 		if t.NumOut() == 0 || | ||||
| 			t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) || | ||||
| 			methtype.PkgPath != "" { | ||||
| 			continue | ||||
| 		} | ||||
| 		// map names while building table | ||||
| 		methods[computeMethodName(methtype.Name, mapping)] = method | ||||
| 	} | ||||
| 	return methods | ||||
| } | ||||
|  | ||||
| func getAllMethods(in interface{}, mapping map[string]string) map[string]reflect.Value { | ||||
| 	if in == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	methods := make(map[string]reflect.Value) | ||||
| 	val := reflect.ValueOf(in) | ||||
| 	typ := val.Type() | ||||
| 	for i := 0; i < typ.NumMethod(); i++ { | ||||
| 		methtype := typ.Method(i) | ||||
| 		method := val.Method(i) | ||||
| 		// map names while building table | ||||
| 		methods[computeMethodName(methtype.Name, mapping)] = method | ||||
| 	} | ||||
| 	return methods | ||||
| } | ||||
|  | ||||
| func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) { | ||||
| 	pointers := make([]interface{}, m.NumArguments()) | ||||
| 	decode := make([]interface{}, 0, len(body)) | ||||
|  | ||||
| 	for i := 0; i < m.NumArguments(); i++ { | ||||
| 		tp := reflect.TypeOf(m.ArgumentValue(i)) | ||||
| 		val := reflect.New(tp) | ||||
| 		pointers[i] = val.Interface() | ||||
| 		if tp == reflect.TypeOf((*Sender)(nil)).Elem() { | ||||
| 			val.Elem().SetString(sender) | ||||
| 		} else if tp == reflect.TypeOf((*Message)(nil)).Elem() { | ||||
| 			val.Elem().Set(reflect.ValueOf(*msg)) | ||||
| 		} else { | ||||
| 			decode = append(decode, pointers[i]) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(decode) != len(body) { | ||||
| 		return nil, ErrMsgInvalidArg | ||||
| 	} | ||||
|  | ||||
| 	if err := Store(body, decode...); err != nil { | ||||
| 		return nil, ErrMsgInvalidArg | ||||
| 	} | ||||
|  | ||||
| 	return pointers, nil | ||||
| } | ||||
|  | ||||
| func (conn *Conn) decodeArguments(m Method, sender string, msg *Message) ([]interface{}, error) { | ||||
| 	if decoder, ok := m.(ArgumentDecoder); ok { | ||||
| 		return decoder.DecodeArguments(conn, sender, msg, msg.Body) | ||||
| 	} | ||||
| 	return standardMethodArgumentDecode(m, sender, msg, msg.Body) | ||||
| } | ||||
|  | ||||
| // handleCall handles the given method call (i.e. looks if it's one of the | ||||
| // pre-implemented ones and searches for a corresponding handler if not). | ||||
| func (conn *Conn) handleCall(msg *Message) { | ||||
| 	name := msg.Headers[FieldMember].value.(string) | ||||
| 	path := msg.Headers[FieldPath].value.(ObjectPath) | ||||
| 	ifaceName, _ := msg.Headers[FieldInterface].value.(string) | ||||
| 	sender, hasSender := msg.Headers[FieldSender].value.(string) | ||||
| 	serial := msg.serial | ||||
|  | ||||
| 	if len(name) == 0 { | ||||
| 		conn.sendError(ErrMsgUnknownMethod, sender, serial) | ||||
| 	} | ||||
|  | ||||
| 	if ifaceName == "org.freedesktop.DBus.Peer" { | ||||
| 		switch name { | ||||
| 		case "Ping": | ||||
| 			conn.sendReply(sender, serial) | ||||
| 		case "GetMachineId": | ||||
| 			conn.sendReply(sender, serial, conn.uuid) | ||||
| 		default: | ||||
| 			conn.sendError(MakeUnknownMethodError(name), sender, serial) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	object, ok := conn.handler.LookupObject(path) | ||||
| 	if !ok { | ||||
| 		conn.sendError(MakeNoObjectError(path), sender, serial) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	iface, exists := object.LookupInterface(ifaceName) | ||||
| 	if !exists { | ||||
| 		conn.sendError(MakeUnknownInterfaceError(ifaceName), sender, serial) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	m, exists := iface.LookupMethod(name) | ||||
| 	if !exists { | ||||
| 		conn.sendError(MakeUnknownMethodError(name), sender, serial) | ||||
| 		return | ||||
| 	} | ||||
| 	args, err := conn.decodeArguments(m, sender, msg) | ||||
| 	if err != nil { | ||||
| 		conn.sendError(err, sender, serial) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ret, err := m.Call(args...) | ||||
| 	if err != nil { | ||||
| 		conn.sendError(err, sender, serial) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if msg.Flags&FlagNoReplyExpected == 0 { | ||||
| 		reply := new(Message) | ||||
| 		reply.Type = TypeMethodReply | ||||
| 		reply.Headers = make(map[HeaderField]Variant) | ||||
| 		if hasSender { | ||||
| 			reply.Headers[FieldDestination] = msg.Headers[FieldSender] | ||||
| 		} | ||||
| 		reply.Headers[FieldReplySerial] = MakeVariant(msg.serial) | ||||
| 		reply.Body = make([]interface{}, len(ret)) | ||||
| 		for i := 0; i < len(ret); i++ { | ||||
| 			reply.Body[i] = ret[i] | ||||
| 		} | ||||
| 		reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...)) | ||||
|  | ||||
| 		if err := reply.IsValid(); err != nil { | ||||
| 			fmt.Fprintf(os.Stderr, "dbus: dropping invalid reply to %s.%s on obj %s: %s\n", ifaceName, name, path, err) | ||||
| 		} else { | ||||
| 			conn.sendMessageAndIfClosed(reply, nil) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Emit emits the given signal on the message bus. The name parameter must be | ||||
| // formatted as "interface.member", e.g., "org.freedesktop.DBus.NameLost". | ||||
| func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) error { | ||||
| 	i := strings.LastIndex(name, ".") | ||||
| 	if i == -1 { | ||||
| 		return errors.New("dbus: invalid method name") | ||||
| 	} | ||||
| 	iface := name[:i] | ||||
| 	member := name[i+1:] | ||||
| 	msg := new(Message) | ||||
| 	msg.Type = TypeSignal | ||||
| 	msg.Headers = make(map[HeaderField]Variant) | ||||
| 	msg.Headers[FieldInterface] = MakeVariant(iface) | ||||
| 	msg.Headers[FieldMember] = MakeVariant(member) | ||||
| 	msg.Headers[FieldPath] = MakeVariant(path) | ||||
| 	msg.Body = values | ||||
| 	if len(values) > 0 { | ||||
| 		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...)) | ||||
| 	} | ||||
| 	if err := msg.IsValid(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	var closed bool | ||||
| 	conn.sendMessageAndIfClosed(msg, func() { | ||||
| 		closed = true | ||||
| 	}) | ||||
| 	if closed { | ||||
| 		return ErrClosed | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Export registers the given value to be exported as an object on the | ||||
| // message bus. | ||||
| // | ||||
| // If a method call on the given path and interface is received, an exported | ||||
| // method with the same name is called with v as the receiver if the | ||||
| // parameters match and the last return value is of type *Error. If this | ||||
| // *Error is not nil, it is sent back to the caller as an error. | ||||
| // Otherwise, a method reply is sent with the other return values as its body. | ||||
| // | ||||
| // Any parameters with the special type Sender are set to the sender of the | ||||
| // dbus message when the method is called. Parameters of this type do not | ||||
| // contribute to the dbus signature of the method (i.e. the method is exposed | ||||
| // as if the parameters of type Sender were not there). | ||||
| // | ||||
| // Similarly, any parameters with the type Message are set to the raw message | ||||
| // received on the bus. Again, parameters of this type do not contribute to the | ||||
| // dbus signature of the method. | ||||
| // | ||||
| // Every method call is executed in a new goroutine, so the method may be called | ||||
| // in multiple goroutines at once. | ||||
| // | ||||
| // Method calls on the interface org.freedesktop.DBus.Peer will be automatically | ||||
| // handled for every object. | ||||
| // | ||||
| // Passing nil as the first parameter will cause conn to cease handling calls on | ||||
| // the given combination of path and interface. | ||||
| // | ||||
| // Export returns an error if path is not a valid path name. | ||||
| func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error { | ||||
| 	return conn.ExportWithMap(v, nil, path, iface) | ||||
| } | ||||
|  | ||||
| // ExportAll registers all exported methods defined by the given object on | ||||
| // the message bus. | ||||
| // | ||||
| // Unlike Export there is no requirement to have the last parameter as type | ||||
| // *Error. If you want to be able to return error then you can append an error | ||||
| // type parameter to your method signature. If the error returned is not nil, | ||||
| // it is sent back to the caller as an error. Otherwise, a method reply is | ||||
| // sent with the other return values as its body. | ||||
| func (conn *Conn) ExportAll(v interface{}, path ObjectPath, iface string) error { | ||||
| 	return conn.export(getAllMethods(v, nil), path, iface, false) | ||||
| } | ||||
|  | ||||
| // ExportWithMap works exactly like Export but provides the ability to remap | ||||
| // method names (e.g. export a lower-case method). | ||||
| // | ||||
| // The keys in the map are the real method names (exported on the struct), and | ||||
| // the values are the method names to be exported on DBus. | ||||
| func (conn *Conn) ExportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error { | ||||
| 	return conn.export(getMethods(v, mapping), path, iface, false) | ||||
| } | ||||
|  | ||||
| // ExportSubtree works exactly like Export but registers the given value for | ||||
| // an entire subtree rather under the root path provided. | ||||
| // | ||||
| // In order to make this useful, one parameter in each of the value's exported | ||||
| // methods should be a Message, in which case it will contain the raw message | ||||
| // (allowing one to get access to the path that caused the method to be called). | ||||
| // | ||||
| // Note that more specific export paths take precedence over less specific. For | ||||
| // example, a method call using the ObjectPath /foo/bar/baz will call a method | ||||
| // exported on /foo/bar before a method exported on /foo. | ||||
| func (conn *Conn) ExportSubtree(v interface{}, path ObjectPath, iface string) error { | ||||
| 	return conn.ExportSubtreeWithMap(v, nil, path, iface) | ||||
| } | ||||
|  | ||||
| // ExportSubtreeWithMap works exactly like ExportSubtree but provides the | ||||
| // ability to remap method names (e.g. export a lower-case method). | ||||
| // | ||||
| // The keys in the map are the real method names (exported on the struct), and | ||||
| // the values are the method names to be exported on DBus. | ||||
| func (conn *Conn) ExportSubtreeWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error { | ||||
| 	return conn.export(getMethods(v, mapping), path, iface, true) | ||||
| } | ||||
|  | ||||
| // ExportMethodTable like Export registers the given methods as an object | ||||
| // on the message bus. Unlike Export the it uses a method table to define | ||||
| // the object instead of a native go object. | ||||
| // | ||||
| // The method table is a map from method name to function closure | ||||
| // representing the method. This allows an object exported on the bus to not | ||||
| // necessarily be a native go object. It can be useful for generating exposed | ||||
| // methods on the fly. | ||||
| // | ||||
| // Any non-function objects in the method table are ignored. | ||||
| func (conn *Conn) ExportMethodTable(methods map[string]interface{}, path ObjectPath, iface string) error { | ||||
| 	return conn.exportMethodTable(methods, path, iface, false) | ||||
| } | ||||
|  | ||||
| // Like ExportSubtree, but with the same caveats as ExportMethodTable. | ||||
| func (conn *Conn) ExportSubtreeMethodTable(methods map[string]interface{}, path ObjectPath, iface string) error { | ||||
| 	return conn.exportMethodTable(methods, path, iface, true) | ||||
| } | ||||
|  | ||||
| func (conn *Conn) exportMethodTable(methods map[string]interface{}, path ObjectPath, iface string, includeSubtree bool) error { | ||||
| 	var out map[string]reflect.Value | ||||
| 	if methods != nil { | ||||
| 		out = make(map[string]reflect.Value) | ||||
| 		for name, method := range methods { | ||||
| 			rval := reflect.ValueOf(method) | ||||
| 			if rval.Kind() != reflect.Func { | ||||
| 				continue | ||||
| 			} | ||||
| 			t := rval.Type() | ||||
| 			// only track valid methods must return *Error as last arg | ||||
| 			if t.NumOut() == 0 || | ||||
| 				t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) { | ||||
| 				continue | ||||
| 			} | ||||
| 			out[name] = rval | ||||
| 		} | ||||
| 	} | ||||
| 	return conn.export(out, path, iface, includeSubtree) | ||||
| } | ||||
|  | ||||
| func (conn *Conn) unexport(h *defaultHandler, path ObjectPath, iface string) error { | ||||
| 	if h.PathExists(path) { | ||||
| 		obj := h.objects[path] | ||||
| 		obj.DeleteInterface(iface) | ||||
| 		if len(obj.interfaces) == 0 { | ||||
| 			h.DeleteObject(path) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // export is the worker function for all exports/registrations. | ||||
| func (conn *Conn) export(methods map[string]reflect.Value, path ObjectPath, iface string, includeSubtree bool) error { | ||||
| 	h, ok := conn.handler.(*defaultHandler) | ||||
| 	if !ok { | ||||
| 		return fmt.Errorf( | ||||
| 			`dbus: export only allowed on the default handler. Received: %T"`, | ||||
| 			conn.handler) | ||||
| 	} | ||||
|  | ||||
| 	if !path.IsValid() { | ||||
| 		return fmt.Errorf(`dbus: Invalid path name: "%s"`, path) | ||||
| 	} | ||||
|  | ||||
| 	// Remove a previous export if the interface is nil | ||||
| 	if methods == nil { | ||||
| 		return conn.unexport(h, path, iface) | ||||
| 	} | ||||
|  | ||||
| 	// If this is the first handler for this path, make a new map to hold all | ||||
| 	// handlers for this path. | ||||
| 	if !h.PathExists(path) { | ||||
| 		h.AddObject(path, newExportedObject()) | ||||
| 	} | ||||
|  | ||||
| 	exportedMethods := make(map[string]Method) | ||||
| 	for name, method := range methods { | ||||
| 		exportedMethods[name] = exportedMethod{method} | ||||
| 	} | ||||
|  | ||||
| 	// Finally, save this handler | ||||
| 	obj := h.objects[path] | ||||
| 	obj.AddInterface(iface, newExportedIntf(exportedMethods, includeSubtree)) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ReleaseName calls org.freedesktop.DBus.ReleaseName and awaits a response. | ||||
| func (conn *Conn) ReleaseName(name string) (ReleaseNameReply, error) { | ||||
| 	var r uint32 | ||||
| 	err := conn.busObj.Call("org.freedesktop.DBus.ReleaseName", 0, name).Store(&r) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	return ReleaseNameReply(r), nil | ||||
| } | ||||
|  | ||||
| // RequestName calls org.freedesktop.DBus.RequestName and awaits a response. | ||||
| func (conn *Conn) RequestName(name string, flags RequestNameFlags) (RequestNameReply, error) { | ||||
| 	var r uint32 | ||||
| 	err := conn.busObj.Call("org.freedesktop.DBus.RequestName", 0, name, flags).Store(&r) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	return RequestNameReply(r), nil | ||||
| } | ||||
|  | ||||
| // ReleaseNameReply is the reply to a ReleaseName call. | ||||
| type ReleaseNameReply uint32 | ||||
|  | ||||
| const ( | ||||
| 	ReleaseNameReplyReleased ReleaseNameReply = 1 + iota | ||||
| 	ReleaseNameReplyNonExistent | ||||
| 	ReleaseNameReplyNotOwner | ||||
| ) | ||||
|  | ||||
| // RequestNameFlags represents the possible flags for a RequestName call. | ||||
| type RequestNameFlags uint32 | ||||
|  | ||||
| const ( | ||||
| 	NameFlagAllowReplacement RequestNameFlags = 1 << iota | ||||
| 	NameFlagReplaceExisting | ||||
| 	NameFlagDoNotQueue | ||||
| ) | ||||
|  | ||||
| // RequestNameReply is the reply to a RequestName call. | ||||
| type RequestNameReply uint32 | ||||
|  | ||||
| const ( | ||||
| 	RequestNameReplyPrimaryOwner RequestNameReply = 1 + iota | ||||
| 	RequestNameReplyInQueue | ||||
| 	RequestNameReplyExists | ||||
| 	RequestNameReplyAlreadyOwner | ||||
| ) | ||||
							
								
								
									
										25
									
								
								vendor/github.com/godbus/dbus/v5/homedir.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/godbus/dbus/v5/homedir.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"os/user" | ||||
| ) | ||||
|  | ||||
| // Get returns the home directory of the current user, which is usually the | ||||
| // value of HOME environment variable. In case it is not set or empty, os/user | ||||
| // package is used. | ||||
| // | ||||
| // If linking statically with cgo enabled against glibc, make sure the | ||||
| // osusergo build tag is used. | ||||
| // | ||||
| // If needing to do nss lookups, do not disable cgo or set osusergo. | ||||
| func getHomeDir() string { | ||||
| 	homeDir := os.Getenv("HOME") | ||||
| 	if homeDir != "" { | ||||
| 		return homeDir | ||||
| 	} | ||||
| 	if u, err := user.Current(); err == nil { | ||||
| 		return u.HomeDir | ||||
| 	} | ||||
| 	return "/" | ||||
| } | ||||
							
								
								
									
										89
									
								
								vendor/github.com/godbus/dbus/v5/match.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								vendor/github.com/godbus/dbus/v5/match.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // MatchOption specifies option for dbus routing match rule. Options can be constructed with WithMatch* helpers. | ||||
| // For full list of available options consult | ||||
| // https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-routing-match-rules | ||||
| type MatchOption struct { | ||||
| 	key   string | ||||
| 	value string | ||||
| } | ||||
|  | ||||
| func formatMatchOptions(options []MatchOption) string { | ||||
| 	items := make([]string, 0, len(options)) | ||||
| 	for _, option := range options { | ||||
| 		items = append(items, option.key+"='"+option.value+"'") | ||||
| 	} | ||||
| 	return strings.Join(items, ",") | ||||
| } | ||||
|  | ||||
| // WithMatchOption creates match option with given key and value | ||||
| func WithMatchOption(key, value string) MatchOption { | ||||
| 	return MatchOption{key, value} | ||||
| } | ||||
|  | ||||
| // doesn't make sense to export this option because clients can only | ||||
| // subscribe to messages with signal type. | ||||
| func withMatchType(typ string) MatchOption { | ||||
| 	return WithMatchOption("type", typ) | ||||
| } | ||||
|  | ||||
| // WithMatchSender sets sender match option. | ||||
| func WithMatchSender(sender string) MatchOption { | ||||
| 	return WithMatchOption("sender", sender) | ||||
| } | ||||
|  | ||||
| // WithMatchSender sets interface match option. | ||||
| func WithMatchInterface(iface string) MatchOption { | ||||
| 	return WithMatchOption("interface", iface) | ||||
| } | ||||
|  | ||||
| // WithMatchMember sets member match option. | ||||
| func WithMatchMember(member string) MatchOption { | ||||
| 	return WithMatchOption("member", member) | ||||
| } | ||||
|  | ||||
| // WithMatchObjectPath creates match option that filters events based on given path | ||||
| func WithMatchObjectPath(path ObjectPath) MatchOption { | ||||
| 	return WithMatchOption("path", string(path)) | ||||
| } | ||||
|  | ||||
| // WithMatchPathNamespace sets path_namespace match option. | ||||
| func WithMatchPathNamespace(namespace ObjectPath) MatchOption { | ||||
| 	return WithMatchOption("path_namespace", string(namespace)) | ||||
| } | ||||
|  | ||||
| // WithMatchDestination sets destination match option. | ||||
| func WithMatchDestination(destination string) MatchOption { | ||||
| 	return WithMatchOption("destination", destination) | ||||
| } | ||||
|  | ||||
| // WithMatchArg sets argN match option, range of N is 0 to 63. | ||||
| func WithMatchArg(argIdx int, value string) MatchOption { | ||||
| 	if argIdx < 0 || argIdx > 63 { | ||||
| 		panic("range of argument index is 0 to 63") | ||||
| 	} | ||||
| 	return WithMatchOption("arg"+strconv.Itoa(argIdx), value) | ||||
| } | ||||
|  | ||||
| // WithMatchArgPath sets argN path match option, range of N is 0 to 63. | ||||
| func WithMatchArgPath(argIdx int, path string) MatchOption { | ||||
| 	if argIdx < 0 || argIdx > 63 { | ||||
| 		panic("range of argument index is 0 to 63") | ||||
| 	} | ||||
| 	return WithMatchOption("arg"+strconv.Itoa(argIdx)+"path", path) | ||||
| } | ||||
|  | ||||
| // WithMatchArg0Namespace sets arg0namespace match option. | ||||
| func WithMatchArg0Namespace(arg0Namespace string) MatchOption { | ||||
| 	return WithMatchOption("arg0namespace", arg0Namespace) | ||||
| } | ||||
|  | ||||
| // WithMatchEavesdrop sets eavesdrop match option. | ||||
| func WithMatchEavesdrop(eavesdrop bool) MatchOption { | ||||
| 	return WithMatchOption("eavesdrop", strconv.FormatBool(eavesdrop)) | ||||
| } | ||||
							
								
								
									
										390
									
								
								vendor/github.com/godbus/dbus/v5/message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										390
									
								
								vendor/github.com/godbus/dbus/v5/message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,390 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| ) | ||||
|  | ||||
| const protoVersion byte = 1 | ||||
|  | ||||
| // Flags represents the possible flags of a D-Bus message. | ||||
| type Flags byte | ||||
|  | ||||
| const ( | ||||
| 	// FlagNoReplyExpected signals that the message is not expected to generate | ||||
| 	// a reply. If this flag is set on outgoing messages, any possible reply | ||||
| 	// will be discarded. | ||||
| 	FlagNoReplyExpected Flags = 1 << iota | ||||
| 	// FlagNoAutoStart signals that the message bus should not automatically | ||||
| 	// start an application when handling this message. | ||||
| 	FlagNoAutoStart | ||||
| 	// FlagAllowInteractiveAuthorization may be set on a method call | ||||
| 	// message to inform the receiving side that the caller is prepared | ||||
| 	// to wait for interactive authorization, which might take a | ||||
| 	// considerable time to complete. For instance, if this flag is set, | ||||
| 	// it would be appropriate to query the user for passwords or | ||||
| 	// confirmation via Polkit or a similar framework. | ||||
| 	FlagAllowInteractiveAuthorization | ||||
| ) | ||||
|  | ||||
| // Type represents the possible types of a D-Bus message. | ||||
| type Type byte | ||||
|  | ||||
| const ( | ||||
| 	TypeMethodCall Type = 1 + iota | ||||
| 	TypeMethodReply | ||||
| 	TypeError | ||||
| 	TypeSignal | ||||
| 	typeMax | ||||
| ) | ||||
|  | ||||
| func (t Type) String() string { | ||||
| 	switch t { | ||||
| 	case TypeMethodCall: | ||||
| 		return "method call" | ||||
| 	case TypeMethodReply: | ||||
| 		return "reply" | ||||
| 	case TypeError: | ||||
| 		return "error" | ||||
| 	case TypeSignal: | ||||
| 		return "signal" | ||||
| 	} | ||||
| 	return "invalid" | ||||
| } | ||||
|  | ||||
| // HeaderField represents the possible byte codes for the headers | ||||
| // of a D-Bus message. | ||||
| type HeaderField byte | ||||
|  | ||||
| const ( | ||||
| 	FieldPath HeaderField = 1 + iota | ||||
| 	FieldInterface | ||||
| 	FieldMember | ||||
| 	FieldErrorName | ||||
| 	FieldReplySerial | ||||
| 	FieldDestination | ||||
| 	FieldSender | ||||
| 	FieldSignature | ||||
| 	FieldUnixFDs | ||||
| 	fieldMax | ||||
| ) | ||||
|  | ||||
| // An InvalidMessageError describes the reason why a D-Bus message is regarded as | ||||
| // invalid. | ||||
| type InvalidMessageError string | ||||
|  | ||||
| func (e InvalidMessageError) Error() string { | ||||
| 	return "dbus: invalid message: " + string(e) | ||||
| } | ||||
|  | ||||
| // fieldType are the types of the various header fields. | ||||
| var fieldTypes = [fieldMax]reflect.Type{ | ||||
| 	FieldPath:        objectPathType, | ||||
| 	FieldInterface:   stringType, | ||||
| 	FieldMember:      stringType, | ||||
| 	FieldErrorName:   stringType, | ||||
| 	FieldReplySerial: uint32Type, | ||||
| 	FieldDestination: stringType, | ||||
| 	FieldSender:      stringType, | ||||
| 	FieldSignature:   signatureType, | ||||
| 	FieldUnixFDs:     uint32Type, | ||||
| } | ||||
|  | ||||
| // requiredFields lists the header fields that are required by the different | ||||
| // message types. | ||||
| var requiredFields = [typeMax][]HeaderField{ | ||||
| 	TypeMethodCall:  {FieldPath, FieldMember}, | ||||
| 	TypeMethodReply: {FieldReplySerial}, | ||||
| 	TypeError:       {FieldErrorName, FieldReplySerial}, | ||||
| 	TypeSignal:      {FieldPath, FieldInterface, FieldMember}, | ||||
| } | ||||
|  | ||||
| // Message represents a single D-Bus message. | ||||
| type Message struct { | ||||
| 	Type | ||||
| 	Flags | ||||
| 	Headers map[HeaderField]Variant | ||||
| 	Body    []interface{} | ||||
|  | ||||
| 	serial uint32 | ||||
| } | ||||
|  | ||||
| type header struct { | ||||
| 	Field byte | ||||
| 	Variant | ||||
| } | ||||
|  | ||||
| func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) { | ||||
| 	var order binary.ByteOrder | ||||
| 	var hlength, length uint32 | ||||
| 	var typ, flags, proto byte | ||||
| 	var headers []header | ||||
|  | ||||
| 	b := make([]byte, 1) | ||||
| 	_, err = rd.Read(b) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	switch b[0] { | ||||
| 	case 'l': | ||||
| 		order = binary.LittleEndian | ||||
| 	case 'B': | ||||
| 		order = binary.BigEndian | ||||
| 	default: | ||||
| 		return nil, InvalidMessageError("invalid byte order") | ||||
| 	} | ||||
|  | ||||
| 	dec := newDecoder(rd, order, fds) | ||||
| 	dec.pos = 1 | ||||
|  | ||||
| 	msg = new(Message) | ||||
| 	vs, err := dec.Decode(Signature{"yyyuu"}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err = Store(vs, &typ, &flags, &proto, &length, &msg.serial); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	msg.Type = Type(typ) | ||||
| 	msg.Flags = Flags(flags) | ||||
|  | ||||
| 	// get the header length separately because we need it later | ||||
| 	b = make([]byte, 4) | ||||
| 	_, err = io.ReadFull(rd, b) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	binary.Read(bytes.NewBuffer(b), order, &hlength) | ||||
| 	if hlength+length+16 > 1<<27 { | ||||
| 		return nil, InvalidMessageError("message is too long") | ||||
| 	} | ||||
| 	dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order, fds) | ||||
| 	dec.pos = 12 | ||||
| 	vs, err = dec.Decode(Signature{"a(yv)"}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err = Store(vs, &headers); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	msg.Headers = make(map[HeaderField]Variant) | ||||
| 	for _, v := range headers { | ||||
| 		msg.Headers[HeaderField(v.Field)] = v.Variant | ||||
| 	} | ||||
|  | ||||
| 	dec.align(8) | ||||
| 	body := make([]byte, int(length)) | ||||
| 	if length != 0 { | ||||
| 		_, err := io.ReadFull(rd, body) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err = msg.IsValid(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	sig, _ := msg.Headers[FieldSignature].value.(Signature) | ||||
| 	if sig.str != "" { | ||||
| 		buf := bytes.NewBuffer(body) | ||||
| 		dec = newDecoder(buf, order, fds) | ||||
| 		vs, err := dec.Decode(sig) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		msg.Body = vs | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DecodeMessage tries to decode a single message in the D-Bus wire format | ||||
| // from the given reader. The byte order is figured out from the first byte. | ||||
| // The possibly returned error can be an error of the underlying reader, an | ||||
| // InvalidMessageError or a FormatError. | ||||
| func DecodeMessage(rd io.Reader) (msg *Message, err error) { | ||||
| 	return DecodeMessageWithFDs(rd, make([]int, 0)) | ||||
| } | ||||
|  | ||||
| type nullwriter struct{} | ||||
|  | ||||
| func (nullwriter) Write(p []byte) (cnt int, err error) { | ||||
| 	return len(p), nil | ||||
| } | ||||
|  | ||||
| func (msg *Message) CountFds() (int, error) { | ||||
| 	if len(msg.Body) == 0 { | ||||
| 		return 0, nil | ||||
| 	} | ||||
| 	enc := newEncoder(nullwriter{}, nativeEndian, make([]int, 0)) | ||||
| 	err := enc.Encode(msg.Body...) | ||||
| 	return len(enc.fds), err | ||||
| } | ||||
|  | ||||
| func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds []int, err error) { | ||||
| 	if err := msg.validateHeader(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var vs [7]interface{} | ||||
| 	switch order { | ||||
| 	case binary.LittleEndian: | ||||
| 		vs[0] = byte('l') | ||||
| 	case binary.BigEndian: | ||||
| 		vs[0] = byte('B') | ||||
| 	default: | ||||
| 		return nil, errors.New("dbus: invalid byte order") | ||||
| 	} | ||||
| 	body := new(bytes.Buffer) | ||||
| 	fds = make([]int, 0) | ||||
| 	enc := newEncoder(body, order, fds) | ||||
| 	if len(msg.Body) != 0 { | ||||
| 		err = enc.Encode(msg.Body...) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	vs[1] = msg.Type | ||||
| 	vs[2] = msg.Flags | ||||
| 	vs[3] = protoVersion | ||||
| 	vs[4] = uint32(len(body.Bytes())) | ||||
| 	vs[5] = msg.serial | ||||
| 	headers := make([]header, 0, len(msg.Headers)) | ||||
| 	for k, v := range msg.Headers { | ||||
| 		headers = append(headers, header{byte(k), v}) | ||||
| 	} | ||||
| 	vs[6] = headers | ||||
| 	var buf bytes.Buffer | ||||
| 	enc = newEncoder(&buf, order, enc.fds) | ||||
| 	err = enc.Encode(vs[:]...) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	enc.align(8) | ||||
| 	body.WriteTo(&buf) | ||||
| 	if buf.Len() > 1<<27 { | ||||
| 		return make([]int, 0), InvalidMessageError("message is too long") | ||||
| 	} | ||||
| 	if _, err := buf.WriteTo(out); err != nil { | ||||
| 		return make([]int, 0), err | ||||
| 	} | ||||
| 	return enc.fds, nil | ||||
| } | ||||
|  | ||||
| // EncodeTo encodes and sends a message to the given writer. The byte order must | ||||
| // be either binary.LittleEndian or binary.BigEndian. If the message is not | ||||
| // valid or an error occurs when writing, an error is returned. | ||||
| func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error) { | ||||
| 	_, err = msg.EncodeToWithFDs(out, order) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // IsValid checks whether msg is a valid message and returns an | ||||
| // InvalidMessageError or FormatError if it is not. | ||||
| func (msg *Message) IsValid() error { | ||||
| 	var b bytes.Buffer | ||||
| 	return msg.EncodeTo(&b, nativeEndian) | ||||
| } | ||||
|  | ||||
| func (msg *Message) validateHeader() error { | ||||
| 	if msg.Flags & ^(FlagNoAutoStart|FlagNoReplyExpected|FlagAllowInteractiveAuthorization) != 0 { | ||||
| 		return InvalidMessageError("invalid flags") | ||||
| 	} | ||||
| 	if msg.Type == 0 || msg.Type >= typeMax { | ||||
| 		return InvalidMessageError("invalid message type") | ||||
| 	} | ||||
| 	for k, v := range msg.Headers { | ||||
| 		if k == 0 || k >= fieldMax { | ||||
| 			return InvalidMessageError("invalid header") | ||||
| 		} | ||||
| 		if reflect.TypeOf(v.value) != fieldTypes[k] { | ||||
| 			return InvalidMessageError("invalid type of header field") | ||||
| 		} | ||||
| 	} | ||||
| 	for _, v := range requiredFields[msg.Type] { | ||||
| 		if _, ok := msg.Headers[v]; !ok { | ||||
| 			return InvalidMessageError("missing required header") | ||||
| 		} | ||||
| 	} | ||||
| 	if path, ok := msg.Headers[FieldPath]; ok { | ||||
| 		if !path.value.(ObjectPath).IsValid() { | ||||
| 			return InvalidMessageError("invalid path name") | ||||
| 		} | ||||
| 	} | ||||
| 	if iface, ok := msg.Headers[FieldInterface]; ok { | ||||
| 		if !isValidInterface(iface.value.(string)) { | ||||
| 			return InvalidMessageError("invalid interface name") | ||||
| 		} | ||||
| 	} | ||||
| 	if member, ok := msg.Headers[FieldMember]; ok { | ||||
| 		if !isValidMember(member.value.(string)) { | ||||
| 			return InvalidMessageError("invalid member name") | ||||
| 		} | ||||
| 	} | ||||
| 	if errname, ok := msg.Headers[FieldErrorName]; ok { | ||||
| 		if !isValidInterface(errname.value.(string)) { | ||||
| 			return InvalidMessageError("invalid error name") | ||||
| 		} | ||||
| 	} | ||||
| 	if len(msg.Body) != 0 { | ||||
| 		if _, ok := msg.Headers[FieldSignature]; !ok { | ||||
| 			return InvalidMessageError("missing signature") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Serial returns the message's serial number. The returned value is only valid | ||||
| // for messages received by eavesdropping. | ||||
| func (msg *Message) Serial() uint32 { | ||||
| 	return msg.serial | ||||
| } | ||||
|  | ||||
| // String returns a string representation of a message similar to the format of | ||||
| // dbus-monitor. | ||||
| func (msg *Message) String() string { | ||||
| 	if err := msg.IsValid(); err != nil { | ||||
| 		return "<invalid>" | ||||
| 	} | ||||
| 	s := msg.Type.String() | ||||
| 	if v, ok := msg.Headers[FieldSender]; ok { | ||||
| 		s += " from " + v.value.(string) | ||||
| 	} | ||||
| 	if v, ok := msg.Headers[FieldDestination]; ok { | ||||
| 		s += " to " + v.value.(string) | ||||
| 	} | ||||
| 	s += " serial " + strconv.FormatUint(uint64(msg.serial), 10) | ||||
| 	if v, ok := msg.Headers[FieldReplySerial]; ok { | ||||
| 		s += " reply_serial " + strconv.FormatUint(uint64(v.value.(uint32)), 10) | ||||
| 	} | ||||
| 	if v, ok := msg.Headers[FieldUnixFDs]; ok { | ||||
| 		s += " unixfds " + strconv.FormatUint(uint64(v.value.(uint32)), 10) | ||||
| 	} | ||||
| 	if v, ok := msg.Headers[FieldPath]; ok { | ||||
| 		s += " path " + string(v.value.(ObjectPath)) | ||||
| 	} | ||||
| 	if v, ok := msg.Headers[FieldInterface]; ok { | ||||
| 		s += " interface " + v.value.(string) | ||||
| 	} | ||||
| 	if v, ok := msg.Headers[FieldErrorName]; ok { | ||||
| 		s += " error " + v.value.(string) | ||||
| 	} | ||||
| 	if v, ok := msg.Headers[FieldMember]; ok { | ||||
| 		s += " member " + v.value.(string) | ||||
| 	} | ||||
| 	if len(msg.Body) != 0 { | ||||
| 		s += "\n" | ||||
| 	} | ||||
| 	for i, v := range msg.Body { | ||||
| 		s += "  " + MakeVariant(v).String() | ||||
| 		if i != len(msg.Body)-1 { | ||||
| 			s += "\n" | ||||
| 		} | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
							
								
								
									
										174
									
								
								vendor/github.com/godbus/dbus/v5/object.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								vendor/github.com/godbus/dbus/v5/object.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // BusObject is the interface of a remote object on which methods can be | ||||
| // invoked. | ||||
| type BusObject interface { | ||||
| 	Call(method string, flags Flags, args ...interface{}) *Call | ||||
| 	CallWithContext(ctx context.Context, method string, flags Flags, args ...interface{}) *Call | ||||
| 	Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call | ||||
| 	GoWithContext(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call | ||||
| 	AddMatchSignal(iface, member string, options ...MatchOption) *Call | ||||
| 	RemoveMatchSignal(iface, member string, options ...MatchOption) *Call | ||||
| 	GetProperty(p string) (Variant, error) | ||||
| 	StoreProperty(p string, value interface{}) error | ||||
| 	SetProperty(p string, v interface{}) error | ||||
| 	Destination() string | ||||
| 	Path() ObjectPath | ||||
| } | ||||
|  | ||||
| // Object represents a remote object on which methods can be invoked. | ||||
| type Object struct { | ||||
| 	conn *Conn | ||||
| 	dest string | ||||
| 	path ObjectPath | ||||
| } | ||||
|  | ||||
| // Call calls a method with (*Object).Go and waits for its reply. | ||||
| func (o *Object) Call(method string, flags Flags, args ...interface{}) *Call { | ||||
| 	return <-o.createCall(context.Background(), method, flags, make(chan *Call, 1), args...).Done | ||||
| } | ||||
|  | ||||
| // CallWithContext acts like Call but takes a context | ||||
| func (o *Object) CallWithContext(ctx context.Context, method string, flags Flags, args ...interface{}) *Call { | ||||
| 	return <-o.createCall(ctx, method, flags, make(chan *Call, 1), args...).Done | ||||
| } | ||||
|  | ||||
| // AddMatchSignal subscribes BusObject to signals from specified interface, | ||||
| // method (member). Additional filter rules can be added via WithMatch* option constructors. | ||||
| // Note: To filter events by object path you have to specify this path via an option. | ||||
| // | ||||
| // Deprecated: use (*Conn) AddMatchSignal instead. | ||||
| func (o *Object) AddMatchSignal(iface, member string, options ...MatchOption) *Call { | ||||
| 	base := []MatchOption{ | ||||
| 		withMatchType("signal"), | ||||
| 		WithMatchInterface(iface), | ||||
| 		WithMatchMember(member), | ||||
| 	} | ||||
|  | ||||
| 	options = append(base, options...) | ||||
| 	return o.conn.BusObject().Call( | ||||
| 		"org.freedesktop.DBus.AddMatch", | ||||
| 		0, | ||||
| 		formatMatchOptions(options), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| // RemoveMatchSignal unsubscribes BusObject from signals from specified interface, | ||||
| // method (member). Additional filter rules can be added via WithMatch* option constructors | ||||
| // | ||||
| // Deprecated: use (*Conn) RemoveMatchSignal instead. | ||||
| func (o *Object) RemoveMatchSignal(iface, member string, options ...MatchOption) *Call { | ||||
| 	base := []MatchOption{ | ||||
| 		withMatchType("signal"), | ||||
| 		WithMatchInterface(iface), | ||||
| 		WithMatchMember(member), | ||||
| 	} | ||||
|  | ||||
| 	options = append(base, options...) | ||||
| 	return o.conn.BusObject().Call( | ||||
| 		"org.freedesktop.DBus.RemoveMatch", | ||||
| 		0, | ||||
| 		formatMatchOptions(options), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| // Go calls a method with the given arguments asynchronously. It returns a | ||||
| // Call structure representing this method call. The passed channel will | ||||
| // return the same value once the call is done. If ch is nil, a new channel | ||||
| // will be allocated. Otherwise, ch has to be buffered or Go will panic. | ||||
| // | ||||
| // If the flags include FlagNoReplyExpected, ch is ignored and a Call structure | ||||
| // is returned with any error in Err and a closed channel in Done containing | ||||
| // the returned Call as it's one entry. | ||||
| // | ||||
| // If the method parameter contains a dot ('.'), the part before the last dot | ||||
| // specifies the interface on which the method is called. | ||||
| func (o *Object) Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call { | ||||
| 	return o.createCall(context.Background(), method, flags, ch, args...) | ||||
| } | ||||
|  | ||||
| // GoWithContext acts like Go but takes a context | ||||
| func (o *Object) GoWithContext(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call { | ||||
| 	return o.createCall(ctx, method, flags, ch, args...) | ||||
| } | ||||
|  | ||||
| func (o *Object) createCall(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call { | ||||
| 	if ctx == nil { | ||||
| 		panic("nil context") | ||||
| 	} | ||||
| 	iface := "" | ||||
| 	i := strings.LastIndex(method, ".") | ||||
| 	if i != -1 { | ||||
| 		iface = method[:i] | ||||
| 	} | ||||
| 	method = method[i+1:] | ||||
| 	msg := new(Message) | ||||
| 	msg.Type = TypeMethodCall | ||||
| 	msg.Flags = flags & (FlagNoAutoStart | FlagNoReplyExpected) | ||||
| 	msg.Headers = make(map[HeaderField]Variant) | ||||
| 	msg.Headers[FieldPath] = MakeVariant(o.path) | ||||
| 	msg.Headers[FieldDestination] = MakeVariant(o.dest) | ||||
| 	msg.Headers[FieldMember] = MakeVariant(method) | ||||
| 	if iface != "" { | ||||
| 		msg.Headers[FieldInterface] = MakeVariant(iface) | ||||
| 	} | ||||
| 	msg.Body = args | ||||
| 	if len(args) > 0 { | ||||
| 		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(args...)) | ||||
| 	} | ||||
| 	return o.conn.SendWithContext(ctx, msg, ch) | ||||
| } | ||||
|  | ||||
| // GetProperty calls org.freedesktop.DBus.Properties.Get on the given | ||||
| // object. The property name must be given in interface.member notation. | ||||
| func (o *Object) GetProperty(p string) (Variant, error) { | ||||
| 	var result Variant | ||||
| 	err := o.StoreProperty(p, &result) | ||||
| 	return result, err | ||||
| } | ||||
|  | ||||
| // StoreProperty calls org.freedesktop.DBus.Properties.Get on the given | ||||
| // object. The property name must be given in interface.member notation. | ||||
| // It stores the returned property into the provided value. | ||||
| func (o *Object) StoreProperty(p string, value interface{}) error { | ||||
| 	idx := strings.LastIndex(p, ".") | ||||
| 	if idx == -1 || idx+1 == len(p) { | ||||
| 		return errors.New("dbus: invalid property " + p) | ||||
| 	} | ||||
|  | ||||
| 	iface := p[:idx] | ||||
| 	prop := p[idx+1:] | ||||
|  | ||||
| 	return o.Call("org.freedesktop.DBus.Properties.Get", 0, iface, prop). | ||||
| 		Store(value) | ||||
| } | ||||
|  | ||||
| // SetProperty calls org.freedesktop.DBus.Properties.Set on the given | ||||
| // object. The property name must be given in interface.member notation. | ||||
| func (o *Object) SetProperty(p string, v interface{}) error { | ||||
| 	idx := strings.LastIndex(p, ".") | ||||
| 	if idx == -1 || idx+1 == len(p) { | ||||
| 		return errors.New("dbus: invalid property " + p) | ||||
| 	} | ||||
|  | ||||
| 	iface := p[:idx] | ||||
| 	prop := p[idx+1:] | ||||
|  | ||||
| 	return o.Call("org.freedesktop.DBus.Properties.Set", 0, iface, prop, v).Err | ||||
| } | ||||
|  | ||||
| // Destination returns the destination that calls on (o *Object) are sent to. | ||||
| func (o *Object) Destination() string { | ||||
| 	return o.dest | ||||
| } | ||||
|  | ||||
| // Path returns the path that calls on (o *Object") are sent to. | ||||
| func (o *Object) Path() ObjectPath { | ||||
| 	return o.path | ||||
| } | ||||
							
								
								
									
										24
									
								
								vendor/github.com/godbus/dbus/v5/sequence.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/godbus/dbus/v5/sequence.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| package dbus | ||||
|  | ||||
| // Sequence represents the value of a monotonically increasing counter. | ||||
| type Sequence uint64 | ||||
|  | ||||
| const ( | ||||
| 	// NoSequence indicates the absence of a sequence value. | ||||
| 	NoSequence Sequence = 0 | ||||
| ) | ||||
|  | ||||
| // sequenceGenerator represents a monotonically increasing counter. | ||||
| type sequenceGenerator struct { | ||||
| 	nextSequence Sequence | ||||
| } | ||||
|  | ||||
| func (generator *sequenceGenerator) next() Sequence { | ||||
| 	result := generator.nextSequence | ||||
| 	generator.nextSequence++ | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| func newSequenceGenerator() *sequenceGenerator { | ||||
| 	return &sequenceGenerator{nextSequence: 1} | ||||
| } | ||||
							
								
								
									
										125
									
								
								vendor/github.com/godbus/dbus/v5/sequential_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								vendor/github.com/godbus/dbus/v5/sequential_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| // NewSequentialSignalHandler returns an instance of a new | ||||
| // signal handler that guarantees sequential processing of signals. It is a | ||||
| // guarantee of this signal handler that signals will be written to | ||||
| // channels in the order they are received on the DBus connection. | ||||
| func NewSequentialSignalHandler() SignalHandler { | ||||
| 	return &sequentialSignalHandler{} | ||||
| } | ||||
|  | ||||
| type sequentialSignalHandler struct { | ||||
| 	mu      sync.RWMutex | ||||
| 	closed  bool | ||||
| 	signals []*sequentialSignalChannelData | ||||
| } | ||||
|  | ||||
| func (sh *sequentialSignalHandler) DeliverSignal(intf, name string, signal *Signal) { | ||||
| 	sh.mu.RLock() | ||||
| 	defer sh.mu.RUnlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	for _, scd := range sh.signals { | ||||
| 		scd.deliver(signal) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (sh *sequentialSignalHandler) Terminate() { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for _, scd := range sh.signals { | ||||
| 		scd.close() | ||||
| 		close(scd.ch) | ||||
| 	} | ||||
| 	sh.closed = true | ||||
| 	sh.signals = nil | ||||
| } | ||||
|  | ||||
| func (sh *sequentialSignalHandler) AddSignal(ch chan<- *Signal) { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	sh.signals = append(sh.signals, newSequentialSignalChannelData(ch)) | ||||
| } | ||||
|  | ||||
| func (sh *sequentialSignalHandler) RemoveSignal(ch chan<- *Signal) { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	for i := len(sh.signals) - 1; i >= 0; i-- { | ||||
| 		if ch == sh.signals[i].ch { | ||||
| 			sh.signals[i].close() | ||||
| 			copy(sh.signals[i:], sh.signals[i+1:]) | ||||
| 			sh.signals[len(sh.signals)-1] = nil | ||||
| 			sh.signals = sh.signals[:len(sh.signals)-1] | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type sequentialSignalChannelData struct { | ||||
| 	ch   chan<- *Signal | ||||
| 	in   chan *Signal | ||||
| 	done chan struct{} | ||||
| } | ||||
|  | ||||
| func newSequentialSignalChannelData(ch chan<- *Signal) *sequentialSignalChannelData { | ||||
| 	scd := &sequentialSignalChannelData{ | ||||
| 		ch:   ch, | ||||
| 		in:   make(chan *Signal), | ||||
| 		done: make(chan struct{}), | ||||
| 	} | ||||
| 	go scd.bufferSignals() | ||||
| 	return scd | ||||
| } | ||||
|  | ||||
| func (scd *sequentialSignalChannelData) bufferSignals() { | ||||
| 	defer close(scd.done) | ||||
|  | ||||
| 	// Ensure that signals are delivered to scd.ch in the same | ||||
| 	// order they are received from scd.in. | ||||
| 	var queue []*Signal | ||||
| 	for { | ||||
| 		if len(queue) == 0 { | ||||
| 			signal, ok := <- scd.in | ||||
| 			if !ok { | ||||
| 				return | ||||
| 			} | ||||
| 			queue = append(queue, signal) | ||||
| 		} | ||||
| 		select { | ||||
| 		case scd.ch <- queue[0]: | ||||
| 			copy(queue, queue[1:]) | ||||
| 			queue[len(queue)-1] = nil | ||||
| 			queue = queue[:len(queue)-1] | ||||
| 		case signal, ok := <-scd.in: | ||||
| 			if !ok { | ||||
| 				return | ||||
| 			} | ||||
| 			queue = append(queue, signal) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (scd *sequentialSignalChannelData) deliver(signal *Signal) { | ||||
| 	scd.in <- signal | ||||
| } | ||||
|  | ||||
| func (scd *sequentialSignalChannelData) close() { | ||||
| 	close(scd.in) | ||||
| 	// Ensure that bufferSignals() has exited and won't attempt | ||||
| 	// any future sends on scd.ch | ||||
| 	<-scd.done | ||||
| } | ||||
							
								
								
									
										107
									
								
								vendor/github.com/godbus/dbus/v5/server_interfaces.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								vendor/github.com/godbus/dbus/v5/server_interfaces.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| package dbus | ||||
|  | ||||
| // Terminator allows a handler to implement a shutdown mechanism that | ||||
| // is called when the connection terminates. | ||||
| type Terminator interface { | ||||
| 	Terminate() | ||||
| } | ||||
|  | ||||
| // Handler is the representation of a D-Bus Application. | ||||
| // | ||||
| // The Handler must have a way to lookup objects given | ||||
| // an ObjectPath. The returned object must implement the | ||||
| // ServerObject interface. | ||||
| type Handler interface { | ||||
| 	LookupObject(path ObjectPath) (ServerObject, bool) | ||||
| } | ||||
|  | ||||
| // ServerObject is the representation of an D-Bus Object. | ||||
| // | ||||
| // Objects are registered at a path for a given Handler. | ||||
| // The Objects implement D-Bus interfaces. The semantics | ||||
| // of Interface lookup is up to the implementation of | ||||
| // the ServerObject. The ServerObject implementation may | ||||
| // choose to implement empty string as a valid interface | ||||
| // represeting all methods or not per the D-Bus specification. | ||||
| type ServerObject interface { | ||||
| 	LookupInterface(name string) (Interface, bool) | ||||
| } | ||||
|  | ||||
| // An Interface is the representation of a D-Bus Interface. | ||||
| // | ||||
| // Interfaces are a grouping of methods implemented by the Objects. | ||||
| // Interfaces are responsible for routing method calls. | ||||
| type Interface interface { | ||||
| 	LookupMethod(name string) (Method, bool) | ||||
| } | ||||
|  | ||||
| // A Method represents the exposed methods on D-Bus. | ||||
| type Method interface { | ||||
| 	// Call requires that all arguments are decoded before being passed to it. | ||||
| 	Call(args ...interface{}) ([]interface{}, error) | ||||
| 	NumArguments() int | ||||
| 	NumReturns() int | ||||
| 	// ArgumentValue returns a representative value for the argument at position | ||||
| 	// it should be of the proper type. reflect.Zero would be a good mechanism | ||||
| 	// to use for this Value. | ||||
| 	ArgumentValue(position int) interface{} | ||||
| 	// ReturnValue returns a representative value for the return at position | ||||
| 	// it should be of the proper type. reflect.Zero would be a good mechanism | ||||
| 	// to use for this Value. | ||||
| 	ReturnValue(position int) interface{} | ||||
| } | ||||
|  | ||||
| // An Argument Decoder can decode arguments using the non-standard mechanism | ||||
| // | ||||
| // If a method implements this interface then the non-standard | ||||
| // decoder will be used. | ||||
| // | ||||
| // Method arguments must be decoded from the message. | ||||
| // The mechanism for doing this will vary based on the | ||||
| // implementation of the method. A normal approach is provided | ||||
| // as part of this library, but may be replaced with | ||||
| // any other decoding scheme. | ||||
| type ArgumentDecoder interface { | ||||
| 	// To decode the arguments of a method the sender and message are | ||||
| 	// provided in case the semantics of the implementer provides access | ||||
| 	// to these as part of the method invocation. | ||||
| 	DecodeArguments(conn *Conn, sender string, msg *Message, args []interface{}) ([]interface{}, error) | ||||
| } | ||||
|  | ||||
| // A SignalHandler is responsible for delivering a signal. | ||||
| // | ||||
| // Signal delivery may be changed from the default channel | ||||
| // based approach by Handlers implementing the SignalHandler | ||||
| // interface. | ||||
| type SignalHandler interface { | ||||
| 	DeliverSignal(iface, name string, signal *Signal) | ||||
| } | ||||
|  | ||||
| // SignalRegistrar manages signal delivery channels. | ||||
| // | ||||
| // This is an optional set of methods for `SignalHandler`. | ||||
| type SignalRegistrar interface { | ||||
| 	AddSignal(ch chan<- *Signal) | ||||
| 	RemoveSignal(ch chan<- *Signal) | ||||
| } | ||||
|  | ||||
| // A DBusError is used to convert a generic object to a D-Bus error. | ||||
| // | ||||
| // Any custom error mechanism may implement this interface to provide | ||||
| // a custom encoding of the error on D-Bus. By default if a normal | ||||
| // error is returned, it will be encoded as the generic | ||||
| // "org.freedesktop.DBus.Error.Failed" error. By implementing this | ||||
| // interface as well a custom encoding may be provided. | ||||
| type DBusError interface { | ||||
| 	DBusError() (string, []interface{}) | ||||
| } | ||||
|  | ||||
| // SerialGenerator is responsible for serials generation. | ||||
| // | ||||
| // Different approaches for the serial generation can be used, | ||||
| // maintaining a map guarded with a mutex (the standard way) or | ||||
| // simply increment an atomic counter. | ||||
| type SerialGenerator interface { | ||||
| 	GetSerial() uint32 | ||||
| 	RetireSerial(serial uint32) | ||||
| } | ||||
							
								
								
									
										293
									
								
								vendor/github.com/godbus/dbus/v5/sig.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								vendor/github.com/godbus/dbus/v5/sig.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,293 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| var sigToType = map[byte]reflect.Type{ | ||||
| 	'y': byteType, | ||||
| 	'b': boolType, | ||||
| 	'n': int16Type, | ||||
| 	'q': uint16Type, | ||||
| 	'i': int32Type, | ||||
| 	'u': uint32Type, | ||||
| 	'x': int64Type, | ||||
| 	't': uint64Type, | ||||
| 	'd': float64Type, | ||||
| 	's': stringType, | ||||
| 	'g': signatureType, | ||||
| 	'o': objectPathType, | ||||
| 	'v': variantType, | ||||
| 	'h': unixFDIndexType, | ||||
| } | ||||
|  | ||||
| // Signature represents a correct type signature as specified by the D-Bus | ||||
| // specification. The zero value represents the empty signature, "". | ||||
| type Signature struct { | ||||
| 	str string | ||||
| } | ||||
|  | ||||
| // SignatureOf returns the concatenation of all the signatures of the given | ||||
| // values. It panics if one of them is not representable in D-Bus. | ||||
| func SignatureOf(vs ...interface{}) Signature { | ||||
| 	var s string | ||||
| 	for _, v := range vs { | ||||
| 		s += getSignature(reflect.TypeOf(v), &depthCounter{}) | ||||
| 	} | ||||
| 	return Signature{s} | ||||
| } | ||||
|  | ||||
| // SignatureOfType returns the signature of the given type. It panics if the | ||||
| // type is not representable in D-Bus. | ||||
| func SignatureOfType(t reflect.Type) Signature { | ||||
| 	return Signature{getSignature(t, &depthCounter{})} | ||||
| } | ||||
|  | ||||
| // getSignature returns the signature of the given type and panics on unknown types. | ||||
| func getSignature(t reflect.Type, depth *depthCounter) (sig string) { | ||||
| 	if !depth.Valid() { | ||||
| 		panic("container nesting too deep") | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if len(sig) > 255 { | ||||
| 			panic("signature exceeds the length limitation") | ||||
| 		} | ||||
| 	}() | ||||
| 	// handle simple types first | ||||
| 	switch t.Kind() { | ||||
| 	case reflect.Uint8: | ||||
| 		return "y" | ||||
| 	case reflect.Bool: | ||||
| 		return "b" | ||||
| 	case reflect.Int16: | ||||
| 		return "n" | ||||
| 	case reflect.Uint16: | ||||
| 		return "q" | ||||
| 	case reflect.Int, reflect.Int32: | ||||
| 		if t == unixFDType { | ||||
| 			return "h" | ||||
| 		} | ||||
| 		return "i" | ||||
| 	case reflect.Uint, reflect.Uint32: | ||||
| 		if t == unixFDIndexType { | ||||
| 			return "h" | ||||
| 		} | ||||
| 		return "u" | ||||
| 	case reflect.Int64: | ||||
| 		return "x" | ||||
| 	case reflect.Uint64: | ||||
| 		return "t" | ||||
| 	case reflect.Float64: | ||||
| 		return "d" | ||||
| 	case reflect.Ptr: | ||||
| 		return getSignature(t.Elem(), depth) | ||||
| 	case reflect.String: | ||||
| 		if t == objectPathType { | ||||
| 			return "o" | ||||
| 		} | ||||
| 		return "s" | ||||
| 	case reflect.Struct: | ||||
| 		if t == variantType { | ||||
| 			return "v" | ||||
| 		} else if t == signatureType { | ||||
| 			return "g" | ||||
| 		} | ||||
| 		var s string | ||||
| 		for i := 0; i < t.NumField(); i++ { | ||||
| 			field := t.Field(i) | ||||
| 			if field.PkgPath == "" && field.Tag.Get("dbus") != "-" { | ||||
| 				s += getSignature(t.Field(i).Type, depth.EnterStruct()) | ||||
| 			} | ||||
| 		} | ||||
| 		if len(s) == 0 { | ||||
| 			panic(InvalidTypeError{t}) | ||||
| 		} | ||||
| 		return "(" + s + ")" | ||||
| 	case reflect.Array, reflect.Slice: | ||||
| 		return "a" + getSignature(t.Elem(), depth.EnterArray()) | ||||
| 	case reflect.Map: | ||||
| 		if !isKeyType(t.Key()) { | ||||
| 			panic(InvalidTypeError{t}) | ||||
| 		} | ||||
| 		return "a{" + getSignature(t.Key(), depth.EnterArray().EnterDictEntry()) + getSignature(t.Elem(), depth.EnterArray().EnterDictEntry()) + "}" | ||||
| 	case reflect.Interface: | ||||
| 		return "v" | ||||
| 	} | ||||
| 	panic(InvalidTypeError{t}) | ||||
| } | ||||
|  | ||||
| // ParseSignature returns the signature represented by this string, or a | ||||
| // SignatureError if the string is not a valid signature. | ||||
| func ParseSignature(s string) (sig Signature, err error) { | ||||
| 	if len(s) == 0 { | ||||
| 		return | ||||
| 	} | ||||
| 	if len(s) > 255 { | ||||
| 		return Signature{""}, SignatureError{s, "too long"} | ||||
| 	} | ||||
| 	sig.str = s | ||||
| 	for err == nil && len(s) != 0 { | ||||
| 		err, s = validSingle(s, &depthCounter{}) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		sig = Signature{""} | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // ParseSignatureMust behaves like ParseSignature, except that it panics if s | ||||
| // is not valid. | ||||
| func ParseSignatureMust(s string) Signature { | ||||
| 	sig, err := ParseSignature(s) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return sig | ||||
| } | ||||
|  | ||||
| // Empty returns whether the signature is the empty signature. | ||||
| func (s Signature) Empty() bool { | ||||
| 	return s.str == "" | ||||
| } | ||||
|  | ||||
| // Single returns whether the signature represents a single, complete type. | ||||
| func (s Signature) Single() bool { | ||||
| 	err, r := validSingle(s.str, &depthCounter{}) | ||||
| 	return err != nil && r == "" | ||||
| } | ||||
|  | ||||
| // String returns the signature's string representation. | ||||
| func (s Signature) String() string { | ||||
| 	return s.str | ||||
| } | ||||
|  | ||||
| // A SignatureError indicates that a signature passed to a function or received | ||||
| // on a connection is not a valid signature. | ||||
| type SignatureError struct { | ||||
| 	Sig    string | ||||
| 	Reason string | ||||
| } | ||||
|  | ||||
| func (e SignatureError) Error() string { | ||||
| 	return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason) | ||||
| } | ||||
|  | ||||
| type depthCounter struct { | ||||
| 	arrayDepth, structDepth, dictEntryDepth int | ||||
| } | ||||
|  | ||||
| func (cnt *depthCounter) Valid() bool { | ||||
| 	return cnt.arrayDepth <= 32 && cnt.structDepth <= 32 && cnt.dictEntryDepth <= 32 | ||||
| } | ||||
|  | ||||
| func (cnt depthCounter) EnterArray() *depthCounter { | ||||
| 	cnt.arrayDepth++ | ||||
| 	return &cnt | ||||
| } | ||||
|  | ||||
| func (cnt depthCounter) EnterStruct() *depthCounter { | ||||
| 	cnt.structDepth++ | ||||
| 	return &cnt | ||||
| } | ||||
|  | ||||
| func (cnt depthCounter) EnterDictEntry() *depthCounter { | ||||
| 	cnt.dictEntryDepth++ | ||||
| 	return &cnt | ||||
| } | ||||
|  | ||||
| // Try to read a single type from this string. If it was successful, err is nil | ||||
| // and rem is the remaining unparsed part. Otherwise, err is a non-nil | ||||
| // SignatureError and rem is "". depth is the current recursion depth which may | ||||
| // not be greater than 64 and should be given as 0 on the first call. | ||||
| func validSingle(s string, depth *depthCounter) (err error, rem string) { | ||||
| 	if s == "" { | ||||
| 		return SignatureError{Sig: s, Reason: "empty signature"}, "" | ||||
| 	} | ||||
| 	if !depth.Valid() { | ||||
| 		return SignatureError{Sig: s, Reason: "container nesting too deep"}, "" | ||||
| 	} | ||||
| 	switch s[0] { | ||||
| 	case 'y', 'b', 'n', 'q', 'i', 'u', 'x', 't', 'd', 's', 'g', 'o', 'v', 'h': | ||||
| 		return nil, s[1:] | ||||
| 	case 'a': | ||||
| 		if len(s) > 1 && s[1] == '{' { | ||||
| 			i := findMatching(s[1:], '{', '}') | ||||
| 			if i == -1 { | ||||
| 				return SignatureError{Sig: s, Reason: "unmatched '{'"}, "" | ||||
| 			} | ||||
| 			i++ | ||||
| 			rem = s[i+1:] | ||||
| 			s = s[2:i] | ||||
| 			if err, _ = validSingle(s[:1], depth.EnterArray().EnterDictEntry()); err != nil { | ||||
| 				return err, "" | ||||
| 			} | ||||
| 			err, nr := validSingle(s[1:], depth.EnterArray().EnterDictEntry()) | ||||
| 			if err != nil { | ||||
| 				return err, "" | ||||
| 			} | ||||
| 			if nr != "" { | ||||
| 				return SignatureError{Sig: s, Reason: "too many types in dict"}, "" | ||||
| 			} | ||||
| 			return nil, rem | ||||
| 		} | ||||
| 		return validSingle(s[1:], depth.EnterArray()) | ||||
| 	case '(': | ||||
| 		i := findMatching(s, '(', ')') | ||||
| 		if i == -1 { | ||||
| 			return SignatureError{Sig: s, Reason: "unmatched ')'"}, "" | ||||
| 		} | ||||
| 		rem = s[i+1:] | ||||
| 		s = s[1:i] | ||||
| 		for err == nil && s != "" { | ||||
| 			err, s = validSingle(s, depth.EnterStruct()) | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			rem = "" | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	return SignatureError{Sig: s, Reason: "invalid type character"}, "" | ||||
| } | ||||
|  | ||||
| func findMatching(s string, left, right rune) int { | ||||
| 	n := 0 | ||||
| 	for i, v := range s { | ||||
| 		if v == left { | ||||
| 			n++ | ||||
| 		} else if v == right { | ||||
| 			n-- | ||||
| 		} | ||||
| 		if n == 0 { | ||||
| 			return i | ||||
| 		} | ||||
| 	} | ||||
| 	return -1 | ||||
| } | ||||
|  | ||||
| // typeFor returns the type of the given signature. It ignores any left over | ||||
| // characters and panics if s doesn't start with a valid type signature. | ||||
| func typeFor(s string) (t reflect.Type) { | ||||
| 	err, _ := validSingle(s, &depthCounter{}) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
|  | ||||
| 	if t, ok := sigToType[s[0]]; ok { | ||||
| 		return t | ||||
| 	} | ||||
| 	switch s[0] { | ||||
| 	case 'a': | ||||
| 		if s[1] == '{' { | ||||
| 			i := strings.LastIndex(s, "}") | ||||
| 			t = reflect.MapOf(sigToType[s[2]], typeFor(s[3:i])) | ||||
| 		} else { | ||||
| 			t = reflect.SliceOf(typeFor(s[1:])) | ||||
| 		} | ||||
| 	case '(': | ||||
| 		t = interfacesType | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										6
									
								
								vendor/github.com/godbus/dbus/v5/transport_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/godbus/dbus/v5/transport_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| package dbus | ||||
|  | ||||
| func (t *unixTransport) SendNullByte() error { | ||||
| 	_, err := t.Write([]byte{0}) | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										52
									
								
								vendor/github.com/godbus/dbus/v5/transport_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/godbus/dbus/v5/transport_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| var nativeEndian binary.ByteOrder | ||||
|  | ||||
| func detectEndianness() binary.ByteOrder { | ||||
| 	var x uint32 = 0x01020304 | ||||
| 	if *(*byte)(unsafe.Pointer(&x)) == 0x01 { | ||||
| 		return binary.BigEndian | ||||
| 	} | ||||
| 	return binary.LittleEndian | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	nativeEndian = detectEndianness() | ||||
| } | ||||
|  | ||||
| type genericTransport struct { | ||||
| 	io.ReadWriteCloser | ||||
| } | ||||
|  | ||||
| func (t genericTransport) SendNullByte() error { | ||||
| 	_, err := t.Write([]byte{0}) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (t genericTransport) SupportsUnixFDs() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (t genericTransport) EnableUnixFDs() {} | ||||
|  | ||||
| func (t genericTransport) ReadMessage() (*Message, error) { | ||||
| 	return DecodeMessage(t) | ||||
| } | ||||
|  | ||||
| func (t genericTransport) SendMessage(msg *Message) error { | ||||
| 	fds, err := msg.CountFds() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if fds != 0 { | ||||
| 		return errors.New("dbus: unix fd passing not enabled") | ||||
| 	} | ||||
| 	return msg.EncodeTo(t, nativeEndian) | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| //+build !windows | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	transports["nonce-tcp"] = newNonceTcpTransport | ||||
| } | ||||
|  | ||||
| func newNonceTcpTransport(keys string) (transport, error) { | ||||
| 	host := getKey(keys, "host") | ||||
| 	port := getKey(keys, "port") | ||||
| 	noncefile := getKey(keys, "noncefile") | ||||
| 	if host == "" || port == "" || noncefile == "" { | ||||
| 		return nil, errors.New("dbus: unsupported address (must set host, port and noncefile)") | ||||
| 	} | ||||
| 	protocol, err := tcpFamily(keys) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	socket, err := net.Dial(protocol, net.JoinHostPort(host, port)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	b, err := ioutil.ReadFile(noncefile) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	_, err = socket.Write(b) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return NewConn(socket) | ||||
| } | ||||
							
								
								
									
										41
									
								
								vendor/github.com/godbus/dbus/v5/transport_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/godbus/dbus/v5/transport_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	transports["tcp"] = newTcpTransport | ||||
| } | ||||
|  | ||||
| func tcpFamily(keys string) (string, error) { | ||||
| 	switch getKey(keys, "family") { | ||||
| 	case "": | ||||
| 		return "tcp", nil | ||||
| 	case "ipv4": | ||||
| 		return "tcp4", nil | ||||
| 	case "ipv6": | ||||
| 		return "tcp6", nil | ||||
| 	default: | ||||
| 		return "", errors.New("dbus: invalid tcp family (must be ipv4 or ipv6)") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newTcpTransport(keys string) (transport, error) { | ||||
| 	host := getKey(keys, "host") | ||||
| 	port := getKey(keys, "port") | ||||
| 	if host == "" || port == "" { | ||||
| 		return nil, errors.New("dbus: unsupported address (must set host and port)") | ||||
| 	} | ||||
|  | ||||
| 	protocol, err := tcpFamily(keys) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	socket, err := net.Dial(protocol, net.JoinHostPort(host, port)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return NewConn(socket) | ||||
| } | ||||
							
								
								
									
										212
									
								
								vendor/github.com/godbus/dbus/v5/transport_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								vendor/github.com/godbus/dbus/v5/transport_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,212 @@ | ||||
| //+build !windows,!solaris | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| type oobReader struct { | ||||
| 	conn *net.UnixConn | ||||
| 	oob  []byte | ||||
| 	buf  [4096]byte | ||||
| } | ||||
|  | ||||
| func (o *oobReader) Read(b []byte) (n int, err error) { | ||||
| 	n, oobn, flags, _, err := o.conn.ReadMsgUnix(b, o.buf[:]) | ||||
| 	if err != nil { | ||||
| 		return n, err | ||||
| 	} | ||||
| 	if flags&syscall.MSG_CTRUNC != 0 { | ||||
| 		return n, errors.New("dbus: control data truncated (too many fds received)") | ||||
| 	} | ||||
| 	o.oob = append(o.oob, o.buf[:oobn]...) | ||||
| 	return n, nil | ||||
| } | ||||
|  | ||||
| type unixTransport struct { | ||||
| 	*net.UnixConn | ||||
| 	rdr        *oobReader | ||||
| 	hasUnixFDs bool | ||||
| } | ||||
|  | ||||
| func newUnixTransport(keys string) (transport, error) { | ||||
| 	var err error | ||||
|  | ||||
| 	t := new(unixTransport) | ||||
| 	abstract := getKey(keys, "abstract") | ||||
| 	path := getKey(keys, "path") | ||||
| 	switch { | ||||
| 	case abstract == "" && path == "": | ||||
| 		return nil, errors.New("dbus: invalid address (neither path nor abstract set)") | ||||
| 	case abstract != "" && path == "": | ||||
| 		t.UnixConn, err = net.DialUnix("unix", nil, &net.UnixAddr{Name: "@" + abstract, Net: "unix"}) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return t, nil | ||||
| 	case abstract == "" && path != "": | ||||
| 		t.UnixConn, err = net.DialUnix("unix", nil, &net.UnixAddr{Name: path, Net: "unix"}) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return t, nil | ||||
| 	default: | ||||
| 		return nil, errors.New("dbus: invalid address (both path and abstract set)") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	transports["unix"] = newUnixTransport | ||||
| } | ||||
|  | ||||
| func (t *unixTransport) EnableUnixFDs() { | ||||
| 	t.hasUnixFDs = true | ||||
| } | ||||
|  | ||||
| func (t *unixTransport) ReadMessage() (*Message, error) { | ||||
| 	var ( | ||||
| 		blen, hlen uint32 | ||||
| 		csheader   [16]byte | ||||
| 		headers    []header | ||||
| 		order      binary.ByteOrder | ||||
| 		unixfds    uint32 | ||||
| 	) | ||||
| 	// To be sure that all bytes of out-of-band data are read, we use a special | ||||
| 	// reader that uses ReadUnix on the underlying connection instead of Read | ||||
| 	// and gathers the out-of-band data in a buffer. | ||||
| 	if t.rdr == nil { | ||||
| 		t.rdr = &oobReader{conn: t.UnixConn} | ||||
| 	} else { | ||||
| 		t.rdr.oob = nil | ||||
| 	} | ||||
|  | ||||
| 	// read the first 16 bytes (the part of the header that has a constant size), | ||||
| 	// from which we can figure out the length of the rest of the message | ||||
| 	if _, err := io.ReadFull(t.rdr, csheader[:]); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	switch csheader[0] { | ||||
| 	case 'l': | ||||
| 		order = binary.LittleEndian | ||||
| 	case 'B': | ||||
| 		order = binary.BigEndian | ||||
| 	default: | ||||
| 		return nil, InvalidMessageError("invalid byte order") | ||||
| 	} | ||||
| 	// csheader[4:8] -> length of message body, csheader[12:16] -> length of | ||||
| 	// header fields (without alignment) | ||||
| 	binary.Read(bytes.NewBuffer(csheader[4:8]), order, &blen) | ||||
| 	binary.Read(bytes.NewBuffer(csheader[12:]), order, &hlen) | ||||
| 	if hlen%8 != 0 { | ||||
| 		hlen += 8 - (hlen % 8) | ||||
| 	} | ||||
|  | ||||
| 	// decode headers and look for unix fds | ||||
| 	headerdata := make([]byte, hlen+4) | ||||
| 	copy(headerdata, csheader[12:]) | ||||
| 	if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	dec := newDecoder(bytes.NewBuffer(headerdata), order, make([]int, 0)) | ||||
| 	dec.pos = 12 | ||||
| 	vs, err := dec.Decode(Signature{"a(yv)"}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	Store(vs, &headers) | ||||
| 	for _, v := range headers { | ||||
| 		if v.Field == byte(FieldUnixFDs) { | ||||
| 			unixfds, _ = v.Variant.value.(uint32) | ||||
| 		} | ||||
| 	} | ||||
| 	all := make([]byte, 16+hlen+blen) | ||||
| 	copy(all, csheader[:]) | ||||
| 	copy(all[16:], headerdata[4:]) | ||||
| 	if _, err := io.ReadFull(t.rdr, all[16+hlen:]); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if unixfds != 0 { | ||||
| 		if !t.hasUnixFDs { | ||||
| 			return nil, errors.New("dbus: got unix fds on unsupported transport") | ||||
| 		} | ||||
| 		// read the fds from the OOB data | ||||
| 		scms, err := syscall.ParseSocketControlMessage(t.rdr.oob) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if len(scms) != 1 { | ||||
| 			return nil, errors.New("dbus: received more than one socket control message") | ||||
| 		} | ||||
| 		fds, err := syscall.ParseUnixRights(&scms[0]) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		msg, err := DecodeMessageWithFDs(bytes.NewBuffer(all), fds) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		// substitute the values in the message body (which are indices for the | ||||
| 		// array receiver via OOB) with the actual values | ||||
| 		for i, v := range msg.Body { | ||||
| 			switch index := v.(type) { | ||||
| 			case UnixFDIndex: | ||||
| 				if uint32(index) >= unixfds { | ||||
| 					return nil, InvalidMessageError("invalid index for unix fd") | ||||
| 				} | ||||
| 				msg.Body[i] = UnixFD(fds[index]) | ||||
| 			case []UnixFDIndex: | ||||
| 				fdArray := make([]UnixFD, len(index)) | ||||
| 				for k, j := range index { | ||||
| 					if uint32(j) >= unixfds { | ||||
| 						return nil, InvalidMessageError("invalid index for unix fd") | ||||
| 					} | ||||
| 					fdArray[k] = UnixFD(fds[j]) | ||||
| 				} | ||||
| 				msg.Body[i] = fdArray | ||||
| 			} | ||||
| 		} | ||||
| 		return msg, nil | ||||
| 	} | ||||
| 	return DecodeMessage(bytes.NewBuffer(all)) | ||||
| } | ||||
|  | ||||
| func (t *unixTransport) SendMessage(msg *Message) error { | ||||
| 	fdcnt, err := msg.CountFds() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if fdcnt != 0 { | ||||
| 		if !t.hasUnixFDs { | ||||
| 			return errors.New("dbus: unix fd passing not enabled") | ||||
| 		} | ||||
| 		msg.Headers[FieldUnixFDs] = MakeVariant(uint32(fdcnt)) | ||||
| 		buf := new(bytes.Buffer) | ||||
| 		fds, err := msg.EncodeToWithFDs(buf, nativeEndian) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		oob := syscall.UnixRights(fds...) | ||||
| 		n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if n != buf.Len() || oobn != len(oob) { | ||||
| 			return io.ErrShortWrite | ||||
| 		} | ||||
| 	} else { | ||||
| 		if err := msg.EncodeTo(t, nativeEndian); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (t *unixTransport) SupportsUnixFDs() bool { | ||||
| 	return true | ||||
| } | ||||
							
								
								
									
										95
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_dragonfly.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_dragonfly.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| // The UnixCredentials system call is currently only implemented on Linux | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_linux.go | ||||
| // https://golang.org/s/go1.4-syscall | ||||
| // http://code.google.com/p/go/source/browse/unix/sockcmsg_linux.go?repo=sys | ||||
|  | ||||
| // Local implementation of the UnixCredentials system call for DragonFly BSD | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| /* | ||||
| #include <sys/ucred.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/ztypes_linux_amd64.go | ||||
| // http://golang.org/src/pkg/syscall/ztypes_dragonfly_amd64.go | ||||
| type Ucred struct { | ||||
| 	Pid int32 | ||||
| 	Uid uint32 | ||||
| 	Gid uint32 | ||||
| } | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/types_linux.go | ||||
| // http://golang.org/src/pkg/syscall/types_dragonfly.go | ||||
| // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/ucred.h | ||||
| const ( | ||||
| 	SizeofUcred = C.sizeof_struct_ucred | ||||
| ) | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_unix.go | ||||
| func cmsgAlignOf(salen int) int { | ||||
| 	// From http://golang.org/src/pkg/syscall/sockcmsg_unix.go | ||||
| 	//salign := sizeofPtr | ||||
| 	// NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels | ||||
| 	// still require 32-bit aligned access to network subsystem. | ||||
| 	//if darwin64Bit || dragonfly64Bit { | ||||
| 	//	salign = 4 | ||||
| 	//} | ||||
| 	salign := 4 | ||||
| 	return (salen + salign - 1) & ^(salign - 1) | ||||
| } | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_unix.go | ||||
| func cmsgData(h *syscall.Cmsghdr) unsafe.Pointer { | ||||
| 	return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(syscall.SizeofCmsghdr))) | ||||
| } | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_linux.go | ||||
| // UnixCredentials encodes credentials into a socket control message | ||||
| // for sending to another process. This can be used for | ||||
| // authentication. | ||||
| func UnixCredentials(ucred *Ucred) []byte { | ||||
| 	b := make([]byte, syscall.CmsgSpace(SizeofUcred)) | ||||
| 	h := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0])) | ||||
| 	h.Level = syscall.SOL_SOCKET | ||||
| 	h.Type = syscall.SCM_CREDS | ||||
| 	h.SetLen(syscall.CmsgLen(SizeofUcred)) | ||||
| 	*((*Ucred)(cmsgData(h))) = *ucred | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_linux.go | ||||
| // ParseUnixCredentials decodes a socket control message that contains | ||||
| // credentials in a Ucred structure. To receive such a message, the | ||||
| // SO_PASSCRED option must be enabled on the socket. | ||||
| func ParseUnixCredentials(m *syscall.SocketControlMessage) (*Ucred, error) { | ||||
| 	if m.Header.Level != syscall.SOL_SOCKET { | ||||
| 		return nil, syscall.EINVAL | ||||
| 	} | ||||
| 	if m.Header.Type != syscall.SCM_CREDS { | ||||
| 		return nil, syscall.EINVAL | ||||
| 	} | ||||
| 	ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0])) | ||||
| 	return &ucred, nil | ||||
| } | ||||
|  | ||||
| func (t *unixTransport) SendNullByte() error { | ||||
| 	ucred := &Ucred{Pid: int32(os.Getpid()), Uid: uint32(os.Getuid()), Gid: uint32(os.Getgid())} | ||||
| 	b := UnixCredentials(ucred) | ||||
| 	_, oobn, err := t.UnixConn.WriteMsgUnix([]byte{0}, b, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if oobn != len(b) { | ||||
| 		return io.ErrShortWrite | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										92
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_freebsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_freebsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| // The UnixCredentials system call is currently only implemented on Linux | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_linux.go | ||||
| // https://golang.org/s/go1.4-syscall | ||||
| // http://code.google.com/p/go/source/browse/unix/sockcmsg_linux.go?repo=sys | ||||
|  | ||||
| // Local implementation of the UnixCredentials system call for FreeBSD | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| /* | ||||
| const int sizeofPtr = sizeof(void*); | ||||
| #define _WANT_UCRED | ||||
| #include <sys/types.h> | ||||
| #include <sys/ucred.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/ztypes_linux_amd64.go | ||||
| // https://golang.org/src/syscall/ztypes_freebsd_amd64.go | ||||
| type Ucred struct { | ||||
| 	Pid int32 | ||||
| 	Uid uint32 | ||||
| 	Gid uint32 | ||||
| } | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/types_linux.go | ||||
| // https://golang.org/src/syscall/types_freebsd.go | ||||
| // https://github.com/freebsd/freebsd/blob/master/sys/sys/ucred.h | ||||
| const ( | ||||
| 	SizeofUcred = C.sizeof_struct_ucred | ||||
| ) | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_unix.go | ||||
| func cmsgAlignOf(salen int) int { | ||||
| 	salign := C.sizeofPtr | ||||
|  | ||||
| 	return (salen + salign - 1) & ^(salign - 1) | ||||
| } | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_unix.go | ||||
| func cmsgData(h *syscall.Cmsghdr) unsafe.Pointer { | ||||
| 	return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(syscall.SizeofCmsghdr))) | ||||
| } | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_linux.go | ||||
| // UnixCredentials encodes credentials into a socket control message | ||||
| // for sending to another process. This can be used for | ||||
| // authentication. | ||||
| func UnixCredentials(ucred *Ucred) []byte { | ||||
| 	b := make([]byte, syscall.CmsgSpace(SizeofUcred)) | ||||
| 	h := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0])) | ||||
| 	h.Level = syscall.SOL_SOCKET | ||||
| 	h.Type = syscall.SCM_CREDS | ||||
| 	h.SetLen(syscall.CmsgLen(SizeofUcred)) | ||||
| 	*((*Ucred)(cmsgData(h))) = *ucred | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_linux.go | ||||
| // ParseUnixCredentials decodes a socket control message that contains | ||||
| // credentials in a Ucred structure. To receive such a message, the | ||||
| // SO_PASSCRED option must be enabled on the socket. | ||||
| func ParseUnixCredentials(m *syscall.SocketControlMessage) (*Ucred, error) { | ||||
| 	if m.Header.Level != syscall.SOL_SOCKET { | ||||
| 		return nil, syscall.EINVAL | ||||
| 	} | ||||
| 	if m.Header.Type != syscall.SCM_CREDS { | ||||
| 		return nil, syscall.EINVAL | ||||
| 	} | ||||
| 	ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0])) | ||||
| 	return &ucred, nil | ||||
| } | ||||
|  | ||||
| func (t *unixTransport) SendNullByte() error { | ||||
| 	ucred := &Ucred{Pid: int32(os.Getpid()), Uid: uint32(os.Getuid()), Gid: uint32(os.Getgid())} | ||||
| 	b := UnixCredentials(ucred) | ||||
| 	_, oobn, err := t.UnixConn.WriteMsgUnix([]byte{0}, b, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if oobn != len(b) { | ||||
| 		return io.ErrShortWrite | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| // The UnixCredentials system call is currently only implemented on Linux | ||||
| // http://golang.org/src/pkg/syscall/sockcmsg_linux.go | ||||
| // https://golang.org/s/go1.4-syscall | ||||
| // http://code.google.com/p/go/source/browse/unix/sockcmsg_linux.go?repo=sys | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| func (t *unixTransport) SendNullByte() error { | ||||
| 	ucred := &syscall.Ucred{Pid: int32(os.Getpid()), Uid: uint32(os.Getuid()), Gid: uint32(os.Getgid())} | ||||
| 	b := syscall.UnixCredentials(ucred) | ||||
| 	_, oobn, err := t.UnixConn.WriteMsgUnix([]byte{0}, b, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if oobn != len(b) { | ||||
| 		return io.ErrShortWrite | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										14
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| package dbus | ||||
|  | ||||
| import "io" | ||||
|  | ||||
| func (t *unixTransport) SendNullByte() error { | ||||
| 	n, _, err := t.UnixConn.WriteMsgUnix([]byte{0}, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if n != 1 { | ||||
| 		return io.ErrShortWrite | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										14
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_openbsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_openbsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| package dbus | ||||
|  | ||||
| import "io" | ||||
|  | ||||
| func (t *unixTransport) SendNullByte() error { | ||||
| 	n, _, err := t.UnixConn.WriteMsgUnix([]byte{0}, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if n != 1 { | ||||
| 		return io.ErrShortWrite | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										6
									
								
								vendor/github.com/godbus/dbus/v5/transport_zos.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/godbus/dbus/v5/transport_zos.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| package dbus | ||||
|  | ||||
| func (t *unixTransport) SendNullByte() error { | ||||
| 	_, err := t.Write([]byte{0}) | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										150
									
								
								vendor/github.com/godbus/dbus/v5/variant.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								vendor/github.com/godbus/dbus/v5/variant.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| ) | ||||
|  | ||||
| // Variant represents the D-Bus variant type. | ||||
| type Variant struct { | ||||
| 	sig   Signature | ||||
| 	value interface{} | ||||
| } | ||||
|  | ||||
| // MakeVariant converts the given value to a Variant. It panics if v cannot be | ||||
| // represented as a D-Bus type. | ||||
| func MakeVariant(v interface{}) Variant { | ||||
| 	return MakeVariantWithSignature(v, SignatureOf(v)) | ||||
| } | ||||
|  | ||||
| // MakeVariantWithSignature converts the given value to a Variant. | ||||
| func MakeVariantWithSignature(v interface{}, s Signature) Variant { | ||||
| 	return Variant{s, v} | ||||
| } | ||||
|  | ||||
| // ParseVariant parses the given string as a variant as described at | ||||
| // https://developer.gnome.org/glib/stable/gvariant-text.html. If sig is not | ||||
| // empty, it is taken to be the expected signature for the variant. | ||||
| func ParseVariant(s string, sig Signature) (Variant, error) { | ||||
| 	tokens := varLex(s) | ||||
| 	p := &varParser{tokens: tokens} | ||||
| 	n, err := varMakeNode(p) | ||||
| 	if err != nil { | ||||
| 		return Variant{}, err | ||||
| 	} | ||||
| 	if sig.str == "" { | ||||
| 		sig, err = varInfer(n) | ||||
| 		if err != nil { | ||||
| 			return Variant{}, err | ||||
| 		} | ||||
| 	} | ||||
| 	v, err := n.Value(sig) | ||||
| 	if err != nil { | ||||
| 		return Variant{}, err | ||||
| 	} | ||||
| 	return MakeVariant(v), nil | ||||
| } | ||||
|  | ||||
| // format returns a formatted version of v and whether this string can be parsed | ||||
| // unambiguously. | ||||
| func (v Variant) format() (string, bool) { | ||||
| 	switch v.sig.str[0] { | ||||
| 	case 'b', 'i': | ||||
| 		return fmt.Sprint(v.value), true | ||||
| 	case 'n', 'q', 'u', 'x', 't', 'd', 'h': | ||||
| 		return fmt.Sprint(v.value), false | ||||
| 	case 's': | ||||
| 		return strconv.Quote(v.value.(string)), true | ||||
| 	case 'o': | ||||
| 		return strconv.Quote(string(v.value.(ObjectPath))), false | ||||
| 	case 'g': | ||||
| 		return strconv.Quote(v.value.(Signature).str), false | ||||
| 	case 'v': | ||||
| 		s, unamb := v.value.(Variant).format() | ||||
| 		if !unamb { | ||||
| 			return "<@" + v.value.(Variant).sig.str + " " + s + ">", true | ||||
| 		} | ||||
| 		return "<" + s + ">", true | ||||
| 	case 'y': | ||||
| 		return fmt.Sprintf("%#x", v.value.(byte)), false | ||||
| 	} | ||||
| 	rv := reflect.ValueOf(v.value) | ||||
| 	switch rv.Kind() { | ||||
| 	case reflect.Slice: | ||||
| 		if rv.Len() == 0 { | ||||
| 			return "[]", false | ||||
| 		} | ||||
| 		unamb := true | ||||
| 		buf := bytes.NewBuffer([]byte("[")) | ||||
| 		for i := 0; i < rv.Len(); i++ { | ||||
| 			// TODO: slooow | ||||
| 			s, b := MakeVariant(rv.Index(i).Interface()).format() | ||||
| 			unamb = unamb && b | ||||
| 			buf.WriteString(s) | ||||
| 			if i != rv.Len()-1 { | ||||
| 				buf.WriteString(", ") | ||||
| 			} | ||||
| 		} | ||||
| 		buf.WriteByte(']') | ||||
| 		return buf.String(), unamb | ||||
| 	case reflect.Map: | ||||
| 		if rv.Len() == 0 { | ||||
| 			return "{}", false | ||||
| 		} | ||||
| 		unamb := true | ||||
| 		var buf bytes.Buffer | ||||
| 		kvs := make([]string, rv.Len()) | ||||
| 		for i, k := range rv.MapKeys() { | ||||
| 			s, b := MakeVariant(k.Interface()).format() | ||||
| 			unamb = unamb && b | ||||
| 			buf.Reset() | ||||
| 			buf.WriteString(s) | ||||
| 			buf.WriteString(": ") | ||||
| 			s, b = MakeVariant(rv.MapIndex(k).Interface()).format() | ||||
| 			unamb = unamb && b | ||||
| 			buf.WriteString(s) | ||||
| 			kvs[i] = buf.String() | ||||
| 		} | ||||
| 		buf.Reset() | ||||
| 		buf.WriteByte('{') | ||||
| 		sort.Strings(kvs) | ||||
| 		for i, kv := range kvs { | ||||
| 			if i > 0 { | ||||
| 				buf.WriteString(", ") | ||||
| 			} | ||||
| 			buf.WriteString(kv) | ||||
| 		} | ||||
| 		buf.WriteByte('}') | ||||
| 		return buf.String(), unamb | ||||
| 	} | ||||
| 	return `"INVALID"`, true | ||||
| } | ||||
|  | ||||
| // Signature returns the D-Bus signature of the underlying value of v. | ||||
| func (v Variant) Signature() Signature { | ||||
| 	return v.sig | ||||
| } | ||||
|  | ||||
| // String returns the string representation of the underlying value of v as | ||||
| // described at https://developer.gnome.org/glib/stable/gvariant-text.html. | ||||
| func (v Variant) String() string { | ||||
| 	s, unamb := v.format() | ||||
| 	if !unamb { | ||||
| 		return "@" + v.sig.str + " " + s | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| // Value returns the underlying value of v. | ||||
| func (v Variant) Value() interface{} { | ||||
| 	return v.value | ||||
| } | ||||
|  | ||||
| // Store converts the variant into a native go type using the same | ||||
| // mechanism as the "Store" function. | ||||
| func (v Variant) Store(value interface{}) error { | ||||
| 	return storeInterfaces(v.value, value) | ||||
| } | ||||
							
								
								
									
										284
									
								
								vendor/github.com/godbus/dbus/v5/variant_lexer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								vendor/github.com/godbus/dbus/v5/variant_lexer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,284 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"unicode" | ||||
| 	"unicode/utf8" | ||||
| ) | ||||
|  | ||||
| // Heavily inspired by the lexer from text/template. | ||||
|  | ||||
| type varToken struct { | ||||
| 	typ varTokenType | ||||
| 	val string | ||||
| } | ||||
|  | ||||
| type varTokenType byte | ||||
|  | ||||
| const ( | ||||
| 	tokEOF varTokenType = iota | ||||
| 	tokError | ||||
| 	tokNumber | ||||
| 	tokString | ||||
| 	tokBool | ||||
| 	tokArrayStart | ||||
| 	tokArrayEnd | ||||
| 	tokDictStart | ||||
| 	tokDictEnd | ||||
| 	tokVariantStart | ||||
| 	tokVariantEnd | ||||
| 	tokComma | ||||
| 	tokColon | ||||
| 	tokType | ||||
| 	tokByteString | ||||
| ) | ||||
|  | ||||
| type varLexer struct { | ||||
| 	input  string | ||||
| 	start  int | ||||
| 	pos    int | ||||
| 	width  int | ||||
| 	tokens []varToken | ||||
| } | ||||
|  | ||||
| type lexState func(*varLexer) lexState | ||||
|  | ||||
| func varLex(s string) []varToken { | ||||
| 	l := &varLexer{input: s} | ||||
| 	l.run() | ||||
| 	return l.tokens | ||||
| } | ||||
|  | ||||
| func (l *varLexer) accept(valid string) bool { | ||||
| 	if strings.ContainsRune(valid, l.next()) { | ||||
| 		return true | ||||
| 	} | ||||
| 	l.backup() | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (l *varLexer) backup() { | ||||
| 	l.pos -= l.width | ||||
| } | ||||
|  | ||||
| func (l *varLexer) emit(t varTokenType) { | ||||
| 	l.tokens = append(l.tokens, varToken{t, l.input[l.start:l.pos]}) | ||||
| 	l.start = l.pos | ||||
| } | ||||
|  | ||||
| func (l *varLexer) errorf(format string, v ...interface{}) lexState { | ||||
| 	l.tokens = append(l.tokens, varToken{ | ||||
| 		tokError, | ||||
| 		fmt.Sprintf(format, v...), | ||||
| 	}) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (l *varLexer) ignore() { | ||||
| 	l.start = l.pos | ||||
| } | ||||
|  | ||||
| func (l *varLexer) next() rune { | ||||
| 	var r rune | ||||
|  | ||||
| 	if l.pos >= len(l.input) { | ||||
| 		l.width = 0 | ||||
| 		return -1 | ||||
| 	} | ||||
| 	r, l.width = utf8.DecodeRuneInString(l.input[l.pos:]) | ||||
| 	l.pos += l.width | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| func (l *varLexer) run() { | ||||
| 	for state := varLexNormal; state != nil; { | ||||
| 		state = state(l) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *varLexer) peek() rune { | ||||
| 	r := l.next() | ||||
| 	l.backup() | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| func varLexNormal(l *varLexer) lexState { | ||||
| 	for { | ||||
| 		r := l.next() | ||||
| 		switch { | ||||
| 		case r == -1: | ||||
| 			l.emit(tokEOF) | ||||
| 			return nil | ||||
| 		case r == '[': | ||||
| 			l.emit(tokArrayStart) | ||||
| 		case r == ']': | ||||
| 			l.emit(tokArrayEnd) | ||||
| 		case r == '{': | ||||
| 			l.emit(tokDictStart) | ||||
| 		case r == '}': | ||||
| 			l.emit(tokDictEnd) | ||||
| 		case r == '<': | ||||
| 			l.emit(tokVariantStart) | ||||
| 		case r == '>': | ||||
| 			l.emit(tokVariantEnd) | ||||
| 		case r == ':': | ||||
| 			l.emit(tokColon) | ||||
| 		case r == ',': | ||||
| 			l.emit(tokComma) | ||||
| 		case r == '\'' || r == '"': | ||||
| 			l.backup() | ||||
| 			return varLexString | ||||
| 		case r == '@': | ||||
| 			l.backup() | ||||
| 			return varLexType | ||||
| 		case unicode.IsSpace(r): | ||||
| 			l.ignore() | ||||
| 		case unicode.IsNumber(r) || r == '+' || r == '-': | ||||
| 			l.backup() | ||||
| 			return varLexNumber | ||||
| 		case r == 'b': | ||||
| 			pos := l.start | ||||
| 			if n := l.peek(); n == '"' || n == '\'' { | ||||
| 				return varLexByteString | ||||
| 			} | ||||
| 			// not a byte string; try to parse it as a type or bool below | ||||
| 			l.pos = pos + 1 | ||||
| 			l.width = 1 | ||||
| 			fallthrough | ||||
| 		default: | ||||
| 			// either a bool or a type. Try bools first. | ||||
| 			l.backup() | ||||
| 			if l.pos+4 <= len(l.input) { | ||||
| 				if l.input[l.pos:l.pos+4] == "true" { | ||||
| 					l.pos += 4 | ||||
| 					l.emit(tokBool) | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			if l.pos+5 <= len(l.input) { | ||||
| 				if l.input[l.pos:l.pos+5] == "false" { | ||||
| 					l.pos += 5 | ||||
| 					l.emit(tokBool) | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			// must be a type. | ||||
| 			return varLexType | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| var varTypeMap = map[string]string{ | ||||
| 	"boolean":    "b", | ||||
| 	"byte":       "y", | ||||
| 	"int16":      "n", | ||||
| 	"uint16":     "q", | ||||
| 	"int32":      "i", | ||||
| 	"uint32":     "u", | ||||
| 	"int64":      "x", | ||||
| 	"uint64":     "t", | ||||
| 	"double":     "f", | ||||
| 	"string":     "s", | ||||
| 	"objectpath": "o", | ||||
| 	"signature":  "g", | ||||
| } | ||||
|  | ||||
| func varLexByteString(l *varLexer) lexState { | ||||
| 	q := l.next() | ||||
| Loop: | ||||
| 	for { | ||||
| 		switch l.next() { | ||||
| 		case '\\': | ||||
| 			if r := l.next(); r != -1 { | ||||
| 				break | ||||
| 			} | ||||
| 			fallthrough | ||||
| 		case -1: | ||||
| 			return l.errorf("unterminated bytestring") | ||||
| 		case q: | ||||
| 			break Loop | ||||
| 		} | ||||
| 	} | ||||
| 	l.emit(tokByteString) | ||||
| 	return varLexNormal | ||||
| } | ||||
|  | ||||
| func varLexNumber(l *varLexer) lexState { | ||||
| 	l.accept("+-") | ||||
| 	digits := "0123456789" | ||||
| 	if l.accept("0") { | ||||
| 		if l.accept("x") { | ||||
| 			digits = "0123456789abcdefABCDEF" | ||||
| 		} else { | ||||
| 			digits = "01234567" | ||||
| 		} | ||||
| 	} | ||||
| 	for strings.ContainsRune(digits, l.next()) { | ||||
| 	} | ||||
| 	l.backup() | ||||
| 	if l.accept(".") { | ||||
| 		for strings.ContainsRune(digits, l.next()) { | ||||
| 		} | ||||
| 		l.backup() | ||||
| 	} | ||||
| 	if l.accept("eE") { | ||||
| 		l.accept("+-") | ||||
| 		for strings.ContainsRune("0123456789", l.next()) { | ||||
| 		} | ||||
| 		l.backup() | ||||
| 	} | ||||
| 	if r := l.peek(); unicode.IsLetter(r) { | ||||
| 		l.next() | ||||
| 		return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) | ||||
| 	} | ||||
| 	l.emit(tokNumber) | ||||
| 	return varLexNormal | ||||
| } | ||||
|  | ||||
| func varLexString(l *varLexer) lexState { | ||||
| 	q := l.next() | ||||
| Loop: | ||||
| 	for { | ||||
| 		switch l.next() { | ||||
| 		case '\\': | ||||
| 			if r := l.next(); r != -1 { | ||||
| 				break | ||||
| 			} | ||||
| 			fallthrough | ||||
| 		case -1: | ||||
| 			return l.errorf("unterminated string") | ||||
| 		case q: | ||||
| 			break Loop | ||||
| 		} | ||||
| 	} | ||||
| 	l.emit(tokString) | ||||
| 	return varLexNormal | ||||
| } | ||||
|  | ||||
| func varLexType(l *varLexer) lexState { | ||||
| 	at := l.accept("@") | ||||
| 	for { | ||||
| 		r := l.next() | ||||
| 		if r == -1 { | ||||
| 			break | ||||
| 		} | ||||
| 		if unicode.IsSpace(r) { | ||||
| 			l.backup() | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	if at { | ||||
| 		if _, err := ParseSignature(l.input[l.start+1 : l.pos]); err != nil { | ||||
| 			return l.errorf("%s", err) | ||||
| 		} | ||||
| 	} else { | ||||
| 		if _, ok := varTypeMap[l.input[l.start:l.pos]]; ok { | ||||
| 			l.emit(tokType) | ||||
| 			return varLexNormal | ||||
| 		} | ||||
| 		return l.errorf("unrecognized type %q", l.input[l.start:l.pos]) | ||||
| 	} | ||||
| 	l.emit(tokType) | ||||
| 	return varLexNormal | ||||
| } | ||||
							
								
								
									
										817
									
								
								vendor/github.com/godbus/dbus/v5/variant_parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										817
									
								
								vendor/github.com/godbus/dbus/v5/variant_parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,817 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"unicode/utf8" | ||||
| ) | ||||
|  | ||||
| type varParser struct { | ||||
| 	tokens []varToken | ||||
| 	i      int | ||||
| } | ||||
|  | ||||
| func (p *varParser) backup() { | ||||
| 	p.i-- | ||||
| } | ||||
|  | ||||
| func (p *varParser) next() varToken { | ||||
| 	if p.i < len(p.tokens) { | ||||
| 		t := p.tokens[p.i] | ||||
| 		p.i++ | ||||
| 		return t | ||||
| 	} | ||||
| 	return varToken{typ: tokEOF} | ||||
| } | ||||
|  | ||||
| type varNode interface { | ||||
| 	Infer() (Signature, error) | ||||
| 	String() string | ||||
| 	Sigs() sigSet | ||||
| 	Value(Signature) (interface{}, error) | ||||
| } | ||||
|  | ||||
| func varMakeNode(p *varParser) (varNode, error) { | ||||
| 	var sig Signature | ||||
|  | ||||
| 	for { | ||||
| 		t := p.next() | ||||
| 		switch t.typ { | ||||
| 		case tokEOF: | ||||
| 			return nil, io.ErrUnexpectedEOF | ||||
| 		case tokError: | ||||
| 			return nil, errors.New(t.val) | ||||
| 		case tokNumber: | ||||
| 			return varMakeNumNode(t, sig) | ||||
| 		case tokString: | ||||
| 			return varMakeStringNode(t, sig) | ||||
| 		case tokBool: | ||||
| 			if sig.str != "" && sig.str != "b" { | ||||
| 				return nil, varTypeError{t.val, sig} | ||||
| 			} | ||||
| 			b, err := strconv.ParseBool(t.val) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			return boolNode(b), nil | ||||
| 		case tokArrayStart: | ||||
| 			return varMakeArrayNode(p, sig) | ||||
| 		case tokVariantStart: | ||||
| 			return varMakeVariantNode(p, sig) | ||||
| 		case tokDictStart: | ||||
| 			return varMakeDictNode(p, sig) | ||||
| 		case tokType: | ||||
| 			if sig.str != "" { | ||||
| 				return nil, errors.New("unexpected type annotation") | ||||
| 			} | ||||
| 			if t.val[0] == '@' { | ||||
| 				sig.str = t.val[1:] | ||||
| 			} else { | ||||
| 				sig.str = varTypeMap[t.val] | ||||
| 			} | ||||
| 		case tokByteString: | ||||
| 			if sig.str != "" && sig.str != "ay" { | ||||
| 				return nil, varTypeError{t.val, sig} | ||||
| 			} | ||||
| 			b, err := varParseByteString(t.val) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			return byteStringNode(b), nil | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unexpected %q", t.val) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type varTypeError struct { | ||||
| 	val string | ||||
| 	sig Signature | ||||
| } | ||||
|  | ||||
| func (e varTypeError) Error() string { | ||||
| 	return fmt.Sprintf("dbus: can't parse %q as type %q", e.val, e.sig.str) | ||||
| } | ||||
|  | ||||
| type sigSet map[Signature]bool | ||||
|  | ||||
| func (s sigSet) Empty() bool { | ||||
| 	return len(s) == 0 | ||||
| } | ||||
|  | ||||
| func (s sigSet) Intersect(s2 sigSet) sigSet { | ||||
| 	r := make(sigSet) | ||||
| 	for k := range s { | ||||
| 		if s2[k] { | ||||
| 			r[k] = true | ||||
| 		} | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| func (s sigSet) Single() (Signature, bool) { | ||||
| 	if len(s) == 1 { | ||||
| 		for k := range s { | ||||
| 			return k, true | ||||
| 		} | ||||
| 	} | ||||
| 	return Signature{}, false | ||||
| } | ||||
|  | ||||
| func (s sigSet) ToArray() sigSet { | ||||
| 	r := make(sigSet, len(s)) | ||||
| 	for k := range s { | ||||
| 		r[Signature{"a" + k.str}] = true | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| type numNode struct { | ||||
| 	sig Signature | ||||
| 	str string | ||||
| 	val interface{} | ||||
| } | ||||
|  | ||||
| var numSigSet = sigSet{ | ||||
| 	Signature{"y"}: true, | ||||
| 	Signature{"n"}: true, | ||||
| 	Signature{"q"}: true, | ||||
| 	Signature{"i"}: true, | ||||
| 	Signature{"u"}: true, | ||||
| 	Signature{"x"}: true, | ||||
| 	Signature{"t"}: true, | ||||
| 	Signature{"d"}: true, | ||||
| } | ||||
|  | ||||
| func (n numNode) Infer() (Signature, error) { | ||||
| 	if strings.ContainsAny(n.str, ".e") { | ||||
| 		return Signature{"d"}, nil | ||||
| 	} | ||||
| 	return Signature{"i"}, nil | ||||
| } | ||||
|  | ||||
| func (n numNode) String() string { | ||||
| 	return n.str | ||||
| } | ||||
|  | ||||
| func (n numNode) Sigs() sigSet { | ||||
| 	if n.sig.str != "" { | ||||
| 		return sigSet{n.sig: true} | ||||
| 	} | ||||
| 	if strings.ContainsAny(n.str, ".e") { | ||||
| 		return sigSet{Signature{"d"}: true} | ||||
| 	} | ||||
| 	return numSigSet | ||||
| } | ||||
|  | ||||
| func (n numNode) Value(sig Signature) (interface{}, error) { | ||||
| 	if n.sig.str != "" && n.sig != sig { | ||||
| 		return nil, varTypeError{n.str, sig} | ||||
| 	} | ||||
| 	if n.val != nil { | ||||
| 		return n.val, nil | ||||
| 	} | ||||
| 	return varNumAs(n.str, sig) | ||||
| } | ||||
|  | ||||
| func varMakeNumNode(tok varToken, sig Signature) (varNode, error) { | ||||
| 	if sig.str == "" { | ||||
| 		return numNode{str: tok.val}, nil | ||||
| 	} | ||||
| 	num, err := varNumAs(tok.val, sig) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return numNode{sig: sig, val: num}, nil | ||||
| } | ||||
|  | ||||
| func varNumAs(s string, sig Signature) (interface{}, error) { | ||||
| 	isUnsigned := false | ||||
| 	size := 32 | ||||
| 	switch sig.str { | ||||
| 	case "n": | ||||
| 		size = 16 | ||||
| 	case "i": | ||||
| 	case "x": | ||||
| 		size = 64 | ||||
| 	case "y": | ||||
| 		size = 8 | ||||
| 		isUnsigned = true | ||||
| 	case "q": | ||||
| 		size = 16 | ||||
| 		isUnsigned = true | ||||
| 	case "u": | ||||
| 		isUnsigned = true | ||||
| 	case "t": | ||||
| 		size = 64 | ||||
| 		isUnsigned = true | ||||
| 	case "d": | ||||
| 		d, err := strconv.ParseFloat(s, 64) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return d, nil | ||||
| 	default: | ||||
| 		return nil, varTypeError{s, sig} | ||||
| 	} | ||||
| 	base := 10 | ||||
| 	if strings.HasPrefix(s, "0x") { | ||||
| 		base = 16 | ||||
| 		s = s[2:] | ||||
| 	} | ||||
| 	if strings.HasPrefix(s, "0") && len(s) != 1 { | ||||
| 		base = 8 | ||||
| 		s = s[1:] | ||||
| 	} | ||||
| 	if isUnsigned { | ||||
| 		i, err := strconv.ParseUint(s, base, size) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		var v interface{} = i | ||||
| 		switch sig.str { | ||||
| 		case "y": | ||||
| 			v = byte(i) | ||||
| 		case "q": | ||||
| 			v = uint16(i) | ||||
| 		case "u": | ||||
| 			v = uint32(i) | ||||
| 		} | ||||
| 		return v, nil | ||||
| 	} | ||||
| 	i, err := strconv.ParseInt(s, base, size) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var v interface{} = i | ||||
| 	switch sig.str { | ||||
| 	case "n": | ||||
| 		v = int16(i) | ||||
| 	case "i": | ||||
| 		v = int32(i) | ||||
| 	} | ||||
| 	return v, nil | ||||
| } | ||||
|  | ||||
| type stringNode struct { | ||||
| 	sig Signature | ||||
| 	str string      // parsed | ||||
| 	val interface{} // has correct type | ||||
| } | ||||
|  | ||||
| var stringSigSet = sigSet{ | ||||
| 	Signature{"s"}: true, | ||||
| 	Signature{"g"}: true, | ||||
| 	Signature{"o"}: true, | ||||
| } | ||||
|  | ||||
| func (n stringNode) Infer() (Signature, error) { | ||||
| 	return Signature{"s"}, nil | ||||
| } | ||||
|  | ||||
| func (n stringNode) String() string { | ||||
| 	return n.str | ||||
| } | ||||
|  | ||||
| func (n stringNode) Sigs() sigSet { | ||||
| 	if n.sig.str != "" { | ||||
| 		return sigSet{n.sig: true} | ||||
| 	} | ||||
| 	return stringSigSet | ||||
| } | ||||
|  | ||||
| func (n stringNode) Value(sig Signature) (interface{}, error) { | ||||
| 	if n.sig.str != "" && n.sig != sig { | ||||
| 		return nil, varTypeError{n.str, sig} | ||||
| 	} | ||||
| 	if n.val != nil { | ||||
| 		return n.val, nil | ||||
| 	} | ||||
| 	switch { | ||||
| 	case sig.str == "g": | ||||
| 		return Signature{n.str}, nil | ||||
| 	case sig.str == "o": | ||||
| 		return ObjectPath(n.str), nil | ||||
| 	case sig.str == "s": | ||||
| 		return n.str, nil | ||||
| 	default: | ||||
| 		return nil, varTypeError{n.str, sig} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func varMakeStringNode(tok varToken, sig Signature) (varNode, error) { | ||||
| 	if sig.str != "" && sig.str != "s" && sig.str != "g" && sig.str != "o" { | ||||
| 		return nil, fmt.Errorf("invalid type %q for string", sig.str) | ||||
| 	} | ||||
| 	s, err := varParseString(tok.val) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	n := stringNode{str: s} | ||||
| 	if sig.str == "" { | ||||
| 		return stringNode{str: s}, nil | ||||
| 	} | ||||
| 	n.sig = sig | ||||
| 	switch sig.str { | ||||
| 	case "o": | ||||
| 		n.val = ObjectPath(s) | ||||
| 	case "g": | ||||
| 		n.val = Signature{s} | ||||
| 	case "s": | ||||
| 		n.val = s | ||||
| 	} | ||||
| 	return n, nil | ||||
| } | ||||
|  | ||||
| func varParseString(s string) (string, error) { | ||||
| 	// quotes are guaranteed to be there | ||||
| 	s = s[1 : len(s)-1] | ||||
| 	buf := new(bytes.Buffer) | ||||
| 	for len(s) != 0 { | ||||
| 		r, size := utf8.DecodeRuneInString(s) | ||||
| 		if r == utf8.RuneError && size == 1 { | ||||
| 			return "", errors.New("invalid UTF-8") | ||||
| 		} | ||||
| 		s = s[size:] | ||||
| 		if r != '\\' { | ||||
| 			buf.WriteRune(r) | ||||
| 			continue | ||||
| 		} | ||||
| 		r, size = utf8.DecodeRuneInString(s) | ||||
| 		if r == utf8.RuneError && size == 1 { | ||||
| 			return "", errors.New("invalid UTF-8") | ||||
| 		} | ||||
| 		s = s[size:] | ||||
| 		switch r { | ||||
| 		case 'a': | ||||
| 			buf.WriteRune(0x7) | ||||
| 		case 'b': | ||||
| 			buf.WriteRune(0x8) | ||||
| 		case 'f': | ||||
| 			buf.WriteRune(0xc) | ||||
| 		case 'n': | ||||
| 			buf.WriteRune('\n') | ||||
| 		case 'r': | ||||
| 			buf.WriteRune('\r') | ||||
| 		case 't': | ||||
| 			buf.WriteRune('\t') | ||||
| 		case '\n': | ||||
| 		case 'u': | ||||
| 			if len(s) < 4 { | ||||
| 				return "", errors.New("short unicode escape") | ||||
| 			} | ||||
| 			r, err := strconv.ParseUint(s[:4], 16, 32) | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 			buf.WriteRune(rune(r)) | ||||
| 			s = s[4:] | ||||
| 		case 'U': | ||||
| 			if len(s) < 8 { | ||||
| 				return "", errors.New("short unicode escape") | ||||
| 			} | ||||
| 			r, err := strconv.ParseUint(s[:8], 16, 32) | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 			buf.WriteRune(rune(r)) | ||||
| 			s = s[8:] | ||||
| 		default: | ||||
| 			buf.WriteRune(r) | ||||
| 		} | ||||
| 	} | ||||
| 	return buf.String(), nil | ||||
| } | ||||
|  | ||||
| var boolSigSet = sigSet{Signature{"b"}: true} | ||||
|  | ||||
| type boolNode bool | ||||
|  | ||||
| func (boolNode) Infer() (Signature, error) { | ||||
| 	return Signature{"b"}, nil | ||||
| } | ||||
|  | ||||
| func (b boolNode) String() string { | ||||
| 	if b { | ||||
| 		return "true" | ||||
| 	} | ||||
| 	return "false" | ||||
| } | ||||
|  | ||||
| func (boolNode) Sigs() sigSet { | ||||
| 	return boolSigSet | ||||
| } | ||||
|  | ||||
| func (b boolNode) Value(sig Signature) (interface{}, error) { | ||||
| 	if sig.str != "b" { | ||||
| 		return nil, varTypeError{b.String(), sig} | ||||
| 	} | ||||
| 	return bool(b), nil | ||||
| } | ||||
|  | ||||
| type arrayNode struct { | ||||
| 	set      sigSet | ||||
| 	children []varNode | ||||
| 	val      interface{} | ||||
| } | ||||
|  | ||||
| func (n arrayNode) Infer() (Signature, error) { | ||||
| 	for _, v := range n.children { | ||||
| 		csig, err := varInfer(v) | ||||
| 		if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		return Signature{"a" + csig.str}, nil | ||||
| 	} | ||||
| 	return Signature{}, fmt.Errorf("can't infer type for %q", n.String()) | ||||
| } | ||||
|  | ||||
| func (n arrayNode) String() string { | ||||
| 	s := "[" | ||||
| 	for i, v := range n.children { | ||||
| 		s += v.String() | ||||
| 		if i != len(n.children)-1 { | ||||
| 			s += ", " | ||||
| 		} | ||||
| 	} | ||||
| 	return s + "]" | ||||
| } | ||||
|  | ||||
| func (n arrayNode) Sigs() sigSet { | ||||
| 	return n.set | ||||
| } | ||||
|  | ||||
| func (n arrayNode) Value(sig Signature) (interface{}, error) { | ||||
| 	if n.set.Empty() { | ||||
| 		// no type information whatsoever, so this must be an empty slice | ||||
| 		return reflect.MakeSlice(typeFor(sig.str), 0, 0).Interface(), nil | ||||
| 	} | ||||
| 	if !n.set[sig] { | ||||
| 		return nil, varTypeError{n.String(), sig} | ||||
| 	} | ||||
| 	s := reflect.MakeSlice(typeFor(sig.str), len(n.children), len(n.children)) | ||||
| 	for i, v := range n.children { | ||||
| 		rv, err := v.Value(Signature{sig.str[1:]}) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		s.Index(i).Set(reflect.ValueOf(rv)) | ||||
| 	} | ||||
| 	return s.Interface(), nil | ||||
| } | ||||
|  | ||||
| func varMakeArrayNode(p *varParser, sig Signature) (varNode, error) { | ||||
| 	var n arrayNode | ||||
| 	if sig.str != "" { | ||||
| 		n.set = sigSet{sig: true} | ||||
| 	} | ||||
| 	if t := p.next(); t.typ == tokArrayEnd { | ||||
| 		return n, nil | ||||
| 	} else { | ||||
| 		p.backup() | ||||
| 	} | ||||
| Loop: | ||||
| 	for { | ||||
| 		t := p.next() | ||||
| 		switch t.typ { | ||||
| 		case tokEOF: | ||||
| 			return nil, io.ErrUnexpectedEOF | ||||
| 		case tokError: | ||||
| 			return nil, errors.New(t.val) | ||||
| 		} | ||||
| 		p.backup() | ||||
| 		cn, err := varMakeNode(p) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if cset := cn.Sigs(); !cset.Empty() { | ||||
| 			if n.set.Empty() { | ||||
| 				n.set = cset.ToArray() | ||||
| 			} else { | ||||
| 				nset := cset.ToArray().Intersect(n.set) | ||||
| 				if nset.Empty() { | ||||
| 					return nil, fmt.Errorf("can't parse %q with given type information", cn.String()) | ||||
| 				} | ||||
| 				n.set = nset | ||||
| 			} | ||||
| 		} | ||||
| 		n.children = append(n.children, cn) | ||||
| 		switch t := p.next(); t.typ { | ||||
| 		case tokEOF: | ||||
| 			return nil, io.ErrUnexpectedEOF | ||||
| 		case tokError: | ||||
| 			return nil, errors.New(t.val) | ||||
| 		case tokArrayEnd: | ||||
| 			break Loop | ||||
| 		case tokComma: | ||||
| 			continue | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unexpected %q", t.val) | ||||
| 		} | ||||
| 	} | ||||
| 	return n, nil | ||||
| } | ||||
|  | ||||
| type variantNode struct { | ||||
| 	n varNode | ||||
| } | ||||
|  | ||||
| var variantSet = sigSet{ | ||||
| 	Signature{"v"}: true, | ||||
| } | ||||
|  | ||||
| func (variantNode) Infer() (Signature, error) { | ||||
| 	return Signature{"v"}, nil | ||||
| } | ||||
|  | ||||
| func (n variantNode) String() string { | ||||
| 	return "<" + n.n.String() + ">" | ||||
| } | ||||
|  | ||||
| func (variantNode) Sigs() sigSet { | ||||
| 	return variantSet | ||||
| } | ||||
|  | ||||
| func (n variantNode) Value(sig Signature) (interface{}, error) { | ||||
| 	if sig.str != "v" { | ||||
| 		return nil, varTypeError{n.String(), sig} | ||||
| 	} | ||||
| 	sig, err := varInfer(n.n) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	v, err := n.n.Value(sig) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return MakeVariant(v), nil | ||||
| } | ||||
|  | ||||
| func varMakeVariantNode(p *varParser, sig Signature) (varNode, error) { | ||||
| 	n, err := varMakeNode(p) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if t := p.next(); t.typ != tokVariantEnd { | ||||
| 		return nil, fmt.Errorf("unexpected %q", t.val) | ||||
| 	} | ||||
| 	vn := variantNode{n} | ||||
| 	if sig.str != "" && sig.str != "v" { | ||||
| 		return nil, varTypeError{vn.String(), sig} | ||||
| 	} | ||||
| 	return variantNode{n}, nil | ||||
| } | ||||
|  | ||||
| type dictEntry struct { | ||||
| 	key, val varNode | ||||
| } | ||||
|  | ||||
| type dictNode struct { | ||||
| 	kset, vset sigSet | ||||
| 	children   []dictEntry | ||||
| 	val        interface{} | ||||
| } | ||||
|  | ||||
| func (n dictNode) Infer() (Signature, error) { | ||||
| 	for _, v := range n.children { | ||||
| 		ksig, err := varInfer(v.key) | ||||
| 		if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		vsig, err := varInfer(v.val) | ||||
| 		if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		return Signature{"a{" + ksig.str + vsig.str + "}"}, nil | ||||
| 	} | ||||
| 	return Signature{}, fmt.Errorf("can't infer type for %q", n.String()) | ||||
| } | ||||
|  | ||||
| func (n dictNode) String() string { | ||||
| 	s := "{" | ||||
| 	for i, v := range n.children { | ||||
| 		s += v.key.String() + ": " + v.val.String() | ||||
| 		if i != len(n.children)-1 { | ||||
| 			s += ", " | ||||
| 		} | ||||
| 	} | ||||
| 	return s + "}" | ||||
| } | ||||
|  | ||||
| func (n dictNode) Sigs() sigSet { | ||||
| 	r := sigSet{} | ||||
| 	for k := range n.kset { | ||||
| 		for v := range n.vset { | ||||
| 			sig := "a{" + k.str + v.str + "}" | ||||
| 			r[Signature{sig}] = true | ||||
| 		} | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| func (n dictNode) Value(sig Signature) (interface{}, error) { | ||||
| 	set := n.Sigs() | ||||
| 	if set.Empty() { | ||||
| 		// no type information -> empty dict | ||||
| 		return reflect.MakeMap(typeFor(sig.str)).Interface(), nil | ||||
| 	} | ||||
| 	if !set[sig] { | ||||
| 		return nil, varTypeError{n.String(), sig} | ||||
| 	} | ||||
| 	m := reflect.MakeMap(typeFor(sig.str)) | ||||
| 	ksig := Signature{sig.str[2:3]} | ||||
| 	vsig := Signature{sig.str[3 : len(sig.str)-1]} | ||||
| 	for _, v := range n.children { | ||||
| 		kv, err := v.key.Value(ksig) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		vv, err := v.val.Value(vsig) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		m.SetMapIndex(reflect.ValueOf(kv), reflect.ValueOf(vv)) | ||||
| 	} | ||||
| 	return m.Interface(), nil | ||||
| } | ||||
|  | ||||
| func varMakeDictNode(p *varParser, sig Signature) (varNode, error) { | ||||
| 	var n dictNode | ||||
|  | ||||
| 	if sig.str != "" { | ||||
| 		if len(sig.str) < 5 { | ||||
| 			return nil, fmt.Errorf("invalid signature %q for dict type", sig) | ||||
| 		} | ||||
| 		ksig := Signature{string(sig.str[2])} | ||||
| 		vsig := Signature{sig.str[3 : len(sig.str)-1]} | ||||
| 		n.kset = sigSet{ksig: true} | ||||
| 		n.vset = sigSet{vsig: true} | ||||
| 	} | ||||
| 	if t := p.next(); t.typ == tokDictEnd { | ||||
| 		return n, nil | ||||
| 	} else { | ||||
| 		p.backup() | ||||
| 	} | ||||
| Loop: | ||||
| 	for { | ||||
| 		t := p.next() | ||||
| 		switch t.typ { | ||||
| 		case tokEOF: | ||||
| 			return nil, io.ErrUnexpectedEOF | ||||
| 		case tokError: | ||||
| 			return nil, errors.New(t.val) | ||||
| 		} | ||||
| 		p.backup() | ||||
| 		kn, err := varMakeNode(p) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if kset := kn.Sigs(); !kset.Empty() { | ||||
| 			if n.kset.Empty() { | ||||
| 				n.kset = kset | ||||
| 			} else { | ||||
| 				n.kset = kset.Intersect(n.kset) | ||||
| 				if n.kset.Empty() { | ||||
| 					return nil, fmt.Errorf("can't parse %q with given type information", kn.String()) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		t = p.next() | ||||
| 		switch t.typ { | ||||
| 		case tokEOF: | ||||
| 			return nil, io.ErrUnexpectedEOF | ||||
| 		case tokError: | ||||
| 			return nil, errors.New(t.val) | ||||
| 		case tokColon: | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unexpected %q", t.val) | ||||
| 		} | ||||
| 		t = p.next() | ||||
| 		switch t.typ { | ||||
| 		case tokEOF: | ||||
| 			return nil, io.ErrUnexpectedEOF | ||||
| 		case tokError: | ||||
| 			return nil, errors.New(t.val) | ||||
| 		} | ||||
| 		p.backup() | ||||
| 		vn, err := varMakeNode(p) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if vset := vn.Sigs(); !vset.Empty() { | ||||
| 			if n.vset.Empty() { | ||||
| 				n.vset = vset | ||||
| 			} else { | ||||
| 				n.vset = n.vset.Intersect(vset) | ||||
| 				if n.vset.Empty() { | ||||
| 					return nil, fmt.Errorf("can't parse %q with given type information", vn.String()) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		n.children = append(n.children, dictEntry{kn, vn}) | ||||
| 		t = p.next() | ||||
| 		switch t.typ { | ||||
| 		case tokEOF: | ||||
| 			return nil, io.ErrUnexpectedEOF | ||||
| 		case tokError: | ||||
| 			return nil, errors.New(t.val) | ||||
| 		case tokDictEnd: | ||||
| 			break Loop | ||||
| 		case tokComma: | ||||
| 			continue | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unexpected %q", t.val) | ||||
| 		} | ||||
| 	} | ||||
| 	return n, nil | ||||
| } | ||||
|  | ||||
| type byteStringNode []byte | ||||
|  | ||||
| var byteStringSet = sigSet{ | ||||
| 	Signature{"ay"}: true, | ||||
| } | ||||
|  | ||||
| func (byteStringNode) Infer() (Signature, error) { | ||||
| 	return Signature{"ay"}, nil | ||||
| } | ||||
|  | ||||
| func (b byteStringNode) String() string { | ||||
| 	return string(b) | ||||
| } | ||||
|  | ||||
| func (b byteStringNode) Sigs() sigSet { | ||||
| 	return byteStringSet | ||||
| } | ||||
|  | ||||
| func (b byteStringNode) Value(sig Signature) (interface{}, error) { | ||||
| 	if sig.str != "ay" { | ||||
| 		return nil, varTypeError{b.String(), sig} | ||||
| 	} | ||||
| 	return []byte(b), nil | ||||
| } | ||||
|  | ||||
| func varParseByteString(s string) ([]byte, error) { | ||||
| 	// quotes and b at start are guaranteed to be there | ||||
| 	b := make([]byte, 0, 1) | ||||
| 	s = s[2 : len(s)-1] | ||||
| 	for len(s) != 0 { | ||||
| 		c := s[0] | ||||
| 		s = s[1:] | ||||
| 		if c != '\\' { | ||||
| 			b = append(b, c) | ||||
| 			continue | ||||
| 		} | ||||
| 		c = s[0] | ||||
| 		s = s[1:] | ||||
| 		switch c { | ||||
| 		case 'a': | ||||
| 			b = append(b, 0x7) | ||||
| 		case 'b': | ||||
| 			b = append(b, 0x8) | ||||
| 		case 'f': | ||||
| 			b = append(b, 0xc) | ||||
| 		case 'n': | ||||
| 			b = append(b, '\n') | ||||
| 		case 'r': | ||||
| 			b = append(b, '\r') | ||||
| 		case 't': | ||||
| 			b = append(b, '\t') | ||||
| 		case 'x': | ||||
| 			if len(s) < 2 { | ||||
| 				return nil, errors.New("short escape") | ||||
| 			} | ||||
| 			n, err := strconv.ParseUint(s[:2], 16, 8) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			b = append(b, byte(n)) | ||||
| 			s = s[2:] | ||||
| 		case '0': | ||||
| 			if len(s) < 3 { | ||||
| 				return nil, errors.New("short escape") | ||||
| 			} | ||||
| 			n, err := strconv.ParseUint(s[:3], 8, 8) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			b = append(b, byte(n)) | ||||
| 			s = s[3:] | ||||
| 		default: | ||||
| 			b = append(b, c) | ||||
| 		} | ||||
| 	} | ||||
| 	return append(b, 0), nil | ||||
| } | ||||
|  | ||||
| func varInfer(n varNode) (Signature, error) { | ||||
| 	if sig, ok := n.Sigs().Single(); ok { | ||||
| 		return sig, nil | ||||
| 	} | ||||
| 	return n.Infer() | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 anthonyrawlins
					anthonyrawlins