mirror of
				https://github.com/taigrr/wtf
				synced 2025-01-18 04:03:14 -08:00 
			
		
		
		
	Add godbus/dbus and sticreations/spotigopher dependencies
These were added as a part of #317 to add the Spotify widget
This commit is contained in:
		
							parent
							
								
									7ca4fae09c
								
							
						
					
					
						commit
						b568351dfd
					
				
							
								
								
									
										17
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										17
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							@ -143,6 +143,14 @@
 | 
				
			|||||||
  pruneopts = "UT"
 | 
					  pruneopts = "UT"
 | 
				
			||||||
  revision = "de7e78efa4a71b3f36c7154989c529dbdf9ae623"
 | 
					  revision = "de7e78efa4a71b3f36c7154989c529dbdf9ae623"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[projects]]
 | 
				
			||||||
 | 
					  digest = "1:57fa4c058c21ce25d0b7272518dd746065117abf6cc706158b0d361202024520"
 | 
				
			||||||
 | 
					  name = "github.com/godbus/dbus"
 | 
				
			||||||
 | 
					  packages = ["."]
 | 
				
			||||||
 | 
					  pruneopts = "UT"
 | 
				
			||||||
 | 
					  revision = "a389bdde4dd695d414e47b755e95e72b7826432c"
 | 
				
			||||||
 | 
					  version = "v4.1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[projects]]
 | 
					[[projects]]
 | 
				
			||||||
  digest = "1:15042ad3498153684d09f393bbaec6b216c8eec6d61f63dff711de7d64ed8861"
 | 
					  digest = "1:15042ad3498153684d09f393bbaec6b216c8eec6d61f63dff711de7d64ed8861"
 | 
				
			||||||
  name = "github.com/golang/protobuf"
 | 
					  name = "github.com/golang/protobuf"
 | 
				
			||||||
@ -239,6 +247,14 @@
 | 
				
			|||||||
  pruneopts = "UT"
 | 
					  pruneopts = "UT"
 | 
				
			||||||
  revision = "21f50f5bc400083b4eb23304887d9cd0fc00d075"
 | 
					  revision = "21f50f5bc400083b4eb23304887d9cd0fc00d075"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[projects]]
 | 
				
			||||||
 | 
					  branch = "master"
 | 
				
			||||||
 | 
					  digest = "1:de0cf35afb9cad7b20ff8871ae3b64cecc7116bffb583bc7b3c1bb5c37473149"
 | 
				
			||||||
 | 
					  name = "github.com/sticreations/spotigopher"
 | 
				
			||||||
 | 
					  packages = ["spotigopher"]
 | 
				
			||||||
 | 
					  pruneopts = "UT"
 | 
				
			||||||
 | 
					  revision = "995ee350dc1c54259597de65dde7a9e56a4b73af"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[projects]]
 | 
					[[projects]]
 | 
				
			||||||
  digest = "1:18752d0b95816a1b777505a97f71c7467a8445b8ffb55631a7bf779f6ba4fa83"
 | 
					  digest = "1:18752d0b95816a1b777505a97f71c7467a8445b8ffb55631a7bf779f6ba4fa83"
 | 
				
			||||||
  name = "github.com/stretchr/testify"
 | 
					  name = "github.com/stretchr/testify"
 | 
				
			||||||
