Index: src/XMPPConnection.h ================================================================== --- src/XMPPConnection.h +++ src/XMPPConnection.h @@ -51,35 +51,25 @@ OFXMLElementBuilderDelegate> { OFTCPSocket *sock; OFXMLParser *parser; OFXMLElementBuilder *elementBuilder; - /// The username to connect with - OFString *username; - /// The password to connect with - OFString *password; - /// The server to connect to - OFString *server; - /// The resource to connect with - OFString *resource; - /// The JID bound to this connection (this is determined by the server) + OFString *username, *password, *server, *resource; XMPPJID *JID; - /// The port to connect to - short port; + uint16_t port; /// Whether to use TLS BOOL useTLS; id delegate; XMPPAuthenticator *authModule; BOOL needsSession; + unsigned int lastID; + OFString *bindID, *sessionID; } -@property (copy) OFString *username; -@property (copy) OFString *password; -@property (copy) OFString *server; -@property (copy) OFString *resource; +@property (copy) OFString *username, *password, *server, *resource; @property (copy, readonly) XMPPJID *JID; -@property (assign) short port; +@property (assign) uint16_t port; @property (assign) BOOL useTLS; @property (retain) id delegate; /** * Connects to the XMPP service. @@ -95,6 +85,13 @@ * Sends an OFXMLElement, usually an XMPPStanza. * * \param elem The element to send */ - (void)sendStanza: (OFXMLElement*)elem; + +/** + * Generates a new, unique stanza ID. + * + * \return A new, generated, unique stanza ID. + */ +- (OFString*)generateStanzaID; @end Index: src/XMPPConnection.m ================================================================== --- src/XMPPConnection.m +++ src/XMPPConnection.m @@ -46,18 +46,18 @@ #define NS_STREAM @"http://etherx.jabber.org/streams" @interface XMPPConnection () - (void)XMPP_startStream; - (void)XMPP_sendAuth: (OFString*)name; -- (void)XMPP_sendResourceBind; -- (void)XMPP_sendSession; -- (void)XMPP_handleResourceBind: (XMPPIQ*)iq; -- (void)XMPP_handleSession; - (void)XMPP_handleFeatures: (OFXMLElement*)elem; - (void)XMPP_handleIQ: (XMPPIQ*)iq; - (void)XMPP_handleMessage: (XMPPMessage*)msg; - (void)XMPP_handlePresence: (XMPPPresence*)pres; +- (void)XMPP_sendResourceBind; +- (void)XMPP_handleResourceBind: (XMPPIQ*)iq; +- (void)XMPP_sendSession; +- (void)XMPP_handleSession: (XMPPIQ*)iq; @end @implementation XMPPConnection @synthesize JID, port, useTLS, delegate; @@ -81,11 +81,19 @@ - (void)dealloc { [sock release]; [parser release]; [elementBuilder release]; + [username release]; + [password release]; + [server release]; + [resource release]; + [JID release]; + [delegate release]; [authModule release]; + [bindID release]; + [sessionID release]; [super dealloc]; } - (void)setUsername: (OFString*)username_ @@ -229,10 +237,15 @@ - (void)sendStanza: (OFXMLElement*)elem { of_log(@"Out: %@", elem); [sock writeString: [elem stringValue]]; } + +- (OFString*)generateStanzaID +{ + return [OFString stringWithFormat: @"objxmpp_%u", lastID++]; +} - (void)parser: (OFXMLParser*)p didStartElement: (OFString*)name withPrefix: (OFString*)prefix namespace: (OFString*)ns @@ -360,18 +373,10 @@ } assert(0); } -- (void)elementBuilder: (OFXMLElementBuilder*)b - didNotExpectCloseTag: (OFString*)name - withPrefix: (OFString*)prefix - namespace: (OFString*)ns -{ - // TODO -} - - (void)XMPP_startStream { [sock writeFormat: @"\n" @"", server]; } - (void)XMPP_handleIQ: (XMPPIQ*)iq { - // FIXME: More checking! - if ([iq.ID isEqual: @"bind0"] && [iq.type isEqual: @"result"]) { + if ([iq.ID isEqual: bindID] && [iq.type isEqual: @"result"]) { [self XMPP_handleResourceBind: iq]; return; } - if ([iq.ID isEqual: @"session0"] && [iq.type isEqual: @"result"]) { - [self XMPP_handleSession]; + if ([iq.ID isEqual: sessionID] && [iq.type isEqual: @"result"]) { + [self XMPP_handleSession: iq]; return; } if ([delegate respondsToSelector: @selector(connection:didReceiveIQ:)]) [delegate connection: self @@ -481,17 +485,24 @@ [self sendStanza: authTag]; } - (void)XMPP_sendResourceBind { - XMPPIQ *iq = [XMPPIQ IQWithType: @"set" - ID: @"bind0"]; - OFXMLElement *bind = [OFXMLElement elementWithName: @"bind" - namespace: NS_BIND]; - if (resource) + XMPPIQ *iq; + OFXMLElement *bind; + + bindID = [[self generateStanzaID] retain]; + iq = [XMPPIQ IQWithType: @"set" + ID: bindID]; + + bind = [OFXMLElement elementWithName: @"bind" + namespace: NS_BIND]; + + if (resource != nil) [bind addChild: [OFXMLElement elementWithName: @"resource" stringValue: resource]]; + [iq addChild: bind]; [self sendStanza: iq]; } @@ -505,10 +516,13 @@ assert(0); jidElem = bindElem.children.firstObject; JID = [[XMPPJID alloc] initWithString: [jidElem.children.firstObject stringValue]]; + + [bindID release]; + bindID = nil; if (needsSession) { [self XMPP_sendSession]; return; } @@ -518,19 +532,28 @@ wasBoundToJID: JID]; } - (void)XMPP_sendSession { - XMPPIQ *iq = [XMPPIQ IQWithType: @"set" - ID: @"session0"]; + XMPPIQ *iq; + + sessionID = [[self generateStanzaID] retain]; + iq = [XMPPIQ IQWithType: @"set" + ID: sessionID]; [iq addChild: [OFXMLElement elementWithName: @"session" namespace: NS_SESSION]]; [self sendStanza: iq]; } -- (void)XMPP_handleSession +- (void)XMPP_handleSession: (XMPPIQ*)iq { + if (![iq.type isEqual: @"result"]) + assert(0); + if ([delegate respondsToSelector: @selector(connection:wasBoundToJID:)]) [delegate connection: self wasBoundToJID: JID]; + + [sessionID release]; + sessionID = nil; } @end