diff --git a/CHANGLOG.md b/CHANGLOG.md index 8f6bc14..fa4c3f7 100644 --- a/CHANGLOG.md +++ b/CHANGLOG.md @@ -3,6 +3,8 @@ Change Log ### master (unreleased) +* Add underlying error reason code + ### 0.6.1 (2015-01-14) * Add SSL handshake error codes diff --git a/Classes/NWPushFeedback.m b/Classes/NWPushFeedback.m index a18b2c0..b0fb6c8 100644 --- a/Classes/NWPushFeedback.m +++ b/Classes/NWPushFeedback.m @@ -73,7 +73,7 @@ - (BOOL)readTokenData:(NSData **)token date:(NSDate **)date error:(NSError *__au return read; } if (length != data.length) { - return [NWErrorUtil noWithErrorCode:kNWErrorFeedbackLength error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorFeedbackLength reason:length error:error]; } uint32_t time = 0; [data getBytes:&time range:NSMakeRange(0, 4)]; @@ -82,7 +82,7 @@ - (BOOL)readTokenData:(NSData **)token date:(NSDate **)date error:(NSError *__au [data getBytes:&l range:NSMakeRange(4, 2)]; NSUInteger tokenLength = htons(l); if (tokenLength != NWTokenMaxSize) { - return [NWErrorUtil noWithErrorCode:kNWErrorFeedbackTokenLength error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorFeedbackTokenLength reason:tokenLength error:error]; } *token = [data subdataWithRange:NSMakeRange(6, length - 6)]; return YES; diff --git a/Classes/NWPusher.m b/Classes/NWPusher.m index 4178eba..8ee446e 100644 --- a/Classes/NWPusher.m +++ b/Classes/NWPusher.m @@ -82,7 +82,7 @@ - (BOOL)pushNotification:(NWNotification *)notification type:(NWNotificationType return written; } if (length != data.length) { - return [NWErrorUtil noWithErrorCode:kNWErrorPushWriteFail error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorPushWriteFail reason:length error:error]; } return YES; } @@ -101,7 +101,7 @@ - (BOOL)readFailedIdentifier:(NSUInteger *)identifier apnError:(NSError *__autor uint8_t command = 0; [data getBytes:&command range:NSMakeRange(0, 1)]; if (command != 8) { - return [NWErrorUtil noWithErrorCode:kNWErrorPushResponseCommand error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorPushResponseCommand reason:command error:error]; } uint8_t status = 0; [data getBytes:&status range:NSMakeRange(1, 1)]; @@ -118,7 +118,7 @@ - (BOOL)readFailedIdentifier:(NSUInteger *)identifier apnError:(NSError *__autor case 7: [NWErrorUtil noWithErrorCode:kNWErrorAPNInvalidPayloadSize error:apnError]; break; case 8: [NWErrorUtil noWithErrorCode:kNWErrorAPNInvalidTokenContent error:apnError]; break; case 10: [NWErrorUtil noWithErrorCode:kNWErrorAPNShutdown error:apnError]; break; - default: [NWErrorUtil noWithErrorCode:kNWErrorAPNUnknownErrorCode error:apnError]; break; + default: [NWErrorUtil noWithErrorCode:kNWErrorAPNUnknownErrorCode reason:status error:apnError]; break; } return YES; } diff --git a/Classes/NWSSLConnection.m b/Classes/NWSSLConnection.m index 91379f5..a7695ff 100644 --- a/Classes/NWSSLConnection.m +++ b/Classes/NWSSLConnection.m @@ -68,7 +68,7 @@ - (BOOL)connectSocketWithError:(NSError *__autoreleasing *)error { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { - return [NWErrorUtil noWithErrorCode:kNWErrorSocketCreate error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSocketCreate reason:sock error:error]; } struct sockaddr_in addr; memset(&addr, 0, sizeof(struct sockaddr_in)); @@ -83,15 +83,15 @@ - (BOOL)connectSocketWithError:(NSError *__autoreleasing *)error addr.sin_family = AF_INET; int conn = connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if (conn < 0) { - return [NWErrorUtil noWithErrorCode:kNWErrorSocketConnect error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSocketConnect reason:conn error:error]; } int cntl = fcntl(sock, F_SETFL, O_NONBLOCK); if (cntl < 0) { - return [NWErrorUtil noWithErrorCode:kNWErrorSocketFileControl error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSocketFileControl reason:cntl error:error]; } int set = 1, sopt = setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); if (sopt < 0) { - return [NWErrorUtil noWithErrorCode:kNWErrorSocketOptions error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSocketOptions reason:sopt error:error]; } _socket = sock; return YES; @@ -105,19 +105,19 @@ - (BOOL)connectSSLWithError:(NSError *__autoreleasing *)error } OSStatus setio = SSLSetIOFuncs(context, NWSSLRead, NWSSLWrite); if (setio != errSecSuccess) { - return [NWErrorUtil noWithErrorCode:kNWErrorSSLIOFuncs error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSSLIOFuncs reason:setio error:error]; } OSStatus setconn = SSLSetConnection(context, (SSLConnectionRef)(NSInteger)_socket); if (setconn != errSecSuccess) { - return [NWErrorUtil noWithErrorCode:kNWErrorSSLConnection error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSSLConnection reason:setconn error:error]; } OSStatus setpeer = SSLSetPeerDomainName(context, _host.UTF8String, strlen(_host.UTF8String)); if (setpeer != errSecSuccess) { - return [NWErrorUtil noWithErrorCode:kNWErrorSSLPeerDomainName error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSSLPeerDomainName reason:setpeer error:error]; } OSStatus setcert = SSLSetCertificate(context, (__bridge CFArrayRef)@[_identity]); if (setcert != errSecSuccess) { - return [NWErrorUtil noWithErrorCode:kNWErrorSSLCertificate error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSSLCertificate reason:setcert error:error]; } _context = context; return YES; @@ -141,7 +141,7 @@ - (BOOL)handshakeSSLWithError:(NSError *__autoreleasing *)error case errSSLClientCertRequested: return [NWErrorUtil noWithErrorCode:kNWErrorSSLHandshakeClientCertRequested error:error]; case errSSLServerAuthCompleted: return [NWErrorUtil noWithErrorCode:kNWErrorSSLHandshakeServerAuthCompleted error:error]; } - return [NWErrorUtil noWithErrorCode:kNWErrorSSLHandshakeFail error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorSSLHandshakeFail reason:status error:error]; } - (void)disconnect @@ -166,7 +166,7 @@ - (BOOL)read:(NSMutableData *)data length:(NSUInteger *)length error:(NSError *_ case errSSLClosedAbort: return [NWErrorUtil noWithErrorCode:kNWErrorReadClosedAbort error:error]; case errSSLClosedGraceful: return [NWErrorUtil noWithErrorCode:kNWErrorReadClosedGraceful error:error]; } - return [NWErrorUtil noWithErrorCode:kNWErrorReadFail error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorReadFail reason:status error:error]; } - (BOOL)write:(NSData *)data length:(NSUInteger *)length error:(NSError *__autoreleasing *)error @@ -182,7 +182,7 @@ - (BOOL)write:(NSData *)data length:(NSUInteger *)length error:(NSError *__autor case errSSLClosedAbort: return [NWErrorUtil noWithErrorCode:kNWErrorWriteClosedAbort error:error]; case errSSLClosedGraceful: return [NWErrorUtil noWithErrorCode:kNWErrorWriteClosedGraceful error:error]; } - return [NWErrorUtil noWithErrorCode:kNWErrorWriteFail error:error]; + return [NWErrorUtil noWithErrorCode:kNWErrorWriteFail reason:status error:error]; } @end diff --git a/Classes/NWSecTools.m b/Classes/NWSecTools.m index b01ea65..2e5c6fe 100644 --- a/Classes/NWSecTools.m +++ b/Classes/NWSecTools.m @@ -38,7 +38,7 @@ + (NWIdentityRef)identityWithPKCS12Data:(NSData *)pkcs12 password:(NSString *)pa return [NWErrorUtil nilWithErrorCode:kNWErrorPKCS12NoItems error:error]; } if (identities.count > 1) { - return [NWErrorUtil nilWithErrorCode:kNWErrorPKCS12MultipleItems error:error]; + return [NWErrorUtil nilWithErrorCode:kNWErrorPKCS12MultipleItems reason:identities.count error:error]; } return identities.lastObject; } @@ -208,7 +208,7 @@ + (NWCertificateRef)certificateWithIdentity:(NWIdentityRef)identity error:(NSErr OSStatus status = identity ? SecIdentityCopyCertificate((__bridge SecIdentityRef)identity, &cert) : errSecParam; NWCertificateRef certificate = CFBridgingRelease(cert); if (status != errSecSuccess || !cert) { - return [NWErrorUtil nilWithErrorCode:kNWErrorIdentityCopyCertificate error:error]; + return [NWErrorUtil nilWithErrorCode:kNWErrorIdentityCopyCertificate reason:status error:error]; } return certificate; } @@ -219,7 +219,7 @@ + (NWKeyRef)keyWithIdentity:(NWIdentityRef)identity error:(NSError *__autoreleas OSStatus status = identity ? SecIdentityCopyPrivateKey((__bridge SecIdentityRef)identity, &k) : errSecParam; NWKeyRef key = CFBridgingRelease(k); if (status != errSecSuccess || !k) { - return [NWErrorUtil nilWithErrorCode:kNWErrorIdentityCopyPrivateKey error:error]; + return [NWErrorUtil nilWithErrorCode:kNWErrorIdentityCopyPrivateKey reason:status error:error]; } return key; } @@ -238,7 +238,7 @@ + (NSArray *)allIdentitiesWithPKCS12Data:(NSData *)data password:(NSString *)pas case errSecPkcs12VerifyFailure: return [NWErrorUtil nilWithErrorCode:kNWErrorPKCS12Password error:error]; #endif } - return [NWErrorUtil nilWithErrorCode:kNWErrorPKCS12Import error:error]; + return [NWErrorUtil nilWithErrorCode:kNWErrorPKCS12Import reason:status error:error]; } return dicts; } @@ -251,7 +251,7 @@ + (NSArray *)allKeychainCertificatesWithError:(NSError *__autoreleasing *)error OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)options, (CFTypeRef *)&certs); NSArray *certificates = CFBridgingRelease(certs); if (status != errSecSuccess || !certs) { - return [NWErrorUtil nilWithErrorCode:kNWErrorKeychainCopyMatching error:error]; + return [NWErrorUtil nilWithErrorCode:kNWErrorKeychainCopyMatching reason:status error:error]; } return certificates; } @@ -266,7 +266,7 @@ + (NWIdentityRef)keychainIdentityWithCertificate:(NWCertificateRef)certificate e switch (status) { case errSecItemNotFound: return [NWErrorUtil nilWithErrorCode:kNWErrorKeychainItemNotFound error:error]; } - return [NWErrorUtil nilWithErrorCode:kNWErrorKeychainCreateIdentity error:error]; + return [NWErrorUtil nilWithErrorCode:kNWErrorKeychainCreateIdentity reason:status error:error]; } return identity; } diff --git a/Classes/NWType.h b/Classes/NWType.h index 2baffba..27076d1 100644 --- a/Classes/NWType.h +++ b/Classes/NWType.h @@ -164,8 +164,10 @@ typedef NS_ENUM(NSInteger, NWError) { /** Assigns the error with provided code and associated description, for returning `NO`. */ + (BOOL)noWithErrorCode:(NWError)code error:(NSError **)error; ++ (BOOL)noWithErrorCode:(NWError)code reason:(NSInteger)reason error:(NSError **)error; /** Assigns the error with provided code and associated description, for returning `nil`. */ + (id)nilWithErrorCode:(NWError)code error:(NSError **)error; ++ (id)nilWithErrorCode:(NWError)code reason:(NSInteger)reason error:(NSError **)error; @end diff --git a/Classes/NWType.m b/Classes/NWType.m index 749721b..14a230b 100644 --- a/Classes/NWType.m +++ b/Classes/NWType.m @@ -85,23 +85,35 @@ + (NSString *)stringWithCode:(NWError)code #pragma mark - Helpers -+ (NSError *)errorWithErrorCode:(NWError)code ++ (NSError *)errorWithErrorCode:(NWError)code reason:(NSInteger)reason { - NSDictionary *info = @{ NSLocalizedDescriptionKey: [self stringWithCode:code] }; + NSString *description = [self stringWithCode:code]; + if (reason) description = [NSString stringWithFormat:@"%@ (%li)", description, reason]; + NSDictionary *info = @{ NSLocalizedDescriptionKey:description }; return [NSError errorWithDomain:@"NWPusherErrorDomain" code:code userInfo:info]; } + (BOOL)noWithErrorCode:(NWError)code error:(NSError *__autoreleasing *)error +{ + return [self noWithErrorCode:code reason:0 error:error]; +} + ++ (BOOL)noWithErrorCode:(NWError)code reason:(NSInteger)reason error:(NSError *__autoreleasing *)error { NSAssert(code != kNWErrorNone, @"code != kNWErrorNone"); - if (error) *error = [self errorWithErrorCode:code]; + if (error) *error = [self errorWithErrorCode:code reason:reason]; return NO; } + (id)nilWithErrorCode:(NWError)code error:(NSError *__autoreleasing *)error +{ + return [self nilWithErrorCode:code reason:0 error:error]; +} + ++ (id)nilWithErrorCode:(NWError)code reason:(NSInteger)reason error:(NSError *__autoreleasing *)error { NSAssert(code != kNWErrorNone, @"code != kNWErrorNone"); - if (error) *error = [self errorWithErrorCode:code]; + if (error) *error = [self errorWithErrorCode:code reason:reason]; return nil; }