Use delegates + object storage instead of listener objects

This commit is contained in:
fiaxh 2017-03-11 23:04:58 +01:00
parent 0ea4ac7e20
commit f40a34bdc1
18 changed files with 252 additions and 352 deletions

View File

@ -73,13 +73,6 @@ public class AvatarManager : StreamInteractionModule, Object {
}
}
private class PublishResponseListenerImpl : Object {
public void on_success(Core.XmppStream stream) {
}
public void on_error(Core.XmppStream stream) { }
}
public static AvatarManager? get_instance(StreamInteractor stream_interaction) {
return (AvatarManager) stream_interaction.get_module(id);
}

View File

@ -28,7 +28,7 @@ public class MucManager : StreamInteractionModule, Object {
public void join(Account account, Jid jid, string nick, string? password = null) {
Core.XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).enter(stream, jid.bare_jid.to_string(), nick, password, new MucEnterListenerImpl(this, jid, nick, account));
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).enter(stream, jid.bare_jid.to_string(), nick, password, on_groupchat_joined, () => {}, Quadruple.create(this, jid, nick, account));
}
public void part(Account account, Jid jid) {
@ -73,10 +73,10 @@ public class MucManager : StreamInteractionModule, Object {
return is_groupchat(jid.bare_jid, account) && jid.is_full();
}
public void get_bookmarks(Account account, Xep.Bookmarks.ConferencesRetrieveResponseListener listener) {
public void get_bookmarks(Account account, Xep.Bookmarks.Module.OnResult listener, Object? store) {
Core.XmppStream? stream = stream_interactor.get_stream(account);
if (stream != null) {
stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, listener);
stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, listener, store);
}
}
@ -158,7 +158,7 @@ public class MucManager : StreamInteractionModule, Object {
private void on_stream_negotiated(Account account) {
Core.XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, new BookmarksRetrieveResponseListener(this, account));
if (stream != null) stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, join_autojoin_conferences, Tuple.create(this, account));
}
private void on_pre_message_received(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation) {
@ -184,41 +184,26 @@ public class MucManager : StreamInteractionModule, Object {
}
}
private class BookmarksRetrieveResponseListener : Xep.Bookmarks.ConferencesRetrieveResponseListener, Object {
MucManager outer = null;
Account account = null;
private static void on_groupchat_joined(Core.XmppStream stream, Object? store) {
Quadruple<MucManager, Jid, string, Account> quadruple = store as Quadruple<MucManager, Jid, string, Account>;
MucManager outer = quadruple.a;
Jid jid = quadruple.b;
string nick = quadruple.c;
Account account = quadruple.d;
outer.groupchat_joined(account, jid, nick);
}
public BookmarksRetrieveResponseListener(MucManager outer, Account account) {
this.outer = outer;
this.account = account;
}
public void on_result(Core.XmppStream stream, ArrayList<Xep.Bookmarks.Conference> conferences) {
foreach (Xep.Bookmarks.Conference bookmark in conferences) {
Jid jid = new Jid(bookmark.jid);
outer.conference_bookmarks[jid] = bookmark;
if (bookmark.autojoin) {
outer.join(account, jid, bookmark.nick);
}
private static void join_autojoin_conferences(Core.XmppStream stream, ArrayList<Xep.Bookmarks.Conference> conferences, Object? o) {
Tuple<MucManager, Account> tuple = o as Tuple<MucManager, Account>;
MucManager outer = tuple.a;
Account account = tuple.b;
foreach (Xep.Bookmarks.Conference bookmark in conferences) {
Jid jid = new Jid(bookmark.jid);
outer.conference_bookmarks[jid] = bookmark;
if (bookmark.autojoin) {
outer.join(account, jid, bookmark.nick);
}
}
}
private class MucEnterListenerImpl : Xep.Muc.MucEnterListener, Object { // TODO
private MucManager outer;
private Jid jid;
private string nick;
private Account account;
public MucEnterListenerImpl(MucManager outer, Jid jid, string nick, Account account) {
this.outer = outer;
this.jid = jid;
this.nick = nick;
this.account = account;
}
public void on_success() {
outer.groupchat_joined(account, jid, nick);
}
public void on_error(Xep.Muc.MucEnterError error) { }
}
}
}

View File

@ -29,7 +29,7 @@ protected class ConferenceList : FilterableList {
});
foreach (Account account in stream_interactor.get_accounts()) {
MucManager.get_instance(stream_interactor).get_bookmarks(account, new BookmarksListener(this, stream_interactor, account));
MucManager.get_instance(stream_interactor).get_bookmarks(account, on_conference_bookmarks_received, Tuple.create(this, account));
}
}
@ -42,18 +42,12 @@ protected class ConferenceList : FilterableList {
}
}
private class BookmarksListener : Xep.Bookmarks.ConferencesRetrieveResponseListener, Object {
ConferenceList outer;
Account account;
public BookmarksListener(ConferenceList outer, StreamInteractor stream_interactor, Account account) {
this.outer = outer;
this.account = account;
}
public void on_result(Core.XmppStream stream, ArrayList<Xep.Bookmarks.Conference> conferences) {
outer.lists[account] = conferences;
Idle.add(() => { outer.refresh_conferences(); return false; });
}
private static void on_conference_bookmarks_received(Core.XmppStream stream, ArrayList<Xep.Bookmarks.Conference> conferences, Object? o) {
Tuple<ConferenceList, Account> tuple = o as Tuple<ConferenceList, Account>;
ConferenceList list = tuple.a;
Account account = tuple.b;
list.lists[account] = conferences;
Idle.add(() => { list.refresh_conferences(); return false; });
}
private void header(ListBoxRow row, ListBoxRow? before_row) {

View File

@ -33,19 +33,13 @@ namespace Xmpp.Bind {
var bind = stream.features.get_subnode("bind", NS_URI);
if (bind != null) {
var flag = new Flag();
StanzaNode bind_node = new StanzaNode.build("bind", NS_URI).add_self_xmlns()
.put_node(new StanzaNode.build("resource", NS_URI).put_node(new StanzaNode.text(requested_resource)));
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, new Iq.Stanza.set(bind_node), new IqResponseListenerImpl());
StanzaNode bind_node = new StanzaNode.build("bind", NS_URI).add_self_xmlns();
bind_node.put_node(new StanzaNode.build("resource", NS_URI).put_node(new StanzaNode.text(requested_resource)));
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, new Iq.Stanza.set(bind_node), on_bind_response);
stream.add_flag(flag);
}
}
private class IqResponseListenerImpl : Iq.ResponseListener, Object {
public void on_result(XmppStream stream, Iq.Stanza iq) {
stream.get_module(Bind.Module.IDENTITY).iq_response_stanza(stream, iq);
}
}
public override void attach(XmppStream stream) {
Iq.Module.require(stream);
stream.received_features_node.connect(this.received_features_node);
@ -69,6 +63,10 @@ namespace Xmpp.Bind {
public override string get_ns() { return NS_URI; }
public override string get_id() { return ID; }
private static void on_bind_response(XmppStream stream, Iq.Stanza iq) {
stream.get_module(Bind.Module.IDENTITY).iq_response_stanza(stream, iq);
}
}
public class Flag : XmppStreamFlag {

View File

@ -12,14 +12,15 @@ namespace Xmpp.Iq {
private HashMap<string, ResponseListener> responseListeners = new HashMap<string, ResponseListener>();
private HashMap<string, ArrayList<Handler>> namespaceRegistrants = new HashMap<string, ArrayList<Handler>>();
public void send_iq(XmppStream stream, Iq.Stanza iq, ResponseListener? listener = null) {
[CCode (has_target = false)] public delegate void OnResult(XmppStream stream, Iq.Stanza iq, Object reference);
public void send_iq(XmppStream stream, Iq.Stanza iq, OnResult? listener = null, Object? reference = null) {
try {
stream.write(iq.stanza);
} catch (IOStreamError e) {
print(@"$(e.message)\n");
}
if (listener != null) {
responseListeners.set(iq.id, listener);
responseListeners[iq.id] = new ResponseListener(listener, reference);
}
}
@ -56,7 +57,7 @@ namespace Xmpp.Iq {
if (responseListeners.has_key(iq.id)) {
ResponseListener? listener = responseListeners.get(iq.id);
if (listener != null) {
listener.on_result(stream, iq);
listener.on_result(stream, iq, listener.reference);
}
responseListeners.unset(iq.id);
}
@ -77,6 +78,16 @@ namespace Xmpp.Iq {
}
}
}
private class ResponseListener {
public OnResult on_result { get; private set; }
public Object? reference { get; private set; }
public ResponseListener(OnResult on_result, Object? reference = null) {
this.on_result = on_result;
this.reference = reference;
}
}
}
public interface Handler : Object {
@ -84,7 +95,4 @@ namespace Xmpp.Iq {
public abstract void on_iq_set(XmppStream stream, Iq.Stanza iq);
}
public interface ResponseListener : Object {
public abstract void on_result(XmppStream stream, Iq.Stanza iq);
}
}

View File

@ -95,20 +95,18 @@ namespace Xmpp.Roster {
Flag.get_flag(stream).iq_id = random_uuid();
StanzaNode query_node = new StanzaNode.build("query", NS_URI).add_self_xmlns();
Iq.Stanza iq = new Iq.Stanza.get(query_node, Flag.get_flag(stream).iq_id);
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, new IqResponseListenerImpl());
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, on_roster_get_received);
}
private class IqResponseListenerImpl : Iq.ResponseListener, Object {
public void on_result(XmppStream stream, Iq.Stanza iq) {
Flag flag = Flag.get_flag(stream);
if (iq.id == flag.iq_id) {
StanzaNode? query_node = iq.stanza.get_subnode("query", NS_URI);
foreach (StanzaNode item_node in query_node.sub_nodes) {
Item item = new Item.from_stanza_node(item_node);
flag.roster_items[item.jid] = item;
}
stream.get_module(Module.IDENTITY).received_roster(stream, flag.roster_items.values);
private static void on_roster_get_received(XmppStream stream, Iq.Stanza iq) {
Flag flag = Flag.get_flag(stream);
if (iq.id == flag.iq_id) {
StanzaNode? query_node = iq.stanza.get_subnode("query", NS_URI);
foreach (StanzaNode item_node in query_node.sub_nodes) {
Item item = new Item.from_stanza_node(item_node);
flag.roster_items[item.jid] = item;
}
stream.get_module(Module.IDENTITY).received_roster(stream, flag.roster_items.values);
}
}
@ -116,7 +114,7 @@ namespace Xmpp.Roster {
StanzaNode query_node = new StanzaNode.build("query", NS_URI).add_self_xmlns()
.put_node(roster_item.stanza_node);
Iq.Stanza iq = new Iq.Stanza.set(query_node);
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, null);
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq);
}
}
}

