Merge pull request #1376 from Zyqsempai/add-cgroups-v2-metrics
Cgroupv2: Added CPU, Memory metrics
This commit is contained in:
commit
5e5960f2bc
@ -19,8 +19,11 @@ limitations under the License.
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/types"
|
"github.com/containerd/containerd/api/types"
|
||||||
v1 "github.com/containerd/containerd/metrics/types/v1"
|
v1 "github.com/containerd/containerd/metrics/types/v1"
|
||||||
|
v2 "github.com/containerd/containerd/metrics/types/v2"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
@ -61,7 +64,8 @@ func (c *criService) containerMetrics(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to extract container metrics")
|
return nil, errors.Wrap(err, "failed to extract container metrics")
|
||||||
}
|
}
|
||||||
metrics := s.(*v1.Metrics)
|
switch metrics := s.(type) {
|
||||||
|
case *v1.Metrics:
|
||||||
if metrics.CPU != nil && metrics.CPU.Usage != nil {
|
if metrics.CPU != nil && metrics.CPU.Usage != nil {
|
||||||
cs.Cpu = &runtime.CpuUsage{
|
cs.Cpu = &runtime.CpuUsage{
|
||||||
Timestamp: stats.Timestamp.UnixNano(),
|
Timestamp: stats.Timestamp.UnixNano(),
|
||||||
@ -76,6 +80,24 @@ func (c *criService) containerMetrics(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &cs, nil
|
return &cs, nil
|
||||||
@ -94,3 +116,14 @@ func getWorkingSet(memory *v1.MemoryStat) uint64 {
|
|||||||
}
|
}
|
||||||
return workingSet
|
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/golang/protobuf aa810b61a9c79d51363740d207bb46cf8e620ed5 # v1.2.0
|
||||||
github.com/gogo/protobuf ba06b47c162d49f2af050fb4c75bcbc86a159d5c # v1.2.1
|
github.com/gogo/protobuf ba06b47c162d49f2af050fb4c75bcbc86a159d5c # v1.2.1
|
||||||
github.com/gogo/googleapis d31c731455cb061f42baff3bda55bad0118b126b # v1.2.0
|
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-units 519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0
|
||||||
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
||||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
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/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||||
github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f
|
github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f
|
||||||
github.com/containerd/go-runc a5c2862aed5e6358b305b0e16bfce58e0549b1cd
|
github.com/containerd/go-runc a5c2862aed5e6358b305b0e16bfce58e0549b1cd
|
||||||
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
||||||
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
|
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
|
||||||
github.com/containerd/containerd 0a1f2b40642e54ed06cd0a22cdf6025cbe70853c
|
github.com/containerd/containerd e1221e69a824ce9aaca34c5bb603feb2f921b883
|
||||||
github.com/containerd/console 8375c3424e4d7b114e8a90a4a40c8e1b40d1d4e6
|
github.com/containerd/console 8375c3424e4d7b114e8a90a4a40c8e1b40d1d4e6
|
||||||
github.com/containerd/cgroups fada802a7909d430bd17126fd6e4bbf5716f2bcd
|
github.com/containerd/cgroups 7347743e5d1e8500d9f27c8e748e689ed991d92b
|
||||||
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
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/Microsoft/go-winio 6c72808b55902eae4c5943626030429ff20f3b63 # v0.4.14
|
||||||
github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1
|
github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1
|
||||||
github.com/cpuguy83/go-md2man 7762f7e404f8416dfa1d9bb6a8c192aa9acb4d19 # v1.0.10
|
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.
|
// CreateProcess launches a new process within the container.
|
||||||
func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, convertSystemError(err, container)
|
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
|
module github.com/Microsoft/hcsshim
|
||||||
|
|
||||||
go 1.12
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5
|
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)")
|
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.
|
// RequestType are the different operations performed to settings.
|
||||||
// Used to update the settings of Endpoint/Namespace objects.
|
// Used to update the settings of Endpoint/Namespace objects.
|
||||||
type RequestType string
|
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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim/internal/hcserror"
|
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||||
"github.com/Microsoft/hcsshim/internal/interop"
|
"github.com/Microsoft/hcsshim/internal/interop"
|
||||||
@ -20,17 +21,36 @@ type Version struct {
|
|||||||
Minor int `json:"Minor"`
|
Minor int `json:"Minor"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VersionRange struct {
|
||||||
|
MinVersion Version
|
||||||
|
MaxVersion Version
|
||||||
|
}
|
||||||
|
|
||||||
|
type VersionRanges []VersionRange
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// HNSVersion1803 added ACL functionality.
|
// 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 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
|
// 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
|
// 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
|
// 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.
|
// GetGlobals returns the global properties of the HCN Service.
|
||||||
|
13
vendor/github.com/Microsoft/hcsshim/hcn/hcnloadbalancer.go
generated
vendored
13
vendor/github.com/Microsoft/hcsshim/hcn/hcnloadbalancer.go
generated
vendored
@ -13,6 +13,7 @@ type LoadBalancerPortMapping struct {
|
|||||||
Protocol uint32 `json:",omitempty"` // EX: TCP = 6, UDP = 17
|
Protocol uint32 `json:",omitempty"` // EX: TCP = 6, UDP = 17
|
||||||
InternalPort uint16 `json:",omitempty"`
|
InternalPort uint16 `json:",omitempty"`
|
||||||
ExternalPort 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"`
|
Flags LoadBalancerPortMappingFlags `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,6 +54,18 @@ var (
|
|||||||
LoadBalancerPortMappingFlagsPreserveDIP LoadBalancerPortMappingFlags = 8
|
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) {
|
func getLoadBalancer(loadBalancerGuid guid.GUID, query string) (*HostComputeLoadBalancer, error) {
|
||||||
// Open loadBalancer.
|
// Open loadBalancer.
|
||||||
var (
|
var (
|
||||||
|
33
vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go
generated
vendored
33
vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go
generated
vendored
@ -11,6 +11,9 @@ type SupportedFeatures struct {
|
|||||||
RemoteSubnet bool `json:"RemoteSubnet"`
|
RemoteSubnet bool `json:"RemoteSubnet"`
|
||||||
HostRoute bool `json:"HostRoute"`
|
HostRoute bool `json:"HostRoute"`
|
||||||
DSR bool `json:"DSR"`
|
DSR bool `json:"DSR"`
|
||||||
|
Slash32EndpointPrefixes bool `json:"Slash32EndpointPrefixes"`
|
||||||
|
AclSupportForProtocol252 bool `json:"AclSupportForProtocol252"`
|
||||||
|
SessionAffinity bool `json:"SessionAffinity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AclFeatures are the supported ACL possibilities.
|
// AclFeatures are the supported ACL possibilities.
|
||||||
@ -53,18 +56,38 @@ func GetSupportedFeatures() SupportedFeatures {
|
|||||||
features.RemoteSubnet = isFeatureSupported(globals.Version, RemoteSubnetVersion)
|
features.RemoteSubnet = isFeatureSupported(globals.Version, RemoteSubnetVersion)
|
||||||
features.HostRoute = isFeatureSupported(globals.Version, HostRouteVersion)
|
features.HostRoute = isFeatureSupported(globals.Version, HostRouteVersion)
|
||||||
features.DSR = isFeatureSupported(globals.Version, DSRVersion)
|
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
|
return features
|
||||||
}
|
}
|
||||||
|
|
||||||
func isFeatureSupported(currentVersion Version, minVersionSupported Version) bool {
|
func isFeatureSupported(currentVersion Version, versionsSupported VersionRanges) bool {
|
||||||
if currentVersion.Major < minVersionSupported.Major {
|
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
|
return false
|
||||||
}
|
}
|
||||||
if currentVersion.Major > minVersionSupported.Major {
|
if currentVersion.Major > versionRange.MaxVersion.Major {
|
||||||
return true
|
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 false
|
||||||
}
|
}
|
||||||
return true
|
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
|
handle vmcompute.HcsProcess
|
||||||
processID int
|
processID int
|
||||||
system *System
|
system *System
|
||||||
|
hasCachedStdio bool
|
||||||
|
stdioLock sync.Mutex
|
||||||
stdin io.WriteCloser
|
stdin io.WriteCloser
|
||||||
stdout io.ReadCloser
|
stdout io.ReadCloser
|
||||||
stderr 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
|
// StdioLegacy returns the stdin, stdout, and stderr pipes, respectively. Closing
|
||||||
// these pipes does not close the underlying pipes; but this function can only
|
// these pipes does not close the underlying pipes. Once returned, these pipes
|
||||||
// be called once on each Process.
|
// are the responsibility of the caller to close.
|
||||||
func (process *Process) StdioLegacy() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, err error) {
|
func (process *Process) StdioLegacy() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, err error) {
|
||||||
operation := "hcsshim::Process::StdioLegacy"
|
operation := "hcsshim::Process::StdioLegacy"
|
||||||
ctx, span := trace.StartSpan(context.Background(), operation)
|
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)
|
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)
|
processInfo, resultJSON, err := vmcompute.HcsGetProcessInfo(ctx, process.handle)
|
||||||
events := processHcsResult(ctx, resultJSON)
|
events := processHcsResult(ctx, resultJSON)
|
||||||
if err != nil {
|
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.
|
// Stdio returns the stdin, stdout, and stderr pipes, respectively.
|
||||||
// To close them, close the process handle.
|
// To close them, close the process handle.
|
||||||
func (process *Process) Stdio() (stdin io.Writer, stdout, stderr io.Reader) {
|
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
|
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)
|
return makeProcessError(process, operation, err, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process.stdioLock.Lock()
|
||||||
if process.stdin != nil {
|
if process.stdin != nil {
|
||||||
process.stdin.Close()
|
process.stdin.Close()
|
||||||
|
process.stdin = nil
|
||||||
}
|
}
|
||||||
|
process.stdioLock.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,15 +382,20 @@ func (process *Process) Close() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process.stdioLock.Lock()
|
||||||
if process.stdin != nil {
|
if process.stdin != nil {
|
||||||
process.stdin.Close()
|
process.stdin.Close()
|
||||||
|
process.stdin = nil
|
||||||
}
|
}
|
||||||
if process.stdout != nil {
|
if process.stdout != nil {
|
||||||
process.stdout.Close()
|
process.stdout.Close()
|
||||||
|
process.stdout = nil
|
||||||
}
|
}
|
||||||
if process.stderr != nil {
|
if process.stderr != nil {
|
||||||
process.stderr.Close()
|
process.stderr.Close()
|
||||||
|
process.stderr = nil
|
||||||
}
|
}
|
||||||
|
process.stdioLock.Unlock()
|
||||||
|
|
||||||
if err = process.unregisterCallback(ctx); err != nil {
|
if err = process.unregisterCallback(ctx); err != nil {
|
||||||
return makeProcessError(process, operation, 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
|
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.
|
// CreateProcess launches a new process within the computeSystem.
|
||||||
func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) (cow.Process, error) {
|
func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) (cow.Process, error) {
|
||||||
operation := "hcsshim::System::CreateProcess"
|
operation := "hcsshim::System::CreateProcess"
|
||||||
@ -534,6 +502,7 @@ func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) (
|
|||||||
process.stdin = pipes[0]
|
process.stdin = pipes[0]
|
||||||
process.stdout = pipes[1]
|
process.stdout = pipes[1]
|
||||||
process.stderr = pipes[2]
|
process.stderr = pipes[2]
|
||||||
|
process.hasCachedStdio = true
|
||||||
|
|
||||||
if err = process.registerCallback(ctx); err != nil {
|
if err = process.registerCallback(ctx); err != nil {
|
||||||
return nil, makeSystemError(computeSystem, operation, "", err, nil)
|
return nil, makeSystemError(computeSystem, operation, "", err, nil)
|
||||||
|
2
vendor/github.com/Microsoft/hcsshim/internal/vmcompute/vmcompute.go
generated
vendored
2
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 != "" {
|
if result != "" {
|
||||||
span.AddAttributes(trace.StringAttribute("result", result))
|
span.AddAttributes(trace.StringAttribute("result", result))
|
||||||
}
|
}
|
||||||
|
if hr != errVmcomputeOperationPending {
|
||||||
oc.SetSpanStatus(span, hr)
|
oc.SetSpanStatus(span, hr)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
span.AddAttributes(trace.StringAttribute("options", options))
|
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).
|
// 2019 (ltsc2019), and Windows 10 (October 2018 Update).
|
||||||
RS5 = 17763
|
RS5 = 17763
|
||||||
|
|
||||||
// V19H1 (version 1903) corresponds to Windows Sever 1903 (semi-annual
|
// V19H1 (version 1903) corresponds to Windows Server 1903 (semi-annual
|
||||||
// channel).
|
// channel).
|
||||||
V19H1 = 18362
|
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 (
|
require (
|
||||||
github.com/cilium/ebpf v0.0.0-20191113100448-d9fb101ca1fb
|
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/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/gogo/protobuf v1.2.1
|
||||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700
|
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700
|
||||||
github.com/pkg/errors v0.8.1
|
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"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
systemdDbus "github.com/coreos/go-systemd/dbus"
|
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
|
||||||
"github.com/godbus/dbus"
|
"github.com/godbus/dbus/v5"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
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
|
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 {
|
type CPU struct {
|
||||||
Weight *uint64
|
Weight *uint64
|
||||||
Max *uint64
|
Max CPUMax
|
||||||
Cpus string
|
Cpus string
|
||||||
Mems 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) {
|
func (r *CPU) Values() (o []Value) {
|
||||||
if r.Weight != nil {
|
if r.Weight != nil {
|
||||||
o = append(o, Value{
|
o = append(o, Value{
|
||||||
@ -30,10 +61,10 @@ func (r *CPU) Values() (o []Value) {
|
|||||||
value: *r.Weight,
|
value: *r.Weight,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if r.Max != nil {
|
if r.Max != "" {
|
||||||
o = append(o, Value{
|
o = append(o, Value{
|
||||||
filename: "cpu.max",
|
filename: "cpu.max",
|
||||||
value: *r.Max,
|
value: r.Max,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if r.Cpus != "" {
|
if r.Cpus != "" {
|
||||||
|
210
vendor/github.com/containerd/cgroups/v2/manager.go
generated
vendored
210
vendor/github.com/containerd/cgroups/v2/manager.go
generated
vendored
@ -19,25 +19,37 @@ package v2
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/containerd/cgroups/v2/stats"
|
"github.com/containerd/cgroups/v2/stats"
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
subtreeControl = "cgroup.subtree_control"
|
subtreeControl = "cgroup.subtree_control"
|
||||||
controllersFile = "cgroup.controllers"
|
controllersFile = "cgroup.controllers"
|
||||||
|
defaultCgroup2Path = "/sys/fs/cgroup"
|
||||||
|
defaultSlice = "system.slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
canDelegate bool
|
||||||
|
once sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
type cgValuer interface {
|
type cgValuer interface {
|
||||||
@ -66,22 +78,45 @@ type Resources struct {
|
|||||||
// Values returns the raw filenames and values that
|
// Values returns the raw filenames and values that
|
||||||
// can be written to the unified hierarchy
|
// can be written to the unified hierarchy
|
||||||
func (r *Resources) Values() (o []Value) {
|
func (r *Resources) Values() (o []Value) {
|
||||||
values := []cgValuer{
|
if r.CPU != nil {
|
||||||
r.CPU,
|
o = append(o, r.CPU.Values()...)
|
||||||
r.Memory,
|
|
||||||
r.Pids,
|
|
||||||
r.IO,
|
|
||||||
r.RDMA,
|
|
||||||
}
|
}
|
||||||
for _, v := range values {
|
if r.Memory != nil {
|
||||||
if v == nil {
|
o = append(o, r.Memory.Values()...)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
o = append(o, v.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
|
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
|
// Value of a cgroup setting
|
||||||
type Value struct {
|
type Value struct {
|
||||||
filename string
|
filename string
|
||||||
@ -102,6 +137,8 @@ func (c *Value) write(path string, perm os.FileMode) error {
|
|||||||
data = t
|
data = t
|
||||||
case string:
|
case string:
|
||||||
data = []byte(t)
|
data = []byte(t)
|
||||||
|
case CPUMax:
|
||||||
|
data = []byte(t)
|
||||||
default:
|
default:
|
||||||
return ErrInvalidFormat
|
return ErrInvalidFormat
|
||||||
}
|
}
|
||||||
@ -129,15 +166,20 @@ func NewManager(mountpoint string, group string, resources *Resources) (*Manager
|
|||||||
if err := os.MkdirAll(path, defaultDirPerm); err != nil {
|
if err := os.MkdirAll(path, defaultDirPerm); err != nil {
|
||||||
return nil, err
|
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
|
// clean up cgroup dir on failure
|
||||||
os.Remove(path)
|
os.Remove(path)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Manager{
|
if err := setResources(path, resources); err != nil {
|
||||||
unifiedMountpoint: mountpoint,
|
os.Remove(path)
|
||||||
path: path,
|
return nil, err
|
||||||
}, nil
|
}
|
||||||
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadManager(mountpoint string, group string) (*Manager, error) {
|
func LoadManager(mountpoint string, group string) (*Manager, error) {
|
||||||
@ -308,14 +350,17 @@ func (c *Manager) Stat() (*stats.Metrics, error) {
|
|||||||
}
|
}
|
||||||
out := make(map[string]interface{})
|
out := make(map[string]interface{})
|
||||||
for _, controller := range controllers {
|
for _, controller := range controllers {
|
||||||
|
switch controller {
|
||||||
|
case "cpu", "memory":
|
||||||
filename := fmt.Sprintf("%s.stat", controller)
|
filename := fmt.Sprintf("%s.stat", controller)
|
||||||
if err := readStatsFile(c.path, filename, out); err != nil {
|
if err := readKVStatsFile(c.path, filename, out); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for _, name := range singleValueFiles {
|
for _, name := range singleValueFiles {
|
||||||
if err := readSingleFile(c.path, name, out); err != nil {
|
if err := readSingleFile(c.path, name, out); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
@ -376,6 +421,8 @@ func (c *Manager) Stat() (*stats.Metrics, error) {
|
|||||||
SwapLimit: getStatFileContentUint64(filepath.Join(c.path, "memory.swap.max")),
|
SwapLimit: getStatFileContentUint64(filepath.Join(c.path, "memory.swap.max")),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metrics.Io = &stats.IOStat{Usage: readIoStats(c.path)}
|
||||||
|
|
||||||
metrics.Rdma = &stats.RdmaStat{
|
metrics.Rdma = &stats.RdmaStat{
|
||||||
Current: rdmaStats(filepath.Join(c.path, "rdma.current")),
|
Current: rdmaStats(filepath.Join(c.path, "rdma.current")),
|
||||||
Limit: rdmaStats(filepath.Join(c.path, "rdma.max")),
|
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
|
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))
|
f, err := os.Open(filepath.Join(path, file))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -447,7 +494,7 @@ func readStatsFile(path string, file string, out map[string]interface{}) error {
|
|||||||
}
|
}
|
||||||
name, value, err := parseKV(s.Text())
|
name, value, err := parseKV(s.Text())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrapf(err, "error while parsing %s (line=%q)", filepath.Join(path, file), s.Text())
|
||||||
}
|
}
|
||||||
out[name] = value
|
out[name] = value
|
||||||
}
|
}
|
||||||
@ -516,7 +563,7 @@ func (c *Manager) waitForEvents(ec chan<- Event, errCh chan<- error) {
|
|||||||
}
|
}
|
||||||
var out map[string]interface{}
|
var out map[string]interface{}
|
||||||
if bytesRead >= syscall.SizeofInotifyEvent {
|
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{
|
e := Event{
|
||||||
High: out["high"].(uint64),
|
High: out["high"].(uint64),
|
||||||
Low: out["low"].(uint64),
|
Low: out["low"].(uint64),
|
||||||
@ -550,3 +597,126 @@ func setDevices(path string, devices []specs.LinuxDeviceCgroup) error {
|
|||||||
}
|
}
|
||||||
return nil
|
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"`
|
CPU *CPUStat `protobuf:"bytes,2,opt,name=cpu,proto3" json:"cpu,omitempty"`
|
||||||
Memory *MemoryStat `protobuf:"bytes,4,opt,name=memory,proto3" json:"memory,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"`
|
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_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
XXX_sizecache int32 `json:"-"`
|
XXX_sizecache int32 `json:"-"`
|
||||||
@ -304,6 +305,89 @@ func (m *RdmaEntry) XXX_DiscardUnknown() {
|
|||||||
|
|
||||||
var xxx_messageInfo_RdmaEntry proto.InternalMessageInfo
|
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() {
|
func init() {
|
||||||
proto.RegisterType((*Metrics)(nil), "io.containerd.cgroups.v2.Metrics")
|
proto.RegisterType((*Metrics)(nil), "io.containerd.cgroups.v2.Metrics")
|
||||||
proto.RegisterType((*PidsStat)(nil), "io.containerd.cgroups.v2.PidsStat")
|
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((*MemoryStat)(nil), "io.containerd.cgroups.v2.MemoryStat")
|
||||||
proto.RegisterType((*RdmaStat)(nil), "io.containerd.cgroups.v2.RdmaStat")
|
proto.RegisterType((*RdmaStat)(nil), "io.containerd.cgroups.v2.RdmaStat")
|
||||||
proto.RegisterType((*RdmaEntry)(nil), "io.containerd.cgroups.v2.RdmaEntry")
|
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() {
|
func init() {
|
||||||
@ -318,68 +404,74 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_2fc6005842049e6b = []byte{
|
var fileDescriptor_2fc6005842049e6b = []byte{
|
||||||
// 965 bytes of a gzipped FileDescriptorProto
|
// 1064 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0x4d, 0x6f, 0x1c, 0x45,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x56, 0x4f, 0x6f, 0x1c, 0xc5,
|
||||||
0x10, 0xcd, 0xe2, 0x8d, 0xbd, 0x5b, 0x6b, 0xc7, 0x4e, 0xc7, 0x31, 0x1d, 0x07, 0xaf, 0xed, 0x35,
|
0x13, 0xcd, 0xda, 0x9b, 0xfd, 0xd3, 0x6b, 0x27, 0x4e, 0xc7, 0xf1, 0xaf, 0xe3, 0xfc, 0xbc, 0xb6,
|
||||||
0xa0, 0x20, 0xc1, 0xae, 0x64, 0x3e, 0x24, 0x50, 0x38, 0x38, 0x86, 0x88, 0x03, 0x06, 0x6b, 0x12,
|
0xd7, 0x80, 0x82, 0x04, 0xbb, 0xc8, 0xfc, 0x13, 0x28, 0x1c, 0x1c, 0x43, 0x04, 0x12, 0x26, 0xd6,
|
||||||
0x8b, 0xe3, 0xa8, 0x77, 0xa6, 0x3d, 0x33, 0xf1, 0x7c, 0xa9, 0xbb, 0xc7, 0x96, 0x39, 0x71, 0xe0,
|
0x26, 0x16, 0xc7, 0x51, 0xef, 0x4c, 0x7b, 0xb7, 0xed, 0x99, 0xe9, 0x51, 0x77, 0xaf, 0xad, 0xe5,
|
||||||
0xce, 0xdf, 0xca, 0x0d, 0x8e, 0x9c, 0x10, 0xf1, 0x7f, 0xe0, 0x8e, 0xaa, 0x6a, 0x66, 0x67, 0x38,
|
0xc4, 0x81, 0x2b, 0xe2, 0x63, 0xf0, 0x55, 0x72, 0x83, 0x23, 0x27, 0x44, 0xfc, 0x49, 0x50, 0x55,
|
||||||
0x18, 0xb8, 0x75, 0xbd, 0xf7, 0xaa, 0xba, 0xea, 0xed, 0x74, 0x2d, 0x7c, 0x12, 0x25, 0x2e, 0xae,
|
0xf5, 0x78, 0x86, 0x83, 0x03, 0xb7, 0xae, 0xf7, 0x5e, 0xd5, 0x54, 0xbd, 0xd9, 0xae, 0x59, 0xf6,
|
||||||
0xe6, 0xd3, 0xa0, 0xc8, 0x66, 0x41, 0x91, 0x3b, 0x95, 0xe4, 0xda, 0x84, 0xb3, 0x20, 0x32, 0x45,
|
0xd1, 0x54, 0xfb, 0xd9, 0x7c, 0x32, 0x8c, 0x4d, 0x36, 0x8a, 0x4d, 0xee, 0xa5, 0xce, 0x95, 0x4d,
|
||||||
0x55, 0xda, 0xd9, 0xe5, 0xe1, 0xcc, 0x3a, 0xe5, 0xec, 0x2c, 0xd3, 0xce, 0x24, 0x81, 0x9d, 0x96,
|
0x46, 0xf1, 0xd4, 0x9a, 0x79, 0xe1, 0x46, 0x17, 0xfb, 0x23, 0xe7, 0xa5, 0x77, 0xa3, 0x4c, 0x79,
|
||||||
0xa6, 0x70, 0x85, 0x90, 0x49, 0x31, 0x6d, 0xd5, 0xd3, 0x5a, 0x3d, 0xbd, 0x3c, 0xdc, 0xde, 0x8c,
|
0xab, 0x63, 0x37, 0x2c, 0xac, 0xf1, 0x86, 0x0b, 0x6d, 0x86, 0x95, 0x7a, 0x18, 0xd4, 0xc3, 0x8b,
|
||||||
0x8a, 0xa8, 0x20, 0xd1, 0x0c, 0x4f, 0xac, 0x9f, 0xfc, 0xd5, 0x83, 0x95, 0x13, 0xae, 0x20, 0x3e,
|
0xfd, 0xcd, 0xf5, 0xa9, 0x99, 0x1a, 0x14, 0x8d, 0xe0, 0x44, 0xfa, 0xc1, 0xaf, 0x4b, 0xac, 0x7d,
|
||||||
0x83, 0x7e, 0x99, 0x84, 0x56, 0xf6, 0xf6, 0x7a, 0x4f, 0x46, 0x87, 0x93, 0xe9, 0x6d, 0xa5, 0xa6,
|
0x44, 0x15, 0xf8, 0x27, 0xac, 0x59, 0xe8, 0xc4, 0x89, 0xc6, 0x4e, 0xe3, 0x71, 0x6f, 0x7f, 0x30,
|
||||||
0xa7, 0x49, 0x68, 0x5f, 0x38, 0xe5, 0x3c, 0xd2, 0x8b, 0xa7, 0xb0, 0x14, 0x94, 0x95, 0x7c, 0x8b,
|
0xbc, 0xa9, 0xd4, 0xf0, 0x58, 0x27, 0xee, 0x85, 0x97, 0x7e, 0x8c, 0x7a, 0xfe, 0x84, 0x2d, 0xc7,
|
||||||
0xd2, 0xf6, 0x6f, 0x4f, 0x3b, 0x3e, 0x3d, 0xc3, 0xac, 0x67, 0x2b, 0x37, 0x7f, 0xec, 0x2e, 0x1d,
|
0xc5, 0x5c, 0x2c, 0x61, 0xda, 0xee, 0xcd, 0x69, 0x87, 0xc7, 0x27, 0x90, 0xf5, 0xb4, 0x7d, 0xf5,
|
||||||
0x9f, 0x9e, 0x79, 0x98, 0x26, 0x9e, 0xc2, 0x72, 0xa6, 0xb3, 0xc2, 0x5c, 0xcb, 0x3e, 0x15, 0x78,
|
0xe7, 0xf6, 0xf2, 0xe1, 0xf1, 0xc9, 0x18, 0xd2, 0xf8, 0x13, 0xd6, 0xca, 0x54, 0x66, 0xec, 0x42,
|
||||||
0xf7, 0xf6, 0x02, 0x27, 0xa4, 0xa3, 0x9b, 0xeb, 0x1c, 0xec, 0xd9, 0x84, 0x99, 0x92, 0x77, 0xff,
|
0x34, 0xb1, 0xc0, 0x5b, 0x37, 0x17, 0x38, 0x42, 0x1d, 0x3e, 0x39, 0xe4, 0x40, 0xcf, 0x36, 0xc9,
|
||||||
0xab, 0x67, 0x2f, 0xcc, 0x14, 0xf7, 0x8c, 0xfa, 0xc9, 0x17, 0x30, 0x68, 0xa6, 0x10, 0x12, 0x56,
|
0xa4, 0xb8, 0xfd, 0x6f, 0x3d, 0x8f, 0x93, 0x4c, 0x52, 0xcf, 0xa0, 0xe7, 0x1f, 0xb0, 0x25, 0x6d,
|
||||||
0x82, 0xca, 0x18, 0x9d, 0x3b, 0x1a, 0xbd, 0xef, 0x35, 0xa1, 0xd8, 0x84, 0xbb, 0x69, 0x92, 0x25,
|
0x44, 0x0b, 0xb3, 0x76, 0x6e, 0xce, 0xfa, 0xe6, 0x39, 0xe6, 0x2c, 0x69, 0x33, 0xf8, 0x9c, 0x75,
|
||||||
0x8e, 0x66, 0xeb, 0x7b, 0x1c, 0x4c, 0x7e, 0xed, 0xc1, 0x4a, 0x3d, 0x8b, 0xd8, 0x01, 0xa8, 0xac,
|
0xca, 0xb9, 0xb9, 0x60, 0xed, 0x78, 0x6e, 0xad, 0xca, 0x3d, 0x9a, 0xd5, 0x1c, 0x97, 0x21, 0x5f,
|
||||||
0x8a, 0xb4, 0x5f, 0x59, 0x1d, 0xd4, 0xe9, 0x43, 0x42, 0xce, 0xac, 0x0e, 0xc4, 0x63, 0x18, 0x56,
|
0x67, 0xb7, 0x53, 0x9d, 0x69, 0x8f, 0x6e, 0x34, 0xc7, 0x14, 0x0c, 0x7e, 0x6b, 0xb0, 0x76, 0x98,
|
||||||
0x56, 0x1b, 0x66, 0xb9, 0xc8, 0x00, 0x01, 0x22, 0x77, 0x61, 0x64, 0xaf, 0xad, 0xd3, 0x19, 0xd3,
|
0x9e, 0x6f, 0x31, 0x36, 0x77, 0x72, 0xaa, 0xa2, 0xb9, 0x53, 0x71, 0x48, 0xef, 0x22, 0x72, 0xe2,
|
||||||
0x4b, 0x44, 0x03, 0x43, 0x24, 0xd8, 0x01, 0xc8, 0x8d, 0x5f, 0x6a, 0x93, 0x14, 0xa1, 0x25, 0x7b,
|
0x54, 0xcc, 0x1f, 0xb1, 0xee, 0xdc, 0x29, 0x4b, 0x2c, 0x15, 0xe9, 0x00, 0x80, 0xe4, 0x36, 0xeb,
|
||||||
0xfa, 0xde, 0x30, 0x37, 0xa7, 0x0c, 0x88, 0x7d, 0x58, 0xcd, 0x8d, 0xef, 0x62, 0x53, 0x38, 0x97,
|
0xb9, 0x85, 0xf3, 0x2a, 0x23, 0x7a, 0x19, 0x69, 0x46, 0x10, 0x0a, 0xb6, 0x18, 0xcb, 0x6d, 0x54,
|
||||||
0xea, 0x90, 0x3c, 0xe8, 0x7b, 0xa3, 0xdc, 0xbc, 0x6c, 0x20, 0xf1, 0x1e, 0xdc, 0x5b, 0xf0, 0x7c,
|
0x28, 0xab, 0x4d, 0xe2, 0xd0, 0xd0, 0xe6, 0xb8, 0x9b, 0xdb, 0x63, 0x02, 0xf8, 0x2e, 0x5b, 0xc9,
|
||||||
0xcb, 0x32, 0x89, 0xd6, 0x16, 0x28, 0x5e, 0x34, 0xf9, 0x65, 0x08, 0xd0, 0x9a, 0x2b, 0x04, 0xf4,
|
0x6d, 0xe4, 0x67, 0xd6, 0x78, 0x9f, 0xaa, 0x04, 0x5d, 0x6b, 0x8e, 0x7b, 0xb9, 0x7d, 0x59, 0x42,
|
||||||
0x55, 0x5e, 0xe4, 0xf5, 0x38, 0x74, 0x46, 0xec, 0x3c, 0x49, 0x75, 0x3d, 0x04, 0x9d, 0xb1, 0x81,
|
0xfc, 0x6d, 0x76, 0xe7, 0x9a, 0xa7, 0xa7, 0xb4, 0x50, 0xb4, 0x7a, 0x8d, 0xc2, 0x83, 0x06, 0xbf,
|
||||||
0x0b, 0x6d, 0x72, 0x9d, 0xfa, 0xd6, 0xa9, 0xe0, 0xa2, 0x9e, 0x60, 0xc4, 0xd8, 0x0b, 0x84, 0x30,
|
0x74, 0x19, 0xab, 0x5e, 0x07, 0xe7, 0xac, 0x29, 0x73, 0x93, 0x87, 0x71, 0xf0, 0x0c, 0xd8, 0xa9,
|
||||||
0xcd, 0xa6, 0x6a, 0x5e, 0x37, 0x4f, 0x67, 0xc2, 0x8a, 0xe0, 0xa2, 0xee, 0x97, 0xce, 0xe8, 0xb4,
|
0x4e, 0x55, 0x18, 0x02, 0xcf, 0xd0, 0xc0, 0xb9, 0xb2, 0xb9, 0x4a, 0x23, 0xe7, 0x65, 0x7c, 0x1e,
|
||||||
0x8d, 0x33, 0x9d, 0xd5, 0xfd, 0x71, 0x80, 0x0e, 0xe1, 0x45, 0x7e, 0xa6, 0xca, 0x52, 0x87, 0x72,
|
0x26, 0xe8, 0x11, 0xf6, 0x02, 0x20, 0x48, 0x73, 0xa9, 0x9c, 0x84, 0xe6, 0xf1, 0x8c, 0x98, 0x89,
|
||||||
0x85, 0x1d, 0x42, 0xe8, 0x84, 0x10, 0x74, 0x88, 0x04, 0x61, 0x62, 0xdc, 0xb5, 0x1c, 0xb0, 0x43,
|
0xcf, 0x43, 0xbf, 0x78, 0x06, 0xa7, 0xdd, 0x2c, 0x53, 0x59, 0xe8, 0x8f, 0x02, 0x70, 0x08, 0x1e,
|
||||||
0x88, 0x7c, 0x85, 0x00, 0x8e, 0x4f, 0xf4, 0x95, 0x49, 0x9c, 0x9e, 0x63, 0x8b, 0x43, 0x1e, 0x1f,
|
0x14, 0x65, 0xb2, 0x28, 0x54, 0x22, 0xda, 0xe4, 0x10, 0x40, 0x47, 0x88, 0x80, 0x43, 0x28, 0x48,
|
||||||
0xd1, 0x1f, 0x1a, 0x50, 0x3c, 0x82, 0x01, 0xce, 0xe8, 0xbb, 0xb8, 0x94, 0xc0, 0x5f, 0x00, 0xc6,
|
0xb4, 0xf5, 0x0b, 0xd1, 0x21, 0x87, 0x00, 0xf9, 0x12, 0x00, 0x18, 0x1f, 0xe9, 0x4b, 0xab, 0xbd,
|
||||||
0x2f, 0xe3, 0x52, 0x1c, 0xc0, 0x5a, 0x92, 0xab, 0xc0, 0x25, 0x97, 0xda, 0x27, 0x4f, 0x46, 0xc4,
|
0x9a, 0x40, 0x8b, 0x5d, 0x1a, 0x1f, 0xd0, 0xef, 0x4b, 0x90, 0x3f, 0x64, 0x1d, 0x98, 0x31, 0xf2,
|
||||||
0xaf, 0x36, 0xe0, 0x11, 0x7a, 0xb3, 0x0b, 0xa3, 0xae, 0x64, 0x95, 0xdb, 0xec, 0x08, 0xba, 0x55,
|
0xb3, 0x42, 0x30, 0xfa, 0x05, 0x40, 0xfc, 0x72, 0x56, 0xf0, 0x3d, 0xb6, 0xaa, 0x73, 0x19, 0x7b,
|
||||||
0xc8, 0xc5, 0xb5, 0x7f, 0x56, 0x79, 0x8e, 0x6e, 0xb6, 0x55, 0x48, 0x72, 0xaf, 0x5b, 0x85, 0x04,
|
0x7d, 0xa1, 0x22, 0xf4, 0xa4, 0x87, 0xfc, 0x4a, 0x09, 0x1e, 0x80, 0x37, 0xdb, 0xac, 0x57, 0x97,
|
||||||
0x7b, 0x30, 0xaa, 0x72, 0x7d, 0x99, 0x04, 0x4e, 0xcd, 0x53, 0x2d, 0xd7, 0xd9, 0xed, 0x0e, 0x24,
|
0xac, 0x50, 0x9b, 0x35, 0x41, 0xbd, 0x0a, 0xba, 0xb8, 0xfa, 0xcf, 0x2a, 0xcf, 0xc0, 0xcd, 0xaa,
|
||||||
0x3e, 0x80, 0x0d, 0x74, 0xd8, 0x37, 0x3a, 0x48, 0x55, 0x92, 0x91, 0x6c, 0x83, 0x64, 0xeb, 0x88,
|
0x0a, 0x4a, 0xee, 0xd4, 0xab, 0xa0, 0x60, 0x87, 0xf5, 0xe6, 0xb9, 0xba, 0xd0, 0xb1, 0x97, 0x93,
|
||||||
0x7b, 0x2d, 0x2c, 0x3e, 0x02, 0x41, 0xd2, 0x2a, 0xef, 0x8a, 0xef, 0x93, 0xf8, 0x3e, 0x32, 0x67,
|
0x54, 0x89, 0xbb, 0xe4, 0x76, 0x0d, 0xe2, 0xef, 0xb2, 0x35, 0x70, 0x38, 0xb2, 0x2a, 0x4e, 0xa5,
|
||||||
0x5d, 0x02, 0xdf, 0x48, 0x19, 0x9d, 0xab, 0x2a, 0x75, 0x52, 0xb0, 0x43, 0x75, 0x28, 0xc6, 0x00,
|
0xce, 0x50, 0xb6, 0x86, 0xb2, 0xbb, 0x80, 0x8f, 0x2b, 0x98, 0xbf, 0xcf, 0x38, 0x4a, 0xe7, 0x79,
|
||||||
0x65, 0x94, 0xa9, 0x57, 0x4c, 0x3e, 0xe0, 0xae, 0x5b, 0x04, 0x2f, 0xba, 0x2a, 0xcc, 0x45, 0x92,
|
0x5d, 0x7c, 0x0f, 0xc5, 0xf7, 0x80, 0x39, 0xa9, 0x13, 0x70, 0x47, 0x8a, 0xe9, 0xa9, 0x9c, 0xa7,
|
||||||
0x47, 0x56, 0x3b, 0xdf, 0x68, 0xd6, 0x6d, 0xf2, 0x45, 0x2d, 0xe3, 0x31, 0x21, 0x66, 0xf0, 0xa0,
|
0x5e, 0x70, 0x72, 0x28, 0x84, 0xbc, 0xcf, 0x58, 0x31, 0xcd, 0xe4, 0x19, 0x91, 0xf7, 0xa9, 0xeb,
|
||||||
0x23, 0xa7, 0xe9, 0x95, 0xd3, 0xf2, 0x21, 0xe9, 0x3b, 0x95, 0x8e, 0x6a, 0x46, 0x7c, 0x0a, 0x5b,
|
0x0a, 0x81, 0x07, 0x5d, 0x1a, 0x7b, 0xae, 0xf3, 0xa9, 0x53, 0x3e, 0xb2, 0x8a, 0x74, 0xeb, 0xf4,
|
||||||
0x9d, 0x84, 0xbc, 0x08, 0x75, 0xdd, 0xb7, 0xdc, 0xa2, 0x9c, 0x87, 0x2d, 0xfb, 0x5d, 0x4b, 0x8a,
|
0xa0, 0x8a, 0x19, 0x13, 0xc1, 0x47, 0xec, 0x7e, 0x4d, 0x8e, 0xd3, 0x4b, 0xaf, 0xc4, 0x03, 0xd4,
|
||||||
0x6d, 0x18, 0x94, 0x91, 0xd1, 0xe7, 0x49, 0x9a, 0xca, 0xb7, 0xf9, 0x61, 0x36, 0xb1, 0xd8, 0x82,
|
0xd7, 0x2a, 0x1d, 0x04, 0x86, 0x7f, 0xcc, 0x36, 0x6a, 0x09, 0xb9, 0x49, 0x54, 0xe8, 0x5b, 0x6c,
|
||||||
0xe5, 0x32, 0xb2, 0x81, 0xca, 0xa5, 0x24, 0xa6, 0x8e, 0xd8, 0x04, 0xeb, 0xb4, 0x4a, 0xe5, 0xa3,
|
0x60, 0xce, 0x83, 0x8a, 0xfd, 0xae, 0x22, 0xf9, 0x26, 0xeb, 0x14, 0x53, 0xab, 0x4e, 0x75, 0x9a,
|
||||||
0xc6, 0x04, 0x0a, 0xd9, 0x84, 0x45, 0xb3, 0xdb, 0x8d, 0x09, 0x0d, 0x22, 0x26, 0xb0, 0x5a, 0x46,
|
0x8a, 0xff, 0xd1, 0xc5, 0x2c, 0x63, 0xbe, 0xc1, 0x5a, 0xc5, 0xd4, 0xc5, 0x32, 0x17, 0x02, 0x99,
|
||||||
0xa1, 0x5e, 0x28, 0x1e, 0xf3, 0xef, 0xdf, 0xc5, 0xb8, 0x46, 0xaa, 0x7e, 0xbc, 0x3e, 0x37, 0x5a,
|
0x10, 0x91, 0x09, 0xce, 0x2b, 0x99, 0x8a, 0x87, 0xa5, 0x09, 0x18, 0x92, 0x09, 0xd7, 0xcd, 0x6e,
|
||||||
0xcb, 0x77, 0x9a, 0x1a, 0x0d, 0x82, 0x3f, 0x7f, 0x1b, 0x85, 0x72, 0x87, 0x7f, 0xfe, 0x0e, 0x24,
|
0x96, 0x26, 0x94, 0x08, 0x1f, 0xb0, 0x95, 0x62, 0x9a, 0xa8, 0x6b, 0xc5, 0x23, 0x7a, 0xff, 0x75,
|
||||||
0xde, 0x87, 0x75, 0x17, 0x97, 0x3e, 0x19, 0xe9, 0xab, 0x34, 0x2d, 0x02, 0x39, 0x6e, 0x9e, 0x7b,
|
0x8c, 0x6a, 0xa4, 0xf2, 0x87, 0xc5, 0xa9, 0x55, 0x4a, 0xfc, 0xbf, 0xac, 0x51, 0x22, 0xf0, 0xfa,
|
||||||
0xf9, 0x1c, 0xd1, 0x23, 0x04, 0xc5, 0x87, 0x20, 0x50, 0x17, 0x14, 0x69, 0xaa, 0x4a, 0xab, 0x6b,
|
0xab, 0x28, 0x11, 0x5b, 0xf4, 0xfa, 0x6b, 0x10, 0x7f, 0x87, 0xdd, 0xf5, 0xb3, 0x22, 0x42, 0x23,
|
||||||
0xe9, 0x2e, 0x49, 0x37, 0x5c, 0x5c, 0x1e, 0xd7, 0x04, 0xab, 0x37, 0xe1, 0x2e, 0x2d, 0x34, 0xb9,
|
0x23, 0x99, 0xa6, 0x26, 0x16, 0xfd, 0xf2, 0xba, 0x17, 0xcf, 0x00, 0x3d, 0x00, 0x90, 0xbf, 0xc7,
|
||||||
0xc7, 0x4f, 0x93, 0x02, 0xfc, 0x5a, 0x79, 0xf1, 0xf1, 0x82, 0xdc, 0xe7, 0x76, 0x09, 0xfa, 0x16,
|
0x38, 0xe8, 0x62, 0x93, 0xa6, 0xb2, 0x70, 0x2a, 0x48, 0xb7, 0x51, 0xba, 0xe6, 0x67, 0xc5, 0x61,
|
||||||
0x11, 0x7c, 0x9a, 0xf6, 0x4a, 0x95, 0x3e, 0xe7, 0x4e, 0xf8, 0x69, 0x22, 0x72, 0x46, 0xf9, 0x0d,
|
0x20, 0x48, 0xbd, 0xce, 0x6e, 0xe3, 0x42, 0x13, 0x3b, 0x74, 0x35, 0x31, 0x80, 0x5f, 0x2b, 0x2d,
|
||||||
0xcd, 0xe9, 0x07, 0x2d, 0x4d, 0xd9, 0x93, 0x9f, 0x7b, 0x30, 0x68, 0x56, 0xb6, 0xf8, 0xb2, 0xbb,
|
0x3e, 0x5a, 0x90, 0xbb, 0xd4, 0x2e, 0x42, 0xdf, 0x02, 0x02, 0x57, 0xd3, 0x5d, 0xca, 0x22, 0xa2,
|
||||||
0xa0, 0x97, 0x9e, 0x8c, 0x0e, 0x0f, 0xfe, 0x7d, 0xcf, 0x7f, 0x9d, 0x3b, 0x73, 0xdd, 0x6e, 0xf1,
|
0xdc, 0x01, 0x5d, 0x4d, 0x40, 0x4e, 0x30, 0xbf, 0xa4, 0x29, 0x7d, 0xaf, 0xa2, 0x31, 0x7b, 0xf0,
|
||||||
0xcf, 0xdb, 0x2d, 0xfe, 0xbf, 0x93, 0xeb, 0x55, 0xaf, 0x61, 0xb8, 0xc0, 0xf0, 0xb3, 0x08, 0xf1,
|
0x53, 0x83, 0x75, 0xca, 0x25, 0xcf, 0xbf, 0xa8, 0x2f, 0xe8, 0xe5, 0xc7, 0xbd, 0xfd, 0xbd, 0x37,
|
||||||
0xad, 0x69, 0x5a, 0x8c, 0x43, 0xaf, 0x8e, 0xd0, 0x8a, 0x38, 0x50, 0x7e, 0xac, 0xf2, 0x30, 0xd5,
|
0x7f, 0x19, 0xbe, 0xca, 0xbd, 0x5d, 0x54, 0x5b, 0xfc, 0xb3, 0x6a, 0x8b, 0xff, 0xe7, 0xe4, 0xb0,
|
||||||
0x96, 0x36, 0xe4, 0x9a, 0x07, 0x71, 0xa0, 0xbe, 0x61, 0xa4, 0x11, 0x14, 0xf3, 0x57, 0x3a, 0x70,
|
0xea, 0x15, 0xeb, 0x5e, 0x63, 0xf0, 0xb3, 0x48, 0xe0, 0xae, 0x29, 0x5c, 0x8c, 0xdd, 0x71, 0x88,
|
||||||
0x96, 0xd6, 0x24, 0x0b, 0xbe, 0x67, 0xe4, 0x99, 0x7c, 0xfd, 0x66, 0x7c, 0xe7, 0xf7, 0x37, 0xe3,
|
0xc0, 0x8a, 0x59, 0x2c, 0xa3, 0x99, 0xcc, 0x93, 0x54, 0x39, 0xdc, 0x90, 0xab, 0x63, 0x36, 0x8b,
|
||||||
0x3b, 0x3f, 0xdd, 0x8c, 0x7b, 0xaf, 0x6f, 0xc6, 0xbd, 0xdf, 0x6e, 0xc6, 0xbd, 0x3f, 0x6f, 0xc6,
|
0xe5, 0xd7, 0x84, 0x94, 0x02, 0x33, 0x39, 0x53, 0xb1, 0x77, 0xb8, 0x26, 0x49, 0xf0, 0x9c, 0x90,
|
||||||
0xbd, 0xf9, 0x32, 0xfd, 0x4d, 0x7f, 0xfc, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2e, 0xcc, 0xc8,
|
0xc1, 0x01, 0x6b, 0xd1, 0xb7, 0x89, 0x7f, 0x5a, 0x9a, 0x4d, 0x83, 0xee, 0xbe, 0xe9, 0x63, 0x16,
|
||||||
0x5a, 0x0e, 0x08, 0x00, 0x00,
|
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) {
|
func (m *Metrics) Marshal() (dAtA []byte, err error) {
|
||||||
@ -437,6 +529,16 @@ func (m *Metrics) MarshalTo(dAtA []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
i += n4
|
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 {
|
if m.XXX_unrecognized != nil {
|
||||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||||
}
|
}
|
||||||
@ -843,6 +945,90 @@ func (m *RdmaEntry) MarshalTo(dAtA []byte) (int, error) {
|
|||||||
return i, nil
|
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 {
|
func encodeVarintMetrics(dAtA []byte, offset int, v uint64) int {
|
||||||
for v >= 1<<7 {
|
for v >= 1<<7 {
|
||||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||||
@ -874,6 +1060,10 @@ func (m *Metrics) Size() (n int) {
|
|||||||
l = m.Rdma.Size()
|
l = m.Rdma.Size()
|
||||||
n += 1 + l + sovMetrics(uint64(l))
|
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 {
|
if m.XXX_unrecognized != nil {
|
||||||
n += len(m.XXX_unrecognized)
|
n += len(m.XXX_unrecognized)
|
||||||
}
|
}
|
||||||
@ -1091,6 +1281,54 @@ func (m *RdmaEntry) Size() (n int) {
|
|||||||
return n
|
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) {
|
func sovMetrics(x uint64) (n int) {
|
||||||
for {
|
for {
|
||||||
n++
|
n++
|
||||||
@ -1113,6 +1351,7 @@ func (this *Metrics) String() string {
|
|||||||
`CPU:` + strings.Replace(fmt.Sprintf("%v", this.CPU), "CPUStat", "CPUStat", 1) + `,`,
|
`CPU:` + strings.Replace(fmt.Sprintf("%v", this.CPU), "CPUStat", "CPUStat", 1) + `,`,
|
||||||
`Memory:` + strings.Replace(fmt.Sprintf("%v", this.Memory), "MemoryStat", "MemoryStat", 1) + `,`,
|
`Memory:` + strings.Replace(fmt.Sprintf("%v", this.Memory), "MemoryStat", "MemoryStat", 1) + `,`,
|
||||||
`Rdma:` + strings.Replace(fmt.Sprintf("%v", this.Rdma), "RdmaStat", "RdmaStat", 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) + `,`,
|
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
|
||||||
`}`,
|
`}`,
|
||||||
}, "")
|
}, "")
|
||||||
@ -1216,6 +1455,33 @@ func (this *RdmaEntry) String() string {
|
|||||||
}, "")
|
}, "")
|
||||||
return s
|
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 {
|
func valueToStringMetrics(v interface{}) string {
|
||||||
rv := reflect.ValueOf(v)
|
rv := reflect.ValueOf(v)
|
||||||
if rv.IsNil() {
|
if rv.IsNil() {
|
||||||
@ -1397,6 +1663,42 @@ func (m *Metrics) Unmarshal(dAtA []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
iNdEx = postIndex
|
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:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipMetrics(dAtA[iNdEx:])
|
skippy, err := skipMetrics(dAtA[iNdEx:])
|
||||||
@ -2647,6 +2949,262 @@ func (m *RdmaEntry) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
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) {
|
func skipMetrics(dAtA []byte) (n int, err error) {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
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"];
|
CPUStat cpu = 2 [(gogoproto.customname) = "CPU"];
|
||||||
MemoryStat memory = 4;
|
MemoryStat memory = 4;
|
||||||
RdmaStat rdma = 5;
|
RdmaStat rdma = 5;
|
||||||
|
IOStat io = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PidsStat {
|
message PidsStat {
|
||||||
@ -74,5 +75,15 @@ message RdmaEntry {
|
|||||||
uint32 hca_objects = 3;
|
uint32 hca_objects = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iostat
|
message IOStat {
|
||||||
// fmt: 230:0 rbytes=394211328 wbytes=65044480 rios=16313 wios=2006 dbytes=0 dios=0
|
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"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
|
||||||
"github.com/containerd/cgroups/v2/stats"
|
"github.com/containerd/cgroups/v2/stats"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -176,7 +179,7 @@ func ToResources(spec *specs.LinuxResources) *Resources {
|
|||||||
resources.CPU.Weight = &convertedWeight
|
resources.CPU.Weight = &convertedWeight
|
||||||
}
|
}
|
||||||
if period := cpu.Period; period != nil {
|
if period := cpu.Period; period != nil {
|
||||||
resources.CPU.Max = period
|
resources.CPU.Max = NewCPUMax(cpu.Quota, period)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if mem := spec.Memory; mem != nil {
|
if mem := spec.Memory; mem != nil {
|
||||||
@ -237,7 +240,6 @@ func ToResources(spec *specs.LinuxResources) *Resources {
|
|||||||
func getStatFileContentUint64(filePath string) uint64 {
|
func getStatFileContentUint64(filePath string) uint64 {
|
||||||
contents, err := ioutil.ReadFile(filePath)
|
contents, err := ioutil.ReadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
trimmed := strings.TrimSpace(string(contents))
|
trimmed := strings.TrimSpace(string(contents))
|
||||||
@ -253,6 +255,64 @@ func getStatFileContentUint64(filePath string) uint64 {
|
|||||||
|
|
||||||
return res
|
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 {
|
func rdmaStats(filepath string) []*stats.RdmaEntry {
|
||||||
currentData, err := ioutil.ReadFile(filepath)
|
currentData, err := ioutil.ReadFile(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -302,3 +362,18 @@ func toRdmaEntry(strEntries []string) []*stats.RdmaEntry {
|
|||||||
}
|
}
|
||||||
return rdmaEntries
|
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/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||||
github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1
|
github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1
|
||||||
github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
|
github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
|
||||||
github.com/containerd/cgroups fada802a7909d430bd17126fd6e4bbf5716f2bcd
|
github.com/containerd/cgroups 7347743e5d1e8500d9f27c8e748e689ed991d92b
|
||||||
github.com/containerd/console 8375c3424e4d7b114e8a90a4a40c8e1b40d1d4e6
|
github.com/containerd/console 8375c3424e4d7b114e8a90a4a40c8e1b40d1d4e6
|
||||||
github.com/containerd/continuity 0ec596719c75bfd42908850990acea594b7593ac
|
github.com/containerd/continuity 0ec596719c75bfd42908850990acea594b7593ac
|
||||||
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
||||||
github.com/containerd/go-runc a5c2862aed5e6358b305b0e16bfce58e0549b1cd
|
github.com/containerd/go-runc a5c2862aed5e6358b305b0e16bfce58e0549b1cd
|
||||||
github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f
|
github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f
|
||||||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
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/cpuguy83/go-md2man 7762f7e404f8416dfa1d9bb6a8c192aa9acb4d19 # v1.0.10
|
||||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
||||||
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
||||||
github.com/docker/go-units 519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0
|
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/googleapis d31c731455cb061f42baff3bda55bad0118b126b # v1.2.0
|
||||||
github.com/gogo/protobuf ba06b47c162d49f2af050fb4c75bcbc86a159d5c # v1.2.1
|
github.com/gogo/protobuf ba06b47c162d49f2af050fb4c75bcbc86a159d5c # v1.2.1
|
||||||
github.com/golang/protobuf aa810b61a9c79d51363740d207bb46cf8e620ed5 # v1.2.0
|
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/konsorten/go-windows-terminal-sequences 5c8c8bd35d3832f5d134ae1e1e375b69a4d25242 # v1.0.1
|
||||||
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c # 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/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/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||||
github.com/opencontainers/image-spec d60099175f88c47cd379c4738d158884749ed235 # v1.0.1
|
github.com/opencontainers/image-spec d60099175f88c47cd379c4738d158884749ed235 # v1.0.1
|
||||||
github.com/opencontainers/runc d736ef14f0288d6993a1845745d6756cfc9ddd5a # v1.0.0-rc9
|
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)
|
[](https://travis-ci.org/coreos/go-systemd)
|
||||||
[](http://godoc.org/github.com/coreos/go-systemd)
|
[](http://godoc.org/github.com/coreos/go-systemd)
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
Go bindings to systemd. The project has several packages:
|
Go bindings to systemd. The project has several packages:
|
||||||
|
|
||||||
- `activation` - for writing and using socket activation from Go
|
- `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
|
- `dbus` - for starting/stopping/inspecting running services and units
|
||||||
- `journal` - for writing to systemd's logging service, journald
|
- `journal` - for writing to systemd's logging service, journald
|
||||||
- `sdjournal` - for reading from journald by wrapping its C API
|
- `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
|
- `machine1` - for registering machines/containers with systemd
|
||||||
- `unit` - for (de)serialization and comparison of unit files
|
- `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
|
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 `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.
|
||||||
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.
|
|
||||||
|
|
||||||
## D-Bus
|
## D-Bus
|
||||||
|
|
||||||
@ -45,6 +48,20 @@ Create `/etc/dbus-1/system-local.conf` that looks like this:
|
|||||||
</busconfig>
|
</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
|
## machined
|
||||||
|
|
||||||
The `machine1` package allows interaction with the [systemd machined D-Bus API](http://www.freedesktop.org/wiki/Software/systemd/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
|
package dbus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/godbus/dbus"
|
"github.com/godbus/dbus/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -60,6 +61,27 @@ func PathBusEscape(path string) string {
|
|||||||
return string(n)
|
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.
|
// Conn is a connection to systemd's dbus endpoint.
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
// sysconn/sysobj are only used to call dbus methods
|
// sysconn/sysobj are only used to call dbus methods
|
||||||
@ -74,13 +96,18 @@ type Conn struct {
|
|||||||
jobs map[dbus.ObjectPath]chan<- string
|
jobs map[dbus.ObjectPath]chan<- string
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
subscriber struct {
|
subStateSubscriber struct {
|
||||||
updateCh chan<- *SubStateUpdate
|
updateCh chan<- *SubStateUpdate
|
||||||
errCh chan<- error
|
errCh chan<- error
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
ignore map[dbus.ObjectPath]int64
|
ignore map[dbus.ObjectPath]int64
|
||||||
cleanIgnore int64
|
cleanIgnore int64
|
||||||
}
|
}
|
||||||
|
propertiesSubscriber struct {
|
||||||
|
updateCh chan<- *PropertiesUpdate
|
||||||
|
errCh chan<- error
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New establishes a connection to any available bus and authenticates.
|
// New establishes a connection to any available bus and authenticates.
|
||||||
@ -116,7 +143,7 @@ func NewUserConnection() (*Conn, error) {
|
|||||||
func NewSystemdConnection() (*Conn, error) {
|
func NewSystemdConnection() (*Conn, error) {
|
||||||
return NewConnection(func() (*dbus.Conn, error) {
|
return NewConnection(func() (*dbus.Conn, error) {
|
||||||
// We skip Hello when talking directly to systemd.
|
// 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")
|
return dbus.Dial("unix:path=/run/systemd/private")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -152,7 +179,7 @@ func NewConnection(dialBus func() (*dbus.Conn, error)) (*Conn, error) {
|
|||||||
sigobj: systemdObject(sigconn),
|
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)
|
c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string)
|
||||||
|
|
||||||
// Setup the listeners on jobs so that we can get completions
|
// 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
|
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()
|
conn, err := createBus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -194,7 +221,7 @@ func dbusAuthConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error
|
|||||||
return conn, nil
|
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)
|
conn, err := dbusAuthConnection(createBus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -16,10 +16,11 @@ package dbus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/godbus/dbus"
|
"github.com/godbus/dbus/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Conn) jobComplete(signal *dbus.Signal) {
|
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)
|
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.
|
// otherwise.
|
||||||
func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode)
|
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.
|
// flavored restart otherwise.
|
||||||
func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode)
|
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()
|
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
|
// SystemState returns the systemd state. Equivalent to `systemctl is-system-running`.
|
||||||
func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]interface{}, error) {
|
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 err error
|
||||||
var props map[string]dbus.Variant
|
var props map[string]dbus.Variant
|
||||||
|
|
||||||
path := unitPath(unit)
|
|
||||||
if !path.IsValid() {
|
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)
|
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
|
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) {
|
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) {
|
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
|
// 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
|
// 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) {
|
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.
|
// 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
|
// 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
|
// 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.
|
// 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) {
|
func (c *Conn) ListUnits() ([]UnitStatus, error) {
|
||||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store)
|
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
|
// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns
|
||||||
// method, this method returns statuses even for inactive or non-existing
|
// method, this method returns statuses even for inactive or non-existing
|
||||||
// units. Input array should contain exact unit names, but not patterns.
|
// 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) {
|
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
|
||||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
|
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 {
|
func unitPath(name string) dbus.ObjectPath {
|
||||||
return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name))
|
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
|
package dbus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/godbus/dbus"
|
"github.com/godbus/dbus/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// From the systemd docs:
|
// From the systemd docs:
|
||||||
@ -56,7 +56,7 @@ type execStart struct {
|
|||||||
// http://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
|
// http://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
|
||||||
func PropExecStart(command []string, uncleanIsFailure bool) Property {
|
func PropExecStart(command []string, uncleanIsFailure bool) Property {
|
||||||
execStarts := []execStart{
|
execStarts := []execStart{
|
||||||
execStart{
|
{
|
||||||
Path: command[0],
|
Path: command[0],
|
||||||
Args: command,
|
Args: command,
|
||||||
UncleanIsFailure: uncleanIsFailure,
|
UncleanIsFailure: uncleanIsFailure,
|
@ -36,7 +36,7 @@ func (s *set) Length() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *set) Values() (values []string) {
|
func (s *set) Values() (values []string) {
|
||||||
for val, _ := range s.data {
|
for val := range s.data {
|
||||||
values = append(values, val)
|
values = append(values, val)
|
||||||
}
|
}
|
||||||
return
|
return
|
@ -16,9 +16,10 @@ package dbus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/godbus/dbus"
|
"github.com/godbus/dbus/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -36,22 +37,12 @@ func (c *Conn) Subscribe() error {
|
|||||||
c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
|
c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
|
||||||
"type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'")
|
"type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'")
|
||||||
|
|
||||||
err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
|
return c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsubscribe this connection from systemd dbus events.
|
// Unsubscribe this connection from systemd dbus events.
|
||||||
func (c *Conn) Unsubscribe() error {
|
func (c *Conn) Unsubscribe() error {
|
||||||
err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
|
return c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) dispatch() {
|
func (c *Conn) dispatch() {
|
||||||
@ -70,7 +61,8 @@ func (c *Conn) dispatch() {
|
|||||||
c.jobComplete(signal)
|
c.jobComplete(signal)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.subscriber.updateCh == nil {
|
if c.subStateSubscriber.updateCh == nil &&
|
||||||
|
c.propertiesSubscriber.updateCh == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +76,12 @@ func (c *Conn) dispatch() {
|
|||||||
case "org.freedesktop.DBus.Properties.PropertiesChanged":
|
case "org.freedesktop.DBus.Properties.PropertiesChanged":
|
||||||
if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" {
|
if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" {
|
||||||
unitPath = signal.Path
|
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.
|
// interval. Deleted units are sent as nil.
|
||||||
func (c *Conn) SubscribeUnits(interval time.Duration) (<-chan map[string]*UnitStatus, <-chan error) {
|
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)
|
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
|
// is full, it attempts to write an error to errCh; if errCh is full, the error
|
||||||
// passes silently.
|
// passes silently.
|
||||||
func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) {
|
func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) {
|
||||||
c.subscriber.Lock()
|
if c == nil {
|
||||||
defer c.subscriber.Unlock()
|
msg := "nil receiver"
|
||||||
c.subscriber.updateCh = updateCh
|
select {
|
||||||
c.subscriber.errCh = errCh
|
case errCh <- errors.New(msg):
|
||||||
}
|
default:
|
||||||
|
log.Printf("full error channel while reporting: %s\n", msg)
|
||||||
func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
|
}
|
||||||
c.subscriber.Lock()
|
|
||||||
defer c.subscriber.Unlock()
|
|
||||||
|
|
||||||
if c.shouldIgnore(path) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := c.GetUnitProperties(string(path))
|
c.subStateSubscriber.Lock()
|
||||||
if err != nil {
|
defer c.subStateSubscriber.Unlock()
|
||||||
select {
|
c.subStateSubscriber.updateCh = updateCh
|
||||||
case c.subscriber.errCh <- err:
|
c.subStateSubscriber.errCh = errCh
|
||||||
default:
|
}
|
||||||
}
|
|
||||||
|
func (c *Conn) sendSubStateUpdate(unitPath dbus.ObjectPath) {
|
||||||
|
c.subStateSubscriber.Lock()
|
||||||
|
defer c.subStateSubscriber.Unlock()
|
||||||
|
|
||||||
|
if c.subStateSubscriber.updateCh == nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
name := info["Id"].(string)
|
isIgnored := c.shouldIgnore(unitPath)
|
||||||
substate := info["SubState"].(string)
|
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}
|
update := &SubStateUpdate{name, substate}
|
||||||
select {
|
select {
|
||||||
case c.subscriber.updateCh <- update:
|
case c.subStateSubscriber.updateCh <- update:
|
||||||
default:
|
default:
|
||||||
|
msg := "update channel is full"
|
||||||
select {
|
select {
|
||||||
case c.subscriber.errCh <- errors.New("update channel full!"):
|
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||||
default:
|
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.
|
// 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).
|
// the properties).
|
||||||
|
|
||||||
func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool {
|
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()
|
return ok && t >= time.Now().UnixNano()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) {
|
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
|
// unit is unloaded - it will trigger bad systemd dbus behavior
|
||||||
if info["LoadState"].(string) == "not-found" {
|
if loadState == "not-found" {
|
||||||
c.subscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
|
c.subStateSubscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// without this, ignore would grow unboundedly over time
|
// without this, ignore would grow unboundedly over time
|
||||||
func (c *Conn) cleanIgnore() {
|
func (c *Conn) cleanIgnore() {
|
||||||
now := time.Now().UnixNano()
|
now := time.Now().UnixNano()
|
||||||
if c.subscriber.cleanIgnore < now {
|
if c.subStateSubscriber.cleanIgnore < now {
|
||||||
c.subscriber.cleanIgnore = now + cleanIgnoreInterval
|
c.subStateSubscriber.cleanIgnore = now + cleanIgnoreInterval
|
||||||
|
|
||||||
for p, t := range c.subscriber.ignore {
|
for p, t := range c.subStateSubscriber.ignore {
|
||||||
if t < now {
|
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
|
dbus
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -12,7 +14,7 @@ D-Bus message bus system.
|
|||||||
|
|
||||||
### Installation
|
### 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
|
go get github.com/godbus/dbus
|
||||||
@ -29,6 +31,7 @@ gives a short overview over the basic usage.
|
|||||||
|
|
||||||
#### Projects using godbus
|
#### Projects using godbus
|
||||||
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
|
- [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
|
Please note that the API is considered unstable for now and may change without
|
||||||
further notice.
|
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 {
|
for _, m := range methods {
|
||||||
if name, data, status := m.FirstData(); bytes.Equal(v, name) {
|
if name, data, status := m.FirstData(); bytes.Equal(v, name) {
|
||||||
var ok bool
|
var ok bool
|
||||||
err = authWriteLine(conn.transport, []byte("AUTH"), []byte(v), data)
|
err = authWriteLine(conn.transport, []byte("AUTH"), v, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -116,7 +116,6 @@ func (conn *Conn) Auth(methods []Auth) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go conn.inWorker()
|
go conn.inWorker()
|
||||||
go conn.outWorker()
|
|
||||||
return nil
|
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
|
// 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
|
// initial authState and in for reading input. It returns (nil, true) on
|
||||||
// success, (nil, false) on a REJECTED and (someErr, false) if some other
|
// 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) {
|
func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, bool) {
|
||||||
for {
|
for {
|
||||||
s, err := authReadLine(in)
|
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
|
// 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,
|
// 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.)
|
// return an error.)
|
||||||
func (a authCookieSha1) getCookie(context, id []byte) []byte {
|
func (a authCookieSha1) getCookie(context, id []byte) []byte {
|
||||||
file, err := os.Open(a.home + "/.dbus-keyrings/" + string(context))
|
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
|
package dbus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errSignature = errors.New("dbus: mismatched signature")
|
||||||
|
|
||||||
// Call represents a pending or completed method call.
|
// Call represents a pending or completed method call.
|
||||||
type Call struct {
|
type Call struct {
|
||||||
Destination string
|
Destination string
|
||||||
@ -20,9 +23,25 @@ type Call struct {
|
|||||||
|
|
||||||
// Holds the response once the call is done.
|
// Holds the response once the call is done.
|
||||||
Body []interface{}
|
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
|
// 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
|
// 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...)
|
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 {
|
if depth >= 64 {
|
||||||
panic(FormatError("input exceeds container depth limit"))
|
panic(FormatError("input exceeds container depth limit"))
|
||||||
}
|
}
|
||||||
|
sig := s[1:]
|
||||||
length := dec.decode("u", depth).(uint32)
|
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
|
// 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
|
spos := dec.pos
|
||||||
for dec.pos < spos+int(length) {
|
for dec.pos < spos+int(length) {
|
||||||
ev := dec.decode(s[1:], depth+1)
|
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.
|
// A FormatError is an error in the wire format.
|
||||||
type FormatError string
|
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
|
bool | BOOLEAN
|
||||||
int16 | INT16
|
int16 | INT16
|
||||||
uint16 | UINT16
|
uint16 | UINT16
|
||||||
|
int | INT32
|
||||||
|
uint | UINT32
|
||||||
int32 | INT32
|
int32 | INT32
|
||||||
uint32 | UINT32
|
uint32 | UINT32
|
||||||
int64 | INT64
|
int64 | INT64
|
||||||
@ -28,6 +30,7 @@ respective D-Bus equivalents:
|
|||||||
ObjectPath | OBJECT_PATH
|
ObjectPath | OBJECT_PATH
|
||||||
Signature | SIGNATURE
|
Signature | SIGNATURE
|
||||||
Variant | VARIANT
|
Variant | VARIANT
|
||||||
|
interface{} | VARIANT
|
||||||
UnixFDIndex | UNIX_FD
|
UnixFDIndex | UNIX_FD
|
||||||
|
|
||||||
Slices and arrays encode as ARRAYs of their element type.
|
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.
|
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
|
Trying to encode any other type or a slice, map or struct containing an
|
||||||
unsupported type will result in an InvalidTypeError.
|
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.
|
first check that they are supported on a connection by calling SupportsUnixFDs.
|
||||||
If it returns true, all method of Connection will translate messages containing
|
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'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
|
of incoming messages are automatically resolved. It shouldn't be necessary to use
|
||||||
UnixFDIndex.
|
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.
|
// are aligned properly as required by the D-Bus spec.
|
||||||
func (enc *encoder) Encode(vs ...interface{}) (err error) {
|
func (enc *encoder) Encode(vs ...interface{}) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -96,10 +96,10 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
|
|||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
enc.binwrite(uint16(v.Uint()))
|
enc.binwrite(uint16(v.Uint()))
|
||||||
enc.pos += 2
|
enc.pos += 2
|
||||||
case reflect.Int32:
|
case reflect.Int, reflect.Int32:
|
||||||
enc.binwrite(int32(v.Int()))
|
enc.binwrite(int32(v.Int()))
|
||||||
enc.pos += 4
|
enc.pos += 4
|
||||||
case reflect.Uint32:
|
case reflect.Uint, reflect.Uint32:
|
||||||
enc.binwrite(uint32(v.Uint()))
|
enc.binwrite(uint32(v.Uint()))
|
||||||
enc.pos += 4
|
enc.pos += 4
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
@ -202,6 +202,8 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
enc.pos += length
|
enc.pos += length
|
||||||
|
case reflect.Interface:
|
||||||
|
enc.encode(reflect.ValueOf(MakeVariant(v.Interface())), depth)
|
||||||
default:
|
default:
|
||||||
panic(InvalidTypeError{v.Type()})
|
panic(InvalidTypeError{v.Type()})
|
||||||
}
|
}
|
361
vendor/github.com/godbus/dbus/export.go → vendor/github.com/godbus/dbus/v5/export.go
generated
vendored
361
vendor/github.com/godbus/dbus/export.go → vendor/github.com/godbus/dbus/v5/export.go
generated
vendored
@ -8,167 +8,73 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errmsgInvalidArg = Error{
|
ErrMsgInvalidArg = Error{
|
||||||
"org.freedesktop.DBus.Error.InvalidArgs",
|
"org.freedesktop.DBus.Error.InvalidArgs",
|
||||||
[]interface{}{"Invalid type / number of args"},
|
[]interface{}{"Invalid type / number of args"},
|
||||||
}
|
}
|
||||||
errmsgNoObject = Error{
|
ErrMsgNoObject = Error{
|
||||||
"org.freedesktop.DBus.Error.NoSuchObject",
|
"org.freedesktop.DBus.Error.NoSuchObject",
|
||||||
[]interface{}{"No such object"},
|
[]interface{}{"No such object"},
|
||||||
}
|
}
|
||||||
errmsgUnknownMethod = Error{
|
ErrMsgUnknownMethod = Error{
|
||||||
"org.freedesktop.DBus.Error.UnknownMethod",
|
"org.freedesktop.DBus.Error.UnknownMethod",
|
||||||
[]interface{}{"Unknown / invalid method"},
|
[]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
|
func MakeFailedError(err error) *Error {
|
||||||
// mapping to allow for exporting lower-case methods, etc.
|
return &Error{
|
||||||
type exportWithMapping struct {
|
"org.freedesktop.DBus.Error.Failed",
|
||||||
export interface{}
|
[]interface{}{err.Error()},
|
||||||
|
}
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sender is a type which can be used in exported methods to receive the message
|
// Sender is a type which can be used in exported methods to receive the message
|
||||||
// sender.
|
// sender.
|
||||||
type Sender string
|
type Sender string
|
||||||
|
|
||||||
func exportedMethod(export exportWithMapping, name string) reflect.Value {
|
func computeMethodName(name string, mapping map[string]string) string {
|
||||||
if export.export == nil {
|
newname, ok := mapping[name]
|
||||||
return reflect.Value{}
|
if ok {
|
||||||
|
name = newname
|
||||||
}
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
// If a mapping was included in the export, check the map to see if we
|
func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
|
||||||
// should be looking for a different method in the export.
|
if in == nil {
|
||||||
if export.mapping != nil {
|
return nil
|
||||||
for key, value := range export.mapping {
|
|
||||||
if value == name {
|
|
||||||
name = key
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
methods := make(map[string]reflect.Value)
|
||||||
// Catch the case where a method is aliased but the client is calling
|
val := reflect.ValueOf(in)
|
||||||
// the original, e.g. the "Foo" method was exported mapped to
|
typ := val.Type()
|
||||||
// "foo," and dbus client called the original "Foo."
|
for i := 0; i < typ.NumMethod(); i++ {
|
||||||
if key == name {
|
methtype := typ.Method(i)
|
||||||
return reflect.Value{}
|
method := val.Method(i)
|
||||||
}
|
t := method.Type()
|
||||||
}
|
// only track valid methods must return *Error as last arg
|
||||||
}
|
// and must be exported
|
||||||
|
|
||||||
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 ||
|
if t.NumOut() == 0 ||
|
||||||
t.Out(t.NumOut()-1) != reflect.TypeOf(&errmsgInvalidArg) {
|
t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) ||
|
||||||
|
methtype.PkgPath != "" {
|
||||||
return reflect.Value{}
|
continue
|
||||||
}
|
}
|
||||||
return m
|
// map names while building table
|
||||||
|
methods[computeMethodName(methtype.Name, mapping)] = method
|
||||||
|
}
|
||||||
|
return methods
|
||||||
}
|
}
|
||||||
|
|
||||||
// searchHandlers will look through all registered handlers looking for one
|
func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) {
|
||||||
// to handle the given path. If a verbatim one isn't found, it will check for
|
pointers := make([]interface{}, m.NumArguments())
|
||||||
// a subtree registration for the path as well.
|
decode := make([]interface{}, 0, len(body))
|
||||||
func (conn *Conn) searchHandlers(path ObjectPath) (map[string]exportWithMapping, bool) {
|
|
||||||
conn.handlersLck.RLock()
|
|
||||||
defer conn.handlersLck.RUnlock()
|
|
||||||
|
|
||||||
handlers, ok := conn.handlers[path]
|
for i := 0; i < m.NumArguments(); i++ {
|
||||||
if ok {
|
tp := reflect.TypeOf(m.ArgumentValue(i))
|
||||||
return handlers, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(name) == 0 {
|
|
||||||
conn.sendError(errmsgUnknownMethod, sender, serial)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the exported handler (if any) for this path
|
|
||||||
handlers, ok := conn.searchHandlers(path)
|
|
||||||
if !ok {
|
|
||||||
conn.sendError(errmsgNoObject, sender, serial)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
val := reflect.New(tp)
|
val := reflect.New(tp)
|
||||||
pointers[i] = val.Interface()
|
pointers[i] = val.Interface()
|
||||||
if tp == reflect.TypeOf((*Sender)(nil)).Elem() {
|
if tp == reflect.TypeOf((*Sender)(nil)).Elem() {
|
||||||
@ -180,26 +86,73 @@ func (conn *Conn) handleCall(msg *Message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(decode) != len(vs) {
|
if len(decode) != len(body) {
|
||||||
conn.sendError(errmsgInvalidArg, sender, serial)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Store(vs, decode...); err != nil {
|
iface, exists := object.LookupInterface(ifaceName)
|
||||||
conn.sendError(errmsgInvalidArg, sender, serial)
|
if !exists {
|
||||||
|
conn.sendError(ErrMsgUnknownInterface, sender, serial)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract parameters
|
m, exists := iface.LookupMethod(name)
|
||||||
params := make([]reflect.Value, len(pointers))
|
if !exists {
|
||||||
for i := 0; i < len(pointers); i++ {
|
conn.sendError(ErrMsgUnknownMethod, sender, serial)
|
||||||
params[i] = reflect.ValueOf(pointers[i]).Elem()
|
return
|
||||||
|
}
|
||||||
|
args, err := conn.decodeArguments(m, sender, msg)
|
||||||
|
if err != nil {
|
||||||
|
conn.sendError(err, sender, serial)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call method
|
ret, err := m.Call(args...)
|
||||||
ret := m.Call(params)
|
if err != nil {
|
||||||
if em := ret[t.NumOut()-1].Interface().(*Error); em != nil {
|
conn.sendError(err, sender, serial)
|
||||||
conn.sendError(*em, sender, serial)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,18 +165,13 @@ func (conn *Conn) handleCall(msg *Message) {
|
|||||||
reply.Headers[FieldDestination] = msg.Headers[FieldSender]
|
reply.Headers[FieldDestination] = msg.Headers[FieldSender]
|
||||||
}
|
}
|
||||||
reply.Headers[FieldReplySerial] = MakeVariant(msg.serial)
|
reply.Headers[FieldReplySerial] = MakeVariant(msg.serial)
|
||||||
reply.Body = make([]interface{}, len(ret)-1)
|
reply.Body = make([]interface{}, len(ret))
|
||||||
for i := 0; i < len(ret)-1; i++ {
|
for i := 0; i < len(ret); i++ {
|
||||||
reply.Body[i] = ret[i].Interface()
|
reply.Body[i] = ret[i]
|
||||||
}
|
}
|
||||||
if len(ret) != 1 {
|
|
||||||
reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...))
|
reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...))
|
||||||
}
|
|
||||||
conn.outLck.RLock()
|
conn.sendMessageAndIfClosed(reply, nil)
|
||||||
if !conn.closed {
|
|
||||||
conn.out <- reply
|
|
||||||
}
|
|
||||||
conn.outLck.RUnlock()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,12 +204,14 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro
|
|||||||
if len(values) > 0 {
|
if len(values) > 0 {
|
||||||
msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...))
|
msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...))
|
||||||
}
|
}
|
||||||
conn.outLck.RLock()
|
|
||||||
defer conn.outLck.RUnlock()
|
var closed bool
|
||||||
if conn.closed {
|
conn.sendMessageAndIfClosed(msg, func() {
|
||||||
|
closed = true
|
||||||
|
})
|
||||||
|
if closed {
|
||||||
return ErrClosed
|
return ErrClosed
|
||||||
}
|
}
|
||||||
conn.out <- msg
|
|
||||||
return nil
|
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 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.
|
// 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 {
|
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
|
// 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 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.
|
// 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 {
|
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.
|
// 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() {
|
if !path.IsValid() {
|
||||||
return fmt.Errorf(`dbus: Invalid path name: "%s"`, path)
|
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
|
// Remove a previous export if the interface is nil
|
||||||
if v == nil {
|
if methods == nil {
|
||||||
if _, ok := conn.handlers[path]; ok {
|
return conn.unexport(h, path, iface)
|
||||||
delete(conn.handlers[path], iface)
|
|
||||||
if len(conn.handlers[path]) == 0 {
|
|
||||||
delete(conn.handlers, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the first handler for this path, make a new map to hold all
|
// If this is the first handler for this path, make a new map to hold all
|
||||||
// handlers for this path.
|
// handlers for this path.
|
||||||
if _, ok := conn.handlers[path]; !ok {
|
if !h.PathExists(path) {
|
||||||
conn.handlers[path] = make(map[string]exportWithMapping)
|
h.AddObject(path, newExportedObject())
|
||||||
|
}
|
||||||
|
|
||||||
|
exportedMethods := make(map[string]Method)
|
||||||
|
for name, method := range methods {
|
||||||
|
exportedMethods[name] = exportedMethod{method}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, save this handler
|
// 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
|
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
|
// FlagNoAutoStart signals that the message bus should not automatically
|
||||||
// start an application when handling this message.
|
// start an application when handling this message.
|
||||||
FlagNoAutoStart
|
FlagNoAutoStart
|
||||||
|
// FlagAllowInteractiveAuthorization may be set on a method call
|
||||||
|
// message to inform the receiving side that the caller is prepared
|
||||||
|
// to wait for interactive authorization, which might take a
|
||||||
|
// considerable time to complete. For instance, if this flag is set,
|
||||||
|
// it would be appropriate to query the user for passwords or
|
||||||
|
// confirmation via Polkit or a similar framework.
|
||||||
|
FlagAllowInteractiveAuthorization
|
||||||
)
|
)
|
||||||
|
|
||||||
// Type represents the possible types of a D-Bus message.
|
// Type 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
|
// IsValid checks whether msg is a valid message and returns an
|
||||||
// InvalidMessageError if it is not.
|
// InvalidMessageError if it is not.
|
||||||
func (msg *Message) IsValid() error {
|
func (msg *Message) IsValid() error {
|
||||||
if msg.Flags & ^(FlagNoAutoStart|FlagNoReplyExpected) != 0 {
|
if msg.Flags & ^(FlagNoAutoStart|FlagNoReplyExpected|FlagAllowInteractiveAuthorization) != 0 {
|
||||||
return InvalidMessageError("invalid flags")
|
return InvalidMessageError("invalid flags")
|
||||||
}
|
}
|
||||||
if msg.Type == 0 || msg.Type >= typeMax {
|
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"
|
return "n"
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
return "q"
|
return "q"
|
||||||
case reflect.Int32:
|
case reflect.Int, reflect.Int32:
|
||||||
if t == unixFDType {
|
if t == unixFDType {
|
||||||
return "h"
|
return "h"
|
||||||
}
|
}
|
||||||
return "i"
|
return "i"
|
||||||
case reflect.Uint32:
|
case reflect.Uint, reflect.Uint32:
|
||||||
if t == unixFDIndexType {
|
if t == unixFDIndexType {
|
||||||
return "h"
|
return "h"
|
||||||
}
|
}
|
||||||
@ -101,6 +101,8 @@ func getSignature(t reflect.Type) string {
|
|||||||
panic(InvalidTypeError{t})
|
panic(InvalidTypeError{t})
|
||||||
}
|
}
|
||||||
return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
|
return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
|
||||||
|
case reflect.Interface:
|
||||||
|
return "v"
|
||||||
}
|
}
|
||||||
panic(InvalidTypeError{t})
|
panic(InvalidTypeError{t})
|
||||||
}
|
}
|
||||||
@ -162,7 +164,7 @@ func (e SignatureError) Error() string {
|
|||||||
return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
|
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
|
// 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
|
// 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.
|
// not be greater than 64 and should be given as 0 on the first call.
|
@ -4,8 +4,23 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"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 {
|
type genericTransport struct {
|
||||||
io.ReadWriteCloser
|
io.ReadWriteCloser
|
||||||
}
|
}
|
||||||
@ -31,5 +46,5 @@ func (t genericTransport) SendMessage(msg *Message) error {
|
|||||||
return errors.New("dbus: unix fd passing not enabled")
|
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
|
package dbus
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ func (o *oobReader) Read(b []byte) (n int, err error) {
|
|||||||
|
|
||||||
type unixTransport struct {
|
type unixTransport struct {
|
||||||
*net.UnixConn
|
*net.UnixConn
|
||||||
|
rdr *oobReader
|
||||||
hasUnixFDs bool
|
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
|
// 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
|
// reader that uses ReadUnix on the underlying connection instead of Read
|
||||||
// and gathers the out-of-band data in a buffer.
|
// 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),
|
// 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
|
// 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
|
return nil, err
|
||||||
}
|
}
|
||||||
switch csheader[0] {
|
switch csheader[0] {
|
||||||
@ -104,7 +110,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
|
|||||||
// decode headers and look for unix fds
|
// decode headers and look for unix fds
|
||||||
headerdata := make([]byte, hlen+4)
|
headerdata := make([]byte, hlen+4)
|
||||||
copy(headerdata, csheader[12:])
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
dec := newDecoder(bytes.NewBuffer(headerdata), order)
|
dec := newDecoder(bytes.NewBuffer(headerdata), order)
|
||||||
@ -122,7 +128,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
|
|||||||
all := make([]byte, 16+hlen+blen)
|
all := make([]byte, 16+hlen+blen)
|
||||||
copy(all, csheader[:])
|
copy(all, csheader[:])
|
||||||
copy(all[16:], headerdata[4:])
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
if unixfds != 0 {
|
if unixfds != 0 {
|
||||||
@ -130,7 +136,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
|
|||||||
return nil, errors.New("dbus: got unix fds on unsupported transport")
|
return nil, errors.New("dbus: got unix fds on unsupported transport")
|
||||||
}
|
}
|
||||||
// read the fds from the OOB data
|
// read the fds from the OOB data
|
||||||
scms, err := syscall.ParseSocketControlMessage(rd.oob)
|
scms, err := syscall.ParseSocketControlMessage(t.rdr.oob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// substitute the values in the message body (which are indices for the
|
||||||
// array receiver via OOB) with the actual values
|
// array receiver via OOB) with the actual values
|
||||||
for i, v := range msg.Body {
|
for i, v := range msg.Body {
|
||||||
if j, ok := v.(UnixFDIndex); ok {
|
switch v.(type) {
|
||||||
|
case UnixFDIndex:
|
||||||
|
j := v.(UnixFDIndex)
|
||||||
if uint32(j) >= unixfds {
|
if uint32(j) >= unixfds {
|
||||||
return nil, InvalidMessageError("invalid index for unix fd")
|
return nil, InvalidMessageError("invalid index for unix fd")
|
||||||
}
|
}
|
||||||
msg.Body[i] = UnixFD(fds[j])
|
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
|
return msg, nil
|
||||||
@ -175,7 +193,7 @@ func (t *unixTransport) SendMessage(msg *Message) error {
|
|||||||
msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds)))
|
msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds)))
|
||||||
oob := syscall.UnixRights(fds...)
|
oob := syscall.UnixRights(fds...)
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
msg.EncodeTo(buf, binary.LittleEndian)
|
msg.EncodeTo(buf, nativeEndian)
|
||||||
n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
|
n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -184,8 +202,8 @@ func (t *unixTransport) SendMessage(msg *Message) error {
|
|||||||
return io.ErrShortWrite
|
return io.ErrShortWrite
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := msg.EncodeTo(t, binary.LittleEndian); err != nil {
|
if err := msg.EncodeTo(t, nativeEndian); err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
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
|
// MakeVariant converts the given value to a Variant. It panics if v cannot be
|
||||||
// represented as a D-Bus type.
|
// represented as a D-Bus type.
|
||||||
func MakeVariant(v interface{}) Variant {
|
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
|
// 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.
|
// empty, it is taken to be the expected signature for the variant.
|
||||||
func ParseVariant(s string, sig Signature) (Variant, error) {
|
func ParseVariant(s string, sig Signature) (Variant, error) {
|
||||||
tokens := varLex(s)
|
tokens := varLex(s)
|
||||||
@ -124,7 +129,7 @@ func (v Variant) Signature() Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string representation of the underlying value of v as
|
// 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 {
|
func (v Variant) String() string {
|
||||||
s, unamb := v.format()
|
s, unamb := v.format()
|
||||||
if !unamb {
|
if !unamb {
|
@ -51,7 +51,7 @@ func varLex(s string) []varToken {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *varLexer) accept(valid string) bool {
|
func (l *varLexer) accept(valid string) bool {
|
||||||
if strings.IndexRune(valid, l.next()) >= 0 {
|
if strings.ContainsRune(valid, l.next()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
l.backup()
|
l.backup()
|
||||||
@ -214,17 +214,17 @@ func varLexNumber(l *varLexer) lexState {
|
|||||||
digits = "01234567"
|
digits = "01234567"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for strings.IndexRune(digits, l.next()) >= 0 {
|
for strings.ContainsRune(digits, l.next()) {
|
||||||
}
|
}
|
||||||
l.backup()
|
l.backup()
|
||||||
if l.accept(".") {
|
if l.accept(".") {
|
||||||
for strings.IndexRune(digits, l.next()) >= 0 {
|
for strings.ContainsRune(digits, l.next()) {
|
||||||
}
|
}
|
||||||
l.backup()
|
l.backup()
|
||||||
}
|
}
|
||||||
if l.accept("eE") {
|
if l.accept("eE") {
|
||||||
l.accept("+-")
|
l.accept("+-")
|
||||||
for strings.IndexRune("0123456789", l.next()) >= 0 {
|
for strings.ContainsRune("0123456789", l.next()) {
|
||||||
}
|
}
|
||||||
l.backup()
|
l.backup()
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user