GithubHelp home page GithubHelp logo

go.dbus's Introduction

NOTE

This repository is now archived. Please use the official repo https://github.com/godbus/dbus instead, where development is continued.

go.dbus

go.dbus is a simple library that implements native Go client bindings for the D-Bus message bus system.

Features

  • Complete native implementation of the D-Bus message protocol
  • Go-like API (channels for signals / asynchronous method calls, Goroutine-safe connections)
  • Subpackages that help with the introspection / property interfaces

Installation

This packages requires Go 1.1. If you installed it and set up your GOPATH, just run:

go get github.com/guelfey/go.dbus

If you want to use the subpackages, you can install them the same way.

Usage

The complete package documentation and some simple examples are available at godoc.org. Also, the _examples directory gives a short overview over the basic usage.

Please note that the API is considered unstable for now and may change without further notice.

License

go.dbus is available under the Simplified BSD License; see LICENSE for the full text.

go.dbus's People

Contributors

guelfey avatar jessevdk avatar tdubrownik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go.dbus's Issues

Rework API for asynchronous calls

net/rpc allows the caller to pass a channel on which the call and its result are sent once it's done. A similar thing should be implemented for this package.

Provide means to emit signals

At the moment, there is no way to emit signals on some objects.

Possible function:

func (conn *Connection) Emit(sm *SignalMessage)

This would be most consistent with other functions, but require the fields of SignalMessage to be changed.

Also, should emitting signals only be allowed on objects that were already registered with Export?

Support autolaunching for the session bus

From the spec:

If DBUS_SESSION_BUS_ADDRESS is not set, or if it's set to the string "autolaunch:", the system should use platform-specific methods of locating a running D-Bus session server, or starting one if a running instance cannot be found.

It doesn't support empty struct .

An empty struct will cause bus connection closed

type of '()' can be show in d-feet. And dbus spec doesn't specify whether an struct can be an empty.

Some parts do not conform to the specification

In particular, most requirements regarding the message format (maximum depth of structures, maximum size of some stuff) are not checked and the incoming messages are not validated in all aspects.

Support eavesdropping

Right now, all incoming messages are treated as if they were directed to the running application, which breaks eavesdropping. This should be relatively easy to fix: we create another channel for all eavesdropped messages, and all messages whose destination is not one of the known names of the connection are forwarded there.

prop.Prop only supports one connection

If you have an object that is exposed on multiple connections (for instance one in a server that allows peer-to-peer connections) it cannot use the current properties support, because it is tied to a specific connection. It should be possible to create the Prop type without reference to an existing connection, and then later export it on one or more connections as they arrive.

Add function for sending arbitrary messages

This is needed for doing some advanced stuff, for example, unicast signals. This means that we either need to export a function to return a serial, or just fill out the serial field for these messages.

Finalize API

Decide on a stable API. Open questions / issues:

  1. Should Encoder / Decoder be exported? No use case outside of the package comes to mind.
  2. Connection creation is inflexible. There's no way to mock a connection, and the user has little control over the low-level details of connecting.

After calling Export, dbus still returns UnknownMethod

Running your _examples/server.go, trying to call
dbus-send --session --print-reply --dest="com.github.guelfey.Demo" /com/github/guelfey/Demo org.freedesktop.DBus.Introspectable.Introspect
results in an UnknownMethod error.

Validate message bodies when decoding

As a consequence, we could make the Body member of messages have type []interface{} instead of []byte. Related to #9 as we can check for the maximum container depth while we're at it.

Is SendNullByte needed?

I'm trying to use go.dbus on OS X which doesn't support syscall.Ucred. However, I found that SendNullByte is currently not used anywhere. Can it be removed altogether?

Whether you can remove the restrict of exported method must be return an *dbus.Error

snyh@5d561fa

I think this restrict is no need.
If some function may return error then return one and handleCall can detect this error to invoke conn.sendError.

If the method must return an dbus.Error then this method can't used by other place natural.

this restrict will cause auto exported struct need use dbus.Error and I think unless the use want more control then no need to know the low-level api