View File

@ -18,4 +18,44 @@ namespace Xmpp {
UUID.unparse_upper(rand, str);
return (string) str;
}
public class Tuple<A,B> : Object {
public A a { get; private set; }
public B b { get; private set; }
public Tuple(A a, B b) {
this.a = a;
this.b = b;
}
public static Tuple<A,B> create<A,B>(A a, B b) {
return new Tuple<A,B>(a,b);
}
}
public class Triple<A,B,C> : Tuple<A,B> {
public C c { get; private set; }
public Triple(A a, B b, C c) {
base(a, b);
this.c = c;
}
public static new Triple<A,B,C> create<A,B,C>(A a, B b, C c) {
return new Triple<A,B,C>(a, b, c);
}
}
public class Quadruple<A,B,C,D> : Triple<A,B,C> {
public D d { get; private set; }
public Quadruple(A a, B b, C c, D d) {
base (a, b, c);
this.d = d;
}
public static new Quadruple<A,B,C,D> create<A,B,C,D>(A a, B b, C c, D d) {
return new Quadruple<A,B,C,D>(a, b, c, d);
}
}
}

View File

@ -29,40 +29,18 @@ namespace Xmpp.Xep.ServiceDiscovery {
identities.add(new Identity(category, type, name));
}
public void request_info(XmppStream stream, string jid, InfoResponseListener response_listener) {
[CCode (has_target = false)] public delegate void OnInfoResult(XmppStream stream, InfoResult query_result, Object? store);
public void request_info(XmppStream stream, string jid, OnInfoResult listener, Object? store) {
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_INFO).add_self_xmlns());
iq.to = jid;
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, new IqInfoResponseListener(response_listener));
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, on_request_info_response, Tuple.create(listener, store));
}
private class IqInfoResponseListener : Iq.ResponseListener, Object {
InfoResponseListener response_listener;
public IqInfoResponseListener(InfoResponseListener response_listener) {
this.response_listener = response_listener;
}
public void on_result(XmppStream stream, Iq.Stanza iq) {
InfoResult? result = InfoResult.create_from_iq(iq);
if (result != null) {
Flag.get_flag(stream).set_entitiy_features(iq.from, result.features);
response_listener.on_result(stream, result);
} else {
response_listener.on_error(stream, iq);
}
}
}
public void request_items(XmppStream stream, string jid, ItemsResponseListener response_listener) {
[CCode (has_target = false)] public delegate void OnItemsResult(XmppStream stream, ItemsResult query_result);
public void request_items(XmppStream stream, string jid, OnItemsResult listener, Object? store) {
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_ITEMS).add_self_xmlns());
iq.to = jid;
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, new IqItemsResponseListener(response_listener));
}
private class IqItemsResponseListener : Iq.ResponseListener, Object {
ItemsResponseListener response_listener;
public IqItemsResponseListener(ItemsResponseListener response_listener) { this.response_listener = response_listener; }
public void on_result(XmppStream stream, Iq.Stanza iq) {
//response_listener.on_result(stream, new ServiceDiscoveryItemsResult.from_iq(iq));
}
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq);
}
public void on_iq_get(XmppStream stream, Iq.Stanza iq) {
@ -90,11 +68,21 @@ namespace Xmpp.Xep.ServiceDiscovery {
public override string get_ns() { return NS_URI; }
public override string get_id() { return ID; }
private static void on_request_info_response(XmppStream stream, Iq.Stanza iq, Object o) {
Tuple<OnInfoResult, Object> tuple = o as Tuple<OnInfoResult, Object>;
OnInfoResult on_result = tuple.a;
InfoResult? result = InfoResult.create_from_iq(iq);
if (result != null) {
Flag.get_flag(stream).set_entitiy_features(iq.from, result.features);
on_result(stream, result, tuple.b);
}
}
private void send_query_result(XmppStream stream, Iq.Stanza iq_request) {
InfoResult query_result = new ServiceDiscovery.InfoResult(iq_request);
query_result.features = Flag.get_flag(stream).features;
query_result.identities = identities;
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, query_result.iq, null);
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, query_result.iq);
}
}
@ -121,14 +109,4 @@ namespace Xmpp.Xep.ServiceDiscovery {
this.node = node;
}
}
public interface InfoResponseListener : Object {
public abstract void on_result(XmppStream stream, InfoResult query_result);
public void on_error(XmppStream stream, Iq.Stanza iq) { }
}
public interface ItemsResponseListener : Object {
public abstract void on_result(XmppStream stream, ItemsResult query_result);
public void on_error(XmppStream stream, Iq.Stanza iq) { }
}
}

