MBWebSocketServer icon indicating copy to clipboard operation
MBWebSocketServer copied to clipboard

Occasionally header gets corrupted

Open hongkongkiwi opened this issue 13 years ago • 3 comments

Sometimes the header key gets corrupted at the server (somewhere) before hashing and it is sent back as the wrong key to the client.

See the following log

MBWebSocketServer Concatenated Key: 83x1Pg9CUHJtPIJxX0cAyQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
WebSocketClient Concatenated Key: ai0oBykize/qngGfSrH3Sw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11

It looks like there is an issue when reading the key before it gets to the hashing stage. This only happens maybe 1/20 times.

hongkongkiwi avatar Dec 18 '12 08:12 hongkongkiwi

I found that the issue was with SocketRocket sending a duplicate header with different keys, so nothing to do with this project. The issue is as follows, the handshake gets sent twice (for whatever reason) and MBWebscketServer only processes the first handshake instead of the latest one.

Although not directly a bug in this project, it would be good to add a little bit of logic to check for multiple instances of the handshake and only process the last one. This would make it much more robust. I'll submit some code tomorrow for this.

See below for duplicate header:

GET / HTTP/1.1

Host: localhost:8001

Origin: http://localhost:8001/

Sec-WebSocket-Key: KO3jnDW54UHeLHiAscOF2Q==

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Version: 13



GET / HTTP/1.1

Host: localhost:8001

Origin: http://localhost:8001/

Sec-WebSocket-Key: 4L5fa8w2NqxQeLKs4Y9JZQ==

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Version: 13

hongkongkiwi avatar Dec 18 '12 10:12 hongkongkiwi

For anybody else who encounters this problem, here's my fix which only fixes the problem if there's duplicate headers sent:

Pass the string to new method in handshakeResponseForData:(NSData *)data after the string is created

// MBWebSocketServer.m
    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    // This is a check to see if there are duplicate headers
    [self fixDuplicateHeader:&string];

Add this method to MBWebSocketServer.m to remove any duplicate header

// MBWebSocketServer.m
- (void)fixDuplicateHeader:(NSString **)headerString {
    // Setup
    NSString *lastHandshake = @"";
    NSString *getStr = @"GET / HTTP/1.1\r\n";
    NSScanner *scanner = [NSScanner scannerWithString:*headerString];

    [scanner scanUpToString:getStr intoString:&lastHandshake]; // Scan all characters before GET str
    if (lastHandshake) {
        while (![scanner isAtEnd]) {
            [scanner setScanLocation:([scanner scanLocation]+getStr.length)];
            //[scanner scanString:@"GET / HTTP/1.1\r\n" intoString:nil]; // Scan the GET str
            [scanner scanUpToString:getStr intoString:&lastHandshake]; // Scan all characters before next GET str
        }
        *headerString = [NSString stringWithFormat:@"%@%@",getStr,lastHandshake];
        NSLog(@"[Server] Removed a duplicate header sent from client");
    }
}

hongkongkiwi avatar Dec 19 '12 02:12 hongkongkiwi

We should handle this properly, even if SocketRocket is behaving badly to trigger it.

mxcl avatar Jan 09 '13 16:01 mxcl