Private
Public Access
1
0

now actually handle pong

This commit is contained in:
2025-06-13 14:47:47 -07:00
parent a9c2f5d93e
commit e1ec237053

View File

@@ -102,8 +102,10 @@
#pragma mark - Override AsyncSocket Delegate #pragma mark - Override AsyncSocket Delegate
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
// xxx: sheesh: really need to get off of CococaHTTPServer.
NSData *maskingKey = [self valueForKey:@"maskingKey"];
BOOL nextFrameMasked = [[self valueForKey:@"nextFrameMasked"] boolValue]; BOOL nextFrameMasked = [[self valueForKey:@"nextFrameMasked"] boolValue];
NSUInteger nextOpCode = [[self valueForKey:@"nextOpCode"] unsignedIntValue]; // sheesh. NSUInteger nextOpCode = [[self valueForKey:@"nextOpCode"] unsignedIntValue];
NSLog(@"tag: %ld, nextOpCode: %lu", tag, (unsigned long)nextOpCode); NSLog(@"tag: %ld, nextOpCode: %lu", tag, (unsigned long)nextOpCode);
@@ -113,10 +115,10 @@
NSData *payload = data; NSData *payload = data;
// If the frame was masked, we need to unmask it // If the frame was masked, we need to unmask it
if (nextFrameMasked && pendingPingPayload) { if (nextFrameMasked && maskingKey) {
NSMutableData *unmaskedPayload = [data mutableCopy]; NSMutableData *unmaskedPayload = [data mutableCopy];
UInt8 *payloadBytes = [unmaskedPayload mutableBytes]; UInt8 *payloadBytes = [unmaskedPayload mutableBytes];
UInt8 *maskBytes = (UInt8 *)[pendingPingPayload bytes]; UInt8 *maskBytes = (UInt8 *)[maskingKey bytes];
for (NSUInteger i = 0; i < [data length]; i++) { for (NSUInteger i = 0; i < [data length]; i++) {
payloadBytes[i] ^= maskBytes[i % 4]; payloadBytes[i] ^= maskBytes[i % 4];
@@ -131,29 +133,60 @@
return; return;
} }
// Let the parent handle the frame parsing logic first // Intercept after masking key is read for ping/pong frames
if (tag == TAG_MSG_MASKING_KEY && (nextOpCode == WS_OP_PING || nextOpCode == WS_OP_PONG)) {
// Store the masking key
maskingKey = [data copy];
// We need to determine the payload length and read it
// The parent class should have stored this somewhere, but we'll need to track it
// For now, let's assume short payload and read what was scheduled
return;
}
// Intercept the payload length phase for ping/pong frames
if (tag == TAG_PAYLOAD_LENGTH && (nextOpCode == WS_OP_PING || nextOpCode == WS_OP_PONG)) {
UInt8 frame = *(UInt8 *)[data bytes];
BOOL masked = (frame & 0x80) != 0;
NSUInteger length = frame & 0x7F;
nextFrameMasked = masked;
if (length <= 125) {
if (nextFrameMasked) {
[asyncSocket readDataToLength:4 withTimeout:TIMEOUT_NONE tag:TAG_MSG_MASKING_KEY];
}
[asyncSocket readDataToLength:length withTimeout:TIMEOUT_NONE tag:TAG_PING_PAYLOAD];
}
else if (length == 126) {
[asyncSocket readDataToLength:2 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_LENGTH16];
}
else {
[asyncSocket readDataToLength:8 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_LENGTH64];
}
return;
}
// Handle extended length for ping/pong
if ((tag == TAG_PAYLOAD_LENGTH16 || tag == TAG_PAYLOAD_LENGTH64) && (nextOpCode == WS_OP_PING || nextOpCode == WS_OP_PONG)) {
NSUInteger length = 0;
if (tag == TAG_PAYLOAD_LENGTH16) {
UInt8 *pFrame = (UInt8 *)[data bytes];
length = ((NSUInteger)pFrame[0] << 8) | (NSUInteger)pFrame[1];
} else {
// For 64-bit length, this is complex - for now just close
[self didClose];
return;
}
if (nextFrameMasked) {
[asyncSocket readDataToLength:4 withTimeout:TIMEOUT_NONE tag:TAG_MSG_MASKING_KEY];
}
[asyncSocket readDataToLength:length withTimeout:TIMEOUT_NONE tag:TAG_PING_PAYLOAD];
return;
}
// For all other cases, call the parent implementation
[super socket:sock didReadData:data withTag:tag]; [super socket:sock didReadData:data withTag:tag];
// After the parent has processed, check if we need to handle ping/pong
if (tag == TAG_MSG_WITH_LENGTH) {
// The parent just finished reading a complete message
if (nextOpCode == WS_OP_PING) {
// This was a ping frame - the parent would have tried to process it as text
// We need to send a pong response
NSData *payload = data;
// If the frame was masked, unmask it (parent already did this)
[self sendPongWithPayload:payload socket:sock];
// Don't call didReceiveMessage for ping frames
return;
}
else if (nextOpCode == WS_OP_PONG) {
// This was a pong frame - just log it and continue
NSLog(@"Received pong frame with payload length: %lu", (unsigned long)[data length]);
return;
}
}
} }