socket.IO-objc icon indicating copy to clipboard operation
socket.IO-objc copied to clipboard

failed to connect to server is wrongly treated as handshake error

Open shekhei opened this issue 12 years ago • 3 comments

line 611 onwards socketio.m

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{
    NSLog(@"ERROR: handshake failed ... %@", [error localizedDescription]);

    _isConnected = NO;
    _isConnecting = NO;

    if ([_delegate respondsToSelector:@selector(socketIO:onError:)]) {
        NSMutableDictionary *errorInfo = [NSDictionary dictionaryWithObject:error forKey:NSLocalizedDescriptionKey];

        NSError *err = [NSError errorWithDomain:SocketIOError
                                           code:SocketIOHandshakeFailed
                                       userInfo:errorInfo];

        [_delegate socketIO:self onError:err];
    }
    // TODO: deprecated - to be removed
    else if ([_delegate respondsToSelector:@selector(socketIOHandshakeFailed:)]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [_delegate socketIOHandshakeFailed:self];
#pragma clang diagnostic pop
    }
}

Even if the server was not reachable, it is being handled as handshake error, i suggest fixing it by adding a new error type, namely SocketIOServerCouldNotBeReached

//socketio.h
typedef enum {
    SocketIOServerRespondedWithInvalidConnectionData = -1,
    SocketIOServerRespondedWithDisconnect = -2,
    SocketIOHeartbeatTimeout = -3,
    SocketIOWebSocketClosed = -4,
    SocketIOTransportsNotSupported = -5,
    SocketIOHandshakeFailed = -6,
    SocketIODataCouldNotBeSend = -7,
    SocketIOServerCouldNotBeReached = -8,
} SocketIOErrorCodes;

and perhaps something along this line

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{
    NSLog(@"ERROR: handshake failed ... %@, %d", [error localizedDescription], [error code]);

    _isConnected = NO;
    _isConnecting = NO;

    if ([_delegate respondsToSelector:@selector(socketIO:onError:)]) {
        NSMutableDictionary *errorInfo = [NSDictionary dictionaryWithObject:error forKey:NSLocalizedDescriptionKey];
        NSError *err = nil;
        if ( 403 == error.code ) { // forbidden, according to the code in socket.io https://github.com/LearnBoost/socket.io/blob/0.9.14/lib/manager.js#L812
            err = [NSError errorWithDomain:SocketIOError
                                           code:SocketIOHandshakeFailed
                                       userInfo:errorInfo];
        } else if ( -1002 == error.code ) { // failed to reach server
            err = [NSError errorWithDomain:SocketIOError
                                      code:SocketIOServerCouldNotBeReached
                                  userInfo:errorInfo];
        }
        [_delegate socketIO:self onError:err];
    }
    // TODO: deprecated - to be removed
    else if ([_delegate respondsToSelector:@selector(socketIOHandshakeFailed:)] && 403 == error.code) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [_delegate socketIOHandshakeFailed:self];
#pragma clang diagnostic pop
    }
}

but of course written properly with maybe a mapping of error with the error code or something

shekhei avatar Apr 24 '13 08:04 shekhei

seems like under the connection errors, apple has a lot of different error codes...

kCFURLErrorUnknown   = -998,
   kCFURLErrorCancelled = -999,
   kCFURLErrorBadURL    = -1000,
   kCFURLErrorTimedOut  = -1001,
   kCFURLErrorUnsupportedURL = -1002,
   kCFURLErrorCannotFindHost = -1003,
   kCFURLErrorCannotConnectToHost    = -1004,
   kCFURLErrorNetworkConnectionLost  = -1005,
   kCFURLErrorDNSLookupFailed        = -1006,
   kCFURLErrorHTTPTooManyRedirects   = -1007,
   kCFURLErrorResourceUnavailable    = -1008,
   kCFURLErrorNotConnectedToInternet = -1009,
   kCFURLErrorRedirectToNonExistentLocation = -1010,
   kCFURLErrorBadServerResponse             = -1011,
   kCFURLErrorUserCancelledAuthentication   = -1012,
   kCFURLErrorUserAuthenticationRequired    = -1013,
   kCFURLErrorZeroByteResource        = -1014,
   kCFURLErrorCannotDecodeRawData     = -1015,
   kCFURLErrorCannotDecodeContentData = -1016,
   kCFURLErrorCannotParseResponse     = -1017,
   kCFURLErrorInternationalRoamingOff = -1018,
   kCFURLErrorCallIsActive               = -1019,
   kCFURLErrorDataNotAllowed             = -1020,
   kCFURLErrorRequestBodyStreamExhausted = -1021,
   kCFURLErrorFileDoesNotExist           = -1100,
   kCFURLErrorFileIsDirectory            = -1101,
   kCFURLErrorNoPermissionsToReadFile    = -1102,
   kCFURLErrorDataLengthExceedsMaximum   = -1103,

shekhei avatar Apr 24 '13 09:04 shekhei

the easiest thing would be to add the error.code to the errorInfo then you can handle the "handshake error" differently depending on the errorcode in your application.

pkyeck avatar Apr 25 '13 10:04 pkyeck

well i suppose that can be done too, but that wouldnt be a very accurate representation of the true error wouldnt it? And this is a very general error, that is triggered by NSURLConnection. Of course, arguable since the only thing NSURLConnection is doing currently is for handshake?

I actually forked and implemented something similar to what I suggested and it seems to work, so what is your call for this? Since i think this really does cause certain problems in the long run, like for my case, if handshake failed I unauthenticate the app and if it cannot be reached it will just run offline mode

Edit: I meant if this is not fixed it can e a problem for some people in the long run

shekhei avatar Apr 25 '13 10:04 shekhei