View File

@ -7,7 +7,7 @@ namespace Xmpp.Xep.Muc {
public class Flag : XmppStreamFlag {
public const string ID = "muc";
private HashMap<string, MucEnterListener> enter_listeners = new HashMap<string, MucEnterListener>();
private HashMap<string, ListenerHolder> enter_listeners = new HashMap<string, ListenerHolder>();
private HashMap<string, string> enter_ids = new HashMap<string, string>();
private HashMap<string, string> own_nicks = new HashMap<string, string>();
private HashMap<string, string> subjects = new HashMap<string, string>();
@ -32,7 +32,7 @@ public class Flag : XmppStreamFlag {
public string? get_enter_id(string bare_jid) { return enter_ids[bare_jid]; }
public MucEnterListener? get_enter_listener(string bare_jid) { return enter_listeners[bare_jid]; }
public ListenerHolder? get_enter_listener(string bare_jid) { return enter_listeners[bare_jid]; }
public bool is_muc(string jid) { return own_nicks[jid] != null; }
@ -51,7 +51,7 @@ public class Flag : XmppStreamFlag {
subjects_by[bare_jid] = full_jid;
}
public void start_muc_enter(string bare_jid, string presence_id, MucEnterListener listener) {
public void start_muc_enter(string bare_jid, string presence_id, ListenerHolder listener) {
enter_listeners[bare_jid] = listener;
enter_ids[bare_jid] = presence_id;
}

View File

@ -37,7 +37,7 @@ public class Module : XmppStreamModule {
public signal void received_occupant_role(XmppStream stream, string jid, string? role);
public signal void subject_set(XmppStream stream, string subject, string jid);
public void enter(XmppStream stream, string bare_jid, string nick, string? password, MucEnterListener listener) {
public void enter(XmppStream stream, string bare_jid, string nick, string? password, ListenerHolder.OnSuccess success_listener, ListenerHolder.OnError error_listener, Object? store) {
Presence.Stanza presence = new Presence.Stanza();
presence.to = bare_jid + "/" + nick;
StanzaNode x_node = new StanzaNode.build("x", NS_URI).add_self_xmlns();
@ -46,7 +46,7 @@ public class Module : XmppStreamModule {
}
presence.stanza.put_node(x_node);
Muc.Flag.get_flag(stream).start_muc_enter(bare_jid, presence.id, listener);
Muc.Flag.get_flag(stream).start_muc_enter(bare_jid, presence.id, new ListenerHolder(success_listener, error_listener, store));
stream.get_module(Presence.Module.IDENTITY).send_presence(stream, presence);
}
@ -130,20 +130,22 @@ public class Module : XmppStreamModule {
string bare_jid = get_bare_jid(presence.from);
ErrorStanza? error_stanza = presence.get_error();
if (flag.get_enter_id(bare_jid) == error_stanza.original_id) {
MucEnterListener listener = flag.get_enter_listener(bare_jid);
ListenerHolder listener = flag.get_enter_listener(bare_jid);
MucEnterError? error = null;
if (error_stanza.condition == ErrorStanza.CONDITION_NOT_AUTHORIZED && ErrorStanza.TYPE_AUTH == error_stanza.type_) {
listener.on_error(MucEnterError.PASSWORD_REQUIRED);
error = MucEnterError.PASSWORD_REQUIRED;
} else if (ErrorStanza.CONDITION_REGISTRATION_REQUIRED == error_stanza.condition && ErrorStanza.TYPE_AUTH == error_stanza.type_) {
listener.on_error(MucEnterError.NOT_IN_MEMBER_LIST);
error = MucEnterError.NOT_IN_MEMBER_LIST;
} else if (ErrorStanza.CONDITION_FORBIDDEN == error_stanza.condition && ErrorStanza.TYPE_AUTH == error_stanza.type_) {
listener.on_error(MucEnterError.BANNED);
error = MucEnterError.BANNED;
} else if (ErrorStanza.CONDITION_CONFLICT == error_stanza.condition && ErrorStanza.TYPE_CANCEL == error_stanza.type_) {
listener.on_error(MucEnterError.NICK_CONFLICT);
error = MucEnterError.NICK_CONFLICT;
} else if (ErrorStanza.CONDITION_SERVICE_UNAVAILABLE == error_stanza.condition && ErrorStanza.TYPE_WAIT == error_stanza.type_) {
listener.on_error(MucEnterError.OCCUPANT_LIMIT_REACHED);
error = MucEnterError.OCCUPANT_LIMIT_REACHED;
} else if (ErrorStanza.CONDITION_ITEM_NOT_FOUND == error_stanza.condition && ErrorStanza.TYPE_CANCEL == error_stanza.type_) {
listener.on_error(MucEnterError.ROOM_DOESNT_EXIST);
error = MucEnterError.ROOM_DOESNT_EXIST;
}
if (error == null) listener.on_error(stream, error, listener.reference);
flag.finish_muc_enter(bare_jid);
}
}
@ -157,7 +159,8 @@ public class Module : XmppStreamModule {
ArrayList<int> status_codes = get_status_codes(x_node);
if (status_codes.contains(StatusCode.SELF_PRESENCE)) {
string bare_jid = get_bare_jid(presence.from);
flag.get_enter_listener(bare_jid).on_success();
ListenerHolder listener = flag.get_enter_listener(bare_jid);
listener.on_success(stream, listener.reference);
flag.finish_muc_enter(bare_jid, get_resource_part(presence.from));
}
string? affiliation = x_node["item", "affiliation"].val;
@ -233,9 +236,17 @@ public enum StatusCode {
REMOVED_SHUTDOWN = 332
}
public interface MucEnterListener : Object {
public abstract void on_success();
public abstract void on_error(MucEnterError error);
public class ListenerHolder {
[CCode (has_target = false)] public delegate void OnSuccess(XmppStream stream, Object? store);
public OnSuccess on_success { get; private set; }
[CCode (has_target = false)] public delegate void OnError(XmppStream stream, MucEnterError error, Object? store);
public OnError on_error { get; private set; }
public Object? reference { get; private set; }
public ListenerHolder(OnSuccess on_success, OnError on_error, Object? reference = null) {
this.on_success = on_success;
this.reference = reference;
}
}
}

View File

@ -2,7 +2,7 @@ using Xmpp.Core;
namespace Xmpp.Xep.Bookmarks {
public class Conference {
public class Conference : Object {
public const string ATTRIBUTE_AUTOJOIN = "autojoin";
public const string ATTRIBUTE_JID = "jid";

View File

@ -11,9 +11,16 @@ public class Module : XmppStreamModule {
public signal void conferences_updated(XmppStream stream, ArrayList<Conference> conferences);
public void get_conferences(XmppStream stream, ConferencesRetrieveResponseListener response_listener) {
[CCode (has_target = false)] public delegate void OnResult(XmppStream stream, ArrayList<Conference> conferences, Object? reference);
public void get_conferences(XmppStream stream, OnResult listener, Object? store) {
StanzaNode get_node = new StanzaNode.build("storage", NS_URI).add_self_xmlns();
stream.get_module(PrivateXmlStorage.Module.IDENTITY).retrieve(stream, get_node, new GetConferences(response_listener));
stream.get_module(PrivateXmlStorage.Module.IDENTITY).retrieve(stream, get_node, on_conferences_received, Tuple.create(listener, store));
}
private static void on_conferences_received(XmppStream stream, StanzaNode node, Object? o) {
Tuple<OnResult, Object?> tuple = o as Tuple<OnResult, Object?>;
OnResult on_result = tuple.a;
on_result(stream, get_conferences_from_stanza(node), tuple.b);
}
public void set_conferences(XmppStream stream, ArrayList<Conference> conferences) {
@ -21,89 +28,58 @@ public class Module : XmppStreamModule {
foreach (Conference conference in conferences) {
storage_node.put_node(conference.stanza_node);
}
stream.get_module(PrivateXmlStorage.Module.IDENTITY).store(stream, storage_node, new StoreResponseListenerImpl(conferences));
stream.get_module(PrivateXmlStorage.Module.IDENTITY).store(stream, storage_node, on_set_conferences_response, conferences);
}
private class StoreResponseListenerImpl : PrivateXmlStorage.StoreResponseListener, Object {
ArrayList<Conference> conferences;
public StoreResponseListenerImpl(ArrayList<Conference> conferences) {
this.conferences = conferences;
}
public void on_success(XmppStream stream) {
stream.get_module(Module.IDENTITY).conferences_updated(stream, conferences);
}
private static void on_set_conferences_response(XmppStream stream, Object? o) {
ArrayList<Conference> conferences = o as ArrayList<Conference>;
stream.get_module(Module.IDENTITY).conferences_updated(stream, conferences);
}
public void add_conference(XmppStream stream, Conference add) {
get_conferences(stream, new AddConference(add));
get_conferences(stream, on_add_conference_response, add);
}
private static void on_add_conference_response(XmppStream stream, ArrayList<Conference> conferences, Object? o) {
Conference add = o as Conference;
conferences.add(add);
stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
}
public void replace_conference(XmppStream stream, Conference was, Conference modified) {
get_conferences(stream, new ModifyConference(was, modified));
get_conferences(stream, on_replace_conference_response, Tuple.create(was, modified));
}
private static void on_replace_conference_response(XmppStream stream, ArrayList<Conference> conferences, Object? o) {
Tuple<Conference, Conference> tuple = o as Tuple<Conference, Conference>;
Conference was = tuple.a;
Conference modified = tuple.b;
foreach (Conference conference in conferences) {
if (conference.name == was.name && conference.jid == was.jid && conference.autojoin == was.autojoin) {
conference.autojoin = modified.autojoin;
conference.name = modified.name;
conference.jid = modified.jid;
break;
}
}
stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
}
public void remove_conference(XmppStream stream, Conference conference) {
get_conferences(stream, new RemoveConference(conference));
get_conferences(stream, on_remove_conference_response, conference);
}
private class GetConferences : PrivateXmlStorage.RetrieveResponseListener, Object {
ConferencesRetrieveResponseListener response_listener;
public GetConferences(ConferencesRetrieveResponseListener response_listener) {
this.response_listener = response_listener;
}
public void on_result(XmppStream stream, StanzaNode node) {
response_listener.on_result(stream, get_conferences_from_stanza(node));
}
}
private class AddConference : ConferencesRetrieveResponseListener, Object {
private Conference conference;
public AddConference(Conference conference) {
this.conference = conference;
}
public void on_result(XmppStream stream, ArrayList<Conference> conferences) {
conferences.add(conference);
stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
}
}
private class ModifyConference : ConferencesRetrieveResponseListener, Object {
private Conference was;
private Conference modified;
public ModifyConference(Conference was, Conference modified) {
this.was = was;
this.modified = modified;
}
public void on_result(XmppStream stream, ArrayList<Conference> conferences) {
foreach (Conference conference in conferences) {
if (conference.name == was.name && conference.jid == was.jid && conference.autojoin == was.autojoin) {
conference.autojoin = modified.autojoin;
conference.name = modified.name;
conference.jid = modified.jid;
break;
}
private static void on_remove_conference_response(XmppStream stream, ArrayList<Conference> conferences, Object? o) {
Conference remove = o as Conference;
Conference? rem = null;
foreach (Conference conference in conferences) {
if (conference.name == remove.name && conference.jid == remove.jid && conference.autojoin == remove.autojoin) {
rem = conference;
break;
}
stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
}
}
private class RemoveConference : ConferencesRetrieveResponseListener, Object {
private Conference remove;
public RemoveConference(Conference remove) {
this.remove = remove;
}
public void on_result(XmppStream stream, ArrayList<Conference> conferences) {
Conference? rem = null;
foreach (Conference conference in conferences) {
if (conference.name == remove.name && conference.jid == remove.jid && conference.autojoin == remove.autojoin) {
rem = conference;
}
}
if (rem != null) conferences.remove(rem);
stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
}
if (rem != null) conferences.remove(rem);
stream.get_module(Module.IDENTITY).set_conferences(stream, conferences);
}
public override void attach(XmppStream stream) { }
@ -127,8 +103,4 @@ public class Module : XmppStreamModule {
}
}
public interface ConferencesRetrieveResponseListener : Object {
public abstract void on_result(XmppStream stream, ArrayList<Conference> conferences);
}
}

View File

@ -1,3 +1,5 @@
using Gee;
using Xmpp.Core;
namespace Xmpp.Xep.PrivateXmlStorage {
@ -7,35 +9,18 @@ namespace Xmpp.Xep.PrivateXmlStorage {
public const string ID = "0049_private_xml_storage";
public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, ID);
public void store(XmppStream stream, StanzaNode node, StoreResponseListener listener) {
[CCode (has_target = false)] public delegate void OnSuccess(XmppStream stream, Object? reference);
public void store(XmppStream stream, StanzaNode node, OnSuccess listener, Object? reference) {
StanzaNode queryNode = new StanzaNode.build("query", NS_URI).add_self_xmlns().put_node(node);
Iq.Stanza iq = new Iq.Stanza.set(queryNode);
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, new IqStoreResponse(listener));
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, on_store_response, Tuple.create(listener, reference));
}
private class IqStoreResponse : Iq.ResponseListener, Object {
StoreResponseListener listener;
public IqStoreResponse(StoreResponseListener listener) {
this.listener = listener;
}
public void on_result(XmppStream stream, Iq.Stanza iq) {
listener.on_success(stream);
}
}
public void retrieve(XmppStream stream, StanzaNode node, RetrieveResponseListener responseListener) {
[CCode (has_target = false)] public delegate void OnResponse(XmppStream stream, StanzaNode node, Object? reference);
public void retrieve(XmppStream stream, StanzaNode node, OnResponse listener, Object? reference) {
StanzaNode queryNode = new StanzaNode.build("query", NS_URI).add_self_xmlns().put_node(node);
Iq.Stanza iq = new Iq.Stanza.get(queryNode);
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, new IqRetrieveResponse(responseListener));
}
private class IqRetrieveResponse : Iq.ResponseListener, Object {
RetrieveResponseListener response_listener;
public IqRetrieveResponse(RetrieveResponseListener response_listener) { this.response_listener = response_listener; }
public void on_result(XmppStream stream, Iq.Stanza iq) {
response_listener.on_result(stream, iq.stanza.get_subnode("query", NS_URI));
}
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, on_retrieve_response, Tuple.create(listener, reference));
}
public override void attach(XmppStream stream) {
@ -50,13 +35,15 @@ namespace Xmpp.Xep.PrivateXmlStorage {
public override string get_ns() { return NS_URI; }
public override string get_id() { return ID; }
}
public interface StoreResponseListener : Object {
public abstract void on_success(XmppStream stream);
}
private static void on_store_response(XmppStream stream, Iq.Stanza iq, Object o) {
Tuple<OnSuccess, Object> tuple = o as Tuple<OnSuccess, Object>;
tuple.a(stream, tuple.b);
}
public interface RetrieveResponseListener : Object {
public abstract void on_result(XmppStream stream, StanzaNode stanzaNode);
private static void on_retrieve_response(XmppStream stream, Iq.Stanza iq, Object o) {
Tuple<OnResponse, Object> tuple = o as Tuple<OnResponse, Object>;
tuple.a(stream, iq.stanza.get_subnode("query", NS_URI), tuple.b);
}
}
}

View File

@ -53,32 +53,22 @@ public class Module : XmppStreamModule {
} else {
iq.to = get_bare_jid(presence.from);
}
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, new IqResponseListenerImpl(this, storage, sha1));
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, on_received_vcard);
}
}
private class IqResponseListenerImpl : Iq.ResponseListener, Object {
Module outer;
PixbufStorage storage;
string id;
public IqResponseListenerImpl(Module outer, PixbufStorage storage, string id) {
this.outer = outer;
this.id = id;
this.storage = storage;
}
public void on_result(XmppStream stream, Iq.Stanza iq) {
if (iq.is_error()) return;
StanzaNode? vcard_node = iq.stanza.get_subnode("vCard", NS_URI);
if (vcard_node == null) return;
StanzaNode? photo_node = vcard_node.get_subnode("PHOTO", NS_URI);
if (photo_node == null) return;
StanzaNode? binary_node = photo_node.get_subnode("BINVAL", NS_URI);
if (binary_node == null) return;
string? content = binary_node.get_string_content();
if (content == null) return;
storage.store(id, Base64.decode(content));
outer.received_avatar(stream, iq.from, id);
}
private static void on_received_vcard(XmppStream stream, Iq.Stanza iq) {
if (iq.is_error()) return;
StanzaNode? vcard_node = iq.stanza.get_subnode("vCard", NS_URI);
if (vcard_node == null) return;
StanzaNode? photo_node = vcard_node.get_subnode("PHOTO", NS_URI);
if (photo_node == null) return;
StanzaNode? binary_node = photo_node.get_subnode("BINVAL", NS_URI);
if (binary_node == null) return;
string? content = binary_node.get_string_content();
if (content == null) return;
string sha1 = Checksum.compute_for_data(ChecksumType.SHA1, content.data);
stream.get_module(IDENTITY).received_avatar(stream, iq.from, sha1);
}
}
}

View File

@ -17,23 +17,11 @@ namespace Xmpp.Xep.Pubsub {
event_listeners[node] = new EventListenerDelegate(on_result, reference);
}
public void request(XmppStream stream, string jid, string node, RequestResponseListener listener) { // TODO multiple nodes gehen auch
[CCode (has_target = false)] public delegate void OnResult(XmppStream stream, string jid, string? id, StanzaNode? node, Object? storage);
public void request(XmppStream stream, string jid, string node, OnResult listener, Object? store) { // TODO multiple nodes gehen auch
Iq.Stanza a = new Iq.Stanza.get(new StanzaNode.build("pubsub", NS_URI).add_self_xmlns().put_node(new StanzaNode.build("items", NS_URI).put_attribute("node", node)));
a.to = jid;
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, a, new IqRequestResponseListener(listener));
}
private class IqRequestResponseListener : Iq.ResponseListener, Object {
RequestResponseListener response_listener;
public IqRequestResponseListener(RequestResponseListener response_listener) { this.response_listener = response_listener; }
public void on_result(XmppStream stream, Iq.Stanza iq) {
StanzaNode event_node = iq.stanza.get_subnode("pubsub", NS_URI);
StanzaNode items_node = event_node != null ? event_node.get_subnode("items", NS_URI) : null;
StanzaNode item_node = items_node != null ? items_node.get_subnode("item", NS_URI) : null;
string? node = items_node != null ? items_node.get_attribute("node", NS_URI) : null;
string? id = item_node != null ? item_node.get_attribute("id", NS_URI) : null;
response_listener.on_result(stream, iq.from, id, item_node != null ? item_node.sub_nodes[0] : null);
}
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, a, on_received_request_response, Tuple.create(listener, store));
}
public void publish(XmppStream stream, string? jid, string node_id, string node, string item_id, StanzaNode content) {
@ -47,18 +35,6 @@ namespace Xmpp.Xep.Pubsub {
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, null);
}
private class IqPublishResponseListener : Iq.ResponseListener, Object {
PublishResponseListener response_listener;
public IqPublishResponseListener(PublishResponseListener response_listener) { this.response_listener = response_listener; }
public void on_result(XmppStream stream, Iq.Stanza iq) {
if (iq.is_error()) {
response_listener.on_error(stream);
} else {
response_listener.on_success(stream);
}
}
}
public override void attach(XmppStream stream) {
Iq.Module.require(stream);
Message.Module.require(stream);
@ -87,10 +63,16 @@ namespace Xmpp.Xep.Pubsub {
event_listeners[node].on_result(stream, message.from, id, item_node.sub_nodes[0]);
}
}
}
public interface RequestResponseListener : Object {
public abstract void on_result(XmppStream stream, string jid, string? id, StanzaNode? node);
private static void on_received_request_response(XmppStream stream, Iq.Stanza iq, Object o) {
Tuple<OnResult, Object?> tuple = o as Tuple<OnResult, Object?>;
OnResult on_result = tuple.a;
StanzaNode event_node = iq.stanza.get_subnode("pubsub", NS_URI);
StanzaNode items_node = event_node != null ? event_node.get_subnode("items", NS_URI) : null;
StanzaNode item_node = items_node != null ? items_node.get_subnode("item", NS_URI) : null;
string? id = item_node != null ? item_node.get_attribute("id", NS_URI) : null;
on_result(stream, iq.from, id, item_node != null ? item_node.sub_nodes[0] : null, tuple.b);
}
}
public class EventListenerDelegate {
@ -103,9 +85,4 @@ namespace Xmpp.Xep.Pubsub {
this.reference = reference;
}
}
public interface PublishResponseListener : Object {
public abstract void on_success(XmppStream stream);
public abstract void on_error(XmppStream stream);
}
}

View File

@ -34,17 +34,6 @@ namespace Xmpp.Xep.UserAvatars {
stream.get_module(Pubsub.Module.IDENTITY).publish(stream, null, NS_URI_METADATA, NS_URI_METADATA, sha1, metadata_node);
}
private class PublishResponseListenerImpl : Pubsub.PublishResponseListener, Object {
PublishResponseListener listener;
PublishResponseListenerImpl other;
public PublishResponseListenerImpl(PublishResponseListener listener, PublishResponseListenerImpl other) {
this.listener = listener;
this.other = other;
}
public void on_success(XmppStream stream) { listener.on_success(stream); }
public void on_error(XmppStream stream) { listener.on_error(stream); }
}
public override void attach(XmppStream stream) {
Pubsub.Module.require(stream);
stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NS_URI_METADATA, on_event_result, this);
@ -59,17 +48,7 @@ namespace Xmpp.Xep.UserAvatars {
if (storage.has_image(id)) {
stream.get_module(Module.IDENTITY).received_avatar(stream, jid, id);
} else {
stream.get_module(Pubsub.Module.IDENTITY).request(stream, jid, NS_URI_DATA, new PubsubRequestResponseListenerImpl(storage));
}
}
class PubsubRequestResponseListenerImpl : Pubsub.RequestResponseListener, Object {
PixbufStorage storage;
public PubsubRequestResponseListenerImpl(PixbufStorage storage) { this.storage = storage; }
public void on_result(XmppStream stream, string jid, string? id, StanzaNode? node) {
if (node == null) return;
storage.store(id, Base64.decode(node.get_string_content()));
stream.get_module(Module.IDENTITY).received_avatar(stream, jid, id);
stream.get_module(Pubsub.Module.IDENTITY).request(stream, jid, NS_URI_DATA, on_pubsub_data_response, storage);
}
}
@ -79,10 +58,12 @@ namespace Xmpp.Xep.UserAvatars {
public override string get_ns() { return NS_URI; }
public override string get_id() { return ID; }
}
public interface PublishResponseListener : Object {
public abstract void on_success(XmppStream stream);
public abstract void on_error(XmppStream stream);
private static void on_pubsub_data_response(XmppStream stream, string jid, string? id, StanzaNode? node, Object? o) {
if (node == null) return;
PixbufStorage storage = o as PixbufStorage;
storage.store(id, Base64.decode(node.get_string_content()));
stream.get_module(Module.IDENTITY).received_avatar(stream, jid, id);
}
}
}

View File

@ -58,26 +58,19 @@ namespace Xmpp.Xep.EntityCapabilities {
string ver_attribute = c_node.get_attribute("ver", NS_URI);
ArrayList<string> capabilities = storage.get_features(ver_attribute);
if (capabilities.size == 0) {
stream.get_module(ServiceDiscovery.Module.IDENTITY)
.request_info(stream, presence.from, new ServiceDiscoveryInfoResponseListenerImpl(storage, ver_attribute));
stream.get_module(ServiceDiscovery.Module.IDENTITY).request_info(stream, presence.from, on_received_info_response, Tuple.create(storage, ver_attribute));
} else {
ServiceDiscovery.Flag.get_flag(stream).set_entitiy_features(presence.from, capabilities);
}
}
}
private class ServiceDiscoveryInfoResponseListenerImpl : ServiceDiscovery.InfoResponseListener, Object {
private Storage storage;
private string entity;
public ServiceDiscoveryInfoResponseListenerImpl(Storage storage, string entity) {
this.storage = storage;
this.entity = entity;
}
public void on_result(XmppStream stream, ServiceDiscovery.InfoResult query_result) {
if (compute_hash(query_result.identities, query_result.features) == entity) {
storage.store_features(entity, query_result.features);
}
private static void on_received_info_response(XmppStream stream, ServiceDiscovery.InfoResult query_result, Object? store) {
Tuple<Storage, string> tuple = store as Tuple<Storage, string>;
Storage storage = tuple.a;
string entity = tuple.b;
if (compute_hash(query_result.identities, query_result.features) == entity) {
storage.store_features(entity, query_result.features);
}
}

View File

@ -9,20 +9,10 @@ namespace Xmpp.Xep.Ping {
public const string ID = "0199_ping";
public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, ID);
public void send_ping(XmppStream stream, string jid, ResponseListener? listener = null) {
public void send_ping(XmppStream stream, string jid, ResponseListener listener) {
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("ping", NS_URI).add_self_xmlns());
iq.to = jid;
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, listener == null? null : new IqResponseListenerImpl(listener));
}
private class IqResponseListenerImpl : Iq.ResponseListener, Object {
ResponseListener listener;
public IqResponseListenerImpl(ResponseListener listener) {
this.listener = listener;
}
public void on_result(XmppStream stream, Iq.Stanza iq) {
listener.on_result(stream);
}
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, on_ping_response, listener);
}
public override void attach(XmppStream stream) {
@ -45,6 +35,11 @@ namespace Xmpp.Xep.Ping {
}
public void on_iq_set(XmppStream stream, Iq.Stanza iq) { }
}
private static void on_ping_response(XmppStream stream, Iq.Stanza iq, Object o) {
ResponseListener listener = o as ResponseListener;
listener.on_result(stream);
}
}
public interface ResponseListener : Object {