diff --git a/kordophone/Bridge/MBIMPingPongWebSocket.m b/kordophone/Bridge/MBIMPingPongWebSocket.m index 1802c3b..3e36fae 100644 --- a/kordophone/Bridge/MBIMPingPongWebSocket.m +++ b/kordophone/Bridge/MBIMPingPongWebSocket.m @@ -101,116 +101,62 @@ #pragma mark - Override AsyncSocket Delegate -- (void)socket:(GCDAsyncSocket *)asyncSocket didReadData:(NSData *)data withTag:(long)tag { +- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { + BOOL nextFrameMasked = [[self valueForKey:@"nextFrameMasked"] boolValue]; NSUInteger nextOpCode = [[self valueForKey:@"nextOpCode"] unsignedIntValue]; // sheesh. - NSLog(@"tag: %ld, nextOpCode: %ld", tag, nextOpCode); + NSLog(@"tag: %ld, nextOpCode: %lu", tag, (unsigned long)nextOpCode); - // Handle our custom ping/pong tags + // Handle our custom ping payload tag if (tag == TAG_PING_PAYLOAD) { // We've read the ping payload, now send the pong response - [self sendPongWithPayload:data socket:asyncSocket]; + NSData *payload = data; + + // If the frame was masked, we need to unmask it + if (nextFrameMasked && pendingPingPayload) { + NSMutableData *unmaskedPayload = [data mutableCopy]; + UInt8 *payloadBytes = [unmaskedPayload mutableBytes]; + UInt8 *maskBytes = (UInt8 *)[pendingPingPayload bytes]; + + for (NSUInteger i = 0; i < [data length]; i++) { + payloadBytes[i] ^= maskBytes[i % 4]; + } + payload = [unmaskedPayload copy]; + } + + [self sendPongWithPayload:payload socket:sock]; // Continue reading the next frame [asyncSocket readDataToLength:1 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_PREFIX]; return; } - if (tag == TAG_PONG_SENT) { - // Pong was sent successfully, continue normal operation - return; - } + // Let the parent handle the frame parsing logic first + [super socket:sock didReadData:data withTag:tag]; - // For TAG_PAYLOAD_PREFIX, we need to intercept and handle ping frames - if (tag == TAG_PAYLOAD_PREFIX) { - UInt8 *pFrame = (UInt8 *)[data bytes]; - UInt8 frame = *pFrame; - - // Check if this is a valid WebSocket frame - if (![self isValidWebSocketFrame:frame]) { - [self didClose]; - return; - } - - NSUInteger opcode = frame & 0x0F; - - // Handle ping frames specially - if (opcode == WS_OP_PING) { - // Read the payload length byte next - [asyncSocket readDataToLength:1 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_LENGTH]; - return; - } - - // Handle pong frames (just log and continue) - if (opcode == WS_OP_PONG) { - NSLog(@"Received pong frame"); - // Read the payload length byte next, but we'll ignore pong payloads - [asyncSocket readDataToLength:1 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_LENGTH]; - return; - } - } - - // For TAG_PAYLOAD_LENGTH, check if we're handling a ping - if (tag == TAG_PAYLOAD_LENGTH) { - UInt8 frame = *(UInt8 *)[data bytes]; - BOOL masked = (frame & 0x80) != 0; - NSUInteger length = frame & 0x7F; - - // If we were processing a ping frame, handle the payload reading + // 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) { - if (length <= 125) { - if (masked) { - // Read masking key first, then payload - [asyncSocket readDataToLength:4 withTimeout:TIMEOUT_NONE tag:TAG_MSG_MASKING_KEY]; - } - // Read ping payload - [asyncSocket readDataToLength:length withTimeout:TIMEOUT_NONE tag:TAG_PING_PAYLOAD]; - return; - } - else if (length == 126) { - [asyncSocket readDataToLength:2 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_LENGTH16]; - return; - } - else { - [asyncSocket readDataToLength:8 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_LENGTH64]; - return; - } + // 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; } - - // If we were processing a pong frame, just skip it - if (nextOpCode == WS_OP_PONG) { - if (length <= 125) { - if (masked) { - [asyncSocket readDataToLength:4 withTimeout:TIMEOUT_NONE tag:TAG_MSG_MASKING_KEY]; - } - // Skip pong payload and continue to next frame - [asyncSocket readDataToLength:length withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_PREFIX]; - return; - } - else if (length == 126) { - [asyncSocket readDataToLength:2 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_LENGTH16]; - return; - } - else { - [asyncSocket readDataToLength:8 withTimeout:TIMEOUT_NONE tag:TAG_PAYLOAD_LENGTH64]; - 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; } } - - // Handle masking key reading for ping frames - if (tag == TAG_MSG_MASKING_KEY && nextOpCode == WS_OP_PING) { - // Store the masking key and read the actual payload - pendingPingPayload = [data copy]; - // The payload length was already determined, read it - // Note: This is a simplified version - you'd need to track the actual length - return; - } - - // For all other cases, call the parent implementation - [super socket:asyncSocket didReadData:data withTag:tag]; } + #pragma mark - Helper Methods // Expose the isValidWebSocketFrame method since it's private in the parent