panic: reflect: call of reflect.Value.Elem on map Value

Hi

I am trying to call GetManagedObjects on the org.freedesktop.DBus.ObjectManager interface of org.freedesktop.UDisks2.

According to
http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager

The signature is:

    org.freedesktop.DBus.ObjectManager.GetManagedObjects (out DICT<OBJPATH,DICT<STRING,DICT<STRING,VARIANT>>> objpath_interfaces_and_properties);
udisk := conn.Object("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2")

...

ret := make(map[dbus.ObjectPath]map[string]dbus.Variant)
err = udisk.Call("org.freedesktop.DBus.ObjectManager.GetManagedObjects", 0).Store(ret)

if err != nil {
  panic(err)
}

results in

panic: reflect: call of reflect.Value.Elem on map Value

What would be the correct way to call this method?

Compound structs where substructs contain arrays causes nil pointer exception

I created several compound structures to return via the dbus.

type GetFileResponse struct {
    Response
    File
}
type Response struct {
    Status int32
    Message string
}
type File struct {
    Fileid int64
    Path string
    Name string
    HashSimple string
    HashSHA1 string
    HashMD5 string
    Filecreationdate int64
    Filemodificationdate int64
    Creationdate int64
    Modificationdate int64
    Size int64
    Isdir bool
    Deleted bool
    Metadata []byte
}

I created it this way for readability and it seemed like it should work based on the documentation, however I found an interesting bug. It seems that when dealing with a compound struct such as GetFileResponse, if a sub-struct has an array in it then go panics with the following stack trace:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x4e1703]

goroutine 11 [running]:
runtime.panic(0x6ad7e0, 0xa36553)
    /usr/lib/go/src/pkg/runtime/panic.c:278 +0xf8
reflect.(*gcProg).appendProg(0xc20805d480, 0x6a23c0)
    /usr/lib/go/src/pkg/reflect/type.go:1508 +0x183
reflect.funcLayout(0x6771c0, 0x6c4700, 0x63b440, 0x18, 0x18)
    /usr/lib/go/src/pkg/reflect/type.go:1787 +0x4d2
reflect.Value.call(0x6c4700, 0xc2080425a0, 0x0, 0xb38, 0x6d9220, 0x4, 0xc20805d460, 0x1, 0x1, 0x0, ...)
    /usr/lib/go/src/pkg/reflect/value.go:535 +0xee1
reflect.Value.Call(0x6c4700, 0xc2080425a0, 0x0, 0xb38, 0xc20805d460, 0x1, 0x1, 0x0, 0x0, 0x0)
    /usr/lib/go/src/pkg/reflect/value.go:411 +0xd7
github.com/guelfey/go%2edbus.(*Conn).handleCall(0xc20807ca20, 0xc20800afc0)
    /var/go/src/github.com/guelfey/go.dbus/export.go:125 +0xf41
created by github.com/guelfey/go%2edbus.(*Conn).inWorker
    /var/go/src/github.com/guelfey/go.dbus/conn.go:328 +0x247

I dug into the reflect package trying to find why this was happening, because it seems to only be in this very complex implementation that it happens, but I was unable to come up with a reason. I figured I would post here to see if anyone else found this issue and could shed some light on it.
I am working around it using simpler structs and more return values, but the readability of this method was pretty fantastic and I would prefer to use it if this issue can be easily corrected.

In the meanwhile, if I happen to figure out what's causing it then I'll submit a PR.
Thanks!

Implement org.freedesktop.DBus.Properties

  1. Create a structure that implements the following interface:

    type Properties interface {
        Get(iface, property string) (Variant, *Error)
        Set(iface, property string, newv Variant) *Error
        GetAll(iface string) (map[string]Variant, *Error)
    }

    Usage:

    var prop Properties
    // ... 
    conn.Export(prop, "/foo/bar", "org.freedesktop.DBus.Properties")
  2. Find a good way to make the properties available from the Go program (define methods that take/return interface{} instead of Variant? let the user give all properties upon creation or make it possible to modify them at runtime?)

