diff --git a/AWSAPIGateway.podspec b/AWSAPIGateway.podspec index 36c307ea3bc..4d23cfa5070 100644 --- a/AWSAPIGateway.podspec +++ b/AWSAPIGateway.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'AWSAPIGateway' - s.version = '2.3.1' + s.version = '2.3.2' s.summary = 'Amazon Web Services SDK for iOS.' s.description = 'The AWS SDK for iOS provides a library, code samples, and documentation for developers to build connected mobile applications using AWS.' @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSAPIGateway/*.{h,m}' end diff --git a/AWSAPIGateway.xcodeproj/project.pbxproj b/AWSAPIGateway.xcodeproj/project.pbxproj index 870eb7383b2..5cdb1250da6 100644 --- a/AWSAPIGateway.xcodeproj/project.pbxproj +++ b/AWSAPIGateway.xcodeproj/project.pbxproj @@ -7,6 +7,15 @@ objects = { /* Begin PBXBuildFile section */ + CE0E82591C16527100D015BA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CED3CFA91C112BC5000AB947 /* libz.tbd */; }; + CE0E825A1C16527500D015BA /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CED3CFAB1C112BC9000AB947 /* libsqlite3.tbd */; }; + CE0E825C1C16528D00D015BA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE0E825B1C16528D00D015BA /* UIKit.framework */; }; + CE0E825D1C16529200D015BA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE0E825B1C16528D00D015BA /* UIKit.framework */; }; + CE100A001C112877008F1A91 /* libAWSAPIGateway.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE6BC1071B4A440B002E2414 /* libAWSAPIGateway.a */; }; + CE100A091C112A58008F1A91 /* libAWSCore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE100A081C112A58008F1A91 /* libAWSCore.a */; }; + CE100A0B1C112AA3008F1A91 /* AWSAPIGatewayUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CE100A061C11289C008F1A91 /* AWSAPIGatewayUnitTests.m */; }; + CE100A0E1C112AF8008F1A91 /* AWSTestUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = CE100A0D1C112AF8008F1A91 /* AWSTestUtility.m */; }; + CE100A0F1C112AF8008F1A91 /* AWSTestUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = CE100A0D1C112AF8008F1A91 /* AWSTestUtility.m */; }; CE2EDE8E1BF3DEDA00B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE65522A1BEC35A300DACBC2 /* module.modulemap */; }; CE6BC1131B4A440C002E2414 /* libAWSAPIGateway.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE6BC1071B4A440B002E2414 /* libAWSAPIGateway.a */; }; CE6BC12C1B4A447D002E2414 /* AWSAPIGatewayClient.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6BC12B1B4A447D002E2414 /* AWSAPIGatewayClient.m */; }; @@ -14,9 +23,23 @@ CEB2AE921B4B3A7300F32474 /* AWSAPIGatewayClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6BC12A1B4A447D002E2414 /* AWSAPIGatewayClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; CEB2AE931B4B3A7A00F32474 /* AWSAPIGateway.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CEB2AE8F1B4B067800F32474 /* AWSAPIGateway.h */; }; CEB2AE941B4B3A7A00F32474 /* AWSAPIGatewayClient.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6BC12A1B4A447D002E2414 /* AWSAPIGatewayClient.h */; }; + CED3CFA81C112BB2000AB947 /* libAWSCore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CED3CFA71C112BB2000AB947 /* libAWSCore.a */; }; + CED3CFAA1C112BC5000AB947 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CED3CFA91C112BC5000AB947 /* libz.tbd */; }; + CED3CFAC1C112BC9000AB947 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CED3CFAB1C112BC9000AB947 /* libsqlite3.tbd */; }; + CED6D9D21C165DBB0030C22F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CED6D9D11C165DBB0030C22F /* SystemConfiguration.framework */; }; + CED6D9D31C165DBF0030C22F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CED6D9D11C165DBB0030C22F /* SystemConfiguration.framework */; }; + CED6D9D51C165DDA0030C22F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CED6D9D41C165DDA0030C22F /* Security.framework */; }; + CED6D9D61C165DE30030C22F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CED6D9D41C165DDA0030C22F /* Security.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + CE100A011C112877008F1A91 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CE6BC0FF1B4A440B002E2414 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CE6BC1061B4A440B002E2414; + remoteInfo = AWSAPIGateway; + }; CE6BC1141B4A440C002E2414 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = CE6BC0FF1B4A440B002E2414 /* Project object */; @@ -51,6 +74,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + CE0E825B1C16528D00D015BA /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + CE1009FB1C112877008F1A91 /* AWSAPIGatewayUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSAPIGatewayUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CE100A061C11289C008F1A91 /* AWSAPIGatewayUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSAPIGatewayUnitTests.m; sourceTree = ""; }; + CE100A081C112A58008F1A91 /* libAWSCore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libAWSCore.a; path = "build/Debug-iphoneos/libAWSCore.a"; sourceTree = ""; }; + CE100A0C1C112AF8008F1A91 /* AWSTestUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWSTestUtility.h; path = AWSCoreTests/AWSTestUtility.h; sourceTree = SOURCE_ROOT; }; + CE100A0D1C112AF8008F1A91 /* AWSTestUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSTestUtility.m; path = AWSCoreTests/AWSTestUtility.m; sourceTree = SOURCE_ROOT; }; CE65522A1BEC35A300DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; CE6BC1071B4A440B002E2414 /* libAWSAPIGateway.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAWSAPIGateway.a; sourceTree = BUILT_PRODUCTS_DIR; }; CE6BC1121B4A440C002E2414 /* AWSAPIGatewayTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSAPIGatewayTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -58,9 +87,28 @@ CE6BC12A1B4A447D002E2414 /* AWSAPIGatewayClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSAPIGatewayClient.h; sourceTree = ""; }; CE6BC12B1B4A447D002E2414 /* AWSAPIGatewayClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSAPIGatewayClient.m; sourceTree = ""; }; CEB2AE8F1B4B067800F32474 /* AWSAPIGateway.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AWSAPIGateway.h; sourceTree = ""; }; + CED3CFA71C112BB2000AB947 /* libAWSCore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libAWSCore.a; path = "build/Debug-iphoneos/libAWSCore.a"; sourceTree = ""; }; + CED3CFA91C112BC5000AB947 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + CED3CFAB1C112BC9000AB947 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; + CED6D9D11C165DBB0030C22F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CED6D9D41C165DDA0030C22F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + CE1009F81C112877008F1A91 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CED6D9D61C165DE30030C22F /* Security.framework in Frameworks */, + CED6D9D31C165DBF0030C22F /* SystemConfiguration.framework in Frameworks */, + CE0E825D1C16529200D015BA /* UIKit.framework in Frameworks */, + CED3CFAC1C112BC9000AB947 /* libsqlite3.tbd in Frameworks */, + CED3CFAA1C112BC5000AB947 /* libz.tbd in Frameworks */, + CE100A091C112A58008F1A91 /* libAWSCore.a in Frameworks */, + CE100A001C112877008F1A91 /* libAWSAPIGateway.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; CE6BC1041B4A440B002E2414 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -72,6 +120,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CED6D9D51C165DDA0030C22F /* Security.framework in Frameworks */, + CED6D9D21C165DBB0030C22F /* SystemConfiguration.framework in Frameworks */, + CE0E825C1C16528D00D015BA /* UIKit.framework in Frameworks */, + CE0E825A1C16527500D015BA /* libsqlite3.tbd in Frameworks */, + CE0E82591C16527100D015BA /* libz.tbd in Frameworks */, + CED3CFA81C112BB2000AB947 /* libAWSCore.a in Frameworks */, CE6BC1131B4A440C002E2414 /* libAWSAPIGateway.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -79,11 +133,26 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + CE100A0A1C112A85008F1A91 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CED6D9D41C165DDA0030C22F /* Security.framework */, + CED6D9D11C165DBB0030C22F /* SystemConfiguration.framework */, + CE0E825B1C16528D00D015BA /* UIKit.framework */, + CED3CFAB1C112BC9000AB947 /* libsqlite3.tbd */, + CED3CFA91C112BC5000AB947 /* libz.tbd */, + CED3CFA71C112BB2000AB947 /* libAWSCore.a */, + CE100A081C112A58008F1A91 /* libAWSCore.a */, + ); + name = Frameworks; + sourceTree = ""; + }; CE6BC0FE1B4A440B002E2414 = { isa = PBXGroup; children = ( CE6BC1091B4A440B002E2414 /* AWSAPIGateway */, CE6BC1161B4A440C002E2414 /* AWSAPIGatewayTests */, + CE100A0A1C112A85008F1A91 /* Frameworks */, CE6BC1081B4A440B002E2414 /* Products */, ); sourceTree = ""; @@ -93,6 +162,7 @@ children = ( CE6BC1071B4A440B002E2414 /* libAWSAPIGateway.a */, CE6BC1121B4A440C002E2414 /* AWSAPIGatewayTests.xctest */, + CE1009FB1C112877008F1A91 /* AWSAPIGatewayUnitTests.xctest */, ); name = Products; sourceTree = ""; @@ -111,6 +181,7 @@ CE6BC1161B4A440C002E2414 /* AWSAPIGatewayTests */ = { isa = PBXGroup; children = ( + CE100A061C11289C008F1A91 /* AWSAPIGatewayUnitTests.m */, CE6BC1171B4A440C002E2414 /* Supporting Files */, ); path = AWSAPIGatewayTests; @@ -119,6 +190,8 @@ CE6BC1171B4A440C002E2414 /* Supporting Files */ = { isa = PBXGroup; children = ( + CE100A0C1C112AF8008F1A91 /* AWSTestUtility.h */, + CE100A0D1C112AF8008F1A91 /* AWSTestUtility.m */, CE6BC1181B4A440C002E2414 /* Info.plist */, ); name = "Supporting Files"; @@ -139,6 +212,24 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + CE1009FA1C112877008F1A91 /* AWSAPIGatewayUnitTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CE100A051C112877008F1A91 /* Build configuration list for PBXNativeTarget "AWSAPIGatewayUnitTests" */; + buildPhases = ( + CE1009F71C112877008F1A91 /* Sources */, + CE1009F81C112877008F1A91 /* Frameworks */, + CE1009F91C112877008F1A91 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CE100A021C112877008F1A91 /* PBXTargetDependency */, + ); + name = AWSAPIGatewayUnitTests; + productName = AWSAPIGatewayUnitTests; + productReference = CE1009FB1C112877008F1A91 /* AWSAPIGatewayUnitTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; CE6BC1061B4A440B002E2414 /* AWSAPIGateway */ = { isa = PBXNativeTarget; buildConfigurationList = CE6BC11B1B4A440C002E2414 /* Build configuration list for PBXNativeTarget "AWSAPIGateway" */; @@ -182,9 +273,12 @@ CE6BC0FF1B4A440B002E2414 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { + CE1009FA1C112877008F1A91 = { + CreatedOnToolsVersion = 7.1.1; + }; CE6BC1061B4A440B002E2414 = { CreatedOnToolsVersion = 6.4; }; @@ -207,11 +301,19 @@ targets = ( CE6BC1061B4A440B002E2414 /* AWSAPIGateway */, CE6BC1111B4A440C002E2414 /* AWSAPIGatewayTests */, + CE1009FA1C112877008F1A91 /* AWSAPIGatewayUnitTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + CE1009F91C112877008F1A91 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; CE6BC1101B4A440C002E2414 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -222,6 +324,15 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + CE1009F71C112877008F1A91 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CE100A0F1C112AF8008F1A91 /* AWSTestUtility.m in Sources */, + CE100A0B1C112AA3008F1A91 /* AWSAPIGatewayUnitTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; CE6BC1031B4A440B002E2414 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -234,12 +345,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + CE100A0E1C112AF8008F1A91 /* AWSTestUtility.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + CE100A021C112877008F1A91 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CE6BC1061B4A440B002E2414 /* AWSAPIGateway */; + targetProxy = CE100A011C112877008F1A91 /* PBXContainerItemProxy */; + }; CE6BC1151B4A440C002E2414 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = CE6BC1061B4A440B002E2414 /* AWSAPIGateway */; @@ -248,6 +365,42 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + CE100A031C112877008F1A91 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + INFOPLIST_FILE = AWSAPIGatewayTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(SYMROOT)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.amazonaws.AWSAPIGatewayUnitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + CE100A041C112877008F1A91 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + INFOPLIST_FILE = AWSAPIGatewayTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(SYMROOT)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.amazonaws.AWSAPIGatewayUnitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; CE6BC1191B4A440C002E2414 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -258,7 +411,8 @@ ); CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_MODULE_DEBUGGING = NO; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -272,6 +426,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -305,7 +460,8 @@ ); CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_MODULE_DEBUGGING = NO; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -344,7 +500,7 @@ DEAD_CODE_STRIPPING = NO; DEFINES_MODULE = YES; MODULEMAP_FILE = "$(PRODUCT_NAME:c99extidentifier)/module.modulemap"; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; STRIP_STYLE = "non-global"; @@ -359,7 +515,7 @@ DEAD_CODE_STRIPPING = NO; DEFINES_MODULE = YES; MODULEMAP_FILE = "$(PRODUCT_NAME:c99extidentifier)/module.modulemap"; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; STRIP_STYLE = "non-global"; @@ -370,16 +526,17 @@ isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = AWSAPIGatewayTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(SYMROOT)", + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -388,12 +545,13 @@ isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = AWSAPIGatewayTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(SYMROOT)", + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -401,6 +559,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + CE100A051C112877008F1A91 /* Build configuration list for PBXNativeTarget "AWSAPIGatewayUnitTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CE100A031C112877008F1A91 /* Debug */, + CE100A041C112877008F1A91 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; CE6BC1021B4A440B002E2414 /* Build configuration list for PBXProject "AWSAPIGateway" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/AWSAPIGateway.xcodeproj/xcshareddata/xcschemes/AWSAPIGateway.xcscheme b/AWSAPIGateway.xcodeproj/xcshareddata/xcschemes/AWSAPIGateway.xcscheme index 93fe9293b70..8e724e4bb29 100644 --- a/AWSAPIGateway.xcodeproj/xcshareddata/xcschemes/AWSAPIGateway.xcscheme +++ b/AWSAPIGateway.xcodeproj/xcshareddata/xcschemes/AWSAPIGateway.xcscheme @@ -1,6 +1,6 @@ = 2) { - for (NSUInteger i = 1; i < [URLPathComponents count] - 1; i++) { - [mutableURLString replaceOccurrencesOfString:[NSString stringWithFormat:@"{%@}", URLPathComponents[i]] - withString:[self encodeQueryStringValue:[URLPathComponentsDictionary valueForKey:URLPathComponents[i]]] - options:NSLiteralSearch - range:NSMakeRange(0, [mutableURLString length])]; - } + for (NSString *key in URLPathComponentsDictionary) { + [mutableURLString replaceOccurrencesOfString:[NSString stringWithFormat:@"{%@}", key] + withString:[self encodeQueryStringValue:URLPathComponentsDictionary[key]] + options:NSLiteralSearch + range:NSMakeRange(0, [mutableURLString length])]; } // Adds query string diff --git a/AWSAPIGatewayTests/Info.plist b/AWSAPIGatewayTests/Info.plist index 55821ba1861..ba72822e872 100644 --- a/AWSAPIGatewayTests/Info.plist +++ b/AWSAPIGatewayTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.amazonaws.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/AWSAutoScaling.podspec b/AWSAutoScaling.podspec index 136d6a1c064..bd1190f1169 100644 --- a/AWSAutoScaling.podspec +++ b/AWSAutoScaling.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'AWSAutoScaling' - s.version = '2.3.1' + s.version = '2.3.2' s.summary = 'Amazon Web Services SDK for iOS.' s.description = 'The AWS SDK for iOS provides a library, code samples, and documentation for developers to build connected mobile applications using AWS.' @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSAutoScaling/*.{h,m}' end diff --git a/AWSAutoScaling.xcodeproj/project.pbxproj b/AWSAutoScaling.xcodeproj/project.pbxproj index d4218bd6bea..67a78a6cd49 100644 --- a/AWSAutoScaling.xcodeproj/project.pbxproj +++ b/AWSAutoScaling.xcodeproj/project.pbxproj @@ -30,6 +30,10 @@ CE27CB401BF17A9500B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB3F1BF17A9500B22AB3 /* UIKit.framework */; }; CE27CB411BF17A9B00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB3F1BF17A9500B22AB3 /* UIKit.framework */; }; CE2EDE901BF3DEEC00B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE65522C1BEC35BD00DACBC2 /* module.modulemap */; }; + CEB3801F1C177EE1008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3801E1C177EE1008B520C /* SystemConfiguration.framework */; }; + CEB380461C177FC1008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3801E1C177EE1008B520C /* SystemConfiguration.framework */; }; + CEB380721C1780D7008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380711C1780D7008B520C /* Security.framework */; }; + CEB380731C1780DB008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380711C1780D7008B520C /* Security.framework */; }; CEE532561B03D1A8002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE532551B03D1A8002CED62 /* libz.dylib */; }; CEE7DE671AC1E0C30095C4B7 /* AWSAutoScalingService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE661AC1E0C30095C4B7 /* AWSAutoScalingService.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -96,6 +100,8 @@ BDF125701B45BF3000DFBFEC /* AWSAutoScalingUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSAutoScalingUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; CE27CB3F1BF17A9500B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE65522C1BEC35BD00DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB3801E1C177EE1008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB380711C1780D7008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE532551B03D1A8002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE661AC1E0C30095C4B7 /* AWSAutoScalingService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWSAutoScalingService.h; path = ../AWSAutoScaling/AWSAutoScalingService.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -112,6 +118,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380721C1780D7008B520C /* Security.framework in Frameworks */, + CEB380461C177FC1008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB401BF17A9500B22AB3 /* UIKit.framework in Frameworks */, CEE532561B03D1A8002CED62 /* libz.dylib in Frameworks */, BD00FF371AB8B683004496EF /* libAWSCore.a in Frameworks */, @@ -123,6 +131,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380731C1780DB008B520C /* Security.framework in Frameworks */, + CEB3801F1C177EE1008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB411BF17A9B00B22AB3 /* UIKit.framework in Frameworks */, BDD876A01B4B4062009268C7 /* libOCMock.a in Frameworks */, BDF125681B45BF3000DFBFEC /* libz.dylib in Frameworks */, @@ -193,6 +203,8 @@ FC5D4AEC7530694251AE5CAE /* Frameworks */ = { isa = PBXGroup; children = ( + CEB380711C1780D7008B520C /* Security.framework */, + CEB3801E1C177EE1008B520C /* SystemConfiguration.framework */, CE27CB3F1BF17A9500B22AB3 /* UIKit.framework */, BDD8769F1B4B4062009268C7 /* libOCMock.a */, CEE532551B03D1A8002CED62 /* libz.dylib */, @@ -279,7 +291,7 @@ BDB5DF141AB37A79002DD224 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDB5DF1B1AB37A79002DD224 = { diff --git a/AWSAutoScaling.xcodeproj/xcshareddata/xcschemes/AWSAutoScaling.xcscheme b/AWSAutoScaling.xcodeproj/xcshareddata/xcschemes/AWSAutoScaling.xcscheme index c0fcb322fc7..13db2dd9aaa 100644 --- a/AWSAutoScaling.xcodeproj/xcshareddata/xcschemes/AWSAutoScaling.xcscheme +++ b/AWSAutoScaling.xcodeproj/xcshareddata/xcschemes/AWSAutoScaling.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSCloudWatch/*.{h,m}' end diff --git a/AWSCloudWatch.xcodeproj/project.pbxproj b/AWSCloudWatch.xcodeproj/project.pbxproj index 376d470394f..d02ae83f185 100644 --- a/AWSCloudWatch.xcodeproj/project.pbxproj +++ b/AWSCloudWatch.xcodeproj/project.pbxproj @@ -29,6 +29,10 @@ CE27CB431BF17AD500B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB421BF17AD500B22AB3 /* UIKit.framework */; }; CE27CB441BF17ADB00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB421BF17AD500B22AB3 /* UIKit.framework */; }; CE2EDE921BF3DF0100B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE65522E1BEC35DE00DACBC2 /* module.modulemap */; }; + CEB380211C177EEB008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380201C177EEB008B520C /* SystemConfiguration.framework */; }; + CEB380451C177FBB008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380201C177EEB008B520C /* SystemConfiguration.framework */; }; + CEB3806F1C1780CE008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3806E1C1780CE008B520C /* Security.framework */; }; + CEB380701C1780D2008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3806E1C1780CE008B520C /* Security.framework */; }; CEE532581B03D332002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE532571B03D332002CED62 /* libz.dylib */; }; CEE7DE691AC1E1330095C4B7 /* AWSCloudWatchService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE681AC1E1330095C4B7 /* AWSCloudWatchService.h */; settings = {ATTRIBUTES = (Public, ); }; }; CEF83EDC1AD3521A00620E1C /* AWSCloudWatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF83ED91AD3521A00620E1C /* AWSCloudWatchTests.m */; }; @@ -93,6 +97,8 @@ BDF559171AB3747F0067F4F1 /* AWSCloudWatchModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSCloudWatchModel.m; path = ../AWSCloudWatch/AWSCloudWatchModel.m; sourceTree = ""; }; CE27CB421BF17AD500B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE65522E1BEC35DE00DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380201C177EEB008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB3806E1C1780CE008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE532571B03D332002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE681AC1E1330095C4B7 /* AWSCloudWatchService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWSCloudWatchService.h; path = ../AWSCloudWatch/AWSCloudWatchService.h; sourceTree = ""; }; CEF83ED91AD3521A00620E1C /* AWSCloudWatchTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSCloudWatchTests.m; path = ../AWSCloudWatchTests/AWSCloudWatchTests.m; sourceTree = ""; }; @@ -105,6 +111,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380701C1780D2008B520C /* Security.framework in Frameworks */, + CEB380211C177EEB008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB441BF17ADB00B22AB3 /* UIKit.framework in Frameworks */, BDD876A21B4B5247009268C7 /* libOCMock.a in Frameworks */, BDF1257A1B45BFE500DFBFEC /* libz.dylib in Frameworks */, @@ -124,6 +132,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3806F1C1780CE008B520C /* Security.framework in Frameworks */, + CEB380451C177FBB008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB431BF17AD500B22AB3 /* UIKit.framework in Frameworks */, CEE532581B03D332002CED62 /* libz.dylib in Frameworks */, BD00FF4B1AB8B700004496EF /* libAWSCore.a in Frameworks */, @@ -137,6 +147,8 @@ 2953C160B39FCEC4E052451B /* Frameworks */ = { isa = PBXGroup; children = ( + CEB3806E1C1780CE008B520C /* Security.framework */, + CEB380201C177EEB008B520C /* SystemConfiguration.framework */, CE27CB421BF17AD500B22AB3 /* UIKit.framework */, BDD876A11B4B5247009268C7 /* libOCMock.a */, CEE532571B03D332002CED62 /* libz.dylib */, @@ -279,7 +291,7 @@ BDF558F01AB374250067F4F1 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDF558F71AB374250067F4F1 = { diff --git a/AWSCloudWatch.xcodeproj/xcshareddata/xcschemes/AWSCloudWatch.xcscheme b/AWSCloudWatch.xcodeproj/xcshareddata/xcschemes/AWSCloudWatch.xcscheme index 6ec48a62584..b1d9d0d2d5b 100644 --- a/AWSCloudWatch.xcodeproj/xcshareddata/xcschemes/AWSCloudWatch.xcscheme +++ b/AWSCloudWatch.xcodeproj/xcshareddata/xcschemes/AWSCloudWatch.xcscheme @@ -1,6 +1,6 @@ + + + + + + + + + + + + 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSDynamoDB/*.{h,m}' end diff --git a/AWSDynamoDB.xcodeproj/project.pbxproj b/AWSDynamoDB.xcodeproj/project.pbxproj index e03f29b7590..d8b3f685cac 100644 --- a/AWSDynamoDB.xcodeproj/project.pbxproj +++ b/AWSDynamoDB.xcodeproj/project.pbxproj @@ -35,6 +35,10 @@ CE27CB531BF1861700B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB521BF1861700B22AB3 /* UIKit.framework */; }; CE27CB541BF1861C00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB521BF1861700B22AB3 /* UIKit.framework */; }; CE2EDE8A1BF3DE1800B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6552301BEC35F400DACBC2 /* module.modulemap */; }; + CEB380231C177EF4008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380221C177EF4008B520C /* SystemConfiguration.framework */; }; + CEB380441C177FB6008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380221C177EF4008B520C /* SystemConfiguration.framework */; }; + CEB3806C1C1780C5008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3806B1C1780C5008B520C /* Security.framework */; }; + CEB3806D1C1780CA008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3806B1C1780C5008B520C /* Security.framework */; }; CEE5325A1B03D374002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE532591B03D374002CED62 /* libz.dylib */; }; CEE7DE6B1AC1E1500095C4B7 /* AWSDynamoDBService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE6A1AC1E1500095C4B7 /* AWSDynamoDBService.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -107,6 +111,8 @@ BDF559481AB375260067F4F1 /* AWSDynamoDBObjectMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSDynamoDBObjectMapper.m; path = ../AWSDynamoDB/AWSDynamoDBObjectMapper.m; sourceTree = ""; }; CE27CB521BF1861700B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE6552301BEC35F400DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380221C177EF4008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB3806B1C1780C5008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE532591B03D374002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE6A1AC1E1500095C4B7 /* AWSDynamoDBService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWSDynamoDBService.h; path = ../AWSDynamoDB/AWSDynamoDBService.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -116,6 +122,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3806D1C1780CA008B520C /* Security.framework in Frameworks */, + CEB380231C177EF4008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB541BF1861C00B22AB3 /* UIKit.framework in Frameworks */, BDD876A41B4B52AE009268C7 /* libOCMock.a in Frameworks */, BDF125921B45C12600DFBFEC /* libz.dylib in Frameworks */, @@ -135,6 +143,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3806C1C1780C5008B520C /* Security.framework in Frameworks */, + CEB380441C177FB6008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB531BF1861700B22AB3 /* UIKit.framework in Frameworks */, CEE5325A1B03D374002CED62 /* libz.dylib in Frameworks */, BD00FF491AB8B6F8004496EF /* libAWSCore.a in Frameworks */, @@ -148,6 +158,8 @@ A5F6D5DAB609D2CE34387FFD /* Frameworks */ = { isa = PBXGroup; children = ( + CEB3806B1C1780C5008B520C /* Security.framework */, + CEB380221C177EF4008B520C /* SystemConfiguration.framework */, CE27CB521BF1861700B22AB3 /* UIKit.framework */, BDD876A31B4B52AE009268C7 /* libOCMock.a */, CEE532591B03D374002CED62 /* libz.dylib */, @@ -297,7 +309,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDF559261AB374F00067F4F1 = { diff --git a/AWSDynamoDB.xcodeproj/xcshareddata/xcschemes/AWSDynamoDB.xcscheme b/AWSDynamoDB.xcodeproj/xcshareddata/xcschemes/AWSDynamoDB.xcscheme index 6b6ec20b5ba..be8fc805bb1 100644 --- a/AWSDynamoDB.xcodeproj/xcshareddata/xcschemes/AWSDynamoDB.xcscheme +++ b/AWSDynamoDB.xcodeproj/xcshareddata/xcschemes/AWSDynamoDB.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSEC2/*.{h,m}' end diff --git a/AWSEC2.xcodeproj/project.pbxproj b/AWSEC2.xcodeproj/project.pbxproj index 2655e65d9d9..2e8fe69366d 100644 --- a/AWSEC2.xcodeproj/project.pbxproj +++ b/AWSEC2.xcodeproj/project.pbxproj @@ -30,6 +30,10 @@ CE27CB561BF187E400B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB551BF187E400B22AB3 /* UIKit.framework */; }; CE27CB571BF187EA00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB551BF187E400B22AB3 /* UIKit.framework */; }; CE2EDE941BF3DF1300B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6552321BEC360700DACBC2 /* module.modulemap */; }; + CEB380251C177EFE008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380241C177EFE008B520C /* SystemConfiguration.framework */; }; + CEB380431C177FB1008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380241C177EFE008B520C /* SystemConfiguration.framework */; }; + CEB380691C1780BD008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380681C1780BD008B520C /* Security.framework */; }; + CEB3806A1C1780C0008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380681C1780BD008B520C /* Security.framework */; }; CEE5326C1B03D3C4002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE5326B1B03D3C4002CED62 /* libz.dylib */; }; CEE7DE6D1AC1E1780095C4B7 /* AWSEC2Service.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE6C1AC1E1780095C4B7 /* AWSEC2Service.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -96,6 +100,8 @@ BDF559791AB375AE0067F4F1 /* AWSEC2Model.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSEC2Model.m; path = ../AWSEC2/AWSEC2Model.m; sourceTree = ""; }; CE27CB551BF187E400B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE6552321BEC360700DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380241C177EFE008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB380681C1780BD008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE5326B1B03D3C4002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE6C1AC1E1780095C4B7 /* AWSEC2Service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWSEC2Service.h; path = ../AWSEC2/AWSEC2Service.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -105,6 +111,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3806A1C1780C0008B520C /* Security.framework in Frameworks */, + CEB380251C177EFE008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB571BF187EA00B22AB3 /* UIKit.framework in Frameworks */, BDD876A61B4B52C1009268C7 /* libOCMock.a in Frameworks */, BDF125A41B45C17D00DFBFEC /* libz.dylib in Frameworks */, @@ -124,6 +132,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380691C1780BD008B520C /* Security.framework in Frameworks */, + CEB380431C177FB1008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB561BF187E400B22AB3 /* UIKit.framework in Frameworks */, CEE5326C1B03D3C4002CED62 /* libz.dylib in Frameworks */, BD00FF471AB8B6F0004496EF /* libAWSCore.a in Frameworks */, @@ -137,6 +147,8 @@ 44F883773B67388A29D3A410 /* Frameworks */ = { isa = PBXGroup; children = ( + CEB380681C1780BD008B520C /* Security.framework */, + CEB380241C177EFE008B520C /* SystemConfiguration.framework */, CE27CB551BF187E400B22AB3 /* UIKit.framework */, BDD876A51B4B52C0009268C7 /* libOCMock.a */, CEE5326B1B03D3C4002CED62 /* libz.dylib */, @@ -279,7 +291,7 @@ BDF559521AB375800067F4F1 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDF559591AB375800067F4F1 = { @@ -520,11 +532,7 @@ CLANG_ENABLE_MODULE_DEBUGGING = NO; DEAD_CODE_STRIPPING = NO; DEFINES_MODULE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "${SRCROOT}/Pods/Headers/**", - ); + HEADER_SEARCH_PATHS = "$(inherited)"; MODULEMAP_FILE = "$(PRODUCT_NAME:c99extidentifier)/module.modulemap"; OTHER_LDFLAGS = ""; PRODUCT_NAME = AWSEC2; @@ -540,11 +548,7 @@ CLANG_ENABLE_MODULE_DEBUGGING = NO; DEAD_CODE_STRIPPING = NO; DEFINES_MODULE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "${SRCROOT}/Pods/Headers/**", - ); + HEADER_SEARCH_PATHS = "$(inherited)"; MODULEMAP_FILE = "$(PRODUCT_NAME:c99extidentifier)/module.modulemap"; OTHER_LDFLAGS = ""; PRODUCT_NAME = AWSEC2; diff --git a/AWSEC2.xcodeproj/xcshareddata/xcschemes/AWSEC2.xcscheme b/AWSEC2.xcodeproj/xcshareddata/xcschemes/AWSEC2.xcscheme index a981295a556..faac62523db 100644 --- a/AWSEC2.xcodeproj/xcshareddata/xcschemes/AWSEC2.xcscheme +++ b/AWSEC2.xcodeproj/xcshareddata/xcschemes/AWSEC2.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSElasticLoadBalancing/*.{h,m}' end diff --git a/AWSElasticLoadBalancing.xcodeproj/project.pbxproj b/AWSElasticLoadBalancing.xcodeproj/project.pbxproj index 0f94408a479..58b71425b95 100644 --- a/AWSElasticLoadBalancing.xcodeproj/project.pbxproj +++ b/AWSElasticLoadBalancing.xcodeproj/project.pbxproj @@ -30,6 +30,10 @@ CE27CB591BF1881B00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB581BF1881B00B22AB3 /* UIKit.framework */; }; CE27CB5A1BF1882000B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB581BF1881B00B22AB3 /* UIKit.framework */; }; CE2EDE961BF3DF2100B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6552341BEC361D00DACBC2 /* module.modulemap */; }; + CEB380271C177F09008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380261C177F09008B520C /* SystemConfiguration.framework */; }; + CEB380421C177FAB008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380261C177F09008B520C /* SystemConfiguration.framework */; }; + CEB380661C1780B4008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380651C1780B4008B520C /* Security.framework */; }; + CEB380671C1780B7008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380651C1780B4008B520C /* Security.framework */; }; CEE532601B03D397002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE5325F1B03D397002CED62 /* libz.dylib */; }; CEE7DE6F1AC1E19D0095C4B7 /* AWSElasticLoadBalancingService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE6E1AC1E19D0095C4B7 /* AWSElasticLoadBalancingService.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -96,6 +100,8 @@ BDF559A81AB3761C0067F4F1 /* AWSElasticLoadBalancingModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSElasticLoadBalancingModel.m; sourceTree = ""; }; CE27CB581BF1881B00B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE6552341BEC361D00DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380261C177F09008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB380651C1780B4008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE5325F1B03D397002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE6E1AC1E19D0095C4B7 /* AWSElasticLoadBalancingService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSElasticLoadBalancingService.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -105,6 +111,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380671C1780B7008B520C /* Security.framework in Frameworks */, + CEB380271C177F09008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB5A1BF1882000B22AB3 /* UIKit.framework in Frameworks */, BDD876A81B4B52CE009268C7 /* libOCMock.a in Frameworks */, BDF125B61B45C1A900DFBFEC /* libz.dylib in Frameworks */, @@ -124,6 +132,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380661C1780B4008B520C /* Security.framework in Frameworks */, + CEB380421C177FAB008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB591BF1881B00B22AB3 /* UIKit.framework in Frameworks */, CEE532601B03D397002CED62 /* libz.dylib in Frameworks */, BD00FF451AB8B6E2004496EF /* libAWSCore.a in Frameworks */, @@ -137,6 +147,8 @@ 412CEC016EC21D18D1D11C56 /* Frameworks */ = { isa = PBXGroup; children = ( + CEB380651C1780B4008B520C /* Security.framework */, + CEB380261C177F09008B520C /* SystemConfiguration.framework */, CE27CB581BF1881B00B22AB3 /* UIKit.framework */, BDD876A71B4B52CE009268C7 /* libOCMock.a */, CEE5325F1B03D397002CED62 /* libz.dylib */, @@ -279,7 +291,7 @@ BDF559811AB375EC0067F4F1 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDF559881AB375EC0067F4F1 = { diff --git a/AWSElasticLoadBalancing.xcodeproj/xcshareddata/xcschemes/AWSElasticLoadBalancing.xcscheme b/AWSElasticLoadBalancing.xcodeproj/xcshareddata/xcschemes/AWSElasticLoadBalancing.xcscheme index cb7840781c7..d8f17586d6d 100644 --- a/AWSElasticLoadBalancing.xcodeproj/xcshareddata/xcschemes/AWSElasticLoadBalancing.xcscheme +++ b/AWSElasticLoadBalancing.xcodeproj/xcshareddata/xcschemes/AWSElasticLoadBalancing.xcscheme @@ -1,6 +1,6 @@ 'amazonwebservices' } + s.platform = :ios, '7.0' + s.source = { :git => 'https://github.com/aws/aws-sdk-ios.git', + :tag => s.version} + s.requires_arc = true + s.dependency 'AWSCore', '2.3.2' + + s.source_files = 'AWSIoT/*.{h,m}', 'AWSIoT/**/*.{h,m}' + s.private_header_files = 'AWSIoT/Internal/*.h' +end diff --git a/AWSIoT.xcodeproj/project.pbxproj b/AWSIoT.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..35b0d5025bc --- /dev/null +++ b/AWSIoT.xcodeproj/project.pbxproj @@ -0,0 +1,656 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A63295181C05090D00493B04 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A63295171C05090D00493B04 /* UIKit.framework */; }; + CE0907641BD9A13600372E85 /* AWSIoTTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0907631BD9A13600372E85 /* AWSIoTTests.m */; }; + CE09076C1BD9A8EF00372E85 /* AWSIoTDataService.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09076A1BD9A8EF00372E85 /* AWSIoTDataService.m */; }; + CE09076F1BD9A91B00372E85 /* AWSIoTDataResources.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09076E1BD9A91B00372E85 /* AWSIoTDataResources.m */; }; + CE0907751BD9AD9F00372E85 /* AWSIoTDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0907721BD9AD9F00372E85 /* AWSIoTDataModel.m */; }; + CE0907781BD9AF0800372E85 /* AWSGeneralIoTDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0907771BD9AF0800372E85 /* AWSGeneralIoTDataTests.m */; }; + CE09077C1BD9B05A00372E85 /* AWSTestUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09077B1BD9B05A00372E85 /* AWSTestUtility.m */; }; + CE09077E1BD9B0BB00372E85 /* AWSIoTDataUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09077D1BD9B0BB00372E85 /* AWSIoTDataUnitTests.m */; }; + CE0907911BD9B7E200372E85 /* AWSIoTCSR.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0907811BD9B7E200372E85 /* AWSIoTCSR.m */; }; + CE0907921BD9B7E200372E85 /* AWSIoTKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0907831BD9B7E200372E85 /* AWSIoTKeychain.m */; }; + CE0907931BD9B7E200372E85 /* AWSIoTMQTTClient.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0907851BD9B7E200372E85 /* AWSIoTMQTTClient.m */; }; + CE0907941BD9B7E200372E85 /* MQTTDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0907881BD9B7E200372E85 /* MQTTDecoder.m */; }; + CE0907951BD9B7E200372E85 /* MQTTEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09078A1BD9B7E200372E85 /* MQTTEncoder.m */; }; + CE0907961BD9B7E200372E85 /* MQTTMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09078C1BD9B7E200372E85 /* MQTTMessage.m */; }; + CE0907971BD9B7E200372E85 /* MQTTSession.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09078E1BD9B7E200372E85 /* MQTTSession.m */; }; + CE0907981BD9B7E200372E85 /* MQttTxFlow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0907901BD9B7E200372E85 /* MQttTxFlow.m */; }; + CE09079B1BD9B91400372E85 /* AWSIoTManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09079A1BD9B91400372E85 /* AWSIoTManager.m */; }; + CE09079E1BD9B99F00372E85 /* AWSIoTDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CE09079D1BD9B99F00372E85 /* AWSIoTDataManager.m */; }; + CE48F5E81BD9768A005F9E3F /* AWSIoTModel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE48F5E31BD9768A005F9E3F /* AWSIoTModel.m */; }; + CE48F5E91BD9768A005F9E3F /* AWSIoTService.m in Sources */ = {isa = PBXBuildFile; fileRef = CE48F5E51BD9768A005F9E3F /* AWSIoTService.m */; }; + CE48F5EC1BD977EE005F9E3F /* AWSIoTResources.m in Sources */ = {isa = PBXBuildFile; fileRef = CE48F5EB1BD977EE005F9E3F /* AWSIoTResources.m */; }; + CE48F5F91BD97F4D005F9E3F /* libAWSIoT.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE48F5CA1BD975A1005F9E3F /* libAWSIoT.a */; }; + CE48F6021BD98604005F9E3F /* AWSGeneralIoTTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CE48F6011BD98604005F9E3F /* AWSGeneralIoTTests.m */; }; + CE48F6061BD98651005F9E3F /* libAWSCore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE48F6051BD98651005F9E3F /* libAWSCore.a */; }; + CE48F6081BD9865B005F9E3F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CE48F6071BD9865B005F9E3F /* libz.tbd */; }; + CE48F60A1BD98661005F9E3F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CE48F6091BD98661005F9E3F /* libsqlite3.tbd */; }; + CE48F60C1BD98673005F9E3F /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE48F60B1BD98673005F9E3F /* libOCMock.a */; }; + CE48F60F1BD986C7005F9E3F /* credentials.json in Resources */ = {isa = PBXBuildFile; fileRef = CE48F60E1BD986C7005F9E3F /* credentials.json */; }; + CE6A6DBB1C03FFC7006F986B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6A6DB91C03FF79006F986B /* module.modulemap */; }; + CEA5FC4E1BE00371002396AB /* AWSIoT.h in Headers */ = {isa = PBXBuildFile; fileRef = CE48F5DC1BD9768A005F9E3F /* AWSIoT.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEA5FC4F1BE00371002396AB /* AWSIoTDataModel.h in Headers */ = {isa = PBXBuildFile; fileRef = CE0907711BD9AD9F00372E85 /* AWSIoTDataModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEA5FC501BE00371002396AB /* AWSIoTDataResources.h in Headers */ = {isa = PBXBuildFile; fileRef = CE09076D1BD9A91B00372E85 /* AWSIoTDataResources.h */; }; + CEA5FC511BE00371002396AB /* AWSIoTDataService.h in Headers */ = {isa = PBXBuildFile; fileRef = CE0907731BD9AD9F00372E85 /* AWSIoTDataService.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEA5FC521BE00371002396AB /* AWSIoTModel.h in Headers */ = {isa = PBXBuildFile; fileRef = CE48F5E21BD9768A005F9E3F /* AWSIoTModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEA5FC531BE00371002396AB /* AWSIoTResources.h in Headers */ = {isa = PBXBuildFile; fileRef = CE48F5EA1BD977EE005F9E3F /* AWSIoTResources.h */; }; + CEA5FC541BE00371002396AB /* AWSIoTService.h in Headers */ = {isa = PBXBuildFile; fileRef = CE48F5E41BD9768A005F9E3F /* AWSIoTService.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEA5FC551BE00371002396AB /* AWSIoTManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CE0907991BD9B91400372E85 /* AWSIoTManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEA5FC561BE00371002396AB /* AWSIoTDataManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CE09079C1BD9B99F00372E85 /* AWSIoTDataManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEA5FC571BE00387002396AB /* AWSIoT.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE48F5DC1BD9768A005F9E3F /* AWSIoT.h */; }; + CEA5FC581BE00387002396AB /* AWSIoTDataModel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE0907711BD9AD9F00372E85 /* AWSIoTDataModel.h */; }; + CEA5FC5A1BE00387002396AB /* AWSIoTDataService.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE0907731BD9AD9F00372E85 /* AWSIoTDataService.h */; }; + CEA5FC5B1BE00387002396AB /* AWSIoTModel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE48F5E21BD9768A005F9E3F /* AWSIoTModel.h */; }; + CEA5FC5D1BE00387002396AB /* AWSIoTService.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE48F5E41BD9768A005F9E3F /* AWSIoTService.h */; }; + CEA5FC5E1BE00387002396AB /* AWSIoTManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE0907991BD9B91400372E85 /* AWSIoTManager.h */; }; + CEA5FC5F1BE00387002396AB /* AWSIoTDataManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE09079C1BD9B99F00372E85 /* AWSIoTDataManager.h */; }; + CEB380291C177F11008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380281C177F11008B520C /* SystemConfiguration.framework */; }; + CEB380641C1780AE008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380631C1780AE008B520C /* Security.framework */; }; + CEB380781C17815B008B520C /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380771C17815B008B520C /* CFNetwork.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + CE48F5FA1BD97F4D005F9E3F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CE48F5C21BD975A1005F9E3F /* Project object */; + proxyType = 1; + remoteGlobalIDString = CE48F5C91BD975A1005F9E3F; + remoteInfo = AWSIoT; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + CE48F5C81BD975A1005F9E3F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + CEA5FC571BE00387002396AB /* AWSIoT.h in CopyFiles */, + CEA5FC581BE00387002396AB /* AWSIoTDataModel.h in CopyFiles */, + CEA5FC5A1BE00387002396AB /* AWSIoTDataService.h in CopyFiles */, + CEA5FC5B1BE00387002396AB /* AWSIoTModel.h in CopyFiles */, + CEA5FC5D1BE00387002396AB /* AWSIoTService.h in CopyFiles */, + CEA5FC5E1BE00387002396AB /* AWSIoTManager.h in CopyFiles */, + CEA5FC5F1BE00387002396AB /* AWSIoTDataManager.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CE6A6DBA1C03FFBB006F986B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "modules/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + CE6A6DBB1C03FFC7006F986B /* module.modulemap in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + A63295151C05087300493B04 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + A63295171C05090D00493B04 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + CE0907631BD9A13600372E85 /* AWSIoTTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSIoTTests.m; path = AWSIoTTests/AWSIoTTests.m; sourceTree = SOURCE_ROOT; }; + CE09076A1BD9A8EF00372E85 /* AWSIoTDataService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTDataService.m; sourceTree = ""; }; + CE09076D1BD9A91B00372E85 /* AWSIoTDataResources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTDataResources.h; sourceTree = ""; }; + CE09076E1BD9A91B00372E85 /* AWSIoTDataResources.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTDataResources.m; sourceTree = ""; }; + CE0907711BD9AD9F00372E85 /* AWSIoTDataModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTDataModel.h; sourceTree = ""; }; + CE0907721BD9AD9F00372E85 /* AWSIoTDataModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTDataModel.m; sourceTree = ""; }; + CE0907731BD9AD9F00372E85 /* AWSIoTDataService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTDataService.h; sourceTree = ""; }; + CE0907771BD9AF0800372E85 /* AWSGeneralIoTDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSGeneralIoTDataTests.m; path = AWSIoTTests/AWSGeneralIoTDataTests.m; sourceTree = SOURCE_ROOT; }; + CE09077A1BD9B05A00372E85 /* AWSTestUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWSTestUtility.h; path = AWSCoreTests/AWSTestUtility.h; sourceTree = SOURCE_ROOT; }; + CE09077B1BD9B05A00372E85 /* AWSTestUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSTestUtility.m; path = AWSCoreTests/AWSTestUtility.m; sourceTree = SOURCE_ROOT; }; + CE09077D1BD9B0BB00372E85 /* AWSIoTDataUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSIoTDataUnitTests.m; path = AWSIoTTests/AWSIoTDataUnitTests.m; sourceTree = SOURCE_ROOT; }; + CE0907801BD9B7E200372E85 /* AWSIoTCSR.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTCSR.h; sourceTree = ""; }; + CE0907811BD9B7E200372E85 /* AWSIoTCSR.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTCSR.m; sourceTree = ""; }; + CE0907821BD9B7E200372E85 /* AWSIoTKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTKeychain.h; sourceTree = ""; }; + CE0907831BD9B7E200372E85 /* AWSIoTKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTKeychain.m; sourceTree = ""; }; + CE0907841BD9B7E200372E85 /* AWSIoTMQTTClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTMQTTClient.h; sourceTree = ""; }; + CE0907851BD9B7E200372E85 /* AWSIoTMQTTClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTMQTTClient.m; sourceTree = ""; }; + CE0907871BD9B7E200372E85 /* MQTTDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MQTTDecoder.h; sourceTree = ""; }; + CE0907881BD9B7E200372E85 /* MQTTDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MQTTDecoder.m; sourceTree = ""; }; + CE0907891BD9B7E200372E85 /* MQTTEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MQTTEncoder.h; sourceTree = ""; }; + CE09078A1BD9B7E200372E85 /* MQTTEncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MQTTEncoder.m; sourceTree = ""; }; + CE09078B1BD9B7E200372E85 /* MQTTMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MQTTMessage.h; sourceTree = ""; }; + CE09078C1BD9B7E200372E85 /* MQTTMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MQTTMessage.m; sourceTree = ""; }; + CE09078D1BD9B7E200372E85 /* MQTTSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MQTTSession.h; sourceTree = ""; }; + CE09078E1BD9B7E200372E85 /* MQTTSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MQTTSession.m; sourceTree = ""; }; + CE09078F1BD9B7E200372E85 /* MQttTxFlow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MQttTxFlow.h; sourceTree = ""; }; + CE0907901BD9B7E200372E85 /* MQttTxFlow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MQttTxFlow.m; sourceTree = ""; }; + CE0907991BD9B91400372E85 /* AWSIoTManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTManager.h; sourceTree = ""; }; + CE09079A1BD9B91400372E85 /* AWSIoTManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTManager.m; sourceTree = ""; }; + CE09079C1BD9B99F00372E85 /* AWSIoTDataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTDataManager.h; sourceTree = ""; }; + CE09079D1BD9B99F00372E85 /* AWSIoTDataManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTDataManager.m; sourceTree = ""; }; + CE48F5CA1BD975A1005F9E3F /* libAWSIoT.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAWSIoT.a; sourceTree = BUILT_PRODUCTS_DIR; }; + CE48F5DC1BD9768A005F9E3F /* AWSIoT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoT.h; sourceTree = ""; }; + CE48F5E21BD9768A005F9E3F /* AWSIoTModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTModel.h; sourceTree = ""; }; + CE48F5E31BD9768A005F9E3F /* AWSIoTModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTModel.m; sourceTree = ""; }; + CE48F5E41BD9768A005F9E3F /* AWSIoTService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTService.h; sourceTree = ""; }; + CE48F5E51BD9768A005F9E3F /* AWSIoTService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTService.m; sourceTree = ""; }; + CE48F5EA1BD977EE005F9E3F /* AWSIoTResources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSIoTResources.h; sourceTree = ""; }; + CE48F5EB1BD977EE005F9E3F /* AWSIoTResources.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSIoTResources.m; sourceTree = ""; }; + CE48F5F41BD97F4D005F9E3F /* AWSIoTUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSIoTUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CE48F5F81BD97F4D005F9E3F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = AWSIoTTests/Info.plist; sourceTree = ""; }; + CE48F6011BD98604005F9E3F /* AWSGeneralIoTTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSGeneralIoTTests.m; path = AWSIoTTests/AWSGeneralIoTTests.m; sourceTree = SOURCE_ROOT; }; + CE48F6051BD98651005F9E3F /* libAWSCore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libAWSCore.a; path = "build/Debug-iphoneos/libAWSCore.a"; sourceTree = ""; }; + CE48F6071BD9865B005F9E3F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + CE48F6091BD98661005F9E3F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; + CE48F60B1BD98673005F9E3F /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libOCMock.a; path = AWSCoreTests/OCMock/libOCMock.a; sourceTree = ""; }; + CE48F60E1BD986C7005F9E3F /* credentials.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = credentials.json; path = AWSCoreTests/credentials.json; sourceTree = SOURCE_ROOT; }; + CE6A6DB91C03FF79006F986B /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380281C177F11008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB380631C1780AE008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + CEB380771C17815B008B520C /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + CE48F5C71BD975A1005F9E3F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CE48F5F11BD97F4D005F9E3F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CEB380781C17815B008B520C /* CFNetwork.framework in Frameworks */, + CEB380641C1780AE008B520C /* Security.framework in Frameworks */, + CEB380291C177F11008B520C /* SystemConfiguration.framework in Frameworks */, + A63295181C05090D00493B04 /* UIKit.framework in Frameworks */, + CE48F60C1BD98673005F9E3F /* libOCMock.a in Frameworks */, + CE48F60A1BD98661005F9E3F /* libsqlite3.tbd in Frameworks */, + CE48F6081BD9865B005F9E3F /* libz.tbd in Frameworks */, + CE48F6061BD98651005F9E3F /* libAWSCore.a in Frameworks */, + CE48F5F91BD97F4D005F9E3F /* libAWSIoT.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + CE0907651BD9A87A00372E85 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + CE09077A1BD9B05A00372E85 /* AWSTestUtility.h */, + CE09077B1BD9B05A00372E85 /* AWSTestUtility.m */, + CE48F60E1BD986C7005F9E3F /* credentials.json */, + CE48F5F81BD97F4D005F9E3F /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + CE09077F1BD9B7E200372E85 /* Internal */ = { + isa = PBXGroup; + children = ( + CE0907801BD9B7E200372E85 /* AWSIoTCSR.h */, + CE0907811BD9B7E200372E85 /* AWSIoTCSR.m */, + CE0907821BD9B7E200372E85 /* AWSIoTKeychain.h */, + CE0907831BD9B7E200372E85 /* AWSIoTKeychain.m */, + CE0907841BD9B7E200372E85 /* AWSIoTMQTTClient.h */, + CE0907851BD9B7E200372E85 /* AWSIoTMQTTClient.m */, + CE0907861BD9B7E200372E85 /* MQTTSDK */, + ); + path = Internal; + sourceTree = ""; + }; + CE0907861BD9B7E200372E85 /* MQTTSDK */ = { + isa = PBXGroup; + children = ( + CE0907871BD9B7E200372E85 /* MQTTDecoder.h */, + CE0907881BD9B7E200372E85 /* MQTTDecoder.m */, + CE0907891BD9B7E200372E85 /* MQTTEncoder.h */, + CE09078A1BD9B7E200372E85 /* MQTTEncoder.m */, + CE09078B1BD9B7E200372E85 /* MQTTMessage.h */, + CE09078C1BD9B7E200372E85 /* MQTTMessage.m */, + CE09078D1BD9B7E200372E85 /* MQTTSession.h */, + CE09078E1BD9B7E200372E85 /* MQTTSession.m */, + CE09078F1BD9B7E200372E85 /* MQttTxFlow.h */, + CE0907901BD9B7E200372E85 /* MQttTxFlow.m */, + ); + path = MQTTSDK; + sourceTree = ""; + }; + CE48F5C11BD975A1005F9E3F = { + isa = PBXGroup; + children = ( + CE48F5CC1BD975A1005F9E3F /* AWSIoT */, + CE48F5F51BD97F4D005F9E3F /* AWSIoTUnitTests */, + CE48F5CB1BD975A1005F9E3F /* Products */, + CE48F6001BD97F6E005F9E3F /* Frameworks */, + ); + sourceTree = ""; + }; + CE48F5CB1BD975A1005F9E3F /* Products */ = { + isa = PBXGroup; + children = ( + CE48F5CA1BD975A1005F9E3F /* libAWSIoT.a */, + CE48F5F41BD97F4D005F9E3F /* AWSIoTUnitTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + CE48F5CC1BD975A1005F9E3F /* AWSIoT */ = { + isa = PBXGroup; + children = ( + CE6A6DB91C03FF79006F986B /* module.modulemap */, + CE48F5DC1BD9768A005F9E3F /* AWSIoT.h */, + CE0907711BD9AD9F00372E85 /* AWSIoTDataModel.h */, + CE0907721BD9AD9F00372E85 /* AWSIoTDataModel.m */, + CE09076D1BD9A91B00372E85 /* AWSIoTDataResources.h */, + CE09076E1BD9A91B00372E85 /* AWSIoTDataResources.m */, + CE0907731BD9AD9F00372E85 /* AWSIoTDataService.h */, + CE09076A1BD9A8EF00372E85 /* AWSIoTDataService.m */, + CE48F5E21BD9768A005F9E3F /* AWSIoTModel.h */, + CE48F5E31BD9768A005F9E3F /* AWSIoTModel.m */, + CE48F5EA1BD977EE005F9E3F /* AWSIoTResources.h */, + CE48F5EB1BD977EE005F9E3F /* AWSIoTResources.m */, + CE48F5E41BD9768A005F9E3F /* AWSIoTService.h */, + CE48F5E51BD9768A005F9E3F /* AWSIoTService.m */, + CE0907991BD9B91400372E85 /* AWSIoTManager.h */, + CE09079A1BD9B91400372E85 /* AWSIoTManager.m */, + CE09079C1BD9B99F00372E85 /* AWSIoTDataManager.h */, + CE09079D1BD9B99F00372E85 /* AWSIoTDataManager.m */, + CE09077F1BD9B7E200372E85 /* Internal */, + ); + path = AWSIoT; + sourceTree = ""; + }; + CE48F5F51BD97F4D005F9E3F /* AWSIoTUnitTests */ = { + isa = PBXGroup; + children = ( + CE0907771BD9AF0800372E85 /* AWSGeneralIoTDataTests.m */, + CE48F6011BD98604005F9E3F /* AWSGeneralIoTTests.m */, + CE09077D1BD9B0BB00372E85 /* AWSIoTDataUnitTests.m */, + CE0907631BD9A13600372E85 /* AWSIoTTests.m */, + CE0907651BD9A87A00372E85 /* Supporting Files */, + ); + path = AWSIoTUnitTests; + sourceTree = ""; + }; + CE48F6001BD97F6E005F9E3F /* Frameworks */ = { + isa = PBXGroup; + children = ( + CEB380771C17815B008B520C /* CFNetwork.framework */, + CEB380631C1780AE008B520C /* Security.framework */, + CEB380281C177F11008B520C /* SystemConfiguration.framework */, + A63295171C05090D00493B04 /* UIKit.framework */, + A63295151C05087300493B04 /* CoreGraphics.framework */, + CE48F60B1BD98673005F9E3F /* libOCMock.a */, + CE48F6091BD98661005F9E3F /* libsqlite3.tbd */, + CE48F6071BD9865B005F9E3F /* libz.tbd */, + CE48F6051BD98651005F9E3F /* libAWSCore.a */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + CEA5FC4D1BE00363002396AB /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CEA5FC4E1BE00371002396AB /* AWSIoT.h in Headers */, + CEA5FC4F1BE00371002396AB /* AWSIoTDataModel.h in Headers */, + CEA5FC511BE00371002396AB /* AWSIoTDataService.h in Headers */, + CEA5FC521BE00371002396AB /* AWSIoTModel.h in Headers */, + CEA5FC541BE00371002396AB /* AWSIoTService.h in Headers */, + CEA5FC551BE00371002396AB /* AWSIoTManager.h in Headers */, + CEA5FC561BE00371002396AB /* AWSIoTDataManager.h in Headers */, + CEA5FC531BE00371002396AB /* AWSIoTResources.h in Headers */, + CEA5FC501BE00371002396AB /* AWSIoTDataResources.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + CE48F5C91BD975A1005F9E3F /* AWSIoT */ = { + isa = PBXNativeTarget; + buildConfigurationList = CE48F5D31BD975A1005F9E3F /* Build configuration list for PBXNativeTarget "AWSIoT" */; + buildPhases = ( + CE48F5C61BD975A1005F9E3F /* Sources */, + CE48F5C71BD975A1005F9E3F /* Frameworks */, + CE48F5C81BD975A1005F9E3F /* CopyFiles */, + CEA5FC4D1BE00363002396AB /* Headers */, + CE6A6DBA1C03FFBB006F986B /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AWSIoT; + productName = AWSIoT; + productReference = CE48F5CA1BD975A1005F9E3F /* libAWSIoT.a */; + productType = "com.apple.product-type.library.static"; + }; + CE48F5F31BD97F4D005F9E3F /* AWSIoTUnitTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CE48F5FC1BD97F4D005F9E3F /* Build configuration list for PBXNativeTarget "AWSIoTUnitTests" */; + buildPhases = ( + CE48F5F01BD97F4D005F9E3F /* Sources */, + CE48F5F11BD97F4D005F9E3F /* Frameworks */, + CE48F5F21BD97F4D005F9E3F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CE48F5FB1BD97F4D005F9E3F /* PBXTargetDependency */, + ); + name = AWSIoTUnitTests; + productName = AWSIoTUnitTests; + productReference = CE48F5F41BD97F4D005F9E3F /* AWSIoTUnitTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + CE48F5C21BD975A1005F9E3F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Amazon Web Services"; + TargetAttributes = { + CE48F5C91BD975A1005F9E3F = { + CreatedOnToolsVersion = 7.1; + }; + CE48F5F31BD97F4D005F9E3F = { + CreatedOnToolsVersion = 7.1; + }; + }; + }; + buildConfigurationList = CE48F5C51BD975A1005F9E3F /* Build configuration list for PBXProject "AWSIoT" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = CE48F5C11BD975A1005F9E3F; + productRefGroup = CE48F5CB1BD975A1005F9E3F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + CE48F5C91BD975A1005F9E3F /* AWSIoT */, + CE48F5F31BD97F4D005F9E3F /* AWSIoTUnitTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + CE48F5F21BD97F4D005F9E3F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CE48F60F1BD986C7005F9E3F /* credentials.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + CE48F5C61BD975A1005F9E3F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CE0907751BD9AD9F00372E85 /* AWSIoTDataModel.m in Sources */, + CE48F5E91BD9768A005F9E3F /* AWSIoTService.m in Sources */, + CE09079E1BD9B99F00372E85 /* AWSIoTDataManager.m in Sources */, + CE09076C1BD9A8EF00372E85 /* AWSIoTDataService.m in Sources */, + CE0907961BD9B7E200372E85 /* MQTTMessage.m in Sources */, + CE48F5EC1BD977EE005F9E3F /* AWSIoTResources.m in Sources */, + CE09076F1BD9A91B00372E85 /* AWSIoTDataResources.m in Sources */, + CE09079B1BD9B91400372E85 /* AWSIoTManager.m in Sources */, + CE0907911BD9B7E200372E85 /* AWSIoTCSR.m in Sources */, + CE0907921BD9B7E200372E85 /* AWSIoTKeychain.m in Sources */, + CE0907931BD9B7E200372E85 /* AWSIoTMQTTClient.m in Sources */, + CE0907951BD9B7E200372E85 /* MQTTEncoder.m in Sources */, + CE0907971BD9B7E200372E85 /* MQTTSession.m in Sources */, + CE0907981BD9B7E200372E85 /* MQttTxFlow.m in Sources */, + CE0907941BD9B7E200372E85 /* MQTTDecoder.m in Sources */, + CE48F5E81BD9768A005F9E3F /* AWSIoTModel.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CE48F5F01BD97F4D005F9E3F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CE0907781BD9AF0800372E85 /* AWSGeneralIoTDataTests.m in Sources */, + CE48F6021BD98604005F9E3F /* AWSGeneralIoTTests.m in Sources */, + CE09077C1BD9B05A00372E85 /* AWSTestUtility.m in Sources */, + CE0907641BD9A13600372E85 /* AWSIoTTests.m in Sources */, + CE09077E1BD9B0BB00372E85 /* AWSIoTDataUnitTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + CE48F5FB1BD97F4D005F9E3F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CE48F5C91BD975A1005F9E3F /* AWSIoT */; + targetProxy = CE48F5FA1BD97F4D005F9E3F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + CE48F5D11BD975A1005F9E3F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = ( + "$(ARCHS_STANDARD)", + armv7s, + ); + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_MODULE_DEBUGGING = NO; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include/**"; + }; + name = Debug; + }; + CE48F5D21BD975A1005F9E3F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = ( + "$(ARCHS_STANDARD)", + armv7s, + ); + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_MODULE_DEBUGGING = NO; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include/**"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + CE48F5D41BD975A1005F9E3F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEAD_CODE_STRIPPING = NO; + DEFINES_MODULE = YES; + MODULEMAP_FILE = "$(PRODUCT_NAME:c99extidentifier)/module.modulemap"; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRIP_STYLE = "non-global"; + }; + name = Debug; + }; + CE48F5D51BD975A1005F9E3F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEAD_CODE_STRIPPING = NO; + DEFINES_MODULE = YES; + MODULEMAP_FILE = "$(PRODUCT_NAME:c99extidentifier)/module.modulemap"; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRIP_STYLE = "non-global"; + }; + name = Release; + }; + CE48F5FD1BD97F4D005F9E3F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_GENERATE_TEST_COVERAGE_FILES = YES; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; + INFOPLIST_FILE = AWSIoTTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(SYMROOT)", + "$(PROJECT_DIR)/AWSCoreTests/OCMock", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-framework", + XCTest, + "-force_load", + "$(PROJECT_DIR)/AWSCoreTests/OCMock/libOCMock.a", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.amazonaws.AWSIoTUnitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include/** $(PROJECT_DIR)/AWSCoreTests/OCMock"; + }; + name = Debug; + }; + CE48F5FE1BD97F4D005F9E3F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_GENERATE_TEST_COVERAGE_FILES = YES; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; + INFOPLIST_FILE = AWSIoTTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(SYMROOT)", + "$(PROJECT_DIR)/AWSCoreTests/OCMock", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-framework", + XCTest, + "-force_load", + "$(PROJECT_DIR)/AWSCoreTests/OCMock/libOCMock.a", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.amazonaws.AWSIoTUnitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include/** $(PROJECT_DIR)/AWSCoreTests/OCMock"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + CE48F5C51BD975A1005F9E3F /* Build configuration list for PBXProject "AWSIoT" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CE48F5D11BD975A1005F9E3F /* Debug */, + CE48F5D21BD975A1005F9E3F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CE48F5D31BD975A1005F9E3F /* Build configuration list for PBXNativeTarget "AWSIoT" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CE48F5D41BD975A1005F9E3F /* Debug */, + CE48F5D51BD975A1005F9E3F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CE48F5FC1BD97F4D005F9E3F /* Build configuration list for PBXNativeTarget "AWSIoTUnitTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CE48F5FD1BD97F4D005F9E3F /* Debug */, + CE48F5FE1BD97F4D005F9E3F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = CE48F5C21BD975A1005F9E3F /* Project object */; +} diff --git a/AWSIoT.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/AWSIoT.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..42e5b527e1f --- /dev/null +++ b/AWSIoT.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/AWSIoT.xcodeproj/xcshareddata/xcschemes/AWSIoT.xcscheme b/AWSIoT.xcodeproj/xcshareddata/xcschemes/AWSIoT.xcscheme new file mode 100644 index 00000000000..34fa0d639f1 --- /dev/null +++ b/AWSIoT.xcodeproj/xcshareddata/xcschemes/AWSIoT.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AWSIoT/AWSIoT.h b/AWSIoT/AWSIoT.h new file mode 100644 index 00000000000..17b84c2e6d2 --- /dev/null +++ b/AWSIoT/AWSIoT.h @@ -0,0 +1,21 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import +#import "AWSIoTService.h" +#import "AWSIoTDataService.h" +#import "AWSIoTManager.h" +#import "AWSIoTDataManager.h" diff --git a/AWSIoT/AWSIoTDataManager.h b/AWSIoT/AWSIoTDataManager.h new file mode 100644 index 00000000000..591a9c72185 --- /dev/null +++ b/AWSIoT/AWSIoTDataManager.h @@ -0,0 +1,247 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTDataService.h" +#import "AWSIoTService.h" + +typedef NS_ENUM(NSInteger, AWSIoTMQTTStatus) { + AWSIoTMQTTStatusUnknown, + AWSIoTMQTTStatusConnecting, + AWSIoTMQTTStatusConnected, + AWSIoTMQTTStatusDisconnected, + AWSIoTMQTTStatusConnectionRefused, + AWSIoTMQTTStatusConnectionError, + AWSIoTMQTTStatusProtocolError +}; + +typedef void(^AWSIoTMQTTNewMessageBlock)(NSData *data); + +@interface AWSIoTDataManager : AWSService + +/** + The service configuration used to instantiate this service client. + + @warning Once the client is instantiated, do not modify the configuration object. It may cause unspecified behaviors. + */ +@property (nonatomic, strong, readonly) AWSServiceConfiguration *configuration; + +/** + Returns the singleton service client. If the singleton object does not exist, the SDK instantiates the default service client with `defaultServiceConfiguration` from `[AWSServiceManager defaultServiceManager]`. The reference to this object is maintained by the SDK, and you do not need to retain it manually. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialProvider) + AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 + credentialsProvider:credentialsProvider]; + [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; + + return YES; + } + + Then call the following to get the default service client: + + *Swift* + + let IoTDataManager = AWSIoTDataManager.defaultIoTDataManager() + + *Objective-C* + + AWSIoTDataManager *IoTDataManager = [AWSIoTDataManager defaultIoTDataManager]; + + @return The default service client. + */ ++ (instancetype)defaultIoTDataManager; + +/** + Creates a service client with the given service configuration and registers it for the key. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) + AWSIoTDataManager.registerIoTDataManagerWithConfiguration(configuration, forKey: "USWest2IoTDataManager") + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 + credentialsProvider:credentialsProvider]; + + [AWSIoTDataManager registerIoTDataManagerWithConfiguration:configuration forKey:@"USWest2IoTDataManager"]; + + return YES; + } + + Then call the following to get the service client: + + *Swift* + + let IoTDataManager = AWSIoTDataManager(forKey: "USWest2IoTDataManager") + + *Objective-C* + + AWSIoTDataManager *IoTDataManager = [AWSIoTDataManager IoTDataManagerForKey:@"USWest2IoTDataManager"]; + + @warning After calling this method, do not modify the configuration object. It may cause unspecified behaviors. + + @param configuration A service configuration object. + @param key A string to identify the service client. + */ ++ (void)registerIoTDataManagerWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key; + +/** + Retrieves the service client associated with the key. You need to call `+ registerIoTDataManagerWithConfiguration:forKey:` before invoking this method. If `+ registerIoTDataManagerWithConfiguration:forKey:` has not been called in advance or the key does not exist, this method returns `nil`. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) + AWSIoTDataManager.registerIoTDataManagerWithConfiguration(configuration, forKey: "USWest2IoTDataManager") + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 + credentialsProvider:credentialsProvider]; + + [AWSIoTDataManager registerIoTDataManagerWithConfiguration:configuration forKey:@"USWest2IoTDataManager"]; + + return YES; + } + + Then call the following to get the service client: + + *Swift* + + let IoTDataManager = AWSIoTDataManager(forKey: "USWest2IoTDataManager") + + *Objective-C* + + AWSIoTDataManager *IoTDataManager = [AWSIoTDataManager IoTDataManagerForKey:@"USWest2IoTDataManager"]; + + @param key A string to identify the service client. + + @return An instance of the service client. + */ ++ (instancetype)IoTDataManagerForKey:(NSString *)key; + +/** + Removes the service client associated with the key and release it. + + @warning Before calling this method, make sure no method is running on this client. + + @param key A string to identify the service client. + */ ++ (void)removeIoTDataManagerForKey:(NSString *)key; + +/** + Initialises the MQTT session and connects to the specified MQTT server + + @return true if initialise finished with success + + @param clientId The Client Identifier identifies the Client to the Server. + + @param cleanSession specifies if the server should discard previous session information. + + @param certificateId contains the ID of the certificate to use in the connection; must be in the keychain + + @param block Reference. When new mqtt session status is received the function of block will be called with new connection status. + + */ +- (BOOL)connectWithClientId:(NSString *)clientId + cleanSession:(BOOL)cleanSession + certificateId:(NSString *)certificateId + statusCallback:(void (^)(AWSIoTMQTTStatus status))callback; + +/** + Disconnect from a mqtt client (close current mqtt session) + + */ +- (void)disconnect; + +/** + Send MQTT message to specified topic + + @param message The message (As NSString object) to be sent. + + @param topic The topic for publish to. + + */ +- (void)publishString:(NSString *)str + onTopic:(NSString *)topic; + +/** + Send MQTT message to specified topic + + @param message The message (As NSData) to be sent. + + @param topic The topic for publish to. + + */ +- (void)publishData:(NSData *)data + onTopic:(NSString *)topic; + +/** + Subscribes to a topic at a specific QoS level + + @param topic The Topic to subscribe to. + + @param qos Specifies the QoS Level of the subscription. Can be 0, 1, or 2. + + @param block Reference to AWSIOTMQTTNewMessageBlock. When new message is received the function of block will be called. + */ +- (void)subscribeToTopic:(NSString *)topic + qos:(UInt8)qos + messageCallback:(AWSIoTMQTTNewMessageBlock)callback; + +/** + Unsubscribes from a topic + + @param topic The Topic to unsubscribe from. + + */ +- (void)unsubscribeTopic:(NSString *)topic; + +@end diff --git a/AWSIoT/AWSIoTDataManager.m b/AWSIoT/AWSIoTDataManager.m new file mode 100644 index 00000000000..9a6e937d60d --- /dev/null +++ b/AWSIoT/AWSIoTDataManager.m @@ -0,0 +1,168 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSSignature.h" +#import "AWSIoTDataManager.h" +#import "AWSIoTMQTTClient.h" +#import "AWSSynchronizedMutableDictionary.h" + +@interface AWSIoTData() + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration; + +@property (nonatomic, readonly) AWSIoTMQTTClient *mqttClient; + +@end + +@interface AWSIoTDataManager() + +@property (nonatomic, strong) AWSIoTData *IoTData; + +@end + +@implementation AWSIoTDataManager + +static AWSSynchronizedMutableDictionary *_serviceClients = nil; +AWSIoTMQTTClient *_mqttClient = nil; + ++ (instancetype)defaultIoTDataManager { + if (![AWSServiceManager defaultServiceManager].defaultServiceConfiguration) { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`defaultServiceConfiguration` is `nil`. You need to set it before using this method." + userInfo:nil]; + } + + static AWSIoTDataManager *_defaultIoTDataManager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _defaultIoTDataManager = [[AWSIoTDataManager alloc] initWithConfiguration:AWSServiceManager.defaultServiceManager.defaultServiceConfiguration]; + }); + + return _defaultIoTDataManager; +} + ++ (void)registerIoTDataManagerWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _serviceClients = [AWSSynchronizedMutableDictionary new]; + }); + [_serviceClients setObject:[[AWSIoTDataManager alloc] initWithConfiguration:configuration] + forKey:key]; +} + ++ (instancetype)IoTDataManagerForKey:(NSString *)key { + return [_serviceClients objectForKey:key]; +} + ++ (void)removeIoTDataManagerForKey:(NSString *)key { + [_serviceClients removeObjectForKey:key]; +} + +- (instancetype)init { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`- init` is not a valid initializer. Use `+ defaultIoTDataManager` or `+ IoTDataManagerForKey:` instead." + userInfo:nil]; + return nil; +} +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration { + if (self = [super init]) { + _configuration = [configuration copy]; + _IoTData = [[AWSIoTData alloc] initWithConfiguration:_configuration]; + } + + return self; +} + +- (AWSIoTMQTTClient *)mqttClient { + static AWSIoTMQTTClient *_mqttClient = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _mqttClient = [AWSIoTMQTTClient sharedInstance]; + [_mqttClient disconnect]; + }); + + return _mqttClient; +} + +- (BOOL)connectWithClientId:(NSString*)clientId + cleanSession:(BOOL)cleanSession + certificateId:(NSString *)certificateId + statusCallback:(void (^)(AWSIoTMQTTStatus status))callback { + NSLog(@"hostName: %@", self.IoTData.configuration.endpoint.hostName); + NSLog(@"URL: %@", self.IoTData.configuration.endpoint.URL); + + if (clientId == nil || [clientId isEqualToString: @""]) { + return false; + } + + if (certificateId == nil || [certificateId isEqualToString:@""]) { + return false; + } + + return [self.mqttClient connectWithClientId:clientId + toHost:self.IoTData.configuration.endpoint.hostName + port:8883 + cleanSession:cleanSession + certificateId:certificateId + statusCallback:callback]; +} + +- (void)disconnect{ + [self.mqttClient disconnect]; +} + +- (void)publishString:(NSString *)str + onTopic:(NSString *)topic { + if (str == nil) { + return; + } + if (topic == nil || [topic isEqualToString:@""]) { + return; + } + + [self.mqttClient publishString:str onTopic:topic]; +} + +- (void)publishData:(NSData *)data + onTopic:(NSString *)topic { + if (data == nil) { + return; + } + if (topic == nil || [topic isEqualToString:@""]) { + return; + } + + [self.mqttClient publishData:data onTopic:topic]; +} + +- (void)subscribeToTopic:(NSString *)topic + qos:(UInt8)qos + messageCallback:(AWSIoTMQTTNewMessageBlock)callback { + if (topic == nil || [topic isEqualToString:@""]) { + return; + } + + [self.mqttClient subscribeToTopic:topic qos:qos messageCallback:callback]; +} + +- (void)unsubscribeTopic:(NSString *)topic { + if (topic == nil || [topic isEqualToString:@""]) { + return; + } + + [self.mqttClient unsubscribeTopic:topic]; +} + +@end diff --git a/AWSIoT/AWSIoTDataModel.h b/AWSIoT/AWSIoTDataModel.h new file mode 100644 index 00000000000..ab18c2117c0 --- /dev/null +++ b/AWSIoT/AWSIoTDataModel.h @@ -0,0 +1,160 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const AWSIoTDataErrorDomain; + +typedef NS_ENUM(NSInteger, AWSIoTDataErrorType) { + AWSIoTDataErrorUnknown, + AWSIoTDataErrorIncompleteSignature, + AWSIoTDataErrorInvalidClientTokenId, + AWSIoTDataErrorMissingAuthenticationToken, + AWSIoTDataErrorConflict, + AWSIoTDataErrorInternalFailure, + AWSIoTDataErrorInvalidRequest, + AWSIoTDataErrorMethodNotAllowed, + AWSIoTDataErrorRequestEntityTooLarge, + AWSIoTDataErrorResourceNotFound, + AWSIoTDataErrorServiceUnavailable, + AWSIoTDataErrorThrottling, + AWSIoTDataErrorUnauthorized, + AWSIoTDataErrorUnsupportedDocumentEncoding, +}; + +@class AWSIoTDataDeleteThingShadowRequest; +@class AWSIoTDataDeleteThingShadowResponse; +@class AWSIoTDataGetThingShadowRequest; +@class AWSIoTDataGetThingShadowResponse; +@class AWSIoTDataPublishRequest; +@class AWSIoTDataUpdateThingShadowRequest; +@class AWSIoTDataUpdateThingShadowResponse; + +/** +

The input for the DeleteThingShadow operation.

+ Required parameters: [thingName] + */ +@interface AWSIoTDataDeleteThingShadowRequest : AWSRequest + + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output from the DeleteThingShadow operation.

+ Required parameters: [payload] + */ +@interface AWSIoTDataDeleteThingShadowResponse : AWSModel + + +/** +

The state information, in JSON format.

+ */ +@property (nonatomic, strong) NSData * _Nullable payload; + +@end + +/** +

The input for the GetThingShadow operation.

+ Required parameters: [thingName] + */ +@interface AWSIoTDataGetThingShadowRequest : AWSRequest + + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output from the GetThingShadow operation.

+ */ +@interface AWSIoTDataGetThingShadowResponse : AWSModel + + +/** +

The state information, in JSON format.

+ */ +@property (nonatomic, strong) NSData * _Nullable payload; + +@end + +/** +

The input for the Publish operation.

+ Required parameters: [topic] + */ +@interface AWSIoTDataPublishRequest : AWSRequest + + +/** +

The state information, in JSON format.

+ */ +@property (nonatomic, strong) NSData * _Nullable payload; + +/** +

The Quality of Service (QoS) level.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable qos; + +/** +

The name of the MQTT topic.

+ */ +@property (nonatomic, strong) NSString * _Nullable topic; + +@end + +/** +

The input for the UpdateThingShadow operation.

+ Required parameters: [thingName, payload] + */ +@interface AWSIoTDataUpdateThingShadowRequest : AWSRequest + + +/** +

The state information, in JSON format.

+ */ +@property (nonatomic, strong) NSData * _Nullable payload; + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output from the UpdateThingShadow operation.

+ */ +@interface AWSIoTDataUpdateThingShadowResponse : AWSModel + + +/** +

The state information, in JSON format.

+ */ +@property (nonatomic, strong) NSData * _Nullable payload; + +@end + +NS_ASSUME_NONNULL_END diff --git a/AWSIoT/AWSIoTDataModel.m b/AWSIoT/AWSIoTDataModel.m new file mode 100644 index 00000000000..38d0e7e985f --- /dev/null +++ b/AWSIoT/AWSIoTDataModel.m @@ -0,0 +1,92 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTDataModel.h" +#import + +NSString *const AWSIoTDataErrorDomain = @"com.amazonaws.AWSIoTDataErrorDomain"; + +@implementation AWSIoTDataDeleteThingShadowRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTDataDeleteThingShadowResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"payload" : @"payload", + }; +} + +@end + +@implementation AWSIoTDataGetThingShadowRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTDataGetThingShadowResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"payload" : @"payload", + }; +} + +@end + +@implementation AWSIoTDataPublishRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"payload" : @"payload", + @"qos" : @"qos", + @"topic" : @"topic", + }; +} + +@end + +@implementation AWSIoTDataUpdateThingShadowRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"payload" : @"payload", + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTDataUpdateThingShadowResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"payload" : @"payload", + }; +} + +@end diff --git a/AWSIoT/AWSIoTDataResources.h b/AWSIoT/AWSIoTDataResources.h new file mode 100644 index 00000000000..a2172756d3c --- /dev/null +++ b/AWSIoT/AWSIoTDataResources.h @@ -0,0 +1,24 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import + +@interface AWSIoTDataResources : NSObject + ++ (instancetype)sharedInstance; + +- (NSDictionary *)JSONObject; + +@end diff --git a/AWSIoT/AWSIoTDataResources.m b/AWSIoT/AWSIoTDataResources.m new file mode 100644 index 00000000000..125a1ce3ee0 --- /dev/null +++ b/AWSIoT/AWSIoTDataResources.m @@ -0,0 +1,573 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTDataResources.h" +#import + +@interface AWSIoTDataResources () + +@property (nonatomic, strong) NSDictionary *definitionDictionary; + +@end + +@implementation AWSIoTDataResources + ++ (instancetype)sharedInstance { + static AWSIoTDataResources *_sharedResources = nil; + static dispatch_once_t once_token; + + dispatch_once(&once_token, ^{ + _sharedResources = [AWSIoTDataResources new]; + }); + + return _sharedResources; +} +- (NSDictionary *)JSONObject { + return self.definitionDictionary; +} + +- (instancetype)init { + if (self = [super init]) { + //init method + NSError *error = nil; + _definitionDictionary = [NSJSONSerialization JSONObjectWithData:[[self definitionString] dataUsingEncoding:NSUTF8StringEncoding] + options:kNilOptions + error:&error]; + if (_definitionDictionary == nil) { + if (error) { + AWSLogError(@"Failed to parse JSON service definition: %@",error); + } + } + } + return self; +} + +- (NSString *)definitionString { + return @" \ +{ \ + \"version\":\"2.0\", \ + \"metadata\":{ \ + \"apiVersion\":\"2015-05-28\", \ + \"endpointPrefix\":\"data.iot\", \ + \"serviceFullName\":\"AWS IoT Data Plane\", \ + \"signatureVersion\":\"v4\", \ + \"signingName\":\"iotdata\", \ + \"protocol\":\"rest-json\" \ + }, \ + \"documentation\":\"AWS IoT (Beta)

AWS IoT is considered a beta service as defined in the Service Terms

AWS IoT-Data enables secure, bi-directional communication between Internet-connected things (such as sensors, actuators, embedded devices, or smart appliances) and the AWS cloud. It implements a broker for applications and things to publish messages over HTTP (Publish) and retrieve, update, and delete thing shadows. A thing shadow is a persistent representation of your things and their state in the AWS cloud.

\", \ + \"operations\":{ \ + \"DeleteThingShadow\":{ \ + \"name\":\"DeleteThingShadow\", \ + \"http\":{ \ + \"method\":\"DELETE\", \ + \"requestUri\":\"/things/{thingName}/shadow\" \ + }, \ + \"input\":{ \ + \"shape\":\"DeleteThingShadowRequest\", \ + \"documentation\":\"

The input for the DeleteThingShadow operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"DeleteThingShadowResponse\", \ + \"documentation\":\"

The output from the DeleteThingShadow operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"MethodNotAllowedException\", \ + \"error\":{\"httpStatusCode\":405}, \ + \"exception\":true, \ + \"documentation\":\"

The specified combination of HTTP verb and URI is not supported.

\" \ + }, \ + { \ + \"shape\":\"UnsupportedDocumentEncodingException\", \ + \"error\":{\"httpStatusCode\":415}, \ + \"exception\":true, \ + \"documentation\":\"

The document encoding is not supported.

\" \ + } \ + ], \ + \"documentation\":\"

Deletes the thing shadow for the specified thing.

For more information, see DeleteThingShadow in the AWS IoT Developer Guide.

\" \ + }, \ + \"GetThingShadow\":{ \ + \"name\":\"GetThingShadow\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/things/{thingName}/shadow\" \ + }, \ + \"input\":{ \ + \"shape\":\"GetThingShadowRequest\", \ + \"documentation\":\"

The input for the GetThingShadow operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"GetThingShadowResponse\", \ + \"documentation\":\"

The output from the GetThingShadow operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"MethodNotAllowedException\", \ + \"error\":{\"httpStatusCode\":405}, \ + \"exception\":true, \ + \"documentation\":\"

The specified combination of HTTP verb and URI is not supported.

\" \ + }, \ + { \ + \"shape\":\"UnsupportedDocumentEncodingException\", \ + \"error\":{\"httpStatusCode\":415}, \ + \"exception\":true, \ + \"documentation\":\"

The document encoding is not supported.

\" \ + } \ + ], \ + \"documentation\":\"

Gets the thing shadow for the specified thing.

For more information, see GetThingShadow in the AWS IoT Developer Guide.

\" \ + }, \ + \"Publish\":{ \ + \"name\":\"Publish\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/topics/{topic}\" \ + }, \ + \"input\":{ \ + \"shape\":\"PublishRequest\", \ + \"documentation\":\"

The input for the Publish operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"MethodNotAllowedException\", \ + \"error\":{\"httpStatusCode\":405}, \ + \"exception\":true, \ + \"documentation\":\"

The specified combination of HTTP verb and URI is not supported.

\" \ + } \ + ], \ + \"documentation\":\"

Publishes state information.

For more information, see HTTP Protocol in the AWS IoT Developer Guide.

\" \ + }, \ + \"UpdateThingShadow\":{ \ + \"name\":\"UpdateThingShadow\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/things/{thingName}/shadow\" \ + }, \ + \"input\":{ \ + \"shape\":\"UpdateThingShadowRequest\", \ + \"documentation\":\"

The input for the UpdateThingShadow operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"UpdateThingShadowResponse\", \ + \"documentation\":\"

The output from the UpdateThingShadow operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ConflictException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

The specified version does not match the version of the document.

\" \ + }, \ + { \ + \"shape\":\"RequestEntityTooLargeException\", \ + \"error\":{\"httpStatusCode\":413}, \ + \"exception\":true, \ + \"documentation\":\"

The payload exceeds the maximum size allowed.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"MethodNotAllowedException\", \ + \"error\":{\"httpStatusCode\":405}, \ + \"exception\":true, \ + \"documentation\":\"

The specified combination of HTTP verb and URI is not supported.

\" \ + }, \ + { \ + \"shape\":\"UnsupportedDocumentEncodingException\", \ + \"error\":{\"httpStatusCode\":415}, \ + \"exception\":true, \ + \"documentation\":\"

The document encoding is not supported.

\" \ + } \ + ], \ + \"documentation\":\"

Updates the thing shadow for the specified thing.

For more information, see UpdateThingShadow in the AWS IoT Developer Guide.

\" \ + } \ + }, \ + \"shapes\":{ \ + \"ConflictException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"ErrorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

The specified version does not match the version of the document.

\" \ + }, \ + \"DeleteThingShadowRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"thingName\"], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DeleteThingShadow operation.

\" \ + }, \ + \"DeleteThingShadowResponse\":{ \ + \"type\":\"structure\", \ + \"required\":[\"payload\"], \ + \"members\":{ \ + \"payload\":{ \ + \"shape\":\"JsonDocument\", \ + \"documentation\":\"

The state information, in JSON format.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the DeleteThingShadow operation.

\", \ + \"payload\":\"payload\" \ + }, \ + \"ErrorMessage\":{\"type\":\"string\"}, \ + \"GetThingShadowRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"thingName\"], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the GetThingShadow operation.

\" \ + }, \ + \"GetThingShadowResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"payload\":{ \ + \"shape\":\"JsonDocument\", \ + \"documentation\":\"

The state information, in JSON format.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the GetThingShadow operation.

\", \ + \"payload\":\"payload\" \ + }, \ + \"InternalFailureException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + \"InvalidRequestException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + \"JsonDocument\":{\"type\":\"blob\"}, \ + \"MethodNotAllowedException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"ErrorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":405}, \ + \"exception\":true, \ + \"documentation\":\"

The specified combination of HTTP verb and URI is not supported.

\" \ + }, \ + \"Payload\":{\"type\":\"blob\"}, \ + \"PublishRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"topic\":{ \ + \"shape\":\"Topic\", \ + \"location\":\"uri\", \ + \"locationName\":\"topic\", \ + \"documentation\":\"

The name of the MQTT topic.

\" \ + }, \ + \"qos\":{ \ + \"shape\":\"Qos\", \ + \"location\":\"querystring\", \ + \"locationName\":\"qos\", \ + \"documentation\":\"

The Quality of Service (QoS) level.

\" \ + }, \ + \"payload\":{ \ + \"shape\":\"Payload\", \ + \"documentation\":\"

The state information, in JSON format.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the Publish operation.

\", \ + \"required\":[\"topic\"], \ + \"payload\":\"payload\" \ + }, \ + \"Qos\":{ \ + \"type\":\"integer\", \ + \"min\":0, \ + \"max\":1 \ + }, \ + \"RequestEntityTooLargeException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"ErrorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":413}, \ + \"exception\":true, \ + \"documentation\":\"

The payload exceeds the maximum size allowed.

\" \ + }, \ + \"ResourceNotFoundException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + \"ServiceUnavailableException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + \"ThingName\":{ \ + \"type\":\"string\", \ + \"min\":1, \ + \"max\":128, \ + \"pattern\":\"[a-zA-Z0-9_-]+\" \ + }, \ + \"ThrottlingException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + \"Topic\":{\"type\":\"string\"}, \ + \"UnauthorizedException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + \"UnsupportedDocumentEncodingException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":415}, \ + \"exception\":true, \ + \"documentation\":\"

The document encoding is not supported.

\" \ + }, \ + \"UpdateThingShadowRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"thingName\", \ + \"payload\" \ + ], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + }, \ + \"payload\":{ \ + \"shape\":\"JsonDocument\", \ + \"documentation\":\"

The state information, in JSON format.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the UpdateThingShadow operation.

\", \ + \"payload\":\"payload\" \ + }, \ + \"UpdateThingShadowResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"payload\":{ \ + \"shape\":\"JsonDocument\", \ + \"documentation\":\"

The state information, in JSON format.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the UpdateThingShadow operation.

\", \ + \"payload\":\"payload\" \ + }, \ + \"errorMessage\":{\"type\":\"string\"} \ + }, \ + \"examples\":{ \ + } \ +} \ + \ +"; +} + +@end diff --git a/AWSIoT/AWSIoTDataService.h b/AWSIoT/AWSIoTDataService.h new file mode 100644 index 00000000000..c04b9d101bc --- /dev/null +++ b/AWSIoT/AWSIoTDataService.h @@ -0,0 +1,222 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import +#import "AWSIoTDataModel.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + AWS IoT (Beta)

AWS IoT is considered a beta service as defined in the Service Terms

AWS IoT-Data enables secure, bi-directional communication between Internet-connected things (such as sensors, actuators, embedded devices, or smart appliances) and the AWS cloud. It implements a broker for applications and things to publish messages over HTTP (Publish) and retrieve, update, and delete thing shadows. A thing shadow is a persistent representation of your things and their state in the AWS cloud.

+ */ +@interface AWSIoTData : AWSService + +/** + The service configuration used to instantiate this service client. + + @warning Once the client is instantiated, do not modify the configuration object. It may cause unspecified behaviors. + */ +@property (nonatomic, strong, readonly) AWSServiceConfiguration *configuration; + +/** + Returns the singleton service client. If the singleton object does not exist, the SDK instantiates the default service client with `defaultServiceConfiguration` from `[AWSServiceManager defaultServiceManager]`. The reference to this object is maintained by the SDK, and you do not need to retain it manually. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialProvider) + AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 + credentialsProvider:credentialsProvider]; + [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; + + return YES; + } + + Then call the following to get the default service client: + + *Swift* + + let IoTData = AWSIoTData.defaultIoTData() + + *Objective-C* + + AWSIoTData *IoTData = [AWSIoTData defaultIoTData]; + + @return The default service client. + */ ++ (instancetype)defaultIoTData; + +/** + Creates a service client with the given service configuration and registers it for the key. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) + AWSIoTData.registerIoTDataWithConfiguration(configuration, forKey: "USWest2IoTData") + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 + credentialsProvider:credentialsProvider]; + + [AWSIoTData registerIoTDataWithConfiguration:configuration forKey:@"USWest2IoTData"]; + + return YES; + } + + Then call the following to get the service client: + + *Swift* + + let IoTData = AWSIoTData(forKey: "USWest2IoTData") + + *Objective-C* + + AWSIoTData *IoTData = [AWSIoTData IoTDataForKey:@"USWest2IoTData"]; + + @warning After calling this method, do not modify the configuration object. It may cause unspecified behaviors. + + @param configuration A service configuration object. + @param key A string to identify the service client. + */ ++ (void)registerIoTDataWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key; + +/** + Retrieves the service client associated with the key. You need to call `+ registerIoTDataWithConfiguration:forKey:` before invoking this method. If `+ registerIoTDataWithConfiguration:forKey:` has not been called in advance or the key does not exist, this method returns `nil`. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) + AWSIoTData.registerIoTDataWithConfiguration(configuration, forKey: "USWest2IoTData") + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 + credentialsProvider:credentialsProvider]; + + [AWSIoTData registerIoTDataWithConfiguration:configuration forKey:@"USWest2IoTData"]; + + return YES; + } + + Then call the following to get the service client: + + *Swift* + + let IoTData = AWSIoTData(forKey: "USWest2IoTData") + + *Objective-C* + + AWSIoTData *IoTData = [AWSIoTData IoTDataForKey:@"USWest2IoTData"]; + + @param key A string to identify the service client. + + @return An instance of the service client. + */ ++ (instancetype)IoTDataForKey:(NSString *)key; + +/** + Removes the service client associated with the key and release it. + + @warning Before calling this method, make sure no method is running on this client. + + @param key A string to identify the service client. + */ ++ (void)removeIoTDataForKey:(NSString *)key; + +/** +

Deletes the thing shadow for the specified thing.

For more information, see DeleteThingShadow in the AWS IoT Developer Guide.

+ + @param request A container for the necessary parameters to execute the DeleteThingShadow service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTDataDeleteThingShadowResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTDataErrorDomain` domain and the following error code: `AWSIoTDataErrorResourceNotFound`, `AWSIoTDataErrorInvalidRequest`, `AWSIoTDataErrorThrottling`, `AWSIoTDataErrorUnauthorized`, `AWSIoTDataErrorServiceUnavailable`, `AWSIoTDataErrorInternalFailure`, `AWSIoTDataErrorMethodNotAllowed`, `AWSIoTDataErrorUnsupportedDocumentEncoding`. + + @see AWSIoTDataDeleteThingShadowRequest + @see AWSIoTDataDeleteThingShadowResponse + */ +- (AWSTask *)deleteThingShadow:(AWSIoTDataDeleteThingShadowRequest *)request; + +/** +

Gets the thing shadow for the specified thing.

For more information, see GetThingShadow in the AWS IoT Developer Guide.

+ + @param request A container for the necessary parameters to execute the GetThingShadow service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTDataGetThingShadowResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTDataErrorDomain` domain and the following error code: `AWSIoTDataErrorInvalidRequest`, `AWSIoTDataErrorResourceNotFound`, `AWSIoTDataErrorThrottling`, `AWSIoTDataErrorUnauthorized`, `AWSIoTDataErrorServiceUnavailable`, `AWSIoTDataErrorInternalFailure`, `AWSIoTDataErrorMethodNotAllowed`, `AWSIoTDataErrorUnsupportedDocumentEncoding`. + + @see AWSIoTDataGetThingShadowRequest + @see AWSIoTDataGetThingShadowResponse + */ +- (AWSTask *)getThingShadow:(AWSIoTDataGetThingShadowRequest *)request; + +/** +

Publishes state information.

For more information, see HTTP Protocol in the AWS IoT Developer Guide.

+ + @param request A container for the necessary parameters to execute the Publish service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTDataErrorDomain` domain and the following error code: `AWSIoTDataErrorInternalFailure`, `AWSIoTDataErrorInvalidRequest`, `AWSIoTDataErrorUnauthorized`, `AWSIoTDataErrorMethodNotAllowed`. + + @see AWSIoTDataPublishRequest + */ +- (AWSTask *)publish:(AWSIoTDataPublishRequest *)request; + +/** +

Updates the thing shadow for the specified thing.

For more information, see UpdateThingShadow in the AWS IoT Developer Guide.

+ + @param request A container for the necessary parameters to execute the UpdateThingShadow service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTDataUpdateThingShadowResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTDataErrorDomain` domain and the following error code: `AWSIoTDataErrorConflict`, `AWSIoTDataErrorRequestEntityTooLarge`, `AWSIoTDataErrorInvalidRequest`, `AWSIoTDataErrorThrottling`, `AWSIoTDataErrorUnauthorized`, `AWSIoTDataErrorServiceUnavailable`, `AWSIoTDataErrorInternalFailure`, `AWSIoTDataErrorMethodNotAllowed`, `AWSIoTDataErrorUnsupportedDocumentEncoding`. + + @see AWSIoTDataUpdateThingShadowRequest + @see AWSIoTDataUpdateThingShadowResponse + */ +- (AWSTask *)updateThingShadow:(AWSIoTDataUpdateThingShadowRequest *)request; + +@end + +NS_ASSUME_NONNULL_END diff --git a/AWSIoT/AWSIoTDataService.m b/AWSIoT/AWSIoTDataService.m new file mode 100644 index 00000000000..242b5ed429d --- /dev/null +++ b/AWSIoT/AWSIoTDataService.m @@ -0,0 +1,301 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTDataService.h" +#import "AWSNetworking.h" +#import "AWSCategory.h" +#import "AWSNetworking.h" +#import "AWSSignature.h" +#import "AWSService.h" +#import "AWSURLRequestSerialization.h" +#import "AWSURLResponseSerialization.h" +#import "AWSURLRequestRetryHandler.h" +#import "AWSSynchronizedMutableDictionary.h" +#import "AWSIoTDataResources.h" + +@interface AWSIoTDataResponseSerializer : AWSJSONResponseSerializer + +@end + +@implementation AWSIoTDataResponseSerializer + +#pragma mark - Service errors + +static NSDictionary *errorCodeDictionary = nil; ++ (void)initialize { + errorCodeDictionary = @{ + @"IncompleteSignature" : @(AWSIoTDataErrorIncompleteSignature), + @"InvalidClientTokenId" : @(AWSIoTDataErrorInvalidClientTokenId), + @"MissingAuthenticationToken" : @(AWSIoTDataErrorMissingAuthenticationToken), + @"ConflictException" : @(AWSIoTDataErrorConflict), + @"InternalFailureException" : @(AWSIoTDataErrorInternalFailure), + @"InvalidRequestException" : @(AWSIoTDataErrorInvalidRequest), + @"MethodNotAllowedException" : @(AWSIoTDataErrorMethodNotAllowed), + @"RequestEntityTooLargeException" : @(AWSIoTDataErrorRequestEntityTooLarge), + @"ResourceNotFoundException" : @(AWSIoTDataErrorResourceNotFound), + @"ServiceUnavailableException" : @(AWSIoTDataErrorServiceUnavailable), + @"ThrottlingException" : @(AWSIoTDataErrorThrottling), + @"UnauthorizedException" : @(AWSIoTDataErrorUnauthorized), + @"UnsupportedDocumentEncodingException" : @(AWSIoTDataErrorUnsupportedDocumentEncoding), + }; +} + +- (id)responseObjectForResponse:(NSHTTPURLResponse *)response + originalRequest:(NSURLRequest *)originalRequest + currentRequest:(NSURLRequest *)currentRequest + data:(id)data + error:(NSError *__autoreleasing *)error { + id responseObject = [super responseObjectForResponse:response + originalRequest:originalRequest + currentRequest:currentRequest + data:data + error:error]; + if (!*error && [responseObject isKindOfClass:[NSDictionary class]]) { + NSString *errorTypeStr = [[response allHeaderFields] objectForKey:@"x-amzn-ErrorType"]; + NSString *errorTypeHeader = [[errorTypeStr componentsSeparatedByString:@":"] firstObject]; + + if ([errorTypeStr length] > 0 && errorTypeHeader) { + if (errorCodeDictionary[errorTypeHeader]) { + if (error) { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey : [responseObject objectForKey:@"message"]?[responseObject objectForKey:@"message"]:[NSNull null], NSLocalizedFailureReasonErrorKey: errorTypeStr}; + *error = [NSError errorWithDomain:AWSIoTDataErrorDomain + code:[[errorCodeDictionary objectForKey:errorTypeHeader] integerValue] + userInfo:userInfo]; + } + return responseObject; + } else if (errorTypeHeader) { + if (error) { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey : [responseObject objectForKey:@"message"]?[responseObject objectForKey:@"message"]:[NSNull null], NSLocalizedFailureReasonErrorKey: errorTypeStr}; + *error = [NSError errorWithDomain:AWSIoTDataErrorDomain + code:AWSIoTDataErrorUnknown + userInfo:userInfo]; + } + return responseObject; + } + } + + if (self.outputClass) { + responseObject = [AWSMTLJSONAdapter modelOfClass:self.outputClass + fromJSONDictionary:responseObject + error:error]; + } + } + + return responseObject; +} + +@end + +@interface AWSIoTDataRequestRetryHandler : AWSURLRequestRetryHandler + +@end + +@implementation AWSIoTDataRequestRetryHandler + +- (AWSNetworkingRetryType)shouldRetry:(uint32_t)currentRetryCount + response:(NSHTTPURLResponse *)response + data:(NSData *)data + error:(NSError *)error { + AWSNetworkingRetryType retryType = [super shouldRetry:currentRetryCount + response:response + data:data + error:error]; + if(retryType == AWSNetworkingRetryTypeShouldNotRetry && + currentRetryCount < self.maxRetryCount) { + if ([error.domain isEqualToString:AWSIoTDataErrorDomain]) { + switch (error.code) { + case AWSIoTDataErrorIncompleteSignature: + case AWSIoTDataErrorInvalidClientTokenId: + case AWSIoTDataErrorMissingAuthenticationToken: + retryType = AWSNetworkingRetryTypeShouldRefreshCredentialsAndRetry; + break; + + default: + break; + } + } else if ([error.domain isEqualToString:AWSGeneralErrorDomain]) { + switch (error.code) { + case AWSGeneralErrorSignatureDoesNotMatch: + retryType = AWSNetworkingRetryTypeShouldCorrectClockSkewAndRetry; + break; + + default: + break; + } + } + } + + return retryType; +} + +@end + +@interface AWSRequest() + +@property (nonatomic, strong) AWSNetworkingRequest *internalRequest; + +@end + +@interface AWSIoTData() + +@property (nonatomic, strong) AWSNetworking *networking; +@property (nonatomic, strong) AWSServiceConfiguration *configuration; +@property (nonatomic, strong) AWSEndpoint *endpoint; + +@end + +@interface AWSServiceConfiguration() + +@property (nonatomic, strong) AWSEndpoint *endpoint; + +@end + +@implementation AWSIoTData + +static AWSSynchronizedMutableDictionary *_serviceClients = nil; + ++ (instancetype)defaultIoTData { + if (![AWSServiceManager defaultServiceManager].defaultServiceConfiguration) { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`defaultServiceConfiguration` is `nil`. You need to set it before using this method." + userInfo:nil]; + } + + static AWSIoTData *_defaultIoTData = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _defaultIoTData = [[AWSIoTData alloc] initWithConfiguration:AWSServiceManager.defaultServiceManager.defaultServiceConfiguration]; + }); + + return _defaultIoTData; +} + ++ (void)registerIoTDataWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _serviceClients = [AWSSynchronizedMutableDictionary new]; + }); + [_serviceClients setObject:[[AWSIoTData alloc] initWithConfiguration:configuration] + forKey:key]; +} + ++ (instancetype)IoTDataForKey:(NSString *)key { + return [_serviceClients objectForKey:key]; +} + ++ (void)removeIoTDataForKey:(NSString *)key { + [_serviceClients removeObjectForKey:key]; +} + +- (instancetype)init { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`- init` is not a valid initializer. Use `+ defaultIoTData` or `+ IoTDataForKey:` instead." + userInfo:nil]; + return nil; +} + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration { + if (self = [super init]) { + _configuration = [configuration copy]; + + _configuration.endpoint = [[AWSEndpoint alloc] initWithRegion:_configuration.regionType + service:AWSServiceIoTData + useUnsafeURL:NO]; + + AWSSignatureV4Signer *signer = [[AWSSignatureV4Signer alloc] initWithCredentialsProvider:_configuration.credentialsProvider + endpoint:_configuration.endpoint]; + AWSNetworkingRequestInterceptor *baseInterceptor = [[AWSNetworkingRequestInterceptor alloc] initWithUserAgent:_configuration.userAgent]; + _configuration.requestInterceptors = @[baseInterceptor, signer]; + + _configuration.baseURL = _configuration.endpoint.URL; + _configuration.requestSerializer = [AWSJSONRequestSerializer new]; + _configuration.retryHandler = [[AWSIoTDataRequestRetryHandler alloc] initWithMaximumRetryCount:_configuration.maxRetryCount]; + _configuration.headers = @{@"Content-Type" : @"application/x-amz-json-1.1"}; + + _networking = [[AWSNetworking alloc] initWithConfiguration:_configuration]; + } + + return self; +} + +- (AWSTask *)invokeRequest:(AWSRequest *)request + HTTPMethod:(AWSHTTPMethod)HTTPMethod + URLString:(NSString *) URLString + targetPrefix:(NSString *)targetPrefix + operationName:(NSString *)operationName + outputClass:(Class)outputClass { + if (!request) { + request = [AWSRequest new]; + } + + AWSNetworkingRequest *networkingRequest = request.internalRequest; + if (request) { + networkingRequest.parameters = [[AWSMTLJSONAdapter JSONDictionaryFromModel:request] aws_removeNullValues]; + } else { + networkingRequest.parameters = @{}; + } + + + NSMutableDictionary *headers = [NSMutableDictionary new]; + + networkingRequest.headers = headers; + networkingRequest.HTTPMethod = HTTPMethod; + networkingRequest.requestSerializer = [[AWSJSONRequestSerializer alloc] initWithJSONDefinition:[[AWSIoTDataResources sharedInstance] JSONObject] + actionName:operationName]; + networkingRequest.responseSerializer = [[AWSIoTDataResponseSerializer alloc] initWithJSONDefinition:[[AWSIoTDataResources sharedInstance] JSONObject] + actionName:operationName + outputClass:outputClass]; + return [self.networking sendRequest:networkingRequest]; +} + +#pragma mark - Service method + +- (AWSTask *)deleteThingShadow:(AWSIoTDataDeleteThingShadowRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodDELETE + URLString:@"/things/{thingName}/shadow" + targetPrefix:@"" + operationName:@"DeleteThingShadow" + outputClass:[AWSIoTDataDeleteThingShadowResponse class]]; +} + +- (AWSTask *)getThingShadow:(AWSIoTDataGetThingShadowRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/things/{thingName}/shadow" + targetPrefix:@"" + operationName:@"GetThingShadow" + outputClass:[AWSIoTDataGetThingShadowResponse class]]; +} + +- (AWSTask *)publish:(AWSIoTDataPublishRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/topics/{topic}" + targetPrefix:@"" + operationName:@"Publish" + outputClass:nil]; +} + +- (AWSTask *)updateThingShadow:(AWSIoTDataUpdateThingShadowRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/things/{thingName}/shadow" + targetPrefix:@"" + operationName:@"UpdateThingShadow" + outputClass:[AWSIoTDataUpdateThingShadowResponse class]]; +} + +@end diff --git a/AWSIoT/AWSIoTManager.h b/AWSIoT/AWSIoTManager.h new file mode 100644 index 00000000000..168b8dae897 --- /dev/null +++ b/AWSIoT/AWSIoTManager.h @@ -0,0 +1,204 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTService.h" + +//CreateCertificateWithResponse +@interface AWSIoTCreateCertificateResponse : AWSModel + +@property (nonatomic, strong) NSString *certificateArn; +@property (nonatomic, strong) NSString *certificateId; +@property (nonatomic, strong) NSString *certificatePem; + +@end + +@interface AWSIoTManager : AWSService + +/** + The service configuration used to instantiate this service client. + + @warning Once the client is instantiated, do not modify the configuration object. It may cause unspecified behaviors. + */ +@property (nonatomic, strong, readonly) AWSServiceConfiguration *configuration; + +/** + Returns the singleton service client. If the singleton object does not exist, the SDK instantiates the default service client with `defaultServiceConfiguration` from `[AWSServiceManager defaultServiceManager]`. The reference to this object is maintained by the SDK, and you do not need to retain it manually. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialProvider) + AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 + credentialsProvider:credentialsProvider]; + [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; + + return YES; + } + + Then call the following to get the default service client: + + *Swift* + + let IoTManager = AWSIoTManager.defaultIoTManager() + + *Objective-C* + + AWSIoTManager *IoTManager = [AWSIoTManager defaultIoTManager]; + + @return The default service client. + */ ++ (instancetype)defaultIoTManager; + +/** + Creates a service client with the given service configuration and registers it for the key. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) + AWSIoTManager.registerIoTManagerWithConfiguration(configuration, forKey: "USWest2IoTManager") + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 + credentialsProvider:credentialsProvider]; + + [AWSIoTManager registerIoTManagerWithConfiguration:configuration forKey:@"USWest2IoTManager"]; + + return YES; + } + + Then call the following to get the service client: + + *Swift* + + let IoTManager = AWSIoTManager(forKey: "USWest2IoTManager") + + *Objective-C* + + AWSIoTManager *IoTManager = [AWSIoTManager IoTManagerForKey:@"USWest2IoTManager"]; + + @warning After calling this method, do not modify the configuration object. It may cause unspecified behaviors. + + @param configuration A service configuration object. + @param key A string to identify the service client. + + @return The service client configured as requested + + */ ++ (void)registerIoTManagerWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key; + +/** + Retrieves the service client associated with the key. You need to call `+ registerIoTManagerWithConfiguration:forKey:` before invoking this method. If `+ registerIoTManagerWithConfiguration:forKey:` has not been called in advance or the key does not exist, this method returns `nil`. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) + AWSIoTManager.registerIoTManagerWithConfiguration(configuration, forKey: "USWest2IoTManager") + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 + credentialsProvider:credentialsProvider]; + + [AWSIoTManager registerIoTManagerWithConfiguration:configuration forKey:@"USWest2IoTManager"]; + + return YES; + } + + Then call the following to get the service client: + + *Swift* + + let IoTManager = AWSIoTManager(forKey: "USWest2IoTManager") + + *Objective-C* + + AWSIoTManager *IoTManager = [AWSIoTManager IoTManagerForKey:@"USWest2IoTManager"]; + + @param key A string to identify the service client. + + @return An instance of the service client. + */ ++ (instancetype)IoTManagerForKey:(NSString *)key; + +/** + Removes the service client associated with the key and release it. + + @warning Before calling this method, make sure no method is running on this client. + + @param key A string to identify the service client. + */ ++ (void)removeIoTManagerForKey:(NSString *)key; + +/** + * Creates keys and certificate from a CSR created using the specified dictionary + * + * @param csrDictionary contains values used to generate the CSR. Requires values for + * keys: commonName, countryName, organizationName, organizationalUnitName + * + * @param callback When new certificate is created the function of block will be called with an instance of `AWSIOTDescribeCertificateResponse` + */ +- (void)createKeysAndCertificateFromCsr:(NSDictionary *)csrDictionary callback:(void (^)(AWSIoTCreateCertificateResponse *mainResponse))callback; + +/** + * Validates the certificate with the given identifier of certificate. + * + * @param certificateId The certificate identifier + * + * @return TRUE if certificate is valid, else FALSE + */ ++ (BOOL)isValidCertificate:(NSString *)certificateId; + +/** + * Deletes keys and certificate + * +* @return TRUE if certificate is deleted, else FALSE + */ ++ (BOOL)deleteCertificate; + +@end diff --git a/AWSIoT/AWSIoTManager.m b/AWSIoT/AWSIoTManager.m new file mode 100644 index 00000000000..9f21e313f71 --- /dev/null +++ b/AWSIoT/AWSIoTManager.m @@ -0,0 +1,199 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTManager.h" +#import "AWSIoTKeychain.h" +#import "AWSIoTCSR.h" +#import + +@interface AWSIoT() + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration; + +@end + +@interface AWSIoTManager() + +@property (nonatomic, strong) AWSIoT *IoT; + +@end + +@implementation AWSIoTCreateCertificateResponse + +@end + +@implementation AWSIoTManager + +static AWSSynchronizedMutableDictionary *_serviceClients = nil; + ++ (instancetype)defaultIoTManager { + if (![AWSServiceManager defaultServiceManager].defaultServiceConfiguration) { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`defaultServiceConfiguration` is `nil`. You need to set it before using this method." + userInfo:nil]; + } + + static AWSIoTManager *_defaultIoTManager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _defaultIoTManager = [[AWSIoTManager alloc] initWithConfiguration:AWSServiceManager.defaultServiceManager.defaultServiceConfiguration]; + }); + + return _defaultIoTManager; +} + ++ (void)registerIoTManagerWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _serviceClients = [AWSSynchronizedMutableDictionary new]; + }); + [_serviceClients setObject:[[AWSIoTManager alloc] initWithConfiguration:configuration] + forKey:key]; +} + ++ (instancetype)IoTManagerForKey:(NSString *)key { + return [_serviceClients objectForKey:key]; +} + ++ (void)removeIoTManagerForKey:(NSString *)key { + [_serviceClients removeObjectForKey:key]; +} + +- (instancetype)init { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`- init` is not a valid initializer. Use `+ defaultIoTManager` or `+ IoTManagerForKey:` instead." + userInfo:nil]; + return nil; +} +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration { + if (self = [super init]) { + _configuration = [configuration copy]; + _IoT = [[AWSIoT alloc] initWithConfiguration:_configuration]; + } + + return self; +} + +- (void)createKeysAndCertificateFromCsr:(NSDictionary *)csrDictionary callback:(void (^)(AWSIoTCreateCertificateResponse *mainResponse))callback { + + NSString *commonName = [csrDictionary objectForKey:@"commonName"]; + NSString *countryName = [csrDictionary objectForKey:@"countryName"]; + NSString *organizationName = [csrDictionary objectForKey:@"organizationName"]; + NSString *organizationalUnitName = [csrDictionary objectForKey:@"organizationalUnitName"]; + + if ((commonName == nil) || (countryName == nil) || (organizationName == nil) || (organizationalUnitName == nil)) + { + NSLog(@"all CSR dictionary fields must be specified"); + callback(nil); + } + + NSString *uuid = [[NSUUID UUID] UUIDString]; + NSString *publicTag = [AWSIoTKeychain.publicKeyTag stringByAppendingString:uuid]; + NSString *privateTag = [AWSIoTKeychain.privateKeyTag stringByAppendingString:uuid]; + [AWSIoTKeychain generateKeyPairWithPublicTag:publicTag privateTag:privateTag]; + + AWSIoTCSR *csr = [[AWSIoTCSR alloc] initWithCommonName: commonName countryName:countryName organizationName: organizationName organizationalUnitName: organizationalUnitName ]; + + NSData* csrData = [csr generateCSRForCertificate:uuid]; + + // Create certificate from CSR + AWSIoTCreateCertificateFromCsrRequest *request = [[AWSIoTCreateCertificateFromCsrRequest alloc] init]; + request.setAsActive = @YES; + + request.certificateSigningRequest = [AWSIoTKeychain base64Encode:csrData]; + + [[self.IoT createCertificateFromCsr:request] continueWithBlock:^id(AWSTask *task) { + NSError *error = task.error; + NSLog(@"error: %@", error); + if (error != nil) { + callback(nil); + return nil; + } + NSException *exception = task.exception; + NSLog(@"exception: %@", exception); + if (exception != nil) { + callback(nil); + return nil; + } + + NSLog(@"result: %@", task.result); + + if ([task.result isKindOfClass:[AWSIoTCreateCertificateFromCsrResponse class]]) { + + AWSIoTCreateCertificateFromCsrResponse *response = task.result; + + NSString* certificateArn = response.certificateArn; + NSLog(@"certificateArn: %@", certificateArn); + + NSString* certificateId = response.certificateId; + NSLog(@"certificateId: %@", certificateId); + + NSString* certificatePem = response.certificatePem; + NSLog(@"certificatePem: %@", certificatePem); + + if (certificatePem != nil && certificateArn != nil && certificateId != nil) { + NSString *newPublicTag = [AWSIoTKeychain.publicKeyTag stringByAppendingString:certificateId]; + NSString *newPrivateTag = [AWSIoTKeychain.privateKeyTag stringByAppendingString:certificateId]; + + SecKeyRef publicKeyRef = [AWSIoTKeychain getPublicKeyRef:publicTag]; + SecKeyRef privateKeyRef = [AWSIoTKeychain getPrivateKeyRef:privateTag]; + + if ([AWSIoTKeychain deleteAsymmetricKeysWithPublicTag:publicTag privateTag:privateTag]) { + if ([AWSIoTKeychain addPrivateKeyRef:privateKeyRef tag:newPrivateTag]) { + if ([AWSIoTKeychain addPublicKeyRef:publicKeyRef tag:newPublicTag]) { + if ([AWSIoTKeychain addCertificateToKeychain:certificatePem]) { + SecIdentityRef secIdentityRef = [AWSIoTKeychain getIdentityRef:newPrivateTag]; + if (secIdentityRef != nil) { + AWSIoTCreateCertificateResponse* resp = [[AWSIoTCreateCertificateResponse alloc] init]; + resp.certificateId = certificateId; + resp.certificatePem = certificatePem; + resp.certificateArn = certificateArn; + + callback(resp); + } else { + callback(nil); + } + } else { + callback(nil); + } + } else { + callback(nil); + } + } else { + callback(nil); + } + } else { + callback(nil); + } + } else { + callback(nil); + } + } else { + callback(nil); + } + + return nil; + }]; +} + ++ (BOOL)deleteCertificate { + return [AWSIoTKeychain removeCertificate]; +} + ++ (BOOL)isValidCertificate:(NSString *)certificateId { + return [AWSIoTKeychain isValidCertificate:[NSString stringWithFormat:@"%@%@",[AWSIoTKeychain privateKeyTag], certificateId ]]; +} + +@end diff --git a/AWSIoT/AWSIoTModel.h b/AWSIoT/AWSIoTModel.h new file mode 100644 index 00000000000..dd4e5ad2f7a --- /dev/null +++ b/AWSIoT/AWSIoTModel.h @@ -0,0 +1,1796 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const AWSIoTErrorDomain; + +typedef NS_ENUM(NSInteger, AWSIoTErrorType) { + AWSIoTErrorUnknown, + AWSIoTErrorIncompleteSignature, + AWSIoTErrorInvalidClientTokenId, + AWSIoTErrorMissingAuthenticationToken, + AWSIoTErrorCertificateState, + AWSIoTErrorDeleteConflict, + AWSIoTErrorInternal, + AWSIoTErrorInternalFailure, + AWSIoTErrorInvalidRequest, + AWSIoTErrorLimitExceeded, + AWSIoTErrorMalformedPolicy, + AWSIoTErrorResourceAlreadyExists, + AWSIoTErrorResourceNotFound, + AWSIoTErrorServiceUnavailable, + AWSIoTErrorSqlParse, + AWSIoTErrorThrottling, + AWSIoTErrorTransferAlreadyCompleted, + AWSIoTErrorTransferConflict, + AWSIoTErrorUnauthorized, + AWSIoTErrorVersionsLimitExceeded, +}; + +typedef NS_ENUM(NSInteger, AWSIoTCertificateStatus) { + AWSIoTCertificateStatusUnknown, + AWSIoTCertificateStatusActive, + AWSIoTCertificateStatusInactive, + AWSIoTCertificateStatusRevoked, + AWSIoTCertificateStatusPendingTransfer, +}; + +typedef NS_ENUM(NSInteger, AWSIoTLogLevel) { + AWSIoTLogLevelUnknown, + AWSIoTLogLevelDebug, + AWSIoTLogLevelInfo, + AWSIoTLogLevelError, + AWSIoTLogLevelWarn, + AWSIoTLogLevelDisabled, +}; + +@class AWSIoTAcceptCertificateTransferRequest; +@class AWSIoTAction; +@class AWSIoTAttachPrincipalPolicyRequest; +@class AWSIoTAttachThingPrincipalRequest; +@class AWSIoTAttachThingPrincipalResponse; +@class AWSIoTAttributePayload; +@class AWSIoTCancelCertificateTransferRequest; +@class AWSIoTCertificate; +@class AWSIoTCertificateDescription; +@class AWSIoTCreateCertificateFromCsrRequest; +@class AWSIoTCreateCertificateFromCsrResponse; +@class AWSIoTCreateKeysAndCertificateRequest; +@class AWSIoTCreateKeysAndCertificateResponse; +@class AWSIoTCreatePolicyRequest; +@class AWSIoTCreatePolicyResponse; +@class AWSIoTCreatePolicyVersionRequest; +@class AWSIoTCreatePolicyVersionResponse; +@class AWSIoTCreateThingRequest; +@class AWSIoTCreateThingResponse; +@class AWSIoTCreateTopicRuleRequest; +@class AWSIoTDeleteCertificateRequest; +@class AWSIoTDeletePolicyRequest; +@class AWSIoTDeletePolicyVersionRequest; +@class AWSIoTDeleteThingRequest; +@class AWSIoTDeleteThingResponse; +@class AWSIoTDeleteTopicRuleRequest; +@class AWSIoTDescribeCertificateRequest; +@class AWSIoTDescribeCertificateResponse; +@class AWSIoTDescribeEndpointRequest; +@class AWSIoTDescribeEndpointResponse; +@class AWSIoTDescribeThingRequest; +@class AWSIoTDescribeThingResponse; +@class AWSIoTDetachPrincipalPolicyRequest; +@class AWSIoTDetachThingPrincipalRequest; +@class AWSIoTDetachThingPrincipalResponse; +@class AWSIoTDynamoDBAction; +@class AWSIoTFirehoseAction; +@class AWSIoTGetLoggingOptionsRequest; +@class AWSIoTGetLoggingOptionsResponse; +@class AWSIoTGetPolicyRequest; +@class AWSIoTGetPolicyResponse; +@class AWSIoTGetPolicyVersionRequest; +@class AWSIoTGetPolicyVersionResponse; +@class AWSIoTGetTopicRuleRequest; +@class AWSIoTGetTopicRuleResponse; +@class AWSIoTKeyPair; +@class AWSIoTKinesisAction; +@class AWSIoTLambdaAction; +@class AWSIoTListCertificatesRequest; +@class AWSIoTListCertificatesResponse; +@class AWSIoTListPoliciesRequest; +@class AWSIoTListPoliciesResponse; +@class AWSIoTListPolicyVersionsRequest; +@class AWSIoTListPolicyVersionsResponse; +@class AWSIoTListPrincipalPoliciesRequest; +@class AWSIoTListPrincipalPoliciesResponse; +@class AWSIoTListPrincipalThingsRequest; +@class AWSIoTListPrincipalThingsResponse; +@class AWSIoTListThingPrincipalsRequest; +@class AWSIoTListThingPrincipalsResponse; +@class AWSIoTListThingsRequest; +@class AWSIoTListThingsResponse; +@class AWSIoTListTopicRulesRequest; +@class AWSIoTListTopicRulesResponse; +@class AWSIoTLoggingOptionsPayload; +@class AWSIoTPolicy; +@class AWSIoTPolicyVersion; +@class AWSIoTRejectCertificateTransferRequest; +@class AWSIoTReplaceTopicRuleRequest; +@class AWSIoTRepublishAction; +@class AWSIoTS3Action; +@class AWSIoTSetDefaultPolicyVersionRequest; +@class AWSIoTSetLoggingOptionsRequest; +@class AWSIoTSnsAction; +@class AWSIoTSqsAction; +@class AWSIoTThingAttribute; +@class AWSIoTTopicRule; +@class AWSIoTTopicRuleListItem; +@class AWSIoTTopicRulePayload; +@class AWSIoTTransferCertificateRequest; +@class AWSIoTTransferCertificateResponse; +@class AWSIoTUpdateCertificateRequest; +@class AWSIoTUpdateThingRequest; +@class AWSIoTUpdateThingResponse; + +/** +

The input for the AcceptCertificateTransfer operation.

+ Required parameters: [certificateId] + */ +@interface AWSIoTAcceptCertificateTransferRequest : AWSRequest + + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +/** +

Specifies whether the certificate is active.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable setAsActive; + +@end + +/** +

Describes the actions associated with a rule.

+ */ +@interface AWSIoTAction : AWSModel + + +/** +

Write to a DynamoDB table.

+ */ +@property (nonatomic, strong) AWSIoTDynamoDBAction * _Nullable dynamoDB; + +/** + + */ +@property (nonatomic, strong) AWSIoTFirehoseAction * _Nullable firehose; + +/** +

Write data to a Kinesis stream.

+ */ +@property (nonatomic, strong) AWSIoTKinesisAction * _Nullable kinesis; + +/** +

Invoke a Lambda function.

+ */ +@property (nonatomic, strong) AWSIoTLambdaAction * _Nullable lambda; + +/** +

Publish to another MQTT topic.

+ */ +@property (nonatomic, strong) AWSIoTRepublishAction * _Nullable republish; + +/** +

Write to an S3 bucket.

+ */ +@property (nonatomic, strong) AWSIoTS3Action * _Nullable s3; + +/** +

Publish to an SNS topic.

+ */ +@property (nonatomic, strong) AWSIoTSnsAction * _Nullable sns; + +/** +

Publish to an SQS queue.

+ */ +@property (nonatomic, strong) AWSIoTSqsAction * _Nullable sqs; + +@end + +/** +

The input for the AttachPrincipalPolicy operation.

+ Required parameters: [policyName, principal] + */ +@interface AWSIoTAttachPrincipalPolicyRequest : AWSRequest + + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +/** +

The principal which can be a certificate ARN (as returned from the CreateCertificate operation) or a Cognito ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable principal; + +@end + +/** +

The input for the AttachThingPrincipal operation.

+ Required parameters: [thingName, principal] + */ +@interface AWSIoTAttachThingPrincipalRequest : AWSRequest + + +/** +

The principal (certificate or other credential).

+ */ +@property (nonatomic, strong) NSString * _Nullable principal; + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output from the AttachThingPrincipal operation.

+ */ +@interface AWSIoTAttachThingPrincipalResponse : AWSModel + + +@end + +/** +

The attribute payload, a JSON string containing up to three key-value pairs.

For example: {\"attributes\":{\"string1\":\"string2\”}}

+ */ +@interface AWSIoTAttributePayload : AWSModel + + +/** +

A JSON string containing up to three key-value pair in JSON format.

For example: {\"attributes\":{\"string1\":\"string2\”}}

+ */ +@property (nonatomic, strong) NSDictionary * _Nullable attributes; + +@end + +/** +

The input for the CancelCertificateTransfer operation.

+ Required parameters: [certificateId] + */ +@interface AWSIoTCancelCertificateTransferRequest : AWSRequest + + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +@end + +/** +

Information about a certificate.

+ */ +@interface AWSIoTCertificate : AWSModel + + +/** +

The ARN of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateArn; + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +/** +

The date and time the certificate was created.

+ */ +@property (nonatomic, strong) NSDate * _Nullable creationDate; + +/** +

The status of the certificate.

+ */ +@property (nonatomic, assign) AWSIoTCertificateStatus status; + +@end + +/** +

Describes a certificate.

+ */ +@interface AWSIoTCertificateDescription : AWSModel + + +/** +

The ARN of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateArn; + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +/** +

The certificate data, in PEM format.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificatePem; + +/** +

The date and time the certificate was created.

+ */ +@property (nonatomic, strong) NSDate * _Nullable creationDate; + +/** +

The date and time the certificate was last modified.

+ */ +@property (nonatomic, strong) NSDate * _Nullable lastModifiedDate; + +/** +

The ID of the AWS account that owns the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable ownedBy; + +/** +

The status of the certificate.

+ */ +@property (nonatomic, assign) AWSIoTCertificateStatus status; + +@end + +/** +

The input for the CreateCertificateFromCsr operation.

+ Required parameters: [certificateSigningRequest] + */ +@interface AWSIoTCreateCertificateFromCsrRequest : AWSRequest + + +/** +

The certificate signing request (CSR).

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateSigningRequest; + +/** +

Specifies whether the certificate is active.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable setAsActive; + +@end + +/** +

The output from the CreateCertificateFromCsr operation.

+ */ +@interface AWSIoTCreateCertificateFromCsrResponse : AWSModel + + +/** +

The Amazon Resource Name (ARN) of the certificate. You can use the ARN as a principal for policy operations.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateArn; + +/** +

The ID of the certificate. Certificate management operations only take a certificateId.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +/** +

The certificate data, in PEM format.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificatePem; + +@end + +/** +

The input for the CreateKeysAndCertificate operation.

+ */ +@interface AWSIoTCreateKeysAndCertificateRequest : AWSRequest + + +/** +

Specifies whether the certificate is active.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable setAsActive; + +@end + +/** +

The output of the CreateKeysAndCertificate operation.

+ */ +@interface AWSIoTCreateKeysAndCertificateResponse : AWSModel + + +/** +

The ARN of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateArn; + +/** +

The ID of the certificate. AWS IoT issues a default subject name for the certificate (e.g., AWS IoT Certificate).

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +/** +

The certificate data, in PEM format.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificatePem; + +/** +

The generated key pair.

+ */ +@property (nonatomic, strong) AWSIoTKeyPair * _Nullable keyPair; + +@end + +/** +

The input for the CreatePolicy operation.

+ Required parameters: [policyName, policyDocument] + */ +@interface AWSIoTCreatePolicyRequest : AWSRequest + + +/** +

The JSON document that describes the policy. The length of the policyDocument must be a minimum length of 1, with a maximum length of 2048, excluding whitespace.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyDocument; + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +@end + +/** +

The output from the CreatePolicy operation.

+ */ +@interface AWSIoTCreatePolicyResponse : AWSModel + + +/** +

The policy ARN.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyArn; + +/** +

The JSON document that describes the policy.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyDocument; + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +/** +

The policy version ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyVersionId; + +@end + +/** +

The input for the CreatePolicyVersion operation.

+ Required parameters: [policyName, policyDocument] + */ +@interface AWSIoTCreatePolicyVersionRequest : AWSRequest + + +/** +

The JSON document that describes the policy.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyDocument; + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +/** +

Specifies whether the policy version is set as the default.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable setAsDefault; + +@end + +/** +

The output of the CreatePolicyVersion operation.

+ */ +@interface AWSIoTCreatePolicyVersionResponse : AWSModel + + +/** +

Specifies whether the policy version is the default.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable isDefaultVersion; + +/** +

The policy ARN.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyArn; + +/** +

The JSON document that describes the policy.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyDocument; + +/** +

The policy version ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyVersionId; + +@end + +/** +

The input for the CreateThing operation.

+ Required parameters: [thingName] + */ +@interface AWSIoTCreateThingRequest : AWSRequest + + +/** +

The attribute payload. Which consists of up to 3 name/value pairs in a JSON document. For example: {\"attributes\":{\"string1\":\"string2\”}}

+ */ +@property (nonatomic, strong) AWSIoTAttributePayload * _Nullable attributePayload; + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output of the CreateThing operation.

+ */ +@interface AWSIoTCreateThingResponse : AWSModel + + +/** +

The thing ARN.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingArn; + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The input for the CreateTopicRule operation.

+ Required parameters: [ruleName, topicRulePayload] + */ +@interface AWSIoTCreateTopicRuleRequest : AWSRequest + + +/** +

The name of the rule.

+ */ +@property (nonatomic, strong) NSString * _Nullable ruleName; + +/** +

The rule payload.

+ */ +@property (nonatomic, strong) AWSIoTTopicRulePayload * _Nullable topicRulePayload; + +@end + +/** +

The input for the DeleteCertificate operation.

+ Required parameters: [certificateId] + */ +@interface AWSIoTDeleteCertificateRequest : AWSRequest + + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +@end + +/** +

The input for the DeletePolicy operation.

+ Required parameters: [policyName] + */ +@interface AWSIoTDeletePolicyRequest : AWSRequest + + +/** +

The name of the policy to delete.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +@end + +/** +

The input for the DeletePolicyVersion operation.

+ Required parameters: [policyName, policyVersionId] + */ +@interface AWSIoTDeletePolicyVersionRequest : AWSRequest + + +/** +

The name of the policy.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +/** +

The policy version ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyVersionId; + +@end + +/** +

The input for the DeleteThing operation.

+ Required parameters: [thingName] + */ +@interface AWSIoTDeleteThingRequest : AWSRequest + + +/** +

The thing name.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output of the DeleteThing operation.

+ */ +@interface AWSIoTDeleteThingResponse : AWSModel + + +@end + +/** +

The input for the DeleteTopicRule operation.

+ Required parameters: [ruleName] + */ +@interface AWSIoTDeleteTopicRuleRequest : AWSRequest + + +/** +

The name of the rule.

+ */ +@property (nonatomic, strong) NSString * _Nullable ruleName; + +@end + +/** +

The input for the DescribeCertificate operation.

+ Required parameters: [certificateId] + */ +@interface AWSIoTDescribeCertificateRequest : AWSRequest + + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +@end + +/** +

The output of the DescribeCertificate operation.

+ */ +@interface AWSIoTDescribeCertificateResponse : AWSModel + + +/** +

The description of the certificate.

+ */ +@property (nonatomic, strong) AWSIoTCertificateDescription * _Nullable certificateDescription; + +@end + +/** +

The input for the DescribeEndpoint operation.

+ */ +@interface AWSIoTDescribeEndpointRequest : AWSRequest + + +@end + +/** +

The output from the DescribeEndpoint operation.

+ */ +@interface AWSIoTDescribeEndpointResponse : AWSModel + + +/** +

The address.

+ */ +@property (nonatomic, strong) NSString * _Nullable endpointAddress; + +@end + +/** +

The input for the DescribeThing operation.

+ Required parameters: [thingName] + */ +@interface AWSIoTDescribeThingRequest : AWSRequest + + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output from the DescribeThing operation.

+ */ +@interface AWSIoTDescribeThingResponse : AWSModel + + +/** +

The attributes which are name/value pairs in JSON format. For example:

{\"attributes\":{\"some-name1\":\"some-value1\”}, {\"some-name2\":\"some-value2\”}, {\"some-name3\":\"some-value3\”}}

+ */ +@property (nonatomic, strong) NSDictionary * _Nullable attributes; + +/** +

The default client ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable defaultClientId; + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The input for the DetachPrincipalPolicy operation.

+ Required parameters: [policyName, principal] + */ +@interface AWSIoTDetachPrincipalPolicyRequest : AWSRequest + + +/** +

The name of the policy to detach.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +/** +

The principal

If the principal is a certificate, specify the certificate ARN. If the principal is a Cognito identity specify the identity ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable principal; + +@end + +/** +

The input for the DetachThingPrincipal operation.

+ Required parameters: [thingName, principal] + */ +@interface AWSIoTDetachThingPrincipalRequest : AWSRequest + + +/** +

The principal.

+ */ +@property (nonatomic, strong) NSString * _Nullable principal; + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output from the DetachThingPrincipal operation.

+ */ +@interface AWSIoTDetachThingPrincipalResponse : AWSModel + + +@end + +/** +

Describes an action to write to a DynamoDB table.

The tableName, hashKeyField, and rangeKeyField values must match the values used when you created the table.

The hashKeyValue and rangeKeyvalue fields use a substitution template syntax. These templates provide data at runtime. The syntax is as follows: ${sql-expression}.

You can specify any expression that's valid in a WHERE or SELECT clause, including JSON properties, comparisons, calculations, and functions. For example, the following field uses the third level of the topic:

"hashKeyValue": "${topic(3)}"

The following field uses the timestamp:

"rangeKeyValue": "${timestamp()}"

+ Required parameters: [tableName, roleArn, hashKeyField, hashKeyValue, rangeKeyField, rangeKeyValue] + */ +@interface AWSIoTDynamoDBAction : AWSModel + + +/** +

The hash key name.

+ */ +@property (nonatomic, strong) NSString * _Nullable hashKeyField; + +/** +

The hash key value.

+ */ +@property (nonatomic, strong) NSString * _Nullable hashKeyValue; + +/** +

The action payload.

+ */ +@property (nonatomic, strong) NSString * _Nullable payloadField; + +/** +

The range key name.

+ */ +@property (nonatomic, strong) NSString * _Nullable rangeKeyField; + +/** +

The range key value.

+ */ +@property (nonatomic, strong) NSString * _Nullable rangeKeyValue; + +/** +

The ARN of the IAM role that grants access.

+ */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +/** +

The name of the DynamoDB table.

+ */ +@property (nonatomic, strong) NSString * _Nullable tableName; + +@end + +/** + + */ +@interface AWSIoTFirehoseAction : AWSModel + + +/** + + */ +@property (nonatomic, strong) NSString * _Nullable deliveryStreamName; + +/** + + */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +@end + +/** +

The input for the GetLoggingOptions operation.

+ */ +@interface AWSIoTGetLoggingOptionsRequest : AWSRequest + + +@end + +/** +

The output from the GetLoggingOptions operation.

+ */ +@interface AWSIoTGetLoggingOptionsResponse : AWSModel + + +/** +

The logging level.

+ */ +@property (nonatomic, assign) AWSIoTLogLevel logLevel; + +/** +

The ARN of the IAM role that grants access.

+ */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +@end + +/** +

The input for the GetPolicy operation.

+ Required parameters: [policyName] + */ +@interface AWSIoTGetPolicyRequest : AWSRequest + + +/** +

The name of the policy.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +@end + +/** +

The output from the GetPolicy operation.

+ */ +@interface AWSIoTGetPolicyResponse : AWSModel + + +/** +

The default policy version ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable defaultVersionId; + +/** +

The policy ARN.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyArn; + +/** +

The JSON document that describes the policy.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyDocument; + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +@end + +/** +

The input for the GetPolicyVersion operation.

+ Required parameters: [policyName, policyVersionId] + */ +@interface AWSIoTGetPolicyVersionRequest : AWSRequest + + +/** +

The name of the policy.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +/** +

The policy version ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyVersionId; + +@end + +/** +

The output from the GetPolicyVersion operation.

+ */ +@interface AWSIoTGetPolicyVersionResponse : AWSModel + + +/** +

Specifies whether the policy version is the default.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable isDefaultVersion; + +/** +

The policy ARN.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyArn; + +/** +

The JSON document that describes the policy.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyDocument; + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +/** +

The policy version ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyVersionId; + +@end + +/** +

The input for the GetTopicRule operation.

+ Required parameters: [ruleName] + */ +@interface AWSIoTGetTopicRuleRequest : AWSRequest + + +/** +

The name of the rule.

+ */ +@property (nonatomic, strong) NSString * _Nullable ruleName; + +@end + +/** +

The output from the GetTopicRule operation.

+ */ +@interface AWSIoTGetTopicRuleResponse : AWSModel + + +/** +

The rule.

+ */ +@property (nonatomic, strong) AWSIoTTopicRule * _Nullable rule; + +@end + +/** +

Describes a key pair.

+ */ +@interface AWSIoTKeyPair : AWSModel + + +/** +

The private key.

+ */ +@property (nonatomic, strong) NSString * _Nullable privateKey; + +/** +

The public key.

+ */ +@property (nonatomic, strong) NSString * _Nullable publicKey; + +@end + +/** +

Describes an action to write data to an Amazon Kinesis stream.

+ Required parameters: [roleArn, streamName] + */ +@interface AWSIoTKinesisAction : AWSModel + + +/** +

The partition key.

+ */ +@property (nonatomic, strong) NSString * _Nullable partitionKey; + +/** +

The ARN of the IAM role that grants access.

+ */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +/** +

The name of the Kinesis stream.

+ */ +@property (nonatomic, strong) NSString * _Nullable streamName; + +@end + +/** +

Describes an action to invoke a Lamdba function.

+ Required parameters: [functionArn] + */ +@interface AWSIoTLambdaAction : AWSModel + + +/** +

The ARN of the Lambda function.

+ */ +@property (nonatomic, strong) NSString * _Nullable functionArn; + +@end + +/** +

The input for the ListCertificates operation.

+ */ +@interface AWSIoTListCertificatesRequest : AWSRequest + + +/** +

Specifies the order for results. If True, the results are returned in ascending order, based on the creation date.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable ascendingOrder; + +/** +

The marker for the next set of results.

+ */ +@property (nonatomic, strong) NSString * _Nullable marker; + +/** +

The result page size.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable pageSize; + +@end + +/** +

The output of the ListCertificates operation.

+ */ +@interface AWSIoTListCertificatesResponse : AWSModel + + +/** +

The descriptions of the certificates.

+ */ +@property (nonatomic, strong) NSArray * _Nullable certificates; + +/** +

The marker for the next set of results, or null if there are no additional results.

+ */ +@property (nonatomic, strong) NSString * _Nullable nextMarker; + +@end + +/** +

The input for the ListPolicies operation.

+ */ +@interface AWSIoTListPoliciesRequest : AWSRequest + + +/** +

Specifies the order for results. If true, the results are returned in ascending creation order.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable ascendingOrder; + +/** +

The marker for the next set of results.

+ */ +@property (nonatomic, strong) NSString * _Nullable marker; + +/** +

The result page size.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable pageSize; + +@end + +/** +

The output from the ListPolicies operation.

+ */ +@interface AWSIoTListPoliciesResponse : AWSModel + + +/** +

The marker for the next set of results, or null if there are no additional results.

+ */ +@property (nonatomic, strong) NSString * _Nullable nextMarker; + +/** +

The descriptions of the policies.

+ */ +@property (nonatomic, strong) NSArray * _Nullable policies; + +@end + +/** +

The input for the ListPolicyVersions operation.

+ Required parameters: [policyName] + */ +@interface AWSIoTListPolicyVersionsRequest : AWSRequest + + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +@end + +/** +

The output from the ListPolicyVersions operation.

+ */ +@interface AWSIoTListPolicyVersionsResponse : AWSModel + + +/** +

The policy versions.

+ */ +@property (nonatomic, strong) NSArray * _Nullable policyVersions; + +@end + +/** +

The input for the ListPrincipalPolicies operation.

+ Required parameters: [principal] + */ +@interface AWSIoTListPrincipalPoliciesRequest : AWSRequest + + +/** +

Specifies the order for results. If true, results are returned in ascending creation order.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable ascendingOrder; + +/** +

The marker for the next set of results.

+ */ +@property (nonatomic, strong) NSString * _Nullable marker; + +/** +

The result page size.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable pageSize; + +/** +

The principal.

+ */ +@property (nonatomic, strong) NSString * _Nullable principal; + +@end + +/** +

The output from the ListPrincipalPolicies operation.

+ */ +@interface AWSIoTListPrincipalPoliciesResponse : AWSModel + + +/** +

The marker for the next set of results, or null if there are no additional results.

+ */ +@property (nonatomic, strong) NSString * _Nullable nextMarker; + +/** +

The policies.

+ */ +@property (nonatomic, strong) NSArray * _Nullable policies; + +@end + +/** +

The input for the ListPrincipalThings operation.

+ Required parameters: [principal] + */ +@interface AWSIoTListPrincipalThingsRequest : AWSRequest + + +/** + + */ +@property (nonatomic, strong) NSNumber * _Nullable maxResults; + +/** + + */ +@property (nonatomic, strong) NSString * _Nullable nextToken; + +/** +

The principal.

+ */ +@property (nonatomic, strong) NSString * _Nullable principal; + +@end + +/** +

The output from the ListPrincipalThings operation.

+ */ +@interface AWSIoTListPrincipalThingsResponse : AWSModel + + +/** +

A token used to retrieve the next value.

+ */ +@property (nonatomic, strong) NSString * _Nullable nextToken; + +/** +

The things.

+ */ +@property (nonatomic, strong) NSArray * _Nullable things; + +@end + +/** +

The input for the ListThingPrincipal operation.

+ Required parameters: [thingName] + */ +@interface AWSIoTListThingPrincipalsRequest : AWSRequest + + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output from the ListThingPrincipals operation.

+ */ +@interface AWSIoTListThingPrincipalsResponse : AWSModel + + +/** +

The principals.

+ */ +@property (nonatomic, strong) NSArray * _Nullable principals; + +@end + +/** +

The input for the ListThings operation.

+ */ +@interface AWSIoTListThingsRequest : AWSRequest + + +/** +

The attribute name.

+ */ +@property (nonatomic, strong) NSString * _Nullable attributeName; + +/** +

The attribute value.

+ */ +@property (nonatomic, strong) NSString * _Nullable attributeValue; + +/** +

The maximum number of results.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable maxResults; + +/** +

The token for the next value.

+ */ +@property (nonatomic, strong) NSString * _Nullable nextToken; + +@end + +/** +

The output from the ListThings operation.

+ */ +@interface AWSIoTListThingsResponse : AWSModel + + +/** +

A token used to retrieve the next value.

+ */ +@property (nonatomic, strong) NSString * _Nullable nextToken; + +/** +

The things.

+ */ +@property (nonatomic, strong) NSArray * _Nullable things; + +@end + +/** +

The input for the ListTopicRules operation.

+ */ +@interface AWSIoTListTopicRulesRequest : AWSRequest + + +/** +

The maximum number of results to return.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable maxResults; + +/** +

A token used to retrieve the next value.

+ */ +@property (nonatomic, strong) NSString * _Nullable nextToken; + +/** +

Specifies whether the rule is disabled.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable ruleDisabled; + +/** +

The topic.

+ */ +@property (nonatomic, strong) NSString * _Nullable topic; + +@end + +/** +

The output from the ListTopicRules operation.

+ */ +@interface AWSIoTListTopicRulesResponse : AWSModel + + +/** +

A token used to retrieve the next value.

+ */ +@property (nonatomic, strong) NSString * _Nullable nextToken; + +/** +

The rules.

+ */ +@property (nonatomic, strong) NSArray * _Nullable rules; + +@end + +/** +

Describes the logging options payload.

+ Required parameters: [roleArn] + */ +@interface AWSIoTLoggingOptionsPayload : AWSModel + + +/** +

The logging level.

+ */ +@property (nonatomic, assign) AWSIoTLogLevel logLevel; + +/** +

The ARN of the IAM role that grants access.

+ */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +@end + +/** +

Describes an AWS IoT policy.

+ */ +@interface AWSIoTPolicy : AWSModel + + +/** +

The policy ARN.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyArn; + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +@end + +/** +

Describes a policy version.

+ */ +@interface AWSIoTPolicyVersion : AWSModel + + +/** +

The date and time the policy was created.

+ */ +@property (nonatomic, strong) NSDate * _Nullable createDate; + +/** +

Specifies whether the policy version is the default.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable isDefaultVersion; + +/** +

The policy version ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable versionId; + +@end + +/** +

The input for the RejectCertificateTransfer operation.

+ Required parameters: [certificateId] + */ +@interface AWSIoTRejectCertificateTransferRequest : AWSRequest + + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +@end + +/** +

The input for the ReplaceTopicRule operation.

+ Required parameters: [ruleName, topicRulePayload] + */ +@interface AWSIoTReplaceTopicRuleRequest : AWSRequest + + +/** +

The name of the rule.

+ */ +@property (nonatomic, strong) NSString * _Nullable ruleName; + +/** +

The rule payload.

+ */ +@property (nonatomic, strong) AWSIoTTopicRulePayload * _Nullable topicRulePayload; + +@end + +/** +

Describes an action to republish to another topic.

+ Required parameters: [roleArn, topic] + */ +@interface AWSIoTRepublishAction : AWSModel + + +/** +

The ARN of the IAM role that grants access.

+ */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +/** +

The name of the MQTT topic.

+ */ +@property (nonatomic, strong) NSString * _Nullable topic; + +@end + +/** +

Describes an action to write data to an Amazon S3 bucket.

+ Required parameters: [roleArn, bucketName, key] + */ +@interface AWSIoTS3Action : AWSModel + + +/** +

The S3 bucket.

+ */ +@property (nonatomic, strong) NSString * _Nullable bucketName; + +/** +

The object key.

+ */ +@property (nonatomic, strong) NSString * _Nullable key; + +/** +

The ARN of the IAM role that grants access.

+ */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +@end + +/** +

The input for the SetDefaultPolicyVersion operation.

+ Required parameters: [policyName, policyVersionId] + */ +@interface AWSIoTSetDefaultPolicyVersionRequest : AWSRequest + + +/** +

The policy name.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyName; + +/** +

The policy version ID.

+ */ +@property (nonatomic, strong) NSString * _Nullable policyVersionId; + +@end + +/** +

The input for the SetLoggingOptions operation.

+ */ +@interface AWSIoTSetLoggingOptionsRequest : AWSRequest + + +/** +

The logging options payload.

+ */ +@property (nonatomic, strong) AWSIoTLoggingOptionsPayload * _Nullable loggingOptionsPayload; + +@end + +/** +

Describes an action to publish to an Amazon SNS topic.

+ Required parameters: [targetArn, roleArn] + */ +@interface AWSIoTSnsAction : AWSModel + + +/** +

The ARN of the IAM role that grants access.

+ */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +/** +

The ARN of the SNS topic.

+ */ +@property (nonatomic, strong) NSString * _Nullable targetArn; + +@end + +/** +

Describes an action to publish data to an SQS queue.

+ Required parameters: [roleArn, queueUrl] + */ +@interface AWSIoTSqsAction : AWSModel + + +/** +

The URL of the Amazon SQS queue.

+ */ +@property (nonatomic, strong) NSString * _Nullable queueUrl; + +/** +

The ARN of the IAM role that grants access.

+ */ +@property (nonatomic, strong) NSString * _Nullable roleArn; + +/** +

Specifies whether to use Base64 encoding.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable useBase64; + +@end + +/** +

Describes a thing attribute.

+ */ +@interface AWSIoTThingAttribute : AWSModel + + +/** +

The attributes.

+ */ +@property (nonatomic, strong) NSDictionary * _Nullable attributes; + +/** +

The name of the thing.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

Describes a rule.

+ */ +@interface AWSIoTTopicRule : AWSModel + + +/** +

The actions associated with the rule.

+ */ +@property (nonatomic, strong) NSArray * _Nullable actions; + +/** +

The date and time the rule was created.

+ */ +@property (nonatomic, strong) NSDate * _Nullable createdAt; + +/** +

The description of the rule.

+ */ +@property (nonatomic, strong) NSString * _Nullable detail; + +/** +

Specifies whether the rule is disabled.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable ruleDisabled; + +/** +

The name of the rule.

+ */ +@property (nonatomic, strong) NSString * _Nullable ruleName; + +/** +

The SQL statement used to query the topic. When using a SQL query with multiple lines, be sure to escape the newline characters properly.

+ */ +@property (nonatomic, strong) NSString * _Nullable sql; + +@end + +/** +

Describes a rule.

+ */ +@interface AWSIoTTopicRuleListItem : AWSModel + + +/** +

The date and time the rule was created.

+ */ +@property (nonatomic, strong) NSDate * _Nullable createdAt; + +/** +

Specifies whether the rule is disabled.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable ruleDisabled; + +/** +

The name of the rule.

+ */ +@property (nonatomic, strong) NSString * _Nullable ruleName; + +/** +

The pattern for the topic names that apply.

+ */ +@property (nonatomic, strong) NSString * _Nullable topicPattern; + +@end + +/** +

Describes a rule.

+ Required parameters: [sql, actions] + */ +@interface AWSIoTTopicRulePayload : AWSModel + + +/** +

The actions associated with the rule.

+ */ +@property (nonatomic, strong) NSArray * _Nullable actions; + +/** +

The description of the rule.

+ */ +@property (nonatomic, strong) NSString * _Nullable detail; + +/** +

Specifies whether the rule is disabled.

+ */ +@property (nonatomic, strong) NSNumber * _Nullable ruleDisabled; + +/** +

The SQL statement used to query the topic. For more information, see AWS IoT SQL Reference in the AWS IoT Developer Guide.

+ */ +@property (nonatomic, strong) NSString * _Nullable sql; + +@end + +/** +

The input for the TransferCertificate operation.

+ Required parameters: [certificateId, targetAwsAccount] + */ +@interface AWSIoTTransferCertificateRequest : AWSRequest + + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +/** +

The AWS account.

+ */ +@property (nonatomic, strong) NSString * _Nullable targetAwsAccount; + +@end + +/** +

The output from the TransferCertificate operation.

+ */ +@interface AWSIoTTransferCertificateResponse : AWSModel + + +/** +

The ARN of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable transferredCertificateArn; + +@end + +/** +

The input for the UpdateCertificate operation.

+ Required parameters: [certificateId, newStatus] + */ +@interface AWSIoTUpdateCertificateRequest : AWSRequest + + +/** +

The ID of the certificate.

+ */ +@property (nonatomic, strong) NSString * _Nullable certificateId; + +/** +

The new status.

+ */ +@property (nonatomic, assign) AWSIoTCertificateStatus latestStatus; + +@end + +/** +

The input for the UpdateThing operation.

+ Required parameters: [thingName, attributePayload] + */ +@interface AWSIoTUpdateThingRequest : AWSRequest + + +/** +

The attribute payload, a JSON string containing up to three key-value pairs.

For example: {\"attributes\":{\"string1\":\"string2\”}}

+ */ +@property (nonatomic, strong) AWSIoTAttributePayload * _Nullable attributePayload; + +/** +

The thing name.

+ */ +@property (nonatomic, strong) NSString * _Nullable thingName; + +@end + +/** +

The output from the UpdateThing operation.

+ */ +@interface AWSIoTUpdateThingResponse : AWSModel + + +@end + +NS_ASSUME_NONNULL_END diff --git a/AWSIoT/AWSIoTModel.m b/AWSIoT/AWSIoTModel.m new file mode 100644 index 00000000000..c53aadb45c8 --- /dev/null +++ b/AWSIoT/AWSIoTModel.m @@ -0,0 +1,1246 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTModel.h" +#import + +NSString *const AWSIoTErrorDomain = @"com.amazonaws.AWSIoTErrorDomain"; + +@implementation AWSIoTAcceptCertificateTransferRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateId" : @"certificateId", + @"setAsActive" : @"setAsActive", + }; +} + +@end + +@implementation AWSIoTAction + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"dynamoDB" : @"dynamoDB", + @"firehose" : @"firehose", + @"kinesis" : @"kinesis", + @"lambda" : @"lambda", + @"republish" : @"republish", + @"s3" : @"s3", + @"sns" : @"sns", + @"sqs" : @"sqs", + }; +} + ++ (NSValueTransformer *)dynamoDBJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTDynamoDBAction class]]; +} + ++ (NSValueTransformer *)firehoseJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTFirehoseAction class]]; +} + ++ (NSValueTransformer *)kinesisJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTKinesisAction class]]; +} + ++ (NSValueTransformer *)lambdaJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTLambdaAction class]]; +} + ++ (NSValueTransformer *)republishJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTRepublishAction class]]; +} + ++ (NSValueTransformer *)s3JSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTS3Action class]]; +} + ++ (NSValueTransformer *)snsJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTSnsAction class]]; +} + ++ (NSValueTransformer *)sqsJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTSqsAction class]]; +} + +@end + +@implementation AWSIoTAttachPrincipalPolicyRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyName" : @"policyName", + @"principal" : @"principal", + }; +} + +@end + +@implementation AWSIoTAttachThingPrincipalRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"principal" : @"principal", + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTAttachThingPrincipalResponse + +@end + +@implementation AWSIoTAttributePayload + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"attributes" : @"attributes", + }; +} + +@end + +@implementation AWSIoTCancelCertificateTransferRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateId" : @"certificateId", + }; +} + +@end + +@implementation AWSIoTCertificate + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateArn" : @"certificateArn", + @"certificateId" : @"certificateId", + @"creationDate" : @"creationDate", + @"status" : @"status", + }; +} + ++ (NSValueTransformer *)creationDateJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSString *str) { + return [NSDate aws_dateFromString:str]; + } reverseBlock:^id(NSDate *date) { + return [date aws_stringValue:AWSDateISO8601DateFormat1]; + }]; +} + ++ (NSValueTransformer *)statusJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { + if ([value isEqualToString:@"ACTIVE"]) { + return @(AWSIoTCertificateStatusActive); + } + if ([value isEqualToString:@"INACTIVE"]) { + return @(AWSIoTCertificateStatusInactive); + } + if ([value isEqualToString:@"REVOKED"]) { + return @(AWSIoTCertificateStatusRevoked); + } + if ([value isEqualToString:@"PENDING_TRANSFER"]) { + return @(AWSIoTCertificateStatusPendingTransfer); + } + return @(AWSIoTCertificateStatusUnknown); + } reverseBlock:^NSString *(NSNumber *value) { + switch ([value integerValue]) { + case AWSIoTCertificateStatusActive: + return @"ACTIVE"; + case AWSIoTCertificateStatusInactive: + return @"INACTIVE"; + case AWSIoTCertificateStatusRevoked: + return @"REVOKED"; + case AWSIoTCertificateStatusPendingTransfer: + return @"PENDING_TRANSFER"; + case AWSIoTCertificateStatusUnknown: + default: + return nil; + } + }]; +} + +@end + +@implementation AWSIoTCertificateDescription + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateArn" : @"certificateArn", + @"certificateId" : @"certificateId", + @"certificatePem" : @"certificatePem", + @"creationDate" : @"creationDate", + @"lastModifiedDate" : @"lastModifiedDate", + @"ownedBy" : @"ownedBy", + @"status" : @"status", + }; +} + ++ (NSValueTransformer *)creationDateJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSString *str) { + return [NSDate aws_dateFromString:str]; + } reverseBlock:^id(NSDate *date) { + return [date aws_stringValue:AWSDateISO8601DateFormat1]; + }]; +} + ++ (NSValueTransformer *)lastModifiedDateJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSString *str) { + return [NSDate aws_dateFromString:str]; + } reverseBlock:^id(NSDate *date) { + return [date aws_stringValue:AWSDateISO8601DateFormat1]; + }]; +} + ++ (NSValueTransformer *)statusJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { + if ([value isEqualToString:@"ACTIVE"]) { + return @(AWSIoTCertificateStatusActive); + } + if ([value isEqualToString:@"INACTIVE"]) { + return @(AWSIoTCertificateStatusInactive); + } + if ([value isEqualToString:@"REVOKED"]) { + return @(AWSIoTCertificateStatusRevoked); + } + if ([value isEqualToString:@"PENDING_TRANSFER"]) { + return @(AWSIoTCertificateStatusPendingTransfer); + } + return @(AWSIoTCertificateStatusUnknown); + } reverseBlock:^NSString *(NSNumber *value) { + switch ([value integerValue]) { + case AWSIoTCertificateStatusActive: + return @"ACTIVE"; + case AWSIoTCertificateStatusInactive: + return @"INACTIVE"; + case AWSIoTCertificateStatusRevoked: + return @"REVOKED"; + case AWSIoTCertificateStatusPendingTransfer: + return @"PENDING_TRANSFER"; + case AWSIoTCertificateStatusUnknown: + default: + return nil; + } + }]; +} + +@end + +@implementation AWSIoTCreateCertificateFromCsrRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateSigningRequest" : @"certificateSigningRequest", + @"setAsActive" : @"setAsActive", + }; +} + +@end + +@implementation AWSIoTCreateCertificateFromCsrResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateArn" : @"certificateArn", + @"certificateId" : @"certificateId", + @"certificatePem" : @"certificatePem", + }; +} + +@end + +@implementation AWSIoTCreateKeysAndCertificateRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"setAsActive" : @"setAsActive", + }; +} + +@end + +@implementation AWSIoTCreateKeysAndCertificateResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateArn" : @"certificateArn", + @"certificateId" : @"certificateId", + @"certificatePem" : @"certificatePem", + @"keyPair" : @"keyPair", + }; +} + ++ (NSValueTransformer *)keyPairJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTKeyPair class]]; +} + +@end + +@implementation AWSIoTCreatePolicyRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyDocument" : @"policyDocument", + @"policyName" : @"policyName", + }; +} + +@end + +@implementation AWSIoTCreatePolicyResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyArn" : @"policyArn", + @"policyDocument" : @"policyDocument", + @"policyName" : @"policyName", + @"policyVersionId" : @"policyVersionId", + }; +} + +@end + +@implementation AWSIoTCreatePolicyVersionRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyDocument" : @"policyDocument", + @"policyName" : @"policyName", + @"setAsDefault" : @"setAsDefault", + }; +} + +@end + +@implementation AWSIoTCreatePolicyVersionResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"isDefaultVersion" : @"isDefaultVersion", + @"policyArn" : @"policyArn", + @"policyDocument" : @"policyDocument", + @"policyVersionId" : @"policyVersionId", + }; +} + +@end + +@implementation AWSIoTCreateThingRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"attributePayload" : @"attributePayload", + @"thingName" : @"thingName", + }; +} + ++ (NSValueTransformer *)attributePayloadJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTAttributePayload class]]; +} + +@end + +@implementation AWSIoTCreateThingResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"thingArn" : @"thingArn", + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTCreateTopicRuleRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"ruleName" : @"ruleName", + @"topicRulePayload" : @"topicRulePayload", + }; +} + ++ (NSValueTransformer *)topicRulePayloadJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTTopicRulePayload class]]; +} + +@end + +@implementation AWSIoTDeleteCertificateRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateId" : @"certificateId", + }; +} + +@end + +@implementation AWSIoTDeletePolicyRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyName" : @"policyName", + }; +} + +@end + +@implementation AWSIoTDeletePolicyVersionRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyName" : @"policyName", + @"policyVersionId" : @"policyVersionId", + }; +} + +@end + +@implementation AWSIoTDeleteThingRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTDeleteThingResponse + +@end + +@implementation AWSIoTDeleteTopicRuleRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"ruleName" : @"ruleName", + }; +} + +@end + +@implementation AWSIoTDescribeCertificateRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateId" : @"certificateId", + }; +} + +@end + +@implementation AWSIoTDescribeCertificateResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateDescription" : @"certificateDescription", + }; +} + ++ (NSValueTransformer *)certificateDescriptionJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTCertificateDescription class]]; +} + +@end + +@implementation AWSIoTDescribeEndpointRequest + +@end + +@implementation AWSIoTDescribeEndpointResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"endpointAddress" : @"endpointAddress", + }; +} + +@end + +@implementation AWSIoTDescribeThingRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTDescribeThingResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"attributes" : @"attributes", + @"defaultClientId" : @"defaultClientId", + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTDetachPrincipalPolicyRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyName" : @"policyName", + @"principal" : @"principal", + }; +} + +@end + +@implementation AWSIoTDetachThingPrincipalRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"principal" : @"principal", + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTDetachThingPrincipalResponse + +@end + +@implementation AWSIoTDynamoDBAction + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"hashKeyField" : @"hashKeyField", + @"hashKeyValue" : @"hashKeyValue", + @"payloadField" : @"payloadField", + @"rangeKeyField" : @"rangeKeyField", + @"rangeKeyValue" : @"rangeKeyValue", + @"roleArn" : @"roleArn", + @"tableName" : @"tableName", + }; +} + +@end + +@implementation AWSIoTFirehoseAction + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"deliveryStreamName" : @"deliveryStreamName", + @"roleArn" : @"roleArn", + }; +} + +@end + +@implementation AWSIoTGetLoggingOptionsRequest + +@end + +@implementation AWSIoTGetLoggingOptionsResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"logLevel" : @"logLevel", + @"roleArn" : @"roleArn", + }; +} + ++ (NSValueTransformer *)logLevelJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { + if ([value isEqualToString:@"DEBUG"]) { + return @(AWSIoTLogLevelDebug); + } + if ([value isEqualToString:@"INFO"]) { + return @(AWSIoTLogLevelInfo); + } + if ([value isEqualToString:@"ERROR"]) { + return @(AWSIoTLogLevelError); + } + if ([value isEqualToString:@"WARN"]) { + return @(AWSIoTLogLevelWarn); + } + if ([value isEqualToString:@"DISABLED"]) { + return @(AWSIoTLogLevelDisabled); + } + return @(AWSIoTLogLevelUnknown); + } reverseBlock:^NSString *(NSNumber *value) { + switch ([value integerValue]) { + case AWSIoTLogLevelDebug: + return @"DEBUG"; + case AWSIoTLogLevelInfo: + return @"INFO"; + case AWSIoTLogLevelError: + return @"ERROR"; + case AWSIoTLogLevelWarn: + return @"WARN"; + case AWSIoTLogLevelDisabled: + return @"DISABLED"; + case AWSIoTLogLevelUnknown: + default: + return nil; + } + }]; +} + +@end + +@implementation AWSIoTGetPolicyRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyName" : @"policyName", + }; +} + +@end + +@implementation AWSIoTGetPolicyResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"defaultVersionId" : @"defaultVersionId", + @"policyArn" : @"policyArn", + @"policyDocument" : @"policyDocument", + @"policyName" : @"policyName", + }; +} + +@end + +@implementation AWSIoTGetPolicyVersionRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyName" : @"policyName", + @"policyVersionId" : @"policyVersionId", + }; +} + +@end + +@implementation AWSIoTGetPolicyVersionResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"isDefaultVersion" : @"isDefaultVersion", + @"policyArn" : @"policyArn", + @"policyDocument" : @"policyDocument", + @"policyName" : @"policyName", + @"policyVersionId" : @"policyVersionId", + }; +} + +@end + +@implementation AWSIoTGetTopicRuleRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"ruleName" : @"ruleName", + }; +} + +@end + +@implementation AWSIoTGetTopicRuleResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"rule" : @"rule", + }; +} + ++ (NSValueTransformer *)ruleJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTTopicRule class]]; +} + +@end + +@implementation AWSIoTKeyPair + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"privateKey" : @"PrivateKey", + @"publicKey" : @"PublicKey", + }; +} + +@end + +@implementation AWSIoTKinesisAction + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"partitionKey" : @"partitionKey", + @"roleArn" : @"roleArn", + @"streamName" : @"streamName", + }; +} + +@end + +@implementation AWSIoTLambdaAction + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"functionArn" : @"functionArn", + }; +} + +@end + +@implementation AWSIoTListCertificatesRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"ascendingOrder" : @"ascendingOrder", + @"marker" : @"marker", + @"pageSize" : @"pageSize", + }; +} + +@end + +@implementation AWSIoTListCertificatesResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificates" : @"certificates", + @"nextMarker" : @"nextMarker", + }; +} + ++ (NSValueTransformer *)certificatesJSONTransformer { + return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSIoTCertificate class]]; +} + +@end + +@implementation AWSIoTListPoliciesRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"ascendingOrder" : @"ascendingOrder", + @"marker" : @"marker", + @"pageSize" : @"pageSize", + }; +} + +@end + +@implementation AWSIoTListPoliciesResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"nextMarker" : @"nextMarker", + @"policies" : @"policies", + }; +} + ++ (NSValueTransformer *)policiesJSONTransformer { + return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSIoTPolicy class]]; +} + +@end + +@implementation AWSIoTListPolicyVersionsRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyName" : @"policyName", + }; +} + +@end + +@implementation AWSIoTListPolicyVersionsResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyVersions" : @"policyVersions", + }; +} + ++ (NSValueTransformer *)policyVersionsJSONTransformer { + return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSIoTPolicyVersion class]]; +} + +@end + +@implementation AWSIoTListPrincipalPoliciesRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"ascendingOrder" : @"ascendingOrder", + @"marker" : @"marker", + @"pageSize" : @"pageSize", + @"principal" : @"principal", + }; +} + +@end + +@implementation AWSIoTListPrincipalPoliciesResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"nextMarker" : @"nextMarker", + @"policies" : @"policies", + }; +} + ++ (NSValueTransformer *)policiesJSONTransformer { + return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSIoTPolicy class]]; +} + +@end + +@implementation AWSIoTListPrincipalThingsRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"maxResults" : @"maxResults", + @"nextToken" : @"nextToken", + @"principal" : @"principal", + }; +} + +@end + +@implementation AWSIoTListPrincipalThingsResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"nextToken" : @"nextToken", + @"things" : @"things", + }; +} + +@end + +@implementation AWSIoTListThingPrincipalsRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTListThingPrincipalsResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"principals" : @"principals", + }; +} + +@end + +@implementation AWSIoTListThingsRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"attributeName" : @"attributeName", + @"attributeValue" : @"attributeValue", + @"maxResults" : @"maxResults", + @"nextToken" : @"nextToken", + }; +} + +@end + +@implementation AWSIoTListThingsResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"nextToken" : @"nextToken", + @"things" : @"things", + }; +} + ++ (NSValueTransformer *)thingsJSONTransformer { + return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSIoTThingAttribute class]]; +} + +@end + +@implementation AWSIoTListTopicRulesRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"maxResults" : @"maxResults", + @"nextToken" : @"nextToken", + @"ruleDisabled" : @"ruleDisabled", + @"topic" : @"topic", + }; +} + +@end + +@implementation AWSIoTListTopicRulesResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"nextToken" : @"nextToken", + @"rules" : @"rules", + }; +} + ++ (NSValueTransformer *)rulesJSONTransformer { + return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSIoTTopicRuleListItem class]]; +} + +@end + +@implementation AWSIoTLoggingOptionsPayload + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"logLevel" : @"logLevel", + @"roleArn" : @"roleArn", + }; +} + ++ (NSValueTransformer *)logLevelJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { + if ([value isEqualToString:@"DEBUG"]) { + return @(AWSIoTLogLevelDebug); + } + if ([value isEqualToString:@"INFO"]) { + return @(AWSIoTLogLevelInfo); + } + if ([value isEqualToString:@"ERROR"]) { + return @(AWSIoTLogLevelError); + } + if ([value isEqualToString:@"WARN"]) { + return @(AWSIoTLogLevelWarn); + } + if ([value isEqualToString:@"DISABLED"]) { + return @(AWSIoTLogLevelDisabled); + } + return @(AWSIoTLogLevelUnknown); + } reverseBlock:^NSString *(NSNumber *value) { + switch ([value integerValue]) { + case AWSIoTLogLevelDebug: + return @"DEBUG"; + case AWSIoTLogLevelInfo: + return @"INFO"; + case AWSIoTLogLevelError: + return @"ERROR"; + case AWSIoTLogLevelWarn: + return @"WARN"; + case AWSIoTLogLevelDisabled: + return @"DISABLED"; + case AWSIoTLogLevelUnknown: + default: + return nil; + } + }]; +} + +@end + +@implementation AWSIoTPolicy + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyArn" : @"policyArn", + @"policyName" : @"policyName", + }; +} + +@end + +@implementation AWSIoTPolicyVersion + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"createDate" : @"createDate", + @"isDefaultVersion" : @"isDefaultVersion", + @"versionId" : @"versionId", + }; +} + ++ (NSValueTransformer *)createDateJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSString *str) { + return [NSDate aws_dateFromString:str]; + } reverseBlock:^id(NSDate *date) { + return [date aws_stringValue:AWSDateISO8601DateFormat1]; + }]; +} + +@end + +@implementation AWSIoTRejectCertificateTransferRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateId" : @"certificateId", + }; +} + +@end + +@implementation AWSIoTReplaceTopicRuleRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"ruleName" : @"ruleName", + @"topicRulePayload" : @"topicRulePayload", + }; +} + ++ (NSValueTransformer *)topicRulePayloadJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTTopicRulePayload class]]; +} + +@end + +@implementation AWSIoTRepublishAction + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"roleArn" : @"roleArn", + @"topic" : @"topic", + }; +} + +@end + +@implementation AWSIoTS3Action + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"bucketName" : @"bucketName", + @"key" : @"key", + @"roleArn" : @"roleArn", + }; +} + +@end + +@implementation AWSIoTSetDefaultPolicyVersionRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"policyName" : @"policyName", + @"policyVersionId" : @"policyVersionId", + }; +} + +@end + +@implementation AWSIoTSetLoggingOptionsRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"loggingOptionsPayload" : @"loggingOptionsPayload", + }; +} + ++ (NSValueTransformer *)loggingOptionsPayloadJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTLoggingOptionsPayload class]]; +} + +@end + +@implementation AWSIoTSnsAction + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"roleArn" : @"roleArn", + @"targetArn" : @"targetArn", + }; +} + +@end + +@implementation AWSIoTSqsAction + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"queueUrl" : @"queueUrl", + @"roleArn" : @"roleArn", + @"useBase64" : @"useBase64", + }; +} + +@end + +@implementation AWSIoTThingAttribute + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"attributes" : @"attributes", + @"thingName" : @"thingName", + }; +} + +@end + +@implementation AWSIoTTopicRule + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"actions" : @"actions", + @"createdAt" : @"createdAt", + @"detail" : @"description", + @"ruleDisabled" : @"ruleDisabled", + @"ruleName" : @"ruleName", + @"sql" : @"sql", + }; +} + ++ (NSValueTransformer *)actionsJSONTransformer { + return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSIoTAction class]]; +} + ++ (NSValueTransformer *)createdAtJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSString *str) { + return [NSDate aws_dateFromString:str]; + } reverseBlock:^id(NSDate *date) { + return [date aws_stringValue:AWSDateISO8601DateFormat1]; + }]; +} + +@end + +@implementation AWSIoTTopicRuleListItem + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"createdAt" : @"createdAt", + @"ruleDisabled" : @"ruleDisabled", + @"ruleName" : @"ruleName", + @"topicPattern" : @"topicPattern", + }; +} + ++ (NSValueTransformer *)createdAtJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^id(NSString *str) { + return [NSDate aws_dateFromString:str]; + } reverseBlock:^id(NSDate *date) { + return [date aws_stringValue:AWSDateISO8601DateFormat1]; + }]; +} + +@end + +@implementation AWSIoTTopicRulePayload + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"actions" : @"actions", + @"detail" : @"description", + @"ruleDisabled" : @"ruleDisabled", + @"sql" : @"sql", + }; +} + ++ (NSValueTransformer *)actionsJSONTransformer { + return [NSValueTransformer awsmtl_JSONArrayTransformerWithModelClass:[AWSIoTAction class]]; +} + +@end + +@implementation AWSIoTTransferCertificateRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateId" : @"certificateId", + @"targetAwsAccount" : @"targetAwsAccount", + }; +} + +@end + +@implementation AWSIoTTransferCertificateResponse + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"transferredCertificateArn" : @"transferredCertificateArn", + }; +} + +@end + +@implementation AWSIoTUpdateCertificateRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"certificateId" : @"certificateId", + @"latestStatus" : @"newStatus", + }; +} + ++ (NSValueTransformer *)latestStatusJSONTransformer { + return [AWSMTLValueTransformer reversibleTransformerWithForwardBlock:^NSNumber *(NSString *value) { + if ([value isEqualToString:@"ACTIVE"]) { + return @(AWSIoTCertificateStatusActive); + } + if ([value isEqualToString:@"INACTIVE"]) { + return @(AWSIoTCertificateStatusInactive); + } + if ([value isEqualToString:@"REVOKED"]) { + return @(AWSIoTCertificateStatusRevoked); + } + if ([value isEqualToString:@"PENDING_TRANSFER"]) { + return @(AWSIoTCertificateStatusPendingTransfer); + } + return @(AWSIoTCertificateStatusUnknown); + } reverseBlock:^NSString *(NSNumber *value) { + switch ([value integerValue]) { + case AWSIoTCertificateStatusActive: + return @"ACTIVE"; + case AWSIoTCertificateStatusInactive: + return @"INACTIVE"; + case AWSIoTCertificateStatusRevoked: + return @"REVOKED"; + case AWSIoTCertificateStatusPendingTransfer: + return @"PENDING_TRANSFER"; + case AWSIoTCertificateStatusUnknown: + default: + return nil; + } + }]; +} + +@end + +@implementation AWSIoTUpdateThingRequest + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{ + @"attributePayload" : @"attributePayload", + @"thingName" : @"thingName", + }; +} + ++ (NSValueTransformer *)attributePayloadJSONTransformer { + return [NSValueTransformer awsmtl_JSONDictionaryTransformerWithModelClass:[AWSIoTAttributePayload class]]; +} + +@end + +@implementation AWSIoTUpdateThingResponse + +@end diff --git a/AWSIoT/AWSIoTResources.h b/AWSIoT/AWSIoTResources.h new file mode 100644 index 00000000000..3c7458b2051 --- /dev/null +++ b/AWSIoT/AWSIoTResources.h @@ -0,0 +1,24 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import + +@interface AWSIoTResources : NSObject + ++ (instancetype)sharedInstance; + +- (NSDictionary *)JSONObject; + +@end diff --git a/AWSIoT/AWSIoTResources.m b/AWSIoT/AWSIoTResources.m new file mode 100644 index 00000000000..a228e2fc7d7 --- /dev/null +++ b/AWSIoT/AWSIoTResources.m @@ -0,0 +1,3938 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTResources.h" +#import + +@interface AWSIoTResources () + +@property (nonatomic, strong) NSDictionary *definitionDictionary; + +@end + +@implementation AWSIoTResources + ++ (instancetype)sharedInstance { + static AWSIoTResources *_sharedResources = nil; + static dispatch_once_t once_token; + + dispatch_once(&once_token, ^{ + _sharedResources = [AWSIoTResources new]; + }); + + return _sharedResources; +} +- (NSDictionary *)JSONObject { + return self.definitionDictionary; +} + +- (instancetype)init { + if (self = [super init]) { + //init method + NSError *error = nil; + _definitionDictionary = [NSJSONSerialization JSONObjectWithData:[[self definitionString] dataUsingEncoding:NSUTF8StringEncoding] + options:kNilOptions + error:&error]; + if (_definitionDictionary == nil) { + if (error) { + AWSLogError(@"Failed to parse JSON service definition: %@",error); + } + } + } + return self; +} + +- (NSString *)definitionString { + return @" \ +{ \ + \"version\":\"2.0\", \ + \"metadata\":{ \ + \"apiVersion\":\"2015-05-28\", \ + \"endpointPrefix\":\"iot\", \ + \"serviceFullName\":\"AWS IoT\", \ + \"signatureVersion\":\"v4\", \ + \"signingName\":\"execute-api\", \ + \"protocol\":\"rest-json\" \ + }, \ + \"documentation\":\"AWS IoT (Beta)

AWS IoT is in beta and is subject to change

AWS IoT provides secure, bi-directional communication between Internet-connected things (such as sensors, actuators, embedded devices, or smart appliances) and the AWS cloud. You can discover your custom IoT-Data endpoint to communicate with, configure rules for data processing and integration with other services, organize resources associated with each thing (Thing Registry), configure logging, and create and manage policies and credentials to authenticate things.

For more information about how AWS IoT works, see the Developer Guide.

\", \ + \"operations\":{ \ + \"AcceptCertificateTransfer\":{ \ + \"name\":\"AcceptCertificateTransfer\", \ + \"http\":{ \ + \"method\":\"PATCH\", \ + \"requestUri\":\"/accept-certificate-transfer/{certificateId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"AcceptCertificateTransferRequest\", \ + \"documentation\":\"

The input for the AcceptCertificateTransfer operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"TransferAlreadyCompletedException\", \ + \"error\":{\"httpStatusCode\":410}, \ + \"exception\":true, \ + \"documentation\":\"

You can't revert the certificate transfer because it has already completed.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Accepts a pending certificate transfer. The default state of the certificate is INACTIVE.

To check for pending certificate transfers, call ListCertificates to enumerate your certificates.

\" \ + }, \ + \"AttachPrincipalPolicy\":{ \ + \"name\":\"AttachPrincipalPolicy\", \ + \"http\":{ \ + \"method\":\"PUT\", \ + \"requestUri\":\"/principal-policies/{policyName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"AttachPrincipalPolicyRequest\", \ + \"documentation\":\"

The input for the AttachPrincipalPolicy operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"LimitExceededException\", \ + \"error\":{\"httpStatusCode\":410}, \ + \"exception\":true, \ + \"documentation\":\"

The number of attached entities exceeds the limit.

\" \ + } \ + ], \ + \"documentation\":\"

Attaches the specified policy to the specified principal (certificate or other credential).

\" \ + }, \ + \"AttachThingPrincipal\":{ \ + \"name\":\"AttachThingPrincipal\", \ + \"http\":{ \ + \"method\":\"PUT\", \ + \"requestUri\":\"/things/{thingName}/principals\" \ + }, \ + \"input\":{ \ + \"shape\":\"AttachThingPrincipalRequest\", \ + \"documentation\":\"

The input for the AttachThingPrincipal operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"AttachThingPrincipalResponse\", \ + \"documentation\":\"

The output from the AttachThingPrincipal operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Attaches the specified principal to the specified thing.

\" \ + }, \ + \"CancelCertificateTransfer\":{ \ + \"name\":\"CancelCertificateTransfer\", \ + \"http\":{ \ + \"method\":\"PATCH\", \ + \"requestUri\":\"/cancel-certificate-transfer/{certificateId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"CancelCertificateTransferRequest\", \ + \"documentation\":\"

The input for the CancelCertificateTransfer operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"TransferAlreadyCompletedException\", \ + \"error\":{\"httpStatusCode\":410}, \ + \"exception\":true, \ + \"documentation\":\"

You can't revert the certificate transfer because it has already completed.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Cancels a pending transfer for the specified certificate.

Note Only the transfer source account can use this operation to cancel a transfer (transfer destinations can use RejectCertificateTransfer instead). After transfer, AWS IoT returns the certificate to the source account in the INACTIVE state. Once the destination account has accepted the transfer, the transfer may no longer be cancelled.

After a certificate transfer is cancelled, the status of the certificate changes from PENDING_TRANSFER to INACTIVE.

\" \ + }, \ + \"CreateCertificateFromCsr\":{ \ + \"name\":\"CreateCertificateFromCsr\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/certificates\" \ + }, \ + \"input\":{ \ + \"shape\":\"CreateCertificateFromCsrRequest\", \ + \"documentation\":\"

The input for the CreateCertificateFromCsr operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"CreateCertificateFromCsrResponse\", \ + \"documentation\":\"

The output from the CreateCertificateFromCsr operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Creates an X.509 certificate using the specified certificate signing request.

Note Reusing the same certificate signing request (CSR) results in a distinct certificate.

\" \ + }, \ + \"CreateKeysAndCertificate\":{ \ + \"name\":\"CreateKeysAndCertificate\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/keys-and-certificate\" \ + }, \ + \"input\":{ \ + \"shape\":\"CreateKeysAndCertificateRequest\", \ + \"documentation\":\"

The input for the CreateKeysAndCertificate operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"CreateKeysAndCertificateResponse\", \ + \"documentation\":\"

The output of the CreateKeysAndCertificate operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Creates a 2048 bit RSA key pair and issues an X.509 certificate using the issued public key.

Note This is the only time AWS IoT issues the private key for this certificate. It is important to keep track of the private key.

\" \ + }, \ + \"CreatePolicy\":{ \ + \"name\":\"CreatePolicy\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/policies/{policyName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"CreatePolicyRequest\", \ + \"documentation\":\"

The input for the CreatePolicy operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"CreatePolicyResponse\", \ + \"documentation\":\"

The output from the CreatePolicy operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceAlreadyExistsException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

The resource already exists.

\" \ + }, \ + { \ + \"shape\":\"MalformedPolicyException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The policy documentation is not valid.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Creates an AWS IoT policy.

The created policy is the default version for the policy. This operation creates a policy version with a version identifier of 1 and sets 1 as the policy's default version.

\" \ + }, \ + \"CreatePolicyVersion\":{ \ + \"name\":\"CreatePolicyVersion\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/policies/{policyName}/version\" \ + }, \ + \"input\":{ \ + \"shape\":\"CreatePolicyVersionRequest\", \ + \"documentation\":\"

The input for the CreatePolicyVersion operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"CreatePolicyVersionResponse\", \ + \"documentation\":\"

The output of the CreatePolicyVersion operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"MalformedPolicyException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The policy documentation is not valid.

\" \ + }, \ + { \ + \"shape\":\"VersionsLimitExceededException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

The number of policy versions exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Creates a new version of the specified AWS IoT policy.

\" \ + }, \ + \"CreateThing\":{ \ + \"name\":\"CreateThing\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/things/{thingName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"CreateThingRequest\", \ + \"documentation\":\"

The input for the CreateThing operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"CreateThingResponse\", \ + \"documentation\":\"

The output of the CreateThing operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"ResourceAlreadyExistsException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

The resource already exists.

\" \ + } \ + ], \ + \"documentation\":\"

Creates a thing in the thing registry.

\" \ + }, \ + \"CreateTopicRule\":{ \ + \"name\":\"CreateTopicRule\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/rules/{ruleName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"CreateTopicRuleRequest\", \ + \"documentation\":\"

The input for the CreateTopicRule operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"SqlParseException\", \ + \"error\":{\"httpStatusCode\":406}, \ + \"exception\":true, \ + \"documentation\":\"

The Rule-SQL expression can't be parsed correctly.

\" \ + }, \ + { \ + \"shape\":\"InternalException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ResourceAlreadyExistsException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

The resource already exists.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + } \ + ], \ + \"documentation\":\"

Creates a rule.

\" \ + }, \ + \"DeleteCertificate\":{ \ + \"name\":\"DeleteCertificate\", \ + \"http\":{ \ + \"method\":\"DELETE\", \ + \"requestUri\":\"/certificates/{certificateId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"DeleteCertificateRequest\", \ + \"documentation\":\"

The input for the DeleteCertificate operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"DeleteConflictException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

You can't delete the resource because it is attached to one or more resources.

\" \ + }, \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"CertificateStateException\", \ + \"error\":{\"httpStatusCode\":406}, \ + \"exception\":true, \ + \"documentation\":\"

The certificate operation is not allowed.

\" \ + } \ + ], \ + \"documentation\":\"

Deletes the specified certificate.

A certificate cannot be deleted if it has a policy attached to it. To delete a certificate, first detach all policies using the DetachPrincipalPolicy operation.

In addition, a certificate cannot be deleted if it is in ACTIVE status. To delete a certificate, first change the status to INACTIVE using the UpdateCertificate operation.

\" \ + }, \ + \"DeletePolicy\":{ \ + \"name\":\"DeletePolicy\", \ + \"http\":{ \ + \"method\":\"DELETE\", \ + \"requestUri\":\"/policies/{policyName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"DeletePolicyRequest\", \ + \"documentation\":\"

The input for the DeletePolicy operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"DeleteConflictException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

You can't delete the resource because it is attached to one or more resources.

\" \ + }, \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Deletes the specified policy.

A policy cannot be deleted if:

- it has non-default versions

- it is attached to any certificate

To delete a policy:

- First delete all the non-default versions of the policy using the DeletePolicyVersion API.

- Detach it from any certificate using the DetachPrincipalPolicy API.

When a policy is deleted, its default version is deleted with it.

\" \ + }, \ + \"DeletePolicyVersion\":{ \ + \"name\":\"DeletePolicyVersion\", \ + \"http\":{ \ + \"method\":\"DELETE\", \ + \"requestUri\":\"/policies/{policyName}/version/{policyVersionId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"DeletePolicyVersionRequest\", \ + \"documentation\":\"

The input for the DeletePolicyVersion operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"DeleteConflictException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

You can't delete the resource because it is attached to one or more resources.

\" \ + }, \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Deletes the specified version of the specified policy. The default version of the policy cannot be deleted.

To delete the default version use the DeletePolicy API or mark the policy as non-default and then delete it.

\" \ + }, \ + \"DeleteThing\":{ \ + \"name\":\"DeleteThing\", \ + \"http\":{ \ + \"method\":\"DELETE\", \ + \"requestUri\":\"/things/{thingName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"DeleteThingRequest\", \ + \"documentation\":\"

The input for the DeleteThing operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"DeleteThingResponse\", \ + \"documentation\":\"

The output of the DeleteThing operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Deletes the specified thing from the Thing Registry.

\" \ + }, \ + \"DeleteTopicRule\":{ \ + \"name\":\"DeleteTopicRule\", \ + \"http\":{ \ + \"method\":\"DELETE\", \ + \"requestUri\":\"/rules/{ruleName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"DeleteTopicRuleRequest\", \ + \"documentation\":\"

The input for the DeleteTopicRule operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InternalException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + } \ + ], \ + \"documentation\":\"

Deletes the specified rule.

\" \ + }, \ + \"DescribeCertificate\":{ \ + \"name\":\"DescribeCertificate\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/certificates/{certificateId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"DescribeCertificateRequest\", \ + \"documentation\":\"

The input for the DescribeCertificate operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"DescribeCertificateResponse\", \ + \"documentation\":\"

The output of the DescribeCertificate operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + } \ + ], \ + \"documentation\":\"

Gets information about the specified certificate.

\" \ + }, \ + \"DescribeEndpoint\":{ \ + \"name\":\"DescribeEndpoint\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/endpoint\" \ + }, \ + \"input\":{ \ + \"shape\":\"DescribeEndpointRequest\", \ + \"documentation\":\"

The input for the DescribeEndpoint operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"DescribeEndpointResponse\", \ + \"documentation\":\"

The output from the DescribeEndpoint operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + } \ + ], \ + \"documentation\":\"

Returns a unique URL specific to the AWS account making the call. The URL points to the AWS IoT data plane endpoint. The customer-specific endpoint should be provided to all data plane operations.

\" \ + }, \ + \"DescribeThing\":{ \ + \"name\":\"DescribeThing\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/things/{thingName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"DescribeThingRequest\", \ + \"documentation\":\"

The input for the DescribeThing operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"DescribeThingResponse\", \ + \"documentation\":\"

The output from the DescribeThing operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Gets information about the specified thing.

\" \ + }, \ + \"DetachPrincipalPolicy\":{ \ + \"name\":\"DetachPrincipalPolicy\", \ + \"http\":{ \ + \"method\":\"DELETE\", \ + \"requestUri\":\"/principal-policies/{policyName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"DetachPrincipalPolicyRequest\", \ + \"documentation\":\"

The input for the DetachPrincipalPolicy operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Removes the specified policy from the specified certificate.

\" \ + }, \ + \"DetachThingPrincipal\":{ \ + \"name\":\"DetachThingPrincipal\", \ + \"http\":{ \ + \"method\":\"DELETE\", \ + \"requestUri\":\"/things/{thingName}/principals\" \ + }, \ + \"input\":{ \ + \"shape\":\"DetachThingPrincipalRequest\", \ + \"documentation\":\"

The input for the DetachThingPrincipal operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"DetachThingPrincipalResponse\", \ + \"documentation\":\"

The output from the DetachThingPrincipal operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Detaches the specified principal from the specified thing.

\" \ + }, \ + \"GetLoggingOptions\":{ \ + \"name\":\"GetLoggingOptions\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/loggingOptions\" \ + }, \ + \"input\":{ \ + \"shape\":\"GetLoggingOptionsRequest\", \ + \"documentation\":\"

The input for the GetLoggingOptions operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"GetLoggingOptionsResponse\", \ + \"documentation\":\"

The output from the GetLoggingOptions operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InternalException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + } \ + ], \ + \"documentation\":\"

Gets the logging options.

\" \ + }, \ + \"GetPolicy\":{ \ + \"name\":\"GetPolicy\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/policies/{policyName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"GetPolicyRequest\", \ + \"documentation\":\"

The input for the GetPolicy operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"GetPolicyResponse\", \ + \"documentation\":\"

The output from the GetPolicy operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Gets information about the specified policy with the policy document of the default version.

\" \ + }, \ + \"GetPolicyVersion\":{ \ + \"name\":\"GetPolicyVersion\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/policies/{policyName}/version/{policyVersionId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"GetPolicyVersionRequest\", \ + \"documentation\":\"

The input for the GetPolicyVersion operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"GetPolicyVersionResponse\", \ + \"documentation\":\"

The output from the GetPolicyVersion operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Gets information about the specified policy version.

\" \ + }, \ + \"GetTopicRule\":{ \ + \"name\":\"GetTopicRule\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/rules/{ruleName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"GetTopicRuleRequest\", \ + \"documentation\":\"

The input for the GetTopicRule operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"GetTopicRuleResponse\", \ + \"documentation\":\"

The output from the GetTopicRule operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InternalException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + } \ + ], \ + \"documentation\":\"

Gets information about the specified rule.

\" \ + }, \ + \"ListCertificates\":{ \ + \"name\":\"ListCertificates\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/certificates\" \ + }, \ + \"input\":{ \ + \"shape\":\"ListCertificatesRequest\", \ + \"documentation\":\"

The input for the ListCertificates operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"ListCertificatesResponse\", \ + \"documentation\":\"

The output of the ListCertificates operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Lists your certificates.

The results are paginated with a default page size of 25. You can retrieve additional results using the returned marker.

\" \ + }, \ + \"ListPolicies\":{ \ + \"name\":\"ListPolicies\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/policies\" \ + }, \ + \"input\":{ \ + \"shape\":\"ListPoliciesRequest\", \ + \"documentation\":\"

The input for the ListPolicies operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"ListPoliciesResponse\", \ + \"documentation\":\"

The output from the ListPolicies operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Lists your policies.

\" \ + }, \ + \"ListPolicyVersions\":{ \ + \"name\":\"ListPolicyVersions\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/policies/{policyName}/version\" \ + }, \ + \"input\":{ \ + \"shape\":\"ListPolicyVersionsRequest\", \ + \"documentation\":\"

The input for the ListPolicyVersions operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"ListPolicyVersionsResponse\", \ + \"documentation\":\"

The output from the ListPolicyVersions operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Lists the versions of the specified policy, and identifies the default version.

\" \ + }, \ + \"ListPrincipalPolicies\":{ \ + \"name\":\"ListPrincipalPolicies\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/principal-policies\" \ + }, \ + \"input\":{ \ + \"shape\":\"ListPrincipalPoliciesRequest\", \ + \"documentation\":\"

The input for the ListPrincipalPolicies operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"ListPrincipalPoliciesResponse\", \ + \"documentation\":\"

The output from the ListPrincipalPolicies operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Lists the policies attached to the specified principal. If you use an Amazon Cognito identity, the ID needs to be in Amazon Cognito Identity format.

\" \ + }, \ + \"ListPrincipalThings\":{ \ + \"name\":\"ListPrincipalThings\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/principals/things\" \ + }, \ + \"input\":{ \ + \"shape\":\"ListPrincipalThingsRequest\", \ + \"documentation\":\"

The input for the ListPrincipalThings operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"ListPrincipalThingsResponse\", \ + \"documentation\":\"

The output from the ListPrincipalThings operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Lists the things associated with the specified principal.

\" \ + }, \ + \"ListThingPrincipals\":{ \ + \"name\":\"ListThingPrincipals\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/things/{thingName}/principals\" \ + }, \ + \"input\":{ \ + \"shape\":\"ListThingPrincipalsRequest\", \ + \"documentation\":\"

The input for the ListThingPrincipal operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"ListThingPrincipalsResponse\", \ + \"documentation\":\"

The output from the ListThingPrincipals operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Lists the principals associated with the specified thing.

\" \ + }, \ + \"ListThings\":{ \ + \"name\":\"ListThings\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/things\" \ + }, \ + \"input\":{ \ + \"shape\":\"ListThingsRequest\", \ + \"documentation\":\"

The input for the ListThings operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"ListThingsResponse\", \ + \"documentation\":\"

The output from the ListThings operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Lists your things. You can pass an AttributeName and/or AttributeValue to filter your things. For example: \\\"ListThings where AttributeName=Color and AttributeValue=Red\\\"

\" \ + }, \ + \"ListTopicRules\":{ \ + \"name\":\"ListTopicRules\", \ + \"http\":{ \ + \"method\":\"GET\", \ + \"requestUri\":\"/rules\" \ + }, \ + \"input\":{ \ + \"shape\":\"ListTopicRulesRequest\", \ + \"documentation\":\"

The input for the ListTopicRules operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"ListTopicRulesResponse\", \ + \"documentation\":\"

The output from the ListTopicRules operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InternalException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + } \ + ], \ + \"documentation\":\"

Lists the rules for the specific topic.

\" \ + }, \ + \"RejectCertificateTransfer\":{ \ + \"name\":\"RejectCertificateTransfer\", \ + \"http\":{ \ + \"method\":\"PATCH\", \ + \"requestUri\":\"/reject-certificate-transfer/{certificateId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"RejectCertificateTransferRequest\", \ + \"documentation\":\"

The input for the RejectCertificateTransfer operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"TransferAlreadyCompletedException\", \ + \"error\":{\"httpStatusCode\":410}, \ + \"exception\":true, \ + \"documentation\":\"

You can't revert the certificate transfer because it has already completed.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Rejects a pending certificate transfer. After AWS IoT rejects a certificate transfer, the certificate status changes from PENDING_TRANFER to INACTIVE.

To check for pending certificate transfers, call ListCertificates to enumerate your certificates.

This operation can only be called by the transfer destination. Once called, the certificate will be returned to the source's account in the INACTIVE state.

\" \ + }, \ + \"ReplaceTopicRule\":{ \ + \"name\":\"ReplaceTopicRule\", \ + \"http\":{ \ + \"method\":\"PATCH\", \ + \"requestUri\":\"/rules/{ruleName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"ReplaceTopicRuleRequest\", \ + \"documentation\":\"

The input for the ReplaceTopicRule operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"SqlParseException\", \ + \"error\":{\"httpStatusCode\":406}, \ + \"exception\":true, \ + \"documentation\":\"

The Rule-SQL expression can't be parsed correctly.

\" \ + }, \ + { \ + \"shape\":\"InternalException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + } \ + ], \ + \"documentation\":\"

Replaces the specified rule. You must specify all parameters for the new rule.

\" \ + }, \ + \"SetDefaultPolicyVersion\":{ \ + \"name\":\"SetDefaultPolicyVersion\", \ + \"http\":{ \ + \"method\":\"PATCH\", \ + \"requestUri\":\"/policies/{policyName}/version/{policyVersionId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"SetDefaultPolicyVersionRequest\", \ + \"documentation\":\"

The input for the SetDefaultPolicyVersion operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Sets the specified policy version as the default for the specified policy.

\" \ + }, \ + \"SetLoggingOptions\":{ \ + \"name\":\"SetLoggingOptions\", \ + \"http\":{ \ + \"method\":\"POST\", \ + \"requestUri\":\"/loggingOptions\" \ + }, \ + \"input\":{ \ + \"shape\":\"SetLoggingOptionsRequest\", \ + \"documentation\":\"

The input for the SetLoggingOptions operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InternalException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + } \ + ], \ + \"documentation\":\"

Sets the logging options.

\" \ + }, \ + \"TransferCertificate\":{ \ + \"name\":\"TransferCertificate\", \ + \"http\":{ \ + \"method\":\"PATCH\", \ + \"requestUri\":\"/transfer-certificate/{certificateId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"TransferCertificateRequest\", \ + \"documentation\":\"

The input for the TransferCertificate operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"TransferCertificateResponse\", \ + \"documentation\":\"

The output from the TransferCertificate operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"CertificateStateException\", \ + \"error\":{\"httpStatusCode\":406}, \ + \"exception\":true, \ + \"documentation\":\"

The certificate operation is not allowed.

\" \ + }, \ + { \ + \"shape\":\"TransferConflictException\", \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

You can't transfer the the certificate because authorization policies are still attached.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Transfers the specified certificate to the specified AWS account.

You can cancel the transfer until it is acknowledged by the recipient.

No notification is sent to the transfer destination's account, it is up to the caller to notify the transfer target.

The certificate being transferred must not be in the ACTIVE state. It can be deactivated using the UpdateCertificate API.

The certificate must not have any policies attached to it. These can be detached using the DetachPrincipalPolicy API.

\" \ + }, \ + \"UpdateCertificate\":{ \ + \"name\":\"UpdateCertificate\", \ + \"http\":{ \ + \"method\":\"PUT\", \ + \"requestUri\":\"/certificates/{certificateId}\" \ + }, \ + \"input\":{ \ + \"shape\":\"UpdateCertificateRequest\", \ + \"documentation\":\"

The input for the UpdateCertificate operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + { \ + \"shape\":\"CertificateStateException\", \ + \"error\":{\"httpStatusCode\":406}, \ + \"exception\":true, \ + \"documentation\":\"

The certificate operation is not allowed.

\" \ + }, \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + } \ + ], \ + \"documentation\":\"

Updates the status of the specified certificate. This operation is idempotent.

Moving a cert from the ACTIVE state (including REVOKED) will NOT disconnect currently-connected devices, although these devices will be unable to reconnect.

The ACTIVE state is required to authenticate devices connecting to AWS IoT using a certificate.

\" \ + }, \ + \"UpdateThing\":{ \ + \"name\":\"UpdateThing\", \ + \"http\":{ \ + \"method\":\"PATCH\", \ + \"requestUri\":\"/things/{thingName}\" \ + }, \ + \"input\":{ \ + \"shape\":\"UpdateThingRequest\", \ + \"documentation\":\"

The input for the UpdateThing operation.

\" \ + }, \ + \"output\":{ \ + \"shape\":\"UpdateThingResponse\", \ + \"documentation\":\"

The output from the UpdateThing operation.

\" \ + }, \ + \"errors\":[ \ + { \ + \"shape\":\"InvalidRequestException\", \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + { \ + \"shape\":\"ThrottlingException\", \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + { \ + \"shape\":\"UnauthorizedException\", \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + { \ + \"shape\":\"ServiceUnavailableException\", \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + { \ + \"shape\":\"InternalFailureException\", \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + { \ + \"shape\":\"ResourceNotFoundException\", \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + } \ + ], \ + \"documentation\":\"

Updates the data for a thing.

\" \ + } \ + }, \ + \"shapes\":{ \ + \"AcceptCertificateTransferRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"certificateId\"], \ + \"members\":{ \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"location\":\"uri\", \ + \"locationName\":\"certificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + }, \ + \"setAsActive\":{ \ + \"shape\":\"SetAsActive\", \ + \"location\":\"querystring\", \ + \"locationName\":\"setAsActive\", \ + \"documentation\":\"

Specifies whether the certificate is active.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the AcceptCertificateTransfer operation.

\" \ + }, \ + \"Action\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"dynamoDB\":{ \ + \"shape\":\"DynamoDBAction\", \ + \"documentation\":\"

Write to a DynamoDB table.

\" \ + }, \ + \"lambda\":{ \ + \"shape\":\"LambdaAction\", \ + \"documentation\":\"

Invoke a Lambda function.

\" \ + }, \ + \"sns\":{ \ + \"shape\":\"SnsAction\", \ + \"documentation\":\"

Publish to an SNS topic.

\" \ + }, \ + \"sqs\":{ \ + \"shape\":\"SqsAction\", \ + \"documentation\":\"

Publish to an SQS queue.

\" \ + }, \ + \"kinesis\":{ \ + \"shape\":\"KinesisAction\", \ + \"documentation\":\"

Write data to a Kinesis stream.

\" \ + }, \ + \"republish\":{ \ + \"shape\":\"RepublishAction\", \ + \"documentation\":\"

Publish to another MQTT topic.

\" \ + }, \ + \"s3\":{ \ + \"shape\":\"S3Action\", \ + \"documentation\":\"

Write to an S3 bucket.

\" \ + }, \ + \"firehose\":{\"shape\":\"FirehoseAction\"} \ + }, \ + \"documentation\":\"

Describes the actions associated with a rule.

\" \ + }, \ + \"ActionList\":{ \ + \"type\":\"list\", \ + \"member\":{\"shape\":\"Action\"}, \ + \"min\":0, \ + \"max\":10 \ + }, \ + \"AscendingOrder\":{\"type\":\"boolean\"}, \ + \"AttachPrincipalPolicyRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"policyName\", \ + \"principal\" \ + ], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The policy name.

\" \ + }, \ + \"principal\":{ \ + \"shape\":\"Principal\", \ + \"location\":\"header\", \ + \"locationName\":\"x-amzn-iot-principal\", \ + \"documentation\":\"

The principal which can be a certificate ARN (as returned from the CreateCertificate operation) or a Cognito ID.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the AttachPrincipalPolicy operation.

\" \ + }, \ + \"AttachThingPrincipalRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"thingName\", \ + \"principal\" \ + ], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + }, \ + \"principal\":{ \ + \"shape\":\"Principal\", \ + \"location\":\"header\", \ + \"locationName\":\"x-amzn-principal\", \ + \"documentation\":\"

The principal (certificate or other credential).

\" \ + } \ + }, \ + \"documentation\":\"

The input for the AttachThingPrincipal operation.

\" \ + }, \ + \"AttachThingPrincipalResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + }, \ + \"documentation\":\"

The output from the AttachThingPrincipal operation.

\" \ + }, \ + \"AttributeName\":{ \ + \"type\":\"string\", \ + \"max\":128, \ + \"pattern\":\"[a-zA-Z0-9_.,@/:#-]+\" \ + }, \ + \"AttributePayload\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"attributes\":{ \ + \"shape\":\"Attributes\", \ + \"documentation\":\"

A JSON string containing up to three key-value pair in JSON format.

For example: {\\\\\\\"attributes\\\\\\\":{\\\\\\\"string1\\\\\\\":\\\\\\\"string2\\\\”}}

\" \ + } \ + }, \ + \"documentation\":\"

The attribute payload, a JSON string containing up to three key-value pairs.

For example: {\\\\\\\"attributes\\\\\\\":{\\\\\\\"string1\\\\\\\":\\\\\\\"string2\\\\”}}

\" \ + }, \ + \"AttributeValue\":{ \ + \"type\":\"string\", \ + \"max\":1024, \ + \"pattern\":\"[a-zA-Z0-9_.,@/:#-]+\" \ + }, \ + \"Attributes\":{ \ + \"type\":\"map\", \ + \"key\":{\"shape\":\"AttributeName\"}, \ + \"value\":{\"shape\":\"AttributeValue\"} \ + }, \ + \"AwsAccountId\":{ \ + \"type\":\"string\", \ + \"pattern\":\"[0-9]{12}\" \ + }, \ + \"AwsArn\":{\"type\":\"string\"}, \ + \"BucketName\":{\"type\":\"string\"}, \ + \"CancelCertificateTransferRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"certificateId\"], \ + \"members\":{ \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"location\":\"uri\", \ + \"locationName\":\"certificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the CancelCertificateTransfer operation.

\" \ + }, \ + \"Certificate\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"certificateArn\":{ \ + \"shape\":\"CertificateArn\", \ + \"documentation\":\"

The ARN of the certificate.

\" \ + }, \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + }, \ + \"status\":{ \ + \"shape\":\"CertificateStatus\", \ + \"documentation\":\"

The status of the certificate.

\" \ + }, \ + \"creationDate\":{ \ + \"shape\":\"DateType\", \ + \"documentation\":\"

The date and time the certificate was created.

\" \ + } \ + }, \ + \"documentation\":\"

Information about a certificate.

\" \ + }, \ + \"CertificateArn\":{\"type\":\"string\"}, \ + \"CertificateDescription\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"certificateArn\":{ \ + \"shape\":\"CertificateArn\", \ + \"documentation\":\"

The ARN of the certificate.

\" \ + }, \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + }, \ + \"status\":{ \ + \"shape\":\"CertificateStatus\", \ + \"documentation\":\"

The status of the certificate.

\" \ + }, \ + \"certificatePem\":{ \ + \"shape\":\"CertificatePem\", \ + \"documentation\":\"

The certificate data, in PEM format.

\" \ + }, \ + \"ownedBy\":{ \ + \"shape\":\"AwsAccountId\", \ + \"documentation\":\"

The ID of the AWS account that owns the certificate.

\" \ + }, \ + \"creationDate\":{ \ + \"shape\":\"DateType\", \ + \"documentation\":\"

The date and time the certificate was created.

\" \ + }, \ + \"lastModifiedDate\":{ \ + \"shape\":\"DateType\", \ + \"documentation\":\"

The date and time the certificate was last modified.

\" \ + } \ + }, \ + \"documentation\":\"

Describes a certificate.

\" \ + }, \ + \"CertificateId\":{ \ + \"type\":\"string\", \ + \"min\":64, \ + \"max\":64, \ + \"pattern\":\"(0x)?[a-fA-F0-9]+\" \ + }, \ + \"CertificatePem\":{\"type\":\"string\"}, \ + \"CertificateSigningRequest\":{ \ + \"type\":\"string\", \ + \"min\":1 \ + }, \ + \"CertificateStateException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":406}, \ + \"exception\":true, \ + \"documentation\":\"

The certificate operation is not allowed.

\" \ + }, \ + \"CertificateStatus\":{ \ + \"type\":\"string\", \ + \"enum\":[ \ + \"ACTIVE\", \ + \"INACTIVE\", \ + \"REVOKED\", \ + \"PENDING_TRANSFER\" \ + ] \ + }, \ + \"Certificates\":{ \ + \"type\":\"list\", \ + \"member\":{\"shape\":\"Certificate\"} \ + }, \ + \"ClientId\":{\"type\":\"string\"}, \ + \"CreateCertificateFromCsrRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"certificateSigningRequest\"], \ + \"members\":{ \ + \"certificateSigningRequest\":{ \ + \"shape\":\"CertificateSigningRequest\", \ + \"documentation\":\"

The certificate signing request (CSR).

\" \ + }, \ + \"setAsActive\":{ \ + \"shape\":\"SetAsActive\", \ + \"location\":\"querystring\", \ + \"locationName\":\"setAsActive\", \ + \"documentation\":\"

Specifies whether the certificate is active.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the CreateCertificateFromCsr operation.

\" \ + }, \ + \"CreateCertificateFromCsrResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"certificateArn\":{ \ + \"shape\":\"CertificateArn\", \ + \"documentation\":\"

The Amazon Resource Name (ARN) of the certificate. You can use the ARN as a principal for policy operations.

\" \ + }, \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"documentation\":\"

The ID of the certificate. Certificate management operations only take a certificateId.

\" \ + }, \ + \"certificatePem\":{ \ + \"shape\":\"CertificatePem\", \ + \"documentation\":\"

The certificate data, in PEM format.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the CreateCertificateFromCsr operation.

\" \ + }, \ + \"CreateKeysAndCertificateRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"setAsActive\":{ \ + \"shape\":\"SetAsActive\", \ + \"location\":\"querystring\", \ + \"locationName\":\"setAsActive\", \ + \"documentation\":\"

Specifies whether the certificate is active.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the CreateKeysAndCertificate operation.

\" \ + }, \ + \"CreateKeysAndCertificateResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"certificateArn\":{ \ + \"shape\":\"CertificateArn\", \ + \"documentation\":\"

The ARN of the certificate.

\" \ + }, \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"documentation\":\"

The ID of the certificate. AWS IoT issues a default subject name for the certificate (e.g., AWS IoT Certificate).

\" \ + }, \ + \"certificatePem\":{ \ + \"shape\":\"CertificatePem\", \ + \"documentation\":\"

The certificate data, in PEM format.

\" \ + }, \ + \"keyPair\":{ \ + \"shape\":\"KeyPair\", \ + \"documentation\":\"

The generated key pair.

\" \ + } \ + }, \ + \"documentation\":\"

The output of the CreateKeysAndCertificate operation.

\" \ + }, \ + \"CreatePolicyRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"policyName\", \ + \"policyDocument\" \ + ], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The policy name.

\" \ + }, \ + \"policyDocument\":{ \ + \"shape\":\"PolicyDocument\", \ + \"documentation\":\"

The JSON document that describes the policy. The length of the policyDocument must be a minimum length of 1, with a maximum length of 2048, excluding whitespace.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the CreatePolicy operation.

\" \ + }, \ + \"CreatePolicyResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"documentation\":\"

The policy name.

\" \ + }, \ + \"policyArn\":{ \ + \"shape\":\"PolicyArn\", \ + \"documentation\":\"

The policy ARN.

\" \ + }, \ + \"policyDocument\":{ \ + \"shape\":\"PolicyDocument\", \ + \"documentation\":\"

The JSON document that describes the policy.

\" \ + }, \ + \"policyVersionId\":{ \ + \"shape\":\"PolicyVersionId\", \ + \"documentation\":\"

The policy version ID.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the CreatePolicy operation.

\" \ + }, \ + \"CreatePolicyVersionRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"policyName\", \ + \"policyDocument\" \ + ], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The policy name.

\" \ + }, \ + \"policyDocument\":{ \ + \"shape\":\"PolicyDocument\", \ + \"documentation\":\"

The JSON document that describes the policy.

\" \ + }, \ + \"setAsDefault\":{ \ + \"shape\":\"SetAsDefault\", \ + \"location\":\"querystring\", \ + \"locationName\":\"setAsDefault\", \ + \"documentation\":\"

Specifies whether the policy version is set as the default.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the CreatePolicyVersion operation.

\" \ + }, \ + \"CreatePolicyVersionResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"policyArn\":{ \ + \"shape\":\"PolicyArn\", \ + \"documentation\":\"

The policy ARN.

\" \ + }, \ + \"policyDocument\":{ \ + \"shape\":\"PolicyDocument\", \ + \"documentation\":\"

The JSON document that describes the policy.

\" \ + }, \ + \"policyVersionId\":{ \ + \"shape\":\"PolicyVersionId\", \ + \"documentation\":\"

The policy version ID.

\" \ + }, \ + \"isDefaultVersion\":{ \ + \"shape\":\"IsDefaultVersion\", \ + \"documentation\":\"

Specifies whether the policy version is the default.

\" \ + } \ + }, \ + \"documentation\":\"

The output of the CreatePolicyVersion operation.

\" \ + }, \ + \"CreateThingRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"thingName\"], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + }, \ + \"attributePayload\":{ \ + \"shape\":\"AttributePayload\", \ + \"documentation\":\"

The attribute payload. Which consists of up to 3 name/value pairs in a JSON document. For example: {\\\\\\\"attributes\\\\\\\":{\\\\\\\"string1\\\\\\\":\\\\\\\"string2\\\\”}}

\" \ + } \ + }, \ + \"documentation\":\"

The input for the CreateThing operation.

\" \ + }, \ + \"CreateThingResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + }, \ + \"thingArn\":{ \ + \"shape\":\"ThingArn\", \ + \"documentation\":\"

The thing ARN.

\" \ + } \ + }, \ + \"documentation\":\"

The output of the CreateThing operation.

\" \ + }, \ + \"CreateTopicRuleRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"ruleName\", \ + \"topicRulePayload\" \ + ], \ + \"members\":{ \ + \"ruleName\":{ \ + \"shape\":\"RuleName\", \ + \"location\":\"uri\", \ + \"locationName\":\"ruleName\", \ + \"documentation\":\"

The name of the rule.

\" \ + }, \ + \"topicRulePayload\":{ \ + \"shape\":\"TopicRulePayload\", \ + \"documentation\":\"

The rule payload.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the CreateTopicRule operation.

\", \ + \"payload\":\"topicRulePayload\" \ + }, \ + \"CreatedAtDate\":{\"type\":\"timestamp\"}, \ + \"DateType\":{\"type\":\"timestamp\"}, \ + \"DeleteCertificateRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"certificateId\"], \ + \"members\":{ \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"location\":\"uri\", \ + \"locationName\":\"certificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DeleteCertificate operation.

\" \ + }, \ + \"DeleteConflictException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

You can't delete the resource because it is attached to one or more resources.

\" \ + }, \ + \"DeletePolicyRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"policyName\"], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The name of the policy to delete.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DeletePolicy operation.

\" \ + }, \ + \"DeletePolicyVersionRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"policyName\", \ + \"policyVersionId\" \ + ], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The name of the policy.

\" \ + }, \ + \"policyVersionId\":{ \ + \"shape\":\"PolicyVersionId\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyVersionId\", \ + \"documentation\":\"

The policy version ID.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DeletePolicyVersion operation.

\" \ + }, \ + \"DeleteThingRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"thingName\"], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The thing name.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DeleteThing operation.

\" \ + }, \ + \"DeleteThingResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + }, \ + \"documentation\":\"

The output of the DeleteThing operation.

\" \ + }, \ + \"DeleteTopicRuleRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"ruleName\":{ \ + \"shape\":\"RuleName\", \ + \"location\":\"uri\", \ + \"locationName\":\"ruleName\", \ + \"documentation\":\"

The name of the rule.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DeleteTopicRule operation.

\", \ + \"required\":[\"ruleName\"] \ + }, \ + \"DeliveryStreamName\":{\"type\":\"string\"}, \ + \"DescribeCertificateRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"certificateId\"], \ + \"members\":{ \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"location\":\"uri\", \ + \"locationName\":\"certificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DescribeCertificate operation.

\" \ + }, \ + \"DescribeCertificateResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"certificateDescription\":{ \ + \"shape\":\"CertificateDescription\", \ + \"documentation\":\"

The description of the certificate.

\" \ + } \ + }, \ + \"documentation\":\"

The output of the DescribeCertificate operation.

\" \ + }, \ + \"DescribeEndpointRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + }, \ + \"documentation\":\"

The input for the DescribeEndpoint operation.

\" \ + }, \ + \"DescribeEndpointResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"endpointAddress\":{ \ + \"shape\":\"EndpointAddress\", \ + \"documentation\":\"

The address.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the DescribeEndpoint operation.

\" \ + }, \ + \"DescribeThingRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"thingName\"], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DescribeThing operation.

\" \ + }, \ + \"DescribeThingResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"defaultClientId\":{ \ + \"shape\":\"ClientId\", \ + \"documentation\":\"

The default client ID.

\" \ + }, \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + }, \ + \"attributes\":{ \ + \"shape\":\"Attributes\", \ + \"documentation\":\"

The attributes which are name/value pairs in JSON format. For example:

{\\\\\\\"attributes\\\\\\\":{\\\\\\\"some-name1\\\\\\\":\\\\\\\"some-value1\\\\”}, {\\\\\\\"some-name2\\\\\\\":\\\\\\\"some-value2\\\\”}, {\\\\\\\"some-name3\\\\\\\":\\\\\\\"some-value3\\\\”}}

\" \ + } \ + }, \ + \"documentation\":\"

The output from the DescribeThing operation.

\" \ + }, \ + \"Description\":{\"type\":\"string\"}, \ + \"DetachPrincipalPolicyRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"policyName\", \ + \"principal\" \ + ], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The name of the policy to detach.

\" \ + }, \ + \"principal\":{ \ + \"shape\":\"Principal\", \ + \"location\":\"header\", \ + \"locationName\":\"x-amzn-iot-principal\", \ + \"documentation\":\"

The principal

If the principal is a certificate, specify the certificate ARN. If the principal is a Cognito identity specify the identity ID.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DetachPrincipalPolicy operation.

\" \ + }, \ + \"DetachThingPrincipalRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"thingName\", \ + \"principal\" \ + ], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + }, \ + \"principal\":{ \ + \"shape\":\"Principal\", \ + \"location\":\"header\", \ + \"locationName\":\"x-amzn-principal\", \ + \"documentation\":\"

The principal.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the DetachThingPrincipal operation.

\" \ + }, \ + \"DetachThingPrincipalResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + }, \ + \"documentation\":\"

The output from the DetachThingPrincipal operation.

\" \ + }, \ + \"DynamoDBAction\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"tableName\", \ + \"roleArn\", \ + \"hashKeyField\", \ + \"hashKeyValue\", \ + \"rangeKeyField\", \ + \"rangeKeyValue\" \ + ], \ + \"members\":{ \ + \"tableName\":{ \ + \"shape\":\"TableName\", \ + \"documentation\":\"

The name of the DynamoDB table.

\" \ + }, \ + \"roleArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the IAM role that grants access.

\" \ + }, \ + \"hashKeyField\":{ \ + \"shape\":\"HashKeyField\", \ + \"documentation\":\"

The hash key name.

\" \ + }, \ + \"hashKeyValue\":{ \ + \"shape\":\"HashKeyValue\", \ + \"documentation\":\"

The hash key value.

\" \ + }, \ + \"rangeKeyField\":{ \ + \"shape\":\"RangeKeyField\", \ + \"documentation\":\"

The range key name.

\" \ + }, \ + \"rangeKeyValue\":{ \ + \"shape\":\"RangeKeyValue\", \ + \"documentation\":\"

The range key value.

\" \ + }, \ + \"payloadField\":{ \ + \"shape\":\"PayloadField\", \ + \"documentation\":\"

The action payload.

\" \ + } \ + }, \ + \"documentation\":\"

Describes an action to write to a DynamoDB table.

The tableName, hashKeyField, and rangeKeyField values must match the values used when you created the table.

The hashKeyValue and rangeKeyvalue fields use a substitution template syntax. These templates provide data at runtime. The syntax is as follows: ${sql-expression}.

You can specify any expression that's valid in a WHERE or SELECT clause, including JSON properties, comparisons, calculations, and functions. For example, the following field uses the third level of the topic:

\\\"hashKeyValue\\\": \\\"${topic(3)}\\\"

The following field uses the timestamp:

\\\"rangeKeyValue\\\": \\\"${timestamp()}\\\"

\" \ + }, \ + \"EndpointAddress\":{\"type\":\"string\"}, \ + \"FirehoseAction\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"roleArn\", \ + \"deliveryStreamName\" \ + ], \ + \"members\":{ \ + \"roleArn\":{\"shape\":\"AwsArn\"}, \ + \"deliveryStreamName\":{\"shape\":\"DeliveryStreamName\"} \ + } \ + }, \ + \"FunctionArn\":{\"type\":\"string\"}, \ + \"GetLoggingOptionsRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + }, \ + \"documentation\":\"

The input for the GetLoggingOptions operation.

\" \ + }, \ + \"GetLoggingOptionsResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"roleArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the IAM role that grants access.

\" \ + }, \ + \"logLevel\":{ \ + \"shape\":\"LogLevel\", \ + \"documentation\":\"

The logging level.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the GetLoggingOptions operation.

\" \ + }, \ + \"GetPolicyRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"policyName\"], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The name of the policy.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the GetPolicy operation.

\" \ + }, \ + \"GetPolicyResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"documentation\":\"

The policy name.

\" \ + }, \ + \"policyArn\":{ \ + \"shape\":\"PolicyArn\", \ + \"documentation\":\"

The policy ARN.

\" \ + }, \ + \"policyDocument\":{ \ + \"shape\":\"PolicyDocument\", \ + \"documentation\":\"

The JSON document that describes the policy.

\" \ + }, \ + \"defaultVersionId\":{ \ + \"shape\":\"PolicyVersionId\", \ + \"documentation\":\"

The default policy version ID.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the GetPolicy operation.

\" \ + }, \ + \"GetPolicyVersionRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"policyName\", \ + \"policyVersionId\" \ + ], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The name of the policy.

\" \ + }, \ + \"policyVersionId\":{ \ + \"shape\":\"PolicyVersionId\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyVersionId\", \ + \"documentation\":\"

The policy version ID.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the GetPolicyVersion operation.

\" \ + }, \ + \"GetPolicyVersionResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"policyArn\":{ \ + \"shape\":\"PolicyArn\", \ + \"documentation\":\"

The policy ARN.

\" \ + }, \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"documentation\":\"

The policy name.

\" \ + }, \ + \"policyDocument\":{ \ + \"shape\":\"PolicyDocument\", \ + \"documentation\":\"

The JSON document that describes the policy.

\" \ + }, \ + \"policyVersionId\":{ \ + \"shape\":\"PolicyVersionId\", \ + \"documentation\":\"

The policy version ID.

\" \ + }, \ + \"isDefaultVersion\":{ \ + \"shape\":\"IsDefaultVersion\", \ + \"documentation\":\"

Specifies whether the policy version is the default.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the GetPolicyVersion operation.

\" \ + }, \ + \"GetTopicRuleRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"ruleName\"], \ + \"members\":{ \ + \"ruleName\":{ \ + \"shape\":\"RuleName\", \ + \"location\":\"uri\", \ + \"locationName\":\"ruleName\", \ + \"documentation\":\"

The name of the rule.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the GetTopicRule operation.

\" \ + }, \ + \"GetTopicRuleResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"rule\":{ \ + \"shape\":\"TopicRule\", \ + \"documentation\":\"

The rule.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the GetTopicRule operation.

\" \ + }, \ + \"HashKeyField\":{\"type\":\"string\"}, \ + \"HashKeyValue\":{\"type\":\"string\"}, \ + \"InternalException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + \"InternalFailureException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":500}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

An unexpected error has occurred.

\" \ + }, \ + \"InvalidRequestException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The request is not valid.

\" \ + }, \ + \"IsDefaultVersion\":{\"type\":\"boolean\"}, \ + \"IsDisabled\":{\"type\":\"boolean\"}, \ + \"Key\":{\"type\":\"string\"}, \ + \"KeyPair\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"PublicKey\":{ \ + \"shape\":\"PublicKey\", \ + \"documentation\":\"

The public key.

\" \ + }, \ + \"PrivateKey\":{ \ + \"shape\":\"PrivateKey\", \ + \"documentation\":\"

The private key.

\" \ + } \ + }, \ + \"documentation\":\"

Describes a key pair.

\" \ + }, \ + \"KinesisAction\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"roleArn\", \ + \"streamName\" \ + ], \ + \"members\":{ \ + \"roleArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the IAM role that grants access.

\" \ + }, \ + \"streamName\":{ \ + \"shape\":\"StreamName\", \ + \"documentation\":\"

The name of the Kinesis stream.

\" \ + }, \ + \"partitionKey\":{ \ + \"shape\":\"PartitionKey\", \ + \"documentation\":\"

The partition key.

\" \ + } \ + }, \ + \"documentation\":\"

Describes an action to write data to an Amazon Kinesis stream.

\" \ + }, \ + \"LambdaAction\":{ \ + \"type\":\"structure\", \ + \"required\":[\"functionArn\"], \ + \"members\":{ \ + \"functionArn\":{ \ + \"shape\":\"FunctionArn\", \ + \"documentation\":\"

The ARN of the Lambda function.

\" \ + } \ + }, \ + \"documentation\":\"

Describes an action to invoke a Lamdba function.

\" \ + }, \ + \"LimitExceededException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":410}, \ + \"exception\":true, \ + \"documentation\":\"

The number of attached entities exceeds the limit.

\" \ + }, \ + \"ListCertificatesRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"pageSize\":{ \ + \"shape\":\"PageSize\", \ + \"location\":\"querystring\", \ + \"locationName\":\"pageSize\", \ + \"documentation\":\"

The result page size.

\" \ + }, \ + \"marker\":{ \ + \"shape\":\"Marker\", \ + \"location\":\"querystring\", \ + \"locationName\":\"marker\", \ + \"documentation\":\"

The marker for the next set of results.

\" \ + }, \ + \"ascendingOrder\":{ \ + \"shape\":\"AscendingOrder\", \ + \"location\":\"querystring\", \ + \"locationName\":\"isAscendingOrder\", \ + \"documentation\":\"

Specifies the order for results. If True, the results are returned in ascending order, based on the creation date.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ListCertificates operation.

\" \ + }, \ + \"ListCertificatesResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"certificates\":{ \ + \"shape\":\"Certificates\", \ + \"documentation\":\"

The descriptions of the certificates.

\" \ + }, \ + \"nextMarker\":{ \ + \"shape\":\"Marker\", \ + \"documentation\":\"

The marker for the next set of results, or null if there are no additional results.

\" \ + } \ + }, \ + \"documentation\":\"

The output of the ListCertificates operation.

\" \ + }, \ + \"ListPoliciesRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"marker\":{ \ + \"shape\":\"Marker\", \ + \"location\":\"querystring\", \ + \"locationName\":\"marker\", \ + \"documentation\":\"

The marker for the next set of results.

\" \ + }, \ + \"pageSize\":{ \ + \"shape\":\"PageSize\", \ + \"location\":\"querystring\", \ + \"locationName\":\"pageSize\", \ + \"documentation\":\"

The result page size.

\" \ + }, \ + \"ascendingOrder\":{ \ + \"shape\":\"AscendingOrder\", \ + \"location\":\"querystring\", \ + \"locationName\":\"isAscendingOrder\", \ + \"documentation\":\"

Specifies the order for results. If true, the results are returned in ascending creation order.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ListPolicies operation.

\" \ + }, \ + \"ListPoliciesResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"policies\":{ \ + \"shape\":\"Policies\", \ + \"documentation\":\"

The descriptions of the policies.

\" \ + }, \ + \"nextMarker\":{ \ + \"shape\":\"Marker\", \ + \"documentation\":\"

The marker for the next set of results, or null if there are no additional results.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the ListPolicies operation.

\" \ + }, \ + \"ListPolicyVersionsRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"policyName\"], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The policy name.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ListPolicyVersions operation.

\" \ + }, \ + \"ListPolicyVersionsResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"policyVersions\":{ \ + \"shape\":\"PolicyVersions\", \ + \"documentation\":\"

The policy versions.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the ListPolicyVersions operation.

\" \ + }, \ + \"ListPrincipalPoliciesRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"principal\"], \ + \"members\":{ \ + \"principal\":{ \ + \"shape\":\"Principal\", \ + \"location\":\"header\", \ + \"locationName\":\"x-amzn-iot-principal\", \ + \"documentation\":\"

The principal.

\" \ + }, \ + \"marker\":{ \ + \"shape\":\"Marker\", \ + \"location\":\"querystring\", \ + \"locationName\":\"marker\", \ + \"documentation\":\"

The marker for the next set of results.

\" \ + }, \ + \"pageSize\":{ \ + \"shape\":\"PageSize\", \ + \"location\":\"querystring\", \ + \"locationName\":\"pageSize\", \ + \"documentation\":\"

The result page size.

\" \ + }, \ + \"ascendingOrder\":{ \ + \"shape\":\"AscendingOrder\", \ + \"location\":\"querystring\", \ + \"locationName\":\"isAscendingOrder\", \ + \"documentation\":\"

Specifies the order for results. If true, results are returned in ascending creation order.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ListPrincipalPolicies operation.

\" \ + }, \ + \"ListPrincipalPoliciesResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"policies\":{ \ + \"shape\":\"Policies\", \ + \"documentation\":\"

The policies.

\" \ + }, \ + \"nextMarker\":{ \ + \"shape\":\"Marker\", \ + \"documentation\":\"

The marker for the next set of results, or null if there are no additional results.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the ListPrincipalPolicies operation.

\" \ + }, \ + \"ListPrincipalThingsRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"principal\"], \ + \"members\":{ \ + \"nextToken\":{ \ + \"shape\":\"NextToken\", \ + \"location\":\"querystring\", \ + \"locationName\":\"nextToken\" \ + }, \ + \"maxResults\":{ \ + \"shape\":\"MaxResults\", \ + \"location\":\"querystring\", \ + \"locationName\":\"maxResults\" \ + }, \ + \"principal\":{ \ + \"shape\":\"Principal\", \ + \"location\":\"header\", \ + \"locationName\":\"x-amzn-principal\", \ + \"documentation\":\"

The principal.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ListPrincipalThings operation.

\" \ + }, \ + \"ListPrincipalThingsResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"things\":{ \ + \"shape\":\"ThingNameList\", \ + \"documentation\":\"

The things.

\" \ + }, \ + \"nextToken\":{ \ + \"shape\":\"NextToken\", \ + \"documentation\":\"

A token used to retrieve the next value.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the ListPrincipalThings operation.

\" \ + }, \ + \"ListThingPrincipalsRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"thingName\"], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ListThingPrincipal operation.

\" \ + }, \ + \"ListThingPrincipalsResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"principals\":{ \ + \"shape\":\"Principals\", \ + \"documentation\":\"

The principals.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the ListThingPrincipals operation.

\" \ + }, \ + \"ListThingsRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"nextToken\":{ \ + \"shape\":\"NextToken\", \ + \"location\":\"querystring\", \ + \"locationName\":\"nextToken\", \ + \"documentation\":\"

The token for the next value.

\" \ + }, \ + \"maxResults\":{ \ + \"shape\":\"MaxResults\", \ + \"location\":\"querystring\", \ + \"locationName\":\"maxResults\", \ + \"documentation\":\"

The maximum number of results.

\" \ + }, \ + \"attributeName\":{ \ + \"shape\":\"AttributeName\", \ + \"location\":\"querystring\", \ + \"locationName\":\"attributeName\", \ + \"documentation\":\"

The attribute name.

\" \ + }, \ + \"attributeValue\":{ \ + \"shape\":\"AttributeValue\", \ + \"location\":\"querystring\", \ + \"locationName\":\"attributeValue\", \ + \"documentation\":\"

The attribute value.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ListThings operation.

\" \ + }, \ + \"ListThingsResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"things\":{ \ + \"shape\":\"ThingAttributeList\", \ + \"documentation\":\"

The things.

\" \ + }, \ + \"nextToken\":{ \ + \"shape\":\"NextToken\", \ + \"documentation\":\"

A token used to retrieve the next value.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the ListThings operation.

\" \ + }, \ + \"ListTopicRulesRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"topic\":{ \ + \"shape\":\"Topic\", \ + \"location\":\"querystring\", \ + \"locationName\":\"topic\", \ + \"documentation\":\"

The topic.

\" \ + }, \ + \"maxResults\":{ \ + \"shape\":\"MaxResults\", \ + \"location\":\"querystring\", \ + \"locationName\":\"maxResults\", \ + \"documentation\":\"

The maximum number of results to return.

\" \ + }, \ + \"nextToken\":{ \ + \"shape\":\"NextToken\", \ + \"location\":\"querystring\", \ + \"locationName\":\"nextToken\", \ + \"documentation\":\"

A token used to retrieve the next value.

\" \ + }, \ + \"ruleDisabled\":{ \ + \"shape\":\"IsDisabled\", \ + \"location\":\"querystring\", \ + \"locationName\":\"ruleDisabled\", \ + \"documentation\":\"

Specifies whether the rule is disabled.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ListTopicRules operation.

\" \ + }, \ + \"ListTopicRulesResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"rules\":{ \ + \"shape\":\"TopicRuleList\", \ + \"documentation\":\"

The rules.

\" \ + }, \ + \"nextToken\":{ \ + \"shape\":\"NextToken\", \ + \"documentation\":\"

A token used to retrieve the next value.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the ListTopicRules operation.

\" \ + }, \ + \"LogLevel\":{ \ + \"type\":\"string\", \ + \"enum\":[ \ + \"DEBUG\", \ + \"INFO\", \ + \"ERROR\", \ + \"WARN\", \ + \"DISABLED\" \ + ] \ + }, \ + \"LoggingOptionsPayload\":{ \ + \"type\":\"structure\", \ + \"required\":[\"roleArn\"], \ + \"members\":{ \ + \"roleArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the IAM role that grants access.

\" \ + }, \ + \"logLevel\":{ \ + \"shape\":\"LogLevel\", \ + \"documentation\":\"

The logging level.

\" \ + } \ + }, \ + \"documentation\":\"

Describes the logging options payload.

\" \ + }, \ + \"MalformedPolicyException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":400}, \ + \"exception\":true, \ + \"documentation\":\"

The policy documentation is not valid.

\" \ + }, \ + \"Marker\":{\"type\":\"string\"}, \ + \"MaxResults\":{ \ + \"type\":\"integer\", \ + \"min\":1, \ + \"max\":10000 \ + }, \ + \"NextToken\":{\"type\":\"string\"}, \ + \"PageSize\":{ \ + \"type\":\"integer\", \ + \"min\":1, \ + \"max\":250 \ + }, \ + \"PartitionKey\":{\"type\":\"string\"}, \ + \"PayloadField\":{\"type\":\"string\"}, \ + \"Policies\":{ \ + \"type\":\"list\", \ + \"member\":{\"shape\":\"Policy\"} \ + }, \ + \"Policy\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"documentation\":\"

The policy name.

\" \ + }, \ + \"policyArn\":{ \ + \"shape\":\"PolicyArn\", \ + \"documentation\":\"

The policy ARN.

\" \ + } \ + }, \ + \"documentation\":\"

Describes an AWS IoT policy.

\" \ + }, \ + \"PolicyArn\":{\"type\":\"string\"}, \ + \"PolicyDocument\":{\"type\":\"string\"}, \ + \"PolicyName\":{ \ + \"type\":\"string\", \ + \"min\":1, \ + \"max\":128, \ + \"pattern\":\"[\\\\w+=,.@-]+\" \ + }, \ + \"PolicyVersion\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"versionId\":{ \ + \"shape\":\"PolicyVersionId\", \ + \"documentation\":\"

The policy version ID.

\" \ + }, \ + \"isDefaultVersion\":{ \ + \"shape\":\"IsDefaultVersion\", \ + \"documentation\":\"

Specifies whether the policy version is the default.

\" \ + }, \ + \"createDate\":{ \ + \"shape\":\"DateType\", \ + \"documentation\":\"

The date and time the policy was created.

\" \ + } \ + }, \ + \"documentation\":\"

Describes a policy version.

\" \ + }, \ + \"PolicyVersionId\":{ \ + \"type\":\"string\", \ + \"pattern\":\"[0-9]+\" \ + }, \ + \"PolicyVersions\":{ \ + \"type\":\"list\", \ + \"member\":{\"shape\":\"PolicyVersion\"} \ + }, \ + \"Principal\":{\"type\":\"string\"}, \ + \"PrincipalArn\":{\"type\":\"string\"}, \ + \"Principals\":{ \ + \"type\":\"list\", \ + \"member\":{\"shape\":\"PrincipalArn\"} \ + }, \ + \"PrivateKey\":{ \ + \"type\":\"string\", \ + \"min\":1 \ + }, \ + \"PublicKey\":{ \ + \"type\":\"string\", \ + \"min\":1 \ + }, \ + \"QueueUrl\":{\"type\":\"string\"}, \ + \"RangeKeyField\":{\"type\":\"string\"}, \ + \"RangeKeyValue\":{\"type\":\"string\"}, \ + \"RejectCertificateTransferRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[\"certificateId\"], \ + \"members\":{ \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"location\":\"uri\", \ + \"locationName\":\"certificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the RejectCertificateTransfer operation.

\" \ + }, \ + \"ReplaceTopicRuleRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"ruleName\", \ + \"topicRulePayload\" \ + ], \ + \"members\":{ \ + \"ruleName\":{ \ + \"shape\":\"RuleName\", \ + \"location\":\"uri\", \ + \"locationName\":\"ruleName\", \ + \"documentation\":\"

The name of the rule.

\" \ + }, \ + \"topicRulePayload\":{ \ + \"shape\":\"TopicRulePayload\", \ + \"documentation\":\"

The rule payload.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the ReplaceTopicRule operation.

\", \ + \"payload\":\"topicRulePayload\" \ + }, \ + \"RepublishAction\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"roleArn\", \ + \"topic\" \ + ], \ + \"members\":{ \ + \"roleArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the IAM role that grants access.

\" \ + }, \ + \"topic\":{ \ + \"shape\":\"TopicPattern\", \ + \"documentation\":\"

The name of the MQTT topic.

\" \ + } \ + }, \ + \"documentation\":\"

Describes an action to republish to another topic.

\" \ + }, \ + \"ResourceAlreadyExistsException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

The resource already exists.

\" \ + }, \ + \"ResourceNotFoundException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":404}, \ + \"exception\":true, \ + \"documentation\":\"

The specified resource does not exist.

\" \ + }, \ + \"RuleName\":{ \ + \"type\":\"string\", \ + \"min\":1, \ + \"max\":128, \ + \"pattern\":\"^[a-zA-Z0-9_]+$\" \ + }, \ + \"S3Action\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"roleArn\", \ + \"bucketName\", \ + \"key\" \ + ], \ + \"members\":{ \ + \"roleArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the IAM role that grants access.

\" \ + }, \ + \"bucketName\":{ \ + \"shape\":\"BucketName\", \ + \"documentation\":\"

The S3 bucket.

\" \ + }, \ + \"key\":{ \ + \"shape\":\"Key\", \ + \"documentation\":\"

The object key.

\" \ + } \ + }, \ + \"documentation\":\"

Describes an action to write data to an Amazon S3 bucket.

\" \ + }, \ + \"SQL\":{\"type\":\"string\"}, \ + \"ServiceUnavailableException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":503}, \ + \"exception\":true, \ + \"fault\":true, \ + \"documentation\":\"

The service is temporarily unavailable.

\" \ + }, \ + \"SetAsActive\":{\"type\":\"boolean\"}, \ + \"SetAsDefault\":{\"type\":\"boolean\"}, \ + \"SetDefaultPolicyVersionRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"policyName\", \ + \"policyVersionId\" \ + ], \ + \"members\":{ \ + \"policyName\":{ \ + \"shape\":\"PolicyName\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyName\", \ + \"documentation\":\"

The policy name.

\" \ + }, \ + \"policyVersionId\":{ \ + \"shape\":\"PolicyVersionId\", \ + \"location\":\"uri\", \ + \"locationName\":\"policyVersionId\", \ + \"documentation\":\"

The policy version ID.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the SetDefaultPolicyVersion operation.

\" \ + }, \ + \"SetLoggingOptionsRequest\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"loggingOptionsPayload\":{ \ + \"shape\":\"LoggingOptionsPayload\", \ + \"documentation\":\"

The logging options payload.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the SetLoggingOptions operation.

\", \ + \"payload\":\"loggingOptionsPayload\" \ + }, \ + \"SnsAction\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"targetArn\", \ + \"roleArn\" \ + ], \ + \"members\":{ \ + \"targetArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the SNS topic.

\" \ + }, \ + \"roleArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the IAM role that grants access.

\" \ + } \ + }, \ + \"documentation\":\"

Describes an action to publish to an Amazon SNS topic.

\" \ + }, \ + \"SqlParseException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":406}, \ + \"exception\":true, \ + \"documentation\":\"

The Rule-SQL expression can't be parsed correctly.

\" \ + }, \ + \"SqsAction\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"roleArn\", \ + \"queueUrl\" \ + ], \ + \"members\":{ \ + \"roleArn\":{ \ + \"shape\":\"AwsArn\", \ + \"documentation\":\"

The ARN of the IAM role that grants access.

\" \ + }, \ + \"queueUrl\":{ \ + \"shape\":\"QueueUrl\", \ + \"documentation\":\"

The URL of the Amazon SQS queue.

\" \ + }, \ + \"useBase64\":{ \ + \"shape\":\"UseBase64\", \ + \"documentation\":\"

Specifies whether to use Base64 encoding.

\" \ + } \ + }, \ + \"documentation\":\"

Describes an action to publish data to an SQS queue.

\" \ + }, \ + \"StreamName\":{\"type\":\"string\"}, \ + \"TableName\":{\"type\":\"string\"}, \ + \"ThingArn\":{\"type\":\"string\"}, \ + \"ThingAttribute\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"documentation\":\"

The name of the thing.

\" \ + }, \ + \"attributes\":{ \ + \"shape\":\"Attributes\", \ + \"documentation\":\"

The attributes.

\" \ + } \ + }, \ + \"documentation\":\"

Describes a thing attribute.

\" \ + }, \ + \"ThingAttributeList\":{ \ + \"type\":\"list\", \ + \"member\":{\"shape\":\"ThingAttribute\"} \ + }, \ + \"ThingName\":{ \ + \"type\":\"string\", \ + \"min\":1, \ + \"max\":128, \ + \"pattern\":\"[a-zA-Z0-9_-]+\" \ + }, \ + \"ThingNameList\":{ \ + \"type\":\"list\", \ + \"member\":{\"shape\":\"ThingName\"} \ + }, \ + \"ThrottlingException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":429}, \ + \"exception\":true, \ + \"documentation\":\"

The rate exceeds the limit.

\" \ + }, \ + \"Topic\":{\"type\":\"string\"}, \ + \"TopicPattern\":{\"type\":\"string\"}, \ + \"TopicRule\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"ruleName\":{ \ + \"shape\":\"RuleName\", \ + \"documentation\":\"

The name of the rule.

\" \ + }, \ + \"sql\":{ \ + \"shape\":\"SQL\", \ + \"documentation\":\"

The SQL statement used to query the topic. When using a SQL query with multiple lines, be sure to escape the newline characters properly.

\" \ + }, \ + \"description\":{ \ + \"shape\":\"Description\", \ + \"documentation\":\"

The description of the rule.

\" \ + }, \ + \"createdAt\":{ \ + \"shape\":\"CreatedAtDate\", \ + \"documentation\":\"

The date and time the rule was created.

\" \ + }, \ + \"actions\":{ \ + \"shape\":\"ActionList\", \ + \"documentation\":\"

The actions associated with the rule.

\" \ + }, \ + \"ruleDisabled\":{ \ + \"shape\":\"IsDisabled\", \ + \"documentation\":\"

Specifies whether the rule is disabled.

\" \ + } \ + }, \ + \"documentation\":\"

Describes a rule.

\" \ + }, \ + \"TopicRuleList\":{ \ + \"type\":\"list\", \ + \"member\":{\"shape\":\"TopicRuleListItem\"} \ + }, \ + \"TopicRuleListItem\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"ruleName\":{ \ + \"shape\":\"RuleName\", \ + \"documentation\":\"

The name of the rule.

\" \ + }, \ + \"topicPattern\":{ \ + \"shape\":\"TopicPattern\", \ + \"documentation\":\"

The pattern for the topic names that apply.

\" \ + }, \ + \"createdAt\":{ \ + \"shape\":\"CreatedAtDate\", \ + \"documentation\":\"

The date and time the rule was created.

\" \ + }, \ + \"ruleDisabled\":{ \ + \"shape\":\"IsDisabled\", \ + \"documentation\":\"

Specifies whether the rule is disabled.

\" \ + } \ + }, \ + \"documentation\":\"

Describes a rule.

\" \ + }, \ + \"TopicRulePayload\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"sql\", \ + \"actions\" \ + ], \ + \"members\":{ \ + \"sql\":{ \ + \"shape\":\"SQL\", \ + \"documentation\":\"

The SQL statement used to query the topic. For more information, see AWS IoT SQL Reference in the AWS IoT Developer Guide.

\" \ + }, \ + \"description\":{ \ + \"shape\":\"Description\", \ + \"documentation\":\"

The description of the rule.

\" \ + }, \ + \"actions\":{ \ + \"shape\":\"ActionList\", \ + \"documentation\":\"

The actions associated with the rule.

\" \ + }, \ + \"ruleDisabled\":{ \ + \"shape\":\"IsDisabled\", \ + \"documentation\":\"

Specifies whether the rule is disabled.

\" \ + } \ + }, \ + \"documentation\":\"

Describes a rule.

\" \ + }, \ + \"TransferAlreadyCompletedException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":410}, \ + \"exception\":true, \ + \"documentation\":\"

You can't revert the certificate transfer because it has already completed.

\" \ + }, \ + \"TransferCertificateRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"certificateId\", \ + \"targetAwsAccount\" \ + ], \ + \"members\":{ \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"location\":\"uri\", \ + \"locationName\":\"certificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + }, \ + \"targetAwsAccount\":{ \ + \"shape\":\"AwsAccountId\", \ + \"location\":\"querystring\", \ + \"locationName\":\"targetAwsAccount\", \ + \"documentation\":\"

The AWS account.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the TransferCertificate operation.

\" \ + }, \ + \"TransferCertificateResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"transferredCertificateArn\":{ \ + \"shape\":\"CertificateArn\", \ + \"documentation\":\"

The ARN of the certificate.

\" \ + } \ + }, \ + \"documentation\":\"

The output from the TransferCertificate operation.

\" \ + }, \ + \"TransferConflictException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

You can't transfer the the certificate because authorization policies are still attached.

\" \ + }, \ + \"UnauthorizedException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":401}, \ + \"exception\":true, \ + \"documentation\":\"

You are not authorized to perform this operation.

\" \ + }, \ + \"UpdateCertificateRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"certificateId\", \ + \"newStatus\" \ + ], \ + \"members\":{ \ + \"certificateId\":{ \ + \"shape\":\"CertificateId\", \ + \"location\":\"uri\", \ + \"locationName\":\"certificateId\", \ + \"documentation\":\"

The ID of the certificate.

\" \ + }, \ + \"newStatus\":{ \ + \"shape\":\"CertificateStatus\", \ + \"location\":\"querystring\", \ + \"locationName\":\"newStatus\", \ + \"documentation\":\"

The new status.

\" \ + } \ + }, \ + \"documentation\":\"

The input for the UpdateCertificate operation.

\" \ + }, \ + \"UpdateThingRequest\":{ \ + \"type\":\"structure\", \ + \"required\":[ \ + \"thingName\", \ + \"attributePayload\" \ + ], \ + \"members\":{ \ + \"thingName\":{ \ + \"shape\":\"ThingName\", \ + \"location\":\"uri\", \ + \"locationName\":\"thingName\", \ + \"documentation\":\"

The thing name.

\" \ + }, \ + \"attributePayload\":{ \ + \"shape\":\"AttributePayload\", \ + \"documentation\":\"

The attribute payload, a JSON string containing up to three key-value pairs.

For example: {\\\\\\\"attributes\\\\\\\":{\\\\\\\"string1\\\\\\\":\\\\\\\"string2\\\\”}}

\" \ + } \ + }, \ + \"documentation\":\"

The input for the UpdateThing operation.

\" \ + }, \ + \"UpdateThingResponse\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + }, \ + \"documentation\":\"

The output from the UpdateThing operation.

\" \ + }, \ + \"UseBase64\":{\"type\":\"boolean\"}, \ + \"VersionsLimitExceededException\":{ \ + \"type\":\"structure\", \ + \"members\":{ \ + \"message\":{ \ + \"shape\":\"errorMessage\", \ + \"documentation\":\"

The message for the exception.

\" \ + } \ + }, \ + \"error\":{\"httpStatusCode\":409}, \ + \"exception\":true, \ + \"documentation\":\"

The number of policy versions exceeds the limit.

\" \ + }, \ + \"errorMessage\":{\"type\":\"string\"} \ + }, \ + \"examples\":{ \ + } \ +} \ + \ +"; +} + +@end diff --git a/AWSIoT/AWSIoTService.h b/AWSIoT/AWSIoTService.h new file mode 100644 index 00000000000..77898cfc85e --- /dev/null +++ b/AWSIoT/AWSIoTService.h @@ -0,0 +1,629 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import +#import "AWSIoTModel.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + AWS IoT (Beta)

AWS IoT is in beta and is subject to change

AWS IoT provides secure, bi-directional communication between Internet-connected things (such as sensors, actuators, embedded devices, or smart appliances) and the AWS cloud. You can discover your custom IoT-Data endpoint to communicate with, configure rules for data processing and integration with other services, organize resources associated with each thing (Thing Registry), configure logging, and create and manage policies and credentials to authenticate things.

For more information about how AWS IoT works, see the Developer Guide.

+ */ +@interface AWSIoT : AWSService + +/** + The service configuration used to instantiate this service client. + + @warning Once the client is instantiated, do not modify the configuration object. It may cause unspecified behaviors. + */ +@property (nonatomic, strong, readonly) AWSServiceConfiguration *configuration; + +/** + Returns the singleton service client. If the singleton object does not exist, the SDK instantiates the default service client with `defaultServiceConfiguration` from `[AWSServiceManager defaultServiceManager]`. The reference to this object is maintained by the SDK, and you do not need to retain it manually. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialProvider) + AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 + credentialsProvider:credentialsProvider]; + [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; + + return YES; + } + + Then call the following to get the default service client: + + *Swift* + + let IoT = AWSIoT.defaultIoT() + + *Objective-C* + + AWSIoT *IoT = [AWSIoT defaultIoT]; + + @return The default service client. + */ ++ (instancetype)defaultIoT; + +/** + Creates a service client with the given service configuration and registers it for the key. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) + AWSIoT.registerIoTWithConfiguration(configuration, forKey: "USWest2IoT") + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 + credentialsProvider:credentialsProvider]; + + [AWSIoT registerIoTWithConfiguration:configuration forKey:@"USWest2IoT"]; + + return YES; + } + + Then call the following to get the service client: + + *Swift* + + let IoT = AWSIoT(forKey: "USWest2IoT") + + *Objective-C* + + AWSIoT *IoT = [AWSIoT IoTForKey:@"USWest2IoT"]; + + @warning After calling this method, do not modify the configuration object. It may cause unspecified behaviors. + + @param configuration A service configuration object. + @param key A string to identify the service client. + */ ++ (instancetype)registerIoTWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key; + +/** + Retrieves the service client associated with the key. You need to call `+ registerIoTWithConfiguration:forKey:` before invoking this method. If `+ registerIoTWithConfiguration:forKey:` has not been called in advance or the key does not exist, this method returns `nil`. + + For example, set the default service configuration in `- application:didFinishLaunchingWithOptions:` + + *Swift* + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YourIdentityPoolId") + let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialProvider) + AWSIoT.registerIoTWithConfiguration(configuration, forKey: "USWest2IoT") + + return true + } + + *Objective-C* + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 + identityPoolId:@"YourIdentityPoolId"]; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2 + credentialsProvider:credentialsProvider]; + + [AWSIoT registerIoTWithConfiguration:configuration forKey:@"USWest2IoT"]; + + return YES; + } + + Then call the following to get the service client: + + *Swift* + + let IoT = AWSIoT(forKey: "USWest2IoT") + + *Objective-C* + + AWSIoT *IoT = [AWSIoT IoTForKey:@"USWest2IoT"]; + + @param key A string to identify the service client. + + @return An instance of the service client. + */ ++ (instancetype)IoTForKey:(NSString *)key; + +/** + Removes the service client associated with the key and release it. + + @warning Before calling this method, make sure no method is running on this client. + + @param key A string to identify the service client. + */ ++ (void)removeIoTForKey:(NSString *)key; + +/** +

Accepts a pending certificate transfer. The default state of the certificate is INACTIVE.

To check for pending certificate transfers, call ListCertificates to enumerate your certificates.

+ + @param request A container for the necessary parameters to execute the AcceptCertificateTransfer service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorTransferAlreadyCompleted`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTAcceptCertificateTransferRequest + */ +- (AWSTask *)acceptCertificateTransfer:(AWSIoTAcceptCertificateTransferRequest *)request; + +/** +

Attaches the specified policy to the specified principal (certificate or other credential).

+ + @param request A container for the necessary parameters to execute the AttachPrincipalPolicy service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`, `AWSIoTErrorLimitExceeded`. + + @see AWSIoTAttachPrincipalPolicyRequest + */ +- (AWSTask *)attachPrincipalPolicy:(AWSIoTAttachPrincipalPolicyRequest *)request; + +/** +

Attaches the specified principal to the specified thing.

+ + @param request A container for the necessary parameters to execute the AttachThingPrincipal service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTAttachThingPrincipalResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTAttachThingPrincipalRequest + @see AWSIoTAttachThingPrincipalResponse + */ +- (AWSTask *)attachThingPrincipal:(AWSIoTAttachThingPrincipalRequest *)request; + +/** +

Cancels a pending transfer for the specified certificate.

Note Only the transfer source account can use this operation to cancel a transfer (transfer destinations can use RejectCertificateTransfer instead). After transfer, AWS IoT returns the certificate to the source account in the INACTIVE state. Once the destination account has accepted the transfer, the transfer may no longer be cancelled.

After a certificate transfer is cancelled, the status of the certificate changes from PENDING_TRANSFER to INACTIVE.

+ + @param request A container for the necessary parameters to execute the CancelCertificateTransfer service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorTransferAlreadyCompleted`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTCancelCertificateTransferRequest + */ +- (AWSTask *)cancelCertificateTransfer:(AWSIoTCancelCertificateTransferRequest *)request; + +/** +

Creates an X.509 certificate using the specified certificate signing request.

Note Reusing the same certificate signing request (CSR) results in a distinct certificate.

+ + @param request A container for the necessary parameters to execute the CreateCertificateFromCsr service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTCreateCertificateFromCsrResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTCreateCertificateFromCsrRequest + @see AWSIoTCreateCertificateFromCsrResponse + */ +- (AWSTask *)createCertificateFromCsr:(AWSIoTCreateCertificateFromCsrRequest *)request; + +/** +

Creates a 2048 bit RSA key pair and issues an X.509 certificate using the issued public key.

Note This is the only time AWS IoT issues the private key for this certificate. It is important to keep track of the private key.

+ + @param request A container for the necessary parameters to execute the CreateKeysAndCertificate service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTCreateKeysAndCertificateResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTCreateKeysAndCertificateRequest + @see AWSIoTCreateKeysAndCertificateResponse + */ +- (AWSTask *)createKeysAndCertificate:(AWSIoTCreateKeysAndCertificateRequest *)request; + +/** +

Creates an AWS IoT policy.

The created policy is the default version for the policy. This operation creates a policy version with a version identifier of 1 and sets 1 as the policy's default version.

+ + @param request A container for the necessary parameters to execute the CreatePolicy service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTCreatePolicyResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceAlreadyExists`, `AWSIoTErrorMalformedPolicy`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTCreatePolicyRequest + @see AWSIoTCreatePolicyResponse + */ +- (AWSTask *)createPolicy:(AWSIoTCreatePolicyRequest *)request; + +/** +

Creates a new version of the specified AWS IoT policy.

+ + @param request A container for the necessary parameters to execute the CreatePolicyVersion service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTCreatePolicyVersionResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorMalformedPolicy`, `AWSIoTErrorVersionsLimitExceeded`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTCreatePolicyVersionRequest + @see AWSIoTCreatePolicyVersionResponse + */ +- (AWSTask *)createPolicyVersion:(AWSIoTCreatePolicyVersionRequest *)request; + +/** +

Creates a thing in the thing registry.

+ + @param request A container for the necessary parameters to execute the CreateThing service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTCreateThingResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`, `AWSIoTErrorResourceAlreadyExists`. + + @see AWSIoTCreateThingRequest + @see AWSIoTCreateThingResponse + */ +- (AWSTask *)createThing:(AWSIoTCreateThingRequest *)request; + +/** +

Creates a rule.

+ + @param request A container for the necessary parameters to execute the CreateTopicRule service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorSqlParse`, `AWSIoTErrorInternal`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorResourceAlreadyExists`, `AWSIoTErrorServiceUnavailable`. + + @see AWSIoTCreateTopicRuleRequest + */ +- (AWSTask *)createTopicRule:(AWSIoTCreateTopicRuleRequest *)request; + +/** +

Deletes the specified certificate.

A certificate cannot be deleted if it has a policy attached to it. To delete a certificate, first detach all policies using the DetachPrincipalPolicy operation.

In addition, a certificate cannot be deleted if it is in ACTIVE status. To delete a certificate, first change the status to INACTIVE using the UpdateCertificate operation.

+ + @param request A container for the necessary parameters to execute the DeleteCertificate service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorDeleteConflict`, `AWSIoTErrorResourceNotFound`, `AWSIoTErrorCertificateState`. + + @see AWSIoTDeleteCertificateRequest + */ +- (AWSTask *)deleteCertificate:(AWSIoTDeleteCertificateRequest *)request; + +/** +

Deletes the specified policy.

A policy cannot be deleted if:

- it has non-default versions

- it is attached to any certificate

To delete a policy:

- First delete all the non-default versions of the policy using the DeletePolicyVersion API.

- Detach it from any certificate using the DetachPrincipalPolicy API.

When a policy is deleted, its default version is deleted with it.

+ + @param request A container for the necessary parameters to execute the DeletePolicy service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorDeleteConflict`, `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTDeletePolicyRequest + */ +- (AWSTask *)deletePolicy:(AWSIoTDeletePolicyRequest *)request; + +/** +

Deletes the specified version of the specified policy. The default version of the policy cannot be deleted.

To delete the default version use the DeletePolicy API or mark the policy as non-default and then delete it.

+ + @param request A container for the necessary parameters to execute the DeletePolicyVersion service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorDeleteConflict`, `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTDeletePolicyVersionRequest + */ +- (AWSTask *)deletePolicyVersion:(AWSIoTDeletePolicyVersionRequest *)request; + +/** +

Deletes the specified thing from the Thing Registry.

+ + @param request A container for the necessary parameters to execute the DeleteThing service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTDeleteThingResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTDeleteThingRequest + @see AWSIoTDeleteThingResponse + */ +- (AWSTask *)deleteThing:(AWSIoTDeleteThingRequest *)request; + +/** +

Deletes the specified rule.

+ + @param request A container for the necessary parameters to execute the DeleteTopicRule service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInternal`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorUnauthorized`. + + @see AWSIoTDeleteTopicRuleRequest + */ +- (AWSTask *)deleteTopicRule:(AWSIoTDeleteTopicRuleRequest *)request; + +/** +

Gets information about the specified certificate.

+ + @param request A container for the necessary parameters to execute the DescribeCertificate service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTDescribeCertificateResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`, `AWSIoTErrorResourceNotFound`. + + @see AWSIoTDescribeCertificateRequest + @see AWSIoTDescribeCertificateResponse + */ +- (AWSTask *)describeCertificate:(AWSIoTDescribeCertificateRequest *)request; + +/** +

Returns a unique URL specific to the AWS account making the call. The URL points to the AWS IoT data plane endpoint. The customer-specific endpoint should be provided to all data plane operations.

+ + @param request A container for the necessary parameters to execute the DescribeEndpoint service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTDescribeEndpointResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInternalFailure`, `AWSIoTErrorUnauthorized`. + + @see AWSIoTDescribeEndpointRequest + @see AWSIoTDescribeEndpointResponse + */ +- (AWSTask *)describeEndpoint:(AWSIoTDescribeEndpointRequest *)request; + +/** +

Gets information about the specified thing.

+ + @param request A container for the necessary parameters to execute the DescribeThing service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTDescribeThingResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTDescribeThingRequest + @see AWSIoTDescribeThingResponse + */ +- (AWSTask *)describeThing:(AWSIoTDescribeThingRequest *)request; + +/** +

Removes the specified policy from the specified certificate.

+ + @param request A container for the necessary parameters to execute the DetachPrincipalPolicy service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTDetachPrincipalPolicyRequest + */ +- (AWSTask *)detachPrincipalPolicy:(AWSIoTDetachPrincipalPolicyRequest *)request; + +/** +

Detaches the specified principal from the specified thing.

+ + @param request A container for the necessary parameters to execute the DetachThingPrincipal service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTDetachThingPrincipalResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTDetachThingPrincipalRequest + @see AWSIoTDetachThingPrincipalResponse + */ +- (AWSTask *)detachThingPrincipal:(AWSIoTDetachThingPrincipalRequest *)request; + +/** +

Gets the logging options.

+ + @param request A container for the necessary parameters to execute the GetLoggingOptions service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTGetLoggingOptionsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInternal`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorServiceUnavailable`. + + @see AWSIoTGetLoggingOptionsRequest + @see AWSIoTGetLoggingOptionsResponse + */ +- (AWSTask *)getLoggingOptions:(AWSIoTGetLoggingOptionsRequest *)request; + +/** +

Gets information about the specified policy with the policy document of the default version.

+ + @param request A container for the necessary parameters to execute the GetPolicy service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTGetPolicyResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTGetPolicyRequest + @see AWSIoTGetPolicyResponse + */ +- (AWSTask *)getPolicy:(AWSIoTGetPolicyRequest *)request; + +/** +

Gets information about the specified policy version.

+ + @param request A container for the necessary parameters to execute the GetPolicyVersion service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTGetPolicyVersionResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTGetPolicyVersionRequest + @see AWSIoTGetPolicyVersionResponse + */ +- (AWSTask *)getPolicyVersion:(AWSIoTGetPolicyVersionRequest *)request; + +/** +

Gets information about the specified rule.

+ + @param request A container for the necessary parameters to execute the GetTopicRule service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTGetTopicRuleResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInternal`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorUnauthorized`. + + @see AWSIoTGetTopicRuleRequest + @see AWSIoTGetTopicRuleResponse + */ +- (AWSTask *)getTopicRule:(AWSIoTGetTopicRuleRequest *)request; + +/** +

Lists your certificates.

The results are paginated with a default page size of 25. You can retrieve additional results using the returned marker.

+ + @param request A container for the necessary parameters to execute the ListCertificates service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTListCertificatesResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTListCertificatesRequest + @see AWSIoTListCertificatesResponse + */ +- (AWSTask *)listCertificates:(AWSIoTListCertificatesRequest *)request; + +/** +

Lists your policies.

+ + @param request A container for the necessary parameters to execute the ListPolicies service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTListPoliciesResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTListPoliciesRequest + @see AWSIoTListPoliciesResponse + */ +- (AWSTask *)listPolicies:(AWSIoTListPoliciesRequest *)request; + +/** +

Lists the versions of the specified policy, and identifies the default version.

+ + @param request A container for the necessary parameters to execute the ListPolicyVersions service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTListPolicyVersionsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTListPolicyVersionsRequest + @see AWSIoTListPolicyVersionsResponse + */ +- (AWSTask *)listPolicyVersions:(AWSIoTListPolicyVersionsRequest *)request; + +/** +

Lists the policies attached to the specified principal. If you use an Amazon Cognito identity, the ID needs to be in Amazon Cognito Identity format.

+ + @param request A container for the necessary parameters to execute the ListPrincipalPolicies service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTListPrincipalPoliciesResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTListPrincipalPoliciesRequest + @see AWSIoTListPrincipalPoliciesResponse + */ +- (AWSTask *)listPrincipalPolicies:(AWSIoTListPrincipalPoliciesRequest *)request; + +/** +

Lists the things associated with the specified principal.

+ + @param request A container for the necessary parameters to execute the ListPrincipalThings service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTListPrincipalThingsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTListPrincipalThingsRequest + @see AWSIoTListPrincipalThingsResponse + */ +- (AWSTask *)listPrincipalThings:(AWSIoTListPrincipalThingsRequest *)request; + +/** +

Lists the principals associated with the specified thing.

+ + @param request A container for the necessary parameters to execute the ListThingPrincipals service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTListThingPrincipalsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTListThingPrincipalsRequest + @see AWSIoTListThingPrincipalsResponse + */ +- (AWSTask *)listThingPrincipals:(AWSIoTListThingPrincipalsRequest *)request; + +/** +

Lists your things. You can pass an AttributeName and/or AttributeValue to filter your things. For example: "ListThings where AttributeName=Color and AttributeValue=Red"

+ + @param request A container for the necessary parameters to execute the ListThings service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTListThingsResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTListThingsRequest + @see AWSIoTListThingsResponse + */ +- (AWSTask *)listThings:(AWSIoTListThingsRequest *)request; + +/** +

Lists the rules for the specific topic.

+ + @param request A container for the necessary parameters to execute the ListTopicRules service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTListTopicRulesResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInternal`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorServiceUnavailable`. + + @see AWSIoTListTopicRulesRequest + @see AWSIoTListTopicRulesResponse + */ +- (AWSTask *)listTopicRules:(AWSIoTListTopicRulesRequest *)request; + +/** +

Rejects a pending certificate transfer. After AWS IoT rejects a certificate transfer, the certificate status changes from PENDING_TRANFER to INACTIVE.

To check for pending certificate transfers, call ListCertificates to enumerate your certificates.

This operation can only be called by the transfer destination. Once called, the certificate will be returned to the source's account in the INACTIVE state.

+ + @param request A container for the necessary parameters to execute the RejectCertificateTransfer service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorTransferAlreadyCompleted`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTRejectCertificateTransferRequest + */ +- (AWSTask *)rejectCertificateTransfer:(AWSIoTRejectCertificateTransferRequest *)request; + +/** +

Replaces the specified rule. You must specify all parameters for the new rule.

+ + @param request A container for the necessary parameters to execute the ReplaceTopicRule service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorSqlParse`, `AWSIoTErrorInternal`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorUnauthorized`. + + @see AWSIoTReplaceTopicRuleRequest + */ +- (AWSTask *)replaceTopicRule:(AWSIoTReplaceTopicRuleRequest *)request; + +/** +

Sets the specified policy version as the default for the specified policy.

+ + @param request A container for the necessary parameters to execute the SetDefaultPolicyVersion service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTSetDefaultPolicyVersionRequest + */ +- (AWSTask *)setDefaultPolicyVersion:(AWSIoTSetDefaultPolicyVersionRequest *)request; + +/** +

Sets the logging options.

+ + @param request A container for the necessary parameters to execute the SetLoggingOptions service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInternal`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorServiceUnavailable`. + + @see AWSIoTSetLoggingOptionsRequest + */ +- (AWSTask *)setLoggingOptions:(AWSIoTSetLoggingOptionsRequest *)request; + +/** +

Transfers the specified certificate to the specified AWS account.

You can cancel the transfer until it is acknowledged by the recipient.

No notification is sent to the transfer destination's account, it is up to the caller to notify the transfer target.

The certificate being transferred must not be in the ACTIVE state. It can be deactivated using the UpdateCertificate API.

The certificate must not have any policies attached to it. These can be detached using the DetachPrincipalPolicy API.

+ + @param request A container for the necessary parameters to execute the TransferCertificate service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTTransferCertificateResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorResourceNotFound`, `AWSIoTErrorCertificateState`, `AWSIoTErrorTransferConflict`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTTransferCertificateRequest + @see AWSIoTTransferCertificateResponse + */ +- (AWSTask *)transferCertificate:(AWSIoTTransferCertificateRequest *)request; + +/** +

Updates the status of the specified certificate. This operation is idempotent.

Moving a cert from the ACTIVE state (including REVOKED) will NOT disconnect currently-connected devices, although these devices will be unable to reconnect.

The ACTIVE state is required to authenticate devices connecting to AWS IoT using a certificate.

+ + @param request A container for the necessary parameters to execute the UpdateCertificate service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will be `nil`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorResourceNotFound`, `AWSIoTErrorCertificateState`, `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`. + + @see AWSIoTUpdateCertificateRequest + */ +- (AWSTask *)updateCertificate:(AWSIoTUpdateCertificateRequest *)request; + +/** +

Updates the data for a thing.

+ + @param request A container for the necessary parameters to execute the UpdateThing service method. + + @return An instance of `AWSTask`. On successful execution, `task.result` will contain an instance of `AWSIoTUpdateThingResponse`. On failed execution, `task.error` may contain an `NSError` with `AWSIoTErrorDomain` domain and the following error code: `AWSIoTErrorInvalidRequest`, `AWSIoTErrorThrottling`, `AWSIoTErrorUnauthorized`, `AWSIoTErrorServiceUnavailable`, `AWSIoTErrorInternalFailure`, `AWSIoTErrorResourceNotFound`. + + @see AWSIoTUpdateThingRequest + @see AWSIoTUpdateThingResponse + */ +- (AWSTask *)updateThing:(AWSIoTUpdateThingRequest *)request; + +@end + +NS_ASSUME_NONNULL_END diff --git a/AWSIoT/AWSIoTService.m b/AWSIoT/AWSIoTService.m new file mode 100644 index 00000000000..3e0afda2dc7 --- /dev/null +++ b/AWSIoT/AWSIoTService.m @@ -0,0 +1,615 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTService.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import "AWSIoTResources.h" + +@interface AWSIoTResponseSerializer : AWSJSONResponseSerializer + +@end + +@implementation AWSIoTResponseSerializer + +#pragma mark - Service errors + +static NSDictionary *errorCodeDictionary = nil; ++ (void)initialize { + errorCodeDictionary = @{ + @"IncompleteSignature" : @(AWSIoTErrorIncompleteSignature), + @"InvalidClientTokenId" : @(AWSIoTErrorInvalidClientTokenId), + @"MissingAuthenticationToken" : @(AWSIoTErrorMissingAuthenticationToken), + @"CertificateStateException" : @(AWSIoTErrorCertificateState), + @"DeleteConflictException" : @(AWSIoTErrorDeleteConflict), + @"InternalException" : @(AWSIoTErrorInternal), + @"InternalFailureException" : @(AWSIoTErrorInternalFailure), + @"InvalidRequestException" : @(AWSIoTErrorInvalidRequest), + @"LimitExceededException" : @(AWSIoTErrorLimitExceeded), + @"MalformedPolicyException" : @(AWSIoTErrorMalformedPolicy), + @"ResourceAlreadyExistsException" : @(AWSIoTErrorResourceAlreadyExists), + @"ResourceNotFoundException" : @(AWSIoTErrorResourceNotFound), + @"ServiceUnavailableException" : @(AWSIoTErrorServiceUnavailable), + @"SqlParseException" : @(AWSIoTErrorSqlParse), + @"ThrottlingException" : @(AWSIoTErrorThrottling), + @"TransferAlreadyCompletedException" : @(AWSIoTErrorTransferAlreadyCompleted), + @"TransferConflictException" : @(AWSIoTErrorTransferConflict), + @"UnauthorizedException" : @(AWSIoTErrorUnauthorized), + @"VersionsLimitExceededException" : @(AWSIoTErrorVersionsLimitExceeded), + }; +} + +- (id)responseObjectForResponse:(NSHTTPURLResponse *)response + originalRequest:(NSURLRequest *)originalRequest + currentRequest:(NSURLRequest *)currentRequest + data:(id)data + error:(NSError *__autoreleasing *)error { + id responseObject = [super responseObjectForResponse:response + originalRequest:originalRequest + currentRequest:currentRequest + data:data + error:error]; + if (!*error && [responseObject isKindOfClass:[NSDictionary class]]) { + NSString *errorTypeStr = [[response allHeaderFields] objectForKey:@"x-amzn-ErrorType"]; + NSString *errorTypeHeader = [[errorTypeStr componentsSeparatedByString:@":"] firstObject]; + + if ([errorTypeStr length] > 0 && errorTypeHeader) { + if (errorCodeDictionary[errorTypeHeader]) { + if (error) { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey : [responseObject objectForKey:@"message"]?[responseObject objectForKey:@"message"]:[NSNull null], NSLocalizedFailureReasonErrorKey: errorTypeStr}; + *error = [NSError errorWithDomain:AWSIoTErrorDomain + code:[[errorCodeDictionary objectForKey:errorTypeHeader] integerValue] + userInfo:userInfo]; + } + return responseObject; + } else if (errorTypeHeader) { + if (error) { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey : [responseObject objectForKey:@"message"]?[responseObject objectForKey:@"message"]:[NSNull null], NSLocalizedFailureReasonErrorKey: errorTypeStr}; + *error = [NSError errorWithDomain:AWSIoTErrorDomain + code:AWSIoTErrorUnknown + userInfo:userInfo]; + } + return responseObject; + } + } + + if (self.outputClass) { + responseObject = [AWSMTLJSONAdapter modelOfClass:self.outputClass + fromJSONDictionary:responseObject + error:error]; + } + } + + return responseObject; +} + +@end + +@interface AWSIoTRequestRetryHandler : AWSURLRequestRetryHandler + +@end + +@implementation AWSIoTRequestRetryHandler + +- (AWSNetworkingRetryType)shouldRetry:(uint32_t)currentRetryCount + response:(NSHTTPURLResponse *)response + data:(NSData *)data + error:(NSError *)error { + AWSNetworkingRetryType retryType = [super shouldRetry:currentRetryCount + response:response + data:data + error:error]; + if(retryType == AWSNetworkingRetryTypeShouldNotRetry + && [error.domain isEqualToString:AWSIoTErrorDomain] + && currentRetryCount < self.maxRetryCount) { + switch (error.code) { + case AWSIoTErrorIncompleteSignature: + case AWSIoTErrorInvalidClientTokenId: + case AWSIoTErrorMissingAuthenticationToken: + retryType = AWSNetworkingRetryTypeShouldRefreshCredentialsAndRetry; + break; + + default: + break; + } + } + + return retryType; +} + +@end + +@interface AWSRequest() + +@property (nonatomic, strong) AWSNetworkingRequest *internalRequest; + +@end + +@interface AWSIoT() + +@property (nonatomic, strong) AWSNetworking *networking; +@property (nonatomic, strong) AWSServiceConfiguration *configuration; +@property (nonatomic, strong) AWSEndpoint *endpoint; + +@end + +@interface AWSServiceConfiguration() + +@property (nonatomic, strong) AWSEndpoint *endpoint; + +@end + +@implementation AWSIoT + +static AWSSynchronizedMutableDictionary *_serviceClients = nil; + ++ (instancetype)defaultIoT { + if (![AWSServiceManager defaultServiceManager].defaultServiceConfiguration) { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`defaultServiceConfiguration` is `nil`. You need to set it before using this method." + userInfo:nil]; + } + + static AWSIoT *_defaultIoT = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _defaultIoT = [[AWSIoT alloc] initWithConfiguration:AWSServiceManager.defaultServiceManager.defaultServiceConfiguration]; + }); + + return _defaultIoT; +} + ++ (instancetype)registerIoTWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _serviceClients = [AWSSynchronizedMutableDictionary new]; + }); + + [_serviceClients setObject:[[AWSIoT alloc] initWithConfiguration:configuration] + forKey:key]; + return [_serviceClients objectForKey:key]; +} + ++ (instancetype)IoTForKey:(NSString *)key { + return [_serviceClients objectForKey:key]; +} + ++ (void)removeIoTForKey:(NSString *)key { + [_serviceClients removeObjectForKey:key]; +} + +- (instancetype)init { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`- init` is not a valid initializer. Use `+ defaultIoT` or `+ IoTForKey:` instead." + userInfo:nil]; + return nil; +} + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration { + if (self = [super init]) { + _configuration = [configuration copy]; + + _configuration.endpoint = [[AWSEndpoint alloc] initWithRegion:_configuration.regionType + service:AWSServiceIoT + useUnsafeURL:NO]; + + AWSSignatureV4Signer *signer = [[AWSSignatureV4Signer alloc] initWithCredentialsProvider:_configuration.credentialsProvider + endpoint:_configuration.endpoint]; + + AWSNetworkingRequestInterceptor *baseInterceptor = [[AWSNetworkingRequestInterceptor alloc] initWithUserAgent:_configuration.userAgent]; + _configuration.requestInterceptors = @[baseInterceptor, signer]; + + _configuration.baseURL = _configuration.endpoint.URL; + _configuration.requestSerializer = [AWSJSONRequestSerializer new]; + _configuration.retryHandler = [[AWSIoTRequestRetryHandler alloc] initWithMaximumRetryCount:_configuration.maxRetryCount]; + _configuration.headers = @{@"Content-Type" : @"application/x-amz-json-1.0"}; + + _networking = [[AWSNetworking alloc] initWithConfiguration:_configuration]; + } + + return self; +} + +- (AWSTask *)invokeRequest:(AWSRequest *)request + HTTPMethod:(AWSHTTPMethod)HTTPMethod + URLString:(NSString *) URLString + targetPrefix:(NSString *)targetPrefix + operationName:(NSString *)operationName + outputClass:(Class)outputClass { + if (!request) { + request = [AWSRequest new]; + } + + AWSNetworkingRequest *networkingRequest = request.internalRequest; + if (request) { + networkingRequest.parameters = [[AWSMTLJSONAdapter JSONDictionaryFromModel:request] aws_removeNullValues]; + } else { + networkingRequest.parameters = @{}; + } + + + NSMutableDictionary *headers = [NSMutableDictionary new]; + + networkingRequest.headers = headers; + networkingRequest.HTTPMethod = HTTPMethod; + networkingRequest.requestSerializer = [[AWSJSONRequestSerializer alloc] initWithJSONDefinition:[[AWSIoTResources sharedInstance] JSONObject] + actionName:operationName]; + networkingRequest.responseSerializer = [[AWSIoTResponseSerializer alloc] initWithJSONDefinition:[[AWSIoTResources sharedInstance] JSONObject] + actionName:operationName + outputClass:outputClass]; + return [self.networking sendRequest:networkingRequest]; +} + +#pragma mark - Service method + +- (AWSTask *)acceptCertificateTransfer:(AWSIoTAcceptCertificateTransferRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPATCH + URLString:@"/accept-certificate-transfer/{certificateId}" + targetPrefix:@"" + operationName:@"AcceptCertificateTransfer" + outputClass:nil]; +} + +- (AWSTask *)attachPrincipalPolicy:(AWSIoTAttachPrincipalPolicyRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPUT + URLString:@"/principal-policies/{policyName}" + targetPrefix:@"" + operationName:@"AttachPrincipalPolicy" + outputClass:nil]; +} + +- (AWSTask *)attachThingPrincipal:(AWSIoTAttachThingPrincipalRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPUT + URLString:@"/things/{thingName}/principals" + targetPrefix:@"" + operationName:@"AttachThingPrincipal" + outputClass:[AWSIoTAttachThingPrincipalResponse class]]; +} + +- (AWSTask *)cancelCertificateTransfer:(AWSIoTCancelCertificateTransferRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPATCH + URLString:@"/cancel-certificate-transfer/{certificateId}" + targetPrefix:@"" + operationName:@"CancelCertificateTransfer" + outputClass:nil]; +} + +- (AWSTask *)createCertificateFromCsr:(AWSIoTCreateCertificateFromCsrRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/certificates" + targetPrefix:@"" + operationName:@"CreateCertificateFromCsr" + outputClass:[AWSIoTCreateCertificateFromCsrResponse class]]; +} + +- (AWSTask *)createKeysAndCertificate:(AWSIoTCreateKeysAndCertificateRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/keys-and-certificate" + targetPrefix:@"" + operationName:@"CreateKeysAndCertificate" + outputClass:[AWSIoTCreateKeysAndCertificateResponse class]]; +} + +- (AWSTask *)createPolicy:(AWSIoTCreatePolicyRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/policies/{policyName}" + targetPrefix:@"" + operationName:@"CreatePolicy" + outputClass:[AWSIoTCreatePolicyResponse class]]; +} + +- (AWSTask *)createPolicyVersion:(AWSIoTCreatePolicyVersionRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/policies/{policyName}/version" + targetPrefix:@"" + operationName:@"CreatePolicyVersion" + outputClass:[AWSIoTCreatePolicyVersionResponse class]]; +} + +- (AWSTask *)createThing:(AWSIoTCreateThingRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/things/{thingName}" + targetPrefix:@"" + operationName:@"CreateThing" + outputClass:[AWSIoTCreateThingResponse class]]; +} + +- (AWSTask *)createTopicRule:(AWSIoTCreateTopicRuleRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/rules/{ruleName}" + targetPrefix:@"" + operationName:@"CreateTopicRule" + outputClass:nil]; +} + +- (AWSTask *)deleteCertificate:(AWSIoTDeleteCertificateRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodDELETE + URLString:@"/certificates/{certificateId}" + targetPrefix:@"" + operationName:@"DeleteCertificate" + outputClass:nil]; +} + +- (AWSTask *)deletePolicy:(AWSIoTDeletePolicyRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodDELETE + URLString:@"/policies/{policyName}" + targetPrefix:@"" + operationName:@"DeletePolicy" + outputClass:nil]; +} + +- (AWSTask *)deletePolicyVersion:(AWSIoTDeletePolicyVersionRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodDELETE + URLString:@"/policies/{policyName}/version/{policyVersionId}" + targetPrefix:@"" + operationName:@"DeletePolicyVersion" + outputClass:nil]; +} + +- (AWSTask *)deleteThing:(AWSIoTDeleteThingRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodDELETE + URLString:@"/things/{thingName}" + targetPrefix:@"" + operationName:@"DeleteThing" + outputClass:[AWSIoTDeleteThingResponse class]]; +} + +- (AWSTask *)deleteTopicRule:(AWSIoTDeleteTopicRuleRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodDELETE + URLString:@"/rules/{ruleName}" + targetPrefix:@"" + operationName:@"DeleteTopicRule" + outputClass:nil]; +} + +- (AWSTask *)describeCertificate:(AWSIoTDescribeCertificateRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/certificates/{certificateId}" + targetPrefix:@"" + operationName:@"DescribeCertificate" + outputClass:[AWSIoTDescribeCertificateResponse class]]; +} + +- (AWSTask *)describeEndpoint:(AWSIoTDescribeEndpointRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/endpoint" + targetPrefix:@"" + operationName:@"DescribeEndpoint" + outputClass:[AWSIoTDescribeEndpointResponse class]]; +} + +- (AWSTask *)describeThing:(AWSIoTDescribeThingRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/things/{thingName}" + targetPrefix:@"" + operationName:@"DescribeThing" + outputClass:[AWSIoTDescribeThingResponse class]]; +} + +- (AWSTask *)detachPrincipalPolicy:(AWSIoTDetachPrincipalPolicyRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodDELETE + URLString:@"/principal-policies/{policyName}" + targetPrefix:@"" + operationName:@"DetachPrincipalPolicy" + outputClass:nil]; +} + +- (AWSTask *)detachThingPrincipal:(AWSIoTDetachThingPrincipalRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodDELETE + URLString:@"/things/{thingName}/principals" + targetPrefix:@"" + operationName:@"DetachThingPrincipal" + outputClass:[AWSIoTDetachThingPrincipalResponse class]]; +} + +- (AWSTask *)getLoggingOptions:(AWSIoTGetLoggingOptionsRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/loggingOptions" + targetPrefix:@"" + operationName:@"GetLoggingOptions" + outputClass:[AWSIoTGetLoggingOptionsResponse class]]; +} + +- (AWSTask *)getPolicy:(AWSIoTGetPolicyRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/policies/{policyName}" + targetPrefix:@"" + operationName:@"GetPolicy" + outputClass:[AWSIoTGetPolicyResponse class]]; +} + +- (AWSTask *)getPolicyVersion:(AWSIoTGetPolicyVersionRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/policies/{policyName}/version/{policyVersionId}" + targetPrefix:@"" + operationName:@"GetPolicyVersion" + outputClass:[AWSIoTGetPolicyVersionResponse class]]; +} + +- (AWSTask *)getTopicRule:(AWSIoTGetTopicRuleRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/rules/{ruleName}" + targetPrefix:@"" + operationName:@"GetTopicRule" + outputClass:[AWSIoTGetTopicRuleResponse class]]; +} + +- (AWSTask *)listCertificates:(AWSIoTListCertificatesRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/certificates" + targetPrefix:@"" + operationName:@"ListCertificates" + outputClass:[AWSIoTListCertificatesResponse class]]; +} + +- (AWSTask *)listPolicies:(AWSIoTListPoliciesRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/policies" + targetPrefix:@"" + operationName:@"ListPolicies" + outputClass:[AWSIoTListPoliciesResponse class]]; +} + +- (AWSTask *)listPolicyVersions:(AWSIoTListPolicyVersionsRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/policies/{policyName}/version" + targetPrefix:@"" + operationName:@"ListPolicyVersions" + outputClass:[AWSIoTListPolicyVersionsResponse class]]; +} + +- (AWSTask *)listPrincipalPolicies:(AWSIoTListPrincipalPoliciesRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/principal-policies" + targetPrefix:@"" + operationName:@"ListPrincipalPolicies" + outputClass:[AWSIoTListPrincipalPoliciesResponse class]]; +} + +- (AWSTask *)listPrincipalThings:(AWSIoTListPrincipalThingsRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/principals/things" + targetPrefix:@"" + operationName:@"ListPrincipalThings" + outputClass:[AWSIoTListPrincipalThingsResponse class]]; +} + +- (AWSTask *)listThingPrincipals:(AWSIoTListThingPrincipalsRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/things/{thingName}/principals" + targetPrefix:@"" + operationName:@"ListThingPrincipals" + outputClass:[AWSIoTListThingPrincipalsResponse class]]; +} + +- (AWSTask *)listThings:(AWSIoTListThingsRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/things" + targetPrefix:@"" + operationName:@"ListThings" + outputClass:[AWSIoTListThingsResponse class]]; +} + +- (AWSTask *)listTopicRules:(AWSIoTListTopicRulesRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodGET + URLString:@"/rules" + targetPrefix:@"" + operationName:@"ListTopicRules" + outputClass:[AWSIoTListTopicRulesResponse class]]; +} + +- (AWSTask *)rejectCertificateTransfer:(AWSIoTRejectCertificateTransferRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPATCH + URLString:@"/reject-certificate-transfer/{certificateId}" + targetPrefix:@"" + operationName:@"RejectCertificateTransfer" + outputClass:nil]; +} + +- (AWSTask *)replaceTopicRule:(AWSIoTReplaceTopicRuleRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPATCH + URLString:@"/rules/{ruleName}" + targetPrefix:@"" + operationName:@"ReplaceTopicRule" + outputClass:nil]; +} + +- (AWSTask *)setDefaultPolicyVersion:(AWSIoTSetDefaultPolicyVersionRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPATCH + URLString:@"/policies/{policyName}/version/{policyVersionId}" + targetPrefix:@"" + operationName:@"SetDefaultPolicyVersion" + outputClass:nil]; +} + +- (AWSTask *)setLoggingOptions:(AWSIoTSetLoggingOptionsRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPOST + URLString:@"/loggingOptions" + targetPrefix:@"" + operationName:@"SetLoggingOptions" + outputClass:nil]; +} + +- (AWSTask *)transferCertificate:(AWSIoTTransferCertificateRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPATCH + URLString:@"/transfer-certificate/{certificateId}" + targetPrefix:@"" + operationName:@"TransferCertificate" + outputClass:[AWSIoTTransferCertificateResponse class]]; +} + +- (AWSTask *)updateCertificate:(AWSIoTUpdateCertificateRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPUT + URLString:@"/certificates/{certificateId}" + targetPrefix:@"" + operationName:@"UpdateCertificate" + outputClass:nil]; +} + +- (AWSTask *)updateThing:(AWSIoTUpdateThingRequest *)request { + return [self invokeRequest:request + HTTPMethod:AWSHTTPMethodPATCH + URLString:@"/things/{thingName}" + targetPrefix:@"" + operationName:@"UpdateThing" + outputClass:[AWSIoTUpdateThingResponse class]]; +} + +@end diff --git a/AWSIoT/Internal/AWSIoTCSR.h b/AWSIoT/Internal/AWSIoTCSR.h new file mode 100644 index 00000000000..8f809af8a45 --- /dev/null +++ b/AWSIoT/Internal/AWSIoTCSR.h @@ -0,0 +1,27 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the \"License\"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the \"license\" file accompanying this file. This file is distributed + on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import + +@interface AWSIoTCSR : NSObject + +- (instancetype)initWithCommonName:(NSString *)commonName + countryName:(NSString *)countryName + organizationName:(NSString *)organizationName + organizationalUnitName:(NSString *)organizationName; + +- (NSData *)generateCSRForCertificate:(NSString *)certificateId; + +@end diff --git a/AWSIoT/Internal/AWSIoTCSR.m b/AWSIoT/Internal/AWSIoTCSR.m new file mode 100644 index 00000000000..0dc5633c5e6 --- /dev/null +++ b/AWSIoT/Internal/AWSIoTCSR.m @@ -0,0 +1,278 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the \"License\"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the \"license\" file accompanying this file. This file is distributed + on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTCSR.h" +#import "AWSIOTService.h" +#import "AWSIoTKeychain.h" + +unsigned char seqTag = 0x30; +unsigned char setTag = 0x31; + +@interface AWSIoTCSR () { + NSString* _commonName; + NSString* _countryName; + NSString* _organizationName; + NSString* _organizationalUnitName; + + NSData *_publicKeyBits; +} + +@end + +@implementation AWSIoTCSR + + +- (instancetype)init { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"`- init` is not a valid initializer. Use `+ defaultIOT` instead." + userInfo:nil]; + return nil; +} + +- (instancetype)initWithCommonName:(NSString*)commonName countryName:(NSString*)countryName organizationName:(NSString*)organizationName organizationalUnitName:(NSString*)organizationalUnitName { + + if (self = [super init]) { + _commonName = commonName; + _countryName = countryName; + _organizationName = organizationName; + _organizationalUnitName = organizationalUnitName; + } + + return self; +} + +- (NSData*)generateCSRForCertificate:(NSString*)certificateId { + + if (!certificateId) { + return nil; + } + + NSString *publicTag = [AWSIoTKeychain.publicKeyTag stringByAppendingString:certificateId]; + NSString *privateTag = [AWSIoTKeychain.privateKeyTag stringByAppendingString:certificateId]; + + _publicKeyBits = [AWSIoTKeychain getPublicKeyBits:publicTag]; + SecKeyRef privateKeyRef = [AWSIoTKeychain getPrivateKeyRef:privateTag]; + + if (!_publicKeyBits || !privateKeyRef) { + return nil; + } + + NSMutableData * certRequestData = [self createCertificateRequestData]; + + CC_SHA1_CTX SHA1Struct; + CC_SHA1_Init(&SHA1Struct); + CC_SHA1_Update(&SHA1Struct, [certRequestData mutableBytes], (unsigned int)[certRequestData length]); + unsigned char SHA1Digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1_Final(SHA1Digest, &SHA1Struct); + + unsigned char sig[256]; + size_t sigLen = sizeof(sig); + OSStatus sanityCheck = SecKeyRawSign(privateKeyRef, kSecPaddingPKCS1SHA1, SHA1Digest, sizeof(SHA1Digest), sig, &sigLen); + if (sanityCheck != noErr) { + return nil; + } + + NSMutableData * scr = [[NSMutableData alloc] initWithData:certRequestData]; + unsigned char tag[] = {0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 1, 1, 5, 0x05, 0x00}; + [scr appendBytes:tag length:sizeof(tag)]; + + NSMutableData * signdata = [NSMutableData new]; + unsigned char null = 0; + [signdata appendBytes:&null length:1]; + [signdata appendBytes:sig length:sigLen]; + + char strBitType = 0x03; + [scr appendBytes:&strBitType length:1]; + [self appendLength:[signdata length] intoData:scr]; + [scr appendData:signdata]; + + [self addByte:seqTag intoData:scr]; + + return [scr copy]; +} + + +- (NSMutableData*)createCertificateRequestData { + + NSMutableData *certRequestData = [NSMutableData new]; + + [self addVersion:certRequestData]; + + [certRequestData appendData:[self createCertInformation]]; + + [certRequestData appendData:[self createPublicKeyDataForCSR]]; + + unsigned char attributes[2] = {0xA0, 0x00}; + [certRequestData appendBytes:attributes length:sizeof(attributes)]; + [self addByte:seqTag intoData:certRequestData]; + + return certRequestData; +} + +- (void)addVersion:(NSMutableData*)certRequestData { + unsigned char version[3] = {0x02, 0x01, 0x00}; + [certRequestData appendBytes:version length:sizeof(version)]; +} + +- (NSData*)createCertInformation { + NSMutableData *certInformationData = [NSMutableData new]; + + if (_countryName) { + unsigned char countryType[5] = {0x06, 0x03, 0x55, 0x04, 0x06}; + [self appendInfo:_countryName forType:countryType intoData:certInformationData]; + } + if (_organizationName) { + unsigned char organizationType[5] = {0x06, 0x03, 0x55, 0x04, 0x0A}; + [self appendInfo:_organizationName forType:organizationType intoData:certInformationData]; + } + if (_organizationalUnitName) { + unsigned char organizationalUnitType[5] = {0x06, 0x03, 0x55, 0x04, 0x0B}; + [self appendInfo:_organizationalUnitName forType:organizationalUnitType intoData:certInformationData]; + } + if (_commonName) { + unsigned char commonType[5] = {0x06, 0x03, 0x55, 0x04, 0x03}; + [self appendInfo:_commonName forType:commonType intoData:certInformationData]; + } + + [self addByte:seqTag intoData:certInformationData]; + return [certInformationData copy]; +} + +- (void)appendInfo:(NSString*)info forType:(unsigned char[5])type intoData:(NSMutableData *)data { + NSMutableData *infoData = [NSMutableData new]; + [infoData appendBytes:type length:5]; + char stringTag = 0x0C; + [infoData appendBytes:&stringTag length:1]; + [self appendLength:[info lengthOfBytesUsingEncoding:NSUTF8StringEncoding] intoData:infoData]; + [infoData appendData:[info dataUsingEncoding:NSUTF8StringEncoding]]; + + [self addByte:seqTag intoData:infoData]; + [self addByte:setTag intoData:infoData]; + + [data appendData:infoData]; +} + +- (void)addByte:(unsigned char)byte intoData:(NSMutableData *)data { + NSMutableData* newData = [NSMutableData dataWithBytes:&byte length:1]; + [self appendLength:[data length] intoData:newData]; + [newData appendData:data]; + [data setData:newData]; +} + +- (void)appendLength:(NSInteger)length intoData:(NSMutableData *)data { + if (length < 128) { + unsigned char d[1] = {length}; + [data appendBytes:&d length:1]; + } else if (length < 0x100) { + unsigned char d[2] = {0x81, length & 0xFF}; + [data appendBytes:&d length:2]; + } else if (length < 0x8000) { + unsigned char d[3] = {0x82, (length & 0xFF00) >> 8, length & 0xFF}; + [data appendBytes:&d length:3]; + } +} + +- (NSData *)createPublicKeyDataForCSR { + + NSMutableData *publicKeyData = [NSMutableData new]; + + unsigned char tag[] = {0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00}; + [publicKeyData appendBytes:tag length:sizeof(tag)]; + [self addByte:seqTag intoData:publicKeyData]; + + NSMutableData *ASNKeyData = [NSMutableData new]; + + char integerTag = 0x02; + [ASNKeyData appendBytes:&integerTag length:1]; + NSData *publicKeyMod = [self getPublicKeyMod]; + [self appendLength:[publicKeyMod length] intoData:ASNKeyData]; + [ASNKeyData appendData:publicKeyMod]; + + NSData *publicKeyExp = [self getPublicKeyExp]; + [ASNKeyData appendBytes:&integerTag length:1]; + [self appendLength:[publicKeyExp length] intoData:ASNKeyData]; + [ASNKeyData appendData:publicKeyExp]; + + [self addByte:seqTag intoData:ASNKeyData]; + + NSMutableData* newData = [NSMutableData new]; + unsigned char byte = 0x00; + [newData appendBytes:&byte length:1]; + [newData appendData:ASNKeyData]; + [ASNKeyData setData:newData]; + + char strBitType = 0x03; + [publicKeyData appendBytes:&strBitType length:1]; + [self appendLength:[ASNKeyData length] intoData:publicKeyData]; + [publicKeyData appendData:ASNKeyData]; + + [self addByte:seqTag intoData:publicKeyData]; + + return [publicKeyData copy]; +} + + +- (NSData*)getPublicKeyExp { + NSData* pk = _publicKeyBits; + if (pk == NULL) return NULL; + + int iterator = 0; + + iterator++; // TYPE - bit stream - mod + exp + [self derEncodingGetSizeFrom:pk at:&iterator]; // Total size + + iterator++; // TYPE - bit stream mod + int mod_size = [self derEncodingGetSizeFrom:pk at:&iterator]; + iterator += mod_size; + + iterator++; // TYPE - bit stream exp + int exp_size = [self derEncodingGetSizeFrom:pk at:&iterator]; + + return [pk subdataWithRange:NSMakeRange(iterator, exp_size)]; +} + +- (NSData*)getPublicKeyMod { + NSData *pk = _publicKeyBits; + if (pk == NULL) return NULL; + + int iterator = 0; + + iterator++; // TYPE - bit stream - mod + exp + [self derEncodingGetSizeFrom:pk at:&iterator]; // Total size + + iterator++; // TYPE - bit stream mod + int mod_size = [self derEncodingGetSizeFrom:pk at:&iterator]; + + return [pk subdataWithRange:NSMakeRange(iterator, mod_size)]; +} + +- (int)derEncodingGetSizeFrom:(NSData*)buf at:(int*)iterator { + const uint8_t* data = [buf bytes]; + int itr = *iterator; + int num_bytes = 1; + int ret = 0; + + if (data[itr] > 0x80) { + num_bytes = data[itr] - 0x80; + itr++; + } + + for (int i = 0 ; i < num_bytes; i++) ret = (ret * 0x100) + data[itr + i]; + + *iterator = itr + num_bytes; + return ret; +} + +@end diff --git a/AWSIoT/Internal/AWSIoTKeychain.h b/AWSIoT/Internal/AWSIoTKeychain.h new file mode 100644 index 00000000000..cd3679d51a3 --- /dev/null +++ b/AWSIoT/Internal/AWSIoTKeychain.h @@ -0,0 +1,54 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import + +#import +#import +#import + +FOUNDATION_EXPORT NSString *const AWSIoTKeychainStartPrivateKeyTag; +FOUNDATION_EXPORT NSString *const AWSIoTKeychainEndPrivateKeyTag; + +FOUNDATION_EXPORT NSString *const AWSIoTKeychainStartCertKeyTag; +FOUNDATION_EXPORT NSString *const AWSIoTKeychainEndCertKeyTag; + +@interface AWSIoTKeychain : NSObject + ++ (NSString *)publicKeyTag; ++ (NSString *)privateKeyTag; ++ (NSString *)certTag; + ++ (NSString *)base64Encode:(NSData *)data; ++ (NSData *)base64Decode:(NSString *)str; ++ (NSData *)base64DecodeWithIgnoreUnknownSymbols:(NSString *)str; + ++ (BOOL)generateKeyPairWithPublicTag:(NSString *)publicTag privateTag:(NSString *)privateTag; ++ (BOOL)deleteAsymmetricKeysWithPublicTag:(NSString *)publicTag privateTag:(NSString *)privateTag; ++ (BOOL)isValidCertificate:(NSString *)tag; ++ (BOOL)addCertificateToKeychain:(NSString *)cert; ++ (BOOL)addCertificate:(NSData *)cert; ++ (BOOL)removeCertificate; ++ (SecKeyRef)getPublicKeyRef:(NSString *)tag; ++ (NSData *)getPublicKeyBits:(NSString *)tag; ++ (SecKeyRef)getPrivateKeyRef:(NSString *)tag; ++ (NSData *)getPrivateKeyBits:(NSString *)tag; ++ (SecIdentityRef)getIdentityRef:(NSString *)tag; ++ (BOOL)addPublicKeyRef:(SecKeyRef)pubkeyRef tag:(NSString *)tag; ++ (BOOL)addPublicKey:(NSData *)pubkey tag:(NSString *)tag; ++ (BOOL)addPrivateKeyRef:(SecKeyRef)privkeyRef tag:(NSString *)tag; ++ (BOOL)addPrivateKey:(NSData *)privkey tag:(NSString *)tag; + +@end diff --git a/AWSIoT/Internal/AWSIoTKeychain.m b/AWSIoT/Internal/AWSIoTKeychain.m new file mode 100644 index 00000000000..653e7770d5b --- /dev/null +++ b/AWSIoT/Internal/AWSIoTKeychain.m @@ -0,0 +1,398 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTKeychain.h" + +NSString *const AWSIoTKeychainStartPrivateKeyTag = @"-----BEGIN RSA PRIVATE KEY-----\n"; +NSString *const AWSIoTKeychainEndPrivateKeyTag = @"\n-----END RSA PRIVATE KEY-----"; + +NSString *const AWSIoTKeychainStartCertKeyTag = @"-----BEGIN CERTIFICATE-----\n"; +NSString *const AWSIoTKeychainEndCertKeyTag = @"\n-----END CERTIFICATE-----"; + +@implementation AWSIoTKeychain + ++ (NSString*)publicKeyTag { + return [NSString stringWithFormat:@"%@.RSAPublicTag.",[[NSBundle mainBundle] bundleIdentifier]]; +} + ++ (NSString*)privateKeyTag { + return [NSString stringWithFormat:@"%@.RSAPrivateTag.",[[NSBundle mainBundle] bundleIdentifier]]; +} + ++ (NSString*)certTag { + return [NSString stringWithFormat:@"%@.RSACertTag.",[[NSBundle mainBundle] bundleIdentifier]]; +} + ++ (NSString*)base64Encode:(NSData*)data { + return [data base64EncodedStringWithOptions:kNilOptions]; +} + ++ (NSData*)base64Decode:(NSString*)str { + return [[NSData alloc] initWithBase64EncodedString:str options:kNilOptions]; +} + ++ (NSData*)base64DecodeWithIgnoreUnknownSymbols:(NSString*)str { + return [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters]; +} + ++ (BOOL)generateKeyPairWithPublicTag:(NSString*)publicTag privateTag:(NSString*)privateTag { + OSStatus sanityCheck = noErr; + SecKeyRef publicKeyRef = NULL; + SecKeyRef privateKeyRef = NULL; + + NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init]; + NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init]; + NSMutableDictionary * keyPairAttr = [[NSMutableDictionary alloc] init]; + + [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecAttrIsPermanent]; + [privateKeyAttr setObject:privateTag forKey:(id)kSecAttrApplicationTag]; + + [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecAttrIsPermanent]; + [publicKeyAttr setObject:publicTag forKey:(id)kSecAttrApplicationTag]; + + [keyPairAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:2048] forKey:(id)kSecAttrKeySizeInBits]; + + [keyPairAttr setObject:privateKeyAttr forKey:(id)kSecPrivateKeyAttrs]; + [keyPairAttr setObject:publicKeyAttr forKey:(id)kSecPublicKeyAttrs]; + + sanityCheck = SecKeyGeneratePair((CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef); + if (sanityCheck != noErr) { + NSLog(@"generateKeyPair finished with error: %d", (int)sanityCheck); + return NO; + } + + if (publicKeyRef == NULL) { + NSLog(@"generateKeyPair missed public key"); + return NO; + } + + if (privateKeyRef == NULL) { + NSLog(@"generateKeyPair missed private key"); + return NO; + } + + NSLog(@"generateKeyPair successfully generated"); + + return YES; +} + ++ (BOOL)deleteAsymmetricKeysWithPublicTag:(NSString*)publicTag privateTag:(NSString*)privateTag { + + BOOL status = YES; + + OSStatus sanityCheck = noErr; + NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init]; + NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init]; + + [queryPublicKey setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [queryPublicKey setObject:publicTag forKey:(id)kSecAttrApplicationTag]; + [queryPublicKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + + [queryPrivateKey setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [queryPrivateKey setObject:privateTag forKey:(id)kSecAttrApplicationTag]; + [queryPrivateKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + + sanityCheck = SecItemDelete((CFDictionaryRef)queryPrivateKey); + if (sanityCheck != noErr) { + if (sanityCheck == errSecItemNotFound) { + NSLog(@"Error removing private key errSecItemNotFound"); + } else { + NSLog(@"Error removing private key, OSStatus == %d.", (int)sanityCheck); + status = NO; + } + } + + sanityCheck = SecItemDelete((CFDictionaryRef)queryPublicKey); + if (sanityCheck != noErr) { + if (sanityCheck == errSecItemNotFound) { + NSLog(@"Error removing public key errSecItemNotFound"); + } else { + NSLog(@"Error removing public key, OSStatus == %d.", (int)sanityCheck); + status = NO; + } + } + + return status; +} + ++ (BOOL)isValidCertificate:(NSString*)tag { + + SecIdentityRef identityRef = [AWSIoTKeychain getIdentityRef:tag]; + if (identityRef) { + SecCertificateRef cert = NULL; + OSStatus status = SecIdentityCopyCertificate(identityRef, &cert); + if (status == noErr) { + return YES; + } else { + NSLog(@"SecIdentityCopyCertificate failed [%d]", (int)status); + } + } + + return NO; +} + ++ (BOOL)addCertificateToKeychain:(NSString*)cert { + + if ([cert rangeOfString:AWSIoTKeychainStartCertKeyTag].location != NSNotFound) { + cert = [cert substringFromIndex:AWSIoTKeychainStartCertKeyTag.length]; + } + if ([cert rangeOfString:AWSIoTKeychainEndCertKeyTag].location != NSNotFound) { + cert = [cert substringToIndex:(cert.length - AWSIoTKeychainEndCertKeyTag.length)]; + } + + NSData *certData = [AWSIoTKeychain base64DecodeWithIgnoreUnknownSymbols:cert]; + return [AWSIoTKeychain addCertificate:certData]; +} + ++ (BOOL)addCertificate:(NSData*)cert { + SecCertificateRef certRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)cert); + if (certRef == NULL) { + NSLog(@"Error create Sec Certificate from data"); + return NO; + } + + NSMutableDictionary * queryCertificate = [[NSMutableDictionary alloc] init]; + + [queryCertificate setObject:(id)kSecClassCertificate forKey:(id)kSecClass]; + [queryCertificate setObject:[AWSIoTKeychain certTag] forKey:(id)kSecAttrLabel]; + [queryCertificate setObject:(__bridge id)certRef forKey:(id)kSecValueRef]; + + OSStatus sanityCheck = SecItemAdd((CFDictionaryRef)queryCertificate, nil); + if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)) { + NSLog(@"add certificate to keychain with error: %d", (int)sanityCheck); + return NO; + } + + return YES; +} + ++ (BOOL)removeCertificate { + + NSMutableDictionary * queryCertificate = [[NSMutableDictionary alloc] init]; + + [queryCertificate setObject:(id)kSecClassCertificate forKey:(id)kSecClass]; + [queryCertificate setObject:[AWSIoTKeychain certTag] forKey:(id)kSecAttrLabel]; + + OSStatus sanityCheck = SecItemDelete((CFDictionaryRef)queryCertificate); + if (sanityCheck != noErr) { + if (sanityCheck == errSecItemNotFound) { + NSLog(@"Error removing certificate key errSecItemNotFound"); + } else { + NSLog(@"Error removing certificate key, OSStatus == %d.", (int)sanityCheck); + return NO; + } + } + + return YES; +} + ++ (SecKeyRef)getPublicKeyRef:(NSString*)tag { + OSStatus sanityCheck = noErr; + SecKeyRef publicKeyReference = NULL; + + NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init]; + + [queryPublicKey setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [queryPublicKey setObject:tag forKey:(id)kSecAttrApplicationTag]; + [queryPublicKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef]; + + sanityCheck = SecItemCopyMatching((CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKeyReference); + + if (sanityCheck != noErr) { + NSLog(@"getPublicKeyRef error: %d",(int)sanityCheck); + } + + return publicKeyReference; +} + ++ (NSData *)getPublicKeyBits:(NSString*)tag { + OSStatus sanityCheck = noErr; + CFTypeRef publicKeyRef = NULL; + + NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init]; + + [queryPublicKey setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [queryPublicKey setObject:tag forKey:(id)kSecAttrApplicationTag]; + [queryPublicKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData]; + + sanityCheck = SecItemCopyMatching((CFDictionaryRef)queryPublicKey, &publicKeyRef); + + if (sanityCheck != noErr){ + NSLog(@"getPublicKeyBits error: %d",(int)sanityCheck); + publicKeyRef = NULL; + } + + return (__bridge NSData *)publicKeyRef; +} + ++ (SecKeyRef)getPrivateKeyRef:(NSString*)tag { + OSStatus sanityCheck = noErr; + SecKeyRef privateKeyReference = NULL; + + NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init]; + + [queryPrivateKey setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [queryPrivateKey setObject:tag forKey:(id)kSecAttrApplicationTag]; + [queryPrivateKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef]; + + sanityCheck = SecItemCopyMatching((CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKeyReference); + + if (sanityCheck != noErr) { + NSLog(@"getPrivateKeyRef error: %d",(int)sanityCheck); + privateKeyReference = NULL; + } + + return privateKeyReference; +} + ++ (NSData *)getPrivateKeyBits:(NSString*)tag { + OSStatus sanityCheck = noErr; + CFTypeRef privateKeyBits = NULL; + + NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init]; + + [queryPrivateKey setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [queryPrivateKey setObject:tag forKey:(id)kSecAttrApplicationTag]; + [queryPrivateKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData]; + + sanityCheck = SecItemCopyMatching((CFDictionaryRef)queryPrivateKey, &privateKeyBits); + + if (sanityCheck != noErr){ + NSLog(@"getPrivateKeyBits error: %d",(int)sanityCheck); + privateKeyBits = NULL; + } + + return (__bridge NSData *)privateKeyBits; +} + ++ (SecIdentityRef)getIdentityRef:(NSString*)tag { + OSStatus sanityCheck = noErr; + SecIdentityRef identityRef = NULL; + + NSMutableDictionary * queryIdentityRef = [[NSMutableDictionary alloc] init]; + + [queryIdentityRef setObject:(id)kSecClassIdentity forKey:(id)kSecClass]; + [queryIdentityRef setObject:tag forKey:(id)kSecAttrApplicationTag]; + [queryIdentityRef setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [queryIdentityRef setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef]; + + sanityCheck = SecItemCopyMatching((CFDictionaryRef)queryIdentityRef, (CFTypeRef *)&identityRef); + + if (sanityCheck != noErr){ + NSLog(@"getIdentityRef error: %d",(int)sanityCheck); + identityRef = NULL; + } + + return identityRef; +} + ++ (BOOL)addPublicKeyRef:(SecKeyRef)pubkeyRef tag:(NSString*)tag { + + OSStatus sanityCheck = noErr; + CFTypeRef persistPeer = NULL; + + NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init]; + + [publicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [publicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [publicKeyAttr setObject:tag forKey:(id)kSecAttrApplicationTag]; + [publicKeyAttr setObject:(__bridge id _Nonnull)(pubkeyRef) forKey:(id)kSecValueRef]; + [publicKeyAttr setObject:(id)kSecAttrKeyClassPublic forKey:(id)kSecAttrKeyClass]; + [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef]; + + sanityCheck = SecItemAdd((CFDictionaryRef) publicKeyAttr, (CFTypeRef *)&persistPeer); + if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){ + NSLog(@"addPublicKeyRef error: %d",(int)sanityCheck); + return NO; + } + + return YES; +} + ++ (BOOL)addPublicKey:(NSData*)pubkey tag:(NSString*)tag { + + OSStatus sanityCheck = noErr; + CFTypeRef persistPeer = NULL; + + NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init]; + + [publicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [publicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [publicKeyAttr setObject:tag forKey:(id)kSecAttrApplicationTag]; + [publicKeyAttr setObject:pubkey forKey:(id)kSecValueData]; + [publicKeyAttr setObject:(id)kSecAttrKeyClassPublic forKey:(id)kSecAttrKeyClass]; + [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef]; + + sanityCheck = SecItemAdd((CFDictionaryRef) publicKeyAttr, (CFTypeRef *)&persistPeer); + if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){ + NSLog(@"addPublicKey error: %d",(int)sanityCheck); + return NO; + } + + return YES; +} + ++ (BOOL)addPrivateKeyRef:(SecKeyRef)privkeyRef tag:(NSString*)tag { + + OSStatus sanityCheck = noErr; + CFTypeRef persistPeer = NULL; + + NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init]; + + [privateKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [privateKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [privateKeyAttr setObject:tag forKey:(id)kSecAttrApplicationTag]; + [privateKeyAttr setObject:(__bridge id _Nonnull)(privkeyRef) forKey:(id)kSecValueRef]; + [privateKeyAttr setObject:(id)kSecAttrKeyClassPrivate forKey:(id)kSecAttrKeyClass]; + [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef]; + + sanityCheck = SecItemAdd((CFDictionaryRef) privateKeyAttr, (CFTypeRef *)&persistPeer); + if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){ + NSLog(@"addPrivateKeyRef error: %d",(int)sanityCheck); + return NO; + } + + return YES; +} + ++ (BOOL)addPrivateKey:(NSData*)privkey tag:(NSString*)tag { + + OSStatus sanityCheck = noErr; + CFTypeRef persistPeer = NULL; + + NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init]; + + [privateKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass]; + [privateKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; + [privateKeyAttr setObject:tag forKey:(id)kSecAttrApplicationTag]; + [privateKeyAttr setObject:privkey forKey:(id)kSecValueData]; + [privateKeyAttr setObject:(id)kSecAttrKeyClassPrivate forKey:(id)kSecAttrKeyClass]; + [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef]; + + sanityCheck = SecItemAdd((CFDictionaryRef) privateKeyAttr, (CFTypeRef *)&persistPeer); + if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){ + NSLog(@"addPrivateKey error: %d",(int)sanityCheck); + return NO; + } + + return YES; +} + +@end diff --git a/AWSIoT/Internal/AWSIoTMQTTClient.h b/AWSIoT/Internal/AWSIoTMQTTClient.h new file mode 100644 index 00000000000..c951fe23e54 --- /dev/null +++ b/AWSIoT/Internal/AWSIoTMQTTClient.h @@ -0,0 +1,82 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import "AWSIoTModel.h" +#import "AWSIoTDataManager.h" + +@interface AWSIoTMQTTTopicModel : NSObject +@property (nonatomic, strong) NSString *topic; +@property (nonatomic) UInt8 qos; +@property (nonatomic, strong) AWSIoTMQTTNewMessageBlock callback; +@end + +@interface AWSIoTMQTTQueueMessage : NSObject +@property (nonatomic, strong) NSString *topic; +@property (nonatomic, strong) NSData *message; +@end + +@interface AWSIoTMQTTClient : NSObject + +/** + Returns a default singleton object. You should use this singleton method instead of creating an instance of the mqtt client. + @return The default mqtt client. This is a singleton object. + */ ++ (instancetype)sharedInstance; + +- (BOOL)connectWithClientId:(NSString *)clientId + toHost:(NSString *)host + port:(UInt32)port + cleanSession:(BOOL)cleanSession + certificateId:(NSString *)certificateId + statusCallback:(void (^)(AWSIoTMQTTStatus status))callback; + +- (void)disconnect; + +/** + Send MQTT message to specified topic + + @param message The message to be sent. + + @param topic The topic for publish to. + + */ +- (void)publishString:(NSString *)str + onTopic:(NSString *)topic; + +- (void)publishData:(NSData *)data + onTopic:(NSString *)topic; + +/** + Subscribes to a topic at a specific QoS level + + @param topic The Topic to subscribe to. + + @param qos Specifies the QoS Level of the subscription. Can be 0, 1, or 2. + + @param delegate Reference to AWSIOTMQTTNewMessageBlock. When new message is received the function of block will be called. + */ +- (void)subscribeToTopic:(NSString *)topic qos:(UInt8)qos + messageCallback:(AWSIoTMQTTNewMessageBlock)callback; + +/** + Unsubscribes from a topic + + @param topic The Topic to unsubscribe from. + + */ +- (void)unsubscribeTopic:(NSString *)topic; + +@end diff --git a/AWSIoT/Internal/AWSIoTMQTTClient.m b/AWSIoT/Internal/AWSIoTMQTTClient.m new file mode 100644 index 00000000000..bceab33cf08 --- /dev/null +++ b/AWSIoT/Internal/AWSIoTMQTTClient.m @@ -0,0 +1,271 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSIoTMQTTClient.h" +#import "AWSSynchronizedMutableDictionary.h" +#import "AWSSignature.h" +#import "AWSURLRequestRetryHandler.h" +#import "AWSIOTService.h" + +#import "MQTTSession.h" + +#import + +#import "AWSIoTKeychain.h" + +@implementation AWSIoTMQTTTopicModel +@end + +@implementation AWSIoTMQTTQueueMessage +@end + +@interface AWSIoTMQTTClient(){ + MQTTSession* _session; + NSMutableDictionary * _topicsListners; + + BOOL _userDisconnect; + BOOL _needReconnect; + + NSString *_host; + UInt32 _port; + BOOL _cleanSession; + NSArray *_clientCerts; +} + + +@end + +@interface AWSIoTMQTTClient() +@property (nonatomic, copy) void (^connectStatusCallback)(AWSIoTMQTTStatus status); +@property (nonatomic, strong) NSMutableArray *queueMessages; +@end + +@implementation AWSIoTMQTTClient + + +static AWSIoTMQTTClient *_defaultMQTTClient = nil; + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _defaultMQTTClient = [AWSIoTMQTTClient new]; + }); + + + return _defaultMQTTClient; +} + +- (instancetype)init { + if ( self = [super init]) { + _topicsListners = [NSMutableDictionary dictionary]; + self.queueMessages = [NSMutableArray new]; + } + return self; +} + + +- (BOOL)connectWithClientId:(NSString*)clientId + toHost:(NSString*)host + port:(UInt32)port + cleanSession:(BOOL)cleanSession + certificateId:(NSString*)certificateId + statusCallback:(void (^)(AWSIoTMQTTStatus status))callback { + SecIdentityRef identityRef = [AWSIoTKeychain getIdentityRef:[NSString stringWithFormat:@"%@%@",[AWSIoTKeychain privateKeyTag], certificateId ]]; + if (identityRef == NULL) { + NSLog(@"Could not find SecIdentityRef"); + return NO; + }; + + _clientCerts = [[NSArray alloc] initWithObjects:(__bridge id)identityRef, nil]; + _host = host; + _port = port; + _cleanSession = cleanSession; + self.connectStatusCallback = callback; + + if (_cleanSession) { + [_topicsListners removeAllObjects]; + [self.queueMessages removeAllObjects]; + } + + _session = [[MQTTSession alloc] initWithClientId:clientId userName:@"" password:@"" keepAlive:60 cleanSession:cleanSession]; + + self.connectStatusCallback(AWSIoTMQTTStatusConnecting); + + _session.delegate = self; + + [_session connectToHost:_host port:_port usingSSL:YES sslCertificated:_clientCerts]; + + return YES; +} + +- (void)disconnect { + _userDisconnect = YES; + [_session close]; + _session.delegate = nil; + _session = nil; +} + +- (void)reconnectToSession { + _needReconnect = _cleanSession; + [_session connectToHost:_host port:_port usingSSL:YES sslCertificated:_clientCerts]; +} + +- (void)resubscribeToTopics { + _needReconnect = NO; + + for (AWSIoTMQTTTopicModel *topic in _topicsListners.allValues) { + [_session subscribeToTopic:topic.topic atLevel:topic.qos]; + } +} + + +- (void)publishString:(NSString*)str onTopic:(NSString*)topic { + [self publishData:[str dataUsingEncoding:NSUTF8StringEncoding] onTopic:topic]; +} + +- (void)publishData:(NSData*)data onTopic:(NSString*)topic { + + NSLog(@"isReadyToPublish: %i",[_session isReadyToPublish]); + + if ([_session isReadyToPublish]) { + [_session publishData:data onTopic:topic]; + } else { + AWSIoTMQTTQueueMessage *message = [AWSIoTMQTTQueueMessage new]; + message.topic = topic; + message.message = data; + [self.queueMessages addObject:message]; + } + + +} + +- (void)subscribeToTopic:(NSString*)topic qos:(UInt8)qos messageCallback:(AWSIoTMQTTNewMessageBlock)callback { + AWSIoTMQTTTopicModel *topicModel = [AWSIoTMQTTTopicModel new]; + topicModel.topic = topic; + topicModel.qos = qos; + topicModel.callback = callback; + [_topicsListners setObject:topicModel forKey:topic]; + + if (_session) { + [_session subscribeToTopic:topicModel.topic atLevel:topicModel.qos]; + } +} + + +- (void)unsubscribeTopic:(NSString*)topic { + if (_session) { + [_session unsubscribeTopic:topic]; + } + [_topicsListners removeObjectForKey:topic]; +} + +- (void)publishMessagesFromQueue { + NSLog(@"publishMessagesFromQueue"); + AWSIoTMQTTQueueMessage *message = [self.queueMessages firstObject]; + if (message && [_session isReadyToPublish]) { + NSLog(@"publishData on topic %@",message.topic); + [_session publishData:message.message onTopic:message.topic]; + [self.queueMessages removeObjectAtIndex:0]; + } + + if (self.queueMessages.count) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + if ([_session isReadyToPublish]) { + [self publishMessagesFromQueue]; + } + }); + } +} + +#pragma-mark MQTTSessionDelegate + +- (void)session:(MQTTSession*)session handleEvent:(MQTTSessionEvent)eventCode { + NSLog(@"MQTTSessionDelegate handleEvent: %i",eventCode); + + switch (eventCode) { + case MQTTSessionEventConnected: + self.connectStatusCallback(AWSIoTMQTTStatusConnected); + if (_needReconnect) { + [self resubscribeToTopics]; + } + if (self.queueMessages.count) { + [self publishMessagesFromQueue]; + } + break; + case MQTTSessionEventConnectionRefused: + self.connectStatusCallback(AWSIoTMQTTStatusConnectionRefused); + break; + case MQTTSessionEventConnectionClosed: + if (!_userDisconnect && _session) { + [self reconnectToSession]; + } else { + _userDisconnect = NO; + self.connectStatusCallback(AWSIoTMQTTStatusDisconnected); + self.connectStatusCallback = nil; + } + break; + case MQTTSessionEventConnectionError: + self.connectStatusCallback(AWSIoTMQTTStatusConnectionError); + if (!_userDisconnect && _session) { + [self reconnectToSession]; + } + break; + case MQTTSessionEventProtocolError: + self.connectStatusCallback(AWSIoTMQTTStatusProtocolError); + break; + default: + break; + } + +} + +- (void)session:(MQTTSession*)session newMessage:(NSData*)data onTopic:(NSString*)topic { + NSLog(@"MQTTSessionDelegate newMessage: %@\n onTopic: %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding], topic); + + NSArray *topicParts = [topic componentsSeparatedByString: @"/"]; + + for (NSString *topicKey in _topicsListners.allKeys) { + NSArray *topicKeyParts = [topicKey componentsSeparatedByString: @"/"]; + + BOOL topicsIsSame = true; + for (int i = 0; i < topicKeyParts.count; i++) { + if (i >= topicParts.count) { + topicsIsSame = false; + break; + } + + NSString *topicPart = topicParts[i]; + NSString *topicKeyPart = topicKeyParts[i]; + + if ([topicKeyPart rangeOfString:@"#"].location == NSNotFound && [topicKeyPart rangeOfString:@"+"].location == NSNotFound) { + if (![topicPart isEqualToString:topicKeyPart]) { + topicsIsSame = false; + break; + } + } + } + + if (topicsIsSame) { + AWSIoTMQTTTopicModel *topicModel = [_topicsListners objectForKey:topicKey]; + if (topicModel) { + topicModel.callback(data); + } + } + } + +} + + +@end diff --git a/AWSIoT/Internal/MQTTSDK/MQTTDecoder.h b/AWSIoT/Internal/MQTTSDK/MQTTDecoder.h new file mode 100644 index 00000000000..6a9aeab263e --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQTTDecoder.h @@ -0,0 +1,59 @@ +// +// MQTTDecoder.h +// MQtt Client +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import +#import "MQTTMessage.h" + +typedef enum { + MQTTDecoderEventProtocolError, + MQTTDecoderEventConnectionClosed, + MQTTDecoderEventConnectionError +} MQTTDecoderEvent; + +typedef enum{ + MQTTDecoderStatusInitializing, + MQTTDecoderStatusDecodingHeader, + MQTTDecoderStatusDecodingLength, + MQTTDecoderStatusDecodingData, + MQTTDecoderStatusConnectionClosed, + MQTTDecoderStatusConnectionError, + MQTTDecoderStatusProtocolError +} MQTTDecoderStatus; + +@class MQTTDecoder; + +@protocol MQTTDecoderDelegate + +- (void)decoder:(MQTTDecoder*)sender newMessage:(MQTTMessage*)msg; +- (void)decoder:(MQTTDecoder*)sender handleEvent:(MQTTDecoderEvent)eventCode; + +@end + +@interface MQTTDecoder : NSObject + +@property (weak) id delegate; +@property (assign) MQTTDecoderStatus status; + +- (id)initWithStream:(NSInputStream*)aStream + runLoop:(NSRunLoop*)aRunLoop + runLoopMode:(NSString*)aMode; +- (void)open; +- (void)close; +- (void)stream:(NSStream*)sender handleEvent:(NSStreamEvent)eventCode; +@end + + diff --git a/AWSIoT/Internal/MQTTSDK/MQTTDecoder.m b/AWSIoT/Internal/MQTTSDK/MQTTDecoder.m new file mode 100644 index 00000000000..9115f0a7c3e --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQTTDecoder.m @@ -0,0 +1,156 @@ +// +// MQTTDecoder.m +// MQtt Client +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import "MQTTDecoder.h" + +@interface MQTTDecoder() { + NSInputStream* stream; + NSRunLoop* runLoop; + NSString* runLoopMode; + UInt8 header; + UInt32 length; + UInt32 lengthMultiplier; + NSMutableData* dataBuffer; + +} + +@end + +@implementation MQTTDecoder + +- (id)initWithStream:(NSInputStream*)aStream + runLoop:(NSRunLoop*)aRunLoop + runLoopMode:(NSString*)aMode { + _status = MQTTDecoderStatusInitializing; + stream = aStream; + [stream setDelegate:self]; + runLoop = aRunLoop; + runLoopMode = aMode; + return self; +} + +- (void)open { + [stream setDelegate:self]; + [stream scheduleInRunLoop:runLoop forMode:runLoopMode]; + [stream open]; +} + +- (void)close { + [stream setDelegate:nil]; + [stream close]; + [stream removeFromRunLoop:runLoop forMode:runLoopMode]; + stream = nil; +} + +- (void)stream:(NSStream*)sender handleEvent:(NSStreamEvent)eventCode { + if(stream == nil) + return; + switch (eventCode) { + case NSStreamEventOpenCompleted: + _status = MQTTDecoderStatusDecodingHeader; + break; + case NSStreamEventHasBytesAvailable: + if (_status == MQTTDecoderStatusDecodingHeader) { + NSInteger n = [stream read:&header maxLength:1]; + if (n == -1) { + _status = MQTTDecoderStatusConnectionError; + [_delegate decoder:self handleEvent:MQTTDecoderEventConnectionError]; + } + else if (n == 1) { + length = 0; + lengthMultiplier = 1; + _status = MQTTDecoderStatusDecodingLength; + } + } + while (_status == MQTTDecoderStatusDecodingLength) { + UInt8 digit; + NSInteger n = [stream read:&digit maxLength:1]; + if (n == -1) { + _status = MQTTDecoderStatusConnectionError; + [_delegate decoder:self handleEvent:MQTTDecoderEventConnectionError]; + break; + } + else if (n == 0) { + break; + } + length += (digit & 0x7f) * lengthMultiplier; + if ((digit & 0x80) == 0x00) { + dataBuffer = [NSMutableData dataWithCapacity:length]; + _status = MQTTDecoderStatusDecodingData; + } + else { + lengthMultiplier *= 128; + } + } + if (_status == MQTTDecoderStatusDecodingData) { + if (length > 0) { + NSInteger n, toRead; + UInt8 buffer[768]; + toRead = length - [dataBuffer length]; + if (toRead > sizeof buffer) { + toRead = sizeof buffer; + } + n = [stream read:buffer maxLength:toRead]; + if (n == -1) { + _status = MQTTDecoderStatusConnectionError; + [_delegate decoder:self handleEvent:MQTTDecoderEventConnectionError]; + } + else { + [dataBuffer appendBytes:buffer length:n]; + } + } + if ([dataBuffer length] == length) { + MQTTMessage* msg; + UInt8 type, qos; + BOOL isDuplicate, retainFlag; + type = (header >> 4) & 0x0f; + isDuplicate = NO; + if ((header & 0x08) == 0x08) { + isDuplicate = YES; + } + // XXX qos > 2 + qos = (header >> 1) & 0x03; + retainFlag = NO; + if ((header & 0x01) == 0x01) { + retainFlag = YES; + } + msg = [[MQTTMessage alloc] initWithType:type + qos:qos + retainFlag:retainFlag + dupFlag:isDuplicate + data:dataBuffer]; + [_delegate decoder:self newMessage:msg]; + dataBuffer = NULL; + _status = MQTTDecoderStatusDecodingHeader; + } + } + break; + case NSStreamEventEndEncountered: + _status = MQTTDecoderStatusConnectionClosed; + [_delegate decoder:self handleEvent:MQTTDecoderEventConnectionClosed]; + break; + case NSStreamEventErrorOccurred: + _status = MQTTDecoderStatusConnectionError; + [_delegate decoder:self handleEvent:MQTTDecoderEventConnectionError]; + break; + default: + NSLog(@"unhandled event code"); + break; + } +} + +@end diff --git a/AWSIoT/Internal/MQTTSDK/MQTTEncoder.h b/AWSIoT/Internal/MQTTSDK/MQTTEncoder.h new file mode 100644 index 00000000000..17e89fbcf44 --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQTTEncoder.h @@ -0,0 +1,58 @@ +// +// MQTTEncoder.h +// MQtt Client +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import +#import "MQTTMessage.h" + +typedef enum { + MQTTEncoderEventReady, + MQTTEncoderEventErrorOccurred +} MQTTEncoderEvent; + +typedef enum { + MQTTEncoderStatusInitializing, + MQTTEncoderStatusReady, + MQTTEncoderStatusSending, + MQTTEncoderStatusEndEncountered, + MQTTEncoderStatusError +} MQTTEncoderStatus; + + +@class MQTTEncoder; + +@protocol MQTTEncoderDelegate + +- (void)encoder:(MQTTEncoder*)sender handleEvent:(MQTTEncoderEvent)eventCode; + +@end + +@interface MQTTEncoder : NSObject + +@property (weak) id delegate; +@property (assign) MQTTEncoderStatus status; + +- (id)initWithStream:(NSOutputStream*)aStream + runLoop:(NSRunLoop*)aRunLoop + runLoopMode:(NSString*)aMode; + +- (void)encodeMessage:(MQTTMessage*)msg; +- (void)open; +- (void)close; + +@end + + diff --git a/AWSIoT/Internal/MQTTSDK/MQTTEncoder.m b/AWSIoT/Internal/MQTTSDK/MQTTEncoder.m new file mode 100644 index 00000000000..4a79280b9e8 --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQTTEncoder.m @@ -0,0 +1,163 @@ +// +// MQTTEncoder.m +// MQtt Client +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import "MQTTEncoder.h" + +@interface MQTTEncoder () { + NSOutputStream* stream; + NSRunLoop* runLoop; + NSString* runLoopMode; + NSMutableData* buffer; + NSInteger byteIndex; +} + +@end + +@implementation MQTTEncoder + +- (id)initWithStream:(NSOutputStream*)aStream + runLoop:(NSRunLoop*)aRunLoop + runLoopMode:(NSString*)aMode { + _status = MQTTEncoderStatusInitializing; + stream = aStream; + [stream setDelegate:self]; + runLoop = aRunLoop; + runLoopMode = aMode; + return self; +} + +- (void)open { + [stream setDelegate:self]; + [stream scheduleInRunLoop:runLoop forMode:runLoopMode]; + [stream open]; +} + +- (void)close { + [stream close]; + [stream setDelegate:nil]; + [stream removeFromRunLoop:runLoop forMode:runLoopMode]; + stream = nil; +} + +- (void)stream:(NSStream*)sender handleEvent:(NSStreamEvent)eventCode { + if(stream == nil) + return; + assert(sender == stream); + switch (eventCode) { + case NSStreamEventOpenCompleted: + break; + case NSStreamEventHasSpaceAvailable: + if (_status == MQTTEncoderStatusInitializing) { + _status = MQTTEncoderStatusReady; + [_delegate encoder:self handleEvent:MQTTEncoderEventReady]; + } + else if (_status == MQTTEncoderStatusReady) { + [_delegate encoder:self handleEvent:MQTTEncoderEventReady]; + } + else if (_status == MQTTEncoderStatusSending) { + UInt8* ptr; + NSInteger n, length; + + ptr = (UInt8*) [buffer bytes] + byteIndex; + // Number of bytes pending for transfer + length = [buffer length] - byteIndex; + n = [stream write:ptr maxLength:length]; + if (n == -1) { + _status = MQTTEncoderStatusError; + [_delegate encoder:self handleEvent:MQTTEncoderEventErrorOccurred]; + } + else if (n < length) { + byteIndex += n; + } + else { + buffer = NULL; + byteIndex = 0; + _status = MQTTEncoderStatusReady; + } + } + break; + case NSStreamEventErrorOccurred: + case NSStreamEventEndEncountered: + if (_status != MQTTEncoderStatusError) { + _status = MQTTEncoderStatusError; + [_delegate encoder:self handleEvent:MQTTEncoderEventErrorOccurred]; + } + break; + default: + NSLog(@"Oops, event code not handled: 0x%02lx", (unsigned long)eventCode); + break; + } +} + +- (void)encodeMessage:(MQTTMessage*)msg { + UInt8 header; + NSInteger n, length; + + if (_status != MQTTEncoderStatusReady) { + NSLog(@"Encoder not ready"); + return; + } + + assert (buffer == NULL); + assert (byteIndex == 0); + + buffer = [[NSMutableData alloc] init]; + + // encode fixed header + header = [msg type] << 4; + if ([msg isDuplicate]) { + header |= 0x08; + } + header |= [msg qos] << 1; + if ([msg retainFlag]) { + header |= 0x01; + } + [buffer appendBytes:&header length:1]; + + // encode remaining length + length = [[msg data] length]; + do { + UInt8 digit = length % 128; + length /= 128; + if (length > 0) { + digit |= 0x80; + } + [buffer appendBytes:&digit length:1]; + } + while (length > 0); + + // encode message data + if ([msg data] != NULL) { + [buffer appendData:[msg data]]; + } + + n = [stream write:[buffer bytes] maxLength:[buffer length]]; + if (n == -1) { + _status = MQTTEncoderStatusError; + [_delegate encoder:self handleEvent:MQTTEncoderEventErrorOccurred]; + } + else if (n < [buffer length]) { + byteIndex += n; + _status = MQTTEncoderStatusSending; + } + else { + buffer = NULL; + // XXX [delegate encoder:self handleEvent:MQTTEncoderEventReady]; + } +} + +@end diff --git a/AWSIoT/Internal/MQTTSDK/MQTTMessage.h b/AWSIoT/Internal/MQTTSDK/MQTTMessage.h new file mode 100644 index 00000000000..c2664dc2610 --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQTTMessage.h @@ -0,0 +1,110 @@ +// +// MQTTMessage.h +// MQtt Client +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import + +typedef enum { + MQTTConnect = 1, + MQTTConnack = 2, + MQTTPublish = 3, + MQTTPuback = 4, + MQTTPubrec = 5, + MQTTPubrel = 6, + MQTTPubcomp = 7, + MQTTSubscribe = 8, + MQTTSuback = 9, + MQTTUnsubscribe = 10, + MQTTUnsuback = 11, + MQTTPingreq = 12, + MQTTPingresp = 13, + MQTTDisconnect = 14 +} MQTTMessageType; + +@interface MQTTMessage : NSObject + +#pragma mark Instance Methods + ++ (id)connectMessageWithClientId:(NSString*)clientId + userName:(NSString*)userName + password:(NSString*)password + keepAlive:(NSInteger)keeplive + cleanSession:(BOOL)cleanSessionFlag; ++ (id)connectMessageWithClientId:(NSString*)clientId + userName:(NSString*)userName + password:(NSString*)password + keepAlive:(NSInteger)keeplive + cleanSession:(BOOL)cleanSessionFlag + willTopic:(NSString*)willTopic + willMsg:(NSData*)willData + willQoS:(UInt8)willQoS + willRetain:(BOOL)willRetainFlag; + ++ (id)pingreqMessage; ++ (id)subscribeMessageWithMessageId:(UInt16)msgId + topic:(NSString*)topic + qos:(UInt8)qos; ++ (id)unsubscribeMessageWithMessageId:(UInt16)msgId + topic:(NSString*)topic; ++ (id)publishMessageWithData:(NSData*)payload + onTopic:(NSString*)theTopic + retainFlag:(BOOL)retain; ++ (id)publishMessageWithData:(NSData*)payload + onTopic:(NSString*)topic + qos:(UInt8)qosLevel + msgId:(UInt16)msgId + retainFlag:(BOOL)retain + dupFlag:(BOOL)dup; ++ (id)pubackMessageWithMessageId:(UInt16)msgId; ++ (id)pubrecMessageWithMessageId:(UInt16)msgId; ++ (id)pubrelMessageWithMessageId:(UInt16)msgId; ++ (id)pubcompMessageWithMessageId:(UInt16)msgId; + +#pragma mark Constructors + +- (id)initWithType:(UInt8)aType; +- (id)initWithType:(UInt8)aType data:(NSData*)aData; +- (id)initWithType:(UInt8)aType + qos:(UInt8)aQos + data:(NSData*)aData; +- (id)initWithType:(UInt8)aType + qos:(UInt8)aQos + retainFlag:(BOOL)aRetainFlag + dupFlag:(BOOL)aDupFlag + data:(NSData*)aData; + +#pragma mark Control methods + +- (void)setDupFlag; + +#pragma mark Message Properties + +@property (assign) UInt8 type; +@property (assign) UInt8 qos; +@property (assign) BOOL retainFlag; +@property (assign) BOOL isDuplicate; +@property (strong) NSData * data; + +@end + +#pragma mark NSMutableData category extension + +@interface NSMutableData (MQTT) +- (void)appendByte:(UInt8)byte; +- (void)appendUInt16BigEndian:(UInt16)val; +- (void)appendMQTTString:(NSString*)s; + +@end diff --git a/AWSIoT/Internal/MQTTSDK/MQTTMessage.m b/AWSIoT/Internal/MQTTSDK/MQTTMessage.m new file mode 100644 index 00000000000..fddeed2d3f3 --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQTTMessage.m @@ -0,0 +1,251 @@ +// +// MQTTMessage.m +// MQtt Client +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import "MQTTMessage.h" + +@implementation MQTTMessage + ++ (id)connectMessageWithClientId:(NSString*)clientId + userName:(NSString*)userName + password:(NSString*)password + keepAlive:(NSInteger)keepAlive + cleanSession:(BOOL)cleanSessionFlag { + MQTTMessage* msg; + UInt8 flags = 0x00; + + if (cleanSessionFlag) { + flags |= 0x02; + } + if ([userName length] > 0) { + flags |= 0x80; + if ([password length] > 0) { + flags |= 0x40; + } + } + + NSMutableData* data = [NSMutableData data]; + [data appendMQTTString:@"MQTT"]; + [data appendByte:4]; + [data appendByte:flags]; + [data appendUInt16BigEndian:keepAlive]; + [data appendMQTTString:clientId]; + if ([userName length] > 0) { + [data appendMQTTString:userName]; + if ([password length] > 0) { + [data appendMQTTString:password]; + } + } + NSLog(@"%@",data); + msg = [[MQTTMessage alloc] initWithType:MQTTConnect data:data]; + return msg; +} + ++ (id)connectMessageWithClientId:(NSString*)clientId + userName:(NSString*)userName + password:(NSString*)password + keepAlive:(NSInteger)keepAlive + cleanSession:(BOOL)cleanSessionFlag + willTopic:(NSString*)willTopic + willMsg:(NSData*)willMsg + willQoS:(UInt8)willQoS + willRetain:(BOOL)willRetainFlag { + UInt8 flags = 0x04 | (willQoS << 4 & 0x18); + + if (willRetainFlag) { + flags |= 0x20; + } + if (cleanSessionFlag) { + flags |= 0x02; + } + if ([userName length] > 0) { + flags |= 0x80; + if ([password length] > 0) { + flags |= 0x40; + } + } + + NSMutableData* data = [NSMutableData data]; + [data appendMQTTString:@"MQTT"]; + [data appendByte:4]; + [data appendByte:flags]; + [data appendUInt16BigEndian:keepAlive]; + [data appendMQTTString:clientId]; + [data appendMQTTString:willTopic]; + [data appendUInt16BigEndian:[willMsg length]]; + [data appendData:willMsg]; + if ([userName length] > 0) { + [data appendMQTTString:userName]; + if ([password length] > 0) { + [data appendMQTTString:password]; + } + } + + MQTTMessage *msg = [[MQTTMessage alloc] initWithType:MQTTConnect + data:data]; + return msg; +} + ++ (id)pingreqMessage { + return [[MQTTMessage alloc] initWithType:MQTTPingreq]; +} + ++ (id)subscribeMessageWithMessageId:(UInt16)msgId + topic:(NSString*)topic + qos:(UInt8)qos { + NSMutableData* data = [NSMutableData data]; + [data appendUInt16BigEndian:msgId]; + [data appendMQTTString:topic]; + [data appendByte:qos]; + MQTTMessage* msg = [[MQTTMessage alloc] initWithType:MQTTSubscribe + qos:1 + data:data]; + return msg; +} + ++ (id)unsubscribeMessageWithMessageId:(UInt16)msgId + topic:(NSString*)topic { + NSMutableData* data = [NSMutableData data]; + [data appendUInt16BigEndian:msgId]; + [data appendMQTTString:topic]; + MQTTMessage* msg = [[MQTTMessage alloc] initWithType:MQTTUnsubscribe + qos:1 + data:data]; + return msg; +} + ++ (id)publishMessageWithData:(NSData*)payload + onTopic:(NSString*)topic + retainFlag:(BOOL)retain { + NSMutableData* data = [NSMutableData data]; + [data appendMQTTString:topic]; + [data appendData:payload]; + MQTTMessage *msg = [[MQTTMessage alloc] initWithType:MQTTPublish + qos:0 + retainFlag:retain + dupFlag:false + data:data]; + return msg; +} + ++ (id)publishMessageWithData:(NSData*)payload + onTopic:(NSString*)topic + qos:(UInt8)qosLevel + msgId:(UInt16)msgId + retainFlag:(BOOL)retain + dupFlag:(BOOL)dup { + NSMutableData* data = [NSMutableData data]; + [data appendMQTTString:topic]; + [data appendUInt16BigEndian:msgId]; + [data appendData:payload]; + MQTTMessage *msg = [[MQTTMessage alloc] initWithType:MQTTPublish + qos:qosLevel + retainFlag:retain + dupFlag:dup + data:data]; + return msg; +} + ++ (id)pubackMessageWithMessageId:(UInt16)msgId { + NSMutableData* data = [NSMutableData data]; + [data appendUInt16BigEndian:msgId]; + return [[MQTTMessage alloc] initWithType:MQTTPuback + data:data]; +} + ++ (id)pubrecMessageWithMessageId:(UInt16)msgId { + NSMutableData* data = [NSMutableData data]; + [data appendUInt16BigEndian:msgId]; + return [[MQTTMessage alloc] initWithType:MQTTPubrec + data:data]; +} + ++ (id)pubrelMessageWithMessageId:(UInt16)msgId { + NSMutableData* data = [NSMutableData data]; + [data appendUInt16BigEndian:msgId]; + return [[MQTTMessage alloc] initWithType:MQTTPubrel + data:data]; +} + ++ (id)pubcompMessageWithMessageId:(UInt16)msgId { + NSMutableData* data = [NSMutableData data]; + [data appendUInt16BigEndian:msgId]; + return [[MQTTMessage alloc] initWithType:MQTTPubcomp + data:data]; +} + +- (id)initWithType:(UInt8)aType { + _type = aType; + self.data = nil; + return self; +} + +- (id)initWithType:(UInt8)aType data:(NSData*)aData { + _type = aType; + self.data = aData; + return self; +} + +- (id)initWithType:(UInt8)aType + qos:(UInt8)aQos + data:(NSData*)aData { + _type = aType; + _qos = aQos; + self.data = aData; + return self; +} + +- (id)initWithType:(UInt8)aType + qos:(UInt8)aQos + retainFlag:(BOOL)aRetainFlag + dupFlag:(BOOL)aDupFlag + data:(NSData*)aData { + _type = aType; + _qos = aQos; + _retainFlag = aRetainFlag; + _isDuplicate = aDupFlag; + self.data = aData; + return self; +} + +- (void)setDupFlag { + _isDuplicate = true; +} + +@end + +@implementation NSMutableData (MQTT) + +- (void)appendByte:(UInt8)byte { + [self appendBytes:&byte length:1]; +} + +- (void)appendUInt16BigEndian:(UInt16)val { + [self appendByte:val / 256]; + [self appendByte:val % 256]; +} + +- (void)appendMQTTString:(NSString*)string { + UInt8 buf[2]; + const char* utf8String = [string UTF8String]; + size_t strLen = strlen(utf8String); + buf[0] = strLen / 256; + buf[1] = strLen % 256; + [self appendBytes:buf length:2]; + [self appendBytes:utf8String length:strLen]; +} + +@end diff --git a/AWSIoT/Internal/MQTTSDK/MQTTSession.h b/AWSIoT/Internal/MQTTSDK/MQTTSession.h new file mode 100644 index 00000000000..2792be335e5 --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQTTSession.h @@ -0,0 +1,129 @@ +// +// MQTTSession.h +// MQtt Client +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import +#import "MQTTMessage.h" + +typedef enum { + MQTTSessionStatusCreated, + MQTTSessionStatusConnecting, + MQTTSessionStatusConnected, + MQTTSessionStatusError +} MQTTSessionStatus; + +typedef enum { + MQTTSessionEventConnected, + MQTTSessionEventConnectionRefused, + MQTTSessionEventConnectionClosed, + MQTTSessionEventConnectionError, + MQTTSessionEventProtocolError +} MQTTSessionEvent; + +@class MQTTSession; + +@protocol MQTTSessionDelegate + +- (void)session:(MQTTSession*)session handleEvent:(MQTTSessionEvent)eventCode; +- (void)session:(MQTTSession*)session newMessage:(NSData*)data onTopic:(NSString*)topic; + +@end + +@interface MQTTSession : NSObject + +#pragma mark Constructors + +- (id)initWithClientId:(NSString*)theClientId; +- (id)initWithClientId:(NSString*)theClientId runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode; +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUsername + password:(NSString*)thePassword; +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword + runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode; +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUsername + password:(NSString*)thePassword + keepAlive:(UInt16)theKeepAliveInterval + cleanSession:(BOOL)cleanSessionFlag; +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUsername + password:(NSString*)thePassword + keepAlive:(UInt16)theKeepAlive + cleanSession:(BOOL)theCleanSessionFlag + runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theMode; +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword + keepAlive:(UInt16)theKeepAliveInterval + cleanSession:(BOOL)theCleanSessionFlag + willTopic:(NSString*)willTopic + willMsg:(NSData*)willMsg + willQoS:(UInt8)willQoS + willRetainFlag:(BOOL)willRetainFlag; +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword + keepAlive:(UInt16)theKeepAliveInterval + cleanSession:(BOOL)theCleanSessionFlag + willTopic:(NSString*)willTopic + willMsg:(NSData*)willMsg + willQoS:(UInt8)willQoS + willRetainFlag:(BOOL)willRetainFlag + runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode; +- (id)initWithClientId:(NSString*)theClientId + keepAlive:(UInt16)theKeepAliveInterval + connectMessage:(MQTTMessage*)theConnectMessage + runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode; + +#pragma mark Delegates and Callback blocks +@property (weak) id delegate; +@property (strong) void (^connectionHandler)(MQTTSessionEvent event); +@property (strong) void (^messageHandler)(NSData* message, NSString* topic); + +#pragma mark Connection Management +- (void)connectToHost:(NSString*)ip port:(UInt32)port; +- (void)connectToHost:(NSString*)ip port:(UInt32)port usingSSL:(BOOL)usingSSL sslCertificated:(NSArray*)sslCertificated; +- (void)connectToHost:(NSString*)ip port:(UInt32)port withConnectionHandler:(void (^)(MQTTSessionEvent event))connHandler messageHandler:(void (^)(NSData* data, NSString* topic))messHandler; +- (void)connectToHost:(NSString*)ip port:(UInt32)port usingSSL:(BOOL)usingSSL sslCertificated:(NSArray*)sslCertificated withConnectionHandler:(void (^)(MQTTSessionEvent event))connHandler messageHandler:(void (^)(NSData* data, NSString* topic))messHandler; +- (void)close; + +#pragma mark Subscription Management +- (void)subscribeTopic:(NSString*)theTopic; +- (void)subscribeToTopic:(NSString*)topic atLevel:(UInt8)qosLevel; +- (void)unsubscribeTopic:(NSString*)theTopic; + +#pragma mark Message Publishing +- (void)publishData:(NSData*)theData onTopic:(NSString*)theTopic; +- (void)publishDataAtLeastOnce:(NSData*)theData onTopic:(NSString*)theTopic; +- (void)publishDataAtLeastOnce:(NSData*)theData onTopic:(NSString*)theTopic retain:(BOOL)retainFlag; +- (void)publishDataAtMostOnce:(NSData*)theData onTopic:(NSString*)theTopic; +- (void)publishDataAtMostOnce:(NSData*)theData onTopic:(NSString*)theTopic retain:(BOOL)retainFlag; +- (void)publishDataExactlyOnce:(NSData*)theData onTopic:(NSString*)theTopic; +- (void)publishDataExactlyOnce:(NSData*)theData onTopic:(NSString*)theTopic retain:(BOOL)retainFlag; +- (void)publishJson:(id)payload onTopic:(NSString*)theTopic; + +- (BOOL)isReadyToPublish; + +@end + + diff --git a/AWSIoT/Internal/MQTTSDK/MQTTSession.m b/AWSIoT/Internal/MQTTSDK/MQTTSession.m new file mode 100644 index 00000000000..ae20d7229ec --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQTTSession.m @@ -0,0 +1,728 @@ +// +// MQTTSession.m +// MQtt Client +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import "MQTTSession.h" +#import "MQTTDecoder.h" +#import "MQTTEncoder.h" +#import "MQttTxFlow.h" + +@interface MQTTSession () { + MQTTSessionStatus status; + NSString* clientId; + //NSString* userName; + //NSString* password; + UInt16 keepAliveInterval; + BOOL cleanSessionFlag; + MQTTMessage* connectMessage; + NSRunLoop* runLoop; + NSString* runLoopMode; + NSTimer* timer; + NSInteger idleTimer; + MQTTEncoder* encoder; + MQTTDecoder* decoder; + UInt16 txMsgId; + NSMutableDictionary* txFlows; + NSMutableDictionary* rxFlows; + unsigned int ticks; +} + +// private methods & properties + +- (void)timerHandler:(NSTimer*)theTimer; +- (void)encoder:(MQTTEncoder*)sender handleEvent:(MQTTEncoderEvent) eventCode; +- (void)decoder:(MQTTDecoder*)sender handleEvent:(MQTTDecoderEvent) eventCode; +- (void)decoder:(MQTTDecoder*)sender newMessage:(MQTTMessage*) msg; + +- (void)newMessage:(MQTTMessage*)msg; +- (void)error:(MQTTSessionEvent)event; +- (void)handlePublish:(MQTTMessage*)msg; +- (void)handlePuback:(MQTTMessage*)msg; +- (void)handlePubrec:(MQTTMessage*)msg; +- (void)handlePubrel:(MQTTMessage*)msg; +- (void)handlePubcomp:(MQTTMessage*)msg; +- (void)send:(MQTTMessage*)msg; +- (UInt16)nextMsgId; + +@property (strong,atomic) NSMutableArray* queue; +@property (strong,atomic) NSMutableArray* timerRing; +@property (strong, nonatomic) NSArray *sslCertificates; + +@end + +@implementation MQTTSession + +- (id)initWithClientId:(NSString*)theClientId { + return [self initWithClientId:theClientId userName:@"" password:@""]; +} + +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword { + return [self initWithClientId:theClientId + userName:theUserName + password:thePassword + keepAlive:60 + cleanSession:YES]; +} + +- (id)initWithClientId:(NSString*)theClientId runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode { + return [self initWithClientId:theClientId userName:@"" password:@"" runLoop:theRunLoop forMode:theRunLoopMode]; +} + +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword + runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode { + return [self initWithClientId:theClientId + userName:theUserName + password:thePassword + keepAlive:60 + cleanSession:YES + runLoop:theRunLoop + forMode:theRunLoopMode]; +} + + +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword + keepAlive:(UInt16)theKeepAliveInterval + cleanSession:(BOOL)theCleanSessionFlag { + return [self initWithClientId:theClientId + userName:theUserName + password:thePassword + keepAlive:theKeepAliveInterval + cleanSession:theCleanSessionFlag + runLoop:[NSRunLoop currentRunLoop] + forMode:NSDefaultRunLoopMode]; +} + +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword + keepAlive:(UInt16)theKeepAliveInterval + cleanSession:(BOOL)theCleanSessionFlag + runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode { + MQTTMessage *msg = [MQTTMessage connectMessageWithClientId:theClientId + userName:theUserName + password:thePassword + keepAlive:theKeepAliveInterval + cleanSession:theCleanSessionFlag]; + return [self initWithClientId:theClientId + keepAlive:theKeepAliveInterval + connectMessage:msg + runLoop:theRunLoop + forMode:theRunLoopMode]; +} + +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword + keepAlive:(UInt16)theKeepAliveInterval + cleanSession:(BOOL)theCleanSessionFlag + willTopic:(NSString*)willTopic + willMsg:(NSData*)willMsg + willQoS:(UInt8)willQoS + willRetainFlag:(BOOL)willRetainFlag { + return [self initWithClientId:theClientId + userName:theUserName + password:thePassword + keepAlive:theKeepAliveInterval + cleanSession:theCleanSessionFlag + willTopic:willTopic + willMsg:willMsg + willQoS:willQoS + willRetainFlag:willRetainFlag + runLoop:[NSRunLoop currentRunLoop] + forMode:NSDefaultRunLoopMode]; +} + +- (id)initWithClientId:(NSString*)theClientId + userName:(NSString*)theUserName + password:(NSString*)thePassword + keepAlive:(UInt16)theKeepAliveInterval + cleanSession:(BOOL)theCleanSessionFlag + willTopic:(NSString*)willTopic + willMsg:(NSData*)willMsg + willQoS:(UInt8)willQoS + willRetainFlag:(BOOL)willRetainFlag + runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode { + MQTTMessage *msg = [MQTTMessage connectMessageWithClientId:theClientId + userName:theUserName + password:thePassword + keepAlive:theKeepAliveInterval + cleanSession:theCleanSessionFlag + willTopic:willTopic + willMsg:willMsg + willQoS:willQoS + willRetain:willRetainFlag]; + return [self initWithClientId:theClientId + keepAlive:theKeepAliveInterval + connectMessage:msg + runLoop:theRunLoop + forMode:theRunLoopMode]; +} + +- (id)initWithClientId:(NSString*)theClientId + keepAlive:(UInt16)theKeepAliveInterval + connectMessage:(MQTTMessage*)theConnectMessage + runLoop:(NSRunLoop*)theRunLoop + forMode:(NSString*)theRunLoopMode { + clientId = theClientId; + keepAliveInterval = theKeepAliveInterval; + connectMessage = theConnectMessage; + runLoop = theRunLoop; + runLoopMode = theRunLoopMode; + + self.queue = [NSMutableArray array]; + txMsgId = 1; + txFlows = [[NSMutableDictionary alloc] init]; + rxFlows = [[NSMutableDictionary alloc] init]; + self.timerRing = [[NSMutableArray alloc] initWithCapacity:60]; + int i; + for (i = 0; i < 60; i++) { + [self.timerRing addObject:[NSMutableSet set]]; + } + ticks = 0; + + return self; +} + +- (void)dealloc { + [encoder close]; + encoder = nil; + [decoder close]; + decoder = nil; + if (timer != nil) { + [timer invalidate]; + timer = nil; + } +} + +- (void)close { + [encoder close]; + [decoder close]; + encoder = nil; + decoder = nil; + if (timer != nil) { + [timer invalidate]; + timer = nil; + } + [self error:MQTTSessionEventConnectionClosed]; +} + +#pragma mark Connection Management + +- (void)connectToHost:(NSString*)ip port:(UInt32)port { + [self connectToHost:ip port:port usingSSL:false sslCertificated:nil]; +} + +- (void)connectToHost:(NSString*)ip port:(UInt32)port usingSSL:(BOOL)usingSSL sslCertificated:(NSArray*)sslCertificated { + + status = MQTTSessionStatusCreated; + + self.sslCertificates = sslCertificated; + + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + + CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)ip, port, &readStream, &writeStream); + + if (usingSSL) { + + CFDictionaryRef sslSettings; + + if (self.sslCertificates.count) { + + const void *keys[] = { kCFStreamSSLLevel, + kCFStreamSSLCertificates }; + + const void *vals[] = { kCFStreamSocketSecurityLevelNegotiatedSSL, + (__bridge const void *)(self.sslCertificates) }; + + sslSettings = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + } else { + const void *keys[] = { kCFStreamSSLLevel, + kCFStreamSSLPeerName }; + + const void *vals[] = { kCFStreamSocketSecurityLevelNegotiatedSSL, + kCFNull }; + + sslSettings = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + + + CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, sslSettings); + CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, sslSettings); + + CFRelease(sslSettings); + } + + encoder = [[MQTTEncoder alloc] initWithStream:(__bridge NSOutputStream*)writeStream + runLoop:runLoop + runLoopMode:runLoopMode]; + + decoder = [[MQTTDecoder alloc] initWithStream:(__bridge NSInputStream*)readStream + runLoop:runLoop + runLoopMode:runLoopMode]; + + [encoder setDelegate:self]; + [decoder setDelegate:self]; + + [encoder open]; + [decoder open]; +} + + +- (void)connectToHost:(NSString*)ip port:(UInt32)port withConnectionHandler:(void (^)(MQTTSessionEvent event))connHandler messageHandler:(void (^)(NSData* data, NSString* topic))messHandler{ + [self connectToHost:ip port:port usingSSL:false sslCertificated:nil withConnectionHandler:(void (^)(MQTTSessionEvent event))connHandler messageHandler:(void (^)(NSData* data, NSString* topic))messHandler]; +} + +- (void)connectToHost:(NSString*)ip port:(UInt32)port usingSSL:(BOOL)usingSSL sslCertificated:(NSArray*)sslCertificated withConnectionHandler:(void (^)(MQTTSessionEvent event))connHandler messageHandler:(void (^)(NSData* data, NSString* topic))messHandler{ + _connectionHandler = [connHandler copy]; + _messageHandler = [messHandler copy]; + + [self connectToHost:ip port:port usingSSL:usingSSL sslCertificated:nil]; +} + + +#pragma mark Subscription Management + +- (void)subscribeTopic:(NSString*)theTopic { + [self subscribeToTopic:theTopic atLevel:0]; +} + +- (void) subscribeToTopic:(NSString*)topic + atLevel:(UInt8)qosLevel { + [self send:[MQTTMessage subscribeMessageWithMessageId:[self nextMsgId] + topic:topic + qos:qosLevel]]; +} + +- (void)unsubscribeTopic:(NSString*)theTopic { + [self send:[MQTTMessage unsubscribeMessageWithMessageId:[self nextMsgId] + topic:theTopic]]; +} + +- (void)publishData:(NSData*)data onTopic:(NSString*)topic { + [self publishDataAtMostOnce:data onTopic:topic]; +} + +- (void)publishDataAtMostOnce:(NSData*)data + onTopic:(NSString*)topic { + [self publishDataAtMostOnce:data onTopic:topic retain:false]; +} + +- (void)publishDataAtMostOnce:(NSData*)data + onTopic:(NSString*)topic + retain:(BOOL)retainFlag { + [self send:[MQTTMessage publishMessageWithData:data + onTopic:topic + retainFlag:retainFlag]]; +} + +- (void)publishDataAtLeastOnce:(NSData*)data + onTopic:(NSString*)topic { + [self publishDataAtLeastOnce:data onTopic:topic retain:false]; +} + +- (void)publishDataAtLeastOnce:(NSData*)data + onTopic:(NSString*)topic + retain:(BOOL)retainFlag { + UInt16 msgId = [self nextMsgId]; + MQTTMessage *msg = [MQTTMessage publishMessageWithData:data + onTopic:topic + qos:1 + msgId:msgId + retainFlag:retainFlag + dupFlag:false]; + MQttTxFlow *flow = [MQttTxFlow flowWithMsg:msg + deadline:(ticks + 60)]; + [txFlows setObject:flow forKey:[NSNumber numberWithUnsignedInt:msgId]]; + [[self.timerRing objectAtIndex:([flow deadline] % 60)] addObject:[NSNumber numberWithUnsignedInt:msgId]]; + [self send:msg]; +} + +- (void)publishDataExactlyOnce:(NSData*)data + onTopic:(NSString*)topic { + [self publishDataExactlyOnce:data onTopic:topic retain:false]; +} + +- (void)publishDataExactlyOnce:(NSData*)data + onTopic:(NSString*)topic + retain:(BOOL)retainFlag { + UInt16 msgId = [self nextMsgId]; + MQTTMessage *msg = [MQTTMessage publishMessageWithData:data + onTopic:topic + qos:2 + msgId:msgId + retainFlag:retainFlag + dupFlag:false]; + MQttTxFlow *flow = [MQttTxFlow flowWithMsg:msg + deadline:(ticks + 60)]; + [txFlows setObject:flow forKey:[NSNumber numberWithUnsignedInt:msgId]]; + [[self.timerRing objectAtIndex:([flow deadline] % 60)] addObject:[NSNumber numberWithUnsignedInt:msgId]]; + [self send:msg]; +} + +- (void)publishJson:(id)payload onTopic:(NSString*)theTopic { + NSError * error = nil; + NSData * data = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; + if(error!=nil){ + //NSLog(@"Error creating JSON: %@",error.description); + return; + } + [self publishData:data onTopic:theTopic]; +} + +- (void)timerHandler:(NSTimer*)theTimer { + idleTimer++; + if (idleTimer >= keepAliveInterval) { + if ([encoder status] == MQTTEncoderStatusReady) { + //NSLog(@"sending PINGREQ"); + [encoder encodeMessage:[MQTTMessage pingreqMessage]]; + idleTimer = 0; + } + } + ticks++; + NSEnumerator *e = [[self.timerRing objectAtIndex:(ticks % 60)] objectEnumerator]; + id msgId; + + while ((msgId = [e nextObject])) { + MQttTxFlow *flow = [txFlows objectForKey:msgId]; + MQTTMessage *msg = [flow msg]; + [flow setDeadline:(ticks + 60)]; + [msg setDupFlag]; + [self send:msg]; + } +} + +- (void)encoder:(MQTTEncoder*)sender handleEvent:(MQTTEncoderEvent) eventCode { + // NSLog(@"encoder:(MQTTEncoder*)sender handleEvent:(MQTTEncoderEvent) eventCode "); + if(sender == encoder) { + switch (eventCode) { + case MQTTEncoderEventReady: + switch (status) { + case MQTTSessionStatusCreated: + //NSLog(@"Encoder has been created. Sending Auth Message"); + [sender encodeMessage:connectMessage]; + status = MQTTSessionStatusConnecting; + break; + case MQTTSessionStatusConnecting: + break; + case MQTTSessionStatusConnected: + if ([self.queue count] > 0) { + MQTTMessage *msg = [self.queue objectAtIndex:0]; + [self.queue removeObjectAtIndex:0]; + [encoder encodeMessage:msg]; + } + break; + case MQTTSessionStatusError: + break; + } + break; + case MQTTEncoderEventErrorOccurred: + [self error:MQTTSessionEventConnectionError]; + break; + } + } +} + +- (void)decoder:(MQTTDecoder*)sender handleEvent:(MQTTDecoderEvent)eventCode { + //NSLog(@"decoder:(MQTTDecoder*)sender handleEvent:(MQTTDecoderEvent)eventCode"); + if(sender == decoder) { + MQTTSessionEvent event; + switch (eventCode) { + case MQTTDecoderEventConnectionClosed: + event = MQTTSessionEventConnectionClosed; + break; + case MQTTDecoderEventConnectionError: + event = MQTTSessionEventConnectionError; + break; + case MQTTDecoderEventProtocolError: + event = MQTTSessionEventProtocolError; + break; + } + [self error:event]; + } +} + +- (void)decoder:(MQTTDecoder*)sender newMessage:(MQTTMessage*)msg { + //NSLog(@"decoder:(MQTTDecoder*)sender newMessage:(MQTTMessage*)msg "); + if(sender == decoder){ + switch (status) { + case MQTTSessionStatusConnecting: + switch ([msg type]) { + case MQTTConnack: + if ([[msg data] length] != 2) { + [self error:MQTTSessionEventProtocolError]; + } + else { + const UInt8 *bytes = [[msg data] bytes]; + if (bytes[1] == 0) { + status = MQTTSessionStatusConnected; + timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1.0] + interval:1.0 + target:self + selector:@selector(timerHandler:) + userInfo:nil + repeats:YES]; + if(_connectionHandler){ + _connectionHandler(MQTTSessionEventConnected); + } + + [_delegate session:self handleEvent:MQTTSessionEventConnected]; + + [runLoop addTimer:timer forMode:runLoopMode]; + } + else { + [self error:MQTTSessionEventConnectionRefused]; + } + } + break; + default: + [self error:MQTTSessionEventProtocolError]; + break; + } + break; + case MQTTSessionStatusConnected: + [self newMessage:msg]; + break; + default: + break; + } + } +} + +- (void)newMessage:(MQTTMessage*)msg { + switch ([msg type]) { + case MQTTPublish: + [self handlePublish:msg]; + break; + case MQTTPuback: + [self handlePuback:msg]; + break; + case MQTTPubrec: + [self handlePubrec:msg]; + break; + case MQTTPubrel: + [self handlePubrel:msg]; + break; + case MQTTPubcomp: + [self handlePubcomp:msg]; + break; + default: + return; + } +} + +- (void)handlePublish:(MQTTMessage*)msg { + + NSData *data = [msg data]; + if ([data length] < 2) { + return; + } + UInt8 const *bytes = [data bytes]; + UInt16 topicLength = 256 * bytes[0] + bytes[1]; + if ([data length] < 2 + topicLength) { + return; + } + NSData *topicData = [data subdataWithRange:NSMakeRange(2, topicLength)]; + NSString *topic = [[NSString alloc] initWithData:topicData + encoding:NSUTF8StringEncoding]; + NSRange range = NSMakeRange(2 + topicLength, [data length] - topicLength - 2); + data = [data subdataWithRange:range]; + if ([msg qos] == 0) { + [_delegate session:self newMessage:data onTopic:topic]; + if(_messageHandler){ + _messageHandler(data, topic); + } + } + else { + if ([data length] < 2) { + return; + } + bytes = [data bytes]; + UInt16 msgId = 256 * bytes[0] + bytes[1]; + if (msgId == 0) { + return; + } + data = [data subdataWithRange:NSMakeRange(2, [data length] - 2)]; + if ([msg qos] == 1) { + [_delegate session:self newMessage:data onTopic:topic]; + + if(_messageHandler){ + _messageHandler(data, topic); + } + [self send:[MQTTMessage pubackMessageWithMessageId:msgId]]; + } + else { + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: + data, @"data", topic, @"topic", nil]; + [rxFlows setObject:dict forKey:[NSNumber numberWithUnsignedInt:msgId]]; + [self send:[MQTTMessage pubrecMessageWithMessageId:msgId]]; + } + } +} + +- (void)handlePuback:(MQTTMessage*)msg { + if ([[msg data] length] != 2) { + return; + } + UInt8 const *bytes = [[msg data] bytes]; + NSNumber *msgId = [NSNumber numberWithUnsignedInt:(256 * bytes[0] + bytes[1])]; + if ([msgId unsignedIntValue] == 0) { + return; + } + MQttTxFlow *flow = [txFlows objectForKey:msgId]; + if (flow == nil) { + return; + } + + if ([[flow msg] type] != MQTTPublish || [[flow msg] qos] != 1) { + return; + } + + [[self.timerRing objectAtIndex:([flow deadline] % 60)] removeObject:msgId]; + [txFlows removeObjectForKey:msgId]; +} + +- (void)handlePubrec:(MQTTMessage*)msg { + if ([[msg data] length] != 2) { + return; + } + UInt8 const *bytes = [[msg data] bytes]; + NSNumber *msgId = [NSNumber numberWithUnsignedInt:(256 * bytes[0] + bytes[1])]; + if ([msgId unsignedIntValue] == 0) { + return; + } + MQttTxFlow *flow = [txFlows objectForKey:msgId]; + if (flow == nil) { + return; + } + msg = [flow msg]; + if ([msg type] != MQTTPublish || [msg qos] != 2) { + return; + } + msg = [MQTTMessage pubrelMessageWithMessageId:[msgId unsignedIntValue]]; + [flow setMsg:msg]; + [[self.timerRing objectAtIndex:([flow deadline] % 60)] removeObject:msgId]; + [flow setDeadline:(ticks + 60)]; + [[self.timerRing objectAtIndex:([flow deadline] % 60)] addObject:msgId]; + + [self send:msg]; +} + +- (void)handlePubrel:(MQTTMessage*)msg { + if ([[msg data] length] != 2) { + return; + } + UInt8 const *bytes = [[msg data] bytes]; + NSNumber *msgId = [NSNumber numberWithUnsignedInt:(256 * bytes[0] + bytes[1])]; + if ([msgId unsignedIntValue] == 0) { + return; + } + NSDictionary *dict = [rxFlows objectForKey:msgId]; + if (dict != nil) { + [_delegate session:self + newMessage:[dict valueForKey:@"data"] + onTopic:[dict valueForKey:@"topic"]]; + + if(_messageHandler){ + _messageHandler([dict valueForKey:@"data"], [dict valueForKey:@"topic"]); + } + + [rxFlows removeObjectForKey:msgId]; + } + [self send:[MQTTMessage pubcompMessageWithMessageId:[msgId unsignedIntegerValue]]]; +} + +- (void)handlePubcomp:(MQTTMessage*)msg { + if ([[msg data] length] != 2) { + return; + } + UInt8 const *bytes = [[msg data] bytes]; + NSNumber *msgId = [NSNumber numberWithUnsignedInt:(256 * bytes[0] + bytes[1])]; + if ([msgId unsignedIntValue] == 0) { + return; + } + MQttTxFlow *flow = [txFlows objectForKey:msgId]; + if (flow == nil || [[flow msg] type] != MQTTPubrel) { + return; + } + + [[self.timerRing objectAtIndex:([flow deadline] % 60)] removeObject:msgId]; + [txFlows removeObjectForKey:msgId]; +} + +- (void)error:(MQTTSessionEvent)eventCode { + + [encoder close]; + encoder = nil; + + [decoder close]; + decoder = nil; + + if (timer != nil) { + [timer invalidate]; + + timer = nil; + } + status = MQTTSessionStatusError; + + usleep(1000000); // 1 sec delay + + [_delegate session:self handleEvent:eventCode]; + + if(_connectionHandler){ + _connectionHandler(eventCode); + } + +} + +- (void)send:(MQTTMessage*)msg { + if ([encoder status] == MQTTEncoderStatusReady) { + [encoder encodeMessage:msg]; + } + else { + [self.queue addObject:msg]; + } +} + +- (UInt16)nextMsgId { + txMsgId++; + while (txMsgId == 0 || [txFlows objectForKey:[NSNumber numberWithUnsignedInt:txMsgId]] != nil) { + txMsgId++; + } + return txMsgId; +} + +- (BOOL)isReadyToPublish { + return encoder && [encoder status] == MQTTEncoderStatusReady; +} + +@end diff --git a/AWSIoT/Internal/MQTTSDK/MQttTxFlow.h b/AWSIoT/Internal/MQTTSDK/MQttTxFlow.h new file mode 100644 index 00000000000..8eda6e31775 --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQttTxFlow.h @@ -0,0 +1,30 @@ +// +// MQttTxFlow.h +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import +#import "MQTTMessage.h" + +@interface MQttTxFlow : NSObject + ++ (id)flowWithMsg:(MQTTMessage*)aMsg + deadline:(unsigned int)aDeadline; +- (id)initWithMsg:(MQTTMessage*)aMsg deadline:(unsigned int)aDeadline; + +@property (strong) MQTTMessage* msg; +@property (assign) unsigned int deadline; + +@end + diff --git a/AWSIoT/Internal/MQTTSDK/MQttTxFlow.m b/AWSIoT/Internal/MQTTSDK/MQttTxFlow.m new file mode 100644 index 00000000000..6ac991d2f1f --- /dev/null +++ b/AWSIoT/Internal/MQTTSDK/MQttTxFlow.m @@ -0,0 +1,33 @@ +// +// MQtttTxFlow.m +// +// Copyright (c) 2011, 2013, 2lemetry LLC +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Eclipse Distribution License v. 1.0 which accompanies this distribution. +// The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +// and the Eclipse Distribution License is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// Contributors: +// Kyle Roche - initial API and implementation and/or initial documentation +// + +#import "MQttTxFlow.h" + +@implementation MQttTxFlow + ++ (id)flowWithMsg:(MQTTMessage*)msg + deadline:(unsigned int)deadline { + return [[MQttTxFlow alloc] initWithMsg:msg deadline:deadline]; +} + +- (id)initWithMsg:(MQTTMessage*)aMsg + deadline:(unsigned int)aDeadline { + _msg = aMsg; + _deadline = aDeadline; + return self; +} + +@end diff --git a/AWSIoT/module.modulemap b/AWSIoT/module.modulemap new file mode 100644 index 00000000000..bb6a7b69843 --- /dev/null +++ b/AWSIoT/module.modulemap @@ -0,0 +1,6 @@ +framework module AWSIoT { + umbrella header "AWSIoT.h" + + export * + module * { export * } +} diff --git a/AWSIoTTests/AWSGeneralIoTDataTests.m b/AWSIoTTests/AWSGeneralIoTDataTests.m new file mode 100644 index 00000000000..ecbc2f6492e --- /dev/null +++ b/AWSIoTTests/AWSGeneralIoTDataTests.m @@ -0,0 +1,152 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import +#import +#import "AWSTestUtility.h" +#import "AWSIoT.h" + +static id mockNetworking = nil; + +@interface AWSGeneralIoTDataTests : XCTestCase + +@end + +@implementation AWSGeneralIoTDataTests + +- (void)setUp { + [super setUp]; + [AWSTestUtility setupFakeCognitoCredentialsProvider]; + + mockNetworking = OCMClassMock([AWSNetworking class]); + AWSTask *errorTask = [AWSTask taskWithError:[NSError errorWithDomain:@"OCMockExpectedNetworkingError" code:8848 userInfo:nil]]; + OCMStub([mockNetworking sendRequest:[OCMArg isKindOfClass:[AWSNetworkingRequest class]]]).andReturn(errorTask); +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testConstructors { + NSString *key = @"testIoTDataConstructors"; + XCTAssertNotNil([AWSIoTData defaultIoTData]); + XCTAssertEqual([[AWSIoTData defaultIoTData] class], [AWSIoTData class]); + XCTAssertNil([AWSIoTData IoTDataForKey:key]); + + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:[AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider]; + [AWSIoTData registerIoTDataWithConfiguration:configuration forKey:key]; + XCTAssertNotNil([AWSIoTData IoTDataForKey:key]); + XCTAssertEqual([[AWSIoTData IoTDataForKey:key] class], [AWSIoTData class]); + XCTAssertEqual([AWSIoTData IoTDataForKey:key].configuration.regionType, AWSRegionUSEast1); + + [AWSIoTData removeIoTDataForKey:key]; + XCTAssertNil([AWSIoTData IoTDataForKey:key]); + +} + +- (void)testDeleteThingShadow { + NSString *key = @"testDeleteThingShadow"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoTData registerIoTDataWithConfiguration:configuration forKey:key]; + + AWSIoTData *awsClient = [AWSIoTData IoTDataForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoTData IoTDataForKey:key] deleteThingShadow:[AWSIoTDataDeleteThingShadowRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoTData removeIoTDataForKey:key]; +} + +- (void)testGetThingShadow { + NSString *key = @"testGetThingShadow"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoTData registerIoTDataWithConfiguration:configuration forKey:key]; + + AWSIoTData *awsClient = [AWSIoTData IoTDataForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoTData IoTDataForKey:key] getThingShadow:[AWSIoTDataGetThingShadowRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoTData removeIoTDataForKey:key]; +} + +- (void)testPublish { + NSString *key = @"testPublish"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoTData registerIoTDataWithConfiguration:configuration forKey:key]; + + AWSIoTData *awsClient = [AWSIoTData IoTDataForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoTData IoTDataForKey:key] publish:[AWSIoTDataPublishRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoTData removeIoTDataForKey:key]; +} + +- (void)testUpdateThingShadow { + NSString *key = @"testUpdateThingShadow"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoTData registerIoTDataWithConfiguration:configuration forKey:key]; + + AWSIoTData *awsClient = [AWSIoTData IoTDataForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoTData IoTDataForKey:key] updateThingShadow:[AWSIoTDataUpdateThingShadowRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoTData removeIoTDataForKey:key]; +} + +@end diff --git a/AWSIoTTests/AWSGeneralIoTTests.m b/AWSIoTTests/AWSGeneralIoTTests.m new file mode 100644 index 00000000000..440e59ec0e6 --- /dev/null +++ b/AWSIoTTests/AWSGeneralIoTTests.m @@ -0,0 +1,957 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import +#import +#import "AWSTestUtility.h" +#import "AWSIoT.h" + +static id mockNetworking = nil; + +@interface AWSGeneralIoTTests : XCTestCase + +@end + +@implementation AWSGeneralIoTTests + +- (void)setUp { + [super setUp]; + [AWSTestUtility setupFakeCognitoCredentialsProvider]; + + mockNetworking = OCMClassMock([AWSNetworking class]); + AWSTask *errorTask = [AWSTask taskWithError:[NSError errorWithDomain:@"OCMockExpectedNetworkingError" code:8848 userInfo:nil]]; + OCMStub([mockNetworking sendRequest:[OCMArg isKindOfClass:[AWSNetworkingRequest class]]]).andReturn(errorTask); +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testConstructors { + NSString *key = @"testIoTConstructors"; + XCTAssertNotNil([AWSIoT defaultIoT]); + XCTAssertEqual([[AWSIoT defaultIoT] class], [AWSIoT class]); + XCTAssertNil([AWSIoT IoTForKey:key]); + + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:[AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + XCTAssertNotNil([AWSIoT IoTForKey:key]); + XCTAssertEqual([[AWSIoT IoTForKey:key] class], [AWSIoT class]); + XCTAssertEqual([AWSIoT IoTForKey:key].configuration.regionType, AWSRegionUSEast1); + + [AWSIoT removeIoTForKey:key]; + XCTAssertNil([AWSIoT IoTForKey:key]); + +} + +- (void)testAcceptCertificateTransfer { + NSString *key = @"testAcceptCertificateTransfer"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] acceptCertificateTransfer:[AWSIoTAcceptCertificateTransferRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testAttachPrincipalPolicy { + NSString *key = @"testAttachPrincipalPolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] attachPrincipalPolicy:[AWSIoTAttachPrincipalPolicyRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testAttachThingPrincipal { + NSString *key = @"testAttachThingPrincipal"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] attachThingPrincipal:[AWSIoTAttachThingPrincipalRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCancelCertificateTransfer { + NSString *key = @"testCancelCertificateTransfer"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] cancelCertificateTransfer:[AWSIoTCancelCertificateTransferRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreateCertificateFromCsr { + NSString *key = @"testCreateCertificateFromCsr"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] createCertificateFromCsr:[AWSIoTCreateCertificateFromCsrRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreateKeysAndCertificate { + NSString *key = @"testCreateKeysAndCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] createKeysAndCertificate:[AWSIoTCreateKeysAndCertificateRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreatePolicy { + NSString *key = @"testCreatePolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] createPolicy:[AWSIoTCreatePolicyRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreatePolicyVersion { + NSString *key = @"testCreatePolicyVersion"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] createPolicyVersion:[AWSIoTCreatePolicyVersionRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreateThing { + NSString *key = @"testCreateThing"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] createThing:[AWSIoTCreateThingRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreateTopicRule { + NSString *key = @"testCreateTopicRule"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] createTopicRule:[AWSIoTCreateTopicRuleRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeleteCertificate { + NSString *key = @"testDeleteCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] deleteCertificate:[AWSIoTDeleteCertificateRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeletePolicy { + NSString *key = @"testDeletePolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] deletePolicy:[AWSIoTDeletePolicyRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeletePolicyVersion { + NSString *key = @"testDeletePolicyVersion"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] deletePolicyVersion:[AWSIoTDeletePolicyVersionRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeleteThing { + NSString *key = @"testDeleteThing"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] deleteThing:[AWSIoTDeleteThingRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeleteTopicRule { + NSString *key = @"testDeleteTopicRule"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] deleteTopicRule:[AWSIoTDeleteTopicRuleRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDescribeCertificate { + NSString *key = @"testDescribeCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] describeCertificate:[AWSIoTDescribeCertificateRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDescribeEndpoint { + NSString *key = @"testDescribeEndpoint"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] describeEndpoint:[AWSIoTDescribeEndpointRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDescribeThing { + NSString *key = @"testDescribeThing"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] describeThing:[AWSIoTDescribeThingRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDetachPrincipalPolicy { + NSString *key = @"testDetachPrincipalPolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] detachPrincipalPolicy:[AWSIoTDetachPrincipalPolicyRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDetachThingPrincipal { + NSString *key = @"testDetachThingPrincipal"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] detachThingPrincipal:[AWSIoTDetachThingPrincipalRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testGetLoggingOptions { + NSString *key = @"testGetLoggingOptions"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] getLoggingOptions:[AWSIoTGetLoggingOptionsRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testGetPolicy { + NSString *key = @"testGetPolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] getPolicy:[AWSIoTGetPolicyRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testGetPolicyVersion { + NSString *key = @"testGetPolicyVersion"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] getPolicyVersion:[AWSIoTGetPolicyVersionRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testGetTopicRule { + NSString *key = @"testGetTopicRule"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] getTopicRule:[AWSIoTGetTopicRuleRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListCertificates { + NSString *key = @"testListCertificates"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] listCertificates:[AWSIoTListCertificatesRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListPolicies { + NSString *key = @"testListPolicies"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] listPolicies:[AWSIoTListPoliciesRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListPolicyVersions { + NSString *key = @"testListPolicyVersions"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] listPolicyVersions:[AWSIoTListPolicyVersionsRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListPrincipalPolicies { + NSString *key = @"testListPrincipalPolicies"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] listPrincipalPolicies:[AWSIoTListPrincipalPoliciesRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListPrincipalThings { + NSString *key = @"testListPrincipalThings"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] listPrincipalThings:[AWSIoTListPrincipalThingsRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListThingPrincipals { + NSString *key = @"testListThingPrincipals"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] listThingPrincipals:[AWSIoTListThingPrincipalsRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListThings { + NSString *key = @"testListThings"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] listThings:[AWSIoTListThingsRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListTopicRules { + NSString *key = @"testListTopicRules"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] listTopicRules:[AWSIoTListTopicRulesRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testRejectCertificateTransfer { + NSString *key = @"testRejectCertificateTransfer"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] rejectCertificateTransfer:[AWSIoTRejectCertificateTransferRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testReplaceTopicRule { + NSString *key = @"testReplaceTopicRule"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] replaceTopicRule:[AWSIoTReplaceTopicRuleRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testSetDefaultPolicyVersion { + NSString *key = @"testSetDefaultPolicyVersion"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] setDefaultPolicyVersion:[AWSIoTSetDefaultPolicyVersionRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testSetLoggingOptions { + NSString *key = @"testSetLoggingOptions"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] setLoggingOptions:[AWSIoTSetLoggingOptionsRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testTransferCertificate { + NSString *key = @"testTransferCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] transferCertificate:[AWSIoTTransferCertificateRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testUpdateCertificate { + NSString *key = @"testUpdateCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] updateCertificate:[AWSIoTUpdateCertificateRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testUpdateThing { + NSString *key = @"testUpdateThing"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); + [awsClient setValue:mockNetworking forKey:@"networking"]; + [[[[AWSIoT IoTForKey:key] updateThing:[AWSIoTUpdateThingRequest new]] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +@end diff --git a/AWSIoTTests/AWSIoTTests.m b/AWSIoTTests/AWSIoTTests.m new file mode 100644 index 00000000000..ca5725baf45 --- /dev/null +++ b/AWSIoTTests/AWSIoTTests.m @@ -0,0 +1,933 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import +#import +#import +#import "AWSIoT.h" + +static id mockNetworking = nil; +static NSString *certificateID = nil; + +@interface AWSIoTUnitTests : XCTestCase + +@end + +@implementation AWSIoTUnitTests + +- (void)setupCredentialsProvider { + + AWSStaticCredentialsProvider *credentialsProvider = [[AWSStaticCredentialsProvider alloc] initWithAccessKey:@"testAccessKey" secretKey:@"testSecretKey"]; + + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 + credentialsProvider:credentialsProvider]; + [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; + +} + +- (void)setUp { + [super setUp]; + [self setupCredentialsProvider]; + + mockNetworking = OCMClassMock([AWSNetworking class]); + AWSTask *errorTask = [AWSTask taskWithError:[NSError errorWithDomain:@"OCMockExpectedNetworkingError" code:8848 userInfo:nil]]; + OCMStub([mockNetworking sendRequest:[OCMArg isKindOfClass:[AWSNetworkingRequest class]]]).andReturn(errorTask); + + certificateID = @"test_cert_ID"; + +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testConstructors { + NSString *key = @"testIOTConstructors"; + XCTAssertNotNil([AWSIoT defaultIoT]); + XCTAssertEqual([[AWSIoT defaultIoT] class], [AWSIoT class]); + XCTAssertNil([AWSIoT IoTForKey:key]); + + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:[AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + XCTAssertNotNil([AWSIoT IoTForKey:key]); + XCTAssertEqual([[AWSIoT IoTForKey:key] class], [AWSIoT class]); + XCTAssertEqual([AWSIoT IoTForKey:key].configuration.regionType, AWSRegionUSEast1); + + [AWSIoT removeIoTForKey:key]; + XCTAssertNil([AWSIoT IoTForKey:key]); + +} + +- (void)testDescribeCertificate { + NSString *key = @"testDescribeCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDescribeCertificateRequest *request = [[AWSIoTDescribeCertificateRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] describeCertificate:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreatePolicy { + NSString *key = @"testCreatePolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTCreatePolicyRequest *request = [[AWSIoTCreatePolicyRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] createPolicy:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testAttachPrincipalPolicy { + NSString *key = @"testAttachPrincipalPolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTAttachPrincipalPolicyRequest *request = [[AWSIoTAttachPrincipalPolicyRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] attachPrincipalPolicy:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testAttachThingPrincipal { + NSString *key = @"testAttachThingPrincipal"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTAttachThingPrincipalRequest *request = [[AWSIoTAttachThingPrincipalRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] attachThingPrincipal:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCancelCertificateTransfer { + NSString *key = @"testCancelCertificateTransfer"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTCancelCertificateTransferRequest *request = [[AWSIoTCancelCertificateTransferRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] cancelCertificateTransfer:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreatePolicyVersion { + NSString *key = @"testCreatePolicyVersion"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTCreatePolicyVersionRequest *request = [[AWSIoTCreatePolicyVersionRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] createPolicyVersion:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreateThing { + NSString *key = @"testCreateThing"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTCreateThingRequest *request = [[AWSIoTCreateThingRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] createThing:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testCreateTopicRule { + NSString *key = @"testCreateTopicRule"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTCreateTopicRuleRequest *request = [[AWSIoTCreateTopicRuleRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] createTopicRule:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeleteCertificate { + NSString *key = @"testDeleteCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDeleteCertificateRequest *request = [[AWSIoTDeleteCertificateRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] deleteCertificate:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeletePolicy { + NSString *key = @"testDeletePolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDeletePolicyRequest *request = [[AWSIoTDeletePolicyRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] deletePolicy:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeletePolicyVersion { + NSString *key = @"testDeletePolicyVersion"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDeletePolicyVersionRequest *request = [[AWSIoTDeletePolicyVersionRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] deletePolicyVersion:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeleteThing { + NSString *key = @"testDeleteThing"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDeleteThingRequest *request = [[AWSIoTDeleteThingRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] deleteThing:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDeleteTopicRule { + NSString *key = @"testDeleteTopicRule"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDeleteTopicRuleRequest *request = [[AWSIoTDeleteTopicRuleRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] deleteTopicRule:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDescribeThing { + NSString *key = @"testDescribeThing"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDescribeThingRequest *request = [[AWSIoTDescribeThingRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] describeThing:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testDetachPrincipalPolicy { + NSString *key = @"testDetachPrincipalPolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDetachPrincipalPolicyRequest *request = [[AWSIoTDetachPrincipalPolicyRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] detachPrincipalPolicy:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +//- (AWSTask *)detachThingPrincipal:(AWSIoTDetachThingPrincipalRequest *)request; +- (void)testDetachThingPrincipal { + NSString *key = @"testDetachThingPrincipal"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTDetachThingPrincipalRequest *request = [[AWSIoTDetachThingPrincipalRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] detachThingPrincipal:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testGetPolicy { + NSString *key = @"testGetPolicy"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTGetPolicyRequest *request = [[AWSIoTGetPolicyRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] getPolicy:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testGetPolicyVersion { + NSString *key = @"testGetPolicyVersion"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTGetPolicyVersionRequest *request = [[AWSIoTGetPolicyVersionRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] getPolicyVersion:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testGetTopicRule { + NSString *key = @"testGetTopicRule"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTGetTopicRuleRequest *request = [[AWSIoTGetTopicRuleRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] getTopicRule:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListCertificates { + NSString *key = @"testListCertificates"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTListCertificatesRequest *request = [[AWSIoTListCertificatesRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] listCertificates:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListPolicies { + NSString *key = @"testListPolicies"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTListPoliciesRequest *request = [[AWSIoTListPoliciesRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] listPolicies:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListPolicyVersions { + NSString *key = @"testListPolicyVersions"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTListPolicyVersionsRequest *request = [[AWSIoTListPolicyVersionsRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] listPolicyVersions:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListPrincipalPolicies { + NSString *key = @"testListPrincipalPolicies"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTListPrincipalPoliciesRequest *request = [[AWSIoTListPrincipalPoliciesRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] listPrincipalPolicies:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListPrincipalThings { + NSString *key = @"testListPrincipalThings"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTListPrincipalThingsRequest *request = [[AWSIoTListPrincipalThingsRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] listPrincipalThings:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListThingPrincipals { + NSString *key = @"testListThingPrincipals"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTListThingPrincipalsRequest *request = [[AWSIoTListThingPrincipalsRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] listThingPrincipals:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListThings { + NSString *key = @"testListThings"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTListThingsRequest *request = [[AWSIoTListThingsRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] listThings:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testListTopicRules { + NSString *key = @"testListTopicRules"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTListTopicRulesRequest *request = [[AWSIoTListTopicRulesRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] listTopicRules:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testRejectCertificateTransfer { + NSString *key = @"testRejectCertificateTransfer"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTRejectCertificateTransferRequest *request = [[AWSIoTRejectCertificateTransferRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] rejectCertificateTransfer:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testReplaceTopicRule { + NSString *key = @"testReplaceTopicRule"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTReplaceTopicRuleRequest *request = [[AWSIoTReplaceTopicRuleRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] replaceTopicRule:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testSetDefaultPolicyVersion { + NSString *key = @"testSetDefaultPolicyVersion"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTSetDefaultPolicyVersionRequest *request = [[AWSIoTSetDefaultPolicyVersionRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] setDefaultPolicyVersion:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testTransferCertificate { + NSString *key = @"testTransferCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTTransferCertificateRequest *request = [[AWSIoTTransferCertificateRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] transferCertificate:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testUpdateCertificate { + NSString *key = @"testUpdateCertificate"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTUpdateCertificateRequest *request = [[AWSIoTUpdateCertificateRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] updateCertificate:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + +- (void)testUpdateThing { + NSString *key = @"testUpdateThing"; + AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil]; + [AWSIoT registerIoTWithConfiguration:configuration forKey:key]; + + AWSIoT *awsClient = [AWSIoT IoTForKey:key]; + XCTAssertNotNil(awsClient); + XCTAssertNotNil(mockNetworking); [awsClient setValue:mockNetworking forKey:@"networking"]; + + AWSIoTUpdateThingRequest *request = [[AWSIoTUpdateThingRequest alloc] init]; + XCTAssertNotNil(request); + + [[[[AWSIoT IoTForKey:key] updateThing:request] continueWithBlock:^id(AWSTask *task) { + XCTAssertNotNil(task.error); + XCTAssertEqualObjects(@"OCMockExpectedNetworkingError", task.error.domain); + XCTAssertEqual(8848, task.error.code); + XCTAssertNil(task.exception); + XCTAssertNil(task.result); + return nil; + }] waitUntilFinished]; + + OCMVerify([mockNetworking sendRequest:[OCMArg isNotNil]]); + + [AWSIoT removeIoTForKey:key]; +} + + +@end diff --git a/AWSIoTTests/Info.plist b/AWSIoTTests/Info.plist new file mode 100644 index 00000000000..ba72822e872 --- /dev/null +++ b/AWSIoTTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/AWSKinesis.podspec b/AWSKinesis.podspec index 88a5f7ec849..1e6fac6c55f 100644 --- a/AWSKinesis.podspec +++ b/AWSKinesis.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'AWSKinesis' - s.version = '2.3.1' + s.version = '2.3.2' s.summary = 'Amazon Web Services SDK for iOS.' s.description = 'The AWS SDK for iOS provides a library, code samples, and documentation for developers to build connected mobile applications using AWS.' @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSKinesis/*.{h,m}' end diff --git a/AWSKinesis.xcodeproj/project.pbxproj b/AWSKinesis.xcodeproj/project.pbxproj index 6fe2d2816e4..ec9bbbb3de7 100644 --- a/AWSKinesis.xcodeproj/project.pbxproj +++ b/AWSKinesis.xcodeproj/project.pbxproj @@ -36,6 +36,13 @@ CE27CB5C1BF1885700B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB5B1BF1885700B22AB3 /* UIKit.framework */; }; CE27CB5D1BF1885C00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB5B1BF1885700B22AB3 /* UIKit.framework */; }; CE2EDE981BF3DF2F00B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6552361BEC363600DACBC2 /* module.modulemap */; }; + CE6A6DB71C03E50F006F986B /* AWSAbstractKinesisRecorder.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CEDEC21A1BFD640100BE16EA /* AWSAbstractKinesisRecorder.h */; }; + CEB3802B1C177F19008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3802A1C177F19008B520C /* SystemConfiguration.framework */; }; + CEB380411C177FA3008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3802A1C177F19008B520C /* SystemConfiguration.framework */; }; + CEB380611C1780A5008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380601C1780A5008B520C /* Security.framework */; }; + CEB380621C1780A9008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380601C1780A5008B520C /* Security.framework */; }; + CEDEC21C1BFD640100BE16EA /* AWSAbstractKinesisRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = CEDEC21A1BFD640100BE16EA /* AWSAbstractKinesisRecorder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEDEC21D1BFD640100BE16EA /* AWSAbstractKinesisRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDEC21B1BFD640100BE16EA /* AWSAbstractKinesisRecorder.m */; }; CEE532661B03D3B2002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE532651B03D3B2002CED62 /* libz.dylib */; }; CEE7DE711AC1E1AF0095C4B7 /* AWSKinesisService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE701AC1E1AF0095C4B7 /* AWSKinesisService.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -64,6 +71,7 @@ dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( + CE6A6DB71C03E50F006F986B /* AWSAbstractKinesisRecorder.h in CopyFiles */, BD9D97621AC1EEAE00CEEE08 /* AWSKinesisService.h in CopyFiles */, BDC91C4D1ABBA0C600F74D49 /* AWSKinesis.h in CopyFiles */, BDC91C4E1ABBA0C600F74D49 /* AWSKinesisModel.h in CopyFiles */, @@ -107,6 +115,10 @@ CE14DF8C1B02DEBC00EF6D09 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; CE27CB5B1BF1885700B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE6552361BEC363600DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB3802A1C177F19008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB380601C1780A5008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + CEDEC21A1BFD640100BE16EA /* AWSAbstractKinesisRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSAbstractKinesisRecorder.h; sourceTree = ""; }; + CEDEC21B1BFD640100BE16EA /* AWSAbstractKinesisRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSAbstractKinesisRecorder.m; sourceTree = ""; }; CEE532651B03D3B2002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE701AC1E1AF0095C4B7 /* AWSKinesisService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSKinesisService.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -116,6 +128,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380621C1780A9008B520C /* Security.framework in Frameworks */, + CEB3802B1C177F19008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB5D1BF1885C00B22AB3 /* UIKit.framework in Frameworks */, BDD876AA1B4B52E3009268C7 /* libOCMock.a in Frameworks */, BDF125C91B45C1D000DFBFEC /* libz.dylib in Frameworks */, @@ -136,6 +150,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380611C1780A5008B520C /* Security.framework in Frameworks */, + CEB380411C177FA3008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB5C1BF1885700B22AB3 /* UIKit.framework in Frameworks */, CEE532661B03D3B2002CED62 /* libz.dylib in Frameworks */, CE14DF8D1B02DEBC00EF6D09 /* libsqlite3.dylib in Frameworks */, @@ -152,8 +168,8 @@ children = ( BDF559BB1AB376720067F4F1 /* AWSKinesis */, BDF559C81AB376720067F4F1 /* AWSKinesisTests */, - BDF559BA1AB376720067F4F1 /* Products */, D34BD40ED7327D8616BDFE58 /* Frameworks */, + BDF559BA1AB376720067F4F1 /* Products */, ); sourceTree = ""; }; @@ -170,16 +186,18 @@ BDF559BB1AB376720067F4F1 /* AWSKinesis */ = { isa = PBXGroup; children = ( - CE6552361BEC363600DACBC2 /* module.modulemap */, + CEDEC21A1BFD640100BE16EA /* AWSAbstractKinesisRecorder.h */, + CEDEC21B1BFD640100BE16EA /* AWSAbstractKinesisRecorder.m */, BDF559D51AB376A50067F4F1 /* AWSKinesis.h */, BDF559D71AB376A50067F4F1 /* AWSKinesisModel.h */, BDF559D81AB376A50067F4F1 /* AWSKinesisModel.m */, BDF559D91AB376A50067F4F1 /* AWSKinesisRecorder.h */, BDF559DA1AB376A50067F4F1 /* AWSKinesisRecorder.m */, - CEE7DE701AC1E1AF0095C4B7 /* AWSKinesisService.h */, - BDF559D61AB376A50067F4F1 /* AWSKinesisService.m */, BDB73D791B1D3EFC00717559 /* AWSKinesisResources.h */, BDB73D7A1B1D3EFC00717559 /* AWSKinesisResources.m */, + CEE7DE701AC1E1AF0095C4B7 /* AWSKinesisService.h */, + BDF559D61AB376A50067F4F1 /* AWSKinesisService.m */, + CE6552361BEC363600DACBC2 /* module.modulemap */, ); path = AWSKinesis; sourceTree = ""; @@ -209,6 +227,8 @@ D34BD40ED7327D8616BDFE58 /* Frameworks */ = { isa = PBXGroup; children = ( + CEB380601C1780A5008B520C /* Security.framework */, + CEB3802A1C177F19008B520C /* SystemConfiguration.framework */, CE27CB5B1BF1885700B22AB3 /* UIKit.framework */, BDD876A91B4B52E3009268C7 /* libOCMock.a */, CEE532651B03D3B2002CED62 /* libz.dylib */, @@ -230,6 +250,7 @@ BDF559DD1AB376A50067F4F1 /* AWSKinesis.h in Headers */, CEE7DE711AC1E1AF0095C4B7 /* AWSKinesisService.h in Headers */, BDB73D7B1B1D3EFC00717559 /* AWSKinesisResources.h in Headers */, + CEDEC21C1BFD640100BE16EA /* AWSAbstractKinesisRecorder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -297,7 +318,7 @@ BDF559B11AB376720067F4F1 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDF559B81AB376720067F4F1 = { @@ -359,6 +380,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + CEDEC21D1BFD640100BE16EA /* AWSAbstractKinesisRecorder.m in Sources */, BDB73D7C1B1D3EFC00717559 /* AWSKinesisResources.m in Sources */, BDF559E21AB376A50067F4F1 /* AWSKinesisRecorder.m in Sources */, BDF559E01AB376A50067F4F1 /* AWSKinesisModel.m in Sources */, diff --git a/AWSKinesis.xcodeproj/xcshareddata/xcschemes/AWSKinesis.xcscheme b/AWSKinesis.xcodeproj/xcshareddata/xcschemes/AWSKinesis.xcscheme index f00cbec7dc0..2438c176495 100644 --- a/AWSKinesis.xcodeproj/xcshareddata/xcschemes/AWSKinesis.xcscheme +++ b/AWSKinesis.xcodeproj/xcshareddata/xcschemes/AWSKinesis.xcscheme @@ -1,6 +1,6 @@ +#import + +/** + `AWSAbstractKinesisRecorder` is an abstract class. You should not instantiate this class directly. Instead use its concrete subclasses `AWSKinesisRecorder` and `AWSFirehoseRecorder`. + */ +@interface AWSAbstractKinesisRecorder : AWSService + +/** + The number of bytes currently used to store AWSKinesisPutRecordInput objects on disk. + */ +@property (nonatomic, assign, readonly) NSUInteger diskBytesUsed; + +/** + The threshold of disk bytes for notification. When exceeded, `saveRecord:streamName:` posts AWSKinesisRecorderByteThresholdReachedNotification. The default is 0 meaning it will not post the notification. + @discussion The `notificationByteThreshold` should be smaller than `diskByteLimit`. + */ +@property (nonatomic, assign) NSUInteger notificationByteThreshold; + +/** + The limit of the disk cache size in bytes. When exceeded, older requests will be discarded. Setting this value to 0.0 meaning no practical limit. The default value is 5MB. + */ +@property (nonatomic, assign) NSUInteger diskByteLimit; + +/** + The age limit of the cached requests. When exceeded, requests older than the specified age will be discarded. Setting this value to 0 meaning no practical limit. The default is no age limit. + */ +@property (nonatomic, assign) NSTimeInterval diskAgeLimit; + +/** + The maxium batch data size in bytes. The default value is 512KB. The maximum is 4MB. + */ +@property (nonatomic, assign) NSUInteger batchRecordsByteLimit; + +/** + Saves a record to local storage to be sent later. The record will be submitted to the streamName provided with a randomly generated partition key to ensure equal distribution across shards. + + @param data The data to send to Amazon Kinesis. It needs to be smaller than 256KB. + @param streamName The stream name for Amazon Kinesis. + + @return AWSTask - task.result is always nil. + */ +- (AWSTask *)saveRecord:(NSData *)data + streamName:(NSString *)streamName; + +/** + Submits all locally saved requests to Amazon Kinesis. Requests that are successfully sent will be deleted from the device. Requests that fail due to the device being offline will stop the submission process and be kept. Requests that fail due to other reasons (such as the request being invalid) will be deleted. + + @return AWSTask - task.result is always nil. + */ +- (AWSTask *)submitAllRecords; + +/** + Removes all requests saved to disk. + + @return AWSTask - task.result is always nil. + */ +- (AWSTask *)removeAllRecords; + +@end diff --git a/AWSKinesis/AWSAbstractKinesisRecorder.m b/AWSKinesis/AWSAbstractKinesisRecorder.m new file mode 100644 index 00000000000..52d35c604ab --- /dev/null +++ b/AWSKinesis/AWSAbstractKinesisRecorder.m @@ -0,0 +1,360 @@ +/* + Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + A copy of the License is located at + + http://aws.amazon.com/apache2.0 + + or in the "license" file accompanying this file. This file is distributed + on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. See the License for the specific language governing + permissions and limitations under the License. + */ + +#import "AWSAbstractKinesisRecorder.h" +#import "AWSKinesis.h" +#import "AWSBolts.h" +#import "AWSLogging.h" +#import "AWSCategory.h" +#import "AWSFMDB.h" +#import "AWSSynchronizedMutableDictionary.h" + +// Kinesis Abstract Client +NSUInteger const AWSKinesisAbstractClientByteLimitDefault = 5 * 1024 * 1024; // 5MB +NSTimeInterval const AWSKinesisAbstractClientAgeLimitDefault = 0.0; // Keeps the data indefinitely unless it hits the size limit. +NSString *const AWSKinesisAbstractClientUserAgent = @"recorder"; +NSUInteger const AWSKinesisAbstractClientBatchRecordByteLimitDefault = 512 * 1024 * 1024; +NSString *const AWSKinesisAbstractClientRecorderDatabasePathPrefix = @"com/amazonaws/AWSKinesisRecorder"; + +@protocol AWSKinesisRecorderHelper + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration; + +- (AWSTask *)submitRecordsForStream:(NSString *)streamName + records:(NSArray *)temporaryRecords + partitionKeys:(NSArray *)partitionKeys + putPartitionKeys:(NSMutableArray *)putPartitionKeys + retryPartitionKeys:(NSMutableArray *)retryPartitionKeys; + +- (NSError *)dataTooLargeError; + +- (void)checkByteThresholdForNotification:(NSUInteger)notificationByteThreshold + notificationSender:(id)notificationSender + fileSize:(NSUInteger)fileSize; + +@end + +@interface AWSAbstractKinesisRecorder() + +@property (nonatomic, strong) id recorderHelper; +@property (nonatomic, strong) AWSFMDatabaseQueue *databaseQueue; +@property (nonatomic, strong) NSString *databasePath; + +@end + +@implementation AWSAbstractKinesisRecorder + +- (instancetype)init { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"You must use subslasses of `AWSAbstractKinesisRecorder`. Use `AWSKinesisRecorder` or `AWSFirehoseRecorder`." + userInfo:nil]; +} + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration + identifier:(NSString *)identifier + cacheName:(NSString *)cacheName { + if (self = [super init]) { + AWSServiceConfiguration *_configuration = [configuration copy]; + [_configuration addUserAgentProductToken:AWSKinesisAbstractClientUserAgent]; + NSString *databaseDirectoryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:AWSKinesisAbstractClientRecorderDatabasePathPrefix]; + + _databasePath = [databaseDirectoryPath stringByAppendingPathComponent:identifier]; + _diskByteLimit = AWSKinesisAbstractClientByteLimitDefault; + _diskAgeLimit = AWSKinesisAbstractClientAgeLimitDefault; + _batchRecordsByteLimit = AWSKinesisAbstractClientBatchRecordByteLimitDefault; + + // Creates a directory for storing databases if it doesn't exist. + BOOL fileExistsAtPath = [[NSFileManager defaultManager] fileExistsAtPath:databaseDirectoryPath]; + if (!fileExistsAtPath) { + NSError *error = nil; + BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:databaseDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (!success) { + AWSLogError(@"Failed to create a directory for database. [%@]", error); + } + } + + // Creates a database for the identifier if it doesn't exist. + AWSLogDebug(@"Database path: [%@]", _databasePath); + _databaseQueue = [AWSFMDatabaseQueue databaseQueueWithPath:_databasePath]; + [_databaseQueue inDatabase:^(AWSFMDatabase *db) { + if (![db executeStatements:@"PRAGMA auto_vacuum = FULL"]) { + AWSLogError(@"Failed to enable 'aut_vacuum' to 'FULL'. %@", db.lastError); + } + + if (![db executeUpdate: + @"CREATE TABLE IF NOT EXISTS record (" + @"partition_key TEXT NOT NULL," + @"stream_name TEXT NOT NULL," + @"data BLOB NOT NULL," + @"timestamp REAL NOT NULL," + @"retry_count INTEGER NOT NULL)"]) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + } + + if (![db executeUpdate:@"VACUUM"]) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + } + }]; + } + return self; +} + ++ (dispatch_queue_t)sharedQueue { + static dispatch_queue_t queue; + static dispatch_once_t predicate; + + dispatch_once(&predicate, ^{ + queue = dispatch_queue_create("com.amazonaws.AWSKinesisRecorder", DISPATCH_QUEUE_SERIAL); + }); + + return queue; +} + +- (AWSTask *)saveRecord:(NSData *)data + streamName:(NSString *)streamName { + // Returns error if the total size of data and partition key exceeds 256KB. + if ([data length] > 256 * 1024) { + return [AWSTask taskWithError:[self.recorderHelper dataTooLargeError]]; + } + + AWSFMDatabaseQueue *databaseQueue = self.databaseQueue; + NSTimeInterval diskAgeLimit = self.diskAgeLimit; + NSString *databasePath = self.databasePath; + NSUInteger notificationByteThreshold = self.notificationByteThreshold; + NSUInteger diskByteLimit = self.diskByteLimit; + __weak id notificationSender = self; + + return [[AWSTask taskWithResult:nil] continueWithSuccessBlock:^id(AWSTask *task) { + // Inserts a new record to the database. + __block NSError *error = nil; + [databaseQueue inDatabase:^(AWSFMDatabase *db) { + BOOL result = [db executeUpdate: + @"INSERT INTO record (" + @"partition_key, stream_name, data, timestamp, retry_count" + @") VALUES (" + @":partition_key, :stream_name, :data, :timestamp, :retry_count" + @")" + withParameterDictionary:@{ + @"partition_key" : [[NSUUID UUID] UUIDString], + @"stream_name" : streamName, + @"data" : data, + @"timestamp" : @([[NSDate date] timeIntervalSince1970]), + @"retry_count" : @0 + } + ]; + + + if (!result) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + error = db.lastError; + } + }]; + + if (!error && diskAgeLimit > 0) { + [databaseQueue inDatabase:^(AWSFMDatabase *db) { + // Deletes old records exceeding the threshold. + BOOL result = [db executeUpdate: + @"DELETE FROM record " + @"WHERE timestamp < :timestamp" + withParameterDictionary:@{ + @"timestamp" : @([[NSDate date] timeIntervalSince1970] - diskAgeLimit) + } + ]; + if (!result) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + error = db.lastError; + } + }]; + } + + if (error) { + return [AWSTask taskWithError:error]; + } + + NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:databasePath + error:&error]; + if (attributes) { + NSUInteger fileSize = (NSUInteger)[attributes fileSize]; + [self.recorderHelper checkByteThresholdForNotification:notificationByteThreshold + notificationSender:notificationSender + fileSize:fileSize]; + if (fileSize > diskByteLimit) { + // Deletes the oldest record if it exceeds the disk size threshold. + [databaseQueue inDatabase:^(AWSFMDatabase *db) { + BOOL result = [db executeUpdate: + @"DELETE FROM record " + @"WHERE partition_key IN ( " + @"SELECT partition_key " + @"FROM record " + @"ORDER BY timestamp ASC " + @"LIMIT 1 " + @")" + ]; + if (!result) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + error = db.lastError; + return; + } + }]; + + } + } else if (error) { + return [AWSTask taskWithError:error]; + } + + return nil; + }]; +} + +- (AWSTask *)submitAllRecords { + AWSFMDatabaseQueue *databaseQueue = self.databaseQueue; + + return [[AWSTask taskWithResult:nil] continueWithExecutor:[AWSExecutor executorWithDispatchQueue:[AWSKinesisRecorder sharedQueue]] withSuccessBlock:^id _Nullable(AWSTask * _Nonnull task) { + __block NSError *error = nil; + __block NSUInteger batchSize = 0; + + do { + [databaseQueue inTransaction:^(AWSFMDatabase *db, BOOL *rollback) { + NSMutableArray *partitionKeys = nil; + + AWSFMResultSet *rs = [db executeQuery: + @"SELECT partition_key, data, retry_count, stream_name " + @"FROM record " + @"WHERE stream_name = (SELECT stream_name FROM record ORDER BY timestamp ASC LIMIT 1) " + @"ORDER BY timestamp ASC " + @"LIMIT 128"]; + if (!rs) { + AWSLogError(@"SQLite error. Rolling back... [%@]", db.lastError); + error = db.lastError; + *rollback = YES; + return; + } + + NSUInteger batchDataSize = 0; + NSMutableArray *temporaryRecords = [NSMutableArray new]; + partitionKeys = [NSMutableArray new]; + while ([rs next]) { + [temporaryRecords addObject:@{ + @"partition_key": [rs stringForColumn:@"partition_key"], + @"data": [rs dataForColumn:@"data"], + @"stream_name": [rs stringForColumn:@"stream_name"], + }]; + + [partitionKeys addObject:[rs stringForColumn:@"partition_key"]]; + batchDataSize += [[rs dataForColumn:@"data"] length]; + + if (batchDataSize > self.batchRecordsByteLimit) { // if the batch size exceeds `batchRecordsByteLimit`, stop there. + break; + } + } + rs = nil; + batchSize = [temporaryRecords count]; + + if (batchSize > 0) { + __block NSMutableArray *putPartitionKeys = [NSMutableArray new]; + __block NSMutableArray *retryPartitionKeys = [NSMutableArray new]; + + NSString *streamName = temporaryRecords[0][@"stream_name"]; + + [[self.recorderHelper submitRecordsForStream:streamName + records:temporaryRecords + partitionKeys:partitionKeys + putPartitionKeys:putPartitionKeys + retryPartitionKeys:retryPartitionKeys] waitUntilFinished]; + + for (NSString *partitionKey in putPartitionKeys) { + BOOL result = [db executeUpdate:@"DELETE FROM record WHERE partition_key = :partition_key" + withParameterDictionary:@{ + @"partition_key" : partitionKey + }]; + if (!result) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + error = db.lastError; + } + } + + for (NSString *partitionKey in retryPartitionKeys) { + BOOL result = [db executeUpdate:@"UPDATE record SET retry_count = retry_count + 1 WHERE partition_key = :partition_key" + withParameterDictionary:@{ + @"partition_key" : partitionKey + }]; + if (!result) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + error = db.lastError; + } + } + } + + // If a record failed three times, give up and delete the record. + BOOL result = [db executeUpdate:@"DELETE FROM record WHERE retry_count > 3"]; + if (!result) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + error = db.lastError; + } + }]; + } while (!error && batchSize > 0); + + if (error) { + return [AWSTask taskWithError:error]; + } + + return nil; + }]; +} + +- (AWSTask *)removeAllRecords { + AWSFMDatabaseQueue *databaseQueue = self.databaseQueue; + + return [[AWSTask taskWithResult:nil] continueWithSuccessBlock:^id(AWSTask *task) { + __block NSError *error = nil; + [databaseQueue inDatabase:^(AWSFMDatabase *db) { + if (![db executeUpdate:@"DELETE FROM record"]) { + AWSLogError(@"SQLite error. [%@]", db.lastError); + error = db.lastError; + } + }]; + + if (error) { + return [AWSTask taskWithError:error]; + } + + return nil; + }]; +} + +- (NSUInteger)diskBytesUsed { + NSError *error = nil; + NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.databasePath + error:&error]; + if (attributes) { + return (NSUInteger)[attributes fileSize]; + } else { + AWSLogError(@"Error [%@]", error); + return 0; + } +} + +- (void)setBatchRecordsByteLimit:(NSUInteger)batchRecordsByteLimit { + if (batchRecordsByteLimit > 4 * 1024 * 1024) { + _batchRecordsByteLimit = 4 * 1024 * 1024; + } else { + _batchRecordsByteLimit = batchRecordsByteLimit; + } +} + +@end diff --git a/AWSKinesis/AWSKinesis.h b/AWSKinesis/AWSKinesis.h index 8597175154e..9793d26e717 100644 --- a/AWSKinesis/AWSKinesis.h +++ b/AWSKinesis/AWSKinesis.h @@ -15,5 +15,6 @@ #import #import + #import "AWSKinesisService.h" #import "AWSKinesisRecorder.h" diff --git a/AWSKinesis/AWSKinesisRecorder.h b/AWSKinesis/AWSKinesisRecorder.h index 94ea3edfb81..9aabdc08425 100644 --- a/AWSKinesis/AWSKinesisRecorder.h +++ b/AWSKinesis/AWSKinesisRecorder.h @@ -14,7 +14,7 @@ */ #import -#import +#import "AWSAbstractKinesisRecorder.h" @class AWSTask; @@ -40,28 +40,7 @@ FOUNDATION_EXPORT NSString *const AWSKinesisRecorderByteThresholdReachedNotifica The AWSKinesisRecorder is a high level client meant for storing put record requests on the user's device. This allows developers to retain requests when the device is offline. It can also increase performance and battery efficiency since the Wi-Fi or cell network does not need to be woken up as frequently. @discussion AWSKinesisRecorder stores the requests unencripted and does not perform additional security measures outside of what the iOS offers by default. Therefore, it is recommended not to store highly sensitive information using AWSKinesisRecorder. */ -@interface AWSKinesisRecorder : AWSService - -/** - The number of bytes currently used to store AWSKinesisPutRecordInput objects on disk. - */ -@property (nonatomic, assign, readonly) NSUInteger diskBytesUsed; - -/** - The threshold of disk bytes for notification. When exceeded, `saveRecord:streamName:` posts AWSKinesisRecorderByteThresholdReachedNotification. The default is 0 meaning it will not post the notification. - @discussion The `notificationByteThreshold` should be smaller than `diskByteLimit`. - */ -@property (nonatomic, assign) NSUInteger notificationByteThreshold; - -/** - The limit of the disk cache size in bytes. When exceeded, older requests will be discarded. Setting this value to 0.0 meaning no practical limit. The default value is 5MB. - */ -@property (nonatomic, assign) NSUInteger diskByteLimit; - -/** - The age limit of the cached requests. When exceeded, requests older than the specified age will be discarded. Setting this value to 0 meaning no practical limit. The default is no age limit. - */ -@property (nonatomic, assign) NSTimeInterval diskAgeLimit; +@interface AWSKinesisRecorder : AWSAbstractKinesisRecorder /** Returns a shared instance of this service client using `[AWSServiceManager defaultServiceManager].defaultServiceConfiguration`. When `defaultServiceConfiguration` is not set, this method returns nil. @@ -202,42 +181,4 @@ FOUNDATION_EXPORT NSString *const AWSKinesisRecorderByteThresholdReachedNotifica */ + (void)removeKinesisRecorderForKey:(NSString *)key; -/** - Returns an instance of this service client using `configuration` and `identifier`. - - @warning This method has been deprecated. Use `+ registerKinesisRecorderWithConfiguration:forKey:` and `+ KinesisRecorderForKey:` instead. - - @param configuration An object to configure the internal `AWSKinesis`. At least `regionType` and `credentialsProvider` need to be set. - @param identifier An unique identifier for AWSKinesisRecorder to create a disk cache. Multiple instances with the same identifier are allowed and can safely access the same data on disk. - - @return An instance of this service client. - */ -- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration - identifier:(NSString *)identifier __attribute__ ((deprecated("Use '+ registerKinesisRecorderWithConfiguration:forKey:' and '+ KinesisRecorderForKey:' instead."))); - -/** - Saves a record to local storage to be sent later. The record will be submitted to the streamName provided with a randomly generated partition key to ensure equal distribution across shards. - - @param data The data to send to Amazon Kinesis. - @param streamName The stream name for Amazon Kinesis. - - @return AWSTask - task.result is always nil. - */ -- (AWSTask *)saveRecord:(NSData *)data - streamName:(NSString *)streamName; - -/** - Submits all locally saved requests to Amazon Kinesis. Requests that are successfully sent will be deleted from the device. Requests that fail due to the device being offline will stop the submission process and be kept. Requests that fail due to other reasons (such as the request being invalid) will be deleted. - - @return AWSTask - task.result is always nil. - */ -- (AWSTask *)submitAllRecords; - -/** - Removes all requests saved to disk. - - @return AWSTask - task.result is always nil. - */ -- (AWSTask *)removeAllRecords; - @end diff --git a/AWSKinesis/AWSKinesisRecorder.m b/AWSKinesis/AWSKinesisRecorder.m index 1ad50459276..90d0d0d16b3 100644 --- a/AWSKinesis/AWSKinesisRecorder.m +++ b/AWSKinesis/AWSKinesisRecorder.m @@ -15,29 +15,35 @@ #import "AWSKinesisRecorder.h" #import "AWSKinesis.h" -#import "AWSBolts.h" -#import "AWSLogging.h" -#import "AWSCategory.h" -#import "AWSFMDB.h" #import "AWSSynchronizedMutableDictionary.h" +// Constants NSString *const AWSKinesisRecorderErrorDomain = @"com.amazonaws.AWSKinesisRecorderErrorDomain"; - NSString *const AWSKinesisRecorderByteThresholdReachedNotification = @"com.amazonaws.AWSKinesisRecorderByteThresholdReachedNotification"; NSString *const AWSKinesisRecorderByteThresholdReachedNotificationDiskBytesUsedKey = @"diskBytesUsed"; -NSString *const AWSKinesisRecorderDatabasePathPrefix = @"com/amazonaws/AWSKinesisRecorder"; -NSUInteger const AWSKinesisRecorderByteLimitDefault = 5 * 1024 * 1024; // 5MB -NSTimeInterval const AWSKinesisRecorderAgeLimitDefault = 0.0; // Keeps the data indefinitely unless it hits the size limit. -NSString *const AWSKinesisRecorderUserAgent = @"recorder"; // Legacy constants NSString *const AWSKinesisRecorderCacheName = @"com.amazonaws.AWSKinesisRecorderCacheName.Cache"; -@interface AWSKinesisRecorder() +@protocol AWSKinesisRecorderHelper + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration; + +@end + +@interface AWSKinesisRecorderHelper : NSObject @property (nonatomic, strong) AWSKinesis *kinesis; -@property (nonatomic, strong) AWSFMDatabaseQueue *databaseQueue; -@property (nonatomic, strong) NSString *databasePath; + +@end + +@interface AWSAbstractKinesisRecorder() + +@property (nonatomic, strong) id recorderHelper; + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration + identifier:(NSString *)identifier + cacheName:(NSString *)cacheName; @end @@ -91,334 +97,95 @@ - (instancetype)init { } - (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration - identifier:(NSString *)identifier { - if (self = [self initWithConfiguration:configuration - identifier:[identifier aws_md5StringLittleEndian] - cacheName:[NSString stringWithFormat:@"%@.%@", AWSKinesisRecorderCacheName, identifier]]) { + identifier:(NSString *)identifier + cacheName:(NSString *)cacheName { + if (self = [super initWithConfiguration:configuration + identifier:identifier + cacheName:cacheName]) { + self.recorderHelper = [[AWSKinesisRecorderHelper alloc] initWithConfiguration:configuration]; } return self; } -- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration - identifier:(NSString *)identifier - cacheName:(NSString *)cacheName { - if (self = [super init]) { - AWSServiceConfiguration *_configuration = [configuration copy]; - [_configuration addUserAgentProductToken:AWSKinesisRecorderUserAgent]; - NSString *databaseDirectoryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:AWSKinesisRecorderDatabasePathPrefix]; +@end +@implementation AWSKinesisRecorderHelper + +- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration { + if (self = [super init]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - _kinesis = [[AWSKinesis alloc] initWithConfiguration:_configuration]; + _kinesis = [[AWSKinesis alloc] initWithConfiguration:configuration]; #pragma clang diagnostic pop - - _databasePath = [databaseDirectoryPath stringByAppendingPathComponent:identifier]; - _diskByteLimit = AWSKinesisRecorderByteLimitDefault; - _diskAgeLimit = AWSKinesisRecorderAgeLimitDefault; - - // Creates a directory for storing databases if it doesn't exist. - BOOL fileExistsAtPath = [[NSFileManager defaultManager] fileExistsAtPath:databaseDirectoryPath]; - if (!fileExistsAtPath) { - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:databaseDirectoryPath - withIntermediateDirectories:YES - attributes:nil - error:&error]; - if (!success) { - AWSLogError(@"Failed to create a directory for database. [%@]", error); - } - } - - // Creates a database for the identifier if it doesn't exist. - AWSLogDebug(@"Database path: [%@]", _databasePath); - _databaseQueue = [AWSFMDatabaseQueue databaseQueueWithPath:_databasePath]; - [_databaseQueue inDatabase:^(AWSFMDatabase *db) { - if (![db executeStatements:@"PRAGMA auto_vacuum = FULL"]) { - AWSLogError(@"Failed to enable 'aut_vacuum' to 'FULL'. %@", db.lastError); - } - - if (![db executeUpdate: - @"CREATE TABLE IF NOT EXISTS record (" - @"partition_key TEXT NOT NULL," - @"stream_name TEXT NOT NULL," - @"data BLOB NOT NULL," - @"timestamp REAL NOT NULL," - @"retry_count INTEGER NOT NULL)"]) { - AWSLogError(@"SQLite error. [%@]", db.lastError); - } - }]; } + return self; } -- (AWSTask *)saveRecord:(NSData *)data - streamName:(NSString *)streamName { - // Returns error if the total size of data and partition key exceeds 50KB. - // Partition key limit is 256 bytes. - if ([data length] > 50 * 1024 - 256) { - return [AWSTask taskWithError:[NSError errorWithDomain:AWSKinesisRecorderErrorDomain - code:AWSKinesisRecorderErrorDataTooLarge - userInfo:nil]]; - } - - AWSFMDatabaseQueue *databaseQueue = self.databaseQueue; - NSTimeInterval diskAgeLimit = self.diskAgeLimit; - NSString *databasePath = self.databasePath; - NSUInteger notificationByteThreshold = self.notificationByteThreshold; - NSUInteger diskByteLimit = self.diskByteLimit; - __weak AWSKinesisRecorder *kinesisRecorder = self; - - return [[AWSTask taskWithResult:nil] continueWithSuccessBlock:^id(AWSTask *task) { - // Inserts a new record to the database. - __block NSError *error = nil; - [databaseQueue inDatabase:^(AWSFMDatabase *db) { - BOOL result = [db executeUpdate: - @"INSERT INTO record (" - @"partition_key, stream_name, data, timestamp, retry_count" - @") VALUES (" - @":partition_key, :stream_name, :data, :timestamp, :retry_count" - @")" - withParameterDictionary:@{ - @"partition_key" : [[NSUUID UUID] UUIDString], - @"stream_name" : streamName, - @"data" : data, - @"timestamp" : @([[NSDate date] timeIntervalSince1970]), - @"retry_count" : @0 - } - ]; - - - if (!result) { - AWSLogError(@"SQLite error. [%@]", db.lastError); - error = db.lastError; - } - }]; - - if (!error && diskAgeLimit > 0) { - [databaseQueue inDatabase:^(AWSFMDatabase *db) { - // Deletes old records exceeding the threshold. - BOOL result = [db executeUpdate: - @"DELETE FROM record " - @"WHERE timestamp < :timestamp" - withParameterDictionary:@{ - @"timestamp" : @([[NSDate date] timeIntervalSince1970] - diskAgeLimit) - } - ]; - if (!result) { - AWSLogError(@"SQLite error. [%@]", db.lastError); - error = db.lastError; - } - }]; - } +- (AWSTask *)submitRecordsForStream:(NSString *)streamName + records:(NSArray *)temporaryRecords + partitionKeys:(NSArray *)partitionKeys + putPartitionKeys:(NSMutableArray *)putPartitionKeys + retryPartitionKeys:(NSMutableArray *)retryPartitionKeys { + NSMutableArray *records = [NSMutableArray new]; - if (error) { - return [AWSTask taskWithError:error]; - } + for (NSDictionary *recordDictionary in temporaryRecords) { + AWSKinesisPutRecordsRequestEntry *requestEntry = [AWSKinesisPutRecordsRequestEntry new]; + requestEntry.partitionKey = recordDictionary[@"partition_key"]; + requestEntry.data = recordDictionary[@"data"]; + streamName = recordDictionary[@"stream_name"]; - NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:databasePath - error:&error]; - if (attributes) { - unsigned long long fileSize = [attributes fileSize]; - if (notificationByteThreshold > 0 - && fileSize > notificationByteThreshold) { - // Sends out a notification if it exceeds the disk size threshold. - [[NSNotificationCenter defaultCenter] postNotificationName:AWSKinesisRecorderByteThresholdReachedNotification - object:kinesisRecorder - userInfo:@{AWSKinesisRecorderByteThresholdReachedNotificationDiskBytesUsedKey : @(fileSize)}]; - } - if (fileSize > diskByteLimit) { - // Deletes the oldest record if it exceeds the disk size threshold. - [databaseQueue inDatabase:^(AWSFMDatabase *db) { - BOOL result = [db executeUpdate: - @"DELETE FROM record " - @"WHERE rowid IN ( " - @"SELECT rowid " - @"FROM record " - @"ORDER BY rowid ASC " - @"LIMIT 1 " - @")" - ]; - if (!result) { - AWSLogError(@"SQLite error. [%@]", db.lastError); - error = db.lastError; - return; - } - }]; + [records addObject:requestEntry]; + } - } - } else if (error) { - return [AWSTask taskWithError:error]; + AWSKinesisPutRecordsInput *putRecordsInput = [AWSKinesisPutRecordsInput new]; + putRecordsInput.streamName = streamName; + putRecordsInput.records = records; + AWSLogVerbose(@"putRecordsInput: [%@]", putRecordsInput); + return [[self.kinesis putRecords:putRecordsInput] continueWithBlock:^id(AWSTask *task) { + if (task.error) { + AWSLogError(@"Error: [%@]", task.error); } - - return nil; - }]; -} - -- (AWSTask *)submitAllRecords { - AWSFMDatabaseQueue *databaseQueue = self.databaseQueue; - AWSKinesis *kinesis = self.kinesis; - - return [[AWSTask taskWithResult:nil] continueWithSuccessBlock:^id(AWSTask *task) { - __block NSError *error = nil; - __block AWSTask *outputTask = [AWSTask taskWithResult:nil]; - - [databaseQueue inTransaction:^(AWSFMDatabase *db, BOOL *rollback) { - AWSFMResultSet *rs = [db executeQuery: - @"SELECT stream_name " - @"FROM record " - @"GROUP BY stream_name "]; - if (!rs) { - AWSLogError(@"SQLite error. Rolling back... [%@]", db.lastError); - error = db.lastError; - *rollback = YES; - return; - } - - NSMutableArray *streamNames = [NSMutableArray new]; - while ([rs next]) { - [streamNames addObject:[rs stringForColumn:@"stream_name"]]; - } - rs = nil; - AWSLogDebug(@"Stream names: [%@]", streamNames); - - for (NSString *streamName in streamNames) { - NSMutableArray *records = nil; - NSMutableArray *rowIds = nil; - NSNumber *startingRowId = @(-1); - do { - AWSFMResultSet *rs = [db executeQuery: - @"SELECT rowid, partition_key, data, retry_count " - @"FROM record " - @"WHERE stream_name = :stream_name " - @"AND rowid > :rowid " - @"ORDER BY rowid ASC " - @"LIMIT 100" - withParameterDictionary:@{ - @"stream_name" : streamName, - @"rowid" : startingRowId - }]; - if (!rs) { - AWSLogError(@"SQLite error. Rolling back... [%@]", db.lastError); - error = db.lastError; - *rollback = YES; - return; - } - - records = [NSMutableArray new]; - rowIds = [NSMutableArray new]; - while ([rs next]) { - AWSKinesisPutRecordsRequestEntry *requestEntry = [AWSKinesisPutRecordsRequestEntry new]; - requestEntry.partitionKey = [rs stringForColumn:@"partition_key"]; - requestEntry.data = [rs dataForColumn:@"data"]; - [records addObject:requestEntry]; - - startingRowId = @([rs longLongIntForColumn:@"rowid"]); - [rowIds addObject:@([rs longLongIntForColumn:@"rowid"])]; - } - rs = nil; - - if ([records count] > 0) { - AWSKinesisPutRecordsInput *putRecordsInput = [AWSKinesisPutRecordsInput new]; - putRecordsInput.streamName = streamName; - putRecordsInput.records = records; - AWSLogVerbose(@"putRecordsInput: [%@]", putRecordsInput); - outputTask = [outputTask continueWithSuccessBlock:^id(AWSTask *task) { - return [[kinesis putRecords:putRecordsInput] continueWithSuccessBlock:^id(AWSTask *task) { - if (task.error) { - AWSLogError(@"Error: [%@]", task.error); - } - if (task.exception) { - AWSLogError(@"Exception: [%@]", task.exception); - } - if (task.result) { - [databaseQueue inDatabase:^(AWSFMDatabase *db) { - AWSKinesisPutRecordsOutput *putRecordsOutput = task.result; - for (int i = 0; i < [putRecordsOutput.records count]; i++) { - AWSKinesisPutRecordsResultEntry *resultEntry = putRecordsOutput.records[i]; - if (resultEntry.errorCode) { - AWSLogInfo(@"Error Code: [%@] Error Message: [%@]", resultEntry.errorCode, resultEntry.errorMessage); - } - // When the error code is ProvisionedThroughputExceededException or InternalFailure, - // we should retry. So, don't delete the row from the database. - if (![resultEntry.errorCode isEqualToString:@"ProvisionedThroughputExceededException"] - && ![resultEntry.errorCode isEqualToString:@"InternalFailure"]) { - BOOL result = [db executeUpdate:@"DELETE FROM record WHERE rowid = :rowid" - withParameterDictionary:@{ - @"rowid" : rowIds[i] - }]; - if (!result) { - AWSLogError(@"SQLite error. [%@]", db.lastError); - error = db.lastError; - } - } - } - }]; - } - return nil; - }]; - }]; - } - } while ([records count] == 100); - } - }]; - - [databaseQueue inDatabase:^(AWSFMDatabase *db) { - if (![db executeStatements:@"PRAGMA auto_vacuum = FULL"]) { - AWSLogError(@"Failed to enable 'aut_vacuum' to 'FULL'. %@", db.lastError); - error = db.lastError; - } - if (![db executeUpdate:@"VACUUM"]) { - AWSLogError(@"SQLite error. [%@]", db.lastError); - error = db.lastError; - } - }]; - - if (error) { - return [AWSTask taskWithError:error]; + if (task.exception) { + AWSLogError(@"Exception: [%@]", task.exception); } + if (task.result) { + AWSKinesisPutRecordsOutput *putRecordsOutput = task.result; - return outputTask; - }]; -} - -- (AWSTask *)removeAllRecords { - AWSFMDatabaseQueue *databaseQueue = self.databaseQueue; - - return [[AWSTask taskWithResult:nil] continueWithSuccessBlock:^id(AWSTask *task) { - __block NSError *error = nil; - [databaseQueue inDatabase:^(AWSFMDatabase *db) { - if (![db executeUpdate:@"DELETE FROM record"]) { - AWSLogError(@"SQLite error. [%@]", db.lastError); - error = db.lastError; - } else { - if (![db executeStatements:@"PRAGMA auto_vacuum = FULL"]) { - AWSLogError(@"Failed to enable 'auto_vacuum' to 'FULL'. %@", db.lastError); - error = db.lastError; + for (int i = 0; i < [putRecordsOutput.records count]; i++) { + AWSKinesisPutRecordsResultEntry *resultEntry = putRecordsOutput.records[i]; + if (resultEntry.errorCode) { + AWSLogInfo(@"Error Code: [%@] Error Message: [%@]", resultEntry.errorCode, resultEntry.errorMessage); } - if (![db executeUpdate:@"VACUUM"]) { - AWSLogError(@"SQLite error. [%@]", db.lastError); - error = db.lastError; + // When the error code is ProvisionedThroughputExceededException or InternalFailure, + // we should retry. So, don't delete the row from the database. + if (![resultEntry.errorCode isEqualToString:@"ProvisionedThroughputExceededException"] + && ![resultEntry.errorCode isEqualToString:@"InternalFailure"]) { + [putPartitionKeys addObject:partitionKeys[i]]; + } else { + [retryPartitionKeys addObject:partitionKeys[i]]; } } - }]; - - if (error) { - return [AWSTask taskWithError:error]; } - return nil; }]; } -- (NSUInteger)diskBytesUsed { - NSError *error = nil; - NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.databasePath - error:&error]; - if (attributes) { - return (NSUInteger)[attributes fileSize]; - } else { - AWSLogError(@"Error [%@]", error); - return 0; +- (NSError *)dataTooLargeError { + return [NSError errorWithDomain:AWSKinesisRecorderErrorDomain + code:AWSKinesisRecorderErrorDataTooLarge + userInfo:nil]; +} + +- (void)checkByteThresholdForNotification:(NSUInteger)notificationByteThreshold + notificationSender:(id)notificationSender + fileSize:(NSUInteger)fileSize { + if (notificationByteThreshold > 0 + && fileSize > notificationByteThreshold) { + // Sends out a notification if it exceeds the disk size threshold. + [[NSNotificationCenter defaultCenter] postNotificationName:AWSKinesisRecorderByteThresholdReachedNotification + object:notificationSender + userInfo:@{AWSKinesisRecorderByteThresholdReachedNotificationDiskBytesUsedKey : @(fileSize)}]; } } diff --git a/AWSKinesisTests/AWSKinesisRecorderTests.m b/AWSKinesisTests/AWSKinesisRecorderTests.m index c79e8b611fb..625c56471b6 100644 --- a/AWSKinesisTests/AWSKinesisRecorderTests.m +++ b/AWSKinesisTests/AWSKinesisRecorderTests.m @@ -110,27 +110,18 @@ - (void)testConstructors { XCTAssertEqual([kinesisRecorder class], [AWSKinesisRecorder class]); [AWSKinesisRecorder removeKinesisRecorderForKey:@"AWSKinesisRecorderTests.testConstructors"]; XCTAssertNil([AWSKinesisRecorder KinesisRecorderForKey:@"AWSKinesisRecorderTests.testConstructors"]); - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - kinesisRecorder = [[AWSKinesisRecorder alloc] initWithConfiguration:serviceConfiguration - identifier:@"Some random string"]; -#pragma clang diagnostic pop - - XCTAssertNotNil(kinesisRecorder); - XCTAssertEqual([kinesisRecorder class], [AWSKinesisRecorder class]); } - (void)testSaveLargeData { NSMutableString *mutableString = [NSMutableString new]; - for (int i = 0; i < 5100; i++) { + for (int i = 0; i < 30000; i++) { [mutableString appendString:@"0123456789"]; } NSData *data = [mutableString dataUsingEncoding:NSUTF8StringEncoding]; - XCTAssertGreaterThan([data length], 50 * 1024 - 256); + XCTAssertGreaterThan([data length], 256 * 1024 - 256); AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder]; [[[kinesisRecorder saveRecord:data - streamName:@"testSaveLargeData"] continueWithBlock:^id(AWSTask *task) { + streamName:@"testSaveLargeData"] continueWithBlock:^id(AWSTask *task) { XCTAssertNil(task.result); XCTAssertNil(task.exception); XCTAssertNotNil(task.error); diff --git a/AWSLambda.podspec b/AWSLambda.podspec index b013df251ee..6751ea6bc10 100644 --- a/AWSLambda.podspec +++ b/AWSLambda.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'AWSLambda' - s.version = '2.3.1' + s.version = '2.3.2' s.summary = 'Amazon Web Services SDK for iOS.' s.description = 'The AWS SDK for iOS provides a library, code samples, and documentation for developers to build connected mobile applications using AWS.' @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSLambda/*.{h,m}' end diff --git a/AWSLambda.xcodeproj/project.pbxproj b/AWSLambda.xcodeproj/project.pbxproj index 06010575745..7dc9956a0f5 100644 --- a/AWSLambda.xcodeproj/project.pbxproj +++ b/AWSLambda.xcodeproj/project.pbxproj @@ -25,6 +25,10 @@ CE6397251AC4A4CC00459E23 /* AWSLambdaTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6397241AC4A4CC00459E23 /* AWSLambdaTests.m */; }; CE6397281AC4A7F300459E23 /* AWSLambdaInvoker.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6397261AC4A7F300459E23 /* AWSLambdaInvoker.h */; settings = {ATTRIBUTES = (Public, ); }; }; CE6397291AC4A7F300459E23 /* AWSLambdaInvoker.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6397271AC4A7F300459E23 /* AWSLambdaInvoker.m */; }; + CEB3802D1C177F1F008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3802C1C177F1F008B520C /* SystemConfiguration.framework */; }; + CEB380401C177F9B008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3802C1C177F1F008B520C /* SystemConfiguration.framework */; }; + CEB3805E1C17809C008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3805D1C17809C008B520C /* Security.framework */; }; + CEB3805F1C1780A0008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3805D1C17809C008B520C /* Security.framework */; }; CED822211AC4895F0017E687 /* libAWSLambda.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CED822151AC4895F0017E687 /* libAWSLambda.a */; }; CED8223C1AC48A3D0017E687 /* AWSLambdaService.m in Sources */ = {isa = PBXBuildFile; fileRef = CED822351AC48A3D0017E687 /* AWSLambdaService.m */; }; CED8223D1AC48A3D0017E687 /* AWSLambdaModel.m in Sources */ = {isa = PBXBuildFile; fileRef = CED822371AC48A3D0017E687 /* AWSLambdaModel.m */; }; @@ -95,6 +99,8 @@ CE6397261AC4A7F300459E23 /* AWSLambdaInvoker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = AWSLambdaInvoker.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; CE6397271AC4A7F300459E23 /* AWSLambdaInvoker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSLambdaInvoker.m; sourceTree = ""; }; CE6552381BEC364700DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB3802C1C177F1F008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB3805D1C17809C008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CED822151AC4895F0017E687 /* libAWSLambda.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAWSLambda.a; sourceTree = BUILT_PRODUCTS_DIR; }; CED822201AC4895F0017E687 /* AWSLambdaTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSLambdaTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; CED822261AC4895F0017E687 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -112,6 +118,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3805F1C1780A0008B520C /* Security.framework in Frameworks */, + CEB3802D1C177F1F008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB601BF188ED00B22AB3 /* UIKit.framework in Frameworks */, BDD876AC1B4B52F0009268C7 /* libOCMock.a in Frameworks */, BDF125DD1B45C22300DFBFEC /* libz.dylib in Frameworks */, @@ -131,6 +139,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3805E1C17809C008B520C /* Security.framework in Frameworks */, + CEB380401C177F9B008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB5F1BF188E900B22AB3 /* UIKit.framework in Frameworks */, CEE532641B03D3A8002CED62 /* libz.dylib in Frameworks */, CE6397131AC48EF300459E23 /* libAWSCore.a in Frameworks */, @@ -144,6 +154,8 @@ 3EAFA3A380A2651599D9FC74 /* Frameworks */ = { isa = PBXGroup; children = ( + CEB3805D1C17809C008B520C /* Security.framework */, + CEB3802C1C177F1F008B520C /* SystemConfiguration.framework */, CE27CB5E1BF188E900B22AB3 /* UIKit.framework */, BDD876AB1B4B52F0009268C7 /* libOCMock.a */, CEE532631B03D3A8002CED62 /* libz.dylib */, @@ -289,7 +301,7 @@ CED8220D1AC4895F0017E687 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { CED822141AC4895F0017E687 = { diff --git a/AWSLambda.xcodeproj/xcshareddata/xcschemes/AWSLambda.xcscheme b/AWSLambda.xcodeproj/xcshareddata/xcschemes/AWSLambda.xcscheme index 7434bf1e520..985e765348a 100644 --- a/AWSLambda.xcodeproj/xcshareddata/xcschemes/AWSLambda.xcscheme +++ b/AWSLambda.xcodeproj/xcshareddata/xcschemes/AWSLambda.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSMachineLearning/*.{h,m}' end diff --git a/AWSMachineLearning.xcodeproj/project.pbxproj b/AWSMachineLearning.xcodeproj/project.pbxproj index aa4775393f9..69f628518b0 100644 --- a/AWSMachineLearning.xcodeproj/project.pbxproj +++ b/AWSMachineLearning.xcodeproj/project.pbxproj @@ -31,6 +31,10 @@ CE92004B1ACF7F3700637171 /* AWSTestUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = CE92004A1ACF7F3700637171 /* AWSTestUtility.m */; }; CE92004D1ACF7FBB00637171 /* libAWSCore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE92004C1ACF7FBB00637171 /* libAWSCore.a */; }; CE92004F1ACF7FFE00637171 /* credentials.json in Resources */ = {isa = PBXBuildFile; fileRef = CE92004E1ACF7FFE00637171 /* credentials.json */; }; + CEB3802F1C177F27008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3802E1C177F27008B520C /* SystemConfiguration.framework */; }; + CEB3803F1C177F95008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3802E1C177F27008B520C /* SystemConfiguration.framework */; }; + CEB3805B1C178091008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3805A1C178091008B520C /* Security.framework */; }; + CEB3805C1C178096008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3805A1C178091008B520C /* Security.framework */; }; CEE5325C1B03D386002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE5325B1B03D386002CED62 /* libz.dylib */; }; /* End PBXBuildFile section */ @@ -96,6 +100,8 @@ CE92004A1ACF7F3700637171 /* AWSTestUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWSTestUtility.m; path = AWSCoreTests/AWSTestUtility.m; sourceTree = SOURCE_ROOT; }; CE92004C1ACF7FBB00637171 /* libAWSCore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libAWSCore.a; path = "build/Debug-iphoneos/libAWSCore.a"; sourceTree = ""; }; CE92004E1ACF7FFE00637171 /* credentials.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = credentials.json; path = AWSCoreTests/credentials.json; sourceTree = SOURCE_ROOT; }; + CEB3802E1C177F27008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB3805A1C178091008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE5325B1B03D386002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -104,6 +110,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3805C1C178096008B520C /* Security.framework in Frameworks */, + CEB3802F1C177F27008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB631BF1891F00B22AB3 /* UIKit.framework in Frameworks */, BDD876AE1B4B5302009268C7 /* libOCMock.a in Frameworks */, BDF125EF1B45C24500DFBFEC /* libz.dylib in Frameworks */, @@ -123,6 +131,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3805B1C178091008B520C /* Security.framework in Frameworks */, + CEB3803F1C177F95008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB621BF1891B00B22AB3 /* UIKit.framework in Frameworks */, CEE5325C1B03D386002CED62 /* libz.dylib in Frameworks */, CE92004D1ACF7FBB00637171 /* libAWSCore.a in Frameworks */, @@ -136,6 +146,8 @@ 13BA91A9ED2214407949A932 /* Frameworks */ = { isa = PBXGroup; children = ( + CEB3805A1C178091008B520C /* Security.framework */, + CEB3802E1C177F27008B520C /* SystemConfiguration.framework */, CE27CB611BF1891B00B22AB3 /* UIKit.framework */, BDD876AD1B4B5302009268C7 /* libOCMock.a */, CEE5325B1B03D386002CED62 /* libz.dylib */, @@ -277,7 +289,7 @@ CE71234D1ACF7A0B00D96A87 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { CE7123541ACF7A0B00D96A87 = { diff --git a/AWSMachineLearning.xcodeproj/xcshareddata/xcschemes/AWSMachineLearning.xcscheme b/AWSMachineLearning.xcodeproj/xcshareddata/xcschemes/AWSMachineLearning.xcscheme index 0018aa3511a..37cb2a6f1e0 100644 --- a/AWSMachineLearning.xcodeproj/xcshareddata/xcschemes/AWSMachineLearning.xcscheme +++ b/AWSMachineLearning.xcodeproj/xcshareddata/xcschemes/AWSMachineLearning.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSMobileAnalytics/*.{h,m}', 'AWSMobileAnalytics/**/*.{h,m}' s.private_header_files = 'AWSMobileAnalytics/Internal/*.h' diff --git a/AWSMobileAnalytics.xcodeproj/project.pbxproj b/AWSMobileAnalytics.xcodeproj/project.pbxproj index 656ffcd9d2f..7f11ccea425 100644 --- a/AWSMobileAnalytics.xcodeproj/project.pbxproj +++ b/AWSMobileAnalytics.xcodeproj/project.pbxproj @@ -39,6 +39,9 @@ CE5FABA01B042B3000D7010F /* AWSMobileAnalyticsERSModel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5FAB991B042B3000D7010F /* AWSMobileAnalyticsERSModel.m */; }; CE5FABA11B042B3000D7010F /* AWSMobileAnalyticsERSService.h in Headers */ = {isa = PBXBuildFile; fileRef = CE5FAB9A1B042B3000D7010F /* AWSMobileAnalyticsERSService.h */; }; CE5FABA21B042B3000D7010F /* AWSMobileAnalyticsERSService.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5FAB9B1B042B3000D7010F /* AWSMobileAnalyticsERSService.m */; }; + CEB380571C178084008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380561C178084008B520C /* Security.framework */; }; + CEB380581C178087008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380561C178084008B520C /* Security.framework */; }; + CEB380591C17808B008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380561C178084008B520C /* Security.framework */; }; CEB3C6B81B2FAE780010599E /* AWSMobileAnalyticsDefaultContext.h in Headers */ = {isa = PBXBuildFile; fileRef = CEB3C6B41B2FAE780010599E /* AWSMobileAnalyticsDefaultContext.h */; }; CEB3C6B91B2FAE780010599E /* AWSMobileAnalyticsDefaultContext.m in Sources */ = {isa = PBXBuildFile; fileRef = CEB3C6B51B2FAE780010599E /* AWSMobileAnalyticsDefaultContext.m */; }; CEB3C6BA1B2FAE780010599E /* AWSMobileAnalyticsStringUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = CEB3C6B61B2FAE780010599E /* AWSMobileAnalyticsStringUtils.h */; }; @@ -312,6 +315,7 @@ CE5FAB9A1B042B3000D7010F /* AWSMobileAnalyticsERSService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWSMobileAnalyticsERSService.h; path = AWSMobileAnalytics/AWSMobileAnalyticsERS/AWSMobileAnalyticsERSService.h; sourceTree = SOURCE_ROOT; }; CE5FAB9B1B042B3000D7010F /* AWSMobileAnalyticsERSService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = AWSMobileAnalyticsERSService.m; path = AWSMobileAnalytics/AWSMobileAnalyticsERS/AWSMobileAnalyticsERSService.m; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; CE65523C1BEC366A00DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380561C178084008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEB3C6B41B2FAE780010599E /* AWSMobileAnalyticsDefaultContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSMobileAnalyticsDefaultContext.h; sourceTree = ""; }; CEB3C6B51B2FAE780010599E /* AWSMobileAnalyticsDefaultContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSMobileAnalyticsDefaultContext.m; sourceTree = ""; }; CEB3C6B61B2FAE780010599E /* AWSMobileAnalyticsStringUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSMobileAnalyticsStringUtils.h; sourceTree = ""; }; @@ -561,6 +565,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380591C17808B008B520C /* Security.framework in Frameworks */, CE27CB671BF1895700B22AB3 /* UIKit.framework in Frameworks */, BDD876B01B4B5316009268C7 /* libOCMock.a in Frameworks */, BDF126021B45C27900DFBFEC /* SystemConfiguration.framework in Frameworks */, @@ -574,6 +579,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380571C178084008B520C /* Security.framework in Frameworks */, CE27CB651BF1894E00B22AB3 /* UIKit.framework in Frameworks */, CE2E0C911B03F2B400DE3906 /* SystemConfiguration.framework in Frameworks */, CE2E0C8F1B03F2A300DE3906 /* libAWSCore.a in Frameworks */, @@ -593,6 +599,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380581C178087008B520C /* Security.framework in Frameworks */, CE27CB661BF1895300B22AB3 /* UIKit.framework in Frameworks */, BD4C9AEB1B4C69DB00267270 /* SystemConfiguration.framework in Frameworks */, BD4C9AEA1B4C697400267270 /* libOCMock.a in Frameworks */, @@ -644,6 +651,7 @@ CEE5326F1B03DE7F002CED62 = { isa = PBXGroup; children = ( + CEB380561C178084008B520C /* Security.framework */, CEE5327A1B03DE7F002CED62 /* AWSMobileAnalytics */, CE2E0C781B03EFD300DE3906 /* AWSMobileAnalyticsTests */, CEE532871B03DE7F002CED62 /* AWSMobileAnalyticsLegacyTests */, @@ -1135,7 +1143,7 @@ CEE532701B03DE7F002CED62 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { CE2E0C761B03EFD300DE3906 = { diff --git a/AWSMobileAnalytics.xcodeproj/xcshareddata/xcschemes/AWSMobileAnalytics.xcscheme b/AWSMobileAnalytics.xcodeproj/xcshareddata/xcschemes/AWSMobileAnalytics.xcscheme index 3510f524fbc..3225ab682b0 100644 --- a/AWSMobileAnalytics.xcodeproj/xcshareddata/xcschemes/AWSMobileAnalytics.xcscheme +++ b/AWSMobileAnalytics.xcodeproj/xcshareddata/xcschemes/AWSMobileAnalytics.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSS3/*.{h,m}' end diff --git a/AWSS3.xcodeproj/project.pbxproj b/AWSS3.xcodeproj/project.pbxproj index 0ea0f84778b..ced6c786123 100644 --- a/AWSS3.xcodeproj/project.pbxproj +++ b/AWSS3.xcodeproj/project.pbxproj @@ -40,6 +40,10 @@ CE2EDEA01BF3DF6600B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE65523E1BEC368100DACBC2 /* module.modulemap */; }; CE83D0EA1B7171EB004A42E4 /* AWSS3TransferUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = CE83D0E81B7171EB004A42E4 /* AWSS3TransferUtility.h */; settings = {ATTRIBUTES = (Public, ); }; }; CE83D0EB1B7171EB004A42E4 /* AWSS3TransferUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = CE83D0E91B7171EB004A42E4 /* AWSS3TransferUtility.m */; }; + CEB380311C177F3C008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380301C177F3C008B520C /* SystemConfiguration.framework */; }; + CEB3803E1C177F89008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380301C177F3C008B520C /* SystemConfiguration.framework */; }; + CEB380541C17807A008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380531C17807A008B520C /* Security.framework */; }; + CEB380551C17807E008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380531C17807A008B520C /* Security.framework */; }; CED7DE4D1BE2E121008DA1DC /* AWSS3TransferUtility.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE83D0E81B7171EB004A42E4 /* AWSS3TransferUtility.h */; }; CEE5326E1B03D3CB002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE5326D1B03D3CB002CED62 /* libz.dylib */; }; CEE7DE731AC1E1DA0095C4B7 /* AWSS3Service.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE721AC1E1DA0095C4B7 /* AWSS3Service.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -118,6 +122,8 @@ CE65523E1BEC368100DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; CE83D0E81B7171EB004A42E4 /* AWSS3TransferUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSS3TransferUtility.h; sourceTree = ""; }; CE83D0E91B7171EB004A42E4 /* AWSS3TransferUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AWSS3TransferUtility.m; sourceTree = ""; }; + CEB380301C177F3C008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB380531C17807A008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE5326D1B03D3CB002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE721AC1E1DA0095C4B7 /* AWSS3Service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSS3Service.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -127,6 +133,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380551C17807E008B520C /* Security.framework in Frameworks */, + CEB380311C177F3C008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB6A1BF18C6500B22AB3 /* UIKit.framework in Frameworks */, BDD876B21B4B5339009268C7 /* libOCMock.a in Frameworks */, BDF126171B45C2C100DFBFEC /* libz.dylib in Frameworks */, @@ -146,6 +154,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380541C17807A008B520C /* Security.framework in Frameworks */, + CEB3803E1C177F89008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB691BF18C6000B22AB3 /* UIKit.framework in Frameworks */, CEE5326E1B03D3CB002CED62 /* libz.dylib in Frameworks */, BD00FF411AB8B6D2004496EF /* libAWSCore.a in Frameworks */, @@ -159,6 +169,8 @@ 7D7D82B43AAE1FAA16A74BC2 /* Frameworks */ = { isa = PBXGroup; children = ( + CEB380531C17807A008B520C /* Security.framework */, + CEB380301C177F3C008B520C /* SystemConfiguration.framework */, CE27CB681BF18C6000B22AB3 /* UIKit.framework */, BDD876B11B4B5339009268C7 /* libOCMock.a */, CEE5326D1B03D3CB002CED62 /* libz.dylib */, @@ -312,7 +324,7 @@ BDF559E41AB376DC0067F4F1 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDF559EB1AB376DC0067F4F1 = { diff --git a/AWSS3.xcodeproj/xcshareddata/xcschemes/AWSS3.xcscheme b/AWSS3.xcodeproj/xcshareddata/xcschemes/AWSS3.xcscheme index d9d2f75f65a..030e218ee81 100644 --- a/AWSS3.xcodeproj/xcshareddata/xcschemes/AWSS3.xcscheme +++ b/AWSS3.xcodeproj/xcshareddata/xcschemes/AWSS3.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSSES/*.{h,m}' end diff --git a/AWSSES.xcodeproj/project.pbxproj b/AWSSES.xcodeproj/project.pbxproj index cddfc082433..8902b47d602 100644 --- a/AWSSES.xcodeproj/project.pbxproj +++ b/AWSSES.xcodeproj/project.pbxproj @@ -30,6 +30,10 @@ CE27CB6C1BF192D800B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB6B1BF192D800B22AB3 /* UIKit.framework */; }; CE27CB6D1BF192DD00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB6B1BF192D800B22AB3 /* UIKit.framework */; }; CE2EDEA21BF3DF7200B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6552401BEC369800DACBC2 /* module.modulemap */; }; + CEB380331C177F43008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380321C177F43008B520C /* SystemConfiguration.framework */; }; + CEB3803D1C177F85008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380321C177F43008B520C /* SystemConfiguration.framework */; }; + CEB380511C17806D008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380501C17806D008B520C /* Security.framework */; }; + CEB380521C178074008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380501C17806D008B520C /* Security.framework */; }; CEE532621B03D3A1002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE532611B03D3A1002CED62 /* libz.dylib */; }; CEE7DE751AC1E2030095C4B7 /* AWSSESService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE741AC1E2030095C4B7 /* AWSSESService.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -96,6 +100,8 @@ BDF126311B45C2E400DFBFEC /* AWSSESUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSSESUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; CE27CB6B1BF192D800B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE6552401BEC369800DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380321C177F43008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB380501C17806D008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE532611B03D3A1002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE741AC1E2030095C4B7 /* AWSSESService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSSESService.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -112,6 +118,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380511C17806D008B520C /* Security.framework in Frameworks */, + CEB3803D1C177F85008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB6C1BF192D800B22AB3 /* UIKit.framework in Frameworks */, CEE532621B03D3A1002CED62 /* libz.dylib in Frameworks */, BD00FF3F1AB8B6CB004496EF /* libAWSCore.a in Frameworks */, @@ -123,6 +131,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380521C178074008B520C /* Security.framework in Frameworks */, + CEB380331C177F43008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB6D1BF192DD00B22AB3 /* UIKit.framework in Frameworks */, BDD876B41B4B5348009268C7 /* libOCMock.a in Frameworks */, BDF126291B45C2E400DFBFEC /* libz.dylib in Frameworks */, @@ -137,6 +147,8 @@ 3389B24E19BA4F4B5860898B /* Frameworks */ = { isa = PBXGroup; children = ( + CEB380501C17806D008B520C /* Security.framework */, + CEB380321C177F43008B520C /* SystemConfiguration.framework */, CE27CB6B1BF192D800B22AB3 /* UIKit.framework */, BDD876B31B4B5348009268C7 /* libOCMock.a */, CEE532611B03D3A1002CED62 /* libz.dylib */, @@ -280,7 +292,7 @@ BDB5DE591AB37745002DD224 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDB5DE601AB37745002DD224 = { diff --git a/AWSSES.xcodeproj/xcshareddata/xcschemes/AWSSES.xcscheme b/AWSSES.xcodeproj/xcshareddata/xcschemes/AWSSES.xcscheme index 8d2a17e869f..8c4f745cdcf 100644 --- a/AWSSES.xcodeproj/xcshareddata/xcschemes/AWSSES.xcscheme +++ b/AWSSES.xcodeproj/xcshareddata/xcschemes/AWSSES.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSSNS/*.{h,m}' end diff --git a/AWSSNS.xcodeproj/project.pbxproj b/AWSSNS.xcodeproj/project.pbxproj index a72e364a4d0..bc41bb47e60 100644 --- a/AWSSNS.xcodeproj/project.pbxproj +++ b/AWSSNS.xcodeproj/project.pbxproj @@ -30,6 +30,10 @@ CE27CB721BF1931C00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB711BF1931C00B22AB3 /* UIKit.framework */; }; CE27CB731BF1932100B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB711BF1931C00B22AB3 /* UIKit.framework */; }; CE2EDEA61BF3DF8B00B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6552441BEC36B900DACBC2 /* module.modulemap */; }; + CEB380371C177F51008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380361C177F51008B520C /* SystemConfiguration.framework */; }; + CEB3803B1C177F75008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380361C177F51008B520C /* SystemConfiguration.framework */; }; + CEB3804E1C17805D008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3804D1C17805D008B520C /* Security.framework */; }; + CEB3804F1C178062008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3804D1C17805D008B520C /* Security.framework */; }; CEE5325E1B03D38F002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE5325D1B03D38F002CED62 /* libz.dylib */; }; CEE7DE771AC1E2270095C4B7 /* AWSSNSService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE761AC1E2270095C4B7 /* AWSSNSService.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -96,6 +100,8 @@ BDF126551B45C34100DFBFEC /* AWSSNSUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSSNSUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; CE27CB711BF1931C00B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE6552441BEC36B900DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380361C177F51008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB3804D1C17805D008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE5325D1B03D38F002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE761AC1E2270095C4B7 /* AWSSNSService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSSNSService.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -112,6 +118,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3804E1C17805D008B520C /* Security.framework in Frameworks */, + CEB3803B1C177F75008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB721BF1931C00B22AB3 /* UIKit.framework in Frameworks */, CEE5325E1B03D38F002CED62 /* libz.dylib in Frameworks */, BD00FF3B1AB8B6B6004496EF /* libAWSCore.a in Frameworks */, @@ -123,6 +131,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3804F1C178062008B520C /* Security.framework in Frameworks */, + CEB380371C177F51008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB731BF1932100B22AB3 /* UIKit.framework in Frameworks */, BDD876B81B4B5361009268C7 /* libOCMock.a in Frameworks */, BDF1264D1B45C34100DFBFEC /* libz.dylib in Frameworks */, @@ -137,6 +147,8 @@ 64A8D5459E21A3F4F06E6A97 /* Frameworks */ = { isa = PBXGroup; children = ( + CEB3804D1C17805D008B520C /* Security.framework */, + CEB380361C177F51008B520C /* SystemConfiguration.framework */, CE27CB711BF1931C00B22AB3 /* UIKit.framework */, BDD876B71B4B5361009268C7 /* libOCMock.a */, CEE5325D1B03D38F002CED62 /* libz.dylib */, @@ -279,7 +291,7 @@ BDB5DEB71AB377FA002DD224 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDB5DEBE1AB377FA002DD224 = { diff --git a/AWSSNS.xcodeproj/xcshareddata/xcschemes/AWSSNS.xcscheme b/AWSSNS.xcodeproj/xcshareddata/xcschemes/AWSSNS.xcscheme index 84b901fbd5f..adcb8105ffc 100644 --- a/AWSSNS.xcodeproj/xcshareddata/xcschemes/AWSSNS.xcscheme +++ b/AWSSNS.xcodeproj/xcshareddata/xcschemes/AWSSNS.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSSQS/*.{h,m}' end diff --git a/AWSSQS.xcodeproj/project.pbxproj b/AWSSQS.xcodeproj/project.pbxproj index 4e943adba12..9e47915f084 100644 --- a/AWSSQS.xcodeproj/project.pbxproj +++ b/AWSSQS.xcodeproj/project.pbxproj @@ -31,6 +31,10 @@ CE27CB751BF1933000B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB741BF1933000B22AB3 /* UIKit.framework */; }; CE27CB761BF1933400B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB741BF1933000B22AB3 /* UIKit.framework */; }; CE2EDEA91BF3DFA100B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6552461BEC36C900DACBC2 /* module.modulemap */; }; + CEB380391C177F58008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380381C177F58008B520C /* SystemConfiguration.framework */; }; + CEB3803A1C177F6F008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380381C177F58008B520C /* SystemConfiguration.framework */; }; + CEB3804B1C178053008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3804A1C178053008B520C /* Security.framework */; }; + CEB3804C1C178057008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB3804A1C178053008B520C /* Security.framework */; }; CEE5326A1B03D3BE002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE532691B03D3BE002CED62 /* libz.dylib */; }; CEE7DE791AC1E23F0095C4B7 /* AWSSQSService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE781AC1E23F0095C4B7 /* AWSSQSService.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -98,6 +102,8 @@ BDF126681B45C36100DFBFEC /* AWSSQSUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSSQSUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; CE27CB741BF1933000B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE6552461BEC36C900DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380381C177F58008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB3804A1C178053008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE532691B03D3BE002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE781AC1E23F0095C4B7 /* AWSSQSService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSSQSService.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -114,6 +120,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3804B1C178053008B520C /* Security.framework in Frameworks */, + CEB3803A1C177F6F008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB751BF1933000B22AB3 /* UIKit.framework in Frameworks */, CEE5326A1B03D3BE002CED62 /* libz.dylib in Frameworks */, BD00FF391AB8B69F004496EF /* libAWSCore.a in Frameworks */, @@ -125,6 +133,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB3804C1C178057008B520C /* Security.framework in Frameworks */, + CEB380391C177F58008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB761BF1933400B22AB3 /* UIKit.framework in Frameworks */, BDD876BA1B4B5370009268C7 /* libOCMock.a in Frameworks */, BDF126601B45C36100DFBFEC /* libz.dylib in Frameworks */, @@ -139,6 +149,8 @@ 9CB08B3BEE06127D4F608086 /* Frameworks */ = { isa = PBXGroup; children = ( + CEB3804A1C178053008B520C /* Security.framework */, + CEB380381C177F58008B520C /* SystemConfiguration.framework */, CE27CB741BF1933000B22AB3 /* UIKit.framework */, BDD876B91B4B5370009268C7 /* libOCMock.a */, CEE532691B03D3BE002CED62 /* libz.dylib */, @@ -282,7 +294,7 @@ BDB5DEE61AB37849002DD224 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDB5DEED1AB37849002DD224 = { diff --git a/AWSSQS.xcodeproj/xcshareddata/xcschemes/AWSSQS.xcscheme b/AWSSQS.xcodeproj/xcshareddata/xcschemes/AWSSQS.xcscheme index af4eac4029b..aa4b1ac3666 100644 --- a/AWSSQS.xcodeproj/xcshareddata/xcschemes/AWSSQS.xcscheme +++ b/AWSSQS.xcodeproj/xcshareddata/xcschemes/AWSSQS.xcscheme @@ -1,6 +1,6 @@ 'https://github.com/aws/aws-sdk-ios.git', :tag => s.version} s.requires_arc = true - s.dependency 'AWSCore', '2.3.1' + s.dependency 'AWSCore', '2.3.2' s.source_files = 'AWSSimpleDB/*.{h,m}' end diff --git a/AWSSimpleDB.xcodeproj/project.pbxproj b/AWSSimpleDB.xcodeproj/project.pbxproj index 7ce0d55661a..927b876c6a1 100644 --- a/AWSSimpleDB.xcodeproj/project.pbxproj +++ b/AWSSimpleDB.xcodeproj/project.pbxproj @@ -30,6 +30,10 @@ CE27CB6F1BF192FF00B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB6E1BF192FF00B22AB3 /* UIKit.framework */; }; CE27CB701BF1930300B22AB3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE27CB6E1BF192FF00B22AB3 /* UIKit.framework */; }; CE2EDEA41BF3DF7E00B9F26B /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE6552421BEC36A800DACBC2 /* module.modulemap */; }; + CEB380351C177F4A008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380341C177F4A008B520C /* SystemConfiguration.framework */; }; + CEB3803C1C177F7D008B520C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380341C177F4A008B520C /* SystemConfiguration.framework */; }; + CEB380481C17802D008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380471C17802D008B520C /* Security.framework */; }; + CEB380491C178036008B520C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB380471C17802D008B520C /* Security.framework */; }; CEE532681B03D3B7002CED62 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE532671B03D3B7002CED62 /* libz.dylib */; }; CEE7DE5F1AC1DEEA0095C4B7 /* AWSSimpleDBService.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE7DE5E1AC1DEEA0095C4B7 /* AWSSimpleDBService.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -96,6 +100,8 @@ BDF126431B45C31C00DFBFEC /* AWSSimpleDBUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AWSSimpleDBUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; CE27CB6E1BF192FF00B22AB3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; CE6552421BEC36A800DACBC2 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; + CEB380341C177F4A008B520C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + CEB380471C17802D008B520C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; CEE532671B03D3B7002CED62 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; CEE7DE5E1AC1DEEA0095C4B7 /* AWSSimpleDBService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSSimpleDBService.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -112,6 +118,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380481C17802D008B520C /* Security.framework in Frameworks */, + CEB3803C1C177F7D008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB6F1BF192FF00B22AB3 /* UIKit.framework in Frameworks */, CEE532681B03D3B7002CED62 /* libz.dylib in Frameworks */, BD00FF3D1AB8B6C4004496EF /* libAWSCore.a in Frameworks */, @@ -123,6 +131,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEB380491C178036008B520C /* Security.framework in Frameworks */, + CEB380351C177F4A008B520C /* SystemConfiguration.framework in Frameworks */, CE27CB701BF1930300B22AB3 /* UIKit.framework in Frameworks */, BDD876B61B4B5354009268C7 /* libOCMock.a in Frameworks */, BDF1263B1B45C31C00DFBFEC /* libz.dylib in Frameworks */, @@ -193,6 +203,8 @@ CC221F0612D8271C7295C9FB /* Frameworks */ = { isa = PBXGroup; children = ( + CEB380471C17802D008B520C /* Security.framework */, + CEB380341C177F4A008B520C /* SystemConfiguration.framework */, CE27CB6E1BF192FF00B22AB3 /* UIKit.framework */, BDD876B51B4B5354009268C7 /* libOCMock.a */, CEE532671B03D3B7002CED62 /* libz.dylib */, @@ -279,7 +291,7 @@ BDB5DE881AB377AF002DD224 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Amazon Web Services"; TargetAttributes = { BDB5DE8F1AB377AF002DD224 = { diff --git a/AWSSimpleDB.xcodeproj/xcshareddata/xcschemes/AWSSimpleDB.xcscheme b/AWSSimpleDB.xcodeproj/xcshareddata/xcschemes/AWSSimpleDB.xcscheme index 55c44c6d698..e6fc225dfaf 100644 --- a/AWSSimpleDB.xcodeproj/xcshareddata/xcschemes/AWSSimpleDB.xcscheme +++ b/AWSSimpleDB.xcodeproj/xcshareddata/xcschemes/AWSSimpleDB.xcscheme @@ -1,6 +1,6 @@ + + diff --git a/CHANGELOG.md b/CHANGELOG.md index eae8a5621c9..7a9ea58c8ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # AWS Mobile SDK for iOS CHANGELOG +## 2.3.2 + +### New Features +* **AWS IoT** + * Added AWS IoT platform APIs. + * Supports publishing and subscribing to MQTT topics with certificate-based authentication. + * Supports device shadows via AWS IoT REST API. + +### Resolved Issues +* **SDK Core** + * Fixed the STS endpoint for the GovCloud region. + * Fixed an issue where module map does not contain appropriate headers. + * Suppressed the erroneous nullability warning. +* **Amazon API Gateway** + * Resolved an issue where the SDK sometimes does not generate the URL path correctly. +* **Amazon Kinesis Recorder** + * Resolved an issue where the SQLite vacuum may fail when there are many concurrent requests. + * Improved the handling of concurrent `DELETE` requests to the SQLite database. + ## 2.3.1 ### New Features diff --git a/LICENSE b/LICENSE index 9bb82c80fea..e8bb87ec79e 100644 --- a/LICENSE +++ b/LICENSE @@ -302,3 +302,13 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==================== + +Components are made available under the terms of the Eclipse Public License v1.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + http://www.eclipse.org/legal/epl-v10.html +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. diff --git a/NOTICE b/NOTICE index 46ed3b56027..ccd5c1e503b 100644 --- a/NOTICE +++ b/NOTICE @@ -34,5 +34,6 @@ This software includes third party software subject to the following copyrights: - Reachability - Copyright (c) 2011-2013, Tony Million. All rights reserved. - https://github.com/tonymillion/Reachability/blob/master/LICENCE.txt - FMDB - Copyright (c) 2008-2014 Flying Meat Inc. - MIT License - Fabric - Copyright (c) 2015 Twitter Inc. - Apache License Version 2.0 +- Objective-C MQTT Client - From the Eclipse Paho Project - Eclipse Public License v1.0 The licenses for these third party components are included in the License file. diff --git a/README.md b/README.md index 00311984a5e..5a1f7a99b25 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ The [sample apps](https://github.com/awslabs/aws-sdk-ios-samples) are standalone pod 'AWSDynamoDB' pod 'AWSEC2' pod 'AWSElasticLoadBalancing' + pod 'AWSIoT' pod 'AWSKinesis' pod 'AWSLambda' pod 'AWSMachineLearning' @@ -90,6 +91,7 @@ The [sample apps](https://github.com/awslabs/aws-sdk-ios-samples) are standalone * `AWSDynamoDB.framework` * `AWSEC2.framework` * `AWSElasticLoadBalancing.framework` + * `AWSIoT.framework` * `AWSKinesis.framework` * `AWSLambda.framework` * `AWSMachineLearning.framework` @@ -101,7 +103,7 @@ The [sample apps](https://github.com/awslabs/aws-sdk-ios-samples) are standalone * `AWSSQS.framework` * `extras/AWSCognito.framework` - for [Amazon Cognito Sync](http://aws.amazon.com/cognito/) -1. Open a target for your project, select **Build Phases**, expand **Link Binary With Libraries**, click the **+** button, and add `libsqlite3.dylib`, `libz.dylib`, and `SystemConfiguration.framework`. +1. Open a target for your project, select **Build Phases**, expand **Link Binary With Libraries**, click the **+** button, and add `libsqlite3.tbd`, `libz.tbd`, `CFNetwork.framework`, `Security.framework`, `SystemConfiguration.framework`, and `UIKit.framework`. ##Update the SDK to a Newer Version @@ -127,6 +129,7 @@ When we release a new version of the SDK, you can pick up the changes as describ * `AWSDynamoDB.framework` * `AWSEC2.framework` * `AWSElasticLoadBalancing.framework` + * `AWSIoT.framework` * `AWSKinesis.framework` * `AWSLambda.framework` * `AWSMachineLearning.framework` @@ -203,7 +206,7 @@ For detailed steps on how to do identify and resolve this issue if your app is a let dynamoDB = AWSDynamoDB.defaultDynamoDB() let listTableInput = AWSDynamoDBListTablesInput() - dynamoDB.listTables(listTableInput).continueWithBlock{ (task: AWSTask!) -> AnyObject! in + dynamoDB.listTables(listTableInput).continueWithBlock{ (task: AWSTask!) -> AnyObject? in if let error = task.error { print("Error occurred: \(error)") return nil @@ -297,7 +300,7 @@ The following logging level options are available: The AWS SDK for iOS includes sample apps that demonstrate common use cases. -###Cognito Sync Sample ([Objective-C](https://github.com/awslabs/aws-sdk-ios-samples/tree/master/CognitoSync-Sample/Objective-C/)) +###Cognito Sync Sample ([Swift](https://github.com/awslabs/aws-sdk-ios-samples/tree/master/CognitoSync-Sample/Swift/), [Objective-C](https://github.com/awslabs/aws-sdk-ios-samples/tree/master/CognitoSync-Sample/Objective-C/)) This sample demonstrates how to securely manage and sync your mobile app data and create unique identities via login providers including Facebook, Google, and Login with Amazon. @@ -344,6 +347,24 @@ This sample demonstrates how to set up Amazon SNS Mobile Push and record events * [Amazon Mobile Analytics](http://aws.amazon.com/mobileanalytics/) * [Amazon Cognito Identity](http://aws.amazon.com/cognito/) +###IoT Sample ([Swift](https://github.com/awslabs/aws-sdk-ios-samples/tree/master/IoT-Sample/Swift/)) + +This sample demonstrates how to publish and subscribe to data using AWS IoT. + +####AWS Services Demonstrated: + +* [Amazon AWS IoT](http://aws.amazon.com/iot/) +* [Amazon Cognito Identity](http://aws.amazon.com/cognito/) + +###IoT Temperature Control Sample ([Swift](https://github.com/awslabs/aws-sdk-ios-samples/tree/master/IoTTemperatureControl-Sample/Swift/)) + +This sample demonstrates accessing device shadows using Cognito authentication; it works in conjunction with the Temperature Control Example Program in the [AWS IoT JavaScript SDK for Embedded Devices](https://github.com/aws/aws-iot-device-sdk-js). + +####AWS Services Demonstrated: + +* [Amazon AWS IoT](http://aws.amazon.com/iot/) +* [Amazon Cognito Identity](http://aws.amazon.com/cognito/) + ##Install the Reference Documentation in Xcode The AWS Mobile SDK for iOS zip file includes documentation in the DocSets format that you can view within Xcode. The easiest way to install the documentation is to use the Mac OS X terminal. diff --git a/Scripts/GenerateAppleDocs.sh b/Scripts/GenerateAppleDocs.sh index 6ba0ba7a205..c95d86dd13c 100644 --- a/Scripts/GenerateAppleDocs.sh +++ b/Scripts/GenerateAppleDocs.sh @@ -9,7 +9,7 @@ function cleanup } -VERSION="2.3.1" +VERSION="2.3.2" if [ -n $1 ] && [ "$1" == "clean" ]; then cleanup @@ -33,6 +33,7 @@ else cp -r AWSDynamoDB ./docs_tmp/AWSDynamoDB cp -r AWSEC2 ./docs_tmp/AWSEC2 cp -r AWSElasticLoadBalancing ./docs_tmp/AWSElasticLoadBalancing + cp -r AWSIoT ./docs_tmp/AWSIoT cp -r AWSKinesis ./docs_tmp/AWSKinesis cp -r AWSLambda ./docs_tmp/AWSLambda cp -r AWSMachineLearning ./docs_tmp/AWSMachineLearning @@ -54,7 +55,7 @@ else rm -rf ./docs_tmp/AWSCore/XMLDictionary rm -rf ./docs_tmp/AWSCore/XMLWriter rm -rf ./docs_tmp/AWSMobileAnalytics/Internal - + rm -rf ./docs_tmp/AWSIoT/Internal if [ -d ./AWSiOSSDKCognitoSync ] then diff --git a/Scripts/Package.sh b/Scripts/Package.sh index 1fd35b431c9..d0eb573029e 100644 --- a/Scripts/Package.sh +++ b/Scripts/Package.sh @@ -28,6 +28,7 @@ if [ -x "Scripts/SdkPackage.sh" ]; then Scripts/SdkPackage.sh AWSDynamoDB Scripts/SdkPackage.sh AWSEC2 Scripts/SdkPackage.sh AWSElasticLoadBalancing + Scripts/SdkPackage.sh AWSIoT Scripts/SdkPackage.sh AWSKinesis Scripts/SdkPackage.sh AWSLambda Scripts/SdkPackage.sh AWSMachineLearning