Skype 通过 DBus API 返回空的 CHATMESSAGES 结果

Skype returning empty CHATMESSAGES results through the DBus API

我正在尝试使用 Skype 的 DBus API 来检索我与联系人交换的消息列表(消息 ID)。但是,SEARCH CHATMESSAGES <target>(协议 >= 3)和 SEARCH MESSAGES <target>(协议 < 3)命令 return 都意外为空结果。

这里是我与 API 的一些交流的痕迹。我使用d-feet发送我的请求,但是我从我自己的程序发送请求的结果是完全一样的。

跟踪:

-> NAME dfeet
<- OK
-> PROTOCOL 8
<- PROTOCOL 8
-> SEARCH CHATMESSAGES mycontact
<- 

另外两个 SEARCH 命令也会发生同样的事情:

此外,当我尝试根据聊天 ID 请求消息列表时,我也得到一个空结果:GET CHAT <chat_id> GETMESSAGES

但是,SEARCH FRIENDSSEARCH CALLSSEARCH ACTIVECHATS 等命令工作得很好,return 他们的 ID 列表(联系人 ID、呼叫 ID 或聊天 ID)如预期。

可能还值得注意的是,无论我与他们交换了多少消息,所有联系人都会发生这种情况(起初我认为可能涉及的消息太多,但无论我向联系人发送了 3 条还是数千条消息,结果都是一样的。

对于这些请求,有什么可以解释为什么我通过 DBus 得到这些空响应吗?

当 Skype 的回复太重时,Skype 将不会使用 Invoke 的 return 值。 事实上,当 Skype 的数据太多时在请求后准备和传输,它会自动 return 向 Invoke 调用发送一个空字符串。 真实、沉重 回复然后由 Skype 异步准备,客户端程序必须准备好在它最终到达时接收它。

无论何时通过 DBus 与 Skype 通信,您的应用程序都必须充当客户端(调用 Invoke)和服务器(提供 DBus 对象供 Skype 访问)。这个设计有点出乎意料(我想我们可以就它的质量争论不休),但这是它需要你做的:

  1. 使您的程序成为 DBus "server"(提供要到达的对象)。通过你的总线名称到 Skype,注册一个名为 /com/Skype/Client 的对象路径,实现 com.Skype.API.Client 接口。
  2. 为此接口的唯一方法准备消息处理程序:Notify(s)。这是 Skype 将尝试调用的方法,以便向你发送对你之前的请求之一的重回复。
  3. 编写您自己的机制,使您的 Invoke 请求与稍后作为答复传入的异步 Notify 消息相匹配。

对象的创建可以通过dbus_connection_register_object_path来完成,其参数为:

  • 表示您的总线名称的 DBusConnection 结构。
  • 您正在注册的对象路径,这里/com/Skype/Client
  • table 个消息处理程序 (DBusObjectPathVTable) 用于处理所有传入请求。
  • 调用这些处理程序时要发送给它们的数据。 这是附加数据,不是收到的实际消息,因为您只是在此处设置处理程序。

例如...

DBusHandlerResult notify_handler(DBusConnection *connection, 
                                DBusMessage *message, 
                                void *user_data){
    return DBUS_HANDLER_RESULT_HANDLED;
}

void unregister_handler(DBusConnection *connection, 
                        void *user_data){}

DBusObjectPathVTable vtable = {
    unregister_handler,
    message_handler,
    NULL
};

if(!dbus_connection_register_object_path(connection,
                                         "/com/Skype/Client",
                                         &vtable, NULL)){
    // Error...
}

请注意,这只是一个对象的定义。为了在 Notify 调用上实际 挂钩 ,您必须 select()DBusWatch 文件描述符上,并分派传入的 DBusMessage 以便调用您的消息处理程序。

如果您正在使用其他绑定,您可能会发现设置对象和开始作为客户端应用程序工作的速度快得多的方法。参见: