Index: src/XMPPConnection.h ================================================================== --- src/XMPPConnection.h +++ src/XMPPConnection.h @@ -243,11 +243,11 @@ * \return Whether the certificate is valid */ - (BOOL)checkCertificateAndGetReason: (OFString**)reason; /** - * \brief Starts a loop handling incomming data. + * \brief Adds the connection to the run loop. */ - (void)handleConnection; /** * \brief Parses the specified buffer. @@ -256,11 +256,11 @@ * * \param buffer The buffer to parse * \param length The length of the buffer. If length is 0, it is assumed that * the connection was closed. */ -- (void)parseBuffer: (const char*)buffer +- (void)parseBuffer: (const void*)buffer length: (size_t)length; /** * \brief Returns the socket used by the XMPPConnection. * Index: src/XMPPConnection.m ================================================================== --- src/XMPPConnection.m +++ src/XMPPConnection.m @@ -53,10 +53,12 @@ #import "XMPPExceptions.h" #import "XMPPXMLElementBuilder.h" #import "namespaces.h" #import + +#define BUFFER_LENGTH 512 @implementation XMPPConnection + connection { return [[[self alloc] init] autorelease]; @@ -290,48 +292,79 @@ [pool release]; } - (void)handleConnection { - char buffer[512]; - - for (;;) { - size_t length = [sock readIntoBuffer: buffer - length: 512]; - - [self parseBuffer: buffer - length: length]; - - if (length < 1) - return; - } -} - -- (void)parseBuffer: (const char*)buffer - length: (size_t)length -{ - if (length < 1) { + char *buffer = [self allocMemoryWithSize: BUFFER_LENGTH]; + + [sock asyncReadIntoBuffer: buffer + length: BUFFER_LENGTH + target: self + selector: @selector(stream:didReadIntoBuffer:length:)]; +} + +- (BOOL)XMPP_parseBuffer: (const void*)buffer + length: (size_t)length +{ + if ([sock isAtEndOfStream]) { [delegates broadcastSelector: @selector(connectionWasClosed:) withObject: self]; - return; + return NO; } @try { [parser parseBuffer: buffer - length: length]; + length: length]; } @catch (OFMalformedXMLException *e) { [self XMPP_sendStreamError: @"bad-format" text: nil]; [self close]; + return NO; } + return YES; +} + +- (void)parseBuffer: (const void*)buffer + length: (size_t)length +{ + [self XMPP_parseBuffer: buffer + length: length]; + [oldParser release]; [oldElementBuilder release]; oldParser = nil; oldElementBuilder = nil; } + +- (BOOL)stream: (OFStream*)stream + didReadIntoBuffer: (char*)buffer + length: (size_t)length +{ + if (![self XMPP_parseBuffer: buffer + length: length]) + return NO; + + if (oldParser != nil || oldElementBuilder != nil) { + [oldParser release]; + [oldElementBuilder release]; + + oldParser = nil; + oldElementBuilder = nil; + + [sock asyncReadIntoBuffer: buffer + length: BUFFER_LENGTH + target: self + selector: @selector(stream: + didReadIntoBuffer:length:)]; + + return NO; + } + + return YES; +} - (OFTCPSocket*)socket { return [[sock retain] autorelease]; } Index: tests/test.m ================================================================== --- tests/test.m +++ tests/test.m @@ -144,11 +144,12 @@ - (void)connection: (XMPPConnection*)conn_ wasBoundToJID: (XMPPJID*)jid { of_log(@"Bound to JID: %@", [jid fullJID]); - of_log(@"Supports SM: %@", [conn_ supportsStreamManagement] ? @"YES" : @"NO"); + of_log(@"Supports SM: %@", + [conn_ supportsStreamManagement] ? @"YES" : @"NO"); [roster requestRoster]; } - (void)rosterWasReceived: (XMPPRoster*)roster_