The server.go example is not properly introspectable

The Introspect method is only implemented on the /com/github/guelfey/Demo path so

dbus-send --session --print-reply --dest="com.github.guelfey.Demo" /com/github/guelfey/Demo org.freedesktop.DBus.Introspectable.Introspect

Returns the right xml while the following does not:

dbus-send --session --print-reply --dest="com.github.guelfey.Demo" / org.freedesktop.DBus.Introspectable.Introspect

The right output would be this:

<node>
   <node name="com"/>
</node>

calling /com should return the github node and so on.

I think there is no tool in the introspect package to generate these.

When call NetworkManager there has an failed with "unexpected EOF"

test with this

package dbus

import "testing"

func TestNM(t *testing.T) {
        s, _ := SystemBus()
        var paths []ObjectPath
        s.Object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Settings").Call("org.freedesktop.NetworkManager.Settings.ListConnections", 0).Store(&paths)

        for _, p := range paths {
                o := s.Object("org.freedesktop.NetworkManager", p)
                c := o.Call("org.freedesktop.NetworkManager.Settings.Connection.GetSettings", 0)
                if c.Err != nil {
                        t.Error(c.Err)
                }
        }
}

I can sure whether everyone will failed , but dbus-send or d-feet call this method will be ok.
(and I have 12 connections, two of them is ok, and others is failed)

If you can't find an failed, you can try create more new connections with nm-connection-editor.

--- FAIL: TestNM (0.00 seconds)
nm_test.go:14: dbus: wire format error: unexpected EOF

relation with godbus/dbus repo

Hi, just wondering if this is going to be maintained separately or if additions would go into godbus/dbus moving forward.

conn.Close() may lose outbound messages

Consider the following code that tries to send a signal:

        conn, err := dbus.SystemBusPrivate()
        conn.Auth(nil)
        conn.Hello()
        conn.RequestName(objName, dbus.NameFlagDoNotQueue)
        conn.Emit(objPath, signalName, "")
        conn.Close()
        os.Exit(0)

Even though the code itself looks correct most likely it will not send any signals. Here Emit() does not actually send a message to the bus, it just queues the message to be sent by a separate goroutine. But there is no guarantee that the message will be sent before program terminates.

conn.Close() closes dbus connection but does not synchronize with outWorker(). Out channel may or may not be empty after Close() and so messages may or may not be sent.

The suggested solution is to add synchronization between Close() and outWorker() so that Close() awaits termination of outWorker() and so guarantees that all outbound signals as well as NoReplyExpected calls are sent to the bus.

Should allow multiple calls to Conn.Close()

Calling Conn.Close() multiple time right now crashes with a panic when closing the out channel multiple times. It is typically good form to close a connection when its not used anymore, but the above makes that unsafe, because there are internal callers to Close() that you can't control (for instance on a socket read error due to a remote close). Since those happen in another thread its basically impossible to propely know if closing is safe.

Support transports besides unix

The protocol defines some other transports (most importantly, tcp) that are not implemented.

This issue has a low priority as unix seems to be the only transport that is actually used.

Make Call return a channel

Method calls should return a channel so that the reply can be waited for with select, like net/rpc does. This probably implies adding a new type like Reply that contains the values or an error.

"dbus: authentication failed" with any example

On Fedora 33, building and running any of the examples e.g. list-names.go will fail with

$ ./listnames
Failed to connect to session bus: dbus: authentication failed

There's a usable session bus address

$ echo $DBUS_SESSION_BUS_ADDRESS
unix:path=/run/user/1000/bus

and command-line d-bus operations work

$ dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames
method return time=1629168407.533841 sender=org.freedesktop.DBus -> destination=:1.10056 serial=4294967295 reply_serial=2
   array [
      string "org.freedesktop.DBus"
      .....

so the bus is usable.

SELinux is in permissive mode (unfortunately, due to unrelated issues) so it's not SELinux related.

I don't see any relevant output in dbus-monitor --session when I attempt to auth while it's running.

It's unclear why this is happening. I'll look into it, but wanted to file this now so others with a similar issue can find it.

Move introspection stuff to a sub-package

It's probably just a personal opinion, but I find that the introspection structures would better be placed in a sub-package. I feel that it somehow works displaced in the documentation.

Handle introspection requests better

Currently, the introspection data that is returned on the "server" side is generated partly from the methods of the given value and partly from an additional parameter containing the rest of the information. This should be fixed in that all introspection data should either be completely generated from structure tags (which would imply that only structs can be exported) or should be completely taken care of by the user.

Make struct-exports customizable

Instead of just using the dbus-tag to omit struct-values from being exported, it could be used (like in encoding/json) to specify the name to export.

Bytestrings (ay)

Hi,

I'm the creator of pydbus, DBus bindings for Python. I've stumbled upon the case of bytestrings - ay - which are commonly used to send non-Unicode data over DBus.

Because of the GDBus's API, apps commonly require these strings to be '\0'-terminated. And that's completely unintuitive for high-level languages, and something that requires the user to read API docs.

I'm thinking about solving the problem automatically, and I see two solutions:

  1. Auto-append and auto-strip the last character of "ay"s; [EDIT: impossible, some APIs use not-terminated strings]
  2. Decree (how?) that GDBus API is wrong, and strings sent over the wire should not be \0-terminated.
  3. [EDIT:] Create a new DBus annotation meaning "All "ay"s in the arguments of this method/signal are \0-terminated bytestrings" - and auto-append/auto-strip \0 if it's present.

Whatever we choose, the solution should be agreed upon by authors of bindings for all languages. That's why I'm here.

Do you have any experience with "ay"-encoded bytestrings?

Relevant discussion: LEW21/pydbus#27

May be shouldn't auto invoke Conn.inWoker.

There is an problem when invoke Conn.inWoker before an dbus object has be exported.

If objectpath A is exported after invoked Conn.inWoker then bus message to objectpath A will be discarded before objectpath A is exported. (I think this is normal and only way now)

And this scene will happen when an dbus serivce is launched by dbus-daemon (service file) caused application freeze (wait dbus timeout).

Maximum depth of container nesting is not checked

From the spec:

Use of variants may not cause a total message depth to be larger than 64, including other container types such as structures.

...

The maximum depth of container type nesting is 32 array type codes and 32 open parentheses.

conn.Close() panics

conn.Close() closes the transport corresponding to the connection. After that inWorker() will see EOF and will try to close the connection again. This then leads to attempt to close closed channel.

$ cat bug.go
package main

import (
        "time"

        dbus "github.com/guelfey/go.dbus"
)

func main() {
        conn, _ := dbus.SessionBusPrivate()
        conn.Auth(nil)
        conn.Hello()
        conn.RequestName("com.github.guelfey.Demo", dbus.NameFlagDoNotQueue)
        conn.Close()
        time.Sleep(1 * time.Second)
}
$ go run bug.go
panic: close of closed channel

goroutine 6 [running]:
github.com/guelfey/go%2edbus.(*Conn).Close(0x4c2080010e0, 0x0, 0x0)
        github.com/guelfey/go.dbus/conn.go:178 +0x62
github.com/guelfey/go%2edbus.(*Conn).inWorker(0x4c2080010e0)
        github.com/guelfey/go.dbus/conn.go:334 +0x10be
created by github.com/guelfey/go%2edbus.(*Conn).Auth
        github.com/guelfey/go.dbus/auth.go:120 +0xecd

introspect: Add some more stuff

Useful things:

  • Function that returns the methods (as a []Method) of some value
  • Constants / variables that hold the introspection data of an Introspectable
    • Add this automatically on call to NewIntrospectable if it's not present yet?
  • ...

Maximum message size is not checked

From the spec:

The maximum length of a message, including header, header alignment padding, and body is 2 to the 27th power or 134217728. Implementations must not send or accept messages exceeding this size.

Support passing sender to method call

It would be nice if the sender could be passed to a method call if a user wants to. A new type Sender string could be introduced which when found in a method signature would receive the sender of the message.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.