From 7fb28f25c8ffe492d55048b62849384d83f855fa Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Fri, 27 Jan 2012 00:23:04 +0100 Subject: [PATCH] Add multicast delegates. --- .hgignore | 1 + ObjXMPP.xcodeproj/project.pbxproj | 8 ++ src/Makefile | 1 + src/XMPPConnection.h | 33 +++++--- src/XMPPConnection.m | 133 ++++++++++++++++-------------- src/XMPPMulticastDelegate.h | 39 +++++++++ src/XMPPMulticastDelegate.m | 111 +++++++++++++++++++++++++ src/XMPPRoster.m | 20 +++-- tests/test.m | 2 +- 9 files changed, 265 insertions(+), 83 deletions(-) create mode 100644 src/XMPPMulticastDelegate.h create mode 100644 src/XMPPMulticastDelegate.m diff --git a/.hgignore b/.hgignore index 6bd7ef5..5d8008f 100644 --- a/.hgignore +++ b/.hgignore @@ -12,6 +12,7 @@ config.h.in config.log config.status configure +DerivedData docs extra.mk ObjXMPP.xcodeproj/*.mode1v3 diff --git a/ObjXMPP.xcodeproj/project.pbxproj b/ObjXMPP.xcodeproj/project.pbxproj index 15cd962..062bd38 100644 --- a/ObjXMPP.xcodeproj/project.pbxproj +++ b/ObjXMPP.xcodeproj/project.pbxproj @@ -16,6 +16,8 @@ 4B19F57C14D17082005D52DC /* XMPPEXTERNALAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19F57814D17081005D52DC /* XMPPEXTERNALAuth.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B19F57D14D17082005D52DC /* XMPPEXTERNALAuth.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B19F57914D17081005D52DC /* XMPPEXTERNALAuth.m */; }; 4B19F5A314D1779E005D52DC /* ObjOpenSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B19F5A214D1779E005D52DC /* ObjOpenSSL.framework */; }; + 4B19F5D114D20B01005D52DC /* XMPPMulticastDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19F5CF14D20B01005D52DC /* XMPPMulticastDelegate.h */; }; + 4B19F5D214D20B01005D52DC /* XMPPMulticastDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B19F5D014D20B01005D52DC /* XMPPMulticastDelegate.m */; }; 4B4844F5138BBC7500EB48A5 /* XMPPSRVLookup.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4844F3138BBC7400EB48A5 /* XMPPSRVLookup.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B4844F6138BBC7500EB48A5 /* XMPPSRVLookup.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B4844F4138BBC7500EB48A5 /* XMPPSRVLookup.m */; }; 4B484501138BBEEB00EB48A5 /* libresolv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B484500138BBEEB00EB48A5 /* libresolv.dylib */; }; @@ -68,6 +70,8 @@ 4B19F57814D17081005D52DC /* XMPPEXTERNALAuth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPEXTERNALAuth.h; path = src/XMPPEXTERNALAuth.h; sourceTree = SOURCE_ROOT; }; 4B19F57914D17081005D52DC /* XMPPEXTERNALAuth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPEXTERNALAuth.m; path = src/XMPPEXTERNALAuth.m; sourceTree = SOURCE_ROOT; }; 4B19F5A214D1779E005D52DC /* ObjOpenSSL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjOpenSSL.framework; path = /Library/Frameworks/ObjOpenSSL.framework; sourceTree = ""; }; + 4B19F5CF14D20B01005D52DC /* XMPPMulticastDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPMulticastDelegate.h; path = src/XMPPMulticastDelegate.h; sourceTree = SOURCE_ROOT; }; + 4B19F5D014D20B01005D52DC /* XMPPMulticastDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPMulticastDelegate.m; path = src/XMPPMulticastDelegate.m; sourceTree = SOURCE_ROOT; }; 4B4844F3138BBC7400EB48A5 /* XMPPSRVLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPSRVLookup.h; path = src/XMPPSRVLookup.h; sourceTree = SOURCE_ROOT; }; 4B4844F4138BBC7500EB48A5 /* XMPPSRVLookup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPSRVLookup.m; path = src/XMPPSRVLookup.m; sourceTree = SOURCE_ROOT; }; 4B484500138BBEEB00EB48A5 /* libresolv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libresolv.dylib; path = usr/lib/libresolv.dylib; sourceTree = SDKROOT; }; @@ -188,6 +192,8 @@ 4BC559E31337AC0900E345C7 /* XMPPJID.m */, 4BC559E41337AC0900E345C7 /* XMPPMessage.h */, 4BC559E51337AC0900E345C7 /* XMPPMessage.m */, + 4B19F5CF14D20B01005D52DC /* XMPPMulticastDelegate.h */, + 4B19F5D014D20B01005D52DC /* XMPPMulticastDelegate.m */, 4BC559E61337AC0900E345C7 /* XMPPPLAINAuth.h */, 4BC559E71337AC0900E345C7 /* XMPPPLAINAuth.m */, 4BC559E81337AC0900E345C7 /* XMPPPresence.h */, @@ -239,6 +245,7 @@ 4B4844F5138BBC7500EB48A5 /* XMPPSRVLookup.h in Headers */, 4BC55A011337AC1800E345C7 /* XMPPStanza.h in Headers */, 4B01D020137C7E7D005624EA /* namespaces.h in Headers */, + 4B19F5D114D20B01005D52DC /* XMPPMulticastDelegate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -344,6 +351,7 @@ 4BD9BF5A134003F700DAB43A /* XMPPRosterItem.m in Sources */, 4BDEF8081340B240000156D1 /* XMPPRoster.m in Sources */, 4B4844F6138BBC7500EB48A5 /* XMPPSRVLookup.m in Sources */, + 4B19F5D214D20B01005D52DC /* XMPPMulticastDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/Makefile b/src/Makefile index 263cdf2..14d8e1c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ SRCS = XMPPAuthenticator.m \ XMPPIQ.m \ XMPPJID.m \ XMPPMessage.m \ + XMPPMulticastDelegate.m \ XMPPPLAINAuth.m \ XMPPPresence.m \ XMPPRoster.m \ diff --git a/src/XMPPConnection.h b/src/XMPPConnection.h index 4fd6afd..8cdad7f 100644 --- a/src/XMPPConnection.h +++ b/src/XMPPConnection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Jonathan Schleifer + * Copyright (c) 2010, 2011, 2012, Jonathan Schleifer * Copyright (c) 2011, Florian Zeitz * * https://webkeks.org/hg/objxmpp/ @@ -32,6 +32,7 @@ @class XMPPRoster; @class XMPPRosterItem; @class SSLSocket; +@class XMPPMulticastDelegate; @protocol XMPPConnectionDelegate #ifndef XMPP_CONNECTION_M @@ -77,7 +78,7 @@ OFString *domain, *domainToASCII; XMPPJID *JID; uint16_t port; - id delegate; + XMPPMulticastDelegate *delegates; OFMutableDictionary *callbacks; XMPPAuthenticator *authModule; BOOL streamOpen; @@ -92,7 +93,6 @@ @property (copy) OFString *privateKeyFile, *certificateFile; @property (copy, readonly) XMPPJID *JID; @property (assign) uint16_t port; -@property (assign) id delegate; @property (readonly, retain) XMPPRoster *roster; @property (readonly, retain, getter=socket) OFTCPSocket *sock; @property (assign) BOOL encryptionRequired; @@ -105,6 +105,20 @@ */ + connection; +/** + * Adds the specified delegate. + * + * \param delegate The delegate to add + */ +- (void)addDelegate: (id )delegate; + +/** + * Removes the specified delegate. + * + * \param delegate The delegate to remove + */ +- (void)removeDelegate: (id )delegate; + /** * Connects to the XMPP service. */ @@ -174,9 +188,9 @@ * \param selector The selector of the callback method, * must take exactly one parameter of type XMPPIQ* */ -- (void)sendIQ: (XMPPIQ*)iq -withCallbackObject: (id)object - selector: (SEL)selector; +- (void)sendIQ: (XMPPIQ*)iq + withCallbackObject: (id)object + selector: (SEL)selector; #ifdef OF_HAVE_BLOCKS /** @@ -184,8 +198,8 @@ withCallbackObject: (id)object * * \param callback The callback block */ -- (void)sendIQ: (XMPPIQ*)iq -withCallbackBlock: (void(^)(XMPPIQ*))callback; +- (void)sendIQ: (XMPPIQ*)iq + withCallbackBlock: (void(^)(XMPPIQ*))block; #endif /** @@ -208,8 +222,6 @@ withCallbackBlock: (void(^)(XMPPIQ*))callback; - (XMPPJID*)JID; - (void)setPort: (uint16_t)port; - (uint16_t)port; -- (void)setDelegate: (id )delegate; -- (id )delegate; - (XMPPRoster*)roster; - (void)XMPP_startStream; @@ -229,6 +241,7 @@ withCallbackBlock: (void(^)(XMPPIQ*))callback; - (void)XMPP_sendSession; - (void)XMPP_handleSession: (XMPPIQ*)iq; - (OFString*)XMPP_IDNAToASCII: (OFString*)domain; +- (XMPPMulticastDelegate*)XMPP_delegates; @end @interface OFObject (XMPPConnectionDelegate) diff --git a/src/XMPPConnection.m b/src/XMPPConnection.m index 2a9dff5..9ceea5a 100644 --- a/src/XMPPConnection.m +++ b/src/XMPPConnection.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Jonathan Schleifer + * Copyright (c) 2010, 2011, 2012, Jonathan Schleifer * Copyright (c) 2011, Florian Zeitz * * https://webkeks.org/hg/objxmpp/ @@ -49,6 +49,7 @@ #import "XMPPPresence.h" #import "XMPPRoster.h" #import "XMPPRosterItem.h" +#import "XMPPMulticastDelegate.h" #import "XMPPExceptions.h" #import "namespaces.h" @@ -67,6 +68,7 @@ port = 5222; encrypted = NO; streamOpen = NO; + delegates = [[XMPPMulticastDelegate alloc] init]; callbacks = [[OFMutableDictionary alloc] init]; } @catch (id e) { [self release]; @@ -89,6 +91,7 @@ [domain release]; [resource release]; [JID release]; + [delegates release]; [callbacks release]; [authModule release]; [roster release]; @@ -304,9 +307,9 @@ - (void)parseBuffer: (const char*)buffer withLength: (size_t)length { - if (length < 1 && [delegate respondsToSelector: - @selector(connectionWasClosed:)]) { - [delegate connectionWasClosed: self]; + if (length < 1) { + [delegates broadcastSelector: @selector(connectionWasClosed:) + forConnection: self]; return; } @@ -375,10 +378,9 @@ - (void)sendStanza: (OFXMLElement*)element { - if ([delegate respondsToSelector: - @selector(connection:didSendElement:)]) - [delegate connection: self - didSendElement: element]; + [delegates broadcastSelector: @selector(connection:didSendElement:) + forConnection: self + withObject: element]; [sock writeString: [element XMLString]]; } @@ -387,37 +389,37 @@ withCallbackObject: (id)object selector: (SEL)selector { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - @try { - if (![iq ID]) - [iq setID: [self generateStanzaID]]; + OFAutoreleasePool *pool; + XMPPCallback *callback; - [callbacks setObject: [XMPPCallback - callbackWithCallbackObject: object - selector: selector] - forKey: [iq ID]]; - } @finally { - [pool release]; - } + if (![iq ID]) + [iq setID: [self generateStanzaID]]; + + pool = [[OFAutoreleasePool alloc] init]; + callback = [XMPPCallback callbackWithCallbackObject: object + selector: selector]; + [callbacks setObject: callback + forKey: [iq ID]]; + [pool release]; [self sendStanza: iq]; } #ifdef OF_HAVE_BLOCKS - (void)sendIQ: (XMPPIQ*)iq - withCallbackBlock: (xmpp_callback_block_t)callback; + withCallbackBlock: (xmpp_callback_block_t)block; { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - @try { - if (![iq ID]) - [iq setID: [self generateStanzaID]]; + OFAutoreleasePool *pool; + XMPPCallback *callback; - [callbacks setObject: [XMPPCallback - callbackWithCallbackBlock: callback] - forKey: [iq ID]]; - } @finally { - [pool release]; - } + if (![iq ID]) + [iq setID: [self generateStanzaID]]; + + pool = [[OFAutoreleasePool alloc] init]; + callback = [XMPPCallback callbackWithCallbackBlock: block]; + [callbacks setObject: callback + forKey: [iq ID]]; + [pool release]; [self sendStanza: iq]; } @@ -486,10 +488,9 @@ [element setPrefix: @"stream" forNamespace: XMPP_NS_STREAM]; - if ([delegate respondsToSelector: - @selector(connection:didReceiveElement:)]) - [delegate connection: self - didReceiveElement: element]; + [delegates broadcastSelector: @selector(connection:didReceiveElement:) + forConnection: self + withObject: element]; if ([[element namespace] isEqual: XMPP_NS_CLIENT]) [self XMPP_handleStanza: element]; @@ -692,9 +693,9 @@ /* FIXME: Catch errors here */ SSLSocket *newSock; - if ([delegate respondsToSelector: - @selector(connectionWillUpgradeToTLS:)]) - [delegate connectionWillUpgradeToTLS: self]; + [delegates broadcastSelector: @selector( + connectionWillUpgradeToTLS:) + forConnection: self]; newSock = [[SSLSocket alloc] initWithSocket: sock privateKeyFile: privateKeyFile @@ -704,9 +705,9 @@ encrypted = YES; - if ([delegate respondsToSelector: - @selector(connectionDidUpgradeToTLS:)]) - [delegate connectionDidUpgradeToTLS: self]; + [delegates broadcastSelector: @selector( + connectionDidUpgradeToTLS:) + forConnection: self]; /* Stream restart */ [self XMPP_startStream]; @@ -748,9 +749,9 @@ [authModule continueWithData: [OFDataArray dataArrayWithBase64EncodedString: [element stringValue]]]; - if ([delegate respondsToSelector: - @selector(connectionWasAuthenticated:)]) - [delegate connectionWasAuthenticated: self]; + [delegates broadcastSelector: @selector( + connectionWWasAuthenticated:) + forConnection: self]; /* Stream restart */ [self XMPP_startStream]; @@ -786,9 +787,10 @@ if ([roster handleIQ: iq]) return; - if ([delegate respondsToSelector: @selector(connection:didReceiveIQ:)]) - handled = [delegate connection: self - didReceiveIQ: iq]; + handled = [delegates broadcastSelector: @selector( + connection:didReceiveIQ:) + forConnection: self + withObject: iq]; if (!handled && ![[iq type] isEqual: @"error"] && ![[iq type] isEqual: @"result"]) { @@ -799,18 +801,16 @@ - (void)XMPP_handleMessage: (XMPPMessage*)message { - if ([delegate respondsToSelector: - @selector(connection:didReceiveMessage:)]) - [delegate connection: self - didReceiveMessage: message]; + [delegates broadcastSelector: @selector(connection:didReceiveMessage:) + forConnection: self + withObject: message]; } - (void)XMPP_handlePresence: (XMPPPresence*)presence { - if ([delegate respondsToSelector: - @selector(connection:didReceivePresence:)]) - [delegate connection: self - didReceivePresence: presence]; + [delegates broadcastSelector: @selector(connection:didReceivePresence:) + forConnection: self + withObject: presence]; } - (void)XMPP_handleFeatures: (OFXMLElement*)element @@ -979,9 +979,9 @@ return; } - if ([delegate respondsToSelector: @selector(connection:wasBoundToJID:)]) - [delegate connection: self - wasBoundToJID: JID]; + [delegates broadcastSelector: @selector(connection:wasBoundToJID:) + forConnection: self + withObject: JID]; } - (void)XMPP_sendSession @@ -1002,9 +1002,9 @@ if (![[iq type] isEqual: @"result"]) assert(0); - if ([delegate respondsToSelector: @selector(connection:wasBoundToJID:)]) - [delegate connection: self - wasBoundToJID: JID]; + [delegates broadcastSelector: @selector(connection:wasBoundToJID:) + forConnection: self + withObject: JID]; } - (OFString*)XMPP_IDNAToASCII: (OFString*)domain_ @@ -1045,14 +1045,19 @@ return port; } -- (void)setDelegate: (id )delegate_ +- (void)addDelegate: (id )delegate { - delegate = (id )delegate_; + [delegates addDelegate: delegate]; } -- (id )delegate +- (void)removeDelegate: (id )delegate { - return delegate; + [delegates removeDelegate: delegate]; +} + +- (XMPPMulticastDelegate*)XMPP_delegates +{ + return delegates; } - (XMPPRoster*)roster diff --git a/src/XMPPMulticastDelegate.h b/src/XMPPMulticastDelegate.h new file mode 100644 index 0000000..c59c107 --- /dev/null +++ b/src/XMPPMulticastDelegate.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2012, Jonathan Schleifer + * + * https://webkeks.org/hg/objxmpp/ + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "XMPPConnection.h" + +@class OFDataArray; + +@interface XMPPMulticastDelegate: OFObject +{ + OFDataArray *delegates; +} + +- (void)addDelegate: (id )delegate; +- (void)removeDelegate: (id )delegate; +- (BOOL)broadcastSelector: (SEL)selector + forConnection: (XMPPConnection*)connection; +- (BOOL)broadcastSelector: (SEL)selector + forConnection: (XMPPConnection*)connection + withObject: (id)object; +@end diff --git a/src/XMPPMulticastDelegate.m b/src/XMPPMulticastDelegate.m new file mode 100644 index 0000000..50577a6 --- /dev/null +++ b/src/XMPPMulticastDelegate.m @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2012, Jonathan Schleifer + * + * https://webkeks.org/hg/objxmpp/ + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#import + +#import "XMPPMulticastDelegate.h" + +@implementation XMPPMulticastDelegate +- init +{ + self = [super init]; + + @try { + delegates = [[OFDataArray alloc] initWithItemSize: sizeof(id)]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [delegates release]; + + [super dealloc]; +} + +- (void)addDelegate: (id )delegate +{ + [delegates addItem: &delegate]; +} + +- (void)removeDelegate: (id)delegate +{ + id *cArray = [delegates cArray]; + size_t i, count = [delegates count]; + + for (i = 0; i < count; i++) { + if (cArray[i] == delegate) { + [delegates removeItemAtIndex: i]; + return; + } + } +} + +- (BOOL)broadcastSelector: (SEL)selector + forConnection: (XMPPConnection*)connection +{ + id *cArray = [delegates cArray]; + size_t i, count = [delegates count]; + BOOL handled = NO; + + for (i = 0; i < count; i++) { + if (![cArray[i] respondsToSelector: selector]) + continue; + + BOOL (*imp)(id, SEL, id) = (BOOL(*)(id, SEL, id)) + [cArray[i] methodForSelector: selector]; + + handled |= imp(cArray[i], selector, connection); + } + + return handled; +} + +- (BOOL)broadcastSelector: (SEL)selector + forConnection: (XMPPConnection*)connection + withObject: (id)object +{ + id *cArray = [delegates cArray]; + size_t i, count = [delegates count]; + BOOL handled = NO; + + for (i = 0; i < count; i++) { + if (![cArray[i] respondsToSelector: selector]) + continue; + + BOOL (*imp)(id, SEL, id, id) = (BOOL(*)(id, SEL, id, id)) + [cArray[i] methodForSelector: selector]; + + handled |= imp(cArray[i], selector, connection, object); + } + + return handled; +} +@end diff --git a/src/XMPPRoster.m b/src/XMPPRoster.m index f3cd965..9a13ca3 100644 --- a/src/XMPPRoster.m +++ b/src/XMPPRoster.m @@ -31,6 +31,7 @@ #import "XMPPConnection.h" #import "XMPPIQ.h" #import "XMPPJID.h" +#import "XMPPMulticastDelegate.h" #import "namespaces.h" @implementation XMPPRoster @@ -157,19 +158,22 @@ else [self XMPP_addRosterItem: rosterItem]; - if (isPush && [[connection delegate] respondsToSelector: - @selector(connection:didReceiveRosterItem:)]) - [[connection delegate] connection: connection - didReceiveRosterItem: rosterItem]; + if (isPush) { + SEL sel = @selector(connection:didReceiveRosterItem:); + + [[connection XMPP_delegates] + broadcastSelector: sel + forConnection: connection + withObject: rosterItem]; + } } if (isPush) { [connection sendStanza: [iq resultIQ]]; } else { - if ([[connection delegate] respondsToSelector: - @selector(connectionDidReceiveRoster:)]) - [[connection delegate] - connectionDidReceiveRoster: connection]; + [[connection XMPP_delegates] + broadcastSelector: @selector(connectionDidReceiveRoster:) + forConnection: connection]; [rosterID release]; rosterID = nil; diff --git a/tests/test.m b/tests/test.m index 5667834..545b46d 100644 --- a/tests/test.m +++ b/tests/test.m @@ -91,7 +91,7 @@ OF_APPLICATION_DELEGATE(AppDelegate) [stanza ID]] isEqual: @"bob@localhost, alice@localhost, get, 42"])); conn = [[XMPPConnection alloc] init]; - [conn setDelegate: self]; + [conn addDelegate: self]; if ([arguments count] != 3) { of_log(@"Invalid count of command line arguments!");