Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebSocket Connection is not closing using SocketRocket

I use the SocketRocket library for Objective-C to connect to a websocket:

-(void)open {

if( self.webSocket ) {
    [self.webSocket close];
    self.webSocket.delegate = nil;
}

self.webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://192.168.0.254:5864"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20]];
self.webSocket.delegate = self;
[self.webSocket open];
}

Opening the connection works totally fine. The delegate is called after the connection was established.

-(void)webSocketDidOpen:(SRWebSocket *)webSocket {

NSLog(@"WebSocket is open");

}

But when I want to close the connection, nothing happens.

-(void)close {

if( !self.webSocket )
    return;

[self.webSocket close];
self.webSocket.delegate = nil;

}

The delegate for successfully closing the connection is not called. Can anyone tell me why this happens?

Thank you for reading my question.

like image 451
Philipp Otto Avatar asked Mar 20 '13 17:03

Philipp Otto


People also ask

How do I close a WebSocket session?

close() The WebSocket. close() method closes the WebSocket connection or connection attempt, if any. If the connection is already CLOSED , this method does nothing.

How long does WebSocket connection stay open?

However, the connection between a client and your WebSocket app closes when no traffic is sent between them for 60 seconds.

Can WebSockets close servers?

Either the client or the server sends a Close frame (WebSockets borrow a lot of TCP terminology, so you exchange data in “frames”), and the other side sends back its own Close frame in response, and then both parties can close their connections.

Can WebSockets be spoofed?

If you build your websocket over HTTP, then yes, it is completely possible for a third party to spoof the connection (and also to eavesdrop). If your HTTPS/WSS system does not properly validate certificates, then that also can be spoofed.


1 Answers

I figured out that the delegate is never called, because the websocket is never really closed. The closing of the websocket in the SRWebSocket happens in the method pumpWriting like this:

if (_closeWhenFinishedWriting && 
    _outputBuffer.length - _outputBufferOffset == 0 && 
    (_inputStream.streamStatus != NSStreamStatusNotOpen &&
     _inputStream.streamStatus != NSStreamStatusClosed) &&
    !_sentClose) {
    _sentClose = YES;

    [_outputStream close];
    [_inputStream close];

    if (!_failed) {
        dispatch_async(_callbackQueue, ^{
            if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) {
                [self.delegate webSocket:self didCloseWithCode:_closeCode reason:_closeReason wasClean:YES];
            }
        });
    }

    _selfRetain = nil;

    NSLog(@" Is really closed and released ");
}
else {

    NSLog(@" Is NOT closed and released ");
}

All streams and an object to retain the websocket are closed or deleted there. As long as they are still open, the socket won´t be closed appropriately. But the closing never happened in my program, because when I tried to close the websocket, _closeWhenFinishedWriting was always NO.

This boolean is only set once in the disconnect method.

- (void)_disconnect;
{

assert(dispatch_get_current_queue() == _workQueue);
SRFastLog(@"Trying to disconnect");
_closeWhenFinishedWriting = YES;
[self _pumpWriting];

}

But when calling the closeWithCode method in SRWebSocket, disconnect is only called in one case and that is, if the websocket is in the connecting state.

BOOL wasConnecting = self.readyState == SR_CONNECTING;

SRFastLog(@"Closing with code %d reason %@", code, reason);
dispatch_async(_workQueue, ^{

    if (wasConnecting) {
        [self _disconnect];
        return;
    }

This means, if the socket is in another state, the websocket will never really close. One workaround is to always call the disconnect method. At least it worked for me and everything seems to be alright.

If anyone has an idea, why SRWebSocket is implemented like that, please leave a comment for this answer and help me out.

like image 165
Philipp Otto Avatar answered Oct 20 '22 18:10

Philipp Otto