@@ -72,6 +72,7 @@ - (void)continueSendElement:(NSXMLElement *)element withTag:(long)tag;
72
72
- (void )startNegotiation ;
73
73
- (void )sendOpeningNegotiation ;
74
74
- (void )continueStartTLS : (NSMutableDictionary *)settings ;
75
+ - (void )continueHandleBinding : (NSString *)alternativeResource ;
75
76
- (void )setupKeepAliveTimer ;
76
77
- (void )keepAlive ;
77
78
@@ -2551,69 +2552,121 @@ - (void)handleBinding:(NSXMLElement *)response
2551
2552
}
2552
2553
else
2553
2554
{
2554
- // It appears the server didn't allow our resource choice
2555
- // First check if we want to try an alternative resource
2556
-
2557
- NSString *alternativeResource = nil ;
2558
-
2559
- NSXMLElement *r_error = [response elementForName: @" error" ];
2560
- NSXMLElement *r_conflict = [r_error elementForName: @" conflict" xmlns: @" urn:ietf:params:xml:ns:xmpp-stanzas" ];
2561
-
2562
- if (r_conflict)
2563
- {
2564
- alternativeResource = [multicastDelegate xmppStream: self alternativeResourceForConflictingResource: [[self myJID ] resource ]];
2565
- }
2555
+ // It appears the server didn't allow our resource choice
2556
+ // First check if we want to try an alternative resource
2557
+
2558
+ NSXMLElement *r_error = [response elementForName: @" error" ];
2559
+ NSXMLElement *r_conflict = [r_error elementForName: @" conflict" xmlns: @" urn:ietf:params:xml:ns:xmpp-stanzas" ];
2566
2560
2567
- if ([alternativeResource length ])
2568
- {
2569
- XMPPJID *alternativeJID = [XMPPJID jidWithUser: [[self myJID ] user ] domain: [[self myJID ] domain ] resource: alternativeResource];
2570
- [self setMyJID: alternativeJID];
2571
-
2572
- NSXMLElement *resource = [NSXMLElement elementWithName: @" resource" ];
2573
- [resource setStringValue: alternativeResource];
2574
-
2575
- NSXMLElement *bind = [NSXMLElement elementWithName: @" bind" xmlns: @" urn:ietf:params:xml:ns:xmpp-bind" ];
2576
- [bind addChild: resource];
2577
-
2578
- NSXMLElement *iq = [NSXMLElement elementWithName: @" iq" ];
2579
- [iq addAttributeWithName: @" type" stringValue: @" set" ];
2580
- [iq addChild: bind];
2581
-
2582
- NSString *outgoingStr = [iq compactXMLString ];
2583
- NSData *outgoingData = [outgoingStr dataUsingEncoding: NSUTF8StringEncoding];
2584
-
2585
- XMPPLogSend (@" SEND: %@ " , outgoingStr);
2586
- numberOfBytesSent += [outgoingData length ];
2587
-
2588
- [asyncSocket writeData: outgoingData
2589
- withTimeout: TIMEOUT_XMPP_WRITE
2590
- tag: TAG_XMPP_WRITE_STREAM];
2591
-
2592
- // The state remains in STATE_XMPP_BINDING
2593
-
2594
- }else {
2595
-
2596
- // We'll simply let the server choose then
2597
-
2598
- NSXMLElement *bind = [NSXMLElement elementWithName: @" bind" xmlns: @" urn:ietf:params:xml:ns:xmpp-bind" ];
2599
-
2600
- NSXMLElement *iq = [NSXMLElement elementWithName: @" iq" ];
2601
- [iq addAttributeWithName: @" type" stringValue: @" set" ];
2602
- [iq addChild: bind];
2603
-
2604
- NSString *outgoingStr = [iq compactXMLString ];
2605
- NSData *outgoingData = [outgoingStr dataUsingEncoding: NSUTF8StringEncoding];
2606
-
2607
- XMPPLogSend (@" SEND: %@ " , outgoingStr);
2608
- numberOfBytesSent += [outgoingData length ];
2609
-
2610
- [asyncSocket writeData: outgoingData
2611
- withTimeout: TIMEOUT_XMPP_WRITE
2612
- tag: TAG_XMPP_WRITE_STREAM];
2613
-
2614
- // The state remains in STATE_XMPP_BINDING
2615
-
2561
+ if (r_conflict)
2562
+ {
2563
+ SEL selector = @selector (xmppStream:alternativeResourceForConflictingResource: );
2564
+
2565
+ if ([multicastDelegate countForSelector: selector] == 0 )
2566
+ {
2567
+ // None of the delegates implement the method.
2568
+ // Use a shortcut.
2569
+
2570
+ [self continueHandleBinding: nil ];
2571
+ }
2572
+ else
2573
+ {
2574
+ // Query all interested delegates.
2575
+ // This must be done serially to maintain thread safety.
2576
+
2577
+ GCDMulticastDelegateEnumerator *delegateEnumerator = [multicastDelegate delegateEnumerator ];
2578
+
2579
+ dispatch_queue_t concurrentQueue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 );
2580
+ dispatch_async (concurrentQueue, ^{ @autoreleasepool {
2581
+
2582
+ // Query delegates for alternative resource
2583
+
2584
+ NSString *currentResource = [[self myJID ] resource ];
2585
+ __block NSString *alternativeResource = nil ;
2586
+
2587
+ id delegate;
2588
+ dispatch_queue_t dq;
2589
+
2590
+ while ([delegateEnumerator getNextDelegate: &delegate delegateQueue: &dq forSelector: selector])
2591
+ {
2592
+ dispatch_sync (dq, ^{ @autoreleasepool {
2593
+
2594
+ NSString *delegateAlternativeResource =
2595
+ [delegate xmppStream: self alternativeResourceForConflictingResource: currentResource];
2596
+
2597
+ if (delegateAlternativeResource)
2598
+ {
2599
+ alternativeResource = delegateAlternativeResource;
2600
+ }
2601
+ }});
2602
+ }
2603
+
2604
+ dispatch_async (xmppQueue, ^{ @autoreleasepool {
2605
+
2606
+ [self continueHandleBinding: alternativeResource];
2607
+
2608
+ }});
2609
+
2610
+ }});
2611
+ }
2616
2612
}
2613
+ else
2614
+ {
2615
+ // Appears to be a conflicting resource, but server didn't specify conflict
2616
+ [self continueHandleBinding: nil ];
2617
+ }
2618
+ }
2619
+ }
2620
+
2621
+ - (void )continueHandleBinding : (NSString *)alternativeResource
2622
+ {
2623
+ if ([alternativeResource length ] > 0 )
2624
+ {
2625
+ // Update myJID
2626
+
2627
+ [self setMyJID_setByClient: [myJID_setByClient jidWithNewResource: alternativeResource]];
2628
+
2629
+ NSXMLElement *resource = [NSXMLElement elementWithName: @" resource" ];
2630
+ [resource setStringValue: alternativeResource];
2631
+
2632
+ NSXMLElement *bind = [NSXMLElement elementWithName: @" bind" xmlns: @" urn:ietf:params:xml:ns:xmpp-bind" ];
2633
+ [bind addChild: resource];
2634
+
2635
+ XMPPIQ *iq = [XMPPIQ iqWithType: @" set" ];
2636
+ [iq addChild: bind];
2637
+
2638
+ NSString *outgoingStr = [iq compactXMLString ];
2639
+ NSData *outgoingData = [outgoingStr dataUsingEncoding: NSUTF8StringEncoding];
2640
+
2641
+ XMPPLogSend (@" SEND: %@ " , outgoingStr);
2642
+ numberOfBytesSent += [outgoingData length ];
2643
+
2644
+ [asyncSocket writeData: outgoingData
2645
+ withTimeout: TIMEOUT_XMPP_WRITE
2646
+ tag: TAG_XMPP_WRITE_STREAM];
2647
+
2648
+ // The state remains in STATE_XMPP_BINDING
2649
+ }
2650
+ else
2651
+ {
2652
+ // We'll simply let the server choose then
2653
+
2654
+ NSXMLElement *bind = [NSXMLElement elementWithName: @" bind" xmlns: @" urn:ietf:params:xml:ns:xmpp-bind" ];
2655
+
2656
+ XMPPIQ *iq = [XMPPIQ iqWithType: @" set" ];
2657
+ [iq addChild: bind];
2658
+
2659
+ NSString *outgoingStr = [iq compactXMLString ];
2660
+ NSData *outgoingData = [outgoingStr dataUsingEncoding: NSUTF8StringEncoding];
2661
+
2662
+ XMPPLogSend (@" SEND: %@ " , outgoingStr);
2663
+ numberOfBytesSent += [outgoingData length ];
2664
+
2665
+ [asyncSocket writeData: outgoingData
2666
+ withTimeout: TIMEOUT_XMPP_WRITE
2667
+ tag: TAG_XMPP_WRITE_STREAM];
2668
+
2669
+ // The state remains in STATE_XMPP_BINDING
2617
2670
}
2618
2671
}
2619
2672
0 commit comments