godbus / dbus

Native Go bindings for D-Bus
BSD 2-Clause "Simplified" License
959 stars 222 forks source link

Error org.freedesktop.DBus.Error.UnknownMethod: Unknown / invalid method 'Notify' #370

Open SchrodingersNeko749 opened 1 year ago

SchrodingersNeko749 commented 1 year ago

I am trying to make a notification server with godbus. I am following https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html to implement it. I have also used _example/server.go in godbus repo as you might notice in my server code provided below. Here is the server code:

package main

import (
    "fmt"
    "os"

    "github.com/godbus/dbus/v5"
    "github.com/godbus/dbus/v5/introspect"
)

const xml = `
<node>
    <interface name="org.freedesktop.Notifications">
        <method name="Notify">
            <arg direction="in" type="s"/>
            <arg direction="in" type="u"/>
            <arg direction="in" type="s"/>
            <arg direction="in" type="s"/>
            <arg direction="in" type="s"/>
            <arg direction="in" type="as"/>
            <arg direction="in" type="a{sv}"/>
            <arg direction="in" type="i"/>
            <arg direction="out" type="u"/>
        </method>

        <method name="GetCapabilities">
            <arg direction="out" type="as"/>
        </method>

        <method name="GetServerInformation">
            <arg direction="out" type="s"/>
            <arg direction="out" type="s"/>
            <arg direction="out" type="s"/>
            <arg direction="out" type="s"/>
        </method>

        <method name="CloseNotification">
            <arg direction="in" type="u"/>
        </method>

        <signal name="NotificationClosed">
            <arg type="u" name="id"/>
            <arg type="u" name="reason"/>
        </signal>
    </interface>` + introspect.IntrospectDataString + `</node> `

type NotificationServer struct {
}

func (s *NotificationServer) Notify(appName string, replacesID uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) (uint32, *dbus.Error) {
    fmt.Printf("New notification: %s\n", body)
    return 0, nil
}

func (s *NotificationServer) GetCapabilities() ([]string, *dbus.Error) {
    return []string{"action-icons", "actions", "body", "body-hyperlinks", "body-images", "body-markup", "icon-multi", "icon-static", "persistence", "sound"}, nil
}

func (s *NotificationServer) GetServerInformation() (string, string, string, string, *dbus.Error) {
    return "antarctica", "antarctica.com", "1.0", "1.2", nil
}

func (s *NotificationServer) CloseNotification(id uint32) *dbus.Error {
    s.NotificationClosed(id, 0)
    return nil
}
func (s *NotificationServer) NotificationClosed(id, reason uint32) {

}

func main() {
    conn, err := dbus.ConnectSessionBus()
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    reply, err := conn.RequestName("com.antarctica.notification",
        dbus.NameFlagDoNotQueue)
    if err != nil {
        panic(err)
    }

    if reply != dbus.RequestNameReplyPrimaryOwner {
        fmt.Fprintln(os.Stderr, "name already taken")
        os.Exit(1)
    }
    server := NotificationServer{}
    conn.Export(server, "/org/freedesktop/Notifications", "org.freedesktop.Notifications")
    conn.Export(introspect.Introspectable(xml), "/org/freedesktop/Notifications", "org.freedesktop.DBus.Introspectable")
    fmt.Println("Listening on com.antarctica.notification / /com/antarctica/notification ...")
    select {}
}

Now the problem is that eventho the introspect xml is accessible to client:

$ gdbus introspect --session --dest com.antarctica.notification --object-path /org/freedesktop/Notifications --xml
> returns xml

I cant use org.freedesktop.Notifications methods that i wrote in my server code. forexample Notify is Unknown/Invalid and this is repeated for each method:

$ dbus-send --session --print-reply=literal --dest=com.antarctica.notification /org/freedesktop/Notifications org.freedesktop.Notifications.Notify
> Error org.freedesktop.DBus.Error.UnknownMethod: Unknown / invalid method 'Notify'

in qdbusviewer also it says "Unable to find method Notify on path /org/freedesktop/Notifications in interface org.freedesktop.Notifications" note that: 1.dbus is up and its working fine 2.my server is running 3.i tried restarting dbus service and my computer as well 4.i think that the bug has something to do with the introspectable xml in org.freedesktop.DBus.Introspectable not pointing to my NotificationServer struct therefore not finding my methods. Qdbusviewer output looks like this:

image

miccoli commented 11 months ago

4.i think that the bug has something to do with the introspectable xml in org.freedesktop.DBus.Introspectable not pointing to my NotificationServer struct therefore not finding my methods.

Providing introspection data is, as far I understand, completely optional. A DBus service should work perfectly fine also if it does not provide the org.freedesktop.DBus.Introspectable interface.

In your specific case I suspect the problem is simply that the call signature from your dbus-send invocation is different from the one provided by NotificationServer.Notify implementation so that the method lookup fails.

In fact this error is generated whenever the method lookup fails: https://github.com/godbus/dbus/blob/76236955d466b078d82dcb16b7cf1dcf40ac25df/export.go#L182-L186