@@ -35,10 +35,11 @@ #import #import #import #import "XMPPConnection.h" +#import "XMPPCallback.h" #import "XMPPSRVLookup.h" #import "XMPPSCRAMAuth.h" #import "XMPPPLAINAuth.h" #import "XMPPStanza.h" #import "XMPPJID.h" @@ -62,10 +63,11 @@ @try { sock = [[OFTCPSocket alloc] init]; port = 5222; encrypted = NO; + callbacks = [[OFMutableDictionary alloc] init]; } @catch (id e) { [self release]; @throw e; } @@ -81,13 +83,12 @@ [password release]; [server release]; [domain release]; [resource release]; [JID release]; + [callbacks release]; [authModule release]; - [bindID release]; - [sessionID release]; [roster release]; [super dealloc]; } @@ -349,10 +350,50 @@ [delegate connection: self didSendElement: element]; [sock writeString: [element XMLString]]; } + +- (void)sendIQ: (XMPPIQ*)iq +withCallbackObject: (id)object + selector: (SEL)selector +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + @try { + if (![iq ID]) + [iq setID: [self generateStanzaID]]; + + [callbacks setObject: [XMPPObjectCallback + callbackWithCallbackObject: object + selector: selector] + forKey: [iq ID]]; + } @finally { + [pool release]; + } + + [self sendStanza: iq]; +} + +#ifdef OF_HAVE_BLOCKS +- (void)sendIQ: (XMPPIQ*)iq +withCallbackBlock: (xmpp_callback_block)callback; +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + @try { + if (![iq ID]) + [iq setID: [self generateStanzaID]]; + + [callbacks setObject: [XMPPBlockCallback + callbackWithCallbackBlock: callback] + forKey: [iq ID]]; + } @finally { + [pool release]; + } + + [self sendStanza: iq]; +} +#endif - (OFString*)generateStanzaID { return [OFString stringWithFormat: @"objxmpp_%u", lastID++]; } @@ -654,18 +695,15 @@ } - (void)XMPP_handleIQ: (XMPPIQ*)iq { BOOL handled = NO; - - if ([[iq ID] isEqual: bindID]) { - [self XMPP_handleResourceBind: iq]; - return; - } - - if ([[iq ID] isEqual: sessionID]) { - [self XMPP_handleSession: iq]; + id callback; + + if ((callback = [callbacks objectForKey: [iq ID]])) { + [callback runWithIQ: iq]; + [callbacks removeObjectForKey: [iq ID]]; return; } if ([iq elementForName: @"query" namespace: XMPP_NS_ROSTER]) @@ -797,13 +835,12 @@ - (void)XMPP_sendResourceBind { XMPPIQ *iq; OFXMLElement *bind; - bindID = [[self generateStanzaID] retain]; iq = [XMPPIQ IQWithType: @"set" - ID: bindID]; + ID: [self generateStanzaID]]; bind = [OFXMLElement elementWithName: @"bind" namespace: XMPP_NS_BIND]; if (resource != nil) @@ -811,11 +848,13 @@ namespace: XMPP_NS_BIND stringValue: resource]]; [iq addChild: bind]; - [self sendStanza: iq]; + [self sendIQ: iq + withCallbackObject: self + selector: @selector(XMPP_handleResourceBind:)]; } - (void)XMPP_handleResourceBind: (XMPPIQ*)iq { OFXMLElement *bindElement; @@ -830,13 +869,10 @@ jidElement = [bindElement elementForName: @"jid" namespace: XMPP_NS_BIND]; JID = [[XMPPJID alloc] initWithString: [jidElement stringValue]]; - [bindID release]; - bindID = nil; - if (needsSession) { [self XMPP_sendSession]; return; } @@ -847,16 +883,17 @@ - (void)XMPP_sendSession { XMPPIQ *iq; - sessionID = [[self generateStanzaID] retain]; iq = [XMPPIQ IQWithType: @"set" - ID: sessionID]; + ID: [self generateStanzaID]]; [iq addChild: [OFXMLElement elementWithName: @"session" namespace: XMPP_NS_SESSION]]; - [self sendStanza: iq]; + [self sendIQ: iq + withCallbackObject: self + selector: @selector(XMPP_handleSession:)]; } - (void)XMPP_handleSession: (XMPPIQ*)iq { if (![[iq type] isEqual: @"result"]) @@ -863,13 +900,10 @@ assert(0); if ([delegate respondsToSelector: @selector(connection:wasBoundToJID:)]) [delegate connection: self wasBoundToJID: JID]; - - [sessionID release]; - sessionID = nil; } - (OFString*)XMPP_IDNAToASCII: (OFString*)domain_ { OFString *ret;