2
2
#import " XMPPParser.h"
3
3
#import " XMPPLogging.h"
4
4
#import " XMPPInternal.h"
5
+ #import " XMPPIDTracker.h"
5
6
#import " XMPPSRVResolver.h"
6
7
#import " NSData+XMPP.h"
7
8
@@ -130,6 +131,8 @@ @interface XMPPStream ()
130
131
XMPPSRVResolver *srvResolver;
131
132
NSArray *srvResults;
132
133
NSUInteger srvResultsIndex;
134
+
135
+ XMPPIDTracker *idTracker;
133
136
134
137
NSMutableArray *receipts;
135
138
@@ -208,6 +211,8 @@ - (void)commonInit
208
211
209
212
registeredModules = [[NSMutableArray alloc ] init ];
210
213
autoDelegateDict = [[NSMutableDictionary alloc ] init ];
214
+
215
+ idTracker = [[XMPPIDTracker alloc ] initWithStream: self dispatchQueue: xmppQueue];
211
216
212
217
receipts = [[NSMutableArray alloc ] init ];
213
218
}
@@ -278,6 +283,8 @@ - (void)dealloc
278
283
dispatch_source_cancel (keepAliveTimer);
279
284
}
280
285
286
+ [idTracker removeAllIDs ];
287
+
281
288
for (XMPPElementReceipt *receipt in receipts)
282
289
{
283
290
[receipt signalFailure ];
@@ -1620,11 +1627,10 @@ - (BOOL)registerWithElements:(NSArray *)elements error:(NSError **)errPtr
1620
1627
[queryElement addChild: element];
1621
1628
}
1622
1629
1623
- NSXMLElement *iqElement = [NSXMLElement elementWithName: @" iq" ];
1624
- [iqElement addAttributeWithName: @" type" stringValue: @" set" ];
1625
- [iqElement addChild: queryElement];
1630
+ XMPPIQ *iq = [XMPPIQ iqWithType: @" set" ];
1631
+ [iq addChild: queryElement];
1626
1632
1627
- NSString *outgoingStr = [iqElement compactXMLString ];
1633
+ NSString *outgoingStr = [iq compactXMLString ];
1628
1634
NSData *outgoingData = [outgoingStr dataUsingEncoding: NSUTF8StringEncoding];
1629
1635
1630
1636
XMPPLogSend (@" SEND: %@ " , outgoingStr);
@@ -3274,9 +3280,7 @@ - (void)handleStreamFeatures
3274
3280
NSXMLElement *bind = [NSXMLElement elementWithName: @" bind" xmlns: @" urn:ietf:params:xml:ns:xmpp-bind" ];
3275
3281
[bind addChild: resource];
3276
3282
3277
- NSXMLElement *iq = [NSXMLElement elementWithName: @" iq" ];
3278
- [iq addAttributeWithName: @" type" stringValue: @" set" ];
3279
- [iq addAttributeWithName: @" id" stringValue: [self generateUUID ]];
3283
+ XMPPIQ *iq = [XMPPIQ iqWithType: @" set" elementID: [self generateUUID ]];
3280
3284
[iq addChild: bind];
3281
3285
3282
3286
NSString *outgoingStr = [iq compactXMLString ];
@@ -3288,16 +3292,19 @@ - (void)handleStreamFeatures
3288
3292
[asyncSocket writeData: outgoingData
3289
3293
withTimeout: TIMEOUT_XMPP_WRITE
3290
3294
tag: TAG_XMPP_WRITE_STREAM];
3295
+
3296
+ [idTracker addElement: iq
3297
+ target: nil
3298
+ selector: NULL
3299
+ timeout: XMPPIDTrackerTimeoutNone];
3291
3300
}
3292
3301
else
3293
3302
{
3294
3303
// The user didn't specify a resource, so we ask the server to bind one for us
3295
3304
3296
3305
NSXMLElement *bind = [NSXMLElement elementWithName: @" bind" xmlns: @" urn:ietf:params:xml:ns:xmpp-bind" ];
3297
3306
3298
- NSXMLElement *iq = [NSXMLElement elementWithName: @" iq" ];
3299
- [iq addAttributeWithName: @" type" stringValue: @" set" ];
3300
- [iq addAttributeWithName: @" id" stringValue: [self generateUUID ]];
3307
+ XMPPIQ *iq = [XMPPIQ iqWithType: @" set" elementID: [self generateUUID ]];
3301
3308
[iq addChild: bind];
3302
3309
3303
3310
NSString *outgoingStr = [iq compactXMLString ];
@@ -3309,6 +3316,11 @@ - (void)handleStreamFeatures
3309
3316
[asyncSocket writeData: outgoingData
3310
3317
withTimeout: TIMEOUT_XMPP_WRITE
3311
3318
tag: TAG_XMPP_WRITE_STREAM];
3319
+
3320
+ [idTracker addElement: iq
3321
+ target: nil
3322
+ selector: NULL
3323
+ timeout: XMPPIDTrackerTimeoutNone];
3312
3324
}
3313
3325
3314
3326
// We're already listening for the response...
@@ -3481,9 +3493,7 @@ - (void)handleBinding:(NSXMLElement *)response
3481
3493
NSXMLElement *session = [NSXMLElement elementWithName: @" session" ];
3482
3494
[session setXmlns: @" urn:ietf:params:xml:ns:xmpp-session" ];
3483
3495
3484
- NSXMLElement *iq = [NSXMLElement elementWithName: @" iq" ];
3485
- [iq addAttributeWithName: @" type" stringValue: @" set" ];
3486
- [iq addAttributeWithName: @" id" stringValue: [self generateUUID ]];
3496
+ XMPPIQ *iq = [XMPPIQ iqWithType: @" set" elementID: [self generateUUID ]];
3487
3497
[iq addChild: session];
3488
3498
3489
3499
NSString *outgoingStr = [iq compactXMLString ];
@@ -3495,6 +3505,11 @@ - (void)handleBinding:(NSXMLElement *)response
3495
3505
[asyncSocket writeData: outgoingData
3496
3506
withTimeout: TIMEOUT_XMPP_WRITE
3497
3507
tag: TAG_XMPP_WRITE_STREAM];
3508
+
3509
+ [idTracker addElement: iq
3510
+ target: nil
3511
+ selector: NULL
3512
+ timeout: XMPPIDTrackerTimeoutNone];
3498
3513
3499
3514
// Update state
3500
3515
state = STATE_XMPP_START_SESSION;
@@ -3601,6 +3616,11 @@ - (void)continueHandleBinding:(NSString *)alternativeResource
3601
3616
[asyncSocket writeData: outgoingData
3602
3617
withTimeout: TIMEOUT_XMPP_WRITE
3603
3618
tag: TAG_XMPP_WRITE_STREAM];
3619
+
3620
+ [idTracker addElement: iq
3621
+ target: nil
3622
+ selector: NULL
3623
+ timeout: XMPPIDTrackerTimeoutNone];
3604
3624
3605
3625
// The state remains in STATE_XMPP_BINDING
3606
3626
}
@@ -3622,6 +3642,11 @@ - (void)continueHandleBinding:(NSString *)alternativeResource
3622
3642
[asyncSocket writeData: outgoingData
3623
3643
withTimeout: TIMEOUT_XMPP_WRITE
3624
3644
tag: TAG_XMPP_WRITE_STREAM];
3645
+
3646
+ [idTracker addElement: iq
3647
+ target: nil
3648
+ selector: NULL
3649
+ timeout: XMPPIDTrackerTimeoutNone];
3625
3650
3626
3651
// The state remains in STATE_XMPP_BINDING
3627
3652
}
@@ -3898,6 +3923,9 @@ - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
3898
3923
// Clear srv results
3899
3924
srvResolver = nil ;
3900
3925
srvResults = nil ;
3926
+
3927
+ // Stop tracking IDs
3928
+ [idTracker removeAllIDs ];
3901
3929
3902
3930
// Clear any pending receipts
3903
3931
for (XMPPElementReceipt *receipt in receipts)
@@ -4010,8 +4038,7 @@ - (void)xmppParser:(XMPPParser *)sender didReadRoot:(NSXMLElement *)root
4010
4038
4011
4039
NSXMLElement *query = [NSXMLElement elementWithName: @" query" xmlns: @" jabber:iq:auth" ];
4012
4040
4013
- NSXMLElement *iq = [NSXMLElement elementWithName: @" iq" ];
4014
- [iq addAttributeWithName: @" type" stringValue: @" get" ];
4041
+ XMPPIQ *iq = [XMPPIQ iqWithType: @" get" elementID: [self generateUUID ]];
4015
4042
[iq addChild: query];
4016
4043
4017
4044
NSString *outgoingStr = [iq compactXMLString ];
@@ -4073,13 +4100,23 @@ - (void)xmppParser:(XMPPParser *)sender didReadElement:(NSXMLElement *)element
4073
4100
}
4074
4101
else if (state == STATE_XMPP_BINDING)
4075
4102
{
4076
- // The response from our binding request
4077
- [self handleBinding: element];
4103
+ XMPPIQ *iq = [XMPPIQ iqFromElement: element];
4104
+
4105
+ if ([idTracker invokeForElement: iq withObject: element])
4106
+ {
4107
+ // The response from our binding request
4108
+ [self handleBinding: element];
4109
+ }
4078
4110
}
4079
4111
else if (state == STATE_XMPP_START_SESSION)
4080
4112
{
4081
- // The response from our start session request
4082
- [self handleStartSessionResponse: element];
4113
+ XMPPIQ *iq = [XMPPIQ iqFromElement: element];
4114
+
4115
+ if ([idTracker invokeForElement: iq withObject: element])
4116
+ {
4117
+ // The response from our start session request
4118
+ [self handleStartSessionResponse: element];
4119
+ }
4083
4120
}
4084
4121
else
4085
4122
{
@@ -4230,6 +4267,49 @@ - (void)keepAlive
4230
4267
}
4231
4268
}
4232
4269
4270
+ // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4271
+ #pragma mark Stanza Validation
4272
+ // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4273
+
4274
+ - (BOOL )isValidResponseElementFrom : (XMPPJID *)from forRequestElementTo : (XMPPJID *)to
4275
+ {
4276
+ BOOL valid = YES ;
4277
+
4278
+ if (to)
4279
+ {
4280
+ if (![to isEqualToJID: from])
4281
+ {
4282
+ valid = NO ;
4283
+ }
4284
+ }
4285
+ /* *
4286
+ * Replies for Stanza's that had no TO will be accepted if the FROM is:
4287
+ *
4288
+ * No from.
4289
+ * from = the bare account JID.
4290
+ * from = the full account JID (legal in 3920, but not 6120).
4291
+ * from = the server's domain.
4292
+ **/
4293
+ else if (!to && from)
4294
+ {
4295
+ if (![from isEqualToJID: self .myJID options: XMPPJIDCompareBare]
4296
+ && ![from isEqualToJID: self .myJID options: XMPPJIDCompareFull]
4297
+ && ![from isEqualToJID: [self .myJID domainJID ] options: XMPPJIDCompareFull])
4298
+ {
4299
+ valid = NO ;
4300
+ }
4301
+ }
4302
+
4303
+ return valid;
4304
+ }
4305
+
4306
+ - (BOOL )isValidResponseElement : (XMPPElement *)response forRequestElement : (XMPPElement *)request
4307
+ {
4308
+ if (!response || !request) return NO ;
4309
+
4310
+ return [self isValidResponseElementFrom: [response from ] forRequestElementTo: [request to ]];
4311
+ }
4312
+
4233
4313
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4234
4314
#pragma mark Module Plug-In System
4235
4315
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0 commit comments