Request and handle roster.

This commit is contained in:
Jonathan Schleifer 2011-03-21 20:51:17 +01:00
parent 456cc295bc
commit e71c601cbe
5 changed files with 111 additions and 15 deletions

View file

@ -1,5 +1,5 @@
all: all:
objfw-compile -Wall --lib 0.0 -o objxmpp *.m \ objfw-compile -Wall -g --lib 0.0 -o objxmpp *.m \
`pkg-config --cflags --libs libidn` -lobjgnutls `pkg-config --cflags --libs libidn` -lobjgnutls
clean: clean:

View file

@ -35,6 +35,7 @@
- (void)connectionWasAuthenticated: (XMPPConnection*)conn; - (void)connectionWasAuthenticated: (XMPPConnection*)conn;
- (void)connection: (XMPPConnection*)conn - (void)connection: (XMPPConnection*)conn
wasBoundToJID: (XMPPJID*)jid; wasBoundToJID: (XMPPJID*)jid;
- (void)connectionDidReceiveRoster: (XMPPConnection*)conn;
- (void)connection: (XMPPConnection*)conn - (void)connection: (XMPPConnection*)conn
didReceiveIQ: (XMPPIQ*)iq; didReceiveIQ: (XMPPIQ*)iq;
- (void)connection: (XMPPConnection*)conn - (void)connection: (XMPPConnection*)conn
@ -62,7 +63,8 @@
XMPPAuthenticator *authModule; XMPPAuthenticator *authModule;
BOOL needsSession; BOOL needsSession;
unsigned int lastID; unsigned int lastID;
OFString *bindID, *sessionID; OFString *bindID, *sessionID, *rosterID;
OFMutableDictionary *roster;
} }
@property (copy) OFString *username, *password, *server, *resource; @property (copy) OFString *username, *password, *server, *resource;
@ -70,6 +72,7 @@
@property (assign) uint16_t port; @property (assign) uint16_t port;
@property (assign) BOOL useTLS; @property (assign) BOOL useTLS;
@property (retain) id <XMPPConnectionDelegate> delegate; @property (retain) id <XMPPConnectionDelegate> delegate;
@property (copy, readonly) OFDictionary *roster;
/** /**
* Connects to the XMPP service. * Connects to the XMPP service.
@ -94,4 +97,9 @@
* \return A new, generated, unique stanza ID. * \return A new, generated, unique stanza ID.
*/ */
- (OFString*)generateStanzaID; - (OFString*)generateStanzaID;
/**
* Requests the roster.
*/
- (void)requestRoster;
@end @end

View file

