Merge pull request #1376 from Zyqsempai/add-cgroups-v2-metrics
Cgroupv2: Added CPU, Memory metrics
This commit is contained in:
		| @@ -19,8 +19,11 @@ limitations under the License. | ||||
| package server | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/containerd/containerd/api/types" | ||||
| 	v1 "github.com/containerd/containerd/metrics/types/v1" | ||||
| 	v2 "github.com/containerd/containerd/metrics/types/v2" | ||||
| 	"github.com/containerd/typeurl" | ||||
| 	"github.com/pkg/errors" | ||||
| 	runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" | ||||
| @@ -61,20 +64,39 @@ func (c *criService) containerMetrics( | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrap(err, "failed to extract container metrics") | ||||
| 		} | ||||
| 		metrics := s.(*v1.Metrics) | ||||
| 		if metrics.CPU != nil && metrics.CPU.Usage != nil { | ||||
| 			cs.Cpu = &runtime.CpuUsage{ | ||||
| 				Timestamp:            stats.Timestamp.UnixNano(), | ||||
| 				UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.Usage.Total}, | ||||
| 		switch metrics := s.(type) { | ||||
| 		case *v1.Metrics: | ||||
| 			if metrics.CPU != nil && metrics.CPU.Usage != nil { | ||||
| 				cs.Cpu = &runtime.CpuUsage{ | ||||
| 					Timestamp:            stats.Timestamp.UnixNano(), | ||||
| 					UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.Usage.Total}, | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if metrics.Memory != nil && metrics.Memory.Usage != nil { | ||||
| 			cs.Memory = &runtime.MemoryUsage{ | ||||
| 				Timestamp: stats.Timestamp.UnixNano(), | ||||
| 				WorkingSetBytes: &runtime.UInt64Value{ | ||||
| 					Value: getWorkingSet(metrics.Memory), | ||||
| 				}, | ||||
| 			if metrics.Memory != nil && metrics.Memory.Usage != nil { | ||||
| 				cs.Memory = &runtime.MemoryUsage{ | ||||
| 					Timestamp: stats.Timestamp.UnixNano(), | ||||
| 					WorkingSetBytes: &runtime.UInt64Value{ | ||||
| 						Value: getWorkingSet(metrics.Memory), | ||||
| 					}, | ||||
| 				} | ||||
| 			} | ||||
| 		case *v2.Metrics: | ||||
| 			if metrics.CPU != nil { | ||||
| 				cs.Cpu = &runtime.CpuUsage{ | ||||
| 					Timestamp:            stats.Timestamp.UnixNano(), | ||||
| 					UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.UsageUsec * 1000}, | ||||
| 				} | ||||
| 			} | ||||
| 			if metrics.Memory != nil { | ||||
| 				cs.Memory = &runtime.MemoryUsage{ | ||||
| 					Timestamp: stats.Timestamp.UnixNano(), | ||||
| 					WorkingSetBytes: &runtime.UInt64Value{ | ||||
| 						Value: getWorkingSetV2(metrics.Memory), | ||||
| 					}, | ||||
| 				} | ||||
| 			} | ||||
| 		default: | ||||
| 			return &cs, errors.New(fmt.Sprintf("unxpected metrics type: %v", metrics)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -94,3 +116,14 @@ func getWorkingSet(memory *v1.MemoryStat) uint64 { | ||||
| 	} | ||||
| 	return workingSet | ||||
| } | ||||
|  | ||||
| // getWorkingSetV2 calculates workingset memory from cgroupv2 memory stats. | ||||
| // The caller should make sure memory is not nil. | ||||
| // workingset = usage - inactive_file | ||||
| func getWorkingSetV2(memory *v2.MemoryStat) uint64 { | ||||
| 	var workingSet uint64 | ||||
| 	if memory.InactiveFile < memory.Usage { | ||||
| 		workingSet = memory.Usage - memory.InactiveFile | ||||
| 	} | ||||
| 	return workingSet | ||||
| } | ||||
|   | ||||
							
								
								
									
										10
									
								
								vendor.conf
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								vendor.conf
									
									
									
									
									
								
							| @@ -34,21 +34,21 @@ github.com/google/uuid 0cd6bf5da1e1c83f8b45653022c74f71af0538a4 # v1.1.1 | ||||
| github.com/golang/protobuf aa810b61a9c79d51363740d207bb46cf8e620ed5 # v1.2.0 | ||||
| github.com/gogo/protobuf ba06b47c162d49f2af050fb4c75bcbc86a159d5c # v1.2.1 | ||||
| github.com/gogo/googleapis d31c731455cb061f42baff3bda55bad0118b126b # v1.2.0 | ||||
| github.com/godbus/dbus c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f | ||||
| github.com/godbus/dbus/v5 37bf87eef99d69c4f1d3528bd66e3a87dc201472 # v5.0.3 | ||||
| github.com/docker/go-units 519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0 | ||||
| github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098 | ||||
| github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 | ||||
| github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6 | ||||
| github.com/coreos/go-systemd/v22 2d78030078ef61b3cae27f42ad6d0e46db51b339 # v22.0.0 | ||||
| github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 | ||||
| github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f | ||||
| github.com/containerd/go-runc a5c2862aed5e6358b305b0e16bfce58e0549b1cd | ||||
| github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13 | ||||
| github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c | ||||
| github.com/containerd/containerd 0a1f2b40642e54ed06cd0a22cdf6025cbe70853c | ||||
| github.com/containerd/containerd e1221e69a824ce9aaca34c5bb603feb2f921b883 | ||||
| github.com/containerd/console 8375c3424e4d7b114e8a90a4a40c8e1b40d1d4e6 | ||||
| github.com/containerd/cgroups fada802a7909d430bd17126fd6e4bbf5716f2bcd | ||||
| github.com/containerd/cgroups 7347743e5d1e8500d9f27c8e748e689ed991d92b | ||||
| github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 | ||||
| github.com/Microsoft/hcsshim d2849cbdb9dfe5f513292a9610ca2eb734cdd1e7 | ||||
| github.com/Microsoft/hcsshim b3f49c06ffaeef24d09c6c08ec8ec8425a0303e2 # v0.8.7 | ||||
| github.com/Microsoft/go-winio 6c72808b55902eae4c5943626030429ff20f3b63 # v0.4.14 | ||||
| github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1 | ||||
| github.com/cpuguy83/go-md2man 7762f7e404f8416dfa1d9bb6a8c192aa9acb4d19 # v1.0.10 | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/Microsoft/hcsshim/container.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/Microsoft/hcsshim/container.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -196,7 +196,7 @@ func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskContr | ||||
|  | ||||
| // CreateProcess launches a new process within the container. | ||||
| func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { | ||||
| 	p, err := container.system.CreateProcessNoStdio(c) | ||||
| 	p, err := container.system.CreateProcess(context.Background(), c) | ||||
| 	if err != nil { | ||||
| 		return nil, convertSystemError(err, container) | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/Microsoft/hcsshim/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/Microsoft/hcsshim/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| module github.com/Microsoft/hcsshim | ||||
|  | ||||
| go 1.12 | ||||
| go 1.13 | ||||
|  | ||||
| require ( | ||||
| 	github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 | ||||
|   | ||||
							
								
								
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/hcn/hcn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/hcn/hcn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -161,6 +161,33 @@ func DSRSupported() error { | ||||
| 	return platformDoesNotSupportError("Direct Server Return (DSR)") | ||||
| } | ||||
|  | ||||
| // Slash32EndpointPrefixesSupported returns an error if the HCN version does not support configuring endpoints with /32 prefixes. | ||||
| func Slash32EndpointPrefixesSupported() error { | ||||
| 	supported := GetSupportedFeatures() | ||||
| 	if supported.Slash32EndpointPrefixes { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return platformDoesNotSupportError("Slash 32 Endpoint prefixes") | ||||
| } | ||||
|  | ||||
| // AclSupportForProtocol252Supported returns an error if the HCN version does not support HNS ACL Policies to support protocol 252 for VXLAN. | ||||
| func AclSupportForProtocol252Supported() error { | ||||
| 	supported := GetSupportedFeatures() | ||||
| 	if supported.AclSupportForProtocol252 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return platformDoesNotSupportError("HNS ACL Policies to support protocol 252 for VXLAN") | ||||
| } | ||||
|  | ||||
| // SessionAffinitySupported returns an error if the HCN version does not support Session Affinity. | ||||
| func SessionAffinitySupported() error { | ||||
| 	supported := GetSupportedFeatures() | ||||
| 	if supported.SessionAffinity { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return platformDoesNotSupportError("Session Affinity") | ||||
| } | ||||
|  | ||||
| // RequestType are the different operations performed to settings. | ||||
| // Used to update the settings of Endpoint/Namespace objects. | ||||
| type RequestType string | ||||
|   | ||||
							
								
								
									
										30
									
								
								vendor/github.com/Microsoft/hcsshim/hcn/hcnglobals.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/Microsoft/hcsshim/hcn/hcnglobals.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,6 +3,7 @@ package hcn | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"math" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| @@ -20,17 +21,36 @@ type Version struct { | ||||
| 	Minor int `json:"Minor"` | ||||
| } | ||||
|  | ||||
| type VersionRange struct { | ||||
| 	MinVersion Version | ||||
| 	MaxVersion Version | ||||
| } | ||||
|  | ||||
| type VersionRanges []VersionRange | ||||
|  | ||||
| var ( | ||||
| 	// HNSVersion1803 added ACL functionality. | ||||
| 	HNSVersion1803 = Version{Major: 7, Minor: 2} | ||||
| 	HNSVersion1803 = VersionRanges{VersionRange{MinVersion: Version{Major: 7, Minor: 2}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}} | ||||
| 	// V2ApiSupport allows the use of V2 Api calls and V2 Schema. | ||||
| 	V2ApiSupport = Version{Major: 9, Minor: 2} | ||||
| 	V2ApiSupport = VersionRanges{VersionRange{MinVersion: Version{Major: 9, Minor: 2}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}} | ||||
| 	// Remote Subnet allows for Remote Subnet policies on Overlay networks | ||||
| 	RemoteSubnetVersion = Version{Major: 9, Minor: 2} | ||||
| 	RemoteSubnetVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 9, Minor: 2}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}} | ||||
| 	// A Host Route policy allows for local container to local host communication Overlay networks | ||||
| 	HostRouteVersion = Version{Major: 9, Minor: 2} | ||||
| 	HostRouteVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 9, Minor: 2}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}} | ||||
| 	// HNS 10.2 allows for Direct Server Return for loadbalancing | ||||
| 	DSRVersion = Version{Major: 10, Minor: 2} | ||||
| 	DSRVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 10, Minor: 2}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}} | ||||
| 	// HNS 9.3 through 10.0 (not included) and, 10.4+ provide support for configuring endpoints with /32 prefixes | ||||
| 	Slash32EndpointPrefixesVersion = VersionRanges{ | ||||
| 		VersionRange{MinVersion: Version{Major: 9, Minor: 3}, MaxVersion: Version{Major: 9, Minor: math.MaxInt32}}, | ||||
| 		VersionRange{MinVersion: Version{Major: 10, Minor: 4}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}, | ||||
| 	} | ||||
| 	// HNS 9.3 through 10.0 (not included) and, 10.4+ allow for HNS ACL Policies to support protocol 252 for VXLAN | ||||
| 	AclSupportForProtocol252Version = VersionRanges{ | ||||
| 		VersionRange{MinVersion: Version{Major: 9, Minor: 3}, MaxVersion: Version{Major: 9, Minor: math.MaxInt32}}, | ||||
| 		VersionRange{MinVersion: Version{Major: 10, Minor: 4}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}, | ||||
| 	} | ||||
| 	// HNS 11.10 allows for session affinity for loadbalancing | ||||
| 	SessionAffinityVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 11, Minor: 10}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}} | ||||
| ) | ||||
|  | ||||
| // GetGlobals returns the global properties of the HCN Service. | ||||
|   | ||||
							
								
								
									
										21
									
								
								vendor/github.com/Microsoft/hcsshim/hcn/hcnloadbalancer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/Microsoft/hcsshim/hcn/hcnloadbalancer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -10,10 +10,11 @@ import ( | ||||
|  | ||||
| // LoadBalancerPortMapping is associated with HostComputeLoadBalancer | ||||
| type LoadBalancerPortMapping struct { | ||||
| 	Protocol     uint32                       `json:",omitempty"` // EX: TCP = 6, UDP = 17 | ||||
| 	InternalPort uint16                       `json:",omitempty"` | ||||
| 	ExternalPort uint16                       `json:",omitempty"` | ||||
| 	Flags        LoadBalancerPortMappingFlags `json:",omitempty"` | ||||
| 	Protocol         uint32                       `json:",omitempty"` // EX: TCP = 6, UDP = 17 | ||||
| 	InternalPort     uint16                       `json:",omitempty"` | ||||
| 	ExternalPort     uint16                       `json:",omitempty"` | ||||
| 	DistributionType LoadBalancerDistribution     `json:",omitempty"` // EX: Distribute per connection = 0, distribute traffic of the same protocol per client IP = 1, distribute per client IP = 2 | ||||
| 	Flags            LoadBalancerPortMappingFlags `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // HostComputeLoadBalancer represents software load balancer. | ||||
| @@ -53,6 +54,18 @@ var ( | ||||
| 	LoadBalancerPortMappingFlagsPreserveDIP LoadBalancerPortMappingFlags = 8 | ||||
| ) | ||||
|  | ||||
| // LoadBalancerDistribution specifies how the loadbalancer distributes traffic. | ||||
| type LoadBalancerDistribution uint32 | ||||
|  | ||||
| var ( | ||||
| 	// LoadBalancerDistributionNone is the default and loadbalances each connection to the same pod. | ||||
| 	LoadBalancerDistributionNone LoadBalancerDistribution | ||||
| 	// LoadBalancerDistributionSourceIPProtocol loadbalances all traffic of the same protocol from a client IP to the same pod. | ||||
| 	LoadBalancerDistributionSourceIPProtocol LoadBalancerDistribution = 1 | ||||
| 	// LoadBalancerDistributionSourceIP loadbalances all traffic from a client IP to the same pod. | ||||
| 	LoadBalancerDistributionSourceIP LoadBalancerDistribution = 2 | ||||
| ) | ||||
|  | ||||
| func getLoadBalancer(loadBalancerGuid guid.GUID, query string) (*HostComputeLoadBalancer, error) { | ||||
| 	// Open loadBalancer. | ||||
| 	var ( | ||||
|   | ||||
							
								
								
									
										43
									
								
								vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -6,11 +6,14 @@ import ( | ||||
|  | ||||
| // SupportedFeatures are the features provided by the Service. | ||||
| type SupportedFeatures struct { | ||||
| 	Acl          AclFeatures `json:"ACL"` | ||||
| 	Api          ApiSupport  `json:"API"` | ||||
| 	RemoteSubnet bool        `json:"RemoteSubnet"` | ||||
| 	HostRoute    bool        `json:"HostRoute"` | ||||
| 	DSR          bool        `json:"DSR"` | ||||
| 	Acl                      AclFeatures `json:"ACL"` | ||||
| 	Api                      ApiSupport  `json:"API"` | ||||
| 	RemoteSubnet             bool        `json:"RemoteSubnet"` | ||||
| 	HostRoute                bool        `json:"HostRoute"` | ||||
| 	DSR                      bool        `json:"DSR"` | ||||
| 	Slash32EndpointPrefixes  bool        `json:"Slash32EndpointPrefixes"` | ||||
| 	AclSupportForProtocol252 bool        `json:"AclSupportForProtocol252"` | ||||
| 	SessionAffinity          bool        `json:"SessionAffinity"` | ||||
| } | ||||
|  | ||||
| // AclFeatures are the supported ACL possibilities. | ||||
| @@ -53,18 +56,38 @@ func GetSupportedFeatures() SupportedFeatures { | ||||
| 	features.RemoteSubnet = isFeatureSupported(globals.Version, RemoteSubnetVersion) | ||||
| 	features.HostRoute = isFeatureSupported(globals.Version, HostRouteVersion) | ||||
| 	features.DSR = isFeatureSupported(globals.Version, DSRVersion) | ||||
| 	features.Slash32EndpointPrefixes = isFeatureSupported(globals.Version, Slash32EndpointPrefixesVersion) | ||||
| 	features.AclSupportForProtocol252 = isFeatureSupported(globals.Version, AclSupportForProtocol252Version) | ||||
| 	features.SessionAffinity = isFeatureSupported(globals.Version, SessionAffinityVersion) | ||||
|  | ||||
| 	return features | ||||
| } | ||||
|  | ||||
| func isFeatureSupported(currentVersion Version, minVersionSupported Version) bool { | ||||
| 	if currentVersion.Major < minVersionSupported.Major { | ||||
| func isFeatureSupported(currentVersion Version, versionsSupported VersionRanges) bool { | ||||
| 	isFeatureSupported := false | ||||
|  | ||||
| 	for _, versionRange := range versionsSupported { | ||||
| 		isFeatureSupported = isFeatureSupported || isFeatureInRange(currentVersion, versionRange) | ||||
| 	} | ||||
|  | ||||
| 	return isFeatureSupported | ||||
| } | ||||
|  | ||||
| func isFeatureInRange(currentVersion Version, versionRange VersionRange) bool { | ||||
| 	if currentVersion.Major < versionRange.MinVersion.Major { | ||||
| 		logrus.Infof("currentVersion.Major < versionRange.MinVersion.Major: %v, %v", currentVersion.Major, versionRange.MinVersion.Major) | ||||
| 		return false | ||||
| 	} | ||||
| 	if currentVersion.Major > minVersionSupported.Major { | ||||
| 		return true | ||||
| 	if currentVersion.Major > versionRange.MaxVersion.Major { | ||||
| 		logrus.Infof("currentVersion.Major > versionRange.MaxVersion.Major: %v, %v", currentVersion.Major, versionRange.MaxVersion.Major) | ||||
| 		return false | ||||
| 	} | ||||
| 	if currentVersion.Minor < minVersionSupported.Minor { | ||||
| 	if currentVersion.Major == versionRange.MinVersion.Major && currentVersion.Minor < versionRange.MinVersion.Minor { | ||||
| 		logrus.Infof("currentVersion.Minor < versionRange.MinVersion.Major: %v, %v", currentVersion.Minor, versionRange.MinVersion.Minor) | ||||
| 		return false | ||||
| 	} | ||||
| 	if currentVersion.Major == versionRange.MaxVersion.Major && currentVersion.Minor > versionRange.MaxVersion.Minor { | ||||
| 		logrus.Infof("currentVersion.Minor > versionRange.MaxVersion.Major: %v, %v", currentVersion.Minor, versionRange.MaxVersion.Minor) | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
|   | ||||
							
								
								
									
										26
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -20,6 +20,8 @@ type Process struct { | ||||
| 	handle         vmcompute.HcsProcess | ||||
| 	processID      int | ||||
| 	system         *System | ||||
| 	hasCachedStdio bool | ||||
| 	stdioLock      sync.Mutex | ||||
| 	stdin          io.WriteCloser | ||||
| 	stdout         io.ReadCloser | ||||
| 	stderr         io.ReadCloser | ||||
| @@ -272,8 +274,8 @@ func (process *Process) ExitCode() (int, error) { | ||||
| } | ||||
|  | ||||
| // StdioLegacy returns the stdin, stdout, and stderr pipes, respectively. Closing | ||||
| // these pipes does not close the underlying pipes; but this function can only | ||||
| // be called once on each Process. | ||||
| // these pipes does not close the underlying pipes. Once returned, these pipes | ||||
| // are the responsibility of the caller to close. | ||||
| func (process *Process) StdioLegacy() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, err error) { | ||||
| 	operation := "hcsshim::Process::StdioLegacy" | ||||
| 	ctx, span := trace.StartSpan(context.Background(), operation) | ||||
| @@ -290,6 +292,15 @@ func (process *Process) StdioLegacy() (_ io.WriteCloser, _ io.ReadCloser, _ io.R | ||||
| 		return nil, nil, nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	process.stdioLock.Lock() | ||||
| 	defer process.stdioLock.Unlock() | ||||
| 	if process.hasCachedStdio { | ||||
| 		stdin, stdout, stderr := process.stdin, process.stdout, process.stderr | ||||
| 		process.stdin, process.stdout, process.stderr = nil, nil, nil | ||||
| 		process.hasCachedStdio = false | ||||
| 		return stdin, stdout, stderr, nil | ||||
| 	} | ||||
|  | ||||
| 	processInfo, resultJSON, err := vmcompute.HcsGetProcessInfo(ctx, process.handle) | ||||
| 	events := processHcsResult(ctx, resultJSON) | ||||
| 	if err != nil { | ||||
| @@ -307,6 +318,8 @@ func (process *Process) StdioLegacy() (_ io.WriteCloser, _ io.ReadCloser, _ io.R | ||||
| // Stdio returns the stdin, stdout, and stderr pipes, respectively. | ||||
| // To close them, close the process handle. | ||||
| func (process *Process) Stdio() (stdin io.Writer, stdout, stderr io.Reader) { | ||||
| 	process.stdioLock.Lock() | ||||
| 	defer process.stdioLock.Unlock() | ||||
| 	return process.stdin, process.stdout, process.stderr | ||||
| } | ||||
|  | ||||
| @@ -340,9 +353,13 @@ func (process *Process) CloseStdin(ctx context.Context) error { | ||||
| 		return makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	process.stdioLock.Lock() | ||||
| 	if process.stdin != nil { | ||||
| 		process.stdin.Close() | ||||
| 		process.stdin = nil | ||||
| 	} | ||||
| 	process.stdioLock.Unlock() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -365,15 +382,20 @@ func (process *Process) Close() (err error) { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	process.stdioLock.Lock() | ||||
| 	if process.stdin != nil { | ||||
| 		process.stdin.Close() | ||||
| 		process.stdin = nil | ||||
| 	} | ||||
| 	if process.stdout != nil { | ||||
| 		process.stdout.Close() | ||||
| 		process.stdout = nil | ||||
| 	} | ||||
| 	if process.stderr != nil { | ||||
| 		process.stderr.Close() | ||||
| 		process.stderr = nil | ||||
| 	} | ||||
| 	process.stdioLock.Unlock() | ||||
|  | ||||
| 	if err = process.unregisterCallback(ctx); err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
|   | ||||
							
								
								
									
										33
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -482,38 +482,6 @@ func (computeSystem *System) createProcess(ctx context.Context, operation string | ||||
| 	return newProcess(processHandle, int(processInfo.ProcessId), computeSystem), &processInfo, nil | ||||
| } | ||||
|  | ||||
| // CreateProcessNoStdio launches a new process within the computeSystem. The | ||||
| // Stdio handles are not cached on the process struct. | ||||
| func (computeSystem *System) CreateProcessNoStdio(c interface{}) (_ cow.Process, err error) { | ||||
| 	operation := "hcsshim::System::CreateProcessNoStdio" | ||||
| 	ctx, span := trace.StartSpan(context.Background(), operation) | ||||
| 	defer span.End() | ||||
| 	defer func() { oc.SetSpanStatus(span, err) }() | ||||
| 	span.AddAttributes(trace.StringAttribute("cid", computeSystem.id)) | ||||
|  | ||||
| 	process, processInfo, err := computeSystem.createProcess(ctx, operation, c) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			process.Close() | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	// We don't do anything with these handles. Close them so they don't leak. | ||||
| 	syscall.Close(processInfo.StdInput) | ||||
| 	syscall.Close(processInfo.StdOutput) | ||||
| 	syscall.Close(processInfo.StdError) | ||||
|  | ||||
| 	if err = process.registerCallback(ctx); err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, operation, "", err, nil) | ||||
| 	} | ||||
| 	go process.waitBackground() | ||||
|  | ||||
| 	return process, nil | ||||
| } | ||||
|  | ||||
| // CreateProcess launches a new process within the computeSystem. | ||||
| func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) (cow.Process, error) { | ||||
| 	operation := "hcsshim::System::CreateProcess" | ||||
| @@ -534,6 +502,7 @@ func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) ( | ||||
| 	process.stdin = pipes[0] | ||||
| 	process.stdout = pipes[1] | ||||
| 	process.stderr = pipes[2] | ||||
| 	process.hasCachedStdio = true | ||||
|  | ||||
| 	if err = process.registerCallback(ctx); err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, operation, "", err, nil) | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/Microsoft/hcsshim/internal/vmcompute/vmcompute.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/Microsoft/hcsshim/internal/vmcompute/vmcompute.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -204,7 +204,9 @@ func HcsShutdownComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, opt | ||||
| 		if result != "" { | ||||
| 			span.AddAttributes(trace.StringAttribute("result", result)) | ||||
| 		} | ||||
| 		oc.SetSpanStatus(span, hr) | ||||
| 		if hr != errVmcomputeOperationPending { | ||||
| 			oc.SetSpanStatus(span, hr) | ||||
| 		} | ||||
| 	}() | ||||
| 	span.AddAttributes(trace.StringAttribute("options", options)) | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ const ( | ||||
| 	// 2019 (ltsc2019), and Windows 10 (October 2018 Update). | ||||
| 	RS5 = 17763 | ||||
|  | ||||
| 	// V19H1 (version 1903) corresponds to Windows Sever 1903 (semi-annual | ||||
| 	// V19H1 (version 1903) corresponds to Windows Server 1903 (semi-annual | ||||
| 	// channel). | ||||
| 	V19H1 = 18362 | ||||
| ) | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/containerd/cgroups/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/containerd/cgroups/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -4,9 +4,9 @@ go 1.12 | ||||
|  | ||||
| require ( | ||||
| 	github.com/cilium/ebpf v0.0.0-20191113100448-d9fb101ca1fb | ||||
| 	github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e | ||||
| 	github.com/coreos/go-systemd/v22 v22.0.0-20191111152658-2d78030078ef | ||||
| 	github.com/docker/go-units v0.4.0 | ||||
| 	github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e | ||||
| 	github.com/godbus/dbus/v5 v5.0.3 | ||||
| 	github.com/gogo/protobuf v1.2.1 | ||||
| 	github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700 | ||||
| 	github.com/pkg/errors v0.8.1 | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/containerd/cgroups/systemd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/containerd/cgroups/systemd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -22,8 +22,8 @@ import ( | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	systemdDbus "github.com/coreos/go-systemd/dbus" | ||||
| 	"github.com/godbus/dbus" | ||||
| 	systemdDbus "github.com/coreos/go-systemd/v22/dbus" | ||||
| 	"github.com/godbus/dbus/v5" | ||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" | ||||
| ) | ||||
|  | ||||
|   | ||||
							
								
								
									
										37
									
								
								vendor/github.com/containerd/cgroups/v2/cpu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/containerd/cgroups/v2/cpu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -16,13 +16,44 @@ | ||||
|  | ||||
| package v2 | ||||
|  | ||||
| import ( | ||||
| 	"math" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type CPUMax string | ||||
|  | ||||
| func NewCPUMax(quota *int64, period *uint64) CPUMax { | ||||
| 	max := "max" | ||||
| 	if quota != nil { | ||||
| 		max = strconv.FormatInt(*quota, 10) | ||||
| 	} | ||||
| 	return CPUMax(strings.Join([]string{max, strconv.FormatUint(*period, 10)}, " ")) | ||||
| } | ||||
|  | ||||
| type CPU struct { | ||||
| 	Weight *uint64 | ||||
| 	Max    *uint64 | ||||
| 	Max    CPUMax | ||||
| 	Cpus   string | ||||
| 	Mems   string | ||||
| } | ||||
|  | ||||
| func (c CPUMax) extractQuotaAndPeriod() (int64, uint64) { | ||||
| 	var ( | ||||
| 		quota  int64 | ||||
| 		period uint64 | ||||
| 	) | ||||
| 	values := strings.Split(string(c), " ") | ||||
| 	if values[0] == "max" { | ||||
| 		quota = math.MaxInt64 | ||||
| 	} else { | ||||
| 		quota, _ = strconv.ParseInt(values[0], 10, 64) | ||||
| 	} | ||||
| 	period, _ = strconv.ParseUint(values[1], 10, 64) | ||||
| 	return quota, period | ||||
| } | ||||
|  | ||||
| func (r *CPU) Values() (o []Value) { | ||||
| 	if r.Weight != nil { | ||||
| 		o = append(o, Value{ | ||||
| @@ -30,10 +61,10 @@ func (r *CPU) Values() (o []Value) { | ||||
| 			value:    *r.Weight, | ||||
| 		}) | ||||
| 	} | ||||
| 	if r.Max != nil { | ||||
| 	if r.Max != "" { | ||||
| 		o = append(o, Value{ | ||||
| 			filename: "cpu.max", | ||||
| 			value:    *r.Max, | ||||
| 			value:    r.Max, | ||||
| 		}) | ||||
| 	} | ||||
| 	if r.Cpus != "" { | ||||
|   | ||||
							
								
								
									
										224
									
								
								vendor/github.com/containerd/cgroups/v2/manager.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										224
									
								
								vendor/github.com/containerd/cgroups/v2/manager.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -19,25 +19,37 @@ package v2 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"fmt" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"io/ioutil" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
|  | ||||
| 	"github.com/containerd/cgroups/v2/stats" | ||||
| 	"github.com/godbus/dbus/v5" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
|  | ||||
| 	systemdDbus "github.com/coreos/go-systemd/v22/dbus" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	subtreeControl  = "cgroup.subtree_control" | ||||
| 	controllersFile = "cgroup.controllers" | ||||
| 	subtreeControl     = "cgroup.subtree_control" | ||||
| 	controllersFile    = "cgroup.controllers" | ||||
| 	defaultCgroup2Path = "/sys/fs/cgroup" | ||||
| 	defaultSlice       = "system.slice" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	canDelegate bool | ||||
| 	once        sync.Once | ||||
| ) | ||||
|  | ||||
| type cgValuer interface { | ||||
| @@ -66,22 +78,45 @@ type Resources struct { | ||||
| // Values returns the raw filenames and values that | ||||
| // can be written to the unified hierarchy | ||||
| func (r *Resources) Values() (o []Value) { | ||||
| 	values := []cgValuer{ | ||||
| 		r.CPU, | ||||
| 		r.Memory, | ||||
| 		r.Pids, | ||||
| 		r.IO, | ||||
| 		r.RDMA, | ||||
| 	if r.CPU != nil { | ||||
| 		o = append(o, r.CPU.Values()...) | ||||
| 	} | ||||
| 	for _, v := range values { | ||||
| 		if v == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		o = append(o, v.Values()...) | ||||
| 	if r.Memory != nil { | ||||
| 		o = append(o, r.Memory.Values()...) | ||||
| 	} | ||||
| 	if r.Pids != nil { | ||||
| 		o = append(o, r.Pids.Values()...) | ||||
| 	} | ||||
| 	if r.IO != nil { | ||||
| 		o = append(o, r.IO.Values()...) | ||||
| 	} | ||||
| 	if r.RDMA != nil { | ||||
| 		o = append(o, r.RDMA.Values()...) | ||||
| 	} | ||||
| 	return o | ||||
| } | ||||
|  | ||||
| // EnabledControllers returns the list of all not nil resource controllers | ||||
| func (r *Resources) EnabledControllers() (c []string) { | ||||
| 	if r.CPU != nil { | ||||
| 		c = append(c, "cpu") | ||||
| 		c = append(c, "cpuset") | ||||
| 	} | ||||
| 	if r.Memory != nil { | ||||
| 		c = append(c, "memory") | ||||
| 	} | ||||
| 	if r.Pids != nil { | ||||
| 		c = append(c, "pids") | ||||
| 	} | ||||
| 	if r.IO != nil { | ||||
| 		c = append(c, "io") | ||||
| 	} | ||||
| 	if r.RDMA != nil { | ||||
| 		c = append(c, "rdma") | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // Value of a cgroup setting | ||||
| type Value struct { | ||||
| 	filename string | ||||
| @@ -102,6 +137,8 @@ func (c *Value) write(path string, perm os.FileMode) error { | ||||
| 		data = t | ||||
| 	case string: | ||||
| 		data = []byte(t) | ||||
| 	case CPUMax: | ||||
| 		data = []byte(t) | ||||
| 	default: | ||||
| 		return ErrInvalidFormat | ||||
| 	} | ||||
| @@ -129,15 +166,20 @@ func NewManager(mountpoint string, group string, resources *Resources) (*Manager | ||||
| 	if err := os.MkdirAll(path, defaultDirPerm); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := setResources(path, resources); err != nil { | ||||
| 	m := Manager{ | ||||
| 		unifiedMountpoint: mountpoint, | ||||
| 		path:              path, | ||||
| 	} | ||||
| 	if err := m.ToggleControllers(resources.EnabledControllers(), Enable); err != nil { | ||||
| 		// clean up cgroup dir on failure | ||||
| 		os.Remove(path) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &Manager{ | ||||
| 		unifiedMountpoint: mountpoint, | ||||
| 		path:              path, | ||||
| 	}, nil | ||||
| 	if err := setResources(path, resources); err != nil { | ||||
| 		os.Remove(path) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &m, nil | ||||
| } | ||||
|  | ||||
| func LoadManager(mountpoint string, group string) (*Manager, error) { | ||||
| @@ -308,12 +350,15 @@ func (c *Manager) Stat() (*stats.Metrics, error) { | ||||
| 	} | ||||
| 	out := make(map[string]interface{}) | ||||
| 	for _, controller := range controllers { | ||||
| 		filename := fmt.Sprintf("%s.stat", controller) | ||||
| 		if err := readStatsFile(c.path, filename, out); err != nil { | ||||
| 			if os.IsNotExist(err) { | ||||
| 				continue | ||||
| 		switch controller { | ||||
| 		case "cpu", "memory": | ||||
| 			filename := fmt.Sprintf("%s.stat", controller) | ||||
| 			if err := readKVStatsFile(c.path, filename, out); err != nil { | ||||
| 				if os.IsNotExist(err) { | ||||
| 					continue | ||||
| 				} | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	for _, name := range singleValueFiles { | ||||
| @@ -376,6 +421,8 @@ func (c *Manager) Stat() (*stats.Metrics, error) { | ||||
| 		SwapLimit:             getStatFileContentUint64(filepath.Join(c.path, "memory.swap.max")), | ||||
| 	} | ||||
|  | ||||
| 	metrics.Io = &stats.IOStat{Usage: readIoStats(c.path)} | ||||
|  | ||||
| 	metrics.Rdma = &stats.RdmaStat{ | ||||
| 		Current: rdmaStats(filepath.Join(c.path, "rdma.current")), | ||||
| 		Limit:   rdmaStats(filepath.Join(c.path, "rdma.max")), | ||||
| @@ -433,7 +480,7 @@ func readSingleFile(path string, file string, out map[string]interface{}) error | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func readStatsFile(path string, file string, out map[string]interface{}) error { | ||||
| func readKVStatsFile(path string, file string, out map[string]interface{}) error { | ||||
| 	f, err := os.Open(filepath.Join(path, file)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -447,7 +494,7 @@ func readStatsFile(path string, file string, out map[string]interface{}) error { | ||||
| 		} | ||||
| 		name, value, err := parseKV(s.Text()) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return errors.Wrapf(err, "error while parsing %s (line=%q)", filepath.Join(path, file), s.Text()) | ||||
| 		} | ||||
| 		out[name] = value | ||||
| 	} | ||||
| @@ -516,7 +563,7 @@ func (c *Manager) waitForEvents(ec chan<- Event, errCh chan<- error) { | ||||
| 		} | ||||
| 		var out map[string]interface{} | ||||
| 		if bytesRead >= syscall.SizeofInotifyEvent { | ||||
| 			if err := readStatsFile(c.path, "memory.events", out); err != nil { | ||||
| 			if err := readKVStatsFile(c.path, "memory.events", out); err != nil { | ||||
| 				e := Event{ | ||||
| 					High:    out["high"].(uint64), | ||||
| 					Low:     out["low"].(uint64), | ||||
| @@ -550,3 +597,126 @@ func setDevices(path string, devices []specs.LinuxDeviceCgroup) error { | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func NewSystemd(slice, group string, pid int, resources *Resources) (*Manager, error) { | ||||
| 	if slice == "" { | ||||
| 		slice = defaultSlice | ||||
| 	} | ||||
| 	path := filepath.Join(defaultCgroup2Path, slice, group) | ||||
| 	conn, err := systemdDbus.New() | ||||
| 	if err != nil { | ||||
| 		return &Manager{}, err | ||||
| 	} | ||||
| 	defer conn.Close() | ||||
|  | ||||
| 	properties := []systemdDbus.Property{ | ||||
| 		systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", group)), | ||||
| 		newSystemdProperty("DefaultDependencies", false), | ||||
| 		newSystemdProperty("MemoryAccounting", true), | ||||
| 		newSystemdProperty("CPUAccounting", true), | ||||
| 		newSystemdProperty("IOAccounting", true), | ||||
| 	} | ||||
|  | ||||
| 	// if we create a slice, the parent is defined via a Wants= | ||||
| 	if strings.HasSuffix(group, ".slice") { | ||||
| 		properties = append(properties, systemdDbus.PropWants(defaultSlice)) | ||||
| 	} else { | ||||
| 		// otherwise, we use Slice= | ||||
| 		properties = append(properties, systemdDbus.PropSlice(defaultSlice)) | ||||
| 	} | ||||
|  | ||||
| 	// only add pid if its valid, -1 is used w/ general slice creation. | ||||
| 	if pid != -1 { | ||||
| 		properties = append(properties, newSystemdProperty("PIDs", []uint32{uint32(pid)})) | ||||
| 	} | ||||
|  | ||||
| 	if resources.Memory != nil && *resources.Memory.Max != 0 { | ||||
| 		properties = append(properties, | ||||
| 			newSystemdProperty("MemoryMax", uint64(*resources.Memory.Max))) | ||||
| 	} | ||||
|  | ||||
| 	if resources.CPU != nil && *resources.CPU.Weight != 0 { | ||||
| 		properties = append(properties, | ||||
| 			newSystemdProperty("CPUWeight", *resources.CPU.Weight)) | ||||
| 	} | ||||
|  | ||||
| 	if resources.CPU != nil && resources.CPU.Max != "" { | ||||
| 		quota, period := resources.CPU.Max.extractQuotaAndPeriod() | ||||
| 		// cpu.cfs_quota_us and cpu.cfs_period_us are controlled by systemd. | ||||
| 		// corresponds to USEC_INFINITY in systemd | ||||
| 		// if USEC_INFINITY is provided, CPUQuota is left unbound by systemd | ||||
| 		// always setting a property value ensures we can apply a quota and remove it later | ||||
| 		cpuQuotaPerSecUSec := uint64(math.MaxUint64) | ||||
| 		if quota > 0 { | ||||
| 			// systemd converts CPUQuotaPerSecUSec (microseconds per CPU second) to CPUQuota | ||||
| 			// (integer percentage of CPU) internally.  This means that if a fractional percent of | ||||
| 			// CPU is indicated by Resources.CpuQuota, we need to round up to the nearest | ||||
| 			// 10ms (1% of a second) such that child cgroups can set the cpu.cfs_quota_us they expect. | ||||
| 			cpuQuotaPerSecUSec = uint64(quota*1000000) / period | ||||
| 			if cpuQuotaPerSecUSec%10000 != 0 { | ||||
| 				cpuQuotaPerSecUSec = ((cpuQuotaPerSecUSec / 10000) + 1) * 10000 | ||||
| 			} | ||||
| 		} | ||||
| 		properties = append(properties, | ||||
| 			newSystemdProperty("CPUQuotaPerSecUSec", cpuQuotaPerSecUSec)) | ||||
| 	} | ||||
|  | ||||
| 	// If we can delegate, we add the property back in | ||||
| 	if canDelegate { | ||||
| 		properties = append(properties, newSystemdProperty("Delegate", true)) | ||||
| 	} | ||||
|  | ||||
| 	if resources.Pids != nil && resources.Pids.Max > 0 { | ||||
| 		properties = append(properties, | ||||
| 			newSystemdProperty("TasksAccounting", true), | ||||
| 			newSystemdProperty("TasksMax", uint64(resources.Pids.Max))) | ||||
| 	} | ||||
|  | ||||
| 	statusChan := make(chan string, 1) | ||||
| 	if _, err := conn.StartTransientUnit(group, "replace", properties, statusChan); err == nil { | ||||
| 		select { | ||||
| 		case <-statusChan: | ||||
| 		case <-time.After(time.Second): | ||||
| 			logrus.Warnf("Timed out while waiting for StartTransientUnit(%s) completion signal from dbus. Continuing...", group) | ||||
| 		} | ||||
| 	} else if !isUnitExists(err) { | ||||
| 		return &Manager{}, err | ||||
| 	} | ||||
|  | ||||
| 	return &Manager{ | ||||
| 		path: path, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func LoadSystemd(slice, group string) (*Manager, error) { | ||||
| 	if slice == "" { | ||||
| 		slice = defaultSlice | ||||
| 	} | ||||
| 	group = filepath.Join(defaultCgroup2Path, slice, group) | ||||
| 	return &Manager{ | ||||
| 		path: group, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (c *Manager) DeleteSystemd() error { | ||||
| 	conn, err := systemdDbus.New() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer conn.Close() | ||||
| 	group := systemdUnitFromPath(c.path) | ||||
| 	ch := make(chan string) | ||||
| 	_, err = conn.StopUnit(group, "replace", ch) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	<-ch | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func newSystemdProperty(name string, units interface{}) systemdDbus.Property { | ||||
| 	return systemdDbus.Property{ | ||||
| 		Name:  name, | ||||
| 		Value: dbus.MakeVariant(units), | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										682
									
								
								vendor/github.com/containerd/cgroups/v2/stats/metrics.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										682
									
								
								vendor/github.com/containerd/cgroups/v2/stats/metrics.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -29,6 +29,7 @@ type Metrics struct { | ||||
| 	CPU                  *CPUStat    `protobuf:"bytes,2,opt,name=cpu,proto3" json:"cpu,omitempty"` | ||||
| 	Memory               *MemoryStat `protobuf:"bytes,4,opt,name=memory,proto3" json:"memory,omitempty"` | ||||
| 	Rdma                 *RdmaStat   `protobuf:"bytes,5,opt,name=rdma,proto3" json:"rdma,omitempty"` | ||||
| 	Io                   *IOStat     `protobuf:"bytes,6,opt,name=io,proto3" json:"io,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}    `json:"-"` | ||||
| 	XXX_unrecognized     []byte      `json:"-"` | ||||
| 	XXX_sizecache        int32       `json:"-"` | ||||
| @@ -304,6 +305,89 @@ func (m *RdmaEntry) XXX_DiscardUnknown() { | ||||
|  | ||||
| var xxx_messageInfo_RdmaEntry proto.InternalMessageInfo | ||||
|  | ||||
| type IOStat struct { | ||||
| 	Usage                []*IOEntry `protobuf:"bytes,1,rep,name=usage,proto3" json:"usage,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}   `json:"-"` | ||||
| 	XXX_unrecognized     []byte     `json:"-"` | ||||
| 	XXX_sizecache        int32      `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *IOStat) Reset()      { *m = IOStat{} } | ||||
| func (*IOStat) ProtoMessage() {} | ||||
| func (*IOStat) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_2fc6005842049e6b, []int{6} | ||||
| } | ||||
| func (m *IOStat) XXX_Unmarshal(b []byte) error { | ||||
| 	return m.Unmarshal(b) | ||||
| } | ||||
| func (m *IOStat) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	if deterministic { | ||||
| 		return xxx_messageInfo_IOStat.Marshal(b, m, deterministic) | ||||
| 	} else { | ||||
| 		b = b[:cap(b)] | ||||
| 		n, err := m.MarshalTo(b) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return b[:n], nil | ||||
| 	} | ||||
| } | ||||
| func (m *IOStat) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_IOStat.Merge(m, src) | ||||
| } | ||||
| func (m *IOStat) XXX_Size() int { | ||||
| 	return m.Size() | ||||
| } | ||||
| func (m *IOStat) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_IOStat.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_IOStat proto.InternalMessageInfo | ||||
|  | ||||
| type IOEntry struct { | ||||
| 	Major                uint64   `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"` | ||||
| 	Minor                uint64   `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"` | ||||
| 	Rbytes               uint64   `protobuf:"varint,3,opt,name=rbytes,proto3" json:"rbytes,omitempty"` | ||||
| 	Wbytes               uint64   `protobuf:"varint,4,opt,name=wbytes,proto3" json:"wbytes,omitempty"` | ||||
| 	Rios                 uint64   `protobuf:"varint,5,opt,name=rios,proto3" json:"rios,omitempty"` | ||||
| 	Wios                 uint64   `protobuf:"varint,6,opt,name=wios,proto3" json:"wios,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *IOEntry) Reset()      { *m = IOEntry{} } | ||||
| func (*IOEntry) ProtoMessage() {} | ||||
| func (*IOEntry) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_2fc6005842049e6b, []int{7} | ||||
| } | ||||
| func (m *IOEntry) XXX_Unmarshal(b []byte) error { | ||||
| 	return m.Unmarshal(b) | ||||
| } | ||||
| func (m *IOEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	if deterministic { | ||||
| 		return xxx_messageInfo_IOEntry.Marshal(b, m, deterministic) | ||||
| 	} else { | ||||
| 		b = b[:cap(b)] | ||||
| 		n, err := m.MarshalTo(b) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return b[:n], nil | ||||
| 	} | ||||
| } | ||||
| func (m *IOEntry) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_IOEntry.Merge(m, src) | ||||
| } | ||||
| func (m *IOEntry) XXX_Size() int { | ||||
| 	return m.Size() | ||||
| } | ||||
| func (m *IOEntry) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_IOEntry.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_IOEntry proto.InternalMessageInfo | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterType((*Metrics)(nil), "io.containerd.cgroups.v2.Metrics") | ||||
| 	proto.RegisterType((*PidsStat)(nil), "io.containerd.cgroups.v2.PidsStat") | ||||
| @@ -311,6 +395,8 @@ func init() { | ||||
| 	proto.RegisterType((*MemoryStat)(nil), "io.containerd.cgroups.v2.MemoryStat") | ||||
| 	proto.RegisterType((*RdmaStat)(nil), "io.containerd.cgroups.v2.RdmaStat") | ||||
| 	proto.RegisterType((*RdmaEntry)(nil), "io.containerd.cgroups.v2.RdmaEntry") | ||||
| 	proto.RegisterType((*IOStat)(nil), "io.containerd.cgroups.v2.IOStat") | ||||
| 	proto.RegisterType((*IOEntry)(nil), "io.containerd.cgroups.v2.IOEntry") | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| @@ -318,68 +404,74 @@ func init() { | ||||
| } | ||||
|  | ||||
| var fileDescriptor_2fc6005842049e6b = []byte{ | ||||
| 	// 965 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0x4d, 0x6f, 0x1c, 0x45, | ||||
| 	0x10, 0xcd, 0xe2, 0x8d, 0xbd, 0x5b, 0x6b, 0xc7, 0x4e, 0xc7, 0x31, 0x1d, 0x07, 0xaf, 0xed, 0x35, | ||||
| 	0xa0, 0x20, 0xc1, 0xae, 0x64, 0x3e, 0x24, 0x50, 0x38, 0x38, 0x86, 0x88, 0x03, 0x06, 0x6b, 0x12, | ||||
| 	0x8b, 0xe3, 0xa8, 0x77, 0xa6, 0x3d, 0x33, 0xf1, 0x7c, 0xa9, 0xbb, 0xc7, 0x96, 0x39, 0x71, 0xe0, | ||||
| 	0xce, 0xdf, 0xca, 0x0d, 0x8e, 0x9c, 0x10, 0xf1, 0x7f, 0xe0, 0x8e, 0xaa, 0x6a, 0x66, 0x67, 0x38, | ||||
| 	0x18, 0xb8, 0x75, 0xbd, 0xf7, 0xaa, 0xba, 0xea, 0xed, 0x74, 0x2d, 0x7c, 0x12, 0x25, 0x2e, 0xae, | ||||
| 	0xe6, 0xd3, 0xa0, 0xc8, 0x66, 0x41, 0x91, 0x3b, 0x95, 0xe4, 0xda, 0x84, 0xb3, 0x20, 0x32, 0x45, | ||||
| 	0x55, 0xda, 0xd9, 0xe5, 0xe1, 0xcc, 0x3a, 0xe5, 0xec, 0x2c, 0xd3, 0xce, 0x24, 0x81, 0x9d, 0x96, | ||||
| 	0xa6, 0x70, 0x85, 0x90, 0x49, 0x31, 0x6d, 0xd5, 0xd3, 0x5a, 0x3d, 0xbd, 0x3c, 0xdc, 0xde, 0x8c, | ||||
| 	0x8a, 0xa8, 0x20, 0xd1, 0x0c, 0x4f, 0xac, 0x9f, 0xfc, 0xd5, 0x83, 0x95, 0x13, 0xae, 0x20, 0x3e, | ||||
| 	0x83, 0x7e, 0x99, 0x84, 0x56, 0xf6, 0xf6, 0x7a, 0x4f, 0x46, 0x87, 0x93, 0xe9, 0x6d, 0xa5, 0xa6, | ||||
| 	0xa7, 0x49, 0x68, 0x5f, 0x38, 0xe5, 0x3c, 0xd2, 0x8b, 0xa7, 0xb0, 0x14, 0x94, 0x95, 0x7c, 0x8b, | ||||
| 	0xd2, 0xf6, 0x6f, 0x4f, 0x3b, 0x3e, 0x3d, 0xc3, 0xac, 0x67, 0x2b, 0x37, 0x7f, 0xec, 0x2e, 0x1d, | ||||
| 	0x9f, 0x9e, 0x79, 0x98, 0x26, 0x9e, 0xc2, 0x72, 0xa6, 0xb3, 0xc2, 0x5c, 0xcb, 0x3e, 0x15, 0x78, | ||||
| 	0xf7, 0xf6, 0x02, 0x27, 0xa4, 0xa3, 0x9b, 0xeb, 0x1c, 0xec, 0xd9, 0x84, 0x99, 0x92, 0x77, 0xff, | ||||
| 	0xab, 0x67, 0x2f, 0xcc, 0x14, 0xf7, 0x8c, 0xfa, 0xc9, 0x17, 0x30, 0x68, 0xa6, 0x10, 0x12, 0x56, | ||||
| 	0x82, 0xca, 0x18, 0x9d, 0x3b, 0x1a, 0xbd, 0xef, 0x35, 0xa1, 0xd8, 0x84, 0xbb, 0x69, 0x92, 0x25, | ||||
| 	0x8e, 0x66, 0xeb, 0x7b, 0x1c, 0x4c, 0x7e, 0xed, 0xc1, 0x4a, 0x3d, 0x8b, 0xd8, 0x01, 0xa8, 0xac, | ||||
| 	0x8a, 0xb4, 0x5f, 0x59, 0x1d, 0xd4, 0xe9, 0x43, 0x42, 0xce, 0xac, 0x0e, 0xc4, 0x63, 0x18, 0x56, | ||||
| 	0x56, 0x1b, 0x66, 0xb9, 0xc8, 0x00, 0x01, 0x22, 0x77, 0x61, 0x64, 0xaf, 0xad, 0xd3, 0x19, 0xd3, | ||||
| 	0x4b, 0x44, 0x03, 0x43, 0x24, 0xd8, 0x01, 0xc8, 0x8d, 0x5f, 0x6a, 0x93, 0x14, 0xa1, 0x25, 0x7b, | ||||
| 	0xfa, 0xde, 0x30, 0x37, 0xa7, 0x0c, 0x88, 0x7d, 0x58, 0xcd, 0x8d, 0xef, 0x62, 0x53, 0x38, 0x97, | ||||
| 	0xea, 0x90, 0x3c, 0xe8, 0x7b, 0xa3, 0xdc, 0xbc, 0x6c, 0x20, 0xf1, 0x1e, 0xdc, 0x5b, 0xf0, 0x7c, | ||||
| 	0xcb, 0x32, 0x89, 0xd6, 0x16, 0x28, 0x5e, 0x34, 0xf9, 0x65, 0x08, 0xd0, 0x9a, 0x2b, 0x04, 0xf4, | ||||
| 	0x55, 0x5e, 0xe4, 0xf5, 0x38, 0x74, 0x46, 0xec, 0x3c, 0x49, 0x75, 0x3d, 0x04, 0x9d, 0xb1, 0x81, | ||||
| 	0x0b, 0x6d, 0x72, 0x9d, 0xfa, 0xd6, 0xa9, 0xe0, 0xa2, 0x9e, 0x60, 0xc4, 0xd8, 0x0b, 0x84, 0x30, | ||||
| 	0xcd, 0xa6, 0x6a, 0x5e, 0x37, 0x4f, 0x67, 0xc2, 0x8a, 0xe0, 0xa2, 0xee, 0x97, 0xce, 0xe8, 0xb4, | ||||
| 	0x8d, 0x33, 0x9d, 0xd5, 0xfd, 0x71, 0x80, 0x0e, 0xe1, 0x45, 0x7e, 0xa6, 0xca, 0x52, 0x87, 0x72, | ||||
| 	0x85, 0x1d, 0x42, 0xe8, 0x84, 0x10, 0x74, 0x88, 0x04, 0x61, 0x62, 0xdc, 0xb5, 0x1c, 0xb0, 0x43, | ||||
| 	0x88, 0x7c, 0x85, 0x00, 0x8e, 0x4f, 0xf4, 0x95, 0x49, 0x9c, 0x9e, 0x63, 0x8b, 0x43, 0x1e, 0x1f, | ||||
| 	0xd1, 0x1f, 0x1a, 0x50, 0x3c, 0x82, 0x01, 0xce, 0xe8, 0xbb, 0xb8, 0x94, 0xc0, 0x5f, 0x00, 0xc6, | ||||
| 	0x2f, 0xe3, 0x52, 0x1c, 0xc0, 0x5a, 0x92, 0xab, 0xc0, 0x25, 0x97, 0xda, 0x27, 0x4f, 0x46, 0xc4, | ||||
| 	0xaf, 0x36, 0xe0, 0x11, 0x7a, 0xb3, 0x0b, 0xa3, 0xae, 0x64, 0x95, 0xdb, 0xec, 0x08, 0xba, 0x55, | ||||
| 	0xc8, 0xc5, 0xb5, 0x7f, 0x56, 0x79, 0x8e, 0x6e, 0xb6, 0x55, 0x48, 0x72, 0xaf, 0x5b, 0x85, 0x04, | ||||
| 	0x7b, 0x30, 0xaa, 0x72, 0x7d, 0x99, 0x04, 0x4e, 0xcd, 0x53, 0x2d, 0xd7, 0xd9, 0xed, 0x0e, 0x24, | ||||
| 	0x3e, 0x80, 0x0d, 0x74, 0xd8, 0x37, 0x3a, 0x48, 0x55, 0x92, 0x91, 0x6c, 0x83, 0x64, 0xeb, 0x88, | ||||
| 	0x7b, 0x2d, 0x2c, 0x3e, 0x02, 0x41, 0xd2, 0x2a, 0xef, 0x8a, 0xef, 0x93, 0xf8, 0x3e, 0x32, 0x67, | ||||
| 	0x5d, 0x02, 0xdf, 0x48, 0x19, 0x9d, 0xab, 0x2a, 0x75, 0x52, 0xb0, 0x43, 0x75, 0x28, 0xc6, 0x00, | ||||
| 	0x65, 0x94, 0xa9, 0x57, 0x4c, 0x3e, 0xe0, 0xae, 0x5b, 0x04, 0x2f, 0xba, 0x2a, 0xcc, 0x45, 0x92, | ||||
| 	0x47, 0x56, 0x3b, 0xdf, 0x68, 0xd6, 0x6d, 0xf2, 0x45, 0x2d, 0xe3, 0x31, 0x21, 0x66, 0xf0, 0xa0, | ||||
| 	0x23, 0xa7, 0xe9, 0x95, 0xd3, 0xf2, 0x21, 0xe9, 0x3b, 0x95, 0x8e, 0x6a, 0x46, 0x7c, 0x0a, 0x5b, | ||||
| 	0x9d, 0x84, 0xbc, 0x08, 0x75, 0xdd, 0xb7, 0xdc, 0xa2, 0x9c, 0x87, 0x2d, 0xfb, 0x5d, 0x4b, 0x8a, | ||||
| 	0x6d, 0x18, 0x94, 0x91, 0xd1, 0xe7, 0x49, 0x9a, 0xca, 0xb7, 0xf9, 0x61, 0x36, 0xb1, 0xd8, 0x82, | ||||
| 	0xe5, 0x32, 0xb2, 0x81, 0xca, 0xa5, 0x24, 0xa6, 0x8e, 0xd8, 0x04, 0xeb, 0xb4, 0x4a, 0xe5, 0xa3, | ||||
| 	0xc6, 0x04, 0x0a, 0xd9, 0x84, 0x45, 0xb3, 0xdb, 0x8d, 0x09, 0x0d, 0x22, 0x26, 0xb0, 0x5a, 0x46, | ||||
| 	0xa1, 0x5e, 0x28, 0x1e, 0xf3, 0xef, 0xdf, 0xc5, 0xb8, 0x46, 0xaa, 0x7e, 0xbc, 0x3e, 0x37, 0x5a, | ||||
| 	0xcb, 0x77, 0x9a, 0x1a, 0x0d, 0x82, 0x3f, 0x7f, 0x1b, 0x85, 0x72, 0x87, 0x7f, 0xfe, 0x0e, 0x24, | ||||
| 	0xde, 0x87, 0x75, 0x17, 0x97, 0x3e, 0x19, 0xe9, 0xab, 0x34, 0x2d, 0x02, 0x39, 0x6e, 0x9e, 0x7b, | ||||
| 	0xf9, 0x1c, 0xd1, 0x23, 0x04, 0xc5, 0x87, 0x20, 0x50, 0x17, 0x14, 0x69, 0xaa, 0x4a, 0xab, 0x6b, | ||||
| 	0xe9, 0x2e, 0x49, 0x37, 0x5c, 0x5c, 0x1e, 0xd7, 0x04, 0xab, 0x37, 0xe1, 0x2e, 0x2d, 0x34, 0xb9, | ||||
| 	0xc7, 0x4f, 0x93, 0x02, 0xfc, 0x5a, 0x79, 0xf1, 0xf1, 0x82, 0xdc, 0xe7, 0x76, 0x09, 0xfa, 0x16, | ||||
| 	0x11, 0x7c, 0x9a, 0xf6, 0x4a, 0x95, 0x3e, 0xe7, 0x4e, 0xf8, 0x69, 0x22, 0x72, 0x46, 0xf9, 0x0d, | ||||
| 	0xcd, 0xe9, 0x07, 0x2d, 0x4d, 0xd9, 0x93, 0x9f, 0x7b, 0x30, 0x68, 0x56, 0xb6, 0xf8, 0xb2, 0xbb, | ||||
| 	0xa0, 0x97, 0x9e, 0x8c, 0x0e, 0x0f, 0xfe, 0x7d, 0xcf, 0x7f, 0x9d, 0x3b, 0x73, 0xdd, 0x6e, 0xf1, | ||||
| 	0xcf, 0xdb, 0x2d, 0xfe, 0xbf, 0x93, 0xeb, 0x55, 0xaf, 0x61, 0xb8, 0xc0, 0xf0, 0xb3, 0x08, 0xf1, | ||||
| 	0xad, 0x69, 0x5a, 0x8c, 0x43, 0xaf, 0x8e, 0xd0, 0x8a, 0x38, 0x50, 0x7e, 0xac, 0xf2, 0x30, 0xd5, | ||||
| 	0x96, 0x36, 0xe4, 0x9a, 0x07, 0x71, 0xa0, 0xbe, 0x61, 0xa4, 0x11, 0x14, 0xf3, 0x57, 0x3a, 0x70, | ||||
| 	0x96, 0xd6, 0x24, 0x0b, 0xbe, 0x67, 0xe4, 0x99, 0x7c, 0xfd, 0x66, 0x7c, 0xe7, 0xf7, 0x37, 0xe3, | ||||
| 	0x3b, 0x3f, 0xdd, 0x8c, 0x7b, 0xaf, 0x6f, 0xc6, 0xbd, 0xdf, 0x6e, 0xc6, 0xbd, 0x3f, 0x6f, 0xc6, | ||||
| 	0xbd, 0xf9, 0x32, 0xfd, 0x4d, 0x7f, 0xfc, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2e, 0xcc, 0xc8, | ||||
| 	0x5a, 0x0e, 0x08, 0x00, 0x00, | ||||
| 	// 1064 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x56, 0x4f, 0x6f, 0x1c, 0xc5, | ||||
| 	0x13, 0xcd, 0xda, 0x9b, 0xfd, 0xd3, 0x6b, 0x27, 0x4e, 0xc7, 0xf1, 0xaf, 0xe3, 0xfc, 0xbc, 0xb6, | ||||
| 	0xd7, 0x80, 0x82, 0x04, 0xbb, 0xc8, 0xfc, 0x13, 0x28, 0x1c, 0x1c, 0x43, 0x04, 0x12, 0x26, 0xd6, | ||||
| 	0x26, 0x16, 0xc7, 0x51, 0xef, 0x4c, 0x7b, 0xb7, 0xed, 0x99, 0xe9, 0x51, 0x77, 0xaf, 0xad, 0xe5, | ||||
| 	0xc4, 0x81, 0x2b, 0xe2, 0x63, 0xf0, 0x55, 0x72, 0x83, 0x23, 0x27, 0x44, 0xfc, 0x49, 0x50, 0x55, | ||||
| 	0xf5, 0x78, 0x86, 0x83, 0x03, 0xb7, 0xae, 0xf7, 0x5e, 0xd5, 0x54, 0xbd, 0xd9, 0xae, 0x59, 0xf6, | ||||
| 	0xd1, 0x54, 0xfb, 0xd9, 0x7c, 0x32, 0x8c, 0x4d, 0x36, 0x8a, 0x4d, 0xee, 0xa5, 0xce, 0x95, 0x4d, | ||||
| 	0x46, 0xf1, 0xd4, 0x9a, 0x79, 0xe1, 0x46, 0x17, 0xfb, 0x23, 0xe7, 0xa5, 0x77, 0xa3, 0x4c, 0x79, | ||||
| 	0xab, 0x63, 0x37, 0x2c, 0xac, 0xf1, 0x86, 0x0b, 0x6d, 0x86, 0x95, 0x7a, 0x18, 0xd4, 0xc3, 0x8b, | ||||
| 	0xfd, 0xcd, 0xf5, 0xa9, 0x99, 0x1a, 0x14, 0x8d, 0xe0, 0x44, 0xfa, 0xc1, 0xaf, 0x4b, 0xac, 0x7d, | ||||
| 	0x44, 0x15, 0xf8, 0x27, 0xac, 0x59, 0xe8, 0xc4, 0x89, 0xc6, 0x4e, 0xe3, 0x71, 0x6f, 0x7f, 0x30, | ||||
| 	0xbc, 0xa9, 0xd4, 0xf0, 0x58, 0x27, 0xee, 0x85, 0x97, 0x7e, 0x8c, 0x7a, 0xfe, 0x84, 0x2d, 0xc7, | ||||
| 	0xc5, 0x5c, 0x2c, 0x61, 0xda, 0xee, 0xcd, 0x69, 0x87, 0xc7, 0x27, 0x90, 0xf5, 0xb4, 0x7d, 0xf5, | ||||
| 	0xe7, 0xf6, 0xf2, 0xe1, 0xf1, 0xc9, 0x18, 0xd2, 0xf8, 0x13, 0xd6, 0xca, 0x54, 0x66, 0xec, 0x42, | ||||
| 	0x34, 0xb1, 0xc0, 0x5b, 0x37, 0x17, 0x38, 0x42, 0x1d, 0x3e, 0x39, 0xe4, 0x40, 0xcf, 0x36, 0xc9, | ||||
| 	0xa4, 0xb8, 0xfd, 0x6f, 0x3d, 0x8f, 0x93, 0x4c, 0x52, 0xcf, 0xa0, 0xe7, 0x1f, 0xb0, 0x25, 0x6d, | ||||
| 	0x44, 0x0b, 0xb3, 0x76, 0x6e, 0xce, 0xfa, 0xe6, 0x39, 0xe6, 0x2c, 0x69, 0x33, 0xf8, 0x9c, 0x75, | ||||
| 	0xca, 0xb9, 0xb9, 0x60, 0xed, 0x78, 0x6e, 0xad, 0xca, 0x3d, 0x9a, 0xd5, 0x1c, 0x97, 0x21, 0x5f, | ||||
| 	0x67, 0xb7, 0x53, 0x9d, 0x69, 0x8f, 0x6e, 0x34, 0xc7, 0x14, 0x0c, 0x7e, 0x6b, 0xb0, 0x76, 0x98, | ||||
| 	0x9e, 0x6f, 0x31, 0x36, 0x77, 0x72, 0xaa, 0xa2, 0xb9, 0x53, 0x71, 0x48, 0xef, 0x22, 0x72, 0xe2, | ||||
| 	0x54, 0xcc, 0x1f, 0xb1, 0xee, 0xdc, 0x29, 0x4b, 0x2c, 0x15, 0xe9, 0x00, 0x80, 0xe4, 0x36, 0xeb, | ||||
| 	0xb9, 0x85, 0xf3, 0x2a, 0x23, 0x7a, 0x19, 0x69, 0x46, 0x10, 0x0a, 0xb6, 0x18, 0xcb, 0x6d, 0x54, | ||||
| 	0x28, 0xab, 0x4d, 0xe2, 0xd0, 0xd0, 0xe6, 0xb8, 0x9b, 0xdb, 0x63, 0x02, 0xf8, 0x2e, 0x5b, 0xc9, | ||||
| 	0x6d, 0xe4, 0x67, 0xd6, 0x78, 0x9f, 0xaa, 0x04, 0x5d, 0x6b, 0x8e, 0x7b, 0xb9, 0x7d, 0x59, 0x42, | ||||
| 	0xfc, 0x6d, 0x76, 0xe7, 0x9a, 0xa7, 0xa7, 0xb4, 0x50, 0xb4, 0x7a, 0x8d, 0xc2, 0x83, 0x06, 0xbf, | ||||
| 	0x74, 0x19, 0xab, 0x5e, 0x07, 0xe7, 0xac, 0x29, 0x73, 0x93, 0x87, 0x71, 0xf0, 0x0c, 0xd8, 0xa9, | ||||
| 	0x4e, 0x55, 0x18, 0x02, 0xcf, 0xd0, 0xc0, 0xb9, 0xb2, 0xb9, 0x4a, 0x23, 0xe7, 0x65, 0x7c, 0x1e, | ||||
| 	0x26, 0xe8, 0x11, 0xf6, 0x02, 0x20, 0x48, 0x73, 0xa9, 0x9c, 0x84, 0xe6, 0xf1, 0x8c, 0x98, 0x89, | ||||
| 	0xcf, 0x43, 0xbf, 0x78, 0x06, 0xa7, 0xdd, 0x2c, 0x53, 0x59, 0xe8, 0x8f, 0x02, 0x70, 0x08, 0x1e, | ||||
| 	0x14, 0x65, 0xb2, 0x28, 0x54, 0x22, 0xda, 0xe4, 0x10, 0x40, 0x47, 0x88, 0x80, 0x43, 0x28, 0x48, | ||||
| 	0xb4, 0xf5, 0x0b, 0xd1, 0x21, 0x87, 0x00, 0xf9, 0x12, 0x00, 0x18, 0x1f, 0xe9, 0x4b, 0xab, 0xbd, | ||||
| 	0x9a, 0x40, 0x8b, 0x5d, 0x1a, 0x1f, 0xd0, 0xef, 0x4b, 0x90, 0x3f, 0x64, 0x1d, 0x98, 0x31, 0xf2, | ||||
| 	0xb3, 0x42, 0x30, 0xfa, 0x05, 0x40, 0xfc, 0x72, 0x56, 0xf0, 0x3d, 0xb6, 0xaa, 0x73, 0x19, 0x7b, | ||||
| 	0x7d, 0xa1, 0x22, 0xf4, 0xa4, 0x87, 0xfc, 0x4a, 0x09, 0x1e, 0x80, 0x37, 0xdb, 0xac, 0x57, 0x97, | ||||
| 	0xac, 0x50, 0x9b, 0x35, 0x41, 0xbd, 0x0a, 0xba, 0xb8, 0xfa, 0xcf, 0x2a, 0xcf, 0xc0, 0xcd, 0xaa, | ||||
| 	0x0a, 0x4a, 0xee, 0xd4, 0xab, 0xa0, 0x60, 0x87, 0xf5, 0xe6, 0xb9, 0xba, 0xd0, 0xb1, 0x97, 0x93, | ||||
| 	0x54, 0x89, 0xbb, 0xe4, 0x76, 0x0d, 0xe2, 0xef, 0xb2, 0x35, 0x70, 0x38, 0xb2, 0x2a, 0x4e, 0xa5, | ||||
| 	0xce, 0x50, 0xb6, 0x86, 0xb2, 0xbb, 0x80, 0x8f, 0x2b, 0x98, 0xbf, 0xcf, 0x38, 0x4a, 0xe7, 0x79, | ||||
| 	0x5d, 0x7c, 0x0f, 0xc5, 0xf7, 0x80, 0x39, 0xa9, 0x13, 0x70, 0x47, 0x8a, 0xe9, 0xa9, 0x9c, 0xa7, | ||||
| 	0x5e, 0x70, 0x72, 0x28, 0x84, 0xbc, 0xcf, 0x58, 0x31, 0xcd, 0xe4, 0x19, 0x91, 0xf7, 0xa9, 0xeb, | ||||
| 	0x0a, 0x81, 0x07, 0x5d, 0x1a, 0x7b, 0xae, 0xf3, 0xa9, 0x53, 0x3e, 0xb2, 0x8a, 0x74, 0xeb, 0xf4, | ||||
| 	0xa0, 0x8a, 0x19, 0x13, 0xc1, 0x47, 0xec, 0x7e, 0x4d, 0x8e, 0xd3, 0x4b, 0xaf, 0xc4, 0x03, 0xd4, | ||||
| 	0xd7, 0x2a, 0x1d, 0x04, 0x86, 0x7f, 0xcc, 0x36, 0x6a, 0x09, 0xb9, 0x49, 0x54, 0xe8, 0x5b, 0x6c, | ||||
| 	0x60, 0xce, 0x83, 0x8a, 0xfd, 0xae, 0x22, 0xf9, 0x26, 0xeb, 0x14, 0x53, 0xab, 0x4e, 0x75, 0x9a, | ||||
| 	0x8a, 0xff, 0xd1, 0xc5, 0x2c, 0x63, 0xbe, 0xc1, 0x5a, 0xc5, 0xd4, 0xc5, 0x32, 0x17, 0x02, 0x99, | ||||
| 	0x10, 0x91, 0x09, 0xce, 0x2b, 0x99, 0x8a, 0x87, 0xa5, 0x09, 0x18, 0x92, 0x09, 0xd7, 0xcd, 0x6e, | ||||
| 	0x96, 0x26, 0x94, 0x08, 0x1f, 0xb0, 0x95, 0x62, 0x9a, 0xa8, 0x6b, 0xc5, 0x23, 0x7a, 0xff, 0x75, | ||||
| 	0x8c, 0x6a, 0xa4, 0xf2, 0x87, 0xc5, 0xa9, 0x55, 0x4a, 0xfc, 0xbf, 0xac, 0x51, 0x22, 0xf0, 0xfa, | ||||
| 	0xab, 0x28, 0x11, 0x5b, 0xf4, 0xfa, 0x6b, 0x10, 0x7f, 0x87, 0xdd, 0xf5, 0xb3, 0x22, 0x42, 0x23, | ||||
| 	0x23, 0x99, 0xa6, 0x26, 0x16, 0xfd, 0xf2, 0xba, 0x17, 0xcf, 0x00, 0x3d, 0x00, 0x90, 0xbf, 0xc7, | ||||
| 	0x38, 0xe8, 0x62, 0x93, 0xa6, 0xb2, 0x70, 0x2a, 0x48, 0xb7, 0x51, 0xba, 0xe6, 0x67, 0xc5, 0x61, | ||||
| 	0x20, 0x48, 0xbd, 0xce, 0x6e, 0xe3, 0x42, 0x13, 0x3b, 0x74, 0x35, 0x31, 0x80, 0x5f, 0x2b, 0x2d, | ||||
| 	0x3e, 0x5a, 0x90, 0xbb, 0xd4, 0x2e, 0x42, 0xdf, 0x02, 0x02, 0x57, 0xd3, 0x5d, 0xca, 0x22, 0xa2, | ||||
| 	0xdc, 0x01, 0x5d, 0x4d, 0x40, 0x4e, 0x30, 0xbf, 0xa4, 0x29, 0x7d, 0xaf, 0xa2, 0x31, 0x7b, 0xf0, | ||||
| 	0x53, 0x83, 0x75, 0xca, 0x25, 0xcf, 0xbf, 0xa8, 0x2f, 0xe8, 0xe5, 0xc7, 0xbd, 0xfd, 0xbd, 0x37, | ||||
| 	0x7f, 0x19, 0xbe, 0xca, 0xbd, 0x5d, 0x54, 0x5b, 0xfc, 0xb3, 0x6a, 0x8b, 0xff, 0xe7, 0xe4, 0xb0, | ||||
| 	0xea, 0x15, 0xeb, 0x5e, 0x63, 0xf0, 0xb3, 0x48, 0xe0, 0xae, 0x29, 0x5c, 0x8c, 0xdd, 0x71, 0x88, | ||||
| 	0xc0, 0x8a, 0x59, 0x2c, 0xa3, 0x99, 0xcc, 0x93, 0x54, 0x39, 0xdc, 0x90, 0xab, 0x63, 0x36, 0x8b, | ||||
| 	0xe5, 0xd7, 0x84, 0x94, 0x02, 0x33, 0x39, 0x53, 0xb1, 0x77, 0xb8, 0x26, 0x49, 0xf0, 0x9c, 0x90, | ||||
| 	0xc1, 0x01, 0x6b, 0xd1, 0xb7, 0x89, 0x7f, 0x5a, 0x9a, 0x4d, 0x83, 0xee, 0xbe, 0xe9, 0x63, 0x16, | ||||
| 	0x3a, 0x45, 0xfd, 0xe0, 0xe7, 0x06, 0x6b, 0x07, 0x08, 0xde, 0x58, 0x26, 0xcf, 0x8c, 0x0d, 0x0b, | ||||
| 	0x9c, 0x02, 0x44, 0x75, 0x6e, 0x6c, 0xf9, 0x31, 0xc3, 0x00, 0x86, 0xb2, 0x93, 0x85, 0x57, 0x2e, | ||||
| 	0x6c, 0xef, 0x10, 0x01, 0x7e, 0x49, 0x38, 0xad, 0xee, 0x10, 0xc1, 0xf2, 0xb6, 0xda, 0xb8, 0x72, | ||||
| 	0x79, 0xc3, 0x19, 0xb0, 0x4b, 0xc0, 0x68, 0x77, 0xe3, 0xf9, 0xa9, 0x78, 0xf5, 0xba, 0x7f, 0xeb, | ||||
| 	0x8f, 0xd7, 0xfd, 0x5b, 0x3f, 0x5e, 0xf5, 0x1b, 0xaf, 0xae, 0xfa, 0x8d, 0xdf, 0xaf, 0xfa, 0x8d, | ||||
| 	0xbf, 0xae, 0xfa, 0x8d, 0x49, 0x0b, 0xff, 0xab, 0x7c, 0xf8, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, | ||||
| 	0xf0, 0xd3, 0x07, 0x15, 0x13, 0x09, 0x00, 0x00, | ||||
| } | ||||
|  | ||||
| func (m *Metrics) Marshal() (dAtA []byte, err error) { | ||||
| @@ -437,6 +529,16 @@ func (m *Metrics) MarshalTo(dAtA []byte) (int, error) { | ||||
| 		} | ||||
| 		i += n4 | ||||
| 	} | ||||
| 	if m.Io != nil { | ||||
| 		dAtA[i] = 0x32 | ||||
| 		i++ | ||||
| 		i = encodeVarintMetrics(dAtA, i, uint64(m.Io.Size())) | ||||
| 		n5, err := m.Io.MarshalTo(dAtA[i:]) | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 		i += n5 | ||||
| 	} | ||||
| 	if m.XXX_unrecognized != nil { | ||||
| 		i += copy(dAtA[i:], m.XXX_unrecognized) | ||||
| 	} | ||||
| @@ -843,6 +945,90 @@ func (m *RdmaEntry) MarshalTo(dAtA []byte) (int, error) { | ||||
| 	return i, nil | ||||
| } | ||||
|  | ||||
| func (m *IOStat) Marshal() (dAtA []byte, err error) { | ||||
| 	size := m.Size() | ||||
| 	dAtA = make([]byte, size) | ||||
| 	n, err := m.MarshalTo(dAtA) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return dAtA[:n], nil | ||||
| } | ||||
|  | ||||
| func (m *IOStat) MarshalTo(dAtA []byte) (int, error) { | ||||
| 	var i int | ||||
| 	_ = i | ||||
| 	var l int | ||||
| 	_ = l | ||||
| 	if len(m.Usage) > 0 { | ||||
| 		for _, msg := range m.Usage { | ||||
| 			dAtA[i] = 0xa | ||||
| 			i++ | ||||
| 			i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) | ||||
| 			n, err := msg.MarshalTo(dAtA[i:]) | ||||
| 			if err != nil { | ||||
| 				return 0, err | ||||
| 			} | ||||
| 			i += n | ||||
| 		} | ||||
| 	} | ||||
| 	if m.XXX_unrecognized != nil { | ||||
| 		i += copy(dAtA[i:], m.XXX_unrecognized) | ||||
| 	} | ||||
| 	return i, nil | ||||
| } | ||||
|  | ||||
| func (m *IOEntry) Marshal() (dAtA []byte, err error) { | ||||
| 	size := m.Size() | ||||
| 	dAtA = make([]byte, size) | ||||
| 	n, err := m.MarshalTo(dAtA) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return dAtA[:n], nil | ||||
| } | ||||
|  | ||||
| func (m *IOEntry) MarshalTo(dAtA []byte) (int, error) { | ||||
| 	var i int | ||||
| 	_ = i | ||||
| 	var l int | ||||
| 	_ = l | ||||
| 	if m.Major != 0 { | ||||
| 		dAtA[i] = 0x8 | ||||
| 		i++ | ||||
| 		i = encodeVarintMetrics(dAtA, i, uint64(m.Major)) | ||||
| 	} | ||||
| 	if m.Minor != 0 { | ||||
| 		dAtA[i] = 0x10 | ||||
| 		i++ | ||||
| 		i = encodeVarintMetrics(dAtA, i, uint64(m.Minor)) | ||||
| 	} | ||||
| 	if m.Rbytes != 0 { | ||||
| 		dAtA[i] = 0x18 | ||||
| 		i++ | ||||
| 		i = encodeVarintMetrics(dAtA, i, uint64(m.Rbytes)) | ||||
| 	} | ||||
| 	if m.Wbytes != 0 { | ||||
| 		dAtA[i] = 0x20 | ||||
| 		i++ | ||||
| 		i = encodeVarintMetrics(dAtA, i, uint64(m.Wbytes)) | ||||
| 	} | ||||
| 	if m.Rios != 0 { | ||||
| 		dAtA[i] = 0x28 | ||||
| 		i++ | ||||
| 		i = encodeVarintMetrics(dAtA, i, uint64(m.Rios)) | ||||
| 	} | ||||
| 	if m.Wios != 0 { | ||||
| 		dAtA[i] = 0x30 | ||||
| 		i++ | ||||
| 		i = encodeVarintMetrics(dAtA, i, uint64(m.Wios)) | ||||
| 	} | ||||
| 	if m.XXX_unrecognized != nil { | ||||
| 		i += copy(dAtA[i:], m.XXX_unrecognized) | ||||
| 	} | ||||
| 	return i, nil | ||||
| } | ||||
|  | ||||
| func encodeVarintMetrics(dAtA []byte, offset int, v uint64) int { | ||||
| 	for v >= 1<<7 { | ||||
| 		dAtA[offset] = uint8(v&0x7f | 0x80) | ||||
| @@ -874,6 +1060,10 @@ func (m *Metrics) Size() (n int) { | ||||
| 		l = m.Rdma.Size() | ||||
| 		n += 1 + l + sovMetrics(uint64(l)) | ||||
| 	} | ||||
| 	if m.Io != nil { | ||||
| 		l = m.Io.Size() | ||||
| 		n += 1 + l + sovMetrics(uint64(l)) | ||||
| 	} | ||||
| 	if m.XXX_unrecognized != nil { | ||||
| 		n += len(m.XXX_unrecognized) | ||||
| 	} | ||||
| @@ -1091,6 +1281,54 @@ func (m *RdmaEntry) Size() (n int) { | ||||
| 	return n | ||||
| } | ||||
|  | ||||
| func (m *IOStat) Size() (n int) { | ||||
| 	if m == nil { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	var l int | ||||
| 	_ = l | ||||
| 	if len(m.Usage) > 0 { | ||||
| 		for _, e := range m.Usage { | ||||
| 			l = e.Size() | ||||
| 			n += 1 + l + sovMetrics(uint64(l)) | ||||
| 		} | ||||
| 	} | ||||
| 	if m.XXX_unrecognized != nil { | ||||
| 		n += len(m.XXX_unrecognized) | ||||
| 	} | ||||
| 	return n | ||||
| } | ||||
|  | ||||
| func (m *IOEntry) Size() (n int) { | ||||
| 	if m == nil { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	var l int | ||||
| 	_ = l | ||||
| 	if m.Major != 0 { | ||||
| 		n += 1 + sovMetrics(uint64(m.Major)) | ||||
| 	} | ||||
| 	if m.Minor != 0 { | ||||
| 		n += 1 + sovMetrics(uint64(m.Minor)) | ||||
| 	} | ||||
| 	if m.Rbytes != 0 { | ||||
| 		n += 1 + sovMetrics(uint64(m.Rbytes)) | ||||
| 	} | ||||
| 	if m.Wbytes != 0 { | ||||
| 		n += 1 + sovMetrics(uint64(m.Wbytes)) | ||||
| 	} | ||||
| 	if m.Rios != 0 { | ||||
| 		n += 1 + sovMetrics(uint64(m.Rios)) | ||||
| 	} | ||||
| 	if m.Wios != 0 { | ||||
| 		n += 1 + sovMetrics(uint64(m.Wios)) | ||||
| 	} | ||||
| 	if m.XXX_unrecognized != nil { | ||||
| 		n += len(m.XXX_unrecognized) | ||||
| 	} | ||||
| 	return n | ||||
| } | ||||
|  | ||||
| func sovMetrics(x uint64) (n int) { | ||||
| 	for { | ||||
| 		n++ | ||||
| @@ -1113,6 +1351,7 @@ func (this *Metrics) String() string { | ||||
| 		`CPU:` + strings.Replace(fmt.Sprintf("%v", this.CPU), "CPUStat", "CPUStat", 1) + `,`, | ||||
| 		`Memory:` + strings.Replace(fmt.Sprintf("%v", this.Memory), "MemoryStat", "MemoryStat", 1) + `,`, | ||||
| 		`Rdma:` + strings.Replace(fmt.Sprintf("%v", this.Rdma), "RdmaStat", "RdmaStat", 1) + `,`, | ||||
| 		`Io:` + strings.Replace(fmt.Sprintf("%v", this.Io), "IOStat", "IOStat", 1) + `,`, | ||||
| 		`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, | ||||
| 		`}`, | ||||
| 	}, "") | ||||
| @@ -1216,6 +1455,33 @@ func (this *RdmaEntry) String() string { | ||||
| 	}, "") | ||||
| 	return s | ||||
| } | ||||
| func (this *IOStat) String() string { | ||||
| 	if this == nil { | ||||
| 		return "nil" | ||||
| 	} | ||||
| 	s := strings.Join([]string{`&IOStat{`, | ||||
| 		`Usage:` + strings.Replace(fmt.Sprintf("%v", this.Usage), "IOEntry", "IOEntry", 1) + `,`, | ||||
| 		`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, | ||||
| 		`}`, | ||||
| 	}, "") | ||||
| 	return s | ||||
| } | ||||
| func (this *IOEntry) String() string { | ||||
| 	if this == nil { | ||||
| 		return "nil" | ||||
| 	} | ||||
| 	s := strings.Join([]string{`&IOEntry{`, | ||||
| 		`Major:` + fmt.Sprintf("%v", this.Major) + `,`, | ||||
| 		`Minor:` + fmt.Sprintf("%v", this.Minor) + `,`, | ||||
| 		`Rbytes:` + fmt.Sprintf("%v", this.Rbytes) + `,`, | ||||
| 		`Wbytes:` + fmt.Sprintf("%v", this.Wbytes) + `,`, | ||||
| 		`Rios:` + fmt.Sprintf("%v", this.Rios) + `,`, | ||||
| 		`Wios:` + fmt.Sprintf("%v", this.Wios) + `,`, | ||||
| 		`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, | ||||
| 		`}`, | ||||
| 	}, "") | ||||
| 	return s | ||||
| } | ||||
| func valueToStringMetrics(v interface{}) string { | ||||
| 	rv := reflect.ValueOf(v) | ||||
| 	if rv.IsNil() { | ||||
| @@ -1397,6 +1663,42 @@ func (m *Metrics) Unmarshal(dAtA []byte) error { | ||||
| 				return err | ||||
| 			} | ||||
| 			iNdEx = postIndex | ||||
| 		case 6: | ||||
| 			if wireType != 2 { | ||||
| 				return fmt.Errorf("proto: wrong wireType = %d for field Io", wireType) | ||||
| 			} | ||||
| 			var msglen int | ||||
| 			for shift := uint(0); ; shift += 7 { | ||||
| 				if shift >= 64 { | ||||
| 					return ErrIntOverflowMetrics | ||||
| 				} | ||||
| 				if iNdEx >= l { | ||||
| 					return io.ErrUnexpectedEOF | ||||
| 				} | ||||
| 				b := dAtA[iNdEx] | ||||
| 				iNdEx++ | ||||
| 				msglen |= int(b&0x7F) << shift | ||||
| 				if b < 0x80 { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 			if msglen < 0 { | ||||
| 				return ErrInvalidLengthMetrics | ||||
| 			} | ||||
| 			postIndex := iNdEx + msglen | ||||
| 			if postIndex < 0 { | ||||
| 				return ErrInvalidLengthMetrics | ||||
| 			} | ||||
| 			if postIndex > l { | ||||
| 				return io.ErrUnexpectedEOF | ||||
| 			} | ||||
| 			if m.Io == nil { | ||||
| 				m.Io = &IOStat{} | ||||
| 			} | ||||
| 			if err := m.Io.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			iNdEx = postIndex | ||||
| 		default: | ||||
| 			iNdEx = preIndex | ||||
| 			skippy, err := skipMetrics(dAtA[iNdEx:]) | ||||
| @@ -2647,6 +2949,262 @@ func (m *RdmaEntry) Unmarshal(dAtA []byte) error { | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| func (m *IOStat) Unmarshal(dAtA []byte) error { | ||||
| 	l := len(dAtA) | ||||
| 	iNdEx := 0 | ||||
| 	for iNdEx < l { | ||||
| 		preIndex := iNdEx | ||||
| 		var wire uint64 | ||||
| 		for shift := uint(0); ; shift += 7 { | ||||
| 			if shift >= 64 { | ||||
| 				return ErrIntOverflowMetrics | ||||
| 			} | ||||
| 			if iNdEx >= l { | ||||
| 				return io.ErrUnexpectedEOF | ||||
| 			} | ||||
| 			b := dAtA[iNdEx] | ||||
| 			iNdEx++ | ||||
| 			wire |= uint64(b&0x7F) << shift | ||||
| 			if b < 0x80 { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		fieldNum := int32(wire >> 3) | ||||
| 		wireType := int(wire & 0x7) | ||||
| 		if wireType == 4 { | ||||
| 			return fmt.Errorf("proto: IOStat: wiretype end group for non-group") | ||||
| 		} | ||||
| 		if fieldNum <= 0 { | ||||
| 			return fmt.Errorf("proto: IOStat: illegal tag %d (wire type %d)", fieldNum, wire) | ||||
| 		} | ||||
| 		switch fieldNum { | ||||
| 		case 1: | ||||
| 			if wireType != 2 { | ||||
| 				return fmt.Errorf("proto: wrong wireType = %d for field Usage", wireType) | ||||
| 			} | ||||
| 			var msglen int | ||||
| 			for shift := uint(0); ; shift += 7 { | ||||
| 				if shift >= 64 { | ||||
| 					return ErrIntOverflowMetrics | ||||
| 				} | ||||
| 				if iNdEx >= l { | ||||
| 					return io.ErrUnexpectedEOF | ||||
| 				} | ||||
| 				b := dAtA[iNdEx] | ||||
| 				iNdEx++ | ||||
| 				msglen |= int(b&0x7F) << shift | ||||
| 				if b < 0x80 { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 			if msglen < 0 { | ||||
| 				return ErrInvalidLengthMetrics | ||||
| 			} | ||||
| 			postIndex := iNdEx + msglen | ||||
| 			if postIndex < 0 { | ||||
| 				return ErrInvalidLengthMetrics | ||||
| 			} | ||||
| 			if postIndex > l { | ||||
| 				return io.ErrUnexpectedEOF | ||||
| 			} | ||||
| 			m.Usage = append(m.Usage, &IOEntry{}) | ||||
| 			if err := m.Usage[len(m.Usage)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			iNdEx = postIndex | ||||
| 		default: | ||||
| 			iNdEx = preIndex | ||||
| 			skippy, err := skipMetrics(dAtA[iNdEx:]) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			if skippy < 0 { | ||||
| 				return ErrInvalidLengthMetrics | ||||
| 			} | ||||
| 			if (iNdEx + skippy) < 0 { | ||||
| 				return ErrInvalidLengthMetrics | ||||
| 			} | ||||
| 			if (iNdEx + skippy) > l { | ||||
| 				return io.ErrUnexpectedEOF | ||||
| 			} | ||||
| 			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) | ||||
| 			iNdEx += skippy | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if iNdEx > l { | ||||
| 		return io.ErrUnexpectedEOF | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| func (m *IOEntry) Unmarshal(dAtA []byte) error { | ||||
| 	l := len(dAtA) | ||||
| 	iNdEx := 0 | ||||
| 	for iNdEx < l { | ||||
| 		preIndex := iNdEx | ||||
| 		var wire uint64 | ||||
| 		for shift := uint(0); ; shift += 7 { | ||||
| 			if shift >= 64 { | ||||
| 				return ErrIntOverflowMetrics | ||||
| 			} | ||||
| 			if iNdEx >= l { | ||||
| 				return io.ErrUnexpectedEOF | ||||
| 			} | ||||
| 			b := dAtA[iNdEx] | ||||
| 			iNdEx++ | ||||
| 			wire |= uint64(b&0x7F) << shift | ||||
| 			if b < 0x80 { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		fieldNum := int32(wire >> 3) | ||||
| 		wireType := int(wire & 0x7) | ||||
| 		if wireType == 4 { | ||||
| 			return fmt.Errorf("proto: IOEntry: wiretype end group for non-group") | ||||
| 		} | ||||
| 		if fieldNum <= 0 { | ||||
| 			return fmt.Errorf("proto: IOEntry: illegal tag %d (wire type %d)", fieldNum, wire) | ||||
| 		} | ||||
| 		switch fieldNum { | ||||
| 		case 1: | ||||
| 			if wireType != 0 { | ||||
| 				return fmt.Errorf("proto: wrong wireType = %d for field Major", wireType) | ||||
| 			} | ||||
| 			m.Major = 0 | ||||
| 			for shift := uint(0); ; shift += 7 { | ||||
| 				if shift >= 64 { | ||||
| 					return ErrIntOverflowMetrics | ||||
| 				} | ||||
| 				if iNdEx >= l { | ||||
| 					return io.ErrUnexpectedEOF | ||||
| 				} | ||||
| 				b := dAtA[iNdEx] | ||||
| 				iNdEx++ | ||||
| 				m.Major |= uint64(b&0x7F) << shift | ||||
| 				if b < 0x80 { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		case 2: | ||||
| 			if wireType != 0 { | ||||
| 				return fmt.Errorf("proto: wrong wireType = %d for field Minor", wireType) | ||||
| 			} | ||||
| 			m.Minor = 0 | ||||
| 			for shift := uint(0); ; shift += 7 { | ||||
| 				if shift >= 64 { | ||||
| 					return ErrIntOverflowMetrics | ||||
| 				} | ||||
| 				if iNdEx >= l { | ||||
| 					return io.ErrUnexpectedEOF | ||||
| 				} | ||||
| 				b := dAtA[iNdEx] | ||||
| 				iNdEx++ | ||||
| 				m.Minor |= uint64(b&0x7F) << shift | ||||
| 				if b < 0x80 { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		case 3: | ||||
| 			if wireType != 0 { | ||||
| 				return fmt.Errorf("proto: wrong wireType = %d for field Rbytes", wireType) | ||||
| 			} | ||||
| 			m.Rbytes = 0 | ||||
| 			for shift := uint(0); ; shift += 7 { | ||||
| 				if shift >= 64 { | ||||
| 					return ErrIntOverflowMetrics | ||||
| 				} | ||||
| 				if iNdEx >= l { | ||||
| 					return io.ErrUnexpectedEOF | ||||
| 				} | ||||
| 				b := dAtA[iNdEx] | ||||
| 				iNdEx++ | ||||
| 				m.Rbytes |= uint64(b&0x7F) << shift | ||||
| 				if b < 0x80 { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		case 4: | ||||
| 			if wireType != 0 { | ||||
| 				return fmt.Errorf("proto: wrong wireType = %d for field Wbytes", wireType) | ||||
| 			} | ||||
| 			m.Wbytes = 0 | ||||
| 			for shift := uint(0); ; shift += 7 { | ||||
| 				if shift >= 64 { | ||||
| 					return ErrIntOverflowMetrics | ||||
| 				} | ||||
| 				if iNdEx >= l { | ||||
| 					return io.ErrUnexpectedEOF | ||||
| 				} | ||||
| 				b := dAtA[iNdEx] | ||||
| 				iNdEx++ | ||||
| 				m.Wbytes |= uint64(b&0x7F) << shift | ||||
| 				if b < 0x80 { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		case 5: | ||||
| 			if wireType != 0 { | ||||
| 				return fmt.Errorf("proto: wrong wireType = %d for field Rios", wireType) | ||||
| 			} | ||||
| 			m.Rios = 0 | ||||
| 			for shift := uint(0); ; shift += 7 { | ||||
| 				if shift >= 64 { | ||||
| 					return ErrIntOverflowMetrics | ||||
| 				} | ||||
| 				if iNdEx >= l { | ||||
| 					return io.ErrUnexpectedEOF | ||||
| 				} | ||||
| 				b := dAtA[iNdEx] | ||||
| 				iNdEx++ | ||||
| 				m.Rios |= uint64(b&0x7F) << shift | ||||
| 				if b < 0x80 { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		case 6: | ||||
| 			if wireType != 0 { | ||||
| 				return fmt.Errorf("proto: wrong wireType = %d for field Wios", wireType) | ||||
| 			} | ||||
| 			m.Wios = 0 | ||||
| 			for shift := uint(0); ; shift += 7 { | ||||
| 				if shift >= 64 { | ||||
| 					return ErrIntOverflowMetrics | ||||
| 				} | ||||
| 				if iNdEx >= l { | ||||
| 					return io.ErrUnexpectedEOF | ||||
| 				} | ||||
| 				b := dAtA[iNdEx] | ||||
| 				iNdEx++ | ||||
| 				m.Wios |= uint64(b&0x7F) << shift | ||||
| 				if b < 0x80 { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		default: | ||||
| 			iNdEx = preIndex | ||||
| 			skippy, err := skipMetrics(dAtA[iNdEx:]) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			if skippy < 0 { | ||||
| 				return ErrInvalidLengthMetrics | ||||
| 			} | ||||
| 			if (iNdEx + skippy) < 0 { | ||||
| 				return ErrInvalidLengthMetrics | ||||
| 			} | ||||
| 			if (iNdEx + skippy) > l { | ||||
| 				return io.ErrUnexpectedEOF | ||||
| 			} | ||||
| 			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) | ||||
| 			iNdEx += skippy | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if iNdEx > l { | ||||
| 		return io.ErrUnexpectedEOF | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| func skipMetrics(dAtA []byte) (n int, err error) { | ||||
| 	l := len(dAtA) | ||||
| 	iNdEx := 0 | ||||
|   | ||||
							
								
								
									
										15
									
								
								vendor/github.com/containerd/cgroups/v2/stats/metrics.proto
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/containerd/cgroups/v2/stats/metrics.proto
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -9,6 +9,7 @@ message Metrics { | ||||
| 	CPUStat cpu = 2 [(gogoproto.customname) = "CPU"]; | ||||
| 	MemoryStat memory = 4; | ||||
| 	RdmaStat rdma = 5; | ||||
| 	IOStat io = 6; | ||||
| } | ||||
|  | ||||
| message PidsStat { | ||||
| @@ -74,5 +75,15 @@ message RdmaEntry { | ||||
| 	uint32 hca_objects = 3; | ||||
| } | ||||
|  | ||||
| // iostat | ||||
| // fmt: 230:0 rbytes=394211328 wbytes=65044480 rios=16313 wios=2006 dbytes=0 dios=0 | ||||
| message IOStat { | ||||
| 	repeated IOEntry usage = 1; | ||||
| } | ||||
|  | ||||
| message IOEntry { | ||||
| 	uint64 major = 1; | ||||
| 	uint64 minor = 2; | ||||
| 	uint64 rbytes = 3; | ||||
| 	uint64 wbytes = 4; | ||||
| 	uint64 rios = 5; | ||||
| 	uint64 wios = 6; | ||||
| } | ||||
|   | ||||
							
								
								
									
										79
									
								
								vendor/github.com/containerd/cgroups/v2/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										79
									
								
								vendor/github.com/containerd/cgroups/v2/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -23,10 +23,13 @@ import ( | ||||
| 	"io/ioutil" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/godbus/dbus/v5" | ||||
|  | ||||
| 	"github.com/containerd/cgroups/v2/stats" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/pkg/errors" | ||||
| @@ -176,7 +179,7 @@ func ToResources(spec *specs.LinuxResources) *Resources { | ||||
| 			resources.CPU.Weight = &convertedWeight | ||||
| 		} | ||||
| 		if period := cpu.Period; period != nil { | ||||
| 			resources.CPU.Max = period | ||||
| 			resources.CPU.Max = NewCPUMax(cpu.Quota, period) | ||||
| 		} | ||||
| 	} | ||||
| 	if mem := spec.Memory; mem != nil { | ||||
| @@ -237,7 +240,6 @@ func ToResources(spec *specs.LinuxResources) *Resources { | ||||
| func getStatFileContentUint64(filePath string) uint64 { | ||||
| 	contents, err := ioutil.ReadFile(filePath) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return 0 | ||||
| 	} | ||||
| 	trimmed := strings.TrimSpace(string(contents)) | ||||
| @@ -253,6 +255,64 @@ func getStatFileContentUint64(filePath string) uint64 { | ||||
|  | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| func readIoStats(path string) []*stats.IOEntry { | ||||
| 	// more details on the io.stat file format: https://www.kernel.org/doc/Documentation/cgroup-v2.txt | ||||
| 	var usage []*stats.IOEntry | ||||
| 	fpath := filepath.Join(path, "io.stat") | ||||
| 	currentData, err := ioutil.ReadFile(fpath) | ||||
| 	if err != nil { | ||||
| 		return usage | ||||
| 	} | ||||
| 	entries := strings.Split(string(currentData), "\n") | ||||
|  | ||||
| 	for _, entry := range entries { | ||||
| 		parts := strings.Split(entry, " ") | ||||
| 		if len(parts) < 2 { | ||||
| 			continue | ||||
| 		} | ||||
| 		majmin := strings.Split(parts[0], ":") | ||||
| 		if len(majmin) != 2 { | ||||
| 			continue | ||||
| 		} | ||||
| 		major, err := strconv.ParseUint(majmin[0], 10, 0) | ||||
| 		if err != nil { | ||||
| 			return usage | ||||
| 		} | ||||
| 		minor, err := strconv.ParseUint(majmin[1], 10, 0) | ||||
| 		if err != nil { | ||||
| 			return usage | ||||
| 		} | ||||
| 		parts = parts[1:] | ||||
| 		ioEntry := stats.IOEntry{ | ||||
| 			Major: major, | ||||
| 			Minor: minor, | ||||
| 		} | ||||
| 		for _, stats := range parts { | ||||
| 			keyPairValue := strings.Split(stats, "=") | ||||
| 			if len(keyPairValue) != 2 { | ||||
| 				continue | ||||
| 			} | ||||
| 			v, err := strconv.ParseUint(keyPairValue[1], 10, 0) | ||||
| 			if err != nil { | ||||
| 				continue | ||||
| 			} | ||||
| 			switch keyPairValue[0] { | ||||
| 			case "rbytes": | ||||
| 				ioEntry.Rbytes = v | ||||
| 			case "wbytes": | ||||
| 				ioEntry.Wbytes = v | ||||
| 			case "rios": | ||||
| 				ioEntry.Rios = v | ||||
| 			case "wios": | ||||
| 				ioEntry.Wios = v | ||||
| 			} | ||||
| 		} | ||||
| 		usage = append(usage, &ioEntry) | ||||
| 	} | ||||
| 	return usage | ||||
| } | ||||
|  | ||||
| func rdmaStats(filepath string) []*stats.RdmaEntry { | ||||
| 	currentData, err := ioutil.ReadFile(filepath) | ||||
| 	if err != nil { | ||||
| @@ -302,3 +362,18 @@ func toRdmaEntry(strEntries []string) []*stats.RdmaEntry { | ||||
| 	} | ||||
| 	return rdmaEntries | ||||
| } | ||||
|  | ||||
| // isUnitExists returns true if the error is that a systemd unit already exists. | ||||
| func isUnitExists(err error) bool { | ||||
| 	if err != nil { | ||||
| 		if dbusError, ok := err.(dbus.Error); ok { | ||||
| 			return strings.Contains(dbusError.Name, "org.freedesktop.systemd1.UnitExists") | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func systemdUnitFromPath(path string) string { | ||||
| 	_, unit := filepath.Split(path) | ||||
| 	return unit | ||||
| } | ||||
|   | ||||
							
								
								
									
										8
									
								
								vendor/github.com/containerd/containerd/vendor.conf
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/containerd/containerd/vendor.conf
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,19 +1,19 @@ | ||||
| github.com/beorn7/perks                             4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 | ||||
| github.com/BurntSushi/toml                          3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1 | ||||
| github.com/containerd/btrfs                         af5082808c833de0e79c1e72eea9fea239364877 | ||||
| github.com/containerd/cgroups                       fada802a7909d430bd17126fd6e4bbf5716f2bcd | ||||
| github.com/containerd/cgroups                       7347743e5d1e8500d9f27c8e748e689ed991d92b | ||||
| github.com/containerd/console                       8375c3424e4d7b114e8a90a4a40c8e1b40d1d4e6 | ||||
| github.com/containerd/continuity                    0ec596719c75bfd42908850990acea594b7593ac | ||||
| github.com/containerd/fifo                          bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13 | ||||
| github.com/containerd/go-runc                       a5c2862aed5e6358b305b0e16bfce58e0549b1cd | ||||
| github.com/containerd/ttrpc                         92c8520ef9f86600c650dd540266a007bf03670f | ||||
| github.com/containerd/typeurl                       a93fcdb778cd272c6e9b3028b2f42d813e785d40 | ||||
| github.com/coreos/go-systemd                        48702e0da86bd25e76cfef347e2adeb434a0d0a6 | ||||
| github.com/coreos/go-systemd/v22                    2d78030078ef61b3cae27f42ad6d0e46db51b339 # v22.0.0 | ||||
| github.com/cpuguy83/go-md2man                       7762f7e404f8416dfa1d9bb6a8c192aa9acb4d19 # v1.0.10 | ||||
| github.com/docker/go-events                         9461782956ad83b30282bf90e31fa6a70c255ba9 | ||||
| github.com/docker/go-metrics                        4ea375f7759c82740c893fc030bc37088d2ec098 | ||||
| github.com/docker/go-units                          519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0 | ||||
| github.com/godbus/dbus                              c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f | ||||
| github.com/godbus/dbus/v5                           37bf87eef99d69c4f1d3528bd66e3a87dc201472 # v5.0.3 | ||||
| github.com/gogo/googleapis                          d31c731455cb061f42baff3bda55bad0118b126b # v1.2.0 | ||||
| github.com/gogo/protobuf                            ba06b47c162d49f2af050fb4c75bcbc86a159d5c # v1.2.1 | ||||
| github.com/golang/protobuf                          aa810b61a9c79d51363740d207bb46cf8e620ed5 # v1.2.0 | ||||
| @@ -27,7 +27,7 @@ github.com/imdario/mergo                            7c29201646fa3de8506f70121347 | ||||
| github.com/konsorten/go-windows-terminal-sequences  5c8c8bd35d3832f5d134ae1e1e375b69a4d25242 # v1.0.1 | ||||
| github.com/matttproud/golang_protobuf_extensions    c12348ce28de40eed0136aa2b644d0ee0650e56c # v1.0.1 | ||||
| github.com/Microsoft/go-winio                       6c72808b55902eae4c5943626030429ff20f3b63 # v0.4.14 | ||||
| github.com/Microsoft/hcsshim                        d2849cbdb9dfe5f513292a9610ca2eb734cdd1e7 | ||||
| github.com/Microsoft/hcsshim                        b3f49c06ffaeef24d09c6c08ec8ec8425a0303e2 # v0.8.7 | ||||
| github.com/opencontainers/go-digest                 c9281466c8b2f606084ac71339773efd177436e7 | ||||
| github.com/opencontainers/image-spec                d60099175f88c47cd379c4738d158884749ed235 # v1.0.1 | ||||
| github.com/opencontainers/runc                      d736ef14f0288d6993a1845745d6756cfc9ddd5a # v1.0.0-rc9 | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/coreos/go-systemd/v22/NOTICE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/coreos/go-systemd/v22/NOTICE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| CoreOS Project | ||||
| Copyright 2018 CoreOS, Inc | ||||
|  | ||||
| This product includes software developed at CoreOS, Inc. | ||||
| (http://www.coreos.com/). | ||||
| @@ -2,13 +2,17 @@ | ||||
| 
 | ||||
| [](https://travis-ci.org/coreos/go-systemd) | ||||
| [](http://godoc.org/github.com/coreos/go-systemd) | ||||
|  | ||||
| 
 | ||||
| 
 | ||||
| Go bindings to systemd. The project has several packages: | ||||
| 
 | ||||
| - `activation` - for writing and using socket activation from Go | ||||
| - `daemon` - for notifying systemd of service status changes | ||||
| - `dbus` - for starting/stopping/inspecting running services and units | ||||
| - `journal` - for writing to systemd's logging service, journald | ||||
| - `sdjournal` - for reading from journald by wrapping its C API | ||||
| - `login1` - for integration with the systemd logind API | ||||
| - `machine1` - for registering machines/containers with systemd | ||||
| - `unit` - for (de)serialization and comparison of unit files | ||||
| 
 | ||||
| @@ -18,10 +22,9 @@ An example HTTP server using socket activation can be quickly set up by followin | ||||
| 
 | ||||
| https://github.com/coreos/go-systemd/tree/master/examples/activation/httpserver | ||||
| 
 | ||||
| ## Journal | ||||
| ## systemd Service Notification | ||||
| 
 | ||||
| Using the pure-Go `journal` package you can submit journal entries directly to systemd's journal, taking advantage of features like indexed key/value pairs for each log entry. | ||||
| The `sdjournal` package provides read access to the journal by wrapping around journald's native C API; consequently it requires cgo and the journal headers to be available. | ||||
| The `daemon` package is an implementation of the [sd_notify protocol](https://www.freedesktop.org/software/systemd/man/sd_notify.html#Description). It can be used to inform systemd of service start-up completion, watchdog events, and other status changes. | ||||
| 
 | ||||
| ## D-Bus | ||||
| 
 | ||||
| @@ -45,6 +48,20 @@ Create `/etc/dbus-1/system-local.conf` that looks like this: | ||||
| </busconfig> | ||||
| ``` | ||||
| 
 | ||||
| ## Journal | ||||
| 
 | ||||
| ### Writing to the Journal | ||||
| 
 | ||||
| Using the pure-Go `journal` package you can submit journal entries directly to systemd's journal, taking advantage of features like indexed key/value pairs for each log entry. | ||||
| 
 | ||||
| ### Reading from the Journal | ||||
| 
 | ||||
| The `sdjournal` package provides read access to the journal by wrapping around journald's native C API; consequently it requires cgo and the journal headers to be available. | ||||
| 
 | ||||
| ## logind | ||||
| 
 | ||||
| The `login1` package provides functions to integrate with the [systemd logind API](http://www.freedesktop.org/wiki/Software/systemd/logind/). | ||||
| 
 | ||||
| ## machined | ||||
| 
 | ||||
| The `machine1` package allows interaction with the [systemd machined D-Bus API](http://www.freedesktop.org/wiki/Software/systemd/machined/). | ||||
| @@ -16,13 +16,14 @@ | ||||
| package dbus | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"github.com/godbus/dbus" | ||||
| 	"github.com/godbus/dbus/v5" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| @@ -60,6 +61,27 @@ func PathBusEscape(path string) string { | ||||
| 	return string(n) | ||||
| } | ||||
| 
 | ||||
| // pathBusUnescape is the inverse of PathBusEscape. | ||||
| func pathBusUnescape(path string) string { | ||||
| 	if path == "_" { | ||||
| 		return "" | ||||
| 	} | ||||
| 	n := []byte{} | ||||
| 	for i := 0; i < len(path); i++ { | ||||
| 		c := path[i] | ||||
| 		if c == '_' && i+2 < len(path) { | ||||
| 			res, err := hex.DecodeString(path[i+1 : i+3]) | ||||
| 			if err == nil { | ||||
| 				n = append(n, res...) | ||||
| 			} | ||||
| 			i += 2 | ||||
| 		} else { | ||||
| 			n = append(n, c) | ||||
| 		} | ||||
| 	} | ||||
| 	return string(n) | ||||
| } | ||||
| 
 | ||||
| // Conn is a connection to systemd's dbus endpoint. | ||||
| type Conn struct { | ||||
| 	// sysconn/sysobj are only used to call dbus methods | ||||
| @@ -74,13 +96,18 @@ type Conn struct { | ||||
| 		jobs map[dbus.ObjectPath]chan<- string | ||||
| 		sync.Mutex | ||||
| 	} | ||||
| 	subscriber struct { | ||||
| 	subStateSubscriber struct { | ||||
| 		updateCh chan<- *SubStateUpdate | ||||
| 		errCh    chan<- error | ||||
| 		sync.Mutex | ||||
| 		ignore      map[dbus.ObjectPath]int64 | ||||
| 		cleanIgnore int64 | ||||
| 	} | ||||
| 	propertiesSubscriber struct { | ||||
| 		updateCh chan<- *PropertiesUpdate | ||||
| 		errCh    chan<- error | ||||
| 		sync.Mutex | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // New establishes a connection to any available bus and authenticates. | ||||
| @@ -116,7 +143,7 @@ func NewUserConnection() (*Conn, error) { | ||||
| func NewSystemdConnection() (*Conn, error) { | ||||
| 	return NewConnection(func() (*dbus.Conn, error) { | ||||
| 		// We skip Hello when talking directly to systemd. | ||||
| 		return dbusAuthConnection(func() (*dbus.Conn, error) { | ||||
| 		return dbusAuthConnection(func(opts ...dbus.ConnOption) (*dbus.Conn, error) { | ||||
| 			return dbus.Dial("unix:path=/run/systemd/private") | ||||
| 		}) | ||||
| 	}) | ||||
| @@ -152,7 +179,7 @@ func NewConnection(dialBus func() (*dbus.Conn, error)) (*Conn, error) { | ||||
| 		sigobj:  systemdObject(sigconn), | ||||
| 	} | ||||
| 
 | ||||
| 	c.subscriber.ignore = make(map[dbus.ObjectPath]int64) | ||||
| 	c.subStateSubscriber.ignore = make(map[dbus.ObjectPath]int64) | ||||
| 	c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string) | ||||
| 
 | ||||
| 	// Setup the listeners on jobs so that we can get completions | ||||
| @@ -174,7 +201,7 @@ func (c *Conn) GetManagerProperty(prop string) (string, error) { | ||||
| 	return variant.String(), nil | ||||
| } | ||||
| 
 | ||||
| func dbusAuthConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) { | ||||
| func dbusAuthConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) { | ||||
| 	conn, err := createBus() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -194,7 +221,7 @@ func dbusAuthConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error | ||||
| 	return conn, nil | ||||
| } | ||||
| 
 | ||||
| func dbusAuthHelloConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) { | ||||
| func dbusAuthHelloConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) { | ||||
| 	conn, err := dbusAuthConnection(createBus) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -1,4 +1,4 @@ | ||||
| // Copyright 2015 CoreOS, Inc. | ||||
| // Copyright 2015, 2018 CoreOS, Inc. | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| @@ -16,10 +16,11 @@ package dbus | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"path" | ||||
| 	"strconv" | ||||
| 
 | ||||
| 	"github.com/godbus/dbus" | ||||
| 	"github.com/godbus/dbus/v5" | ||||
| ) | ||||
| 
 | ||||
| func (c *Conn) jobComplete(signal *dbus.Signal) { | ||||
| @@ -116,13 +117,13 @@ func (c *Conn) TryRestartUnit(name string, mode string, ch chan<- string) (int, | ||||
| 	return c.startJob(ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode) | ||||
| } | ||||
| 
 | ||||
| // ReloadOrRestart attempts a reload if the unit supports it and use a restart | ||||
| // ReloadOrRestartUnit attempts a reload if the unit supports it and use a restart | ||||
| // otherwise. | ||||
| func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) { | ||||
| 	return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode) | ||||
| } | ||||
| 
 | ||||
| // ReloadOrTryRestart attempts a reload if the unit supports it and use a "Try" | ||||
| // ReloadOrTryRestartUnit attempts a reload if the unit supports it and use a "Try" | ||||
| // flavored restart otherwise. | ||||
| func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) { | ||||
| 	return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode) | ||||
| @@ -148,14 +149,27 @@ func (c *Conn) ResetFailedUnit(name string) error { | ||||
| 	return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store() | ||||
| } | ||||
| 
 | ||||
| // getProperties takes the unit name and returns all of its dbus object properties, for the given dbus interface | ||||
| func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]interface{}, error) { | ||||
| // SystemState returns the systemd state. Equivalent to `systemctl is-system-running`. | ||||
| func (c *Conn) SystemState() (*Property, error) { | ||||
| 	var err error | ||||
| 	var prop dbus.Variant | ||||
| 
 | ||||
| 	obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1") | ||||
| 	err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return &Property{Name: "SystemState", Value: prop}, nil | ||||
| } | ||||
| 
 | ||||
| // getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface | ||||
| func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) { | ||||
| 	var err error | ||||
| 	var props map[string]dbus.Variant | ||||
| 
 | ||||
| 	path := unitPath(unit) | ||||
| 	if !path.IsValid() { | ||||
| 		return nil, errors.New("invalid unit name: " + unit) | ||||
| 		return nil, fmt.Errorf("invalid unit name: %v", path) | ||||
| 	} | ||||
| 
 | ||||
| 	obj := c.sysconn.Object("org.freedesktop.systemd1", path) | ||||
| @@ -172,9 +186,21 @@ func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]inte | ||||
| 	return out, nil | ||||
| } | ||||
| 
 | ||||
| // GetUnitProperties takes the unit name and returns all of its dbus object properties. | ||||
| // GetUnitProperties takes the (unescaped) unit name and returns all of its dbus object properties. | ||||
| func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) { | ||||
| 	return c.getProperties(unit, "org.freedesktop.systemd1.Unit") | ||||
| 	path := unitPath(unit) | ||||
| 	return c.getProperties(path, "org.freedesktop.systemd1.Unit") | ||||
| } | ||||
| 
 | ||||
| // GetUnitPathProperties takes the (escaped) unit path and returns all of its dbus object properties. | ||||
| func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) { | ||||
| 	return c.getProperties(path, "org.freedesktop.systemd1.Unit") | ||||
| } | ||||
| 
 | ||||
| // GetAllProperties takes the (unescaped) unit name and returns all of its dbus object properties. | ||||
| func (c *Conn) GetAllProperties(unit string) (map[string]interface{}, error) { | ||||
| 	path := unitPath(unit) | ||||
| 	return c.getProperties(path, "") | ||||
| } | ||||
| 
 | ||||
| func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) { | ||||
| @@ -208,7 +234,8 @@ func (c *Conn) GetServiceProperty(service string, propertyName string) (*Propert | ||||
| // Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope | ||||
| // return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit | ||||
| func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) { | ||||
| 	return c.getProperties(unit, "org.freedesktop.systemd1."+unitType) | ||||
| 	path := unitPath(unit) | ||||
| 	return c.getProperties(path, "org.freedesktop.systemd1."+unitType) | ||||
| } | ||||
| 
 | ||||
| // SetUnitProperties() may be used to modify certain unit properties at runtime. | ||||
| @@ -270,6 +297,8 @@ func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) { | ||||
| // ListUnits returns an array with all currently loaded units. Note that | ||||
| // units may be known by multiple names at the same time, and hence there might | ||||
| // be more unit names loaded than actual units behind them. | ||||
| // Also note that a unit is only loaded if it is active and/or enabled. | ||||
| // Units that are both disabled and inactive will thus not be returned. | ||||
| func (c *Conn) ListUnits() ([]UnitStatus, error) { | ||||
| 	return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store) | ||||
| } | ||||
| @@ -292,6 +321,7 @@ func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitSt | ||||
| // names and returns an UnitStatus array. Comparing to ListUnitsByPatterns | ||||
| // method, this method returns statuses even for inactive or non-existing | ||||
| // units. Input array should contain exact unit names, but not patterns. | ||||
| // Note: Requires systemd v230 or higher | ||||
| func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) { | ||||
| 	return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store) | ||||
| } | ||||
| @@ -563,3 +593,8 @@ func (c *Conn) Reload() error { | ||||
| func unitPath(name string) dbus.ObjectPath { | ||||
| 	return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name)) | ||||
| } | ||||
| 
 | ||||
| // unitName returns the unescaped base element of the supplied escaped path | ||||
| func unitName(dpath dbus.ObjectPath) string { | ||||
| 	return pathBusUnescape(path.Base(string(dpath))) | ||||
| } | ||||
| @@ -15,7 +15,7 @@ | ||||
| package dbus | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/godbus/dbus" | ||||
| 	"github.com/godbus/dbus/v5" | ||||
| ) | ||||
| 
 | ||||
| // From the systemd docs: | ||||
| @@ -56,7 +56,7 @@ type execStart struct { | ||||
| // http://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart= | ||||
| func PropExecStart(command []string, uncleanIsFailure bool) Property { | ||||
| 	execStarts := []execStart{ | ||||
| 		execStart{ | ||||
| 		{ | ||||
| 			Path:             command[0], | ||||
| 			Args:             command, | ||||
| 			UncleanIsFailure: uncleanIsFailure, | ||||
| @@ -36,7 +36,7 @@ func (s *set) Length() int { | ||||
| } | ||||
| 
 | ||||
| func (s *set) Values() (values []string) { | ||||
| 	for val, _ := range s.data { | ||||
| 	for val := range s.data { | ||||
| 		values = append(values, val) | ||||
| 	} | ||||
| 	return | ||||
| @@ -16,9 +16,10 @@ package dbus | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"log" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/godbus/dbus" | ||||
| 	"github.com/godbus/dbus/v5" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| @@ -36,22 +37,12 @@ func (c *Conn) Subscribe() error { | ||||
| 	c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, | ||||
| 		"type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'") | ||||
| 
 | ||||
| 	err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| 	return c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store() | ||||
| } | ||||
| 
 | ||||
| // Unsubscribe this connection from systemd dbus events. | ||||
| func (c *Conn) Unsubscribe() error { | ||||
| 	err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| 	return c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store() | ||||
| } | ||||
| 
 | ||||
| func (c *Conn) dispatch() { | ||||
| @@ -70,7 +61,8 @@ func (c *Conn) dispatch() { | ||||
| 				c.jobComplete(signal) | ||||
| 			} | ||||
| 
 | ||||
| 			if c.subscriber.updateCh == nil { | ||||
| 			if c.subStateSubscriber.updateCh == nil && | ||||
| 				c.propertiesSubscriber.updateCh == nil { | ||||
| 				continue | ||||
| 			} | ||||
| 
 | ||||
| @@ -84,6 +76,12 @@ func (c *Conn) dispatch() { | ||||
| 			case "org.freedesktop.DBus.Properties.PropertiesChanged": | ||||
| 				if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" { | ||||
| 					unitPath = signal.Path | ||||
| 
 | ||||
| 					if len(signal.Body) >= 2 { | ||||
| 						if changed, ok := signal.Body[1].(map[string]dbus.Variant); ok { | ||||
| 							c.sendPropertiesUpdate(unitPath, changed) | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| @@ -96,7 +94,7 @@ func (c *Conn) dispatch() { | ||||
| 	}() | ||||
| } | ||||
| 
 | ||||
| // Returns two unbuffered channels which will receive all changed units every | ||||
| // SubscribeUnits returns two unbuffered channels which will receive all changed units every | ||||
| // interval.  Deleted units are sent as nil. | ||||
| func (c *Conn) SubscribeUnits(interval time.Duration) (<-chan map[string]*UnitStatus, <-chan error) { | ||||
| 	return c.SubscribeUnitsCustom(interval, 0, func(u1, u2 *UnitStatus) bool { return *u1 != *u2 }, nil) | ||||
| @@ -169,42 +167,80 @@ type SubStateUpdate struct { | ||||
| // is full, it attempts to write an error to errCh; if errCh is full, the error | ||||
| // passes silently. | ||||
| func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) { | ||||
| 	c.subscriber.Lock() | ||||
| 	defer c.subscriber.Unlock() | ||||
| 	c.subscriber.updateCh = updateCh | ||||
| 	c.subscriber.errCh = errCh | ||||
| } | ||||
| 
 | ||||
| func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) { | ||||
| 	c.subscriber.Lock() | ||||
| 	defer c.subscriber.Unlock() | ||||
| 
 | ||||
| 	if c.shouldIgnore(path) { | ||||
| 	if c == nil { | ||||
| 		msg := "nil receiver" | ||||
| 		select { | ||||
| 		case errCh <- errors.New(msg): | ||||
| 		default: | ||||
| 			log.Printf("full error channel while reporting: %s\n", msg) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	info, err := c.GetUnitProperties(string(path)) | ||||
| 	if err != nil { | ||||
| 		select { | ||||
| 		case c.subscriber.errCh <- err: | ||||
| 		default: | ||||
| 		} | ||||
| 	c.subStateSubscriber.Lock() | ||||
| 	defer c.subStateSubscriber.Unlock() | ||||
| 	c.subStateSubscriber.updateCh = updateCh | ||||
| 	c.subStateSubscriber.errCh = errCh | ||||
| } | ||||
| 
 | ||||
| func (c *Conn) sendSubStateUpdate(unitPath dbus.ObjectPath) { | ||||
| 	c.subStateSubscriber.Lock() | ||||
| 	defer c.subStateSubscriber.Unlock() | ||||
| 
 | ||||
| 	if c.subStateSubscriber.updateCh == nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	name := info["Id"].(string) | ||||
| 	substate := info["SubState"].(string) | ||||
| 	isIgnored := c.shouldIgnore(unitPath) | ||||
| 	defer c.cleanIgnore() | ||||
| 	if isIgnored { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	info, err := c.GetUnitPathProperties(unitPath) | ||||
| 	if err != nil { | ||||
| 		select { | ||||
| 		case c.subStateSubscriber.errCh <- err: | ||||
| 		default: | ||||
| 			log.Printf("full error channel while reporting: %s\n", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	defer c.updateIgnore(unitPath, info) | ||||
| 
 | ||||
| 	name, ok := info["Id"].(string) | ||||
| 	if !ok { | ||||
| 		msg := "failed to cast info.Id" | ||||
| 		select { | ||||
| 		case c.subStateSubscriber.errCh <- errors.New(msg): | ||||
| 		default: | ||||
| 			log.Printf("full error channel while reporting: %s\n", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	substate, ok := info["SubState"].(string) | ||||
| 	if !ok { | ||||
| 		msg := "failed to cast info.SubState" | ||||
| 		select { | ||||
| 		case c.subStateSubscriber.errCh <- errors.New(msg): | ||||
| 		default: | ||||
| 			log.Printf("full error channel while reporting: %s\n", msg) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	update := &SubStateUpdate{name, substate} | ||||
| 	select { | ||||
| 	case c.subscriber.updateCh <- update: | ||||
| 	case c.subStateSubscriber.updateCh <- update: | ||||
| 	default: | ||||
| 		msg := "update channel is full" | ||||
| 		select { | ||||
| 		case c.subscriber.errCh <- errors.New("update channel full!"): | ||||
| 		case c.subStateSubscriber.errCh <- errors.New(msg): | ||||
| 		default: | ||||
| 			log.Printf("full error channel while reporting: %s\n", msg) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c.updateIgnore(path, info) | ||||
| } | ||||
| 
 | ||||
| // The ignore functions work around a wart in the systemd dbus interface. | ||||
| @@ -222,29 +258,76 @@ func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) { | ||||
| // the properties). | ||||
| 
 | ||||
| func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool { | ||||
| 	t, ok := c.subscriber.ignore[path] | ||||
| 	t, ok := c.subStateSubscriber.ignore[path] | ||||
| 	return ok && t >= time.Now().UnixNano() | ||||
| } | ||||
| 
 | ||||
| func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) { | ||||
| 	c.cleanIgnore() | ||||
| 	loadState, ok := info["LoadState"].(string) | ||||
| 	if !ok { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// unit is unloaded - it will trigger bad systemd dbus behavior | ||||
| 	if info["LoadState"].(string) == "not-found" { | ||||
| 		c.subscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval | ||||
| 	if loadState == "not-found" { | ||||
| 		c.subStateSubscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // without this, ignore would grow unboundedly over time | ||||
| func (c *Conn) cleanIgnore() { | ||||
| 	now := time.Now().UnixNano() | ||||
| 	if c.subscriber.cleanIgnore < now { | ||||
| 		c.subscriber.cleanIgnore = now + cleanIgnoreInterval | ||||
| 	if c.subStateSubscriber.cleanIgnore < now { | ||||
| 		c.subStateSubscriber.cleanIgnore = now + cleanIgnoreInterval | ||||
| 
 | ||||
| 		for p, t := range c.subscriber.ignore { | ||||
| 		for p, t := range c.subStateSubscriber.ignore { | ||||
| 			if t < now { | ||||
| 				delete(c.subscriber.ignore, p) | ||||
| 				delete(c.subStateSubscriber.ignore, p) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // PropertiesUpdate holds a map of a unit's changed properties | ||||
| type PropertiesUpdate struct { | ||||
| 	UnitName string | ||||
| 	Changed  map[string]dbus.Variant | ||||
| } | ||||
| 
 | ||||
| // SetPropertiesSubscriber writes to updateCh when any unit's properties | ||||
| // change. Every property change reported by systemd will be sent; that is, no | ||||
| // transitions will be "missed" (as they might be with SetSubStateSubscriber). | ||||
| // However, state changes will only be written to the channel with non-blocking | ||||
| // writes.  If updateCh is full, it attempts to write an error to errCh; if | ||||
| // errCh is full, the error passes silently. | ||||
| func (c *Conn) SetPropertiesSubscriber(updateCh chan<- *PropertiesUpdate, errCh chan<- error) { | ||||
| 	c.propertiesSubscriber.Lock() | ||||
| 	defer c.propertiesSubscriber.Unlock() | ||||
| 	c.propertiesSubscriber.updateCh = updateCh | ||||
| 	c.propertiesSubscriber.errCh = errCh | ||||
| } | ||||
| 
 | ||||
| // we don't need to worry about shouldIgnore() here because | ||||
| // sendPropertiesUpdate doesn't call GetProperties() | ||||
| func (c *Conn) sendPropertiesUpdate(unitPath dbus.ObjectPath, changedProps map[string]dbus.Variant) { | ||||
| 	c.propertiesSubscriber.Lock() | ||||
| 	defer c.propertiesSubscriber.Unlock() | ||||
| 
 | ||||
| 	if c.propertiesSubscriber.updateCh == nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	update := &PropertiesUpdate{unitName(unitPath), changedProps} | ||||
| 
 | ||||
| 	select { | ||||
| 	case c.propertiesSubscriber.updateCh <- update: | ||||
| 	default: | ||||
| 		msg := "update channel is full" | ||||
| 		select { | ||||
| 		case c.propertiesSubscriber.errCh <- errors.New(msg): | ||||
| 		default: | ||||
| 			log.Printf("full error channel while reporting: %s\n", msg) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										5
									
								
								vendor/github.com/coreos/go-systemd/v22/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/coreos/go-systemd/v22/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| module github.com/coreos/go-systemd/v22 | ||||
|  | ||||
| go 1.12 | ||||
|  | ||||
| require github.com/godbus/dbus/v5 v5.0.3 | ||||
							
								
								
									
										625
									
								
								vendor/github.com/godbus/dbus/conn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										625
									
								
								vendor/github.com/godbus/dbus/conn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,625 +0,0 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| const defaultSystemBusAddress = "unix:path=/var/run/dbus/system_bus_socket" | ||||
|  | ||||
| var ( | ||||
| 	systemBus     *Conn | ||||
| 	systemBusLck  sync.Mutex | ||||
| 	sessionBus    *Conn | ||||
| 	sessionBusLck sync.Mutex | ||||
| ) | ||||
|  | ||||
| // ErrClosed is the error returned by calls on a closed connection. | ||||
| var ErrClosed = errors.New("dbus: connection closed by user") | ||||
|  | ||||
| // Conn represents a connection to a message bus (usually, the system or | ||||
| // session bus). | ||||
| // | ||||
| // Connections are either shared or private. Shared connections | ||||
| // are shared between calls to the functions that return them. As a result, | ||||
| // the methods Close, Auth and Hello must not be called on them. | ||||
| // | ||||
| // Multiple goroutines may invoke methods on a connection simultaneously. | ||||
| type Conn struct { | ||||
| 	transport | ||||
|  | ||||
| 	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 | ||||
|  | ||||
| 	handlers    map[ObjectPath]map[string]exportWithMapping | ||||
| 	handlersLck sync.RWMutex | ||||
|  | ||||
| 	out    chan *Message | ||||
| 	closed bool | ||||
| 	outLck sync.RWMutex | ||||
|  | ||||
| 	signals    []chan<- *Signal | ||||
| 	signalsLck sync.Mutex | ||||
|  | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| // SessionBusPrivate returns a new private connection to the session bus. | ||||
| func SessionBusPrivate() (*Conn, error) { | ||||
| 	address := os.Getenv("DBUS_SESSION_BUS_ADDRESS") | ||||
| 	if address != "" && address != "autolaunch:" { | ||||
| 		return Dial(address) | ||||
| 	} | ||||
|  | ||||
| 	return sessionBusPlatform() | ||||
| } | ||||
|  | ||||
| // 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) { | ||||
| 	address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS") | ||||
| 	if address != "" { | ||||
| 		return Dial(address) | ||||
| 	} | ||||
| 	return Dial(defaultSystemBusAddress) | ||||
| } | ||||
|  | ||||
| // 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) | ||||
| } | ||||
|  | ||||
| // NewConn creates a new private *Conn from an already established connection. | ||||
| func NewConn(conn io.ReadWriteCloser) (*Conn, error) { | ||||
| 	return newConn(genericTransport{conn}) | ||||
| } | ||||
|  | ||||
| // newConn creates a new *Conn from a transport. | ||||
| func newConn(tr transport) (*Conn, error) { | ||||
| 	conn := new(Conn) | ||||
| 	conn.transport = tr | ||||
| 	conn.calls = make(map[uint32]*Call) | ||||
| 	conn.out = make(chan *Message, 10) | ||||
| 	conn.handlers = make(map[ObjectPath]map[string]exportWithMapping) | ||||
| 	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() | ||||
| 	conn.signalsLck.Lock() | ||||
| 	for _, ch := range conn.signals { | ||||
| 		close(ch) | ||||
| 	} | ||||
| 	conn.signalsLck.Unlock() | ||||
| 	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() | ||||
| 					} | ||||
| 				} | ||||
| 				signal := &Signal{ | ||||
| 					Sender: sender, | ||||
| 					Path:   msg.Headers[FieldPath].value.(ObjectPath), | ||||
| 					Name:   iface + "." + member, | ||||
| 					Body:   msg.Body, | ||||
| 				} | ||||
| 				conn.signalsLck.Lock() | ||||
| 				for _, ch := range conn.signals { | ||||
| 					ch <- signal | ||||
| 				} | ||||
| 				conn.signalsLck.Unlock() | ||||
| 			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 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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(e Error, dest string, serial uint32) { | ||||
| 	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() | ||||
| } | ||||
|  | ||||
| // 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. Passing a | ||||
| // channel that already is registered will remove it from the list of the | ||||
| // registered channels. | ||||
| // | ||||
| // 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.signalsLck.Lock() | ||||
| 	conn.signals = append(conn.signals, ch) | ||||
| 	conn.signalsLck.Unlock() | ||||
| } | ||||
|  | ||||
| // 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 { | ||||
| 	i := strings.Index(s, key) | ||||
| 	if i == -1 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	if i+len(key)+1 >= len(s) || s[i+len(key)] != '=' { | ||||
| 		return "" | ||||
| 	} | ||||
| 	j := strings.Index(s, ",") | ||||
| 	if j == -1 { | ||||
| 		j = len(s) | ||||
| 	} | ||||
| 	return s[i+len(key)+1 : j] | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/godbus/dbus/conn_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/godbus/dbus/conn_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,21 +0,0 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"os/exec" | ||||
| ) | ||||
|  | ||||
| func sessionBusPlatform() (*Conn, error) { | ||||
| 	cmd := exec.Command("launchctl", "getenv", "DBUS_LAUNCHD_SESSION_BUS_SOCKET") | ||||
| 	b, err := cmd.CombinedOutput() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(b) == 0 { | ||||
| 		return nil, errors.New("dbus: couldn't determine address of session bus") | ||||
| 	} | ||||
|  | ||||
| 	return Dial("unix:path=" + string(b[:len(b)-1])) | ||||
| } | ||||
							
								
								
									
										27
									
								
								vendor/github.com/godbus/dbus/conn_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/godbus/dbus/conn_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,27 +0,0 @@ | ||||
| // +build !darwin | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"os/exec" | ||||
| ) | ||||
|  | ||||
| func sessionBusPlatform() (*Conn, error) { | ||||
| 	cmd := exec.Command("dbus-launch") | ||||
| 	b, err := cmd.CombinedOutput() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	i := bytes.IndexByte(b, '=') | ||||
| 	j := bytes.IndexByte(b, '\n') | ||||
|  | ||||
| 	if i == -1 || j == -1 { | ||||
| 		return nil, errors.New("dbus: couldn't determine address of session bus") | ||||
| 	} | ||||
|  | ||||
| 	return Dial(string(b[i+1 : j])) | ||||
| } | ||||
							
								
								
									
										258
									
								
								vendor/github.com/godbus/dbus/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										258
									
								
								vendor/github.com/godbus/dbus/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,258 +0,0 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"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)) | ||||
| 	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{}{}) | ||||
| 	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 := store(src[i], dest[i]); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func store(src, dest interface{}) error { | ||||
| 	if reflect.TypeOf(dest).Elem() == reflect.TypeOf(src) { | ||||
| 		reflect.ValueOf(dest).Elem().Set(reflect.ValueOf(src)) | ||||
| 		return nil | ||||
| 	} else if hasStruct(dest) { | ||||
| 		rv := reflect.ValueOf(dest).Elem() | ||||
| 		switch rv.Kind() { | ||||
| 		case reflect.Struct: | ||||
| 			vs, ok := src.([]interface{}) | ||||
| 			if !ok { | ||||
| 				return errors.New("dbus.Store: type mismatch") | ||||
| 			} | ||||
| 			t := rv.Type() | ||||
| 			ndest := make([]interface{}, 0, rv.NumField()) | ||||
| 			for i := 0; i < rv.NumField(); i++ { | ||||
| 				field := t.Field(i) | ||||
| 				if field.PkgPath == "" && field.Tag.Get("dbus") != "-" { | ||||
| 					ndest = append(ndest, rv.Field(i).Addr().Interface()) | ||||
| 				} | ||||
| 			} | ||||
| 			if len(vs) != len(ndest) { | ||||
| 				return errors.New("dbus.Store: type mismatch") | ||||
| 			} | ||||
| 			err := Store(vs, ndest...) | ||||
| 			if err != nil { | ||||
| 				return errors.New("dbus.Store: type mismatch") | ||||
| 			} | ||||
| 		case reflect.Slice: | ||||
| 			sv := reflect.ValueOf(src) | ||||
| 			if sv.Kind() != reflect.Slice { | ||||
| 				return errors.New("dbus.Store: type mismatch") | ||||
| 			} | ||||
| 			rv.Set(reflect.MakeSlice(rv.Type(), sv.Len(), sv.Len())) | ||||
| 			for i := 0; i < sv.Len(); i++ { | ||||
| 				if err := store(sv.Index(i).Interface(), rv.Index(i).Addr().Interface()); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 		case reflect.Map: | ||||
| 			sv := reflect.ValueOf(src) | ||||
| 			if sv.Kind() != reflect.Map { | ||||
| 				return errors.New("dbus.Store: type mismatch") | ||||
| 			} | ||||
| 			keys := sv.MapKeys() | ||||
| 			rv.Set(reflect.MakeMap(sv.Type())) | ||||
| 			for _, key := range keys { | ||||
| 				v := reflect.New(sv.Type().Elem()) | ||||
| 				if err := store(v, sv.MapIndex(key).Interface()); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				rv.SetMapIndex(key, v.Elem()) | ||||
| 			} | ||||
| 		default: | ||||
| 			return errors.New("dbus.Store: type mismatch") | ||||
| 		} | ||||
| 		return nil | ||||
| 	} else { | ||||
| 		return errors.New("dbus.Store: type mismatch") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func hasStruct(v interface{}) bool { | ||||
| 	t := reflect.TypeOf(v) | ||||
| 	for { | ||||
| 		switch t.Kind() { | ||||
| 		case reflect.Struct: | ||||
| 			return true | ||||
| 		case reflect.Slice, reflect.Ptr, reflect.Map: | ||||
| 			t = t.Elem() | ||||
| 		default: | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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: // sometimes used for structs | ||||
| 		return 8 | ||||
| 	} | ||||
| 	switch t.Kind() { | ||||
| 	case reflect.Uint8: | ||||
| 		return 1 | ||||
| 	case reflect.Uint16, reflect.Int16: | ||||
| 		return 2 | ||||
| 	case 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: | ||||
|  | ||||
| 		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 == '_' | ||||
| } | ||||
							
								
								
									
										126
									
								
								vendor/github.com/godbus/dbus/object.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										126
									
								
								vendor/github.com/godbus/dbus/object.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,126 +0,0 @@ | ||||
| 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 | ||||
| } | ||||
|  | ||||
| // 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 of which only the Err member is valid. | ||||
| // | ||||
| // 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() | ||||
| 	if o.conn.closed { | ||||
| 		return &Call{Err: ErrClosed} | ||||
| 	} | ||||
| 	o.conn.out <- msg | ||||
| 	return &Call{Err: nil} | ||||
| } | ||||
|  | ||||
| // 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 are sent to. | ||||
| func (o *Object) Destination() string { | ||||
| 	return o.dest | ||||
| } | ||||
|  | ||||
| // Path returns the path that calls on o are sent to. | ||||
| func (o *Object) Path() ObjectPath { | ||||
| 	return o.path | ||||
| } | ||||
							
								
								
									
										0
									
								
								vendor/github.com/godbus/dbus/LICENSE → vendor/github.com/godbus/dbus/v5/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								vendor/github.com/godbus/dbus/LICENSE → vendor/github.com/godbus/dbus/v5/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,5 @@ | ||||
| [](https://travis-ci.org/godbus/dbus) | ||||
| 
 | ||||
| dbus | ||||
| ---- | ||||
| 
 | ||||
| @@ -12,7 +14,7 @@ D-Bus message bus system. | ||||
| 
 | ||||
| ### Installation | ||||
| 
 | ||||
| This packages requires Go 1.1. If you installed it and set up your GOPATH, just run: | ||||
| This packages requires Go 1.7. If you installed it and set up your GOPATH, just run: | ||||
| 
 | ||||
| ``` | ||||
| go get github.com/godbus/dbus | ||||
| @@ -29,6 +31,7 @@ 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. | ||||
							
								
								
									
										5
									
								
								vendor/github.com/godbus/dbus/auth.go → vendor/github.com/godbus/dbus/v5/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/godbus/dbus/auth.go → vendor/github.com/godbus/dbus/v5/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -77,7 +77,7 @@ func (conn *Conn) Auth(methods []Auth) error { | ||||
| 		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) | ||||
| 				err = authWriteLine(conn.transport, []byte("AUTH"), v, data) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| @@ -116,7 +116,6 @@ func (conn *Conn) Auth(methods []Auth) error { | ||||
| 						return err | ||||
| 					} | ||||
| 					go conn.inWorker() | ||||
| 					go conn.outWorker() | ||||
| 					return nil | ||||
| 				} | ||||
| 			} | ||||
| @@ -128,7 +127,7 @@ func (conn *Conn) Auth(methods []Auth) error { | ||||
| // 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. | ||||
| // error occurred. | ||||
| func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, bool) { | ||||
| 	for { | ||||
| 		s, err := authReadLine(in) | ||||
							
								
								
									
										16
									
								
								vendor/github.com/godbus/dbus/v5/auth_anonymous.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/godbus/dbus/v5/auth_anonymous.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| package dbus | ||||
|  | ||||
| // AuthAnonymous returns an Auth that uses the ANONYMOUS mechanism. | ||||
| func AuthAnonymous() Auth { | ||||
| 	return &authAnonymous{} | ||||
| } | ||||
|  | ||||
| type authAnonymous struct{} | ||||
|  | ||||
| func (a *authAnonymous) FirstData() (name, resp []byte, status AuthStatus) { | ||||
| 	return []byte("ANONYMOUS"), nil, AuthOk | ||||
| } | ||||
|  | ||||
| func (a *authAnonymous) HandleData(data []byte) (resp []byte, status AuthStatus) { | ||||
| 	return nil, AuthError | ||||
| } | ||||
| @@ -60,7 +60,7 @@ func (a authCookieSha1) HandleData(data []byte) ([]byte, AuthStatus) { | ||||
| 
 | ||||
| // 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 | ||||
| // but only whether an error occurred, this function also doesn't bother to | ||||
| // return an error.) | ||||
| func (a authCookieSha1) getCookie(context, id []byte) []byte { | ||||
| 	file, err := os.Open(a.home + "/.dbus-keyrings/" + string(context)) | ||||
							
								
								
									
										26
									
								
								vendor/github.com/godbus/dbus/call.go → vendor/github.com/godbus/dbus/v5/call.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/godbus/dbus/call.go → vendor/github.com/godbus/dbus/v5/call.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,9 +1,12 @@ | ||||
| package dbus | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| var errSignature = errors.New("dbus: mismatched signature") | ||||
| 
 | ||||
| // Call represents a pending or completed method call. | ||||
| type Call struct { | ||||
| 	Destination string | ||||
| @@ -20,9 +23,25 @@ type Call struct { | ||||
| 
 | ||||
| 	// Holds the response once the call is done. | ||||
| 	Body []interface{} | ||||
| 
 | ||||
| 	// tracks context and canceler | ||||
| 	ctx         context.Context | ||||
| 	ctxCanceler context.CancelFunc | ||||
| } | ||||
| 
 | ||||
| var errSignature = errors.New("dbus: mismatched signature") | ||||
| func (c *Call) Context() context.Context { | ||||
| 	if c.ctx == nil { | ||||
| 		return context.Background() | ||||
| 	} | ||||
| 
 | ||||
| 	return c.ctx | ||||
| } | ||||
| 
 | ||||
| func (c *Call) ContextCancel() { | ||||
| 	if c.ctxCanceler != nil { | ||||
| 		c.ctxCanceler() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Store stores the body of the reply into the provided pointers. It returns | ||||
| // an error if the signatures of the body and retvalues don't match, or if | ||||
| @@ -34,3 +53,8 @@ func (c *Call) Store(retvalues ...interface{}) error { | ||||
| 
 | ||||
| 	return Store(c.Body, retvalues...) | ||||
| } | ||||
| 
 | ||||
| func (c *Call) done() { | ||||
| 	c.Done <- c | ||||
| 	c.ContextCancel() | ||||
| } | ||||
							
								
								
									
										912
									
								
								vendor/github.com/godbus/dbus/v5/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										912
									
								
								vendor/github.com/godbus/dbus/v5/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,912 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	systemBus     *Conn | ||||
| 	systemBusLck  sync.Mutex | ||||
| 	sessionBus    *Conn | ||||
| 	sessionBusLck sync.Mutex | ||||
| ) | ||||
|  | ||||
| // ErrClosed is the error returned by calls on a closed connection. | ||||
| var ErrClosed = errors.New("dbus: connection closed by user") | ||||
|  | ||||
| // Conn represents a connection to a message bus (usually, the system or | ||||
| // session bus). | ||||
| // | ||||
| // Connections are either shared or private. Shared connections | ||||
| // are shared between calls to the functions that return them. As a result, | ||||
| // the methods Close, Auth and Hello must not be called on them. | ||||
| // | ||||
| // Multiple goroutines may invoke methods on a connection simultaneously. | ||||
| type Conn struct { | ||||
| 	transport | ||||
|  | ||||
| 	ctx       context.Context | ||||
| 	cancelCtx context.CancelFunc | ||||
|  | ||||
| 	closeOnce sync.Once | ||||
| 	closeErr  error | ||||
|  | ||||
| 	busObj BusObject | ||||
| 	unixFD bool | ||||
| 	uuid   string | ||||
|  | ||||
| 	handler       Handler | ||||
| 	signalHandler SignalHandler | ||||
| 	serialGen     SerialGenerator | ||||
| 	inInt         Interceptor | ||||
| 	outInt        Interceptor | ||||
|  | ||||
| 	names      *nameTracker | ||||
| 	calls      *callTracker | ||||
| 	outHandler *outputHandler | ||||
|  | ||||
| 	eavesdropped    chan<- *Message | ||||
| 	eavesdroppedLck sync.Mutex | ||||
| } | ||||
|  | ||||
| // SessionBus returns a shared connection to the session bus, connecting to it | ||||
| // if not already done. | ||||
| func SessionBus() (conn *Conn, err error) { | ||||
| 	sessionBusLck.Lock() | ||||
| 	defer sessionBusLck.Unlock() | ||||
| 	if sessionBus != nil { | ||||
| 		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) { | ||||
| 	if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" { | ||||
| 		return address, nil | ||||
|  | ||||
| 	} else if address := tryDiscoverDbusSessionBusAddress(); address != "" { | ||||
| 		os.Setenv("DBUS_SESSION_BUS_ADDRESS", address) | ||||
| 		return address, nil | ||||
| 	} | ||||
| 	return getSessionBusPlatformAddress() | ||||
| } | ||||
|  | ||||
| // SessionBusPrivate returns a new private connection to the session bus. | ||||
| func SessionBusPrivate(opts ...ConnOption) (*Conn, error) { | ||||
| 	address, err := getSessionBusAddress() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return Dial(address, opts...) | ||||
| } | ||||
|  | ||||
| // SessionBusPrivate returns a new private connection to the session bus. | ||||
| // | ||||
| // Deprecated: use SessionBusPrivate with options instead. | ||||
| func SessionBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) { | ||||
| 	return SessionBusPrivate(WithHandler(handler), WithSignalHandler(signalHandler)) | ||||
| } | ||||
|  | ||||
| // SystemBus returns a shared connection to the system bus, connecting to it if | ||||
| // not already done. | ||||
| func SystemBus() (conn *Conn, err error) { | ||||
| 	systemBusLck.Lock() | ||||
| 	defer systemBusLck.Unlock() | ||||
| 	if systemBus != nil { | ||||
| 		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. | ||||
| // Note: this connection is not ready to use. One must perform Auth and Hello | ||||
| // on the connection before it is useable. | ||||
| func SystemBusPrivate(opts ...ConnOption) (*Conn, error) { | ||||
| 	return Dial(getSystemBusPlatformAddress(), opts...) | ||||
| } | ||||
|  | ||||
| // SystemBusPrivateHandler returns a new private connection to the system bus, using the provided handlers. | ||||
| // | ||||
| // Deprecated: use SystemBusPrivate with options instead. | ||||
| func SystemBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) { | ||||
| 	return SystemBusPrivate(WithHandler(handler), WithSignalHandler(signalHandler)) | ||||
| } | ||||
|  | ||||
| // Dial establishes a new private connection to the message bus specified by address. | ||||
| func Dial(address string, opts ...ConnOption) (*Conn, error) { | ||||
| 	tr, err := getTransport(address) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return newConn(tr, opts...) | ||||
| } | ||||
|  | ||||
| // DialHandler establishes a new private connection to the message bus specified by address, using the supplied handlers. | ||||
| // | ||||
| // Deprecated: use Dial with options instead. | ||||
| func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) { | ||||
| 	return Dial(address, WithSignalHandler(signalHandler)) | ||||
| } | ||||
|  | ||||
| // ConnOption is a connection option. | ||||
| type ConnOption func(conn *Conn) error | ||||
|  | ||||
| // WithHandler overrides the default handler. | ||||
| func WithHandler(handler Handler) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.handler = handler | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithSignalHandler overrides the default signal handler. | ||||
| func WithSignalHandler(handler SignalHandler) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.signalHandler = handler | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithSerialGenerator overrides the default signals generator. | ||||
| func WithSerialGenerator(gen SerialGenerator) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.serialGen = gen | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Interceptor intercepts incoming and outgoing messages. | ||||
| type Interceptor func(msg *Message) | ||||
|  | ||||
| // WithIncomingInterceptor sets the given interceptor for incoming messages. | ||||
| func WithIncomingInterceptor(interceptor Interceptor) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.inInt = interceptor | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithOutgoingInterceptor sets the given interceptor for outgoing messages. | ||||
| func WithOutgoingInterceptor(interceptor Interceptor) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.outInt = interceptor | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithContext overrides  the default context for the connection. | ||||
| func WithContext(ctx context.Context) ConnOption { | ||||
| 	return func(conn *Conn) error { | ||||
| 		conn.ctx = ctx | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewConn creates a new private *Conn from an already established connection. | ||||
| func NewConn(conn io.ReadWriteCloser, opts ...ConnOption) (*Conn, error) { | ||||
| 	return newConn(genericTransport{conn}, opts...) | ||||
| } | ||||
|  | ||||
| // NewConnHandler creates a new private *Conn from an already established connection, using the supplied handlers. | ||||
| // | ||||
| // Deprecated: use NewConn with options instead. | ||||
| func NewConnHandler(conn io.ReadWriteCloser, handler Handler, signalHandler SignalHandler) (*Conn, error) { | ||||
| 	return NewConn(genericTransport{conn}, WithHandler(handler), WithSignalHandler(signalHandler)) | ||||
| } | ||||
|  | ||||
| // newConn creates a new *Conn from a transport. | ||||
| func newConn(tr transport, opts ...ConnOption) (*Conn, error) { | ||||
| 	conn := new(Conn) | ||||
| 	conn.transport = tr | ||||
| 	for _, opt := range opts { | ||||
| 		if err := opt(conn); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	if conn.ctx == nil { | ||||
| 		conn.ctx = context.Background() | ||||
| 	} | ||||
| 	conn.ctx, conn.cancelCtx = context.WithCancel(conn.ctx) | ||||
| 	go func() { | ||||
| 		<-conn.ctx.Done() | ||||
| 		conn.Close() | ||||
| 	}() | ||||
|  | ||||
| 	conn.calls = newCallTracker() | ||||
| 	if conn.handler == nil { | ||||
| 		conn.handler = NewDefaultHandler() | ||||
| 	} | ||||
| 	if conn.signalHandler == nil { | ||||
| 		conn.signalHandler = NewDefaultSignalHandler() | ||||
| 	} | ||||
| 	if conn.serialGen == nil { | ||||
| 		conn.serialGen = newSerialGenerator() | ||||
| 	} | ||||
| 	conn.outHandler = &outputHandler{conn: conn} | ||||
| 	conn.names = newNameTracker() | ||||
| 	conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus") | ||||
| 	return conn, nil | ||||
| } | ||||
|  | ||||
| // BusObject returns the object owned by the bus daemon which handles | ||||
| // administrative requests. | ||||
| func (conn *Conn) BusObject() BusObject { | ||||
| 	return conn.busObj | ||||
| } | ||||
|  | ||||
| // Close closes the connection. Any blocked operations will return with errors | ||||
| // and the channels passed to Eavesdrop and Signal are closed. This method must | ||||
| // not be called on shared connections. | ||||
| func (conn *Conn) Close() error { | ||||
| 	conn.closeOnce.Do(func() { | ||||
| 		conn.outHandler.close() | ||||
| 		if term, ok := conn.signalHandler.(Terminator); ok { | ||||
| 			term.Terminate() | ||||
| 		} | ||||
|  | ||||
| 		if term, ok := conn.handler.(Terminator); ok { | ||||
| 			term.Terminate() | ||||
| 		} | ||||
|  | ||||
| 		conn.eavesdroppedLck.Lock() | ||||
| 		if conn.eavesdropped != nil { | ||||
| 			close(conn.eavesdropped) | ||||
| 		} | ||||
| 		conn.eavesdroppedLck.Unlock() | ||||
|  | ||||
| 		conn.cancelCtx() | ||||
|  | ||||
| 		conn.closeErr = conn.transport.Close() | ||||
| 	}) | ||||
| 	return conn.closeErr | ||||
| } | ||||
|  | ||||
| // Context returns the context associated with the connection.  The | ||||
| // context will be cancelled when the connection is closed. | ||||
| func (conn *Conn) Context() context.Context { | ||||
| 	return conn.ctx | ||||
| } | ||||
|  | ||||
| // Eavesdrop causes conn to send all incoming messages to the given channel | ||||
| // without further processing. Method replies, errors and signals will not be | ||||
| // sent to the appropriate channels and method calls will not be handled. If nil | ||||
| // is passed, the normal behaviour is restored. | ||||
| // | ||||
| // The caller has to make sure that ch is sufficiently buffered; | ||||
| // if a message arrives when a write to ch is not possible, the message is | ||||
| // discarded. | ||||
| func (conn *Conn) Eavesdrop(ch chan<- *Message) { | ||||
| 	conn.eavesdroppedLck.Lock() | ||||
| 	conn.eavesdropped = ch | ||||
| 	conn.eavesdroppedLck.Unlock() | ||||
| } | ||||
|  | ||||
| // getSerial returns an unused serial. | ||||
| func (conn *Conn) getSerial() uint32 { | ||||
| 	return conn.serialGen.GetSerial() | ||||
| } | ||||
|  | ||||
| // Hello sends the initial org.freedesktop.DBus.Hello call. This method must be | ||||
| // called after authentication, but before sending any other messages to the | ||||
| // bus. Hello must not be called for shared connections. | ||||
| func (conn *Conn) Hello() error { | ||||
| 	var s string | ||||
| 	err := conn.busObj.Call("org.freedesktop.DBus.Hello", 0).Store(&s) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	conn.names.acquireUniqueConnectionName(s) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // inWorker runs in an own goroutine, reading incoming messages from the | ||||
| // transport and dispatching them appropiately. | ||||
| func (conn *Conn) inWorker() { | ||||
| 	for { | ||||
| 		msg, err := conn.ReadMessage() | ||||
| 		if err != nil { | ||||
| 			if _, ok := err.(InvalidMessageError); !ok { | ||||
| 				// Some read error occurred (usually EOF); we can't really do | ||||
| 				// anything but to shut down all stuff and returns errors to all | ||||
| 				// pending replies. | ||||
| 				conn.Close() | ||||
| 				conn.calls.finalizeAllWithError(err) | ||||
| 				return | ||||
| 			} | ||||
| 			// invalid messages are ignored | ||||
| 			continue | ||||
| 		} | ||||
| 		conn.eavesdroppedLck.Lock() | ||||
| 		if conn.eavesdropped != nil { | ||||
| 			select { | ||||
| 			case conn.eavesdropped <- msg: | ||||
| 			default: | ||||
| 			} | ||||
| 			conn.eavesdroppedLck.Unlock() | ||||
| 			continue | ||||
| 		} | ||||
| 		conn.eavesdroppedLck.Unlock() | ||||
| 		dest, _ := msg.Headers[FieldDestination].value.(string) | ||||
| 		found := dest == "" || | ||||
| 			!conn.names.uniqueNameIsKnown() || | ||||
| 			conn.names.isKnownName(dest) | ||||
| 		if !found { | ||||
| 			// Eavesdropped a message, but no channel for it is registered. | ||||
| 			// Ignore it. | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if conn.inInt != nil { | ||||
| 			conn.inInt(msg) | ||||
| 		} | ||||
| 		switch msg.Type { | ||||
| 		case TypeError: | ||||
| 			conn.serialGen.RetireSerial(conn.calls.handleDBusError(msg)) | ||||
| 		case TypeMethodReply: | ||||
| 			conn.serialGen.RetireSerial(conn.calls.handleReply(msg)) | ||||
| 		case TypeSignal: | ||||
| 			conn.handleSignal(msg) | ||||
| 		case TypeMethodCall: | ||||
| 			go conn.handleCall(msg) | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 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) | ||||
| 	if iface == "org.freedesktop.DBus" && sender == "org.freedesktop.DBus" { | ||||
| 		if member == "NameLost" { | ||||
| 			// If we lost the name on the bus, remove it from our | ||||
| 			// tracking list. | ||||
| 			name, ok := msg.Body[0].(string) | ||||
| 			if !ok { | ||||
| 				panic("Unable to read the lost name") | ||||
| 			} | ||||
| 			conn.names.loseName(name) | ||||
| 		} else if member == "NameAcquired" { | ||||
| 			// If we acquired the name on the bus, add it to our | ||||
| 			// tracking list. | ||||
| 			name, ok := msg.Body[0].(string) | ||||
| 			if !ok { | ||||
| 				panic("Unable to read the acquired name") | ||||
| 			} | ||||
| 			conn.names.acquireName(name) | ||||
| 		} | ||||
| 	} | ||||
| 	signal := &Signal{ | ||||
| 		Sender: sender, | ||||
| 		Path:   msg.Headers[FieldPath].value.(ObjectPath), | ||||
| 		Name:   iface + "." + member, | ||||
| 		Body:   msg.Body, | ||||
| 	} | ||||
| 	conn.signalHandler.DeliverSignal(iface, member, signal) | ||||
| } | ||||
|  | ||||
| // Names returns the list of all names that are currently owned by this | ||||
| // connection. The slice is always at least one element long, the first element | ||||
| // being the unique name of the connection. | ||||
| func (conn *Conn) Names() []string { | ||||
| 	return conn.names.listKnownNames() | ||||
| } | ||||
|  | ||||
| // Object returns the object identified by the given destination name and path. | ||||
| func (conn *Conn) Object(dest string, path ObjectPath) BusObject { | ||||
| 	return &Object{conn, dest, path} | ||||
| } | ||||
|  | ||||
| func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) { | ||||
| 	if conn.outInt != nil { | ||||
| 		conn.outInt(msg) | ||||
| 	} | ||||
| 	err := conn.outHandler.sendAndIfClosed(msg, ifClosed) | ||||
| 	conn.calls.handleSendError(msg, err) | ||||
| 	if err != nil { | ||||
| 		conn.serialGen.RetireSerial(msg.serial) | ||||
| 	} else if msg.Type != TypeMethodCall { | ||||
| 		conn.serialGen.RetireSerial(msg.serial) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Send sends the given message to the message bus. You usually don't need to | ||||
| // use this; use the higher-level equivalents (Call / Go, Emit and Export) | ||||
| // instead. If msg is a method call and NoReplyExpected is not set, a non-nil | ||||
| // call is returned and the same value is sent to ch (which must be buffered) | ||||
| // once the call is complete. Otherwise, ch is ignored and a Call structure is | ||||
| // returned of which only the Err member is valid. | ||||
| func (conn *Conn) Send(msg *Message, ch chan *Call) *Call { | ||||
| 	return conn.send(context.Background(), msg, ch) | ||||
| } | ||||
|  | ||||
| // SendWithContext acts like Send but takes a context | ||||
| func (conn *Conn) SendWithContext(ctx context.Context, msg *Message, ch chan *Call) *Call { | ||||
| 	return conn.send(ctx, msg, ch) | ||||
| } | ||||
|  | ||||
| func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call { | ||||
| 	if ctx == nil { | ||||
| 		panic("nil context") | ||||
| 	} | ||||
|  | ||||
| 	var call *Call | ||||
| 	ctx, canceler := context.WithCancel(ctx) | ||||
| 	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 | ||||
| 		call.ctx = ctx | ||||
| 		call.ctxCanceler = canceler | ||||
| 		conn.calls.track(msg.serial, call) | ||||
| 		go func() { | ||||
| 			<-ctx.Done() | ||||
| 			conn.calls.handleSendError(msg, ctx.Err()) | ||||
| 		}() | ||||
| 		conn.sendMessageAndIfClosed(msg, func() { | ||||
| 			conn.calls.handleSendError(msg, ErrClosed) | ||||
| 			canceler() | ||||
| 		}) | ||||
| 	} else { | ||||
| 		canceler() | ||||
| 		call = &Call{Err: nil} | ||||
| 		conn.sendMessageAndIfClosed(msg, func() { | ||||
| 			call = &Call{Err: ErrClosed} | ||||
| 		}) | ||||
| 	} | ||||
| 	return call | ||||
| } | ||||
|  | ||||
| // sendError creates an error message corresponding to the parameters and sends | ||||
| // it to conn.out. | ||||
| func (conn *Conn) sendError(err error, dest string, serial uint32) { | ||||
| 	var e *Error | ||||
| 	switch em := err.(type) { | ||||
| 	case Error: | ||||
| 		e = &em | ||||
| 	case *Error: | ||||
| 		e = em | ||||
| 	case DBusError: | ||||
| 		name, body := em.DBusError() | ||||
| 		e = NewError(name, body) | ||||
| 	default: | ||||
| 		e = MakeFailedError(err) | ||||
| 	} | ||||
| 	msg := new(Message) | ||||
| 	msg.Type = TypeError | ||||
| 	msg.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.sendMessageAndIfClosed(msg, nil) | ||||
| } | ||||
|  | ||||
| // sendReply creates a method reply message corresponding to the parameters and | ||||
| // sends it to conn.out. | ||||
| func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) { | ||||
| 	msg := new(Message) | ||||
| 	msg.Type = TypeMethodReply | ||||
| 	msg.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.sendMessageAndIfClosed(msg, nil) | ||||
| } | ||||
|  | ||||
| // AddMatchSignal registers the given match rule to receive broadcast | ||||
| // signals based on their contents. | ||||
| func (conn *Conn) AddMatchSignal(options ...MatchOption) error { | ||||
| 	options = append([]MatchOption{withMatchType("signal")}, options...) | ||||
| 	return conn.busObj.Call( | ||||
| 		"org.freedesktop.DBus.AddMatch", 0, | ||||
| 		formatMatchOptions(options), | ||||
| 	).Store() | ||||
| } | ||||
|  | ||||
| // RemoveMatchSignal removes the first rule that matches previously registered with AddMatchSignal. | ||||
| func (conn *Conn) RemoveMatchSignal(options ...MatchOption) error { | ||||
| 	options = append([]MatchOption{withMatchType("signal")}, options...) | ||||
| 	return conn.busObj.Call( | ||||
| 		"org.freedesktop.DBus.RemoveMatch", 0, | ||||
| 		formatMatchOptions(options), | ||||
| 	).Store() | ||||
| } | ||||
|  | ||||
| // Signal registers the given channel to be passed all received signal messages. | ||||
| // | ||||
| // Multiple of these channels can be registered at the same time. | ||||
| // | ||||
| // These channels are "overwritten" by Eavesdrop; i.e., if there currently is a | ||||
| // channel for eavesdropped messages, this channel receives all signals, and | ||||
| // none of the channels passed to Signal will receive any signals. | ||||
| // | ||||
| // Panics if the signal handler is not a `SignalRegistrar`. | ||||
| func (conn *Conn) Signal(ch chan<- *Signal) { | ||||
| 	handler, ok := conn.signalHandler.(SignalRegistrar) | ||||
| 	if !ok { | ||||
| 		panic("cannot use this method with a non SignalRegistrar handler") | ||||
| 	} | ||||
| 	handler.AddSignal(ch) | ||||
| } | ||||
|  | ||||
| // RemoveSignal removes the given channel from the list of the registered channels. | ||||
| // | ||||
| // Panics if the signal handler is not a `SignalRegistrar`. | ||||
| func (conn *Conn) RemoveSignal(ch chan<- *Signal) { | ||||
| 	handler, ok := conn.signalHandler.(SignalRegistrar) | ||||
| 	if !ok { | ||||
| 		panic("cannot use this method with a non SignalRegistrar handler") | ||||
| 	} | ||||
| 	handler.RemoveSignal(ch) | ||||
| } | ||||
|  | ||||
| // SupportsUnixFDs returns whether the underlying transport supports passing of | ||||
| // unix file descriptors. If this is false, method calls containing unix file | ||||
| // descriptors will return an error and emitted signals containing them will | ||||
| // not be sent. | ||||
| func (conn *Conn) SupportsUnixFDs() bool { | ||||
| 	return conn.unixFD | ||||
| } | ||||
|  | ||||
| // Error represents a D-Bus message of type Error. | ||||
| type Error struct { | ||||
| 	Name string | ||||
| 	Body []interface{} | ||||
| } | ||||
|  | ||||
| func NewError(name string, body []interface{}) *Error { | ||||
| 	return &Error{name, body} | ||||
| } | ||||
|  | ||||
| func (e Error) Error() string { | ||||
| 	if len(e.Body) >= 1 { | ||||
| 		s, ok := e.Body[0].(string) | ||||
| 		if ok { | ||||
| 			return s | ||||
| 		} | ||||
| 	} | ||||
| 	return e.Name | ||||
| } | ||||
|  | ||||
| // Signal represents a D-Bus message of type Signal. The name member is given in | ||||
| // "interface.member" notation, e.g. org.freedesktop.D-Bus.NameLost. | ||||
| type Signal struct { | ||||
| 	Sender string | ||||
| 	Path   ObjectPath | ||||
| 	Name   string | ||||
| 	Body   []interface{} | ||||
| } | ||||
|  | ||||
| // transport is a D-Bus transport. | ||||
| type transport interface { | ||||
| 	// Read and Write raw data (for example, for the authentication protocol). | ||||
| 	io.ReadWriteCloser | ||||
|  | ||||
| 	// Send the initial null byte used for the EXTERNAL mechanism. | ||||
| 	SendNullByte() error | ||||
|  | ||||
| 	// Returns whether this transport supports passing Unix FDs. | ||||
| 	SupportsUnixFDs() bool | ||||
|  | ||||
| 	// Signal the transport that Unix FD passing is enabled for this connection. | ||||
| 	EnableUnixFDs() | ||||
|  | ||||
| 	// Read / send a message, handling things like Unix FDs. | ||||
| 	ReadMessage() (*Message, error) | ||||
| 	SendMessage(*Message) error | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	transports = make(map[string]func(string) (transport, error)) | ||||
| ) | ||||
|  | ||||
| func getTransport(address string) (transport, error) { | ||||
| 	var err error | ||||
| 	var t transport | ||||
|  | ||||
| 	addresses := strings.Split(address, ";") | ||||
| 	for _, v := range addresses { | ||||
| 		i := strings.IndexRune(v, ':') | ||||
| 		if i == -1 { | ||||
| 			err = errors.New("dbus: invalid bus address (no transport)") | ||||
| 			continue | ||||
| 		} | ||||
| 		f := transports[v[:i]] | ||||
| 		if f == nil { | ||||
| 			err = errors.New("dbus: invalid bus address (invalid or unsupported transport)") | ||||
| 			continue | ||||
| 		} | ||||
| 		t, err = f(v[i+1:]) | ||||
| 		if err == nil { | ||||
| 			return t, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, err | ||||
| } | ||||
|  | ||||
| // getKey gets a key from a the list of keys. Returns "" on error / not found... | ||||
| func getKey(s, key string) string { | ||||
| 	for _, keyEqualsValue := range strings.Split(s, ",") { | ||||
| 		keyValue := strings.SplitN(keyEqualsValue, "=", 2) | ||||
| 		if len(keyValue) == 2 && keyValue[0] == key { | ||||
| 			return keyValue[1] | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type outputHandler struct { | ||||
| 	conn    *Conn | ||||
| 	sendLck sync.Mutex | ||||
| 	closed  struct { | ||||
| 		isClosed bool | ||||
| 		lck      sync.RWMutex | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *outputHandler) sendAndIfClosed(msg *Message, ifClosed func()) error { | ||||
| 	h.closed.lck.RLock() | ||||
| 	defer h.closed.lck.RUnlock() | ||||
| 	if h.closed.isClosed { | ||||
| 		if ifClosed != nil { | ||||
| 			ifClosed() | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| 	h.sendLck.Lock() | ||||
| 	defer h.sendLck.Unlock() | ||||
| 	return h.conn.SendMessage(msg) | ||||
| } | ||||
|  | ||||
| func (h *outputHandler) close() { | ||||
| 	h.closed.lck.Lock() | ||||
| 	defer h.closed.lck.Unlock() | ||||
| 	h.closed.isClosed = true | ||||
| } | ||||
|  | ||||
| type serialGenerator struct { | ||||
| 	lck        sync.Mutex | ||||
| 	nextSerial uint32 | ||||
| 	serialUsed map[uint32]bool | ||||
| } | ||||
|  | ||||
| func newSerialGenerator() *serialGenerator { | ||||
| 	return &serialGenerator{ | ||||
| 		serialUsed: map[uint32]bool{0: true}, | ||||
| 		nextSerial: 1, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (gen *serialGenerator) GetSerial() uint32 { | ||||
| 	gen.lck.Lock() | ||||
| 	defer gen.lck.Unlock() | ||||
| 	n := gen.nextSerial | ||||
| 	for gen.serialUsed[n] { | ||||
| 		n++ | ||||
| 	} | ||||
| 	gen.serialUsed[n] = true | ||||
| 	gen.nextSerial = n + 1 | ||||
| 	return n | ||||
| } | ||||
|  | ||||
| func (gen *serialGenerator) RetireSerial(serial uint32) { | ||||
| 	gen.lck.Lock() | ||||
| 	defer gen.lck.Unlock() | ||||
| 	delete(gen.serialUsed, serial) | ||||
| } | ||||
|  | ||||
| type nameTracker struct { | ||||
| 	lck    sync.RWMutex | ||||
| 	unique string | ||||
| 	names  map[string]struct{} | ||||
| } | ||||
|  | ||||
| func newNameTracker() *nameTracker { | ||||
| 	return &nameTracker{names: map[string]struct{}{}} | ||||
| } | ||||
| func (tracker *nameTracker) acquireUniqueConnectionName(name string) { | ||||
| 	tracker.lck.Lock() | ||||
| 	defer tracker.lck.Unlock() | ||||
| 	tracker.unique = name | ||||
| } | ||||
| func (tracker *nameTracker) acquireName(name string) { | ||||
| 	tracker.lck.Lock() | ||||
| 	defer tracker.lck.Unlock() | ||||
| 	tracker.names[name] = struct{}{} | ||||
| } | ||||
| func (tracker *nameTracker) loseName(name string) { | ||||
| 	tracker.lck.Lock() | ||||
| 	defer tracker.lck.Unlock() | ||||
| 	delete(tracker.names, name) | ||||
| } | ||||
|  | ||||
| func (tracker *nameTracker) uniqueNameIsKnown() bool { | ||||
| 	tracker.lck.RLock() | ||||
| 	defer tracker.lck.RUnlock() | ||||
| 	return tracker.unique != "" | ||||
| } | ||||
| func (tracker *nameTracker) isKnownName(name string) bool { | ||||
| 	tracker.lck.RLock() | ||||
| 	defer tracker.lck.RUnlock() | ||||
| 	_, ok := tracker.names[name] | ||||
| 	return ok || name == tracker.unique | ||||
| } | ||||
| func (tracker *nameTracker) listKnownNames() []string { | ||||
| 	tracker.lck.RLock() | ||||
| 	defer tracker.lck.RUnlock() | ||||
| 	out := make([]string, 0, len(tracker.names)+1) | ||||
| 	out = append(out, tracker.unique) | ||||
| 	for k := range tracker.names { | ||||
| 		out = append(out, k) | ||||
| 	} | ||||
| 	return out | ||||
| } | ||||
|  | ||||
| type callTracker struct { | ||||
| 	calls map[uint32]*Call | ||||
| 	lck   sync.RWMutex | ||||
| } | ||||
|  | ||||
| func newCallTracker() *callTracker { | ||||
| 	return &callTracker{calls: map[uint32]*Call{}} | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) track(sn uint32, call *Call) { | ||||
| 	tracker.lck.Lock() | ||||
| 	tracker.calls[sn] = call | ||||
| 	tracker.lck.Unlock() | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) handleReply(msg *Message) uint32 { | ||||
| 	serial := msg.Headers[FieldReplySerial].value.(uint32) | ||||
| 	tracker.lck.RLock() | ||||
| 	_, ok := tracker.calls[serial] | ||||
| 	tracker.lck.RUnlock() | ||||
| 	if ok { | ||||
| 		tracker.finalizeWithBody(serial, msg.Body) | ||||
| 	} | ||||
| 	return serial | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) handleDBusError(msg *Message) uint32 { | ||||
| 	serial := msg.Headers[FieldReplySerial].value.(uint32) | ||||
| 	tracker.lck.RLock() | ||||
| 	_, ok := tracker.calls[serial] | ||||
| 	tracker.lck.RUnlock() | ||||
| 	if ok { | ||||
| 		name, _ := msg.Headers[FieldErrorName].value.(string) | ||||
| 		tracker.finalizeWithError(serial, Error{name, msg.Body}) | ||||
| 	} | ||||
| 	return serial | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) handleSendError(msg *Message, err error) { | ||||
| 	if err == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	tracker.lck.RLock() | ||||
| 	_, ok := tracker.calls[msg.serial] | ||||
| 	tracker.lck.RUnlock() | ||||
| 	if ok { | ||||
| 		tracker.finalizeWithError(msg.serial, err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // finalize was the only func that did not strobe Done | ||||
| func (tracker *callTracker) finalize(sn uint32) { | ||||
| 	tracker.lck.Lock() | ||||
| 	defer tracker.lck.Unlock() | ||||
| 	c, ok := tracker.calls[sn] | ||||
| 	if ok { | ||||
| 		delete(tracker.calls, sn) | ||||
| 		c.ContextCancel() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) finalizeWithBody(sn uint32, body []interface{}) { | ||||
| 	tracker.lck.Lock() | ||||
| 	c, ok := tracker.calls[sn] | ||||
| 	if ok { | ||||
| 		delete(tracker.calls, sn) | ||||
| 	} | ||||
| 	tracker.lck.Unlock() | ||||
| 	if ok { | ||||
| 		c.Body = body | ||||
| 		c.done() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) finalizeWithError(sn uint32, err error) { | ||||
| 	tracker.lck.Lock() | ||||
| 	c, ok := tracker.calls[sn] | ||||
| 	if ok { | ||||
| 		delete(tracker.calls, sn) | ||||
| 	} | ||||
| 	tracker.lck.Unlock() | ||||
| 	if ok { | ||||
| 		c.Err = err | ||||
| 		c.done() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (tracker *callTracker) finalizeAllWithError(err error) { | ||||
| 	tracker.lck.Lock() | ||||
| 	closedCalls := make([]*Call, 0, len(tracker.calls)) | ||||
| 	for sn := range tracker.calls { | ||||
| 		closedCalls = append(closedCalls, tracker.calls[sn]) | ||||
| 	} | ||||
| 	tracker.calls = map[uint32]*Call{} | ||||
| 	tracker.lck.Unlock() | ||||
| 	for _, call := range closedCalls { | ||||
| 		call.Err = err | ||||
| 		call.done() | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										37
									
								
								vendor/github.com/godbus/dbus/v5/conn_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/godbus/dbus/v5/conn_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| ) | ||||
|  | ||||
| const defaultSystemBusAddress = "unix:path=/opt/local/var/run/dbus/system_bus_socket" | ||||
|  | ||||
| func getSessionBusPlatformAddress() (string, error) { | ||||
| 	cmd := exec.Command("launchctl", "getenv", "DBUS_LAUNCHD_SESSION_BUS_SOCKET") | ||||
| 	b, err := cmd.CombinedOutput() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	if len(b) == 0 { | ||||
| 		return "", errors.New("dbus: couldn't determine address of session bus") | ||||
| 	} | ||||
|  | ||||
| 	return "unix:path=" + string(b[:len(b)-1]), nil | ||||
| } | ||||
|  | ||||
| func getSystemBusPlatformAddress() string { | ||||
| 	address := os.Getenv("DBUS_LAUNCHD_SESSION_BUS_SOCKET") | ||||
| 	if address != "" { | ||||
| 		return fmt.Sprintf("unix:path=%s", address) | ||||
| 	} | ||||
| 	return defaultSystemBusAddress | ||||
| } | ||||
|  | ||||
| func tryDiscoverDbusSessionBusAddress() string { | ||||
| 	return "" | ||||
| } | ||||
							
								
								
									
										93
									
								
								vendor/github.com/godbus/dbus/v5/conn_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								vendor/github.com/godbus/dbus/v5/conn_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| // +build !darwin | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"os/user" | ||||
| 	"path" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| var execCommand = exec.Command | ||||
|  | ||||
| func getSessionBusPlatformAddress() (string, error) { | ||||
| 	cmd := execCommand("dbus-launch") | ||||
| 	b, err := cmd.CombinedOutput() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	i := bytes.IndexByte(b, '=') | ||||
| 	j := bytes.IndexByte(b, '\n') | ||||
|  | ||||
| 	if i == -1 || j == -1 || i > j { | ||||
| 		return "", errors.New("dbus: couldn't determine address of session bus") | ||||
| 	} | ||||
|  | ||||
| 	env, addr := string(b[0:i]), string(b[i+1:j]) | ||||
| 	os.Setenv(env, addr) | ||||
|  | ||||
| 	return addr, nil | ||||
| } | ||||
|  | ||||
| // tryDiscoverDbusSessionBusAddress tries to discover an existing dbus session | ||||
| // and return the value of its DBUS_SESSION_BUS_ADDRESS. | ||||
| // It tries different techniques employed by different operating systems, | ||||
| // returning the first valid address it finds, or an empty string. | ||||
| // | ||||
| // * /run/user/<uid>/bus           if this exists, it *is* the bus socket. present on | ||||
| //                                 Ubuntu 18.04 | ||||
| // * /run/user/<uid>/dbus-session: if this exists, it can be parsed for the bus | ||||
| //                                 address. present on Ubuntu 16.04 | ||||
| // | ||||
| // See https://dbus.freedesktop.org/doc/dbus-launch.1.html | ||||
| func tryDiscoverDbusSessionBusAddress() string { | ||||
| 	if runtimeDirectory, err := getRuntimeDirectory(); err == nil { | ||||
|  | ||||
| 		if runUserBusFile := path.Join(runtimeDirectory, "bus"); fileExists(runUserBusFile) { | ||||
| 			// if /run/user/<uid>/bus exists, that file itself | ||||
| 			// *is* the unix socket, so return its path | ||||
| 			return fmt.Sprintf("unix:path=%s", runUserBusFile) | ||||
| 		} | ||||
| 		if runUserSessionDbusFile := path.Join(runtimeDirectory, "dbus-session"); fileExists(runUserSessionDbusFile) { | ||||
| 			// if /run/user/<uid>/dbus-session exists, it's a | ||||
| 			// text file // containing the address of the socket, e.g.: | ||||
| 			// DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-E1c73yNqrG | ||||
|  | ||||
| 			if f, err := ioutil.ReadFile(runUserSessionDbusFile); err == nil { | ||||
| 				fileContent := string(f) | ||||
|  | ||||
| 				prefix := "DBUS_SESSION_BUS_ADDRESS=" | ||||
|  | ||||
| 				if strings.HasPrefix(fileContent, prefix) { | ||||
| 					address := strings.TrimRight(strings.TrimPrefix(fileContent, prefix), "\n\r") | ||||
| 					return address | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func getRuntimeDirectory() (string, error) { | ||||
| 	if currentUser, err := user.Current(); err != nil { | ||||
| 		return "", err | ||||
| 	} else { | ||||
| 		return fmt.Sprintf("/run/user/%s", currentUser.Uid), nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func fileExists(filename string) bool { | ||||
| 	if _, err := os.Stat(filename); !os.IsNotExist(err) { | ||||
| 		return true | ||||
| 	} else { | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/github.com/godbus/dbus/v5/conn_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/godbus/dbus/v5/conn_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| //+build !windows,!solaris,!darwin | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| const defaultSystemBusAddress = "unix:path=/var/run/dbus/system_bus_socket" | ||||
|  | ||||
| func getSystemBusPlatformAddress() string { | ||||
| 	address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS") | ||||
| 	if address != "" { | ||||
| 		return address | ||||
| 	} | ||||
| 	return defaultSystemBusAddress | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/github.com/godbus/dbus/v5/conn_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/godbus/dbus/v5/conn_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| //+build windows | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import "os" | ||||
|  | ||||
| const defaultSystemBusAddress = "tcp:host=127.0.0.1,port=12434" | ||||
|  | ||||
| func getSystemBusPlatformAddress() string { | ||||
| 	address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS") | ||||
| 	if address != "" { | ||||
| 		return address | ||||
| 	} | ||||
| 	return defaultSystemBusAddress | ||||
| } | ||||
							
								
								
									
										428
									
								
								vendor/github.com/godbus/dbus/v5/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								vendor/github.com/godbus/dbus/v5/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,428 @@ | ||||
| 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) | ||||
| 		return store(dest, src) | ||||
| 	} | ||||
| 	if !src.Type().ConvertibleTo(dest.Type()) { | ||||
| 		return fmt.Errorf( | ||||
| 			"dbus.Store: type mismatch: cannot convert %s to %s", | ||||
| 			src.Type(), dest.Type()) | ||||
| 	} | ||||
| 	dest.Set(src.Convert(dest.Type())) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func kindsAreCompatible(dest, src reflect.Type) bool { | ||||
| 	switch { | ||||
| 	case isVariant(dest): | ||||
| 		return true | ||||
| 	case dest.Kind() == reflect.Interface: | ||||
| 		return true | ||||
| 	default: | ||||
| 		return dest.Kind() == src.Kind() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func isConvertibleTo(dest, src reflect.Type) bool { | ||||
| 	switch { | ||||
| 	case isVariant(dest): | ||||
| 		return true | ||||
| 	case dest.Kind() == reflect.Interface: | ||||
| 		return true | ||||
| 	case dest.Kind() == reflect.Slice: | ||||
| 		return src.Kind() == reflect.Slice && | ||||
| 			isConvertibleTo(dest.Elem(), src.Elem()) | ||||
| 	case dest.Kind() == reflect.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 == '_' | ||||
| } | ||||
							
								
								
									
										62
									
								
								vendor/github.com/godbus/dbus/decoder.go → vendor/github.com/godbus/dbus/v5/decoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/godbus/dbus/decoder.go → vendor/github.com/godbus/dbus/v5/decoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -188,10 +188,23 @@ func (dec *decoder) decode(s string, depth int) interface{} { | ||||
| 		if depth >= 64 { | ||||
| 			panic(FormatError("input exceeds container depth limit")) | ||||
| 		} | ||||
| 		sig := s[1:] | ||||
| 		length := dec.decode("u", depth).(uint32) | ||||
| 		v := reflect.MakeSlice(reflect.SliceOf(typeFor(s[1:])), 0, int(length)) | ||||
| 		// capacity can be determined only for fixed-size element types | ||||
| 		var capacity int | ||||
| 		if s := sigByteSize(sig); s != 0 { | ||||
| 			capacity = int(length) / s | ||||
| 		} | ||||
| 		v := reflect.MakeSlice(reflect.SliceOf(typeFor(sig)), 0, capacity) | ||||
| 		// Even for empty arrays, the correct padding must be included | ||||
| 		dec.align(alignment(typeFor(s[1:]))) | ||||
| 		align := alignment(typeFor(s[1:])) | ||||
| 		if len(s) > 1 && s[1] == '(' { | ||||
| 			//Special case for arrays of structs | ||||
| 			//structs decode as a slice of interface{} values | ||||
| 			//but the dbus alignment does not match this | ||||
| 			align = 8 | ||||
| 		} | ||||
| 		dec.align(align) | ||||
| 		spos := dec.pos | ||||
| 		for dec.pos < spos+int(length) { | ||||
| 			ev := dec.decode(s[1:], depth+1) | ||||
| @@ -220,6 +233,51 @@ func (dec *decoder) decode(s string, depth int) interface{} { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // sigByteSize tries to calculates size of the given signature in bytes. | ||||
| // | ||||
| // It returns zero when it can't, for example when it contains non-fixed size | ||||
| // types such as strings, maps and arrays that require reading of the transmitted | ||||
| // data, for that we would need to implement the unread method for Decoder first. | ||||
| func sigByteSize(sig string) int { | ||||
| 	var total int | ||||
| 	for offset := 0; offset < len(sig); { | ||||
| 		switch sig[offset] { | ||||
| 		case 'y': | ||||
| 			total += 1 | ||||
| 			offset += 1 | ||||
| 		case 'n', 'q': | ||||
| 			total += 2 | ||||
| 			offset += 1 | ||||
| 		case 'b', 'i', 'u', 'h': | ||||
| 			total += 4 | ||||
| 			offset += 1 | ||||
| 		case 'x', 't', 'd': | ||||
| 			total += 8 | ||||
| 			offset += 1 | ||||
| 		case '(': | ||||
| 			i := 1 | ||||
| 			depth := 1 | ||||
| 			for i < len(sig[offset:]) && depth != 0 { | ||||
| 				if sig[offset+i] == '(' { | ||||
| 					depth++ | ||||
| 				} else if sig[offset+i] == ')' { | ||||
| 					depth-- | ||||
| 				} | ||||
| 				i++ | ||||
| 			} | ||||
| 			s := sigByteSize(sig[offset+1 : offset+i-1]) | ||||
| 			if s == 0 { | ||||
| 				return 0 | ||||
| 			} | ||||
| 			total += s | ||||
| 			offset += i | ||||
| 		default: | ||||
| 			return 0 | ||||
| 		} | ||||
| 	} | ||||
| 	return total | ||||
| } | ||||
| 
 | ||||
| // A FormatError is an error in the wire format. | ||||
| type FormatError string | ||||
| 
 | ||||
							
								
								
									
										328
									
								
								vendor/github.com/godbus/dbus/v5/default_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								vendor/github.com/godbus/dbus/v5/default_handler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,328 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| func newIntrospectIntf(h *defaultHandler) *exportedIntf { | ||||
| 	methods := make(map[string]Method) | ||||
| 	methods["Introspect"] = exportedMethod{ | ||||
| 		reflect.ValueOf(func(msg Message) (string, *Error) { | ||||
| 			path := msg.Headers[FieldPath].value.(ObjectPath) | ||||
| 			return h.introspectPath(path), nil | ||||
| 		}), | ||||
| 	} | ||||
| 	return newExportedIntf(methods, true) | ||||
| } | ||||
|  | ||||
| //NewDefaultHandler returns an instance of the default | ||||
| //call handler. This is useful if you want to implement only | ||||
| //one of the two handlers but not both. | ||||
| // | ||||
| // Deprecated: this is the default value, don't use it, it will be unexported. | ||||
| func NewDefaultHandler() *defaultHandler { | ||||
| 	h := &defaultHandler{ | ||||
| 		objects:     make(map[ObjectPath]*exportedObj), | ||||
| 		defaultIntf: make(map[string]*exportedIntf), | ||||
| 	} | ||||
| 	h.defaultIntf["org.freedesktop.DBus.Introspectable"] = newIntrospectIntf(h) | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| type defaultHandler struct { | ||||
| 	sync.RWMutex | ||||
| 	objects     map[ObjectPath]*exportedObj | ||||
| 	defaultIntf map[string]*exportedIntf | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) PathExists(path ObjectPath) bool { | ||||
| 	_, ok := h.objects[path] | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) introspectPath(path ObjectPath) string { | ||||
| 	subpath := make(map[string]struct{}) | ||||
| 	var xml bytes.Buffer | ||||
| 	xml.WriteString("<node>") | ||||
| 	for obj := range h.objects { | ||||
| 		p := string(path) | ||||
| 		if p != "/" { | ||||
| 			p += "/" | ||||
| 		} | ||||
| 		if strings.HasPrefix(string(obj), p) { | ||||
| 			node_name := strings.Split(string(obj[len(p):]), "/")[0] | ||||
| 			subpath[node_name] = struct{}{} | ||||
| 		} | ||||
| 	} | ||||
| 	for s := range subpath { | ||||
| 		xml.WriteString("\n\t<node name=\"" + s + "\"/>") | ||||
| 	} | ||||
| 	xml.WriteString("\n</node>") | ||||
| 	return xml.String() | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) LookupObject(path ObjectPath) (ServerObject, bool) { | ||||
| 	h.RLock() | ||||
| 	defer h.RUnlock() | ||||
| 	object, ok := h.objects[path] | ||||
| 	if ok { | ||||
| 		return object, ok | ||||
| 	} | ||||
|  | ||||
| 	// If an object wasn't found for this exact path, | ||||
| 	// look for a matching subtree registration | ||||
| 	subtreeObject := newExportedObject() | ||||
| 	path = path[:strings.LastIndex(string(path), "/")] | ||||
| 	for len(path) > 0 { | ||||
| 		object, ok = h.objects[path] | ||||
| 		if ok { | ||||
| 			for name, iface := range object.interfaces { | ||||
| 				// Only include this handler if it registered for the subtree | ||||
| 				if iface.isFallbackInterface() { | ||||
| 					subtreeObject.interfaces[name] = iface | ||||
| 				} | ||||
| 			} | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		path = path[:strings.LastIndex(string(path), "/")] | ||||
| 	} | ||||
|  | ||||
| 	for name, intf := range h.defaultIntf { | ||||
| 		if _, exists := subtreeObject.interfaces[name]; exists { | ||||
| 			continue | ||||
| 		} | ||||
| 		subtreeObject.interfaces[name] = intf | ||||
| 	} | ||||
|  | ||||
| 	return subtreeObject, true | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) AddObject(path ObjectPath, object *exportedObj) { | ||||
| 	h.Lock() | ||||
| 	h.objects[path] = object | ||||
| 	h.Unlock() | ||||
| } | ||||
|  | ||||
| func (h *defaultHandler) DeleteObject(path ObjectPath) { | ||||
| 	h.Lock() | ||||
| 	delete(h.objects, path) | ||||
| 	h.Unlock() | ||||
| } | ||||
|  | ||||
| type exportedMethod struct { | ||||
| 	reflect.Value | ||||
| } | ||||
|  | ||||
| func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) { | ||||
| 	t := m.Type() | ||||
|  | ||||
| 	params := make([]reflect.Value, len(args)) | ||||
| 	for i := 0; i < len(args); i++ { | ||||
| 		params[i] = reflect.ValueOf(args[i]).Elem() | ||||
| 	} | ||||
|  | ||||
| 	ret := m.Value.Call(params) | ||||
|  | ||||
| 	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 { | ||||
| 	mu         sync.RWMutex | ||||
| 	interfaces map[string]*exportedIntf | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) LookupInterface(name string) (Interface, bool) { | ||||
| 	if name == "" { | ||||
| 		return obj, true | ||||
| 	} | ||||
| 	obj.mu.RLock() | ||||
| 	defer obj.mu.RUnlock() | ||||
| 	intf, exists := obj.interfaces[name] | ||||
| 	return intf, exists | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) AddInterface(name string, iface *exportedIntf) { | ||||
| 	obj.mu.Lock() | ||||
| 	defer obj.mu.Unlock() | ||||
| 	obj.interfaces[name] = iface | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) DeleteInterface(name string) { | ||||
| 	obj.mu.Lock() | ||||
| 	defer obj.mu.Unlock() | ||||
| 	delete(obj.interfaces, name) | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) LookupMethod(name string) (Method, bool) { | ||||
| 	obj.mu.RLock() | ||||
| 	defer obj.mu.RUnlock() | ||||
| 	for _, intf := range obj.interfaces { | ||||
| 		method, exists := intf.LookupMethod(name) | ||||
| 		if exists { | ||||
| 			return method, exists | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, false | ||||
| } | ||||
|  | ||||
| func (obj *exportedObj) isFallbackInterface() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func newExportedIntf(methods map[string]Method, includeSubtree bool) *exportedIntf { | ||||
| 	return &exportedIntf{ | ||||
| 		methods:        methods, | ||||
| 		includeSubtree: includeSubtree, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type exportedIntf struct { | ||||
| 	methods map[string]Method | ||||
|  | ||||
| 	// Whether or not this export is for the entire subtree | ||||
| 	includeSubtree bool | ||||
| } | ||||
|  | ||||
| func (obj *exportedIntf) LookupMethod(name string) (Method, bool) { | ||||
| 	out, exists := obj.methods[name] | ||||
| 	return out, exists | ||||
| } | ||||
|  | ||||
| func (obj *exportedIntf) isFallbackInterface() bool { | ||||
| 	return obj.includeSubtree | ||||
| } | ||||
|  | ||||
| //NewDefaultSignalHandler returns an instance of the default | ||||
| //signal handler. This is useful if you want to implement only | ||||
| //one of the two handlers but not both. | ||||
| // | ||||
| // Deprecated: this is the default value, don't use it, it will be unexported. | ||||
| func NewDefaultSignalHandler() *defaultSignalHandler { | ||||
| 	return &defaultSignalHandler{} | ||||
| } | ||||
|  | ||||
| type defaultSignalHandler struct { | ||||
| 	mu      sync.RWMutex | ||||
| 	closed  bool | ||||
| 	signals []*signalChannelData | ||||
| } | ||||
|  | ||||
| func (sh *defaultSignalHandler) DeliverSignal(intf, name string, signal *Signal) { | ||||
| 	sh.mu.RLock() | ||||
| 	defer sh.mu.RUnlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	for _, scd := range sh.signals { | ||||
| 		scd.deliver(signal) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (sh *defaultSignalHandler) Terminate() { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for _, scd := range sh.signals { | ||||
| 		scd.close() | ||||
| 		close(scd.ch) | ||||
| 	} | ||||
| 	sh.closed = true | ||||
| 	sh.signals = nil | ||||
| } | ||||
|  | ||||
| func (sh *defaultSignalHandler) AddSignal(ch chan<- *Signal) { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	sh.signals = append(sh.signals, &signalChannelData{ | ||||
| 		ch:   ch, | ||||
| 		done: make(chan struct{}), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (sh *defaultSignalHandler) RemoveSignal(ch chan<- *Signal) { | ||||
| 	sh.mu.Lock() | ||||
| 	defer sh.mu.Unlock() | ||||
| 	if sh.closed { | ||||
| 		return | ||||
| 	} | ||||
| 	for i := len(sh.signals) - 1; i >= 0; i-- { | ||||
| 		if ch == sh.signals[i].ch { | ||||
| 			sh.signals[i].close() | ||||
| 			copy(sh.signals[i:], sh.signals[i+1:]) | ||||
| 			sh.signals[len(sh.signals)-1] = nil | ||||
| 			sh.signals = sh.signals[:len(sh.signals)-1] | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type signalChannelData struct { | ||||
| 	wg   sync.WaitGroup | ||||
| 	ch   chan<- *Signal | ||||
| 	done chan struct{} | ||||
| } | ||||
|  | ||||
| func (scd *signalChannelData) deliver(signal *Signal) { | ||||
| 	select { | ||||
| 	case scd.ch <- signal: | ||||
| 	case <-scd.done: | ||||
| 		return | ||||
| 	default: | ||||
| 		scd.wg.Add(1) | ||||
| 		go scd.deferredDeliver(signal) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (scd *signalChannelData) deferredDeliver(signal *Signal) { | ||||
| 	select { | ||||
| 	case scd.ch <- signal: | ||||
| 	case <-scd.done: | ||||
| 	} | ||||
| 	scd.wg.Done() | ||||
| } | ||||
|  | ||||
| func (scd *signalChannelData) close() { | ||||
| 	close(scd.done) | ||||
| 	scd.wg.Wait() // wait until all spawned goroutines return | ||||
| } | ||||
							
								
								
									
										8
									
								
								vendor/github.com/godbus/dbus/doc.go → vendor/github.com/godbus/dbus/v5/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/godbus/dbus/doc.go → vendor/github.com/godbus/dbus/v5/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -19,6 +19,8 @@ respective D-Bus equivalents: | ||||
|      bool        | BOOLEAN | ||||
|      int16       | INT16 | ||||
|      uint16      | UINT16 | ||||
|      int         | INT32 | ||||
|      uint        | UINT32 | ||||
|      int32       | INT32 | ||||
|      uint32      | UINT32 | ||||
|      int64       | INT64 | ||||
| @@ -28,6 +30,7 @@ respective D-Bus equivalents: | ||||
|      ObjectPath  | OBJECT_PATH | ||||
|      Signature   | SIGNATURE | ||||
|      Variant     | VARIANT | ||||
|      interface{} | VARIANT | ||||
|      UnixFDIndex | UNIX_FD | ||||
| 
 | ||||
| Slices and arrays encode as ARRAYs of their element type. | ||||
| @@ -41,6 +44,9 @@ 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. | ||||
| 
 | ||||
| @@ -55,7 +61,7 @@ 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 | ||||
| UnixFD values being substituted by the correct indices. Similarly, the indices | ||||
| of incoming messages are automatically resolved. It shouldn't be necessary to use | ||||
| UnixFDIndex. | ||||
| 
 | ||||
| @@ -60,7 +60,7 @@ func (enc *encoder) binwrite(v interface{}) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Encode encodes the given values to the underyling reader. All written values | ||||
| // Encode encodes the given values to the underlying reader. All written values | ||||
| // are aligned properly as required by the D-Bus spec. | ||||
| func (enc *encoder) Encode(vs ...interface{}) (err error) { | ||||
| 	defer func() { | ||||
| @@ -96,10 +96,10 @@ func (enc *encoder) encode(v reflect.Value, depth int) { | ||||
| 	case reflect.Uint16: | ||||
| 		enc.binwrite(uint16(v.Uint())) | ||||
| 		enc.pos += 2 | ||||
| 	case reflect.Int32: | ||||
| 	case reflect.Int, reflect.Int32: | ||||
| 		enc.binwrite(int32(v.Int())) | ||||
| 		enc.pos += 4 | ||||
| 	case reflect.Uint32: | ||||
| 	case reflect.Uint, reflect.Uint32: | ||||
| 		enc.binwrite(uint32(v.Uint())) | ||||
| 		enc.pos += 4 | ||||
| 	case reflect.Int64: | ||||
| @@ -202,6 +202,8 @@ func (enc *encoder) encode(v reflect.Value, depth int) { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		enc.pos += length | ||||
| 	case reflect.Interface: | ||||
| 		enc.encode(reflect.ValueOf(MakeVariant(v.Interface())), depth) | ||||
| 	default: | ||||
| 		panic(InvalidTypeError{v.Type()}) | ||||
| 	} | ||||
							
								
								
									
										363
									
								
								vendor/github.com/godbus/dbus/export.go → vendor/github.com/godbus/dbus/v5/export.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										363
									
								
								vendor/github.com/godbus/dbus/export.go → vendor/github.com/godbus/dbus/v5/export.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -8,167 +8,73 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	errmsgInvalidArg = Error{ | ||||
| 	ErrMsgInvalidArg = Error{ | ||||
| 		"org.freedesktop.DBus.Error.InvalidArgs", | ||||
| 		[]interface{}{"Invalid type / number of args"}, | ||||
| 	} | ||||
| 	errmsgNoObject = Error{ | ||||
| 	ErrMsgNoObject = Error{ | ||||
| 		"org.freedesktop.DBus.Error.NoSuchObject", | ||||
| 		[]interface{}{"No such object"}, | ||||
| 	} | ||||
| 	errmsgUnknownMethod = Error{ | ||||
| 	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"}, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| // exportWithMapping represents an exported struct along with a method name | ||||
| // mapping to allow for exporting lower-case methods, etc. | ||||
| type exportWithMapping struct { | ||||
| 	export interface{} | ||||
| 
 | ||||
| 	// Method name mapping; key -> struct method, value -> dbus method. | ||||
| 	mapping map[string]string | ||||
| 
 | ||||
| 	// Whether or not this export is for the entire subtree | ||||
| 	includeSubtree bool | ||||
| 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 exportedMethod(export exportWithMapping, name string) reflect.Value { | ||||
| 	if export.export == nil { | ||||
| 		return reflect.Value{} | ||||
| 	} | ||||
| 
 | ||||
| 	// If a mapping was included in the export, check the map to see if we | ||||
| 	// should be looking for a different method in the export. | ||||
| 	if export.mapping != nil { | ||||
| 		for key, value := range export.mapping { | ||||
| 			if value == name { | ||||
| 				name = key | ||||
| 				break | ||||
| 			} | ||||
| 
 | ||||
| 			// Catch the case where a method is aliased but the client is calling | ||||
| 			// the original, e.g. the "Foo" method was exported mapped to | ||||
| 			// "foo," and dbus client called the original "Foo." | ||||
| 			if key == name { | ||||
| 				return reflect.Value{} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	value := reflect.ValueOf(export.export) | ||||
| 	m := value.MethodByName(name) | ||||
| 
 | ||||
| 	// Catch the case of attempting to call an unexported method | ||||
| 	method, ok := value.Type().MethodByName(name) | ||||
| 
 | ||||
| 	if !m.IsValid() || !ok || method.PkgPath != "" { | ||||
| 		return reflect.Value{} | ||||
| 	} | ||||
| 	t := m.Type() | ||||
| 	if t.NumOut() == 0 || | ||||
| 		t.Out(t.NumOut()-1) != reflect.TypeOf(&errmsgInvalidArg) { | ||||
| 
 | ||||
| 		return reflect.Value{} | ||||
| 	} | ||||
| 	return m | ||||
| } | ||||
| 
 | ||||
| // searchHandlers will look through all registered handlers looking for one | ||||
| // to handle the given path. If a verbatim one isn't found, it will check for | ||||
| // a subtree registration for the path as well. | ||||
| func (conn *Conn) searchHandlers(path ObjectPath) (map[string]exportWithMapping, bool) { | ||||
| 	conn.handlersLck.RLock() | ||||
| 	defer conn.handlersLck.RUnlock() | ||||
| 
 | ||||
| 	handlers, ok := conn.handlers[path] | ||||
| func computeMethodName(name string, mapping map[string]string) string { | ||||
| 	newname, ok := mapping[name] | ||||
| 	if ok { | ||||
| 		return handlers, ok | ||||
| 		name = newname | ||||
| 	} | ||||
| 
 | ||||
| 	// If handlers weren't found for this exact path, look for a matching subtree | ||||
| 	// registration | ||||
| 	handlers = make(map[string]exportWithMapping) | ||||
| 	path = path[:strings.LastIndex(string(path), "/")] | ||||
| 	for len(path) > 0 { | ||||
| 		var subtreeHandlers map[string]exportWithMapping | ||||
| 		subtreeHandlers, ok = conn.handlers[path] | ||||
| 		if ok { | ||||
| 			for iface, handler := range subtreeHandlers { | ||||
| 				// Only include this handler if it registered for the subtree | ||||
| 				if handler.includeSubtree { | ||||
| 					handlers[iface] = handler | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			break | ||||
| 		} | ||||
| 
 | ||||
| 		path = path[:strings.LastIndex(string(path), "/")] | ||||
| 	} | ||||
| 
 | ||||
| 	return handlers, ok | ||||
| 	return name | ||||
| } | ||||
| 
 | ||||
| // 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, hasIface := 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) | ||||
| 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 | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	if len(name) == 0 { | ||||
| 		conn.sendError(errmsgUnknownMethod, sender, serial) | ||||
| 		// map names while building table | ||||
| 		methods[computeMethodName(methtype.Name, mapping)] = method | ||||
| 	} | ||||
| 	return methods | ||||
| } | ||||
| 
 | ||||
| 	// Find the exported handler (if any) for this path | ||||
| 	handlers, ok := conn.searchHandlers(path) | ||||
| 	if !ok { | ||||
| 		conn.sendError(errmsgNoObject, sender, serial) | ||||
| 		return | ||||
| 	} | ||||
| func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) { | ||||
| 	pointers := make([]interface{}, m.NumArguments()) | ||||
| 	decode := make([]interface{}, 0, len(body)) | ||||
| 
 | ||||
| 	var m reflect.Value | ||||
| 	if hasIface { | ||||
| 		iface := handlers[ifaceName] | ||||
| 		m = exportedMethod(iface, name) | ||||
| 	} else { | ||||
| 		for _, v := range handlers { | ||||
| 			m = exportedMethod(v, name) | ||||
| 			if m.IsValid() { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if !m.IsValid() { | ||||
| 		conn.sendError(errmsgUnknownMethod, sender, serial) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	t := m.Type() | ||||
| 	vs := msg.Body | ||||
| 	pointers := make([]interface{}, t.NumIn()) | ||||
| 	decode := make([]interface{}, 0, len(vs)) | ||||
| 	for i := 0; i < t.NumIn(); i++ { | ||||
| 		tp := t.In(i) | ||||
| 	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() { | ||||
| @@ -180,26 +86,73 @@ func (conn *Conn) handleCall(msg *Message) { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if len(decode) != len(vs) { | ||||
| 		conn.sendError(errmsgInvalidArg, sender, serial) | ||||
| 	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 | ||||
| 	} | ||||
| 
 | ||||
| 	if err := Store(vs, decode...); err != nil { | ||||
| 		conn.sendError(errmsgInvalidArg, sender, serial) | ||||
| 	iface, exists := object.LookupInterface(ifaceName) | ||||
| 	if !exists { | ||||
| 		conn.sendError(ErrMsgUnknownInterface, sender, serial) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Extract parameters | ||||
| 	params := make([]reflect.Value, len(pointers)) | ||||
| 	for i := 0; i < len(pointers); i++ { | ||||
| 		params[i] = reflect.ValueOf(pointers[i]).Elem() | ||||
| 	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 | ||||
| 	} | ||||
| 
 | ||||
| 	// Call method | ||||
| 	ret := m.Call(params) | ||||
| 	if em := ret[t.NumOut()-1].Interface().(*Error); em != nil { | ||||
| 		conn.sendError(*em, sender, serial) | ||||
| 	ret, err := m.Call(args...) | ||||
| 	if err != nil { | ||||
| 		conn.sendError(err, sender, serial) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| @@ -212,18 +165,13 @@ func (conn *Conn) handleCall(msg *Message) { | ||||
| 			reply.Headers[FieldDestination] = msg.Headers[FieldSender] | ||||
| 		} | ||||
| 		reply.Headers[FieldReplySerial] = MakeVariant(msg.serial) | ||||
| 		reply.Body = make([]interface{}, len(ret)-1) | ||||
| 		for i := 0; i < len(ret)-1; i++ { | ||||
| 			reply.Body[i] = ret[i].Interface() | ||||
| 		reply.Body = make([]interface{}, len(ret)) | ||||
| 		for i := 0; i < len(ret); i++ { | ||||
| 			reply.Body[i] = ret[i] | ||||
| 		} | ||||
| 		if len(ret) != 1 { | ||||
| 			reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...)) | ||||
| 		} | ||||
| 		conn.outLck.RLock() | ||||
| 		if !conn.closed { | ||||
| 			conn.out <- reply | ||||
| 		} | ||||
| 		conn.outLck.RUnlock() | ||||
| 		reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...)) | ||||
| 
 | ||||
| 		conn.sendMessageAndIfClosed(reply, nil) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @@ -256,12 +204,14 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro | ||||
| 	if len(values) > 0 { | ||||
| 		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...)) | ||||
| 	} | ||||
| 	conn.outLck.RLock() | ||||
| 	defer conn.outLck.RUnlock() | ||||
| 	if conn.closed { | ||||
| 
 | ||||
| 	var closed bool | ||||
| 	conn.sendMessageAndIfClosed(msg, func() { | ||||
| 		closed = true | ||||
| 	}) | ||||
| 	if closed { | ||||
| 		return ErrClosed | ||||
| 	} | ||||
| 	conn.out <- msg | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -303,7 +253,7 @@ func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error { | ||||
| // 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.exportWithMap(v, mapping, path, iface, false) | ||||
| 	return conn.export(getMethods(v, mapping), path, iface, false) | ||||
| } | ||||
| 
 | ||||
| // ExportSubtree works exactly like Export but registers the given value for | ||||
| @@ -326,38 +276,89 @@ func (conn *Conn) ExportSubtree(v interface{}, path ObjectPath, iface string) er | ||||
| // 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.exportWithMap(v, mapping, path, iface, true) | ||||
| 	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) exportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string, includeSubtree bool) error { | ||||
| 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) | ||||
| 	} | ||||
| 
 | ||||
| 	conn.handlersLck.Lock() | ||||
| 	defer conn.handlersLck.Unlock() | ||||
| 
 | ||||
| 	// Remove a previous export if the interface is nil | ||||
| 	if v == nil { | ||||
| 		if _, ok := conn.handlers[path]; ok { | ||||
| 			delete(conn.handlers[path], iface) | ||||
| 			if len(conn.handlers[path]) == 0 { | ||||
| 				delete(conn.handlers, path) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return 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 _, ok := conn.handlers[path]; !ok { | ||||
| 		conn.handlers[path] = make(map[string]exportWithMapping) | ||||
| 	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 | ||||
| 	conn.handlers[path][iface] = exportWithMapping{export: v, mapping: mapping, includeSubtree: includeSubtree} | ||||
| 	obj := h.objects[path] | ||||
| 	obj.AddInterface(iface, newExportedIntf(exportedMethods, includeSubtree)) | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										3
									
								
								vendor/github.com/godbus/dbus/v5/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/godbus/dbus/v5/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| module github.com/godbus/dbus/v5 | ||||
|  | ||||
| go 1.12 | ||||
							
								
								
									
										62
									
								
								vendor/github.com/godbus/dbus/v5/match.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/godbus/dbus/v5/match.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // MatchOption specifies option for dbus routing match rule. Options can be constructed with WithMatch* helpers. | ||||
| // For full list of available options consult | ||||
| // https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-routing-match-rules | ||||
| type MatchOption struct { | ||||
| 	key   string | ||||
| 	value string | ||||
| } | ||||
|  | ||||
| func formatMatchOptions(options []MatchOption) string { | ||||
| 	items := make([]string, 0, len(options)) | ||||
| 	for _, option := range options { | ||||
| 		items = append(items, option.key+"='"+option.value+"'") | ||||
| 	} | ||||
| 	return strings.Join(items, ",") | ||||
| } | ||||
|  | ||||
| // WithMatchOption creates match option with given key and value | ||||
| func WithMatchOption(key, value string) MatchOption { | ||||
| 	return MatchOption{key, value} | ||||
| } | ||||
|  | ||||
| // doesn't make sense to export this option because clients can only | ||||
| // subscribe to messages with signal type. | ||||
| func withMatchType(typ string) MatchOption { | ||||
| 	return WithMatchOption("type", typ) | ||||
| } | ||||
|  | ||||
| // WithMatchSender sets sender match option. | ||||
| func WithMatchSender(sender string) MatchOption { | ||||
| 	return WithMatchOption("sender", sender) | ||||
| } | ||||
|  | ||||
| // WithMatchSender sets interface match option. | ||||
| func WithMatchInterface(iface string) MatchOption { | ||||
| 	return WithMatchOption("interface", iface) | ||||
| } | ||||
|  | ||||
| // WithMatchMember sets member match option. | ||||
| func WithMatchMember(member string) MatchOption { | ||||
| 	return WithMatchOption("member", member) | ||||
| } | ||||
|  | ||||
| // WithMatchObjectPath creates match option that filters events based on given path | ||||
| func WithMatchObjectPath(path ObjectPath) MatchOption { | ||||
| 	return WithMatchOption("path", string(path)) | ||||
| } | ||||
|  | ||||
| // WithMatchPathNamespace sets path_namespace match option. | ||||
| func WithMatchPathNamespace(namespace ObjectPath) MatchOption { | ||||
| 	return WithMatchOption("path_namespace", string(namespace)) | ||||
| } | ||||
|  | ||||
| // WithMatchDestination sets destination match option. | ||||
| func WithMatchDestination(destination string) MatchOption { | ||||
| 	return WithMatchOption("destination", destination) | ||||
| } | ||||
| @@ -22,6 +22,13 @@ const ( | ||||
| 	// 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. | ||||
| @@ -248,7 +255,7 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error { | ||||
| // 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) != 0 { | ||||
| 	if msg.Flags & ^(FlagNoAutoStart|FlagNoReplyExpected|FlagAllowInteractiveAuthorization) != 0 { | ||||
| 		return InvalidMessageError("invalid flags") | ||||
| 	} | ||||
| 	if msg.Type == 0 || msg.Type >= typeMax { | ||||
							
								
								
									
										211
									
								
								vendor/github.com/godbus/dbus/v5/object.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								vendor/github.com/godbus/dbus/v5/object.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,211 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // BusObject is the interface of a remote object on which methods can be | ||||
| // invoked. | ||||
| type BusObject interface { | ||||
| 	Call(method string, flags Flags, args ...interface{}) *Call | ||||
| 	CallWithContext(ctx context.Context, method string, flags Flags, args ...interface{}) *Call | ||||
| 	Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call | ||||
| 	GoWithContext(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call | ||||
| 	AddMatchSignal(iface, member string, options ...MatchOption) *Call | ||||
| 	RemoveMatchSignal(iface, member string, options ...MatchOption) *Call | ||||
| 	GetProperty(p string) (Variant, error) | ||||
| 	SetProperty(p string, v interface{}) error | ||||
| 	Destination() string | ||||
| 	Path() ObjectPath | ||||
| } | ||||
|  | ||||
| // Object represents a remote object on which methods can be invoked. | ||||
| type Object struct { | ||||
| 	conn *Conn | ||||
| 	dest string | ||||
| 	path ObjectPath | ||||
| } | ||||
|  | ||||
| // Call calls a method with (*Object).Go and waits for its reply. | ||||
| func (o *Object) Call(method string, flags Flags, args ...interface{}) *Call { | ||||
| 	return <-o.createCall(context.Background(), method, flags, make(chan *Call, 1), args...).Done | ||||
| } | ||||
|  | ||||
| // CallWithContext acts like Call but takes a context | ||||
| func (o *Object) CallWithContext(ctx context.Context, method string, flags Flags, args ...interface{}) *Call { | ||||
| 	return <-o.createCall(ctx, method, flags, make(chan *Call, 1), args...).Done | ||||
| } | ||||
|  | ||||
| // AddMatchSignal subscribes BusObject to signals from specified interface, | ||||
| // method (member). Additional filter rules can be added via WithMatch* option constructors. | ||||
| // Note: To filter events by object path you have to specify this path via an option. | ||||
| // | ||||
| // Deprecated: use (*Conn) AddMatchSignal instead. | ||||
| func (o *Object) AddMatchSignal(iface, member string, options ...MatchOption) *Call { | ||||
| 	base := []MatchOption{ | ||||
| 		withMatchType("signal"), | ||||
| 		WithMatchInterface(iface), | ||||
| 		WithMatchMember(member), | ||||
| 	} | ||||
|  | ||||
| 	options = append(base, options...) | ||||
| 	return o.conn.BusObject().Call( | ||||
| 		"org.freedesktop.DBus.AddMatch", | ||||
| 		0, | ||||
| 		formatMatchOptions(options), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| // RemoveMatchSignal unsubscribes BusObject from signals from specified interface, | ||||
| // method (member). Additional filter rules can be added via WithMatch* option constructors | ||||
| // | ||||
| // Deprecated: use (*Conn) RemoveMatchSignal instead. | ||||
| func (o *Object) RemoveMatchSignal(iface, member string, options ...MatchOption) *Call { | ||||
| 	base := []MatchOption{ | ||||
| 		withMatchType("signal"), | ||||
| 		WithMatchInterface(iface), | ||||
| 		WithMatchMember(member), | ||||
| 	} | ||||
|  | ||||
| 	options = append(base, options...) | ||||
| 	return o.conn.BusObject().Call( | ||||
| 		"org.freedesktop.DBus.RemoveMatch", | ||||
| 		0, | ||||
| 		formatMatchOptions(options), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| // Go calls a method with the given arguments asynchronously. It returns a | ||||
| // Call structure representing this method call. The passed channel will | ||||
| // return the same value once the call is done. If ch is nil, a new channel | ||||
| // will be allocated. Otherwise, ch has to be buffered or Go will panic. | ||||
| // | ||||
| // If the flags include FlagNoReplyExpected, ch is ignored and a Call structure | ||||
| // is returned with any error in Err and a closed channel in Done containing | ||||
| // the returned Call as it's one entry. | ||||
| // | ||||
| // If the method parameter contains a dot ('.'), the part before the last dot | ||||
| // specifies the interface on which the method is called. | ||||
| func (o *Object) Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call { | ||||
| 	return o.createCall(context.Background(), method, flags, ch, args...) | ||||
| } | ||||
|  | ||||
| // GoWithContext acts like Go but takes a context | ||||
| func (o *Object) GoWithContext(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call { | ||||
| 	return o.createCall(ctx, method, flags, ch, args...) | ||||
| } | ||||
|  | ||||
| func (o *Object) createCall(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call { | ||||
| 	if ctx == nil { | ||||
| 		panic("nil context") | ||||
| 	} | ||||
| 	iface := "" | ||||
| 	i := strings.LastIndex(method, ".") | ||||
| 	if i != -1 { | ||||
| 		iface = method[:i] | ||||
| 	} | ||||
| 	method = method[i+1:] | ||||
| 	msg := new(Message) | ||||
| 	msg.Type = TypeMethodCall | ||||
| 	msg.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, 1) | ||||
| 		} else if cap(ch) == 0 { | ||||
| 			panic("dbus: unbuffered channel passed to (*Object).Go") | ||||
| 		} | ||||
| 		ctx, cancel := context.WithCancel(ctx) | ||||
| 		call := &Call{ | ||||
| 			Destination: o.dest, | ||||
| 			Path:        o.path, | ||||
| 			Method:      method, | ||||
| 			Args:        args, | ||||
| 			Done:        ch, | ||||
| 			ctxCanceler: cancel, | ||||
| 			ctx:         ctx, | ||||
| 		} | ||||
| 		o.conn.calls.track(msg.serial, call) | ||||
| 		o.conn.sendMessageAndIfClosed(msg, func() { | ||||
| 			o.conn.calls.handleSendError(msg, ErrClosed) | ||||
| 			cancel() | ||||
| 		}) | ||||
| 		go func() { | ||||
| 			<-ctx.Done() | ||||
| 			o.conn.calls.handleSendError(msg, ctx.Err()) | ||||
| 		}() | ||||
|  | ||||
| 		return call | ||||
| 	} | ||||
| 	done := make(chan *Call, 1) | ||||
| 	call := &Call{ | ||||
| 		Err:  nil, | ||||
| 		Done: done, | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		call.Done <- call | ||||
| 		close(done) | ||||
| 	}() | ||||
| 	o.conn.sendMessageAndIfClosed(msg, func() { | ||||
| 		call.Err = ErrClosed | ||||
| 	}) | ||||
| 	return call | ||||
| } | ||||
|  | ||||
| // GetProperty calls org.freedesktop.DBus.Properties.Get on the given | ||||
| // object. The property name must be given in interface.member notation. | ||||
| func (o *Object) GetProperty(p string) (Variant, error) { | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| // SetProperty calls org.freedesktop.DBus.Properties.Set on the given | ||||
| // object. The property name must be given in interface.member notation. | ||||
| func (o *Object) SetProperty(p string, v interface{}) error { | ||||
| 	idx := strings.LastIndex(p, ".") | ||||
| 	if idx == -1 || idx+1 == len(p) { | ||||
| 		return errors.New("dbus: invalid property " + p) | ||||
| 	} | ||||
|  | ||||
| 	iface := p[:idx] | ||||
| 	prop := p[idx+1:] | ||||
|  | ||||
| 	return o.Call("org.freedesktop.DBus.Properties.Set", 0, iface, prop, v).Err | ||||
| } | ||||
|  | ||||
| // Destination returns the destination that calls on (o *Object) are sent to. | ||||
| func (o *Object) Destination() string { | ||||
| 	return o.dest | ||||
| } | ||||
|  | ||||
| // Path returns the path that calls on (o *Object") are sent to. | ||||
| func (o *Object) Path() ObjectPath { | ||||
| 	return o.path | ||||
| } | ||||
							
								
								
									
										107
									
								
								vendor/github.com/godbus/dbus/v5/server_interfaces.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								vendor/github.com/godbus/dbus/v5/server_interfaces.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| package dbus | ||||
|  | ||||
| // Terminator allows a handler to implement a shutdown mechanism that | ||||
| // is called when the connection terminates. | ||||
| type Terminator interface { | ||||
| 	Terminate() | ||||
| } | ||||
|  | ||||
| // Handler is the representation of a D-Bus Application. | ||||
| // | ||||
| // The Handler must have a way to lookup objects given | ||||
| // an ObjectPath. The returned object must implement the | ||||
| // ServerObject interface. | ||||
| type Handler interface { | ||||
| 	LookupObject(path ObjectPath) (ServerObject, bool) | ||||
| } | ||||
|  | ||||
| // ServerObject is the representation of an D-Bus Object. | ||||
| // | ||||
| // Objects are registered at a path for a given Handler. | ||||
| // The Objects implement D-Bus interfaces. The semantics | ||||
| // of Interface lookup is up to the implementation of | ||||
| // the ServerObject. The ServerObject implementation may | ||||
| // choose to implement empty string as a valid interface | ||||
| // represeting all methods or not per the D-Bus specification. | ||||
| type ServerObject interface { | ||||
| 	LookupInterface(name string) (Interface, bool) | ||||
| } | ||||
|  | ||||
| // An Interface is the representation of a D-Bus Interface. | ||||
| // | ||||
| // Interfaces are a grouping of methods implemented by the Objects. | ||||
| // Interfaces are responsible for routing method calls. | ||||
| type Interface interface { | ||||
| 	LookupMethod(name string) (Method, bool) | ||||
| } | ||||
|  | ||||
| // A Method represents the exposed methods on D-Bus. | ||||
| type Method interface { | ||||
| 	// Call requires that all arguments are decoded before being passed to it. | ||||
| 	Call(args ...interface{}) ([]interface{}, error) | ||||
| 	NumArguments() int | ||||
| 	NumReturns() int | ||||
| 	// ArgumentValue returns a representative value for the argument at position | ||||
| 	// it should be of the proper type. reflect.Zero would be a good mechanism | ||||
| 	// to use for this Value. | ||||
| 	ArgumentValue(position int) interface{} | ||||
| 	// ReturnValue returns a representative value for the return at position | ||||
| 	// it should be of the proper type. reflect.Zero would be a good mechanism | ||||
| 	// to use for this Value. | ||||
| 	ReturnValue(position int) interface{} | ||||
| } | ||||
|  | ||||
| // An Argument Decoder can decode arguments using the non-standard mechanism | ||||
| // | ||||
| // If a method implements this interface then the non-standard | ||||
| // decoder will be used. | ||||
| // | ||||
| // Method arguments must be decoded from the message. | ||||
| // The mechanism for doing this will vary based on the | ||||
| // implementation of the method. A normal approach is provided | ||||
| // as part of this library, but may be replaced with | ||||
| // any other decoding scheme. | ||||
| type ArgumentDecoder interface { | ||||
| 	// To decode the arguments of a method the sender and message are | ||||
| 	// provided 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) | ||||
| } | ||||
|  | ||||
| // SignalRegistrar manages signal delivery channels. | ||||
| // | ||||
| // This is an optional set of methods for `SignalHandler`. | ||||
| type SignalRegistrar interface { | ||||
| 	AddSignal(ch chan<- *Signal) | ||||
| 	RemoveSignal(ch chan<- *Signal) | ||||
| } | ||||
|  | ||||
| // A DBusError is used to convert a generic object to a D-Bus error. | ||||
| // | ||||
| // Any custom error mechanism may implement this interface to provide | ||||
| // a custom encoding of the error on D-Bus. By default if a normal | ||||
| // error is returned, it will be encoded as the generic | ||||
| // "org.freedesktop.DBus.Error.Failed" error. By implementing this | ||||
| // interface as well a custom encoding may be provided. | ||||
| type DBusError interface { | ||||
| 	DBusError() (string, []interface{}) | ||||
| } | ||||
|  | ||||
| // SerialGenerator is responsible for serials generation. | ||||
| // | ||||
| // Different approaches for the serial generation can be used, | ||||
| // maintaining a map guarded with a mutex (the standard way) or | ||||
| // simply increment an atomic counter. | ||||
| type SerialGenerator interface { | ||||
| 	GetSerial() uint32 | ||||
| 	RetireSerial(serial uint32) | ||||
| } | ||||
							
								
								
									
										8
									
								
								vendor/github.com/godbus/dbus/sig.go → vendor/github.com/godbus/dbus/v5/sig.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/godbus/dbus/sig.go → vendor/github.com/godbus/dbus/v5/sig.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -57,12 +57,12 @@ func getSignature(t reflect.Type) string { | ||||
| 		return "n" | ||||
| 	case reflect.Uint16: | ||||
| 		return "q" | ||||
| 	case reflect.Int32: | ||||
| 	case reflect.Int, reflect.Int32: | ||||
| 		if t == unixFDType { | ||||
| 			return "h" | ||||
| 		} | ||||
| 		return "i" | ||||
| 	case reflect.Uint32: | ||||
| 	case reflect.Uint, reflect.Uint32: | ||||
| 		if t == unixFDIndexType { | ||||
| 			return "h" | ||||
| 		} | ||||
| @@ -101,6 +101,8 @@ func getSignature(t reflect.Type) string { | ||||
| 			panic(InvalidTypeError{t}) | ||||
| 		} | ||||
| 		return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}" | ||||
| 	case reflect.Interface: | ||||
| 		return "v" | ||||
| 	} | ||||
| 	panic(InvalidTypeError{t}) | ||||
| } | ||||
| @@ -162,7 +164,7 @@ 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 successfull, err is nil | ||||
| // 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. | ||||
| @@ -4,8 +4,23 @@ 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 | ||||
| } | ||||
| @@ -31,5 +46,5 @@ func (t genericTransport) SendMessage(msg *Message) error { | ||||
| 			return errors.New("dbus: unix fd passing not enabled") | ||||
| 		} | ||||
| 	} | ||||
| 	return msg.EncodeTo(t, binary.LittleEndian) | ||||
| 	return msg.EncodeTo(t, nativeEndian) | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| //+build !windows | ||||
|  | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	transports["nonce-tcp"] = newNonceTcpTransport | ||||
| } | ||||
|  | ||||
| func newNonceTcpTransport(keys string) (transport, error) { | ||||
| 	host := getKey(keys, "host") | ||||
| 	port := getKey(keys, "port") | ||||
| 	noncefile := getKey(keys, "noncefile") | ||||
| 	if host == "" || port == "" || noncefile == "" { | ||||
| 		return nil, errors.New("dbus: unsupported address (must set host, port and noncefile)") | ||||
| 	} | ||||
| 	protocol, err := tcpFamily(keys) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	socket, err := net.Dial(protocol, net.JoinHostPort(host, port)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	b, err := ioutil.ReadFile(noncefile) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	_, err = socket.Write(b) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return NewConn(socket) | ||||
| } | ||||
							
								
								
									
										41
									
								
								vendor/github.com/godbus/dbus/v5/transport_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/godbus/dbus/v5/transport_tcp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package dbus | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	transports["tcp"] = newTcpTransport | ||||
| } | ||||
|  | ||||
| func tcpFamily(keys string) (string, error) { | ||||
| 	switch getKey(keys, "family") { | ||||
| 	case "": | ||||
| 		return "tcp", nil | ||||
| 	case "ipv4": | ||||
| 		return "tcp4", nil | ||||
| 	case "ipv6": | ||||
| 		return "tcp6", nil | ||||
| 	default: | ||||
| 		return "", errors.New("dbus: invalid tcp family (must be ipv4 or ipv6)") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newTcpTransport(keys string) (transport, error) { | ||||
| 	host := getKey(keys, "host") | ||||
| 	port := getKey(keys, "port") | ||||
| 	if host == "" || port == "" { | ||||
| 		return nil, errors.New("dbus: unsupported address (must set host and port)") | ||||
| 	} | ||||
|  | ||||
| 	protocol, err := tcpFamily(keys) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	socket, err := net.Dial(protocol, net.JoinHostPort(host, port)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return NewConn(socket) | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| //+build !windows | ||||
| //+build !windows,!solaris | ||||
| 
 | ||||
| package dbus | ||||
| 
 | ||||
| @@ -31,6 +31,7 @@ func (o *oobReader) Read(b []byte) (n int, err error) { | ||||
| 
 | ||||
| type unixTransport struct { | ||||
| 	*net.UnixConn | ||||
| 	rdr        *oobReader | ||||
| 	hasUnixFDs bool | ||||
| } | ||||
| 
 | ||||
| @@ -79,10 +80,15 @@ func (t *unixTransport) ReadMessage() (*Message, error) { | ||||
| 	// 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} | ||||
| 	if t.rdr == nil { | ||||
| 		t.rdr = &oobReader{conn: t.UnixConn} | ||||
| 	} else { | ||||
| 		t.rdr.oob = nil | ||||
| 	} | ||||
| 
 | ||||
| 	// read the first 16 bytes (the part of the header that has a constant size), | ||||
| 	// from which we can figure out the length of the rest of the message | ||||
| 	if _, err := io.ReadFull(rd, csheader[:]); err != nil { | ||||
| 	if _, err := io.ReadFull(t.rdr, csheader[:]); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	switch csheader[0] { | ||||
| @@ -104,7 +110,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) { | ||||
| 	// 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 { | ||||
| 	if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	dec := newDecoder(bytes.NewBuffer(headerdata), order) | ||||
| @@ -122,7 +128,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) { | ||||
| 	all := make([]byte, 16+hlen+blen) | ||||
| 	copy(all, csheader[:]) | ||||
| 	copy(all[16:], headerdata[4:]) | ||||
| 	if _, err := io.ReadFull(rd, all[16+hlen:]); err != nil { | ||||
| 	if _, err := io.ReadFull(t.rdr, all[16+hlen:]); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if unixfds != 0 { | ||||
| @@ -130,7 +136,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) { | ||||
| 			return nil, errors.New("dbus: got unix fds on unsupported transport") | ||||
| 		} | ||||
| 		// read the fds from the OOB data | ||||
| 		scms, err := syscall.ParseSocketControlMessage(rd.oob) | ||||
| 		scms, err := syscall.ParseSocketControlMessage(t.rdr.oob) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @@ -148,11 +154,23 @@ func (t *unixTransport) ReadMessage() (*Message, error) { | ||||
| 		// 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 { | ||||
| 			switch v.(type) { | ||||
| 			case UnixFDIndex: | ||||
| 				j := v.(UnixFDIndex) | ||||
| 				if uint32(j) >= unixfds { | ||||
| 					return nil, InvalidMessageError("invalid index for unix fd") | ||||
| 				} | ||||
| 				msg.Body[i] = UnixFD(fds[j]) | ||||
| 			case []UnixFDIndex: | ||||
| 				idxArray := v.([]UnixFDIndex) | ||||
| 				fdArray := make([]UnixFD, len(idxArray)) | ||||
| 				for k, j := range idxArray { | ||||
| 					if uint32(j) >= unixfds { | ||||
| 						return nil, InvalidMessageError("invalid index for unix fd") | ||||
| 					} | ||||
| 					fdArray[k] = UnixFD(fds[j]) | ||||
| 				} | ||||
| 				msg.Body[i] = fdArray | ||||
| 			} | ||||
| 		} | ||||
| 		return msg, nil | ||||
| @@ -175,7 +193,7 @@ func (t *unixTransport) SendMessage(msg *Message) error { | ||||
| 		msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds))) | ||||
| 		oob := syscall.UnixRights(fds...) | ||||
| 		buf := new(bytes.Buffer) | ||||
| 		msg.EncodeTo(buf, binary.LittleEndian) | ||||
| 		msg.EncodeTo(buf, nativeEndian) | ||||
| 		n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| @@ -184,8 +202,8 @@ func (t *unixTransport) SendMessage(msg *Message) error { | ||||
| 			return io.ErrShortWrite | ||||
| 		} | ||||
| 	} else { | ||||
| 		if err := msg.EncodeTo(t, binary.LittleEndian); err != nil { | ||||
| 			return nil | ||||
| 		if err := msg.EncodeTo(t, nativeEndian); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
							
								
								
									
										91
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_freebsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/godbus/dbus/v5/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 | ||||
| } | ||||
							
								
								
									
										14
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_openbsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/godbus/dbus/v5/transport_unixcred_openbsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| package dbus | ||||
|  | ||||
| import "io" | ||||
|  | ||||
| func (t *unixTransport) SendNullByte() error { | ||||
| 	n, _, err := t.UnixConn.WriteMsgUnix([]byte{0}, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if n != 1 { | ||||
| 		return io.ErrShortWrite | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										11
									
								
								vendor/github.com/godbus/dbus/variant.go → vendor/github.com/godbus/dbus/v5/variant.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/godbus/dbus/variant.go → vendor/github.com/godbus/dbus/v5/variant.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -17,11 +17,16 @@ type Variant struct { | ||||
| // 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 Variant{SignatureOf(v), v} | ||||
| 	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 | ||||
| // https://developer.gnome.org/glib/stable/gvariant-text.html. If sig is not | ||||
| // empty, it is taken to be the expected signature for the variant. | ||||
| func ParseVariant(s string, sig Signature) (Variant, error) { | ||||
| 	tokens := varLex(s) | ||||
| @@ -124,7 +129,7 @@ func (v Variant) Signature() Signature { | ||||
| } | ||||
| 
 | ||||
| // String returns the string representation of the underlying value of v as | ||||
| // described at https://developer.gnome.org/glib/unstable/gvariant-text.html. | ||||
| // described at https://developer.gnome.org/glib/stable/gvariant-text.html. | ||||
| func (v Variant) String() string { | ||||
| 	s, unamb := v.format() | ||||
| 	if !unamb { | ||||
| @@ -51,7 +51,7 @@ func varLex(s string) []varToken { | ||||
| } | ||||
| 
 | ||||
| func (l *varLexer) accept(valid string) bool { | ||||
| 	if strings.IndexRune(valid, l.next()) >= 0 { | ||||
| 	if strings.ContainsRune(valid, l.next()) { | ||||
| 		return true | ||||
| 	} | ||||
| 	l.backup() | ||||
| @@ -214,17 +214,17 @@ func varLexNumber(l *varLexer) lexState { | ||||
| 			digits = "01234567" | ||||
| 		} | ||||
| 	} | ||||
| 	for strings.IndexRune(digits, l.next()) >= 0 { | ||||
| 	for strings.ContainsRune(digits, l.next()) { | ||||
| 	} | ||||
| 	l.backup() | ||||
| 	if l.accept(".") { | ||||
| 		for strings.IndexRune(digits, l.next()) >= 0 { | ||||
| 		for strings.ContainsRune(digits, l.next()) { | ||||
| 		} | ||||
| 		l.backup() | ||||
| 	} | ||||
| 	if l.accept("eE") { | ||||
| 		l.accept("+-") | ||||
| 		for strings.IndexRune("0123456789", l.next()) >= 0 { | ||||
| 		for strings.ContainsRune("0123456789", l.next()) { | ||||
| 		} | ||||
| 		l.backup() | ||||
| 	} | ||||
		Reference in New Issue
	
	Block a user
	 Akihiro Suda
					Akihiro Suda