@ -370,6 +386,7 @@
 | 
				
			|||||||
    "github.com/pkg/profile",
 | 
					    "github.com/pkg/profile",
 | 
				
			||||||
    "github.com/radovskyb/watcher",
 | 
					    "github.com/radovskyb/watcher",
 | 
				
			||||||
    "github.com/rivo/tview",
 | 
					    "github.com/rivo/tview",
 | 
				
			||||||
 | 
					    "github.com/sticreations/spotigopher/spotigopher",
 | 
				
			||||||
    "github.com/stretchr/testify/assert",
 | 
					    "github.com/stretchr/testify/assert",
 | 
				
			||||||
    "github.com/xanzy/go-gitlab",
 | 
					    "github.com/xanzy/go-gitlab",
 | 
				
			||||||
    "github.com/yfronto/newrelic",
 | 
					    "github.com/yfronto/newrelic",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										40
									
								
								vendor/github.com/godbus/dbus/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								vendor/github.com/godbus/dbus/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					dist: precise
 | 
				
			||||||
 | 
					language: go
 | 
				
			||||||
 | 
					go_import_path: github.com/godbus/dbus
 | 
				
			||||||
 | 
					sudo: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go:
 | 
				
			||||||
 | 
					  - 1.6.3
 | 
				
			||||||
 | 
					  - 1.7.3
 | 
				
			||||||
 | 
					  - tip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  global:
 | 
				
			||||||
 | 
					  matrix:
 | 
				
			||||||
 | 
					   - TARGET=amd64
 | 
				
			||||||
 | 
					   - TARGET=arm64
 | 
				
			||||||
 | 
					   - TARGET=arm
 | 
				
			||||||
 | 
					   - TARGET=386
 | 
				
			||||||
 | 
					   - TARGET=ppc64le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					matrix:
 | 
				
			||||||
 | 
					  fast_finish: true
 | 
				
			||||||
 | 
					  allow_failures:
 | 
				
			||||||
 | 
					    - go: tip
 | 
				
			||||||
 | 
					  exclude:
 | 
				
			||||||
 | 
					  - go: tip
 | 
				
			||||||
 | 
					    env: TARGET=arm
 | 
				
			||||||
 | 
					  - go: tip
 | 
				
			||||||
 | 
					    env: TARGET=arm64
 | 
				
			||||||
 | 
					  - go: tip
 | 
				
			||||||
 | 
					    env: TARGET=386
 | 
				
			||||||
 | 
					  - go: tip
 | 
				
			||||||
 | 
					    env: TARGET=ppc64le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					addons:
 | 
				
			||||||
 | 
					  apt:
 | 
				
			||||||
 | 
					    packages:
 | 
				
			||||||
 | 
					    - dbus
 | 
				
			||||||
 | 
					    - dbus-x11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					before_install:
 | 
				
			||||||
							
								
								
									
										50
									
								
								vendor/github.com/godbus/dbus/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								vendor/github.com/godbus/dbus/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/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/godbus/dbus/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/MAINTAINERS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/godbus/dbus/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)
 | 
				
			||||||
							
								
								
									
										44
									
								
								vendor/github.com/godbus/dbus/README.markdown
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/godbus/dbus/README.markdown
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					[](https://travis-ci.org/godbus/dbus)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.1. If you installed it and set up your GOPATH, just run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					go get github.com/godbus/dbus
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you want to use the subpackages, you can install them the same way.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 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
 | 
				
			||||||
 | 
					- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
 | 
				
			||||||
 | 
					- [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
							
								
								
									
										253
									
								
								vendor/github.com/godbus/dbus/auth.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								vendor/github.com/godbus/dbus/auth.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,253 @@
 | 
				
			|||||||
 | 
					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 mechnism, 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.Getuid())
 | 
				
			||||||
 | 
							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, data, status := m.FirstData(); bytes.Equal(v, name) {
 | 
				
			||||||
 | 
									var ok bool
 | 
				
			||||||
 | 
									err = authWriteLine(conn.transport, []byte("AUTH"), []byte(v), data)
 | 
				
			||||||
 | 
									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()
 | 
				
			||||||
 | 
										go conn.outWorker()
 | 
				
			||||||
 | 
										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 occured.
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								conn.uuid = string(s[1])
 | 
				
			||||||
 | 
								return nil, true
 | 
				
			||||||
 | 
							case state == waitingForOk && string(s[0]) == "REJECTED":
 | 
				
			||||||
 | 
								return nil, false
 | 
				
			||||||
 | 
							case state == waitingForOk && (string(s[0]) == "DATA" ||
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								vendor/github.com/godbus/dbus/auth_external.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/godbus/dbus/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/auth_sha1.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/godbus/dbus/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 occured, 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								vendor/github.com/godbus/dbus/call.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/godbus/dbus/call.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var errSignature = errors.New("dbus: mismatched signature")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										683
									
								
								vendor/github.com/godbus/dbus/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										683
									
								
								vendor/github.com/godbus/dbus/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,683 @@
 | 
				
			|||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						systemBus     *Conn
 | 
				
			||||||
 | 
						systemBusLck  sync.Mutex
 | 
				
			||||||
 | 
						sessionBus    *Conn
 | 
				
			||||||
 | 
						sessionBusLck sync.Mutex
 | 
				
			||||||
 | 
						sessionEnvLck 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						busObj BusObject
 | 
				
			||||||
 | 
						unixFD bool
 | 
				
			||||||
 | 
						uuid   string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						names    []string
 | 
				
			||||||
 | 
						namesLck sync.RWMutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						serialLck  sync.Mutex
 | 
				
			||||||
 | 
						nextSerial uint32
 | 
				
			||||||
 | 
						serialUsed map[uint32]bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						calls    map[uint32]*Call
 | 
				
			||||||
 | 
						callsLck sync.RWMutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						handler Handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out    chan *Message
 | 
				
			||||||
 | 
						closed bool
 | 
				
			||||||
 | 
						outLck sync.RWMutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						signalHandler SignalHandler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 {
 | 
				
			||||||
 | 
							return sessionBus, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if conn != nil {
 | 
				
			||||||
 | 
								sessionBus = conn
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						conn, err = SessionBusPrivate()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err = conn.Auth(nil); err != nil {
 | 
				
			||||||
 | 
							conn.Close()
 | 
				
			||||||
 | 
							conn = nil
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err = conn.Hello(); err != nil {
 | 
				
			||||||
 | 
							conn.Close()
 | 
				
			||||||
 | 
							conn = nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getSessionBusAddress() (string, error) {
 | 
				
			||||||
 | 
						sessionEnvLck.Lock()
 | 
				
			||||||
 | 
						defer sessionEnvLck.Unlock()
 | 
				
			||||||
 | 
						address := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
 | 
				
			||||||
 | 
						if address != "" && address != "autolaunch:" {
 | 
				
			||||||
 | 
							return address, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return getSessionBusPlatformAddress()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SessionBusPrivate returns a new private connection to the session bus.
 | 
				
			||||||
 | 
					func SessionBusPrivate() (*Conn, error) {
 | 
				
			||||||
 | 
						address, err := getSessionBusAddress()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Dial(address)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SessionBusPrivate returns a new private connection to the session bus.
 | 
				
			||||||
 | 
					func SessionBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) {
 | 
				
			||||||
 | 
						address, err := getSessionBusAddress()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return DialHandler(address, handler, 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 {
 | 
				
			||||||
 | 
							return systemBus, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if conn != nil {
 | 
				
			||||||
 | 
								systemBus = conn
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						conn, err = SystemBusPrivate()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err = conn.Auth(nil); err != nil {
 | 
				
			||||||
 | 
							conn.Close()
 | 
				
			||||||
 | 
							conn = nil
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err = conn.Hello(); err != nil {
 | 
				
			||||||
 | 
							conn.Close()
 | 
				
			||||||
 | 
							conn = nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SystemBusPrivate returns a new private connection to the system bus.
 | 
				
			||||||
 | 
					func SystemBusPrivate() (*Conn, error) {
 | 
				
			||||||
 | 
						return Dial(getSystemBusPlatformAddress())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SystemBusPrivateHandler returns a new private connection to the system bus, using the provided handlers.
 | 
				
			||||||
 | 
					func SystemBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) {
 | 
				
			||||||
 | 
						return DialHandler(getSystemBusPlatformAddress(), handler, signalHandler)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Dial establishes a new private connection to the message bus specified by address.
 | 
				
			||||||
 | 
					func Dial(address string) (*Conn, error) {
 | 
				
			||||||
 | 
						tr, err := getTransport(address)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return newConn(tr, NewDefaultHandler(), NewDefaultSignalHandler())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DialHandler establishes a new private connection to the message bus specified by address, using the supplied handlers.
 | 
				
			||||||
 | 
					func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) {
 | 
				
			||||||
 | 
						tr, err := getTransport(address)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return newConn(tr, handler, signalHandler)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewConn creates a new private *Conn from an already established connection.
 | 
				
			||||||
 | 
					func NewConn(conn io.ReadWriteCloser) (*Conn, error) {
 | 
				
			||||||
 | 
						return NewConnHandler(conn, NewDefaultHandler(), NewDefaultSignalHandler())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewConnHandler creates a new private *Conn from an already established connection, using the supplied handlers.
 | 
				
			||||||
 | 
					func NewConnHandler(conn io.ReadWriteCloser, handler Handler, signalHandler SignalHandler) (*Conn, error) {
 | 
				
			||||||
 | 
						return newConn(genericTransport{conn}, handler, signalHandler)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// newConn creates a new *Conn from a transport.
 | 
				
			||||||
 | 
					func newConn(tr transport, handler Handler, signalHandler SignalHandler) (*Conn, error) {
 | 
				
			||||||
 | 
						conn := new(Conn)
 | 
				
			||||||
 | 
						conn.transport = tr
 | 
				
			||||||
 | 
						conn.calls = make(map[uint32]*Call)
 | 
				
			||||||
 | 
						conn.out = make(chan *Message, 10)
 | 
				
			||||||
 | 
						conn.handler = handler
 | 
				
			||||||
 | 
						conn.signalHandler = signalHandler
 | 
				
			||||||
 | 
						conn.nextSerial = 1
 | 
				
			||||||
 | 
						conn.serialUsed = map[uint32]bool{0: true}
 | 
				
			||||||
 | 
						conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
 | 
				
			||||||
 | 
						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.outLck.Lock()
 | 
				
			||||||
 | 
						if conn.closed {
 | 
				
			||||||
 | 
							// inWorker calls Close on read error, the read error may
 | 
				
			||||||
 | 
							// be caused by another caller calling Close to shutdown the
 | 
				
			||||||
 | 
							// dbus connection, a double-close scenario we prevent here.
 | 
				
			||||||
 | 
							conn.outLck.Unlock()
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						close(conn.out)
 | 
				
			||||||
 | 
						conn.closed = true
 | 
				
			||||||
 | 
						conn.outLck.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return conn.transport.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 appropiate 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 {
 | 
				
			||||||
 | 
						conn.serialLck.Lock()
 | 
				
			||||||
 | 
						defer conn.serialLck.Unlock()
 | 
				
			||||||
 | 
						n := conn.nextSerial
 | 
				
			||||||
 | 
						for conn.serialUsed[n] {
 | 
				
			||||||
 | 
							n++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn.serialUsed[n] = true
 | 
				
			||||||
 | 
						conn.nextSerial = n + 1
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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.namesLck.Lock()
 | 
				
			||||||
 | 
						conn.names = make([]string, 1)
 | 
				
			||||||
 | 
						conn.names[0] = s
 | 
				
			||||||
 | 
						conn.namesLck.Unlock()
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// inWorker runs in an own goroutine, reading incoming messages from the
 | 
				
			||||||
 | 
					// transport and dispatching them appropiately.
 | 
				
			||||||
 | 
					func (conn *Conn) inWorker() {
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							msg, err := conn.ReadMessage()
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								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 := false
 | 
				
			||||||
 | 
								if dest == "" {
 | 
				
			||||||
 | 
									found = true
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									conn.namesLck.RLock()
 | 
				
			||||||
 | 
									if len(conn.names) == 0 {
 | 
				
			||||||
 | 
										found = true
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for _, v := range conn.names {
 | 
				
			||||||
 | 
										if dest == v {
 | 
				
			||||||
 | 
											found = true
 | 
				
			||||||
 | 
											break
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									conn.namesLck.RUnlock()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !found {
 | 
				
			||||||
 | 
									// Eavesdropped a message, but no channel for it is registered.
 | 
				
			||||||
 | 
									// Ignore it.
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								switch msg.Type {
 | 
				
			||||||
 | 
								case TypeMethodReply, TypeError:
 | 
				
			||||||
 | 
									serial := msg.Headers[FieldReplySerial].value.(uint32)
 | 
				
			||||||
 | 
									conn.callsLck.Lock()
 | 
				
			||||||
 | 
									if c, ok := conn.calls[serial]; ok {
 | 
				
			||||||
 | 
										if msg.Type == TypeError {
 | 
				
			||||||
 | 
											name, _ := msg.Headers[FieldErrorName].value.(string)
 | 
				
			||||||
 | 
											c.Err = Error{name, msg.Body}
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											c.Body = msg.Body
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										c.Done <- c
 | 
				
			||||||
 | 
										conn.serialLck.Lock()
 | 
				
			||||||
 | 
										delete(conn.serialUsed, serial)
 | 
				
			||||||
 | 
										conn.serialLck.Unlock()
 | 
				
			||||||
 | 
										delete(conn.calls, serial)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									conn.callsLck.Unlock()
 | 
				
			||||||
 | 
								case TypeSignal:
 | 
				
			||||||
 | 
									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.namesLck.Lock()
 | 
				
			||||||
 | 
											for i, v := range conn.names {
 | 
				
			||||||
 | 
												if v == name {
 | 
				
			||||||
 | 
													conn.names = append(conn.names[:i],
 | 
				
			||||||
 | 
														conn.names[i+1:]...)
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											conn.namesLck.Unlock()
 | 
				
			||||||
 | 
										} 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.namesLck.Lock()
 | 
				
			||||||
 | 
											conn.names = append(conn.names, name)
 | 
				
			||||||
 | 
											conn.namesLck.Unlock()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									conn.handleSignal(msg)
 | 
				
			||||||
 | 
								case TypeMethodCall:
 | 
				
			||||||
 | 
									go conn.handleCall(msg)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if _, ok := err.(InvalidMessageError); !ok {
 | 
				
			||||||
 | 
								// Some read error occured (usually EOF); we can't really do
 | 
				
			||||||
 | 
								// anything but to shut down all stuff and returns errors to all
 | 
				
			||||||
 | 
								// pending replies.
 | 
				
			||||||
 | 
								conn.Close()
 | 
				
			||||||
 | 
								conn.callsLck.RLock()
 | 
				
			||||||
 | 
								for _, v := range conn.calls {
 | 
				
			||||||
 | 
									v.Err = err
 | 
				
			||||||
 | 
									v.Done <- v
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								conn.callsLck.RUnlock()
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// invalid messages are ignored
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (conn *Conn) handleSignal(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)
 | 
				
			||||||
 | 
						signal := &Signal{
 | 
				
			||||||
 | 
							Sender: sender,
 | 
				
			||||||
 | 
							Path:   msg.Headers[FieldPath].value.(ObjectPath),
 | 
				
			||||||
 | 
							Name:   iface + "." + member,
 | 
				
			||||||
 | 
							Body:   msg.Body,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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 {
 | 
				
			||||||
 | 
						conn.namesLck.RLock()
 | 
				
			||||||
 | 
						// copy the slice so it can't be modified
 | 
				
			||||||
 | 
						s := make([]string, len(conn.names))
 | 
				
			||||||
 | 
						copy(s, conn.names)
 | 
				
			||||||
 | 
						conn.namesLck.RUnlock()
 | 
				
			||||||
 | 
						return s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// outWorker runs in an own goroutine, encoding and sending messages that are
 | 
				
			||||||
 | 
					// sent to conn.out.
 | 
				
			||||||
 | 
					func (conn *Conn) outWorker() {
 | 
				
			||||||
 | 
						for msg := range conn.out {
 | 
				
			||||||
 | 
							err := conn.SendMessage(msg)
 | 
				
			||||||
 | 
							conn.callsLck.RLock()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if c := conn.calls[msg.serial]; c != nil {
 | 
				
			||||||
 | 
									c.Err = err
 | 
				
			||||||
 | 
									c.Done <- c
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								conn.serialLck.Lock()
 | 
				
			||||||
 | 
								delete(conn.serialUsed, msg.serial)
 | 
				
			||||||
 | 
								conn.serialLck.Unlock()
 | 
				
			||||||
 | 
							} else if msg.Type != TypeMethodCall {
 | 
				
			||||||
 | 
								conn.serialLck.Lock()
 | 
				
			||||||
 | 
								delete(conn.serialUsed, msg.serial)
 | 
				
			||||||
 | 
								conn.serialLck.Unlock()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							conn.callsLck.RUnlock()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
						var call *Call
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg.serial = conn.getSerial()
 | 
				
			||||||
 | 
						if msg.Type == TypeMethodCall && msg.Flags&FlagNoReplyExpected == 0 {
 | 
				
			||||||
 | 
							if ch == nil {
 | 
				
			||||||
 | 
								ch = make(chan *Call, 5)
 | 
				
			||||||
 | 
							} else if cap(ch) == 0 {
 | 
				
			||||||
 | 
								panic("dbus: unbuffered channel passed to (*Conn).Send")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							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
 | 
				
			||||||
 | 
							conn.callsLck.Lock()
 | 
				
			||||||
 | 
							conn.calls[msg.serial] = call
 | 
				
			||||||
 | 
							conn.callsLck.Unlock()
 | 
				
			||||||
 | 
							conn.outLck.RLock()
 | 
				
			||||||
 | 
							if conn.closed {
 | 
				
			||||||
 | 
								call.Err = ErrClosed
 | 
				
			||||||
 | 
								call.Done <- call
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								conn.out <- msg
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							conn.outLck.RUnlock()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							conn.outLck.RLock()
 | 
				
			||||||
 | 
							if conn.closed {
 | 
				
			||||||
 | 
								call = &Call{Err: ErrClosed}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								conn.out <- msg
 | 
				
			||||||
 | 
								call = &Call{Err: nil}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							conn.outLck.RUnlock()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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.serial = conn.getSerial()
 | 
				
			||||||
 | 
						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.outLck.RLock()
 | 
				
			||||||
 | 
						if !conn.closed {
 | 
				
			||||||
 | 
							conn.out <- msg
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn.outLck.RUnlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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.serial = conn.getSerial()
 | 
				
			||||||
 | 
						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.outLck.RLock()
 | 
				
			||||||
 | 
						if !conn.closed {
 | 
				
			||||||
 | 
							conn.out <- msg
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn.outLck.RUnlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (conn *Conn) defaultSignalAction(fn func(h *defaultSignalHandler, ch chan<- *Signal), ch chan<- *Signal) {
 | 
				
			||||||
 | 
						if !isDefaultSignalHandler(conn.signalHandler) {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						handler := conn.signalHandler.(*defaultSignalHandler)
 | 
				
			||||||
 | 
						fn(handler, ch)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Signal registers the given channel to be passed all received signal messages.
 | 
				
			||||||
 | 
					// The caller has to make sure that ch is sufficiently buffered; if a message
 | 
				
			||||||
 | 
					// arrives when a write to c is not possible, it is discarded.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Multiple of these channels can be registered at the same time.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// 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.
 | 
				
			||||||
 | 
					func (conn *Conn) Signal(ch chan<- *Signal) {
 | 
				
			||||||
 | 
						conn.defaultSignalAction((*defaultSignalHandler).addSignal, ch)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RemoveSignal removes the given channel from the list of the registered channels.
 | 
				
			||||||
 | 
					func (conn *Conn) RemoveSignal(ch chan<- *Signal) {
 | 
				
			||||||
 | 
						conn.defaultSignalAction((*defaultSignalHandler).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{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// dereferenceAll returns a slice that, assuming that vs is a slice of pointers
 | 
				
			||||||
 | 
					// of arbitrary types, containes the values that are obtained from dereferencing
 | 
				
			||||||
 | 
					// all elements in vs.
 | 
				
			||||||
 | 
					func dereferenceAll(vs []interface{}) []interface{} {
 | 
				
			||||||
 | 
						for i := range vs {
 | 
				
			||||||
 | 
							v := reflect.ValueOf(vs[i])
 | 
				
			||||||
 | 
							v = v.Elem()
 | 
				
			||||||
 | 
							vs[i] = v.Interface()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return vs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
								return keyValue[1]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								vendor/github.com/godbus/dbus/conn_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/godbus/dbus/conn_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										42
									
								
								vendor/github.com/godbus/dbus/conn_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/godbus/dbus/conn_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					// +build !darwin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const defaultSystemBusAddress = "unix:path=/var/run/dbus/system_bus_socket"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getSessionBusPlatformAddress() (string, error) {
 | 
				
			||||||
 | 
						cmd := exec.Command("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 {
 | 
				
			||||||
 | 
							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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getSystemBusPlatformAddress() string {
 | 
				
			||||||
 | 
						address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS")
 | 
				
			||||||
 | 
						if address != "" {
 | 
				
			||||||
 | 
							return fmt.Sprintf("unix:path=%s", address)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return defaultSystemBusAddress
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										427
									
								
								vendor/github.com/godbus/dbus/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										427
									
								
								vendor/github.com/godbus/dbus/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,427 @@
 | 
				
			|||||||
 | 
					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))
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
							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)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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.Struct:
 | 
				
			||||||
 | 
							return src == interfacesType
 | 
				
			||||||
 | 
						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()))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if dest.Len() != src.Len() {
 | 
				
			||||||
 | 
							return fmt.Errorf(
 | 
				
			||||||
 | 
								"dbus.Store: type mismatch: "+
 | 
				
			||||||
 | 
									"slices are different lengths "+
 | 
				
			||||||
 | 
									"need: %d have: %d",
 | 
				
			||||||
 | 
								src.Len(), dest.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 == '_'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										228
									
								
								vendor/github.com/godbus/dbus/decoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								vendor/github.com/godbus/dbus/decoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,228 @@
 | 
				
			|||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/binary"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type decoder struct {
 | 
				
			||||||
 | 
						in    io.Reader
 | 
				
			||||||
 | 
						order binary.ByteOrder
 | 
				
			||||||
 | 
						pos   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) *decoder {
 | 
				
			||||||
 | 
						dec := new(decoder)
 | 
				
			||||||
 | 
						dec.in = in
 | 
				
			||||||
 | 
						dec.order = order
 | 
				
			||||||
 | 
						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, 0)
 | 
				
			||||||
 | 
							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, 0)
 | 
				
			||||||
 | 
							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':
 | 
				
			||||||
 | 
							return UnixFDIndex(dec.decode("u", depth).(uint32))
 | 
				
			||||||
 | 
						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"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							length := dec.decode("u", depth).(uint32)
 | 
				
			||||||
 | 
							v := reflect.MakeSlice(reflect.SliceOf(typeFor(s[1:])), 0, int(length))
 | 
				
			||||||
 | 
							// Even for empty arrays, the correct padding must be included
 | 
				
			||||||
 | 
							dec.align(alignment(typeFor(s[1:])))
 | 
				
			||||||
 | 
							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, 0)
 | 
				
			||||||
 | 
								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})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A FormatError is an error in the wire format.
 | 
				
			||||||
 | 
					type FormatError string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e FormatError) Error() string {
 | 
				
			||||||
 | 
						return "dbus: wire format error: " + string(e)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										291
									
								
								vendor/github.com/godbus/dbus/default_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										291
									
								
								vendor/github.com/godbus/dbus/default_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,291 @@
 | 
				
			|||||||
 | 
					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.
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := ret[t.NumOut()-1].Interface().(*Error)
 | 
				
			||||||
 | 
						ret = ret[:t.NumOut()-1]
 | 
				
			||||||
 | 
						out := make([]interface{}, len(ret))
 | 
				
			||||||
 | 
						for i, val := range ret {
 | 
				
			||||||
 | 
							out[i] = val.Interface()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if 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 {
 | 
				
			||||||
 | 
						interfaces map[string]*exportedIntf
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (obj *exportedObj) LookupInterface(name string) (Interface, bool) {
 | 
				
			||||||
 | 
						if name == "" {
 | 
				
			||||||
 | 
							return obj, true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						intf, exists := obj.interfaces[name]
 | 
				
			||||||
 | 
						return intf, exists
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (obj *exportedObj) AddInterface(name string, iface *exportedIntf) {
 | 
				
			||||||
 | 
						obj.interfaces[name] = iface
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (obj *exportedObj) DeleteInterface(name string) {
 | 
				
			||||||
 | 
						delete(obj.interfaces, name)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (obj *exportedObj) LookupMethod(name string) (Method, bool) {
 | 
				
			||||||
 | 
						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.
 | 
				
			||||||
 | 
					func NewDefaultSignalHandler() *defaultSignalHandler {
 | 
				
			||||||
 | 
						return &defaultSignalHandler{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isDefaultSignalHandler(handler SignalHandler) bool {
 | 
				
			||||||
 | 
						_, ok := handler.(*defaultSignalHandler)
 | 
				
			||||||
 | 
						return ok
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type defaultSignalHandler struct {
 | 
				
			||||||
 | 
						sync.RWMutex
 | 
				
			||||||
 | 
						closed  bool
 | 
				
			||||||
 | 
						signals []chan<- *Signal
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sh *defaultSignalHandler) DeliverSignal(intf, name string, signal *Signal) {
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							sh.RLock()
 | 
				
			||||||
 | 
							defer sh.RUnlock()
 | 
				
			||||||
 | 
							if sh.closed {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, ch := range sh.signals {
 | 
				
			||||||
 | 
								ch <- signal
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sh *defaultSignalHandler) Init() error {
 | 
				
			||||||
 | 
						sh.Lock()
 | 
				
			||||||
 | 
						sh.signals = make([]chan<- *Signal, 0)
 | 
				
			||||||
 | 
						sh.Unlock()
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sh *defaultSignalHandler) Terminate() {
 | 
				
			||||||
 | 
						sh.Lock()
 | 
				
			||||||
 | 
						sh.closed = true
 | 
				
			||||||
 | 
						for _, ch := range sh.signals {
 | 
				
			||||||
 | 
							close(ch)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sh.signals = nil
 | 
				
			||||||
 | 
						sh.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sh *defaultSignalHandler) addSignal(ch chan<- *Signal) {
 | 
				
			||||||
 | 
						sh.Lock()
 | 
				
			||||||
 | 
						defer sh.Unlock()
 | 
				
			||||||
 | 
						if sh.closed {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sh.signals = append(sh.signals, ch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sh *defaultSignalHandler) removeSignal(ch chan<- *Signal) {
 | 
				
			||||||
 | 
						sh.Lock()
 | 
				
			||||||
 | 
						defer sh.Unlock()
 | 
				
			||||||
 | 
						if sh.closed {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := len(sh.signals) - 1; i >= 0; i-- {
 | 
				
			||||||
 | 
							if ch == sh.signals[i] {
 | 
				
			||||||
 | 
								copy(sh.signals[i:], sh.signals[i+1:])
 | 
				
			||||||
 | 
								sh.signals[len(sh.signals)-1] = nil
 | 
				
			||||||
 | 
								sh.signals = sh.signals[:len(sh.signals)-1]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										69
									
								
								vendor/github.com/godbus/dbus/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/godbus/dbus/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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. 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. 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. Similarily, the indices
 | 
				
			||||||
 | 
					of incoming messages are automatically resolved. It shouldn't be necessary to use
 | 
				
			||||||
 | 
					UnixFDIndex.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package dbus
 | 
				
			||||||
							
								
								
									
										210
									
								
								vendor/github.com/godbus/dbus/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								vendor/github.com/godbus/dbus/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,210 @@
 | 
				
			|||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"encoding/binary"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// An encoder encodes values to the D-Bus wire format.
 | 
				
			||||||
 | 
					type encoder struct {
 | 
				
			||||||
 | 
						out   io.Writer
 | 
				
			||||||
 | 
						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) *encoder {
 | 
				
			||||||
 | 
						return newEncoderAtOffset(out, 0, order)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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) *encoder {
 | 
				
			||||||
 | 
						enc := new(encoder)
 | 
				
			||||||
 | 
						enc.out = out
 | 
				
			||||||
 | 
						enc.order = order
 | 
				
			||||||
 | 
						enc.pos = offset
 | 
				
			||||||
 | 
						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 underyling 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) {
 | 
				
			||||||
 | 
						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:
 | 
				
			||||||
 | 
							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:
 | 
				
			||||||
 | 
							enc.encode(reflect.ValueOf(uint32(len(v.String()))), depth)
 | 
				
			||||||
 | 
							b := make([]byte, v.Len()+1)
 | 
				
			||||||
 | 
							copy(b, v.String())
 | 
				
			||||||
 | 
							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:
 | 
				
			||||||
 | 
							if depth >= 64 {
 | 
				
			||||||
 | 
								panic(FormatError("input exceeds container depth limit"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for i := 0; i < v.Len(); i++ {
 | 
				
			||||||
 | 
								bufenc.encode(v.Index(i), depth+1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							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:
 | 
				
			||||||
 | 
							if depth >= 64 && v.Type() != signatureType {
 | 
				
			||||||
 | 
								panic(FormatError("input exceeds container depth limit"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch t := v.Type(); t {
 | 
				
			||||||
 | 
							case signatureType:
 | 
				
			||||||
 | 
								str := v.Field(0)
 | 
				
			||||||
 | 
								enc.encode(reflect.ValueOf(byte(str.Len())), depth+1)
 | 
				
			||||||
 | 
								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 depth >= 63 {
 | 
				
			||||||
 | 
								panic(FormatError("input exceeds container depth limit"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							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)
 | 
				
			||||||
 | 
							for _, k := range keys {
 | 
				
			||||||
 | 
								bufenc.align(8)
 | 
				
			||||||
 | 
								bufenc.encode(k, depth+2)
 | 
				
			||||||
 | 
								bufenc.encode(v.MapIndex(k), depth+2)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							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()})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										413
									
								
								vendor/github.com/godbus/dbus/export.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										413
									
								
								vendor/github.com/godbus/dbus/export.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,413 @@
 | 
				
			|||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"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 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 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 ifaceName == "org.freedesktop.DBus.Peer" {
 | 
				
			||||||
 | 
							switch name {
 | 
				
			||||||
 | 
							case "Ping":
 | 
				
			||||||
 | 
								conn.sendReply(sender, serial)
 | 
				
			||||||
 | 
							case "GetMachineId":
 | 
				
			||||||
 | 
								conn.sendReply(sender, serial, conn.uuid)
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								conn.sendError(ErrMsgUnknownMethod, sender, serial)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(name) == 0 {
 | 
				
			||||||
 | 
							conn.sendError(ErrMsgUnknownMethod, sender, serial)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						object, ok := conn.handler.LookupObject(path)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							conn.sendError(ErrMsgNoObject, sender, serial)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iface, exists := object.LookupInterface(ifaceName)
 | 
				
			||||||
 | 
						if !exists {
 | 
				
			||||||
 | 
							conn.sendError(ErrMsgUnknownInterface, sender, serial)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m, exists := iface.LookupMethod(name)
 | 
				
			||||||
 | 
						if !exists {
 | 
				
			||||||
 | 
							conn.sendError(ErrMsgUnknownMethod, 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.serial = conn.getSerial()
 | 
				
			||||||
 | 
							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...))
 | 
				
			||||||
 | 
							conn.outLck.RLock()
 | 
				
			||||||
 | 
							if !conn.closed {
 | 
				
			||||||
 | 
								conn.out <- reply
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							conn.outLck.RUnlock()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
						if !path.IsValid() {
 | 
				
			||||||
 | 
							return errors.New("dbus: invalid object path")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						i := strings.LastIndex(name, ".")
 | 
				
			||||||
 | 
						if i == -1 {
 | 
				
			||||||
 | 
							return errors.New("dbus: invalid method name")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						iface := name[:i]
 | 
				
			||||||
 | 
						member := name[i+1:]
 | 
				
			||||||
 | 
						if !isValidMember(member) {
 | 
				
			||||||
 | 
							return errors.New("dbus: invalid method name")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !isValidInterface(iface) {
 | 
				
			||||||
 | 
							return errors.New("dbus: invalid interface name")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						msg := new(Message)
 | 
				
			||||||
 | 
						msg.Type = TypeSignal
 | 
				
			||||||
 | 
						msg.serial = conn.getSerial()
 | 
				
			||||||
 | 
						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...))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn.outLck.RLock()
 | 
				
			||||||
 | 
						defer conn.outLck.RUnlock()
 | 
				
			||||||
 | 
						if conn.closed {
 | 
				
			||||||
 | 
							return ErrClosed
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn.out <- msg
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// exportWithMap 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 hander handler have %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
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										28
									
								
								vendor/github.com/godbus/dbus/homedir.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/godbus/dbus/homedir.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						homeDir     string
 | 
				
			||||||
 | 
						homeDirLock sync.Mutex
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getHomeDir() string {
 | 
				
			||||||
 | 
						homeDirLock.Lock()
 | 
				
			||||||
 | 
						defer homeDirLock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if homeDir != "" {
 | 
				
			||||||
 | 
							return homeDir
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						homeDir = os.Getenv("HOME")
 | 
				
			||||||
 | 
						if homeDir != "" {
 | 
				
			||||||
 | 
							return homeDir
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						homeDir = lookupHomeDir()
 | 
				
			||||||
 | 
						return homeDir
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								vendor/github.com/godbus/dbus/homedir_dynamic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/godbus/dbus/homedir_dynamic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					// +build !static_build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os/user"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func lookupHomeDir() string {
 | 
				
			||||||
 | 
						u, err := user.Current()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "/"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return u.HomeDir
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								vendor/github.com/godbus/dbus/homedir_static.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								vendor/github.com/godbus/dbus/homedir_static.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					// +build static_build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func lookupHomeDir() string {
 | 
				
			||||||
 | 
						myUid := os.Getuid()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f, err := os.Open("/etc/passwd")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "/"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s := bufio.NewScanner(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for s.Scan() {
 | 
				
			||||||
 | 
							if err := s.Err(); err != nil {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							line := strings.TrimSpace(s.Text())
 | 
				
			||||||
 | 
							if line == "" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							parts := strings.Split(line, ":")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if len(parts) >= 6 {
 | 
				
			||||||
 | 
								uid, err := strconv.Atoi(parts[2])
 | 
				
			||||||
 | 
								if err == nil && uid == myUid {
 | 
				
			||||||
 | 
									return parts[5]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Default to / if we can't get a better value
 | 
				
			||||||
 | 
						return "/"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										353
									
								
								vendor/github.com/godbus/dbus/message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								vendor/github.com/godbus/dbus/message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,353 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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) {
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
							vs, err := dec.Decode(sig)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msg.Body = vs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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) error {
 | 
				
			||||||
 | 
						if err := msg.IsValid(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var vs [7]interface{}
 | 
				
			||||||
 | 
						switch order {
 | 
				
			||||||
 | 
						case binary.LittleEndian:
 | 
				
			||||||
 | 
							vs[0] = byte('l')
 | 
				
			||||||
 | 
						case binary.BigEndian:
 | 
				
			||||||
 | 
							vs[0] = byte('B')
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return errors.New("dbus: invalid byte order")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						body := new(bytes.Buffer)
 | 
				
			||||||
 | 
						enc := newEncoder(body, order)
 | 
				
			||||||
 | 
						if len(msg.Body) != 0 {
 | 
				
			||||||
 | 
							enc.Encode(msg.Body...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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.Encode(vs[:]...)
 | 
				
			||||||
 | 
						enc.align(8)
 | 
				
			||||||
 | 
						body.WriteTo(&buf)
 | 
				
			||||||
 | 
						if buf.Len() > 1<<27 {
 | 
				
			||||||
 | 
							return InvalidMessageError("message is too long")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, err := buf.WriteTo(out); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsValid checks whether msg is a valid message and returns an
 | 
				
			||||||
 | 
					// InvalidMessageError if it is not.
 | 
				
			||||||
 | 
					func (msg *Message) IsValid() 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										147
									
								
								vendor/github.com/godbus/dbus/object.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								vendor/github.com/godbus/dbus/object.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,147 @@
 | 
				
			|||||||
 | 
					package dbus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"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
 | 
				
			||||||
 | 
						Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call
 | 
				
			||||||
 | 
						GetProperty(p string) (Variant, 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.Go(method, flags, make(chan *Call, 1), args...).Done
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddMatchSignal subscribes BusObject to signals from specified interface and
 | 
				
			||||||
 | 
					// method (member).
 | 
				
			||||||
 | 
					func (o *Object) AddMatchSignal(iface, member string) *Call {
 | 
				
			||||||
 | 
						return o.Call(
 | 
				
			||||||
 | 
							"org.freedesktop.DBus.AddMatch",
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
							"type='signal',interface='"+iface+"',member='"+member+"'",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
						iface := ""
 | 
				
			||||||
 | 
						i := strings.LastIndex(method, ".")
 | 
				
			||||||
 | 
						if i != -1 {
 | 
				
			||||||
 | 
							iface = method[:i]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						method = method[i+1:]
 | 
				
			||||||
 | 
						msg := new(Message)
 | 
				
			||||||
 | 
						msg.Type = TypeMethodCall
 | 
				
			||||||
 | 
						msg.serial = o.conn.getSerial()
 | 
				
			||||||
 | 
						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...))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if msg.Flags&FlagNoReplyExpected == 0 {
 | 
				
			||||||
 | 
							if ch == nil {
 | 
				
			||||||
 | 
								ch = make(chan *Call, 10)
 | 
				
			||||||
 | 
							} else if cap(ch) == 0 {
 | 
				
			||||||
 | 
								panic("dbus: unbuffered channel passed to (*Object).Go")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							call := &Call{
 | 
				
			||||||
 | 
								Destination: o.dest,
 | 
				
			||||||
 | 
								Path:        o.path,
 | 
				
			||||||
 | 
								Method:      method,
 | 
				
			||||||
 | 
								Args:        args,
 | 
				
			||||||
 | 
								Done:        ch,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							o.conn.callsLck.Lock()
 | 
				
			||||||
 | 
							o.conn.calls[msg.serial] = call
 | 
				
			||||||
 | 
							o.conn.callsLck.Unlock()
 | 
				
			||||||
 | 
							o.conn.outLck.RLock()
 | 
				
			||||||
 | 
							if o.conn.closed {
 | 
				
			||||||
 | 
								call.Err = ErrClosed
 | 
				
			||||||
 | 
								call.Done <- call
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								o.conn.out <- msg
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							o.conn.outLck.RUnlock()
 | 
				
			||||||
 | 
							return call
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						o.conn.outLck.RLock()
 | 
				
			||||||
 | 
						defer o.conn.outLck.RUnlock()
 | 
				
			||||||
 | 
						done := make(chan *Call, 1)
 | 
				
			||||||
 | 
						call := &Call{
 | 
				
			||||||
 | 
							Err:  nil,
 | 
				
			||||||
 | 
							Done: done,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							call.Done <- call
 | 
				
			||||||
 | 
							close(done)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						if o.conn.closed {
 | 
				
			||||||
 | 
							call.Err = ErrClosed
 | 
				
			||||||
 | 
							return call
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						o.conn.out <- msg
 | 
				
			||||||
 | 
						return call
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetProperty calls org.freedesktop.DBus.Properties.GetProperty on the given
 | 
				
			||||||
 | 
					// object. The property name must be given in interface.member notation.
 | 
				
			||||||
 | 
					func (o *Object) GetProperty(p string) (Variant, error) {
 | 
				
			||||||
 | 
						idx := strings.LastIndex(p, ".")
 | 
				
			||||||
 | 
						if idx == -1 || idx+1 == len(p) {
 | 
				
			||||||
 | 
							return Variant{}, errors.New("dbus: invalid property " + p)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iface := p[:idx]
 | 
				
			||||||
 | 
						prop := p[idx+1:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result := Variant{}
 | 
				
			||||||
 | 
						err := o.Call("org.freedesktop.DBus.Properties.Get", 0, iface, prop).Store(&result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return Variant{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										89
									
								
								vendor/github.com/godbus/dbus/server_interfaces.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								vendor/github.com/godbus/dbus/server_interfaces.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					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 incase 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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										259
									
								
								vendor/github.com/godbus/dbus/sig.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								vendor/github.com/godbus/dbus/sig.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,259 @@
 | 
				
			|||||||
 | 
					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))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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)}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getSignature returns the signature of the given type and panics on unknown types.
 | 
				
			||||||
 | 
					func getSignature(t reflect.Type) string {
 | 
				
			||||||
 | 
						// 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())
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return "(" + s + ")"
 | 
				
			||||||
 | 
						case reflect.Array, reflect.Slice:
 | 
				
			||||||
 | 
							return "a" + getSignature(t.Elem())
 | 
				
			||||||
 | 
						case reflect.Map:
 | 
				
			||||||
 | 
							if !isKeyType(t.Key()) {
 | 
				
			||||||
 | 
								panic(InvalidTypeError{t})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
 | 
				
			||||||
 | 
						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, 0)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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 retruns 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, 0)
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 int) (err error, rem string) {
 | 
				
			||||||
 | 
						if s == "" {
 | 
				
			||||||
 | 
							return SignatureError{Sig: s, Reason: "empty signature"}, ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if depth > 64 {
 | 
				
			||||||
 | 
							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+1); err != nil {
 | 
				
			||||||
 | 
									return err, ""
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								err, nr := validSingle(s[1:], depth+1)
 | 
				
			||||||
 | 
								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+1)
 | 
				
			||||||
 | 
						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+1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							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, 0)
 | 
				
			||||||
 | 
						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/transport_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/godbus/dbus/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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										50
									
								
								vendor/github.com/godbus/dbus/transport_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								vendor/github.com/godbus/dbus/transport_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					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 {
 | 
				
			||||||
 | 
						for _, v := range msg.Body {
 | 
				
			||||||
 | 
							if _, ok := v.(UnixFD); ok {
 | 
				
			||||||
 | 
								return errors.New("dbus: unix fd passing not enabled")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return msg.EncodeTo(t, nativeEndian)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								vendor/github.com/godbus/dbus/transport_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								vendor/github.com/godbus/dbus/transport_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					//+build !windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										196
									
								
								vendor/github.com/godbus/dbus/transport_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								vendor/github.com/godbus/dbus/transport_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,196 @@
 | 
				
			|||||||
 | 
					//+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
 | 
				
			||||||
 | 
						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.
 | 
				
			||||||
 | 
						rd := &oobReader{conn: t.UnixConn}
 | 
				
			||||||
 | 
						// 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(rd, 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, headerdata[4:]); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dec := newDecoder(bytes.NewBuffer(headerdata), order)
 | 
				
			||||||
 | 
						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(rd, 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(rd.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 := DecodeMessage(bytes.NewBuffer(all))
 | 
				
			||||||
 | 
							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 {
 | 
				
			||||||
 | 
								if j, ok := v.(UnixFDIndex); ok {
 | 
				
			||||||
 | 
									if uint32(j) >= unixfds {
 | 
				
			||||||
 | 
										return nil, InvalidMessageError("invalid index for unix fd")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									msg.Body[i] = UnixFD(fds[j])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return msg, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return DecodeMessage(bytes.NewBuffer(all))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *unixTransport) SendMessage(msg *Message) error {
 | 
				
			||||||
 | 
						fds := make([]int, 0)
 | 
				
			||||||
 | 
						for i, v := range msg.Body {
 | 
				
			||||||
 | 
							if fd, ok := v.(UnixFD); ok {
 | 
				
			||||||
 | 
								msg.Body[i] = UnixFDIndex(len(fds))
 | 
				
			||||||
 | 
								fds = append(fds, int(fd))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(fds) != 0 {
 | 
				
			||||||
 | 
							if !t.hasUnixFDs {
 | 
				
			||||||
 | 
								return errors.New("dbus: unix fd passing not enabled")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds)))
 | 
				
			||||||
 | 
							oob := syscall.UnixRights(fds...)
 | 
				
			||||||
 | 
							buf := new(bytes.Buffer)
 | 
				
			||||||
 | 
							msg.EncodeTo(buf, nativeEndian)
 | 
				
			||||||
 | 
							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 nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *unixTransport) SupportsUnixFDs() bool {
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										95
									
								
								vendor/github.com/godbus/dbus/transport_unixcred_dragonfly.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								vendor/github.com/godbus/dbus/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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										91
									
								
								vendor/github.com/godbus/dbus/transport_unixcred_freebsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/godbus/dbus/transport_unixcred_freebsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					// 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/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/transport_unixcred_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/godbus/dbus/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/transport_unixcred_openbsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/godbus/dbus/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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										144
									
								
								vendor/github.com/godbus/dbus/variant.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								vendor/github.com/godbus/dbus/variant.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					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/unstable/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
 | 
				
			||||||
 | 
					// unambigously.
 | 
				
			||||||
 | 
					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/unstable/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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										284
									
								
								vendor/github.com/godbus/dbus/variant_lexer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								vendor/github.com/godbus/dbus/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.IndexRune(valid, l.next()) >= 0 {
 | 
				
			||||||
 | 
							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.IndexRune(digits, l.next()) >= 0 {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						l.backup()
 | 
				
			||||||
 | 
						if l.accept(".") {
 | 
				
			||||||
 | 
							for strings.IndexRune(digits, l.next()) >= 0 {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							l.backup()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if l.accept("eE") {
 | 
				
			||||||
 | 
							l.accept("+-")
 | 
				
			||||||
 | 
							for strings.IndexRune("0123456789", l.next()) >= 0 {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							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/variant_parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										817
									
								
								vendor/github.com/godbus/dbus/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()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										112
									
								
								vendor/github.com/sticreations/spotigopher/spotigopher/spotigopher.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								vendor/github.com/sticreations/spotigopher/spotigopher/spotigopher.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					package spotigopher
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/godbus/dbus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SpotifyClient struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Info holds all available Information we get over the dbus
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					type Info struct {
 | 
				
			||||||
 | 
						Artist      []string
 | 
				
			||||||
 | 
						Title       string
 | 
				
			||||||
 | 
						Album       string
 | 
				
			||||||
 | 
						Rating      string
 | 
				
			||||||
 | 
						TrackID     string
 | 
				
			||||||
 | 
						TrackNumber int32
 | 
				
			||||||
 | 
						URL         string
 | 
				
			||||||
 | 
						ArtworkURL  string
 | 
				
			||||||
 | 
						Status      string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var sdbus dbus.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					NewClient returns an Instance of Spotify Cleint
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func NewClient() SpotifyClient {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client := SpotifyClient{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return client
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getSpotifyBus() dbus.BusObject {
 | 
				
			||||||
 | 
						con, err := dbus.SessionBus()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Could not get SessionBus: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						//TODO: Test what happens when Spotify is Closed!
 | 
				
			||||||
 | 
						spotifyBus := con.Object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")
 | 
				
			||||||
 | 
						return spotifyBus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					PlayPause sends a PlayPause Command on the DBus
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func (s *SpotifyClient) PlayPause() {
 | 
				
			||||||
 | 
						sendAction("org.mpris.MediaPlayer2.Player.PlayPause")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Next sends a Next Command on the DBus
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func (s *SpotifyClient) Next() {
 | 
				
			||||||
 | 
						sendAction("org.mpris.MediaPlayer2.Player.Next")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Previous sends a Previous Command on the DBus
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func (s *SpotifyClient) Previous() {
 | 
				
			||||||
 | 
						sendAction("org.mpris.MediaPlayer2.Player.Previous")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Stop sends a Stop Command on the DBus
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func (s *SpotifyClient) Stop() {
 | 
				
			||||||
 | 
						sendAction("org.mpris.MediaPlayer2.Player.Stop")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					GetInfo returns all Spotify related Information, when Spotify is running
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func (s *SpotifyClient) GetInfo() (Info, error) {
 | 
				
			||||||
 | 
						info := Info{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spotifyBus := getSpotifyBus()
 | 
				
			||||||
 | 
						props, err := spotifyBus.GetProperty("org.mpris.MediaPlayer2.Player.Metadata")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return Info{}, errors.New("Could not get any Info from Spotify. Are you sure Spotify is running?")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						songData := props.Value().(map[string]dbus.Variant)
 | 
				
			||||||
 | 
						info.TrackID = songData["mpris:trackid"].Value().(string)
 | 
				
			||||||
 | 
						info.Artist = songData["xesam:artist"].Value().([]string)
 | 
				
			||||||
 | 
						info.Title = songData["xesam:title"].Value().(string)
 | 
				
			||||||
 | 
						info.Album = songData["xesam:album"].Value().(string)
 | 
				
			||||||
 | 
						info.TrackNumber = songData["xesam:trackNumber"].Value().(int32)
 | 
				
			||||||
 | 
						info.URL = songData["xesam:url"].Value().(string)
 | 
				
			||||||
 | 
						info.ArtworkURL = songData["mpris:artUrl"].Value().(string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status, err := spotifyBus.GetProperty("org.mpris.MediaPlayer2.Player.PlaybackStatus")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Could not get Playback Status : %v", err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						info.Status = status.Value().(string)
 | 
				
			||||||
 | 
						return info, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sendAction(method string) error {
 | 
				
			||||||
 | 
						sdbus := getSpotifyBus()
 | 
				
			||||||
 | 
						call := sdbus.Call(method, 0)
 | 
				
			||||||
 | 
						return call.Err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user