@ -40,6 +40,7 @@
#define NS_BIND @"urn:ietf:params:xml:ns:xmpp-bind" #define NS_BIND @"urn:ietf:params:xml:ns:xmpp-bind"
#define NS_CLIENT @"jabber:client" #define NS_CLIENT @"jabber:client"
#define NS_ROSTER @"jabber:iq:roster"
#define NS_SASL @"urn:ietf:params:xml:ns:xmpp-sasl" #define NS_SASL @"urn:ietf:params:xml:ns:xmpp-sasl"
#define NS_STARTTLS @"urn:ietf:params:xml:ns:xmpp-tls" #define NS_STARTTLS @"urn:ietf:params:xml:ns:xmpp-tls"
#define NS_SESSION @"urn:ietf:params:xml:ns:xmpp-session" #define NS_SESSION @"urn:ietf:params:xml:ns:xmpp-session"
@ -56,24 +57,32 @@
- (void)XMPP_handleResourceBind: (XMPPIQ*)iq; - (void)XMPP_handleResourceBind: (XMPPIQ*)iq;
- (void)XMPP_sendSession; - (void)XMPP_sendSession;
- (void)XMPP_handleSession: (XMPPIQ*)iq; - (void)XMPP_handleSession: (XMPPIQ*)iq;
- (void)XMPP_handleRoster: (XMPPIQ*)iq;
@end @end
@implementation XMPPConnection @implementation XMPPConnection
@synthesize JID, port, useTLS, delegate; @synthesize JID, port, useTLS, delegate, roster;
- init - init
{ {
self = [super init]; self = [super init];
sock = [[OFTCPSocket alloc] init]; @try {
parser = [[OFXMLParser alloc] init]; sock = [[OFTCPSocket alloc] init];
elementBuilder = [[OFXMLElementBuilder alloc] init]; parser = [[OFXMLParser alloc] init];
elementBuilder = [[OFXMLElementBuilder alloc] init];
port = 5222; port = 5222;
useTLS = YES; useTLS = YES;
parser.delegate = self; parser.delegate = self;
elementBuilder.delegate = self; elementBuilder.delegate = self;
roster = [[OFMutableDictionary alloc] init];
} @catch (id e) {
[self release];
@throw e;
}
return self; return self;
} }
@ -92,6 +101,8 @@
[authModule release]; [authModule release];
[bindID release]; [bindID release];
[sessionID release]; [sessionID release];
[rosterID release];
[roster release];
[super dealloc]; [super dealloc];
} }
@ -385,16 +396,21 @@
- (void)XMPP_handleIQ: (XMPPIQ*)iq - (void)XMPP_handleIQ: (XMPPIQ*)iq
{ {
if ([iq.ID isEqual: bindID] && [iq.type isEqual: @"result"]) { if ([iq.ID isEqual: bindID]) {
[self XMPP_handleResourceBind: iq]; [self XMPP_handleResourceBind: iq];
return; return;
} }
if ([iq.ID isEqual: sessionID] && [iq.type isEqual: @"result"]) { if ([iq.ID isEqual: sessionID]) {
[self XMPP_handleSession: iq]; [self XMPP_handleSession: iq];
return; return;
} }
if ([iq.ID isEqual: rosterID]) {
[self XMPP_handleRoster: iq];
return;
}
if ([delegate respondsToSelector: @selector(connection:didReceiveIQ:)]) if ([delegate respondsToSelector: @selector(connection:didReceiveIQ:)])
[delegate connection: self [delegate connection: self
didReceiveIQ: iq]; didReceiveIQ: iq];
@ -508,9 +524,14 @@
- (void)XMPP_handleResourceBind: (XMPPIQ*)iq - (void)XMPP_handleResourceBind: (XMPPIQ*)iq
{ {
OFXMLElement *bindElem = iq.children.firstObject; OFXMLElement *bindElem;
OFXMLElement *jidElem; OFXMLElement *jidElem;
if (![iq.type isEqual: @"result"])
assert(0);
bindElem = iq.children.firstObject;
if (![bindElem.name isEqual: @"bind"] || if (![bindElem.name isEqual: @"bind"] ||
![bindElem.namespace isEqual: NS_BIND]) ![bindElem.namespace isEqual: NS_BIND])
assert(0); assert(0);
@ -556,4 +577,64 @@
[sessionID release]; [sessionID release];
sessionID = nil; sessionID = nil;
} }
- (void)requestRoster
{
XMPPIQ *iq;
if (rosterID != nil)
assert(0);
rosterID = [[self generateStanzaID] retain];
iq = [XMPPIQ IQWithType: @"get"
ID: rosterID];
[iq addChild: [OFXMLElement elementWithName: @"query"
namespace: NS_ROSTER]];
[self sendStanza: iq];
}
- (void)XMPP_handleRoster: (XMPPIQ*)iq
{
OFXMLElement *rosterElem;
if (![iq.type isEqual: @"result"])
assert(0);
rosterElem = iq.children.firstObject;
if (![rosterElem.name isEqual: @"query"] ||
![rosterElem.namespace isEqual: NS_ROSTER])
assert(0);
for (OFXMLElement *elem in rosterElem.children) {
OFString *group;
OFMutableArray *rosterGroup;
if (![elem.name isEqual: @"item"] ||
![elem.ns isEqual: NS_ROSTER])
continue;
group = [[elem
elementsForName: @"group"
namespace: NS_ROSTER].firstObject stringValue];
if (group == nil)
group = @"";
if ((rosterGroup = [roster objectForKey: group]) == nil) {
rosterGroup = [OFMutableArray array];
[roster setObject: rosterGroup
forKey: group];
}
[rosterGroup addObject: elem];
}
if ([delegate respondsToSelector:
@selector(connectionDidReceiveRoster:)])
[delegate connectionDidReceiveRoster: self];
[rosterID release];
rosterID = nil;
}
@end @end

View file

@ -1,5 +1,5 @@
all: all:
objfw-compile -Wall -o tests *.m -I../src -L../src -lobjxmpp objfw-compile -Wall -g -o tests *.m -I../src -L../src -lobjxmpp
clean: clean:
rm -f tests *.o rm -f tests *.o

View file

@ -110,10 +110,17 @@ OF_APPLICATION_DELEGATE(AppDelegate)
- (void)connection: (XMPPConnection*)conn - (void)connection: (XMPPConnection*)conn
wasBoundToJID: (XMPPJID*)jid wasBoundToJID: (XMPPJID*)jid
{
of_log(@"Bound to JID: %@", [jid fullJID]);
[conn requestRoster];
}
- (void)connectionDidReceiveRoster :(XMPPConnection*)conn
{ {
XMPPPresence *pres; XMPPPresence *pres;
of_log(@"Bound to JID: %@", [jid fullJID]); of_log(@"Got roster");
pres = [XMPPPresence presence]; pres = [XMPPPresence presence];
[pres addPriority: 10]; [pres addPriority: 10];