├── .gitignore ├── Cartfile ├── Info.plist ├── LICENSE ├── MPMessagePack iOS └── Info.plist ├── MPMessagePack.podspec ├── MPMessagePack.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── MPMessagePack iOS.xcscheme │ └── MPMessagePack.xcscheme ├── MPMessagePack ├── MPMessagePack.h ├── MPMessagePackReader.m ├── MPMessagePackWriter.m ├── NSArray+MPMessagePack.m ├── NSData+MPMessagePack.m ├── NSDictionary+MPMessagePack.m ├── RPC │ ├── MPDispatchRequest.m │ ├── MPMessagePackClient.m │ ├── MPMessagePackServer.m │ ├── MPRPCProtocol.m │ └── MPRequestor.m ├── XPC │ ├── MPXPCClient.m │ ├── MPXPCProtocol.m │ └── MPXPCService.m ├── cmp.c └── include │ ├── MPDefines.h │ ├── MPLog.h │ ├── MPMessagePackReader.h │ ├── MPMessagePackWriter.h │ ├── NSArray+MPMessagePack.h │ ├── NSData+MPMessagePack.h │ ├── NSDictionary+MPMessagePack.h │ ├── RPC │ ├── MPDispatchRequest.h │ ├── MPMessagePackClient.h │ ├── MPMessagePackServer.h │ ├── MPRPCProtocol.h │ └── MPRequestor.h │ ├── XPC │ ├── MPXDefines.h │ ├── MPXPCClient.h │ ├── MPXPCProtocol.h │ └── MPXPCService.h │ └── cmp.h ├── MPMessagePackTests ├── Info.plist ├── MPMessagePackClientTest.m ├── MPMessagePackTest.m ├── MPRPCProtocolTest.m └── MPXPCTest.m ├── Package.resolved ├── Package.swift ├── Podfile ├── Podfile.lock ├── README.md └── msgpack.org.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | *.xcscmblueprint 20 | 21 | #CocoaPods 22 | Pods 23 | *.xcworkspace 24 | 25 | Cartfile.resolved 26 | Carthage 27 | build 28 | 29 | # Swift Package Manager 30 | # 31 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 32 | # Packages/ 33 | # Package.pins 34 | # Package.resolved 35 | # *.xcodeproj 36 | # 37 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 38 | # hence it is not needed unless you have added a package configuration file to your project 39 | .swiftpm 40 | 41 | .build/ 42 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "gabriel/GHODictionary" 2 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2015 Gabriel Handford. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Gabriel Handford 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /MPMessagePack iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /MPMessagePack.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "MPMessagePack" 4 | s.version = "1.5.2" 5 | s.summary = "Library for MessagePack" 6 | s.homepage = "https://github.com/gabriel/MPMessagePack" 7 | s.license = { :type => "MIT" } 8 | s.authors = { "Gabriel Handford" => "gabrielh@gmail.com" } 9 | s.source = { :git => "https://github.com/gabriel/MPMessagePack.git", :tag => s.version.to_s } 10 | s.requires_arc = true 11 | 12 | s.dependency "GHODictionary" 13 | 14 | s.ios.deployment_target = "6.0" 15 | s.ios.source_files = "MPMessagePack/**/*.{c,h,m}" 16 | s.ios.exclude_files = "MPMessagePack/XPC/**/*.{c,h,m}", "MPMessagePack/include/XPC/**/*.{c,h,m}" 17 | 18 | s.tvos.deployment_target = "10.0" 19 | s.tvos.source_files = "MPMessagePack/**/*.{c,h,m}" 20 | s.tvos.exclude_files = "MPMessagePack/XPC/**/*.{c,h,m}", "MPMessagePack/include/XPC/**/*.{c,h,m}" 21 | 22 | s.osx.deployment_target = "10.8" 23 | s.osx.source_files = "MPMessagePack/**/*.{c,h,m}" 24 | 25 | end 26 | -------------------------------------------------------------------------------- /MPMessagePack.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 001392211B0418EF0082DEA8 /* cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 00FB32E119661B0A0060AF33 /* cmp.c */; }; 11 | 001392241B0418EF0082DEA8 /* MPMessagePackWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 00FB32CC19661A870060AF33 /* MPMessagePackWriter.m */; }; 12 | 001392261B0418EF0082DEA8 /* MPMessagePackReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 006555AC1966276400288AE7 /* MPMessagePackReader.m */; }; 13 | 001392281B0418EF0082DEA8 /* NSDictionary+MPMessagePack.m in Sources */ = {isa = PBXBuildFile; fileRef = 006555B41966395500288AE7 /* NSDictionary+MPMessagePack.m */; }; 14 | 0013922A1B0418EF0082DEA8 /* NSArray+MPMessagePack.m in Sources */ = {isa = PBXBuildFile; fileRef = 006555B81966397500288AE7 /* NSArray+MPMessagePack.m */; }; 15 | 001392311B0418EF0082DEA8 /* NSData+MPMessagePack.m in Sources */ = {isa = PBXBuildFile; fileRef = 007110B21A5B68DB005DF8D1 /* NSData+MPMessagePack.m */; }; 16 | 003126161E0B456800657DAF /* MPMessagePack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33220B171CFF952F00F3C3DA /* MPMessagePack.framework */; }; 17 | 0031261C1E0B457300657DAF /* MPMessagePackTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 005F67BA1B1503B900898B3C /* MPMessagePackTest.m */; }; 18 | 004270D11B14E74C006F17C7 /* MPMessagePack.h in Headers */ = {isa = PBXBuildFile; fileRef = 006555AF19662E3000288AE7 /* MPMessagePack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | 004CF23B1B93986A002BE5A4 /* MPRPCProtocolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 004CF23A1B93986A002BE5A4 /* MPRPCProtocolTest.m */; }; 20 | 005F67B31B15039100898B3C /* MPMessagePack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 001392081B0418E20082DEA8 /* MPMessagePack.framework */; }; 21 | 005F67BC1B1503B900898B3C /* MPMessagePackClientTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 005F67B91B1503B900898B3C /* MPMessagePackClientTest.m */; }; 22 | 005F67BD1B1503B900898B3C /* MPMessagePackTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 005F67BA1B1503B900898B3C /* MPMessagePackTest.m */; }; 23 | 005F67BE1B1503B900898B3C /* MPXPCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 005F67BB1B1503B900898B3C /* MPXPCTest.m */; }; 24 | 33220B1F1CFF954B00F3C3DA /* MPMessagePack.h in Headers */ = {isa = PBXBuildFile; fileRef = 006555AF19662E3000288AE7 /* MPMessagePack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25 | 33220B201CFF954B00F3C3DA /* cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 00FB32E119661B0A0060AF33 /* cmp.c */; }; 26 | 33220B231CFF954B00F3C3DA /* MPMessagePackWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 00FB32CC19661A870060AF33 /* MPMessagePackWriter.m */; }; 27 | 33220B251CFF954B00F3C3DA /* MPMessagePackReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 006555AC1966276400288AE7 /* MPMessagePackReader.m */; }; 28 | 33220B271CFF954B00F3C3DA /* NSDictionary+MPMessagePack.m in Sources */ = {isa = PBXBuildFile; fileRef = 006555B41966395500288AE7 /* NSDictionary+MPMessagePack.m */; }; 29 | 33220B291CFF954B00F3C3DA /* NSArray+MPMessagePack.m in Sources */ = {isa = PBXBuildFile; fileRef = 006555B81966397500288AE7 /* NSArray+MPMessagePack.m */; }; 30 | 33220B2C1CFF954B00F3C3DA /* NSData+MPMessagePack.m in Sources */ = {isa = PBXBuildFile; fileRef = 007110B21A5B68DB005DF8D1 /* NSData+MPMessagePack.m */; }; 31 | D97D5F4126970910007B5FEE /* NSArray+MPMessagePack.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F2E26970910007B5FEE /* NSArray+MPMessagePack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32 | D97D5F4226970910007B5FEE /* MPMessagePackWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F2F26970910007B5FEE /* MPMessagePackWriter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 33 | D97D5F4326970910007B5FEE /* NSData+MPMessagePack.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3026970910007B5FEE /* NSData+MPMessagePack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34 | D97D5F4426970910007B5FEE /* cmp.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3126970910007B5FEE /* cmp.h */; settings = {ATTRIBUTES = (Public, ); }; }; 35 | D97D5F4526970910007B5FEE /* NSDictionary+MPMessagePack.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3226970910007B5FEE /* NSDictionary+MPMessagePack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 36 | D97D5F4626970910007B5FEE /* MPDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3326970910007B5FEE /* MPDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; 37 | D97D5F4726970910007B5FEE /* MPMessagePackReader.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3426970910007B5FEE /* MPMessagePackReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 38 | D97D5F4826970910007B5FEE /* MPLog.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3526970910007B5FEE /* MPLog.h */; settings = {ATTRIBUTES = (Public, ); }; }; 39 | D97D5F4926970910007B5FEE /* MPRequestor.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3726970910007B5FEE /* MPRequestor.h */; settings = {ATTRIBUTES = (Public, ); }; }; 40 | D97D5F4A26970910007B5FEE /* MPMessagePackServer.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3826970910007B5FEE /* MPMessagePackServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 41 | D97D5F4B26970910007B5FEE /* MPDispatchRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3926970910007B5FEE /* MPDispatchRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; 42 | D97D5F4C26970910007B5FEE /* MPRPCProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3A26970910007B5FEE /* MPRPCProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 43 | D97D5F4D26970910007B5FEE /* MPMessagePackClient.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3B26970910007B5FEE /* MPMessagePackClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; 44 | D97D5F4E26970910007B5FEE /* MPXPCClient.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3D26970910007B5FEE /* MPXPCClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; 45 | D97D5F4F26970910007B5FEE /* MPXDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3E26970910007B5FEE /* MPXDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; 46 | D97D5F5026970910007B5FEE /* MPXPCService.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3F26970910007B5FEE /* MPXPCService.h */; settings = {ATTRIBUTES = (Public, ); }; }; 47 | D97D5F5126970910007B5FEE /* MPXPCProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F4026970910007B5FEE /* MPXPCProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 48 | D97D5F5826970941007B5FEE /* MPMessagePackClient.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5326970941007B5FEE /* MPMessagePackClient.m */; }; 49 | D97D5F5926970941007B5FEE /* MPMessagePackClient.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5326970941007B5FEE /* MPMessagePackClient.m */; }; 50 | D97D5F5A26970941007B5FEE /* MPRPCProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5426970941007B5FEE /* MPRPCProtocol.m */; }; 51 | D97D5F5B26970941007B5FEE /* MPRPCProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5426970941007B5FEE /* MPRPCProtocol.m */; }; 52 | D97D5F5C26970941007B5FEE /* MPRequestor.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5526970941007B5FEE /* MPRequestor.m */; }; 53 | D97D5F5D26970941007B5FEE /* MPRequestor.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5526970941007B5FEE /* MPRequestor.m */; }; 54 | D97D5F5E26970941007B5FEE /* MPDispatchRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5626970941007B5FEE /* MPDispatchRequest.m */; }; 55 | D97D5F5F26970941007B5FEE /* MPDispatchRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5626970941007B5FEE /* MPDispatchRequest.m */; }; 56 | D97D5F6026970941007B5FEE /* MPMessagePackServer.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5726970941007B5FEE /* MPMessagePackServer.m */; }; 57 | D97D5F6126970941007B5FEE /* MPMessagePackServer.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F5726970941007B5FEE /* MPMessagePackServer.m */; }; 58 | D97D5F662697094A007B5FEE /* MPXPCProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F632697094A007B5FEE /* MPXPCProtocol.m */; }; 59 | D97D5F672697094A007B5FEE /* MPXPCClient.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F642697094A007B5FEE /* MPXPCClient.m */; }; 60 | D97D5F682697094A007B5FEE /* MPXPCService.m in Sources */ = {isa = PBXBuildFile; fileRef = D97D5F652697094A007B5FEE /* MPXPCService.m */; }; 61 | D97D5F7D26970D98007B5FEE /* MPMessagePackWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F2F26970910007B5FEE /* MPMessagePackWriter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62 | D97D5F7E26970D98007B5FEE /* NSDictionary+MPMessagePack.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3226970910007B5FEE /* NSDictionary+MPMessagePack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 63 | D97D5F7F26970D98007B5FEE /* MPDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3326970910007B5FEE /* MPDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; 64 | D97D5F8026970D98007B5FEE /* MPLog.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3526970910007B5FEE /* MPLog.h */; settings = {ATTRIBUTES = (Public, ); }; }; 65 | D97D5F8126970D98007B5FEE /* MPMessagePackReader.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3426970910007B5FEE /* MPMessagePackReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 66 | D97D5F8226970D98007B5FEE /* NSArray+MPMessagePack.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F2E26970910007B5FEE /* NSArray+MPMessagePack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 67 | D97D5F8326970D98007B5FEE /* NSData+MPMessagePack.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3026970910007B5FEE /* NSData+MPMessagePack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 68 | D97D5F8426970D98007B5FEE /* cmp.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3126970910007B5FEE /* cmp.h */; settings = {ATTRIBUTES = (Public, ); }; }; 69 | D97D5F8526970DA1007B5FEE /* MPMessagePackServer.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3826970910007B5FEE /* MPMessagePackServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 70 | D97D5F8626970DA1007B5FEE /* MPRPCProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3A26970910007B5FEE /* MPRPCProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 71 | D97D5F8726970DA1007B5FEE /* MPMessagePackClient.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3B26970910007B5FEE /* MPMessagePackClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; 72 | D97D5F8826970DA1007B5FEE /* MPRequestor.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3726970910007B5FEE /* MPRequestor.h */; settings = {ATTRIBUTES = (Public, ); }; }; 73 | D97D5F8926970DA1007B5FEE /* MPDispatchRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D97D5F3926970910007B5FEE /* MPDispatchRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; 74 | /* End PBXBuildFile section */ 75 | 76 | /* Begin PBXContainerItemProxy section */ 77 | 003126171E0B456800657DAF /* PBXContainerItemProxy */ = { 78 | isa = PBXContainerItemProxy; 79 | containerPortal = 00FB32BF19661A860060AF33 /* Project object */; 80 | proxyType = 1; 81 | remoteGlobalIDString = 33220B161CFF952F00F3C3DA; 82 | remoteInfo = "MPMessagePack iOS"; 83 | }; 84 | 005F67B41B15039100898B3C /* PBXContainerItemProxy */ = { 85 | isa = PBXContainerItemProxy; 86 | containerPortal = 00FB32BF19661A860060AF33 /* Project object */; 87 | proxyType = 1; 88 | remoteGlobalIDString = 001392071B0418E20082DEA8; 89 | remoteInfo = MPMessagePack; 90 | }; 91 | /* End PBXContainerItemProxy section */ 92 | 93 | /* Begin PBXFileReference section */ 94 | 001392081B0418E20082DEA8 /* MPMessagePack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MPMessagePack.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 95 | 0031260B1E0B443300657DAF /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 96 | 003126111E0B456800657DAF /* MPMessagePack iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MPMessagePack iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 97 | 0031261D1E0B482400657DAF /* Cartfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cartfile; sourceTree = ""; }; 98 | 004CF23A1B93986A002BE5A4 /* MPRPCProtocolTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRPCProtocolTest.m; sourceTree = ""; }; 99 | 0057EDD519664B7E00F39536 /* msgpack.org.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = msgpack.org.md; sourceTree = ""; }; 100 | 005F67AD1B15039000898B3C /* MPMessagePackTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MPMessagePackTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 101 | 005F67B01B15039100898B3C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 102 | 005F67B91B1503B900898B3C /* MPMessagePackClientTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMessagePackClientTest.m; sourceTree = ""; }; 103 | 005F67BA1B1503B900898B3C /* MPMessagePackTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMessagePackTest.m; sourceTree = ""; }; 104 | 005F67BB1B1503B900898B3C /* MPXPCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPXPCTest.m; sourceTree = ""; }; 105 | 006555AC1966276400288AE7 /* MPMessagePackReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMessagePackReader.m; sourceTree = ""; }; 106 | 006555AF19662E3000288AE7 /* MPMessagePack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMessagePack.h; sourceTree = ""; }; 107 | 006555B41966395500288AE7 /* NSDictionary+MPMessagePack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+MPMessagePack.m"; sourceTree = ""; }; 108 | 006555B81966397500288AE7 /* NSArray+MPMessagePack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+MPMessagePack.m"; sourceTree = ""; }; 109 | 006555BB19663A1600288AE7 /* MPMessagePack.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = MPMessagePack.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 110 | 007110B21A5B68DB005DF8D1 /* NSData+MPMessagePack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+MPMessagePack.m"; sourceTree = ""; }; 111 | 00FB32CC19661A870060AF33 /* MPMessagePackWriter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPMessagePackWriter.m; sourceTree = ""; }; 112 | 00FB32E119661B0A0060AF33 /* cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmp.c; sourceTree = ""; }; 113 | 00FB32E51966240B0060AF33 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 114 | 33220B171CFF952F00F3C3DA /* MPMessagePack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MPMessagePack.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 115 | 33220B1B1CFF952F00F3C3DA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 116 | D97D5F2E26970910007B5FEE /* NSArray+MPMessagePack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+MPMessagePack.h"; sourceTree = ""; }; 117 | D97D5F2F26970910007B5FEE /* MPMessagePackWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMessagePackWriter.h; sourceTree = ""; }; 118 | D97D5F3026970910007B5FEE /* NSData+MPMessagePack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+MPMessagePack.h"; sourceTree = ""; }; 119 | D97D5F3126970910007B5FEE /* cmp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmp.h; sourceTree = ""; }; 120 | D97D5F3226970910007B5FEE /* NSDictionary+MPMessagePack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+MPMessagePack.h"; sourceTree = ""; }; 121 | D97D5F3326970910007B5FEE /* MPDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPDefines.h; sourceTree = ""; }; 122 | D97D5F3426970910007B5FEE /* MPMessagePackReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMessagePackReader.h; sourceTree = ""; }; 123 | D97D5F3526970910007B5FEE /* MPLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLog.h; sourceTree = ""; }; 124 | D97D5F3726970910007B5FEE /* MPRequestor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRequestor.h; sourceTree = ""; }; 125 | D97D5F3826970910007B5FEE /* MPMessagePackServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMessagePackServer.h; sourceTree = ""; }; 126 | D97D5F3926970910007B5FEE /* MPDispatchRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPDispatchRequest.h; sourceTree = ""; }; 127 | D97D5F3A26970910007B5FEE /* MPRPCProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRPCProtocol.h; sourceTree = ""; }; 128 | D97D5F3B26970910007B5FEE /* MPMessagePackClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMessagePackClient.h; sourceTree = ""; }; 129 | D97D5F3D26970910007B5FEE /* MPXPCClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPXPCClient.h; sourceTree = ""; }; 130 | D97D5F3E26970910007B5FEE /* MPXDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPXDefines.h; sourceTree = ""; }; 131 | D97D5F3F26970910007B5FEE /* MPXPCService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPXPCService.h; sourceTree = ""; }; 132 | D97D5F4026970910007B5FEE /* MPXPCProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPXPCProtocol.h; sourceTree = ""; }; 133 | D97D5F5326970941007B5FEE /* MPMessagePackClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMessagePackClient.m; sourceTree = ""; }; 134 | D97D5F5426970941007B5FEE /* MPRPCProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRPCProtocol.m; sourceTree = ""; }; 135 | D97D5F5526970941007B5FEE /* MPRequestor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRequestor.m; sourceTree = ""; }; 136 | D97D5F5626970941007B5FEE /* MPDispatchRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPDispatchRequest.m; sourceTree = ""; }; 137 | D97D5F5726970941007B5FEE /* MPMessagePackServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMessagePackServer.m; sourceTree = ""; }; 138 | D97D5F632697094A007B5FEE /* MPXPCProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPXPCProtocol.m; sourceTree = ""; }; 139 | D97D5F642697094A007B5FEE /* MPXPCClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPXPCClient.m; sourceTree = ""; }; 140 | D97D5F652697094A007B5FEE /* MPXPCService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPXPCService.m; sourceTree = ""; }; 141 | /* End PBXFileReference section */ 142 | 143 | /* Begin PBXFrameworksBuildPhase section */ 144 | 001392041B0418E20082DEA8 /* Frameworks */ = { 145 | isa = PBXFrameworksBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | ); 149 | runOnlyForDeploymentPostprocessing = 0; 150 | }; 151 | 0031260E1E0B456800657DAF /* Frameworks */ = { 152 | isa = PBXFrameworksBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | 003126161E0B456800657DAF /* MPMessagePack.framework in Frameworks */, 156 | ); 157 | runOnlyForDeploymentPostprocessing = 0; 158 | }; 159 | 005F67AA1B15039000898B3C /* Frameworks */ = { 160 | isa = PBXFrameworksBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | 005F67B31B15039100898B3C /* MPMessagePack.framework in Frameworks */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | 33220B131CFF952F00F3C3DA /* Frameworks */ = { 168 | isa = PBXFrameworksBuildPhase; 169 | buildActionMask = 2147483647; 170 | files = ( 171 | ); 172 | runOnlyForDeploymentPostprocessing = 0; 173 | }; 174 | /* End PBXFrameworksBuildPhase section */ 175 | 176 | /* Begin PBXGroup section */ 177 | 005F67AE1B15039100898B3C /* MPMessagePackTests */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | 005F67BA1B1503B900898B3C /* MPMessagePackTest.m */, 181 | 005F67B91B1503B900898B3C /* MPMessagePackClientTest.m */, 182 | 005F67BB1B1503B900898B3C /* MPXPCTest.m */, 183 | 004CF23A1B93986A002BE5A4 /* MPRPCProtocolTest.m */, 184 | 005F67AF1B15039100898B3C /* Supporting Files */, 185 | ); 186 | path = MPMessagePackTests; 187 | sourceTree = ""; 188 | }; 189 | 005F67AF1B15039100898B3C /* Supporting Files */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 005F67B01B15039100898B3C /* Info.plist */, 193 | ); 194 | name = "Supporting Files"; 195 | sourceTree = ""; 196 | }; 197 | 00FB32BE19661A860060AF33 = { 198 | isa = PBXGroup; 199 | children = ( 200 | 0031261D1E0B482400657DAF /* Cartfile */, 201 | 0031260B1E0B443300657DAF /* Podfile */, 202 | 006555BB19663A1600288AE7 /* MPMessagePack.podspec */, 203 | 00FB32E51966240B0060AF33 /* README.md */, 204 | 0057EDD519664B7E00F39536 /* msgpack.org.md */, 205 | 00FB32C919661A860060AF33 /* MPMessagePack */, 206 | 005F67AE1B15039100898B3C /* MPMessagePackTests */, 207 | 33220B181CFF952F00F3C3DA /* MPMessagePack iOS */, 208 | 00FB32C819661A860060AF33 /* Products */, 209 | ); 210 | sourceTree = ""; 211 | }; 212 | 00FB32C819661A860060AF33 /* Products */ = { 213 | isa = PBXGroup; 214 | children = ( 215 | 001392081B0418E20082DEA8 /* MPMessagePack.framework */, 216 | 005F67AD1B15039000898B3C /* MPMessagePackTests.xctest */, 217 | 33220B171CFF952F00F3C3DA /* MPMessagePack.framework */, 218 | 003126111E0B456800657DAF /* MPMessagePack iOS Tests.xctest */, 219 | ); 220 | name = Products; 221 | sourceTree = ""; 222 | }; 223 | 00FB32C919661A860060AF33 /* MPMessagePack */ = { 224 | isa = PBXGroup; 225 | children = ( 226 | D97D5F2D26970910007B5FEE /* include */, 227 | D97D5F5226970941007B5FEE /* RPC */, 228 | D97D5F622697094A007B5FEE /* XPC */, 229 | 006555AF19662E3000288AE7 /* MPMessagePack.h */, 230 | 00FB32E119661B0A0060AF33 /* cmp.c */, 231 | 00FB32CC19661A870060AF33 /* MPMessagePackWriter.m */, 232 | 006555AC1966276400288AE7 /* MPMessagePackReader.m */, 233 | 006555B41966395500288AE7 /* NSDictionary+MPMessagePack.m */, 234 | 006555B81966397500288AE7 /* NSArray+MPMessagePack.m */, 235 | 007110B21A5B68DB005DF8D1 /* NSData+MPMessagePack.m */, 236 | ); 237 | path = MPMessagePack; 238 | sourceTree = ""; 239 | }; 240 | 33220B181CFF952F00F3C3DA /* MPMessagePack iOS */ = { 241 | isa = PBXGroup; 242 | children = ( 243 | 33220B1B1CFF952F00F3C3DA /* Info.plist */, 244 | ); 245 | path = "MPMessagePack iOS"; 246 | sourceTree = ""; 247 | }; 248 | D97D5F2D26970910007B5FEE /* include */ = { 249 | isa = PBXGroup; 250 | children = ( 251 | D97D5F2E26970910007B5FEE /* NSArray+MPMessagePack.h */, 252 | D97D5F2F26970910007B5FEE /* MPMessagePackWriter.h */, 253 | D97D5F3026970910007B5FEE /* NSData+MPMessagePack.h */, 254 | D97D5F3126970910007B5FEE /* cmp.h */, 255 | D97D5F3226970910007B5FEE /* NSDictionary+MPMessagePack.h */, 256 | D97D5F3326970910007B5FEE /* MPDefines.h */, 257 | D97D5F3426970910007B5FEE /* MPMessagePackReader.h */, 258 | D97D5F3526970910007B5FEE /* MPLog.h */, 259 | D97D5F3626970910007B5FEE /* RPC */, 260 | D97D5F3C26970910007B5FEE /* XPC */, 261 | ); 262 | path = include; 263 | sourceTree = ""; 264 | }; 265 | D97D5F3626970910007B5FEE /* RPC */ = { 266 | isa = PBXGroup; 267 | children = ( 268 | D97D5F3726970910007B5FEE /* MPRequestor.h */, 269 | D97D5F3826970910007B5FEE /* MPMessagePackServer.h */, 270 | D97D5F3926970910007B5FEE /* MPDispatchRequest.h */, 271 | D97D5F3A26970910007B5FEE /* MPRPCProtocol.h */, 272 | D97D5F3B26970910007B5FEE /* MPMessagePackClient.h */, 273 | ); 274 | path = RPC; 275 | sourceTree = ""; 276 | }; 277 | D97D5F3C26970910007B5FEE /* XPC */ = { 278 | isa = PBXGroup; 279 | children = ( 280 | D97D5F3D26970910007B5FEE /* MPXPCClient.h */, 281 | D97D5F3E26970910007B5FEE /* MPXDefines.h */, 282 | D97D5F3F26970910007B5FEE /* MPXPCService.h */, 283 | D97D5F4026970910007B5FEE /* MPXPCProtocol.h */, 284 | ); 285 | path = XPC; 286 | sourceTree = ""; 287 | }; 288 | D97D5F5226970941007B5FEE /* RPC */ = { 289 | isa = PBXGroup; 290 | children = ( 291 | D97D5F5326970941007B5FEE /* MPMessagePackClient.m */, 292 | D97D5F5426970941007B5FEE /* MPRPCProtocol.m */, 293 | D97D5F5526970941007B5FEE /* MPRequestor.m */, 294 | D97D5F5626970941007B5FEE /* MPDispatchRequest.m */, 295 | D97D5F5726970941007B5FEE /* MPMessagePackServer.m */, 296 | ); 297 | path = RPC; 298 | sourceTree = ""; 299 | }; 300 | D97D5F622697094A007B5FEE /* XPC */ = { 301 | isa = PBXGroup; 302 | children = ( 303 | D97D5F632697094A007B5FEE /* MPXPCProtocol.m */, 304 | D97D5F642697094A007B5FEE /* MPXPCClient.m */, 305 | D97D5F652697094A007B5FEE /* MPXPCService.m */, 306 | ); 307 | path = XPC; 308 | sourceTree = ""; 309 | }; 310 | /* End PBXGroup section */ 311 | 312 | /* Begin PBXHeadersBuildPhase section */ 313 | 001392051B0418E20082DEA8 /* Headers */ = { 314 | isa = PBXHeadersBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | D97D5F4626970910007B5FEE /* MPDefines.h in Headers */, 318 | D97D5F4126970910007B5FEE /* NSArray+MPMessagePack.h in Headers */, 319 | D97D5F4426970910007B5FEE /* cmp.h in Headers */, 320 | D97D5F4926970910007B5FEE /* MPRequestor.h in Headers */, 321 | D97D5F4C26970910007B5FEE /* MPRPCProtocol.h in Headers */, 322 | D97D5F4A26970910007B5FEE /* MPMessagePackServer.h in Headers */, 323 | D97D5F4526970910007B5FEE /* NSDictionary+MPMessagePack.h in Headers */, 324 | D97D5F4E26970910007B5FEE /* MPXPCClient.h in Headers */, 325 | D97D5F4B26970910007B5FEE /* MPDispatchRequest.h in Headers */, 326 | D97D5F4326970910007B5FEE /* NSData+MPMessagePack.h in Headers */, 327 | D97D5F4826970910007B5FEE /* MPLog.h in Headers */, 328 | D97D5F5126970910007B5FEE /* MPXPCProtocol.h in Headers */, 329 | D97D5F4F26970910007B5FEE /* MPXDefines.h in Headers */, 330 | D97D5F4D26970910007B5FEE /* MPMessagePackClient.h in Headers */, 331 | 004270D11B14E74C006F17C7 /* MPMessagePack.h in Headers */, 332 | D97D5F4226970910007B5FEE /* MPMessagePackWriter.h in Headers */, 333 | D97D5F5026970910007B5FEE /* MPXPCService.h in Headers */, 334 | D97D5F4726970910007B5FEE /* MPMessagePackReader.h in Headers */, 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | 33220B141CFF952F00F3C3DA /* Headers */ = { 339 | isa = PBXHeadersBuildPhase; 340 | buildActionMask = 2147483647; 341 | files = ( 342 | D97D5F8026970D98007B5FEE /* MPLog.h in Headers */, 343 | D97D5F8926970DA1007B5FEE /* MPDispatchRequest.h in Headers */, 344 | D97D5F8526970DA1007B5FEE /* MPMessagePackServer.h in Headers */, 345 | D97D5F7F26970D98007B5FEE /* MPDefines.h in Headers */, 346 | D97D5F8726970DA1007B5FEE /* MPMessagePackClient.h in Headers */, 347 | D97D5F8626970DA1007B5FEE /* MPRPCProtocol.h in Headers */, 348 | 33220B1F1CFF954B00F3C3DA /* MPMessagePack.h in Headers */, 349 | D97D5F8826970DA1007B5FEE /* MPRequestor.h in Headers */, 350 | D97D5F8326970D98007B5FEE /* NSData+MPMessagePack.h in Headers */, 351 | D97D5F7D26970D98007B5FEE /* MPMessagePackWriter.h in Headers */, 352 | D97D5F7E26970D98007B5FEE /* NSDictionary+MPMessagePack.h in Headers */, 353 | D97D5F8426970D98007B5FEE /* cmp.h in Headers */, 354 | D97D5F8126970D98007B5FEE /* MPMessagePackReader.h in Headers */, 355 | D97D5F8226970D98007B5FEE /* NSArray+MPMessagePack.h in Headers */, 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | }; 359 | /* End PBXHeadersBuildPhase section */ 360 | 361 | /* Begin PBXNativeTarget section */ 362 | 001392071B0418E20082DEA8 /* MPMessagePack */ = { 363 | isa = PBXNativeTarget; 364 | buildConfigurationList = 0013921B1B0418E20082DEA8 /* Build configuration list for PBXNativeTarget "MPMessagePack" */; 365 | buildPhases = ( 366 | 001392031B0418E20082DEA8 /* Sources */, 367 | 001392041B0418E20082DEA8 /* Frameworks */, 368 | 001392051B0418E20082DEA8 /* Headers */, 369 | 001392061B0418E20082DEA8 /* Resources */, 370 | ); 371 | buildRules = ( 372 | ); 373 | dependencies = ( 374 | ); 375 | name = MPMessagePack; 376 | productName = MPMessagePackOSX; 377 | productReference = 001392081B0418E20082DEA8 /* MPMessagePack.framework */; 378 | productType = "com.apple.product-type.framework"; 379 | }; 380 | 003126101E0B456800657DAF /* MPMessagePack iOS Tests */ = { 381 | isa = PBXNativeTarget; 382 | buildConfigurationList = 0031261B1E0B456800657DAF /* Build configuration list for PBXNativeTarget "MPMessagePack iOS Tests" */; 383 | buildPhases = ( 384 | 0031260D1E0B456800657DAF /* Sources */, 385 | 0031260E1E0B456800657DAF /* Frameworks */, 386 | 0031260F1E0B456800657DAF /* Resources */, 387 | ); 388 | buildRules = ( 389 | ); 390 | dependencies = ( 391 | 003126181E0B456800657DAF /* PBXTargetDependency */, 392 | ); 393 | name = "MPMessagePack iOS Tests"; 394 | productName = "MPMessagePack iOS Tests"; 395 | productReference = 003126111E0B456800657DAF /* MPMessagePack iOS Tests.xctest */; 396 | productType = "com.apple.product-type.bundle.unit-test"; 397 | }; 398 | 005F67AC1B15039000898B3C /* MPMessagePackTests */ = { 399 | isa = PBXNativeTarget; 400 | buildConfigurationList = 005F67B61B15039100898B3C /* Build configuration list for PBXNativeTarget "MPMessagePackTests" */; 401 | buildPhases = ( 402 | 005F67A91B15039000898B3C /* Sources */, 403 | 005F67AA1B15039000898B3C /* Frameworks */, 404 | 005F67AB1B15039000898B3C /* Resources */, 405 | ); 406 | buildRules = ( 407 | ); 408 | dependencies = ( 409 | 005F67B51B15039100898B3C /* PBXTargetDependency */, 410 | ); 411 | name = MPMessagePackTests; 412 | productName = MPMessagePackTests; 413 | productReference = 005F67AD1B15039000898B3C /* MPMessagePackTests.xctest */; 414 | productType = "com.apple.product-type.bundle.unit-test"; 415 | }; 416 | 33220B161CFF952F00F3C3DA /* MPMessagePack iOS */ = { 417 | isa = PBXNativeTarget; 418 | buildConfigurationList = 33220B1E1CFF952F00F3C3DA /* Build configuration list for PBXNativeTarget "MPMessagePack iOS" */; 419 | buildPhases = ( 420 | 33220B121CFF952F00F3C3DA /* Sources */, 421 | 33220B131CFF952F00F3C3DA /* Frameworks */, 422 | 33220B141CFF952F00F3C3DA /* Headers */, 423 | 33220B151CFF952F00F3C3DA /* Resources */, 424 | ); 425 | buildRules = ( 426 | ); 427 | dependencies = ( 428 | ); 429 | name = "MPMessagePack iOS"; 430 | productName = "MPMessagePack iOS"; 431 | productReference = 33220B171CFF952F00F3C3DA /* MPMessagePack.framework */; 432 | productType = "com.apple.product-type.framework"; 433 | }; 434 | /* End PBXNativeTarget section */ 435 | 436 | /* Begin PBXProject section */ 437 | 00FB32BF19661A860060AF33 /* Project object */ = { 438 | isa = PBXProject; 439 | attributes = { 440 | LastSwiftUpdateCheck = 0700; 441 | LastUpgradeCheck = 0940; 442 | ORGANIZATIONNAME = "Gabriel Handford"; 443 | TargetAttributes = { 444 | 001392071B0418E20082DEA8 = { 445 | CreatedOnToolsVersion = 6.3.1; 446 | }; 447 | 003126101E0B456800657DAF = { 448 | CreatedOnToolsVersion = 8.2.1; 449 | ProvisioningStyle = Automatic; 450 | }; 451 | 005F67AC1B15039000898B3C = { 452 | CreatedOnToolsVersion = 6.3.2; 453 | }; 454 | 33220B161CFF952F00F3C3DA = { 455 | CreatedOnToolsVersion = 7.3.1; 456 | DevelopmentTeam = 7ZVA8A38DQ; 457 | }; 458 | }; 459 | }; 460 | buildConfigurationList = 00FB32C219661A860060AF33 /* Build configuration list for PBXProject "MPMessagePack" */; 461 | compatibilityVersion = "Xcode 3.2"; 462 | developmentRegion = English; 463 | hasScannedForEncodings = 0; 464 | knownRegions = ( 465 | English, 466 | en, 467 | Base, 468 | ); 469 | mainGroup = 00FB32BE19661A860060AF33; 470 | productRefGroup = 00FB32C819661A860060AF33 /* Products */; 471 | projectDirPath = ""; 472 | projectRoot = ""; 473 | targets = ( 474 | 001392071B0418E20082DEA8 /* MPMessagePack */, 475 | 005F67AC1B15039000898B3C /* MPMessagePackTests */, 476 | 33220B161CFF952F00F3C3DA /* MPMessagePack iOS */, 477 | 003126101E0B456800657DAF /* MPMessagePack iOS Tests */, 478 | ); 479 | }; 480 | /* End PBXProject section */ 481 | 482 | /* Begin PBXResourcesBuildPhase section */ 483 | 001392061B0418E20082DEA8 /* Resources */ = { 484 | isa = PBXResourcesBuildPhase; 485 | buildActionMask = 2147483647; 486 | files = ( 487 | ); 488 | runOnlyForDeploymentPostprocessing = 0; 489 | }; 490 | 0031260F1E0B456800657DAF /* Resources */ = { 491 | isa = PBXResourcesBuildPhase; 492 | buildActionMask = 2147483647; 493 | files = ( 494 | ); 495 | runOnlyForDeploymentPostprocessing = 0; 496 | }; 497 | 005F67AB1B15039000898B3C /* Resources */ = { 498 | isa = PBXResourcesBuildPhase; 499 | buildActionMask = 2147483647; 500 | files = ( 501 | ); 502 | runOnlyForDeploymentPostprocessing = 0; 503 | }; 504 | 33220B151CFF952F00F3C3DA /* Resources */ = { 505 | isa = PBXResourcesBuildPhase; 506 | buildActionMask = 2147483647; 507 | files = ( 508 | ); 509 | runOnlyForDeploymentPostprocessing = 0; 510 | }; 511 | /* End PBXResourcesBuildPhase section */ 512 | 513 | /* Begin PBXSourcesBuildPhase section */ 514 | 001392031B0418E20082DEA8 /* Sources */ = { 515 | isa = PBXSourcesBuildPhase; 516 | buildActionMask = 2147483647; 517 | files = ( 518 | D97D5F5E26970941007B5FEE /* MPDispatchRequest.m in Sources */, 519 | D97D5F6026970941007B5FEE /* MPMessagePackServer.m in Sources */, 520 | 001392311B0418EF0082DEA8 /* NSData+MPMessagePack.m in Sources */, 521 | 0013922A1B0418EF0082DEA8 /* NSArray+MPMessagePack.m in Sources */, 522 | D97D5F662697094A007B5FEE /* MPXPCProtocol.m in Sources */, 523 | D97D5F5C26970941007B5FEE /* MPRequestor.m in Sources */, 524 | D97D5F682697094A007B5FEE /* MPXPCService.m in Sources */, 525 | 001392241B0418EF0082DEA8 /* MPMessagePackWriter.m in Sources */, 526 | D97D5F5826970941007B5FEE /* MPMessagePackClient.m in Sources */, 527 | 001392211B0418EF0082DEA8 /* cmp.c in Sources */, 528 | 001392281B0418EF0082DEA8 /* NSDictionary+MPMessagePack.m in Sources */, 529 | D97D5F672697094A007B5FEE /* MPXPCClient.m in Sources */, 530 | D97D5F5A26970941007B5FEE /* MPRPCProtocol.m in Sources */, 531 | 001392261B0418EF0082DEA8 /* MPMessagePackReader.m in Sources */, 532 | ); 533 | runOnlyForDeploymentPostprocessing = 0; 534 | }; 535 | 0031260D1E0B456800657DAF /* Sources */ = { 536 | isa = PBXSourcesBuildPhase; 537 | buildActionMask = 2147483647; 538 | files = ( 539 | 0031261C1E0B457300657DAF /* MPMessagePackTest.m in Sources */, 540 | ); 541 | runOnlyForDeploymentPostprocessing = 0; 542 | }; 543 | 005F67A91B15039000898B3C /* Sources */ = { 544 | isa = PBXSourcesBuildPhase; 545 | buildActionMask = 2147483647; 546 | files = ( 547 | 005F67BC1B1503B900898B3C /* MPMessagePackClientTest.m in Sources */, 548 | 005F67BD1B1503B900898B3C /* MPMessagePackTest.m in Sources */, 549 | 004CF23B1B93986A002BE5A4 /* MPRPCProtocolTest.m in Sources */, 550 | 005F67BE1B1503B900898B3C /* MPXPCTest.m in Sources */, 551 | ); 552 | runOnlyForDeploymentPostprocessing = 0; 553 | }; 554 | 33220B121CFF952F00F3C3DA /* Sources */ = { 555 | isa = PBXSourcesBuildPhase; 556 | buildActionMask = 2147483647; 557 | files = ( 558 | D97D5F5F26970941007B5FEE /* MPDispatchRequest.m in Sources */, 559 | D97D5F6126970941007B5FEE /* MPMessagePackServer.m in Sources */, 560 | 33220B291CFF954B00F3C3DA /* NSArray+MPMessagePack.m in Sources */, 561 | 33220B231CFF954B00F3C3DA /* MPMessagePackWriter.m in Sources */, 562 | D97D5F5D26970941007B5FEE /* MPRequestor.m in Sources */, 563 | 33220B2C1CFF954B00F3C3DA /* NSData+MPMessagePack.m in Sources */, 564 | D97D5F5926970941007B5FEE /* MPMessagePackClient.m in Sources */, 565 | 33220B201CFF954B00F3C3DA /* cmp.c in Sources */, 566 | 33220B271CFF954B00F3C3DA /* NSDictionary+MPMessagePack.m in Sources */, 567 | D97D5F5B26970941007B5FEE /* MPRPCProtocol.m in Sources */, 568 | 33220B251CFF954B00F3C3DA /* MPMessagePackReader.m in Sources */, 569 | ); 570 | runOnlyForDeploymentPostprocessing = 0; 571 | }; 572 | /* End PBXSourcesBuildPhase section */ 573 | 574 | /* Begin PBXTargetDependency section */ 575 | 003126181E0B456800657DAF /* PBXTargetDependency */ = { 576 | isa = PBXTargetDependency; 577 | target = 33220B161CFF952F00F3C3DA /* MPMessagePack iOS */; 578 | targetProxy = 003126171E0B456800657DAF /* PBXContainerItemProxy */; 579 | }; 580 | 005F67B51B15039100898B3C /* PBXTargetDependency */ = { 581 | isa = PBXTargetDependency; 582 | target = 001392071B0418E20082DEA8 /* MPMessagePack */; 583 | targetProxy = 005F67B41B15039100898B3C /* PBXContainerItemProxy */; 584 | }; 585 | /* End PBXTargetDependency section */ 586 | 587 | /* Begin XCBuildConfiguration section */ 588 | 0013921C1B0418E20082DEA8 /* Debug */ = { 589 | isa = XCBuildConfiguration; 590 | buildSettings = { 591 | CLANG_ENABLE_MODULES = YES; 592 | CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = NO; 593 | COMBINE_HIDPI_IMAGES = YES; 594 | CURRENT_PROJECT_VERSION = 1; 595 | DEBUG_INFORMATION_FORMAT = dwarf; 596 | DEFINES_MODULE = YES; 597 | DYLIB_COMPATIBILITY_VERSION = 1; 598 | DYLIB_CURRENT_VERSION = 1; 599 | FRAMEWORK_SEARCH_PATHS = ( 600 | "$(inherited)", 601 | "$(PROJECT_DIR)/Carthage/Build/Mac", 602 | ); 603 | FRAMEWORK_VERSION = A; 604 | GCC_NO_COMMON_BLOCKS = YES; 605 | GCC_PREPROCESSOR_DEFINITIONS = ( 606 | "DEBUG=1", 607 | "$(inherited)", 608 | ); 609 | INFOPLIST_FILE = Info.plist; 610 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 611 | MACOSX_DEPLOYMENT_TARGET = 10.10; 612 | MTL_ENABLE_DEBUG_INFO = YES; 613 | PRODUCT_BUNDLE_IDENTIFIER = "me.rel.$(PRODUCT_NAME:rfc1034identifier)"; 614 | PRODUCT_NAME = MPMessagePack; 615 | SDKROOT = macosx; 616 | SKIP_INSTALL = YES; 617 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 618 | VERSIONING_SYSTEM = "apple-generic"; 619 | VERSION_INFO_PREFIX = ""; 620 | }; 621 | name = Debug; 622 | }; 623 | 0013921D1B0418E20082DEA8 /* Release */ = { 624 | isa = XCBuildConfiguration; 625 | buildSettings = { 626 | CLANG_ENABLE_MODULES = YES; 627 | CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = NO; 628 | COMBINE_HIDPI_IMAGES = YES; 629 | COPY_PHASE_STRIP = NO; 630 | CURRENT_PROJECT_VERSION = 1; 631 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 632 | DEFINES_MODULE = YES; 633 | DYLIB_COMPATIBILITY_VERSION = 1; 634 | DYLIB_CURRENT_VERSION = 1; 635 | FRAMEWORK_SEARCH_PATHS = ( 636 | "$(inherited)", 637 | "$(PROJECT_DIR)/Carthage/Build/Mac", 638 | ); 639 | FRAMEWORK_VERSION = A; 640 | GCC_NO_COMMON_BLOCKS = YES; 641 | INFOPLIST_FILE = Info.plist; 642 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 643 | MACOSX_DEPLOYMENT_TARGET = 10.10; 644 | MTL_ENABLE_DEBUG_INFO = NO; 645 | PRODUCT_BUNDLE_IDENTIFIER = "me.rel.$(PRODUCT_NAME:rfc1034identifier)"; 646 | PRODUCT_NAME = MPMessagePack; 647 | SDKROOT = macosx; 648 | SKIP_INSTALL = YES; 649 | VERSIONING_SYSTEM = "apple-generic"; 650 | VERSION_INFO_PREFIX = ""; 651 | }; 652 | name = Release; 653 | }; 654 | 003126191E0B456800657DAF /* Debug */ = { 655 | isa = XCBuildConfiguration; 656 | buildSettings = { 657 | CLANG_ANALYZER_NONNULL = YES; 658 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 659 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 660 | DEBUG_INFORMATION_FORMAT = dwarf; 661 | INFOPLIST_FILE = MPMessagePackTests/Info.plist; 662 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 663 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 664 | MTL_ENABLE_DEBUG_INFO = YES; 665 | PRODUCT_BUNDLE_IDENTIFIER = "rel.me.MPMessagePack-iOS-Tests"; 666 | PRODUCT_NAME = "$(TARGET_NAME)"; 667 | }; 668 | name = Debug; 669 | }; 670 | 0031261A1E0B456800657DAF /* Release */ = { 671 | isa = XCBuildConfiguration; 672 | buildSettings = { 673 | CLANG_ANALYZER_NONNULL = YES; 674 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 675 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 676 | COPY_PHASE_STRIP = NO; 677 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 678 | INFOPLIST_FILE = MPMessagePackTests/Info.plist; 679 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 680 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 681 | MTL_ENABLE_DEBUG_INFO = NO; 682 | PRODUCT_BUNDLE_IDENTIFIER = "rel.me.MPMessagePack-iOS-Tests"; 683 | PRODUCT_NAME = "$(TARGET_NAME)"; 684 | }; 685 | name = Release; 686 | }; 687 | 005F67B71B15039100898B3C /* Debug */ = { 688 | isa = XCBuildConfiguration; 689 | buildSettings = { 690 | COMBINE_HIDPI_IMAGES = YES; 691 | DEBUG_INFORMATION_FORMAT = dwarf; 692 | FRAMEWORK_SEARCH_PATHS = ( 693 | "$(DEVELOPER_FRAMEWORKS_DIR)", 694 | "$(inherited)", 695 | ); 696 | GCC_NO_COMMON_BLOCKS = YES; 697 | GCC_PREPROCESSOR_DEFINITIONS = ( 698 | "DEBUG=1", 699 | "$(inherited)", 700 | ); 701 | INFOPLIST_FILE = MPMessagePackTests/Info.plist; 702 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 703 | MACOSX_DEPLOYMENT_TARGET = 10.10; 704 | MTL_ENABLE_DEBUG_INFO = YES; 705 | PRODUCT_BUNDLE_IDENTIFIER = "me.rel.$(PRODUCT_NAME:rfc1034identifier)"; 706 | PRODUCT_NAME = "$(TARGET_NAME)"; 707 | SDKROOT = macosx; 708 | }; 709 | name = Debug; 710 | }; 711 | 005F67B81B15039100898B3C /* Release */ = { 712 | isa = XCBuildConfiguration; 713 | buildSettings = { 714 | COMBINE_HIDPI_IMAGES = YES; 715 | COPY_PHASE_STRIP = NO; 716 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 717 | FRAMEWORK_SEARCH_PATHS = ( 718 | "$(DEVELOPER_FRAMEWORKS_DIR)", 719 | "$(inherited)", 720 | ); 721 | GCC_NO_COMMON_BLOCKS = YES; 722 | INFOPLIST_FILE = MPMessagePackTests/Info.plist; 723 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 724 | MACOSX_DEPLOYMENT_TARGET = 10.10; 725 | MTL_ENABLE_DEBUG_INFO = NO; 726 | PRODUCT_BUNDLE_IDENTIFIER = "me.rel.$(PRODUCT_NAME:rfc1034identifier)"; 727 | PRODUCT_NAME = "$(TARGET_NAME)"; 728 | SDKROOT = macosx; 729 | }; 730 | name = Release; 731 | }; 732 | 00FB32D919661A870060AF33 /* Debug */ = { 733 | isa = XCBuildConfiguration; 734 | buildSettings = { 735 | ALWAYS_SEARCH_USER_PATHS = NO; 736 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 737 | CLANG_CXX_LIBRARY = "libc++"; 738 | CLANG_ENABLE_MODULES = YES; 739 | CLANG_ENABLE_OBJC_ARC = YES; 740 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 741 | CLANG_WARN_BOOL_CONVERSION = YES; 742 | CLANG_WARN_COMMA = YES; 743 | CLANG_WARN_CONSTANT_CONVERSION = YES; 744 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 745 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 746 | CLANG_WARN_EMPTY_BODY = YES; 747 | CLANG_WARN_ENUM_CONVERSION = YES; 748 | CLANG_WARN_INFINITE_RECURSION = YES; 749 | CLANG_WARN_INT_CONVERSION = YES; 750 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 751 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 752 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 753 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 754 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 755 | CLANG_WARN_STRICT_PROTOTYPES = YES; 756 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 757 | CLANG_WARN_UNREACHABLE_CODE = YES; 758 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 759 | COPY_PHASE_STRIP = NO; 760 | ENABLE_STRICT_OBJC_MSGSEND = YES; 761 | ENABLE_TESTABILITY = YES; 762 | GCC_C_LANGUAGE_STANDARD = gnu99; 763 | GCC_DYNAMIC_NO_PIC = NO; 764 | GCC_NO_COMMON_BLOCKS = YES; 765 | GCC_OPTIMIZATION_LEVEL = 0; 766 | GCC_PREPROCESSOR_DEFINITIONS = ( 767 | "DEBUG=1", 768 | "$(inherited)", 769 | ); 770 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 771 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 772 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 773 | GCC_WARN_UNDECLARED_SELECTOR = YES; 774 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 775 | GCC_WARN_UNUSED_FUNCTION = YES; 776 | GCC_WARN_UNUSED_VARIABLE = YES; 777 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 778 | MACOSX_DEPLOYMENT_TARGET = 10.10; 779 | METAL_ENABLE_DEBUG_INFO = YES; 780 | ONLY_ACTIVE_ARCH = YES; 781 | SDKROOT = iphoneos; 782 | }; 783 | name = Debug; 784 | }; 785 | 00FB32DA19661A870060AF33 /* Release */ = { 786 | isa = XCBuildConfiguration; 787 | buildSettings = { 788 | ALWAYS_SEARCH_USER_PATHS = NO; 789 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 790 | CLANG_CXX_LIBRARY = "libc++"; 791 | CLANG_ENABLE_MODULES = YES; 792 | CLANG_ENABLE_OBJC_ARC = YES; 793 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 794 | CLANG_WARN_BOOL_CONVERSION = YES; 795 | CLANG_WARN_COMMA = YES; 796 | CLANG_WARN_CONSTANT_CONVERSION = YES; 797 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 798 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 799 | CLANG_WARN_EMPTY_BODY = YES; 800 | CLANG_WARN_ENUM_CONVERSION = YES; 801 | CLANG_WARN_INFINITE_RECURSION = YES; 802 | CLANG_WARN_INT_CONVERSION = YES; 803 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 804 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 805 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 806 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 807 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 808 | CLANG_WARN_STRICT_PROTOTYPES = YES; 809 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 810 | CLANG_WARN_UNREACHABLE_CODE = YES; 811 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 812 | COPY_PHASE_STRIP = YES; 813 | ENABLE_NS_ASSERTIONS = NO; 814 | ENABLE_STRICT_OBJC_MSGSEND = YES; 815 | GCC_C_LANGUAGE_STANDARD = gnu99; 816 | GCC_NO_COMMON_BLOCKS = YES; 817 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 818 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 819 | GCC_WARN_UNDECLARED_SELECTOR = YES; 820 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 821 | GCC_WARN_UNUSED_FUNCTION = YES; 822 | GCC_WARN_UNUSED_VARIABLE = YES; 823 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 824 | MACOSX_DEPLOYMENT_TARGET = 10.10; 825 | METAL_ENABLE_DEBUG_INFO = NO; 826 | SDKROOT = iphoneos; 827 | VALIDATE_PRODUCT = YES; 828 | }; 829 | name = Release; 830 | }; 831 | 33220B1C1CFF952F00F3C3DA /* Debug */ = { 832 | isa = XCBuildConfiguration; 833 | buildSettings = { 834 | CLANG_ANALYZER_NONNULL = YES; 835 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 836 | CURRENT_PROJECT_VERSION = 1; 837 | DEBUG_INFORMATION_FORMAT = dwarf; 838 | DEFINES_MODULE = YES; 839 | DYLIB_COMPATIBILITY_VERSION = 1; 840 | DYLIB_CURRENT_VERSION = 1; 841 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 842 | FRAMEWORK_SEARCH_PATHS = ( 843 | "$(inherited)", 844 | "$(PROJECT_DIR)/Carthage/Build/iOS", 845 | ); 846 | GCC_NO_COMMON_BLOCKS = YES; 847 | INFOPLIST_FILE = "MPMessagePack iOS/Info.plist"; 848 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 849 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 850 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 851 | MTL_ENABLE_DEBUG_INFO = YES; 852 | PRODUCT_BUNDLE_IDENTIFIER = "me.rel.MPMessagePack-iOS"; 853 | PRODUCT_NAME = MPMessagePack; 854 | SKIP_INSTALL = YES; 855 | TARGETED_DEVICE_FAMILY = "1,2"; 856 | VERSIONING_SYSTEM = "apple-generic"; 857 | VERSION_INFO_PREFIX = ""; 858 | }; 859 | name = Debug; 860 | }; 861 | 33220B1D1CFF952F00F3C3DA /* Release */ = { 862 | isa = XCBuildConfiguration; 863 | buildSettings = { 864 | CLANG_ANALYZER_NONNULL = YES; 865 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 866 | COPY_PHASE_STRIP = NO; 867 | CURRENT_PROJECT_VERSION = 1; 868 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 869 | DEFINES_MODULE = YES; 870 | DYLIB_COMPATIBILITY_VERSION = 1; 871 | DYLIB_CURRENT_VERSION = 1; 872 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 873 | FRAMEWORK_SEARCH_PATHS = ( 874 | "$(inherited)", 875 | "$(PROJECT_DIR)/Carthage/Build/iOS", 876 | ); 877 | GCC_NO_COMMON_BLOCKS = YES; 878 | INFOPLIST_FILE = "MPMessagePack iOS/Info.plist"; 879 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 880 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 881 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 882 | MTL_ENABLE_DEBUG_INFO = NO; 883 | PRODUCT_BUNDLE_IDENTIFIER = "me.rel.MPMessagePack-iOS"; 884 | PRODUCT_NAME = MPMessagePack; 885 | SKIP_INSTALL = YES; 886 | TARGETED_DEVICE_FAMILY = "1,2"; 887 | VERSIONING_SYSTEM = "apple-generic"; 888 | VERSION_INFO_PREFIX = ""; 889 | }; 890 | name = Release; 891 | }; 892 | /* End XCBuildConfiguration section */ 893 | 894 | /* Begin XCConfigurationList section */ 895 | 0013921B1B0418E20082DEA8 /* Build configuration list for PBXNativeTarget "MPMessagePack" */ = { 896 | isa = XCConfigurationList; 897 | buildConfigurations = ( 898 | 0013921C1B0418E20082DEA8 /* Debug */, 899 | 0013921D1B0418E20082DEA8 /* Release */, 900 | ); 901 | defaultConfigurationIsVisible = 0; 902 | defaultConfigurationName = Release; 903 | }; 904 | 0031261B1E0B456800657DAF /* Build configuration list for PBXNativeTarget "MPMessagePack iOS Tests" */ = { 905 | isa = XCConfigurationList; 906 | buildConfigurations = ( 907 | 003126191E0B456800657DAF /* Debug */, 908 | 0031261A1E0B456800657DAF /* Release */, 909 | ); 910 | defaultConfigurationIsVisible = 0; 911 | defaultConfigurationName = Release; 912 | }; 913 | 005F67B61B15039100898B3C /* Build configuration list for PBXNativeTarget "MPMessagePackTests" */ = { 914 | isa = XCConfigurationList; 915 | buildConfigurations = ( 916 | 005F67B71B15039100898B3C /* Debug */, 917 | 005F67B81B15039100898B3C /* Release */, 918 | ); 919 | defaultConfigurationIsVisible = 0; 920 | defaultConfigurationName = Release; 921 | }; 922 | 00FB32C219661A860060AF33 /* Build configuration list for PBXProject "MPMessagePack" */ = { 923 | isa = XCConfigurationList; 924 | buildConfigurations = ( 925 | 00FB32D919661A870060AF33 /* Debug */, 926 | 00FB32DA19661A870060AF33 /* Release */, 927 | ); 928 | defaultConfigurationIsVisible = 0; 929 | defaultConfigurationName = Release; 930 | }; 931 | 33220B1E1CFF952F00F3C3DA /* Build configuration list for PBXNativeTarget "MPMessagePack iOS" */ = { 932 | isa = XCConfigurationList; 933 | buildConfigurations = ( 934 | 33220B1C1CFF952F00F3C3DA /* Debug */, 935 | 33220B1D1CFF952F00F3C3DA /* Release */, 936 | ); 937 | defaultConfigurationIsVisible = 0; 938 | defaultConfigurationName = Release; 939 | }; 940 | /* End XCConfigurationList section */ 941 | }; 942 | rootObject = 00FB32BF19661A860060AF33 /* Project object */; 943 | } 944 | -------------------------------------------------------------------------------- /MPMessagePack.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MPMessagePack.xcodeproj/xcshareddata/xcschemes/MPMessagePack iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /MPMessagePack.xcodeproj/xcshareddata/xcschemes/MPMessagePack.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 83 | 84 | 90 | 91 | 92 | 93 | 94 | 95 | 101 | 102 | 108 | 109 | 110 | 111 | 113 | 114 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /MPMessagePack/MPMessagePack.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePack.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for MPMessagePack. 12 | FOUNDATION_EXPORT double MPMessagePackVersionNumber; 13 | 14 | //! Project version string for MPMessagePack. 15 | FOUNDATION_EXPORT const unsigned char MPMessagePackVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | #import 20 | #import 21 | #import 22 | 23 | #import 24 | #import 25 | #import 26 | #import 27 | 28 | #import 29 | #import 30 | #import 31 | 32 | #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED 33 | #import 34 | #import 35 | #import 36 | #endif 37 | 38 | 39 | -------------------------------------------------------------------------------- /MPMessagePack/MPMessagePackReader.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackReader.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPMessagePackReader.h" 10 | 11 | #include "cmp.h" 12 | #import "MPDefines.h" 13 | 14 | #if SWIFT_PACKAGE 15 | @import GHODictionary; 16 | #else 17 | #import 18 | #endif 19 | 20 | @interface MPMessagePackReader () 21 | @property NSData *data; 22 | @property size_t index; 23 | @property MPMessagePackReaderOptions options; 24 | @end 25 | 26 | @implementation MPMessagePackReader 27 | 28 | - (instancetype)initWithData:(NSData *)data { 29 | if ((self = [super init])) { 30 | _data = data; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithData:(NSData *)data options:(MPMessagePackReaderOptions)options { 36 | if ((self = [self initWithData:data])) { 37 | _options = options; 38 | } 39 | return self; 40 | } 41 | 42 | - (id)readFromContext:(cmp_ctx_t *)context error:(NSError **)error { 43 | cmp_object_t obj; 44 | if (!cmp_read_object(context, &obj)) { 45 | return [self returnNilWithErrorCode:200 description:@"Unable to read object" error:error]; 46 | } 47 | 48 | switch (obj.type) { 49 | case CMP_TYPE_NIL: 50 | return [NSNull null]; 51 | case CMP_TYPE_BOOLEAN: 52 | return obj.as.boolean ? @YES : @NO; 53 | 54 | case CMP_TYPE_BIN8: 55 | case CMP_TYPE_BIN16: 56 | case CMP_TYPE_BIN32: { 57 | uint32_t length = obj.as.bin_size; 58 | if (length == 0) return [NSData data]; 59 | if (length > [_data length]) { // binary data can't be larger than the total data size 60 | return [self returnNilWithErrorCode:298 description:@"Invalid data length, data might be malformed" error:error]; 61 | } 62 | NSMutableData *data = [NSMutableData dataWithLength:length]; 63 | bool readSuccess = context->read(context, [data mutableBytes], length); 64 | if (!readSuccess) { 65 | return [self returnNilWithErrorCode:202 description:@"Unable to read bytes" error:error]; 66 | } 67 | return data; 68 | } 69 | 70 | case CMP_TYPE_POSITIVE_FIXNUM: return @(obj.as.u8); 71 | case CMP_TYPE_NEGATIVE_FIXNUM:return @(obj.as.s8); 72 | case CMP_TYPE_FLOAT: return @(obj.as.flt); 73 | case CMP_TYPE_DOUBLE: return @(obj.as.dbl); 74 | case CMP_TYPE_UINT8: return @(obj.as.u8); 75 | case CMP_TYPE_UINT16: return @(obj.as.u16); 76 | case CMP_TYPE_UINT32: return @(obj.as.u32); 77 | case CMP_TYPE_UINT64: return @(obj.as.u64); 78 | case CMP_TYPE_SINT8: return @(obj.as.s8); 79 | case CMP_TYPE_SINT16: return @(obj.as.s16); 80 | case CMP_TYPE_SINT32: return @(obj.as.s32); 81 | case CMP_TYPE_SINT64: return @(obj.as.s64); 82 | 83 | case CMP_TYPE_FIXSTR: 84 | case CMP_TYPE_STR8: 85 | case CMP_TYPE_STR16: 86 | case CMP_TYPE_STR32: { 87 | uint32_t length = obj.as.str_size; 88 | if (length == 0) return @""; 89 | if (length > [_data length]) { // str data can't be larger than the total data size 90 | return [self returnNilWithErrorCode:298 description:@"Invalid data length, data might be malformed" error:error]; 91 | } 92 | NSMutableData *data = [NSMutableData dataWithLength:length]; 93 | bool readSuccess = context->read(context, [data mutableBytes], length); 94 | if (!readSuccess) { 95 | return [self returnNilWithErrorCode:206 description:@"Unable to read string" error:error]; 96 | } 97 | NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 98 | if (!str) { 99 | // Invalid string encoding 100 | // Other languages have a raw byte string but not Objective-C 101 | MPErr(@"Invalid string encoding (type=%@), using str instead of bin? We'll have to return an NSData. (%@)", @(obj.type), data); 102 | return data; 103 | //return [NSNull null]; 104 | } 105 | return str; 106 | } 107 | 108 | case CMP_TYPE_FIXARRAY: 109 | case CMP_TYPE_ARRAY16: 110 | case CMP_TYPE_ARRAY32: { 111 | uint32_t length = obj.as.array_size; 112 | return [self readArrayFromContext:context length:length error:error]; 113 | } 114 | 115 | case CMP_TYPE_FIXMAP: 116 | case CMP_TYPE_MAP16: 117 | case CMP_TYPE_MAP32: { 118 | uint32_t length = obj.as.map_size; 119 | return [self readDictionaryFromContext:context length:length error:error]; 120 | } 121 | 122 | case CMP_TYPE_EXT8: 123 | case CMP_TYPE_EXT16: 124 | case CMP_TYPE_EXT32: 125 | case CMP_TYPE_FIXEXT1: 126 | case CMP_TYPE_FIXEXT2: 127 | case CMP_TYPE_FIXEXT4: 128 | case CMP_TYPE_FIXEXT8: 129 | case CMP_TYPE_FIXEXT16:{ 130 | // Type and size 131 | int8_t type = obj.as.ext.type; 132 | uint32_t length = obj.as.ext.size; 133 | 134 | // Read data 135 | if (length == 0) return [NSData data]; 136 | if (length > [_data length]) { // binary data can't be larger than the total data size 137 | return [self returnNilWithErrorCode:298 description:@"Invalid data length, data might be malformed" error:error]; 138 | } 139 | NSMutableData *data = [NSMutableData dataWithLength:length]; 140 | bool readSuccess = context->read(context, [data mutableBytes], length); 141 | if (!readSuccess) { 142 | return [self returnNilWithErrorCode:202 description:@"Unable to read bytes" error:error]; 143 | } 144 | 145 | // Return a dict with everything 146 | return @{ 147 | @"type":@(type), 148 | @"length":@(length), 149 | @"data":data 150 | }; 151 | } 152 | 153 | default: { 154 | return [self returnNilWithErrorCode:201 description:[NSString stringWithFormat:@"Unsupported object type: %@", @(obj.type)] error:error]; 155 | } 156 | } 157 | } 158 | 159 | - (NSMutableArray *)readArrayFromContext:(cmp_ctx_t *)context length:(uint32_t)length error:(NSError **)error { 160 | NSUInteger capacity = length < 1000 ? length : 1000; 161 | NSMutableArray *array = [NSMutableArray arrayWithCapacity:capacity]; 162 | for (NSInteger i = 0; i < length; i++) { 163 | id obj = [self readFromContext:context error:error]; 164 | if (!obj) return nil; 165 | [array addObject:obj]; 166 | } 167 | return array; 168 | } 169 | 170 | - (NSMutableDictionary *)readDictionaryFromContext:(cmp_ctx_t *)context length:(uint32_t)length error:(NSError **)error { 171 | NSUInteger capacity = length < 1000 ? length : 1000; 172 | 173 | id dict = nil; 174 | if ((_options & MPMessagePackReaderOptionsUseOrderedDictionary) == MPMessagePackReaderOptionsUseOrderedDictionary) { 175 | dict = [[GHODictionary alloc] initWithCapacity:capacity]; 176 | } else { 177 | dict = [NSMutableDictionary dictionaryWithCapacity:capacity]; 178 | } 179 | 180 | for (NSInteger i = 0; i < length; i++) { 181 | id key = [self readFromContext:context error:error]; 182 | if (!key) return nil; 183 | id value = [self readFromContext:context error:error]; 184 | if (!value) return nil; 185 | dict[key] = value; 186 | } 187 | return dict; 188 | } 189 | 190 | - (id)returnNilWithErrorCode:(NSInteger)errorCode description:(NSString *)description error:(NSError **)error { 191 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:errorCode userInfo:@{NSLocalizedDescriptionKey: description}]; 192 | return nil; 193 | } 194 | 195 | - (size_t)read:(void *)data limit:(size_t)limit { 196 | if (_index + limit > [_data length]) { 197 | return 0; 198 | } 199 | [_data getBytes:data range:NSMakeRange(_index, limit)]; 200 | 201 | // NSData *read = [NSData dataWithBytes:data length:limit]; 202 | // NSLog(@"Read bytes: %@", read); 203 | 204 | _index += limit; 205 | return limit; 206 | } 207 | 208 | static bool mp_reader(cmp_ctx_t *ctx, void *data, size_t limit) { 209 | MPMessagePackReader *mp = (__bridge MPMessagePackReader *)ctx->buf; 210 | return [mp read:data limit:limit]; 211 | } 212 | 213 | static size_t mp_writer(cmp_ctx_t *ctx, const void *data, size_t count) { 214 | return 0; 215 | } 216 | 217 | - (id)readObject:(NSError **)error { 218 | cmp_ctx_t ctx; 219 | cmp_init(&ctx, (__bridge void *)self, mp_reader, mp_writer); 220 | size_t index = _index; 221 | id obj = [self readFromContext:&ctx error:error]; 222 | if (error && *error) _index = index; 223 | return obj; 224 | } 225 | 226 | + (id)readData:(NSData *)data error:(NSError **)error { 227 | return [self readData:data options:0 error:error]; 228 | } 229 | 230 | + (id)readData:(NSData *)data options:(MPMessagePackReaderOptions)options error:(NSError **)error { 231 | MPMessagePackReader *messagePackReader = [[MPMessagePackReader alloc] initWithData:data options:options]; 232 | id obj = [messagePackReader readObject:error]; 233 | 234 | if (!obj && error && !*error) { 235 | *error = [NSError errorWithDomain:@"MPMessagePack" code:299 userInfo:@{NSLocalizedDescriptionKey: @"Unable to read object"}]; 236 | return nil; 237 | } 238 | 239 | return obj; 240 | } 241 | 242 | @end 243 | -------------------------------------------------------------------------------- /MPMessagePack/MPMessagePackWriter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackWriter.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPMessagePackWriter.h" 10 | 11 | #include "cmp.h" 12 | 13 | #if SWIFT_PACKAGE 14 | @import GHODictionary; 15 | #else 16 | #import 17 | #endif 18 | 19 | #import "MPDefines.h" 20 | 21 | @interface MPMessagePackWriter () 22 | @property NSMutableData *data; 23 | @end 24 | 25 | @implementation MPMessagePackWriter 26 | 27 | - (size_t)write:(const void *)data count:(size_t)count { 28 | [_data appendBytes:data length:count]; 29 | return count; 30 | } 31 | 32 | static bool mp_reader(cmp_ctx_t *ctx, void *data, size_t limit) { 33 | return 0; 34 | } 35 | 36 | static size_t mp_writer(cmp_ctx_t *ctx, const void *data, size_t count) { 37 | MPMessagePackWriter *mp = (__bridge MPMessagePackWriter *)ctx->buf; 38 | return [mp write:data count:count]; 39 | } 40 | 41 | - (NSMutableData *)writeObject:(id)obj options:(MPMessagePackWriterOptions)options error:(NSError **)error { 42 | _data = [NSMutableData data]; 43 | 44 | cmp_ctx_t ctx; 45 | cmp_init(&ctx, (__bridge void *)self, mp_reader, mp_writer); 46 | 47 | if (![self writeObject:obj options:options context:&ctx error:error]) { 48 | return nil; 49 | } 50 | 51 | return _data; 52 | } 53 | 54 | + (NSMutableData *)writeObject:(id)obj error:(NSError **)error { 55 | return [self writeObject:obj options:0 error:error]; 56 | } 57 | 58 | + (NSMutableData *)writeObject:(id)obj options:(MPMessagePackWriterOptions)options error:(NSError **)error { 59 | MPMessagePackWriter *messagePack = [[MPMessagePackWriter alloc] init]; 60 | 61 | if (![messagePack writeObject:obj options:options error:error]) { 62 | return nil; 63 | } 64 | 65 | return messagePack.data; 66 | } 67 | 68 | - (BOOL)writeNumber:(NSNumber *)number context:(cmp_ctx_t *)context error:(NSError **)error { 69 | if ((id)number == (id)kCFBooleanTrue || (id)number == (id)kCFBooleanFalse) { 70 | cmp_write_bool(context, number.boolValue); 71 | return YES; 72 | } 73 | 74 | CFNumberType numberType = CFNumberGetType((CFNumberRef)number); 75 | switch (numberType) { 76 | case kCFNumberFloat32Type: 77 | case kCFNumberFloatType: 78 | case kCFNumberCGFloatType: 79 | cmp_write_float(context, number.floatValue); 80 | return YES; 81 | case kCFNumberFloat64Type: 82 | case kCFNumberDoubleType: 83 | cmp_write_double(context, number.doubleValue); 84 | return YES; 85 | default: 86 | break; 87 | } 88 | 89 | if ([number compare:@(0)] >= 0) { 90 | cmp_write_uint(context, number.unsignedLongLongValue); 91 | return YES; 92 | } else { 93 | cmp_write_sint(context, number.longLongValue); 94 | return YES; 95 | } 96 | } 97 | 98 | - (BOOL)writeObject:(id)obj options:(MPMessagePackWriterOptions)options context:(cmp_ctx_t *)context error:(NSError **)error { 99 | if ([obj isKindOfClass:[NSArray class]]) { 100 | if (!cmp_write_array(context, (uint32_t)[obj count])) { 101 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:102 userInfo:@{NSLocalizedDescriptionKey: @"Error writing array"}]; 102 | return NO; 103 | } 104 | for (id element in obj) { 105 | if (![self writeObject:element options:options context:context error:error]) { 106 | return NO; 107 | } 108 | } 109 | } else if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[GHODictionary class]]) { 110 | if (!cmp_write_map(context, (uint32_t)[obj count])) { 111 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:102 userInfo:@{NSLocalizedDescriptionKey: @"Error writing map"}]; 112 | return NO; 113 | } 114 | 115 | NSEnumerator *keyEnumerator; 116 | if ((options & MPMessagePackWriterOptionsSortDictionaryKeys) == MPMessagePackWriterOptionsSortDictionaryKeys) { 117 | keyEnumerator = [[[obj allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectEnumerator]; 118 | } else { 119 | keyEnumerator = [obj keyEnumerator]; 120 | } 121 | 122 | for (id key in keyEnumerator) { 123 | if (![self writeObject:key options:options context:context error:error]) { 124 | return NO; 125 | } 126 | if (![self writeObject:obj[key] options:options context:context error:error]) { 127 | return NO; 128 | } 129 | } 130 | } else if ([obj isKindOfClass:[NSString class]]) { 131 | NSString *s = (NSString *)obj; 132 | const char *str = [s UTF8String]; 133 | size_t len = strlen(str); 134 | if (!cmp_write_str(context, str, (uint32_t)len)) { 135 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:102 userInfo:@{NSLocalizedDescriptionKey: @"Error writing string"}]; 136 | return NO; 137 | } 138 | } else if ([obj isKindOfClass:[NSNumber class]]) { 139 | [self writeNumber:obj context:context error:error]; 140 | } else if ([obj isKindOfClass:[NSNull class]]) { 141 | if (!cmp_write_nil(context)) { 142 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:102 userInfo:@{NSLocalizedDescriptionKey: @"Error writing nil"}]; 143 | return NO; 144 | } 145 | } else if ([obj isKindOfClass:[NSData class]]) { 146 | if (!cmp_write_bin(context, [obj bytes], (uint32_t)[obj length])) { 147 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:102 userInfo:@{NSLocalizedDescriptionKey: @"Error writing binary"}]; 148 | return NO; 149 | } 150 | } else { 151 | NSString *errorDescription = [NSString stringWithFormat:@"Unable to write object: %@", obj]; 152 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:102 userInfo:@{NSLocalizedDescriptionKey: errorDescription}]; 153 | return NO; 154 | } 155 | return YES; 156 | } 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /MPMessagePack/NSArray+MPMessagePack.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+MPMessagePack.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "NSArray+MPMessagePack.h" 10 | 11 | @implementation NSArray (MPMessagePack) 12 | 13 | - (NSData *)mp_messagePack { 14 | return [self mp_messagePack:0]; 15 | } 16 | 17 | - (NSData *)mp_messagePack:(MPMessagePackWriterOptions)options { 18 | return [MPMessagePackWriter writeObject:self options:options error:nil]; 19 | } 20 | 21 | - (NSData *)mp_messagePack:(MPMessagePackWriterOptions)options error:(NSError **)error { 22 | return [MPMessagePackWriter writeObject:self options:options error:error]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /MPMessagePack/NSData+MPMessagePack.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+MPMessagePack.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 1/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "NSData+MPMessagePack.h" 10 | 11 | #if SWIFT_PACKAGE 12 | @import GHODictionary; 13 | #else 14 | #import 15 | #endif 16 | 17 | @implementation NSData (MPMessagePack) 18 | 19 | - (NSString *)mp_hexString { 20 | if ([self length] == 0) return nil; 21 | NSMutableString *hexString = [NSMutableString stringWithCapacity:[self length] * 2]; 22 | for (NSUInteger i = 0; i < [self length]; ++i) { 23 | [hexString appendFormat:@"%02X", *((uint8_t *)[self bytes] + i)]; 24 | } 25 | return [hexString lowercaseString]; 26 | } 27 | 28 | + (NSData *)mp_dataFromHexString:(NSString *)str { 29 | const char *chars = [str UTF8String]; 30 | NSMutableData *data = [NSMutableData dataWithCapacity:str.length / 2]; 31 | char byteChars[3] = {0, 0, 0}; 32 | unsigned long wholeByte; 33 | for (int i = 0; i < str.length; i += 2) { 34 | byteChars[0] = chars[i]; 35 | byteChars[1] = chars[i + 1]; 36 | wholeByte = strtoul(byteChars, NULL, 16); 37 | [data appendBytes:&wholeByte length:1]; 38 | } 39 | return data; 40 | } 41 | 42 | - (NSDictionary *)mp_dict:(NSError **)error { 43 | return [self mp_dict:0 error:error]; 44 | } 45 | 46 | - (id)mp_dict:(MPMessagePackReaderOptions)options error:(NSError **)error { 47 | id obj = [MPMessagePackReader readData:self options:options error:error]; 48 | if (!obj) return nil; 49 | if (![obj isKindOfClass:NSDictionary.class] && ![obj isKindOfClass:GHODictionary.class]) { 50 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Object was not of type NSDictionary or GHODictionary", @"MPObject": obj}]; 51 | return nil; 52 | } 53 | return obj; 54 | } 55 | 56 | - (NSArray *)mp_array:(NSError **)error { 57 | return [self mp_array:0 error:error]; 58 | } 59 | 60 | - (NSArray *)mp_array:(MPMessagePackReaderOptions)options error:(NSError **)error { 61 | id obj = [MPMessagePackReader readData:self error:error]; 62 | if (!obj) return nil; 63 | if (![obj isKindOfClass:NSArray.class]) { 64 | if (error) *error = [NSError errorWithDomain:@"MPMessagePack" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Object was not of type NSArray", @"MPObject": obj}]; 65 | return nil; 66 | } 67 | return obj; 68 | } 69 | 70 | - (id)mp_object:(NSError **)error { 71 | return [MPMessagePackReader readData:self error:error]; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /MPMessagePack/NSDictionary+MPMessagePack.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MPMessagePack.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+MPMessagePack.h" 10 | 11 | @implementation NSDictionary (MPMessagePack) 12 | 13 | - (NSData *)mp_messagePack { 14 | return [self mp_messagePack:0]; 15 | } 16 | 17 | - (NSData *)mp_messagePack:(MPMessagePackWriterOptions)options { 18 | return [MPMessagePackWriter writeObject:self options:options error:nil]; 19 | } 20 | 21 | - (NSData *)mp_messagePack:(MPMessagePackWriterOptions)options error:(NSError **)error { 22 | return [MPMessagePackWriter writeObject:self options:options error:error]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /MPMessagePack/RPC/MPDispatchRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPDispatchRequest.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 10/14/15. 6 | // Copyright © 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPDispatchRequest.h" 10 | 11 | @interface MPDispatchRequest () 12 | @property dispatch_semaphore_t semaphore; 13 | @end 14 | 15 | @implementation MPDispatchRequest 16 | 17 | + (instancetype)dispatchRequest { 18 | MPDispatchRequest *request = [[MPDispatchRequest alloc] init]; 19 | request.semaphore = dispatch_semaphore_create(0); 20 | return request; 21 | } 22 | 23 | - (void)completeWithResult:(id)result error:(NSError *)error { 24 | _result = result; 25 | if (!_error) _error = error; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /MPMessagePack/RPC/MPMessagePackClient.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackRPClient.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 12/12/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPMessagePackClient.h" 10 | 11 | #import "MPRequestor.h" 12 | #import "MPDispatchRequest.h" 13 | #include 14 | #include 15 | 16 | @interface MPMessagePackClient () 17 | @property MPRPCProtocol *protocol; 18 | @property NSString *name; 19 | @property MPMessagePackOptions options; 20 | 21 | @property (nonatomic) MPMessagePackClientStatus status; 22 | @property NSInputStream *inputStream; 23 | @property NSOutputStream *outputStream; 24 | 25 | @property NSMutableArray *bufferQueue; 26 | 27 | @property NSMutableDictionary *requests; 28 | 29 | @property NSMutableData *readBuffer; 30 | @property NSInteger writeIndex; 31 | 32 | @property (copy) MPCompletion openCompletion; 33 | 34 | @property CFSocketRef socket; 35 | @property CFSocketNativeHandle nativeSocket; // For native local socket 36 | @end 37 | 38 | 39 | typedef void (^MPDispatchSignal)(NSInteger messageId); 40 | 41 | @implementation MPMessagePackClient 42 | 43 | - (instancetype)init { 44 | return [self initWithName:@"" options:0]; 45 | } 46 | 47 | - (instancetype)initWithName:(NSString *)name options:(MPMessagePackOptions)options { 48 | if ((self = [super init])) { 49 | _name = name; 50 | _options = options; 51 | _bufferQueue = [NSMutableArray array]; 52 | _readBuffer = [NSMutableData data]; 53 | _requests = [NSMutableDictionary dictionary]; 54 | _protocol = [[MPRPCProtocol alloc] init]; 55 | } 56 | return self; 57 | } 58 | 59 | - (void)dealloc { 60 | _inputStream.delegate = nil; 61 | _outputStream.delegate = nil; 62 | } 63 | 64 | - (void)setInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream { 65 | _inputStream = inputStream; 66 | _outputStream = outputStream; 67 | _inputStream.delegate = self; 68 | _outputStream.delegate = self; 69 | [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 70 | [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 71 | //MPDebug(@"[%@] Opening streams", _name); 72 | self.status = MPMessagePackClientStatusOpening; 73 | [_inputStream open]; 74 | [_outputStream open]; 75 | } 76 | 77 | - (void)openWithHost:(NSString *)host port:(UInt32)port completion:(MPCompletion)completion { 78 | if (_status == MPMessagePackClientStatusOpen || _status == MPMessagePackClientStatusOpening) { 79 | MPErr(@"[%@] Already open", _name); 80 | completion(nil); // TODO: Maybe something better to do here 81 | return; 82 | } 83 | CFReadStreamRef readStream; 84 | CFWriteStreamRef writeStream; 85 | CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream); 86 | _openCompletion = completion; 87 | [self setInputStream:(__bridge NSInputStream *)(readStream) outputStream:(__bridge NSOutputStream *)(writeStream)]; 88 | } 89 | 90 | - (void)close { 91 | if (_openCompletion) { 92 | MPErr(@"We had an open completion block set"); 93 | _openCompletion = nil; 94 | } 95 | 96 | _inputStream.delegate = nil; 97 | [_inputStream close]; 98 | [_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 99 | _inputStream = nil; 100 | _outputStream.delegate = nil; 101 | [_outputStream close]; 102 | [_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 103 | _outputStream = nil; 104 | 105 | if (_socket) { 106 | CFSocketInvalidate(_socket); 107 | _socket = NULL; 108 | } 109 | 110 | if (_nativeSocket) { 111 | close(_nativeSocket); 112 | _nativeSocket = 0; 113 | } 114 | 115 | self.status = MPMessagePackClientStatusClosed; 116 | } 117 | 118 | - (void)sendRequestWithMethod:(NSString *)method params:(NSArray *)params messageId:(NSInteger)messageId completion:(MPRequestCompletion)completion { 119 | params = [self encodeObject:params]; 120 | NSError *error = nil; 121 | NSData *data = [_protocol encodeRequestWithMethod:method params:params messageId:messageId options:0 framed:(_options & MPMessagePackOptionsFramed) error:&error]; 122 | if (!data) { 123 | completion(error, nil); 124 | return; 125 | } 126 | 127 | _requests[@(messageId)] = [MPRequestor requestWithCompletion:completion]; 128 | //MPDebug(@"Send: %@", [request componentsJoinedByString:@", "]); 129 | [self writeData:data]; 130 | } 131 | 132 | - (id)encodeObject:(id)object { 133 | if (!object) return nil; 134 | if (_coder) { 135 | if ([object isKindOfClass:NSArray.class]) { 136 | NSMutableArray *encoded = [NSMutableArray array]; 137 | for (id obj in (NSArray *)object) { 138 | [encoded addObject:[self encodeObject:obj]]; 139 | } 140 | object = encoded; 141 | } else if ([object isKindOfClass:NSDictionary.class]) { 142 | NSMutableDictionary *encoded = [NSMutableDictionary dictionary]; 143 | for (id key in (NSDictionary *)object) { 144 | id value = ((NSDictionary *)object)[key]; 145 | encoded[key] = [self encodeObject:value]; 146 | } 147 | object = encoded; 148 | } else { 149 | object = [_coder encodeObject:object]; 150 | } 151 | } 152 | return object; 153 | } 154 | 155 | - (void)sendResponseWithResult:(id)result error:(id)error messageId:(NSInteger)messageId { 156 | if ([error isKindOfClass:NSError.class]) { 157 | NSError *responseError = error; 158 | 159 | NSMutableArray *messages = [NSMutableArray array]; 160 | if (responseError.localizedDescription) [messages addObject:responseError.localizedDescription]; 161 | if (responseError.localizedFailureReason) [messages addObject:responseError.localizedFailureReason]; 162 | if (responseError.localizedRecoverySuggestion) [messages addObject:responseError.localizedRecoverySuggestion]; 163 | 164 | error = @{@"code": @(responseError.code), @"desc": [messages componentsJoinedByString:@". "]}; 165 | } 166 | 167 | result = [self encodeObject:result]; 168 | 169 | NSError *encodeError = nil; 170 | NSData *data = [_protocol encodeResponseWithResult:result error:error messageId:messageId options:0 framed:(_options & MPMessagePackOptionsFramed) encodeError:&encodeError]; 171 | NSAssert(data, @"Error building response: %@", encodeError); 172 | [self writeData:data]; 173 | } 174 | 175 | - (void)writeData:(NSData *)data { 176 | NSAssert(data.length > 0, @"Data was empty"); 177 | [_bufferQueue addObject:data]; 178 | [self checkQueue]; 179 | } 180 | 181 | - (void)checkQueue { 182 | while (YES) { 183 | if (![_outputStream hasSpaceAvailable]) break; 184 | 185 | NSMutableData *data = [_bufferQueue firstObject]; 186 | if (!data) break; 187 | 188 | NSUInteger length = data.length - _writeIndex; 189 | if (length == 0) break; 190 | 191 | uint8_t buffer[length]; 192 | //MPDebug(@"Write(%@): %@", @(length), [data base64EncodedStringWithOptions:0]); // [data mp_hexString]); 193 | [data getBytes:buffer range:NSMakeRange(_writeIndex, length)]; 194 | NSInteger bytesWritten = [_outputStream write:(const uint8_t *)buffer maxLength:length]; 195 | //MPDebug(@"[%@] Wrote %d", _name, (int)bytesWritten); 196 | if (bytesWritten == 0) { 197 | __weak MPMessagePackClient *gself = self; 198 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 199 | [gself checkQueue]; 200 | }); 201 | } else if (bytesWritten != length) { 202 | _writeIndex += bytesWritten; 203 | } else { 204 | if ([_bufferQueue count] > 0) [_bufferQueue removeObjectAtIndex:0]; 205 | _writeIndex = 0; 206 | } 207 | } 208 | } 209 | 210 | - (void)readInputStream { 211 | if (![_inputStream hasBytesAvailable]) return; 212 | 213 | // TODO: Buffer size 214 | uint8_t buffer[4096]; 215 | NSInteger length = [_inputStream read:buffer maxLength:4096]; 216 | if (length > 0) { 217 | //MPDebug(@"[%@] Bytes: (%@)", _name, @(length)); 218 | [_readBuffer appendBytes:buffer length:length]; 219 | [self checkReadBuffer]; 220 | } 221 | } 222 | 223 | - (void)checkReadBuffer { 224 | //MPDebug(@"[%@] Checking read buffer: %d", _name, (int)_readBuffer.length); 225 | if (_readBuffer.length == 0) return; 226 | 227 | MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:_readBuffer]; // TODO: Fix init every check 228 | 229 | if (_options & MPMessagePackOptionsFramed) { 230 | NSError *error = nil; 231 | NSNumber *frameSize = [reader readObject:&error]; 232 | //MPDebug(@"[%@] Read frame size: %@", _name, frameSize); 233 | if (error) { 234 | [self handleError:error fatal:YES]; 235 | return; 236 | } 237 | if (!frameSize) return; 238 | if (![frameSize isKindOfClass:NSNumber.class]) { 239 | [self handleError:MPMakeError(MPRPCErrorResponseInvalid, @"[%@] Expected number for frame size. You need to have framing on for both sides?", _name) fatal:YES]; 240 | return; 241 | } 242 | if (_readBuffer.length < (frameSize.unsignedIntegerValue + reader.index)) { 243 | //MPDebug(@"Not enough data for response in frame: %d < %d", (int)_readBuffer.length, (int)(frameSize.unsignedIntegerValue + reader.index)); 244 | return; 245 | } 246 | 247 | // To debug the message 248 | //NSData *data = [_readBuffer subdataWithRange:NSMakeRange(reader.index, frameSize.unsignedIntegerValue)]; 249 | //MPDebug(@"Data: %@", [data base64EncodedStringWithOptions:0]); 250 | } 251 | 252 | [self _readMessage:reader completion:^(NSError *error, NSArray *message) { 253 | if (error) { 254 | [self handleError:error fatal:YES]; 255 | return; 256 | } 257 | 258 | if (message) { 259 | [self _handleMessage:message]; 260 | } 261 | 262 | self.readBuffer = [[self.readBuffer subdataWithRange:NSMakeRange(reader.index, self.readBuffer.length - reader.index)] mutableCopy]; // TODO: Fix mutable copy (this might actually no-op tho) 263 | [self checkReadBuffer]; 264 | }]; 265 | } 266 | 267 | - (void)_readMessage:(MPMessagePackReader *)reader completion:(void (^)(NSError *error, NSArray *message))completion { 268 | NSError *error = nil; 269 | id obj = [reader readObject:&error]; 270 | if (!obj || error) { 271 | completion(error, nil); 272 | return; 273 | } 274 | 275 | if (!MPVerifyMessage(obj, &error)) { 276 | completion(error, nil); 277 | return; 278 | } 279 | 280 | NSArray *message = (NSArray *)obj; 281 | completion(nil, message); 282 | } 283 | 284 | - (void)_handleMessage:(NSArray *)message { 285 | NSInteger type = [message[0] integerValue]; 286 | NSNumber *messageId = message[1]; 287 | NSError *error = nil; 288 | 289 | if (type == 0) { 290 | if (!MPVerifyRequest(message, &error)) { 291 | [self handleError:error fatal:YES]; 292 | return; 293 | } 294 | //MPDebug(@"Request, messageId=%@", messageId); 295 | NSString *method = MPIfNull(message[2], nil); 296 | NSArray *params = MPIfNull(message[3], nil); 297 | NSAssert(self.requestHandler, @"No request handler"); 298 | self.requestHandler(messageId, method, params, ^(NSError *error, id result) { 299 | //MPDebug(@"Sending response, messageId=%@", messageId); 300 | [self sendResponseWithResult:result error:error messageId:messageId.integerValue]; 301 | }); 302 | } else if (type == 1) { 303 | if (!MPVerifyResponse(message, &error)) { 304 | [self handleError:error fatal:YES]; 305 | return; 306 | } 307 | 308 | NSDictionary *responseError = MPIfNull(message[2], nil); 309 | NSError *error = nil; 310 | if (responseError) { 311 | error = MPErrorFromErrorDict(@"MPMessagePack", responseError); 312 | } 313 | 314 | id result = MPIfNull(message[3], nil); 315 | MPRequestor *request = _requests[messageId]; 316 | [_requests removeObjectForKey:messageId]; 317 | if (!request.completion) { 318 | MPErr(@"No completion block for request: %@", messageId); 319 | [self handleError:MPMakeError(MPRPCErrorResponseInvalid, @"[%@] Got response for unknown request", _name) fatal:NO]; 320 | } else { 321 | [request completeWithResult:result error:error]; 322 | } 323 | } else if (type == 2) { 324 | NSString *method = MPIfNull(message[1], nil); 325 | NSArray *params = MPIfNull(message[2], nil); 326 | [self.delegate client:self didReceiveNotificationWithMethod:method params:params]; 327 | } 328 | } 329 | 330 | - (void)setStatus:(MPMessagePackClientStatus)status { 331 | if (_status != status) { 332 | _status = status; 333 | [self.delegate client:self didChangeStatus:_status]; 334 | } 335 | } 336 | 337 | - (void)handleError:(NSError *)error fatal:(BOOL)fatal { 338 | MPErr(@"[%@] Error: %@", _name, error); 339 | [self.delegate client:self didError:error fatal:fatal]; 340 | if (fatal) { 341 | [self close]; 342 | } 343 | } 344 | 345 | #pragma mark Dispatch 346 | 347 | - (id)sendRequestWithMethod:(NSString *)method params:(NSArray *)params messageId:(NSInteger)messageId timeout:(NSTimeInterval)timeout error:(NSError **)error { 348 | MPDispatchRequest *dispatchRequest = [MPDispatchRequest dispatchRequest]; 349 | 350 | MPDebug(@"Send request: %@", @(messageId)); 351 | [self sendRequestWithMethod:method params:params messageId:messageId completion:^(NSError *requestError, id result) { 352 | MPDebug(@"Done: %@", @(messageId)); 353 | dispatchRequest.result = result; 354 | dispatchRequest.error = requestError; 355 | [self _signalDispatch:messageId dispatchRequest:dispatchRequest]; 356 | }]; 357 | 358 | [self _waitDispatch:messageId dispatchRequest:dispatchRequest timeout:timeout]; 359 | if (dispatchRequest.error) { 360 | *error = dispatchRequest.error; 361 | return nil; 362 | } 363 | 364 | if (!dispatchRequest.result) return [NSNull null]; 365 | return dispatchRequest.result; 366 | } 367 | 368 | - (BOOL)_signalDispatch:(NSInteger)messageId dispatchRequest:(MPDispatchRequest *)dispatchRequest { 369 | if (!dispatchRequest) { 370 | MPErr(@"No request to signal (%@)", @(messageId)); 371 | return NO; 372 | } 373 | 374 | MPDebug(@"Signal: %@", dispatchRequest); 375 | long signalStatus = dispatch_semaphore_signal(dispatchRequest.semaphore); 376 | MPDebug(@"Signal status: %@", @(signalStatus)); 377 | return (signalStatus != 0); 378 | } 379 | 380 | - (void)_waitDispatch:(NSInteger)messageId dispatchRequest:(MPDispatchRequest *)dispatchRequest timeout:(NSTimeInterval)timeout { 381 | if (!dispatchRequest.semaphore) { 382 | dispatchRequest.error = MPMakeError(MPRPCErrorResponseInvalid, @"Nothing to wait on. Response already timed out, canceled or responded?"); 383 | return; 384 | } 385 | 386 | MPDebug(@"Wait: %@", @(messageId)); 387 | 388 | dispatch_time_t time = timeout > 0 ? dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC) : DISPATCH_TIME_FOREVER; 389 | long status = dispatch_semaphore_wait(dispatchRequest.semaphore, time); 390 | 391 | if (status != 0 && !dispatchRequest.error) dispatchRequest.error = MPMakeError(MPRPCErrorRequestTimeout, @"Request timeout"); 392 | } 393 | 394 | - (BOOL)cancelRequestWithMessageId:(NSInteger)messageId { 395 | MPDebug(@"Cancel: %@", @(messageId)); 396 | MPRequestor *request = _requests[@(messageId)]; 397 | if (!request.completion) return NO; 398 | 399 | [request completeWithResult:nil error:MPMakeError(MPRPCErrorRequestCanceled, @"Cancelled")]; 400 | return YES; 401 | } 402 | 403 | #pragma mark Stream Events 404 | 405 | NSString *MPNSStringFromNSStreamEvent(NSStreamEvent e) { 406 | NSMutableString *str = [[NSMutableString alloc] init]; 407 | if (e & NSStreamEventOpenCompleted) [str appendString:@"NSStreamEventOpenCompleted"]; 408 | if (e & NSStreamEventHasBytesAvailable) [str appendString:@"NSStreamEventHasBytesAvailable"]; 409 | if (e & NSStreamEventHasSpaceAvailable) [str appendString:@"NSStreamEventHasSpaceAvailable"]; 410 | if (e & NSStreamEventErrorOccurred) [str appendString:@"NSStreamEventErrorOccurred"]; 411 | if (e & NSStreamEventEndEncountered) [str appendString:@"NSStreamEventEndEncountered"]; 412 | return str; 413 | } 414 | 415 | - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event { 416 | //MPDebug(@"[%@] Stream event: %@ (%@)", _name, MPNSStringFromNSStreamEvent(event), NSStringFromClass(stream.class)); 417 | switch (event) { 418 | case NSStreamEventNone: 419 | break; 420 | 421 | case NSStreamEventOpenCompleted: { 422 | if ([stream isKindOfClass:NSOutputStream.class]) { 423 | if (_status != MPMessagePackClientStatusOpening) { 424 | MPErr(@"[%@] Status wasn't opening and we got an open completed event", _name); 425 | } 426 | self.status = MPMessagePackClientStatusOpen; 427 | if (self.openCompletion) { 428 | self.openCompletion(nil); 429 | self.openCompletion = nil; 430 | } 431 | } 432 | break; 433 | } 434 | case NSStreamEventHasSpaceAvailable: { 435 | [self checkQueue]; 436 | break; 437 | } 438 | case NSStreamEventHasBytesAvailable: { 439 | if (stream == _inputStream) { 440 | [self readInputStream]; 441 | } 442 | break; 443 | } 444 | case NSStreamEventErrorOccurred: { 445 | MPErr(@"[%@] Stream error", _name); 446 | if (self.openCompletion) { 447 | self.openCompletion(stream.streamError); 448 | self.openCompletion = nil; 449 | } else { 450 | [self handleError:stream.streamError fatal:YES]; 451 | } 452 | break; 453 | } 454 | case NSStreamEventEndEncountered: { 455 | // NSData *data = [_inputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; 456 | // if (!data) { 457 | // MPErr(@"[%@] No data from end event", _name); 458 | // } else { 459 | // [_readBuffer appendData:data]; 460 | // [self checkReadBuffer]; 461 | // } 462 | //MPDebug(@"[%@] Stream end", _name); 463 | [self close]; 464 | break; 465 | } 466 | } 467 | } 468 | 469 | #pragma mark Unix Socket 470 | 471 | - (BOOL)openWithSocket:(NSString *)socketName completion:(MPCompletion)completion { 472 | CFSocketContext context = {0, (__bridge void *)self, nil, nil, nil}; 473 | CFSocketCallBackType types = kCFSocketConnectCallBack; 474 | CFSocketNativeHandle sock = socket(AF_UNIX, SOCK_STREAM, 0); 475 | _socket = CFSocketCreateWithNative(nil, sock, types, MPSocketClientCallback, &context); 476 | if (!_socket) { 477 | completion(MPMakeError(MPRPCErrorSocketCreateError, @"Couldn't create native socket to: %@", socketName)); 478 | return NO; 479 | } 480 | 481 | if (![NSFileManager.defaultManager isReadableFileAtPath:socketName]) { 482 | completion(MPMakeError(MPRPCErrorSocketOpenError, @"Path doesn't exist or is unreadable: %@", socketName)); 483 | return NO; 484 | } 485 | 486 | struct sockaddr_un sun; 487 | sun.sun_len = sizeof(struct sockaddr_un); 488 | sun.sun_family = AF_UNIX; 489 | strcpy(&sun.sun_path[0], [socketName UTF8String]); 490 | NSData *address = [NSData dataWithBytes:&sun length:sizeof(sun)]; 491 | 492 | CFSocketError err = CFSocketConnectToAddress(_socket, (__bridge CFDataRef)address, (CFTimeInterval)2); 493 | if (err != kCFSocketSuccess) { 494 | MPRPCError mpError; 495 | switch (err) { 496 | case kCFSocketError: mpError = MPRPCErrorSocketOpenError; break; 497 | case kCFSocketTimeout: mpError = MPRPCErrorSocketOpenTimeout; break; 498 | case kCFSocketSuccess: mpError = 0; break; // This will never happen 499 | } 500 | completion(MPMakeError(mpError, @"Couldn't open socket: %@", socketName)); 501 | return NO; 502 | } 503 | 504 | _openCompletion = completion; 505 | CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0); 506 | CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes); 507 | CFRelease(sourceRef); 508 | 509 | return YES; 510 | } 511 | 512 | static void MPSocketClientCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { 513 | MPMessagePackClient *client = (__bridge MPMessagePackClient *)info; 514 | //MPDebug(@"Callback: %d", (int)type); 515 | switch (type) { 516 | case kCFSocketConnectCallBack: 517 | //if (data) { 518 | [client connectSocketStreams]; 519 | break; 520 | default: 521 | break; 522 | } 523 | } 524 | 525 | - (void)connectSocketStreams { 526 | //MPDebug(@"Connecting streams"); 527 | _nativeSocket = CFSocketGetNative(_socket); 528 | 529 | // 530 | // From CocoaAsyncSocket 531 | // 532 | 533 | // Setup the CFSocket so that invalidating it will not close the underlying native socket 534 | CFSocketSetSocketFlags(_socket, 0); 535 | 536 | // Invalidate and release the CFSocket - All we need from here on out is the nativeSocket. 537 | // Note: If we don't invalidate the CFSocket (leaving the native socket open) 538 | // then readStream and writeStream won't function properly. 539 | // Specifically, their callbacks won't work, with the exception of kCFStreamEventOpenCompleted. 540 | // 541 | // This is likely due to the mixture of the CFSocketCreateWithNative method, 542 | // along with the CFStreamCreatePairWithSocket method. 543 | // The documentation for CFSocketCreateWithNative states: 544 | // 545 | // If a CFSocket object already exists for sock, 546 | // the function returns the pre-existing object instead of creating a new object; 547 | // the context, callout, and callBackTypes parameters are ignored in this case. 548 | // 549 | // So the CFStreamCreateWithNative method invokes the CFSocketCreateWithNative method, 550 | // thinking that is creating a new underlying CFSocket for it's own purposes. 551 | // When it does this, it uses the context/callout/callbackTypes parameters to setup everything appropriately. 552 | // However, if a CFSocket already exists for the native socket, 553 | // then it is returned (as per the documentation), which in turn screws up the CFStreams. 554 | 555 | CFSocketInvalidate(_socket); 556 | CFRelease(_socket); 557 | _socket = NULL; 558 | 559 | CFReadStreamRef readStream = NULL; 560 | CFWriteStreamRef writeStream = NULL; 561 | CFStreamCreatePairWithSocket(kCFAllocatorDefault, _nativeSocket, &readStream, &writeStream); 562 | if (readStream && writeStream) { 563 | CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 564 | CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 565 | [self setInputStream:(__bridge NSInputStream *)readStream outputStream:(__bridge NSOutputStream *)writeStream]; 566 | } else { 567 | close(_nativeSocket); 568 | } 569 | if (readStream) { 570 | CFRelease(readStream); 571 | readStream = nil; 572 | } 573 | if (writeStream) { 574 | CFRelease(writeStream); 575 | writeStream = nil; 576 | } 577 | } 578 | 579 | @end 580 | 581 | -------------------------------------------------------------------------------- /MPMessagePack/RPC/MPMessagePackServer.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackServer.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 12/13/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPMessagePackServer.h" 10 | 11 | #import "MPMessagePackClient.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | NSString *const MPMessagePackServerErrorDomain = @"MPMessagePackServerErrorDomain"; 19 | 20 | @interface MPMessagePackServer () 21 | @property MPMessagePackOptions options; 22 | @property CFSocketRef socket; 23 | @property MPMessagePackClient *client; 24 | @end 25 | 26 | @implementation MPMessagePackServer 27 | 28 | - (instancetype)initWithOptions:(MPMessagePackOptions)options { 29 | if ((self = [super init])) { 30 | _options = options; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)connectionWithInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream { 36 | NSAssert(!_client, @"This server only handles a single client"); // TODO 37 | 38 | MPDebug(@"[Server] Client connected"); 39 | 40 | _client = [[MPMessagePackClient alloc] initWithName:@"Server" options:_options]; 41 | _client.requestHandler = _requestHandler; 42 | _client.delegate = self; 43 | [_client setInputStream:inputStream outputStream:outputStream]; 44 | } 45 | 46 | - (void)setRequestHandler:(MPRequestHandler)requestHandler { 47 | _requestHandler = requestHandler; 48 | _client.requestHandler = requestHandler; 49 | } 50 | 51 | static void MPMessagePackServerAcceptCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { 52 | MPMessagePackServer *server = (__bridge MPMessagePackServer *)info; 53 | //MPDebug(@"Accept callback type: %d", (int)type); 54 | if (kCFSocketAcceptCallBack == type) { 55 | CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle *)data; 56 | CFReadStreamRef readStream = NULL; 57 | CFWriteStreamRef writeStream = NULL; 58 | CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, &writeStream); 59 | if (readStream && writeStream) { 60 | CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 61 | CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 62 | [server connectionWithInputStream:(__bridge NSInputStream *)readStream outputStream:(__bridge NSOutputStream *)writeStream]; 63 | } else { 64 | close(nativeSocketHandle); 65 | } 66 | if (readStream) { 67 | CFRelease(readStream); 68 | readStream = nil; 69 | } 70 | if (writeStream) { 71 | CFRelease(writeStream); 72 | writeStream = nil; 73 | } 74 | } 75 | } 76 | 77 | - (BOOL)openWithPort:(uint16_t)port error:(NSError **)error { 78 | struct sockaddr_in addr4; 79 | memset(&addr4, 0, sizeof(addr4)); 80 | addr4.sin_len = sizeof(addr4); 81 | addr4.sin_family = AF_INET; 82 | addr4.sin_port = htons(port); 83 | addr4.sin_addr.s_addr = htonl(INADDR_ANY); 84 | NSData *address = [NSData dataWithBytes:&addr4 length:sizeof(addr4)]; 85 | 86 | CFSocketContext socketContext = {0, (__bridge void *)(self), NULL, NULL, NULL}; 87 | _socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&MPMessagePackServerAcceptCallBack, &socketContext); 88 | 89 | if (!_socket) { 90 | if (_socket) CFRelease(_socket); 91 | _socket = NULL; 92 | if (error) { 93 | *error = MPMakeError(errno, @"Couldn't create socket"); 94 | } 95 | return NO; 96 | } 97 | 98 | int yes = 1; 99 | setsockopt(CFSocketGetNative(_socket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); 100 | // TODO: tcp_no_delay? 101 | 102 | if (kCFSocketSuccess != CFSocketSetAddress(_socket, (CFDataRef)address)) { 103 | if (_socket) { 104 | CFRelease(_socket); 105 | _socket = NULL; 106 | } 107 | if (error) { 108 | *error = MPMakeError(501, @"Couldn't bind socket"); 109 | } 110 | return NO; 111 | } 112 | 113 | CFRunLoopSourceRef source4 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0); 114 | CFRunLoopAddSource(CFRunLoopGetCurrent(), source4, kCFRunLoopCommonModes); 115 | CFRelease(source4); 116 | 117 | MPDebug(@"Created socket"); 118 | return YES; 119 | } 120 | 121 | - (void)close { 122 | if (_socket) { 123 | CFSocketInvalidate(_socket); 124 | _socket = NULL; 125 | } 126 | } 127 | 128 | #pragma mark - 129 | 130 | - (void)client:(MPMessagePackClient *)client didError:(NSError *)error fatal:(BOOL)fatal { 131 | MPErr(@"Client error: %@", error); 132 | if (fatal) { 133 | [_client close]; 134 | } 135 | } 136 | 137 | - (void)client:(MPMessagePackClient *)client didReceiveNotificationWithMethod:(NSString *)method params:(id)params { 138 | if (self.notificationHandler) self.notificationHandler(nil, method, params, nil); 139 | } 140 | 141 | - (void)client:(MPMessagePackClient *)client didChangeStatus:(MPMessagePackClientStatus)status { 142 | 143 | } 144 | 145 | #pragma mark - 146 | 147 | /* 148 | - (BOOL)openWithSocket:(NSString *)socketName error:(NSError **)error { 149 | struct sockaddr_un sun; 150 | sun.sun_family = AF_UNIX; 151 | strcpy(&sun.sun_path[0], [socketName UTF8String]); 152 | size_t len = SUN_LEN(&sun); 153 | sun.sun_len = len; 154 | NSData *address = [NSData dataWithBytes:&sun length:SUN_LEN(&sun)]; 155 | 156 | if ([NSFileManager.defaultManager fileExistsAtPath:socketName]) { 157 | unlink([socketName UTF8String]); // fileSystemRepresentation? 158 | [NSFileManager.defaultManager removeItemAtPath:socketName error:error]; 159 | if (*error) { 160 | return NO; 161 | } 162 | } 163 | 164 | CFSocketNativeHandle socketHandle = socket(AF_UNIX, SOCK_STREAM, 0); 165 | CFSocketContext context = {0, (__bridge void *)self, nil, nil, nil}; 166 | _socket = CFSocketCreateWithNative(nil, socketHandle, kCFSocketAcceptCallBack, MPMessagePackSocketCallBack, &context); 167 | 168 | if (!_socket) { 169 | *error = MPMakeError(-3, @"Unable to create socket %@", socketName); 170 | return NO; 171 | } 172 | 173 | int opt = 1; 174 | setsockopt(socketHandle, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)); 175 | setsockopt(socketHandle, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof(opt)); 176 | 177 | if (CFSocketSetAddress(_socket, (__bridge CFDataRef)address) != kCFSocketSuccess) { 178 | *error = MPMakeError(-3, @"Unable to set socket address %@", socketName); 179 | return NO; 180 | } 181 | 182 | CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0); 183 | CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes); 184 | CFRelease(sourceRef); 185 | 186 | return YES; 187 | 188 | // int serverSocket = socket(AF_UNIX, SOCK_STREAM, 0); 189 | // if (bind(serverSocket, (struct sockaddr *)&sun, sun.sun_len) != 0) { 190 | // *error = MPMakeError(-2, @"Unable to bind to %@", socketName); 191 | // return NO; 192 | // } 193 | // if (listen(serverSocket, 1) != 0) { // In practice you'd specify more than 1 194 | // *error = MPMakeError(-3, @"Unable to listen to %@", socketName); 195 | // return NO; 196 | // }; 197 | // 198 | // dispatch_queue_t queue = dispatch_queue_create("MPMessagePackServer", NULL); 199 | // 200 | // dispatch_async(queue, ^{ 201 | // CFSocketNativeHandle sock = accept(serverSocket, NULL, NULL); 202 | // CFReadStreamRef readStream = NULL; 203 | // CFWriteStreamRef writeStream = NULL; 204 | // CFStreamCreatePairWithSocket (kCFAllocatorDefault, sock, &readStream, &writeStream); 205 | // //dispatch_async(dispatch_get_main_queue(), ^{ 206 | // [self connectionWithInputStream:(__bridge NSInputStream *)readStream outputStream:(__bridge NSOutputStream *)writeStream]; 207 | // //}); 208 | // }); 209 | 210 | return YES; 211 | } 212 | 213 | static void MPMessagePackSocketCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { 214 | MPMessagePackServer *server = (__bridge MPMessagePackServer *)info; 215 | MPDebug(@"Socket callback: %d", (int)type); 216 | if (kCFSocketAcceptCallBack == type) { 217 | [server connectStreams]; 218 | } 219 | } 220 | 221 | - (void)connectStreams { 222 | CFSocketNativeHandle sock = CFSocketGetNative(_socket); 223 | CFSocketSetSocketFlags(_socket, 0); 224 | CFSocketInvalidate(_socket); 225 | CFRelease(_socket); 226 | 227 | CFReadStreamRef readStream = NULL; 228 | CFWriteStreamRef writeStream = NULL; 229 | CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock, &readStream, &writeStream); 230 | if (readStream && writeStream) { 231 | CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 232 | CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 233 | [self connectionWithInputStream:(__bridge NSInputStream *)readStream outputStream:(__bridge NSOutputStream *)writeStream]; 234 | } else { 235 | MPDebug(@"Unable to create streams"); 236 | close(sock); 237 | } 238 | if (readStream) { 239 | CFRelease(readStream); 240 | readStream = nil; 241 | } 242 | if (writeStream) { 243 | CFRelease(writeStream); 244 | writeStream = nil; 245 | } 246 | } 247 | */ 248 | 249 | @end 250 | -------------------------------------------------------------------------------- /MPMessagePack/RPC/MPRPCProtocol.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPRPCProtocol.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 8/30/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPRPCProtocol.h" 10 | #import "MPDefines.h" 11 | 12 | NSString *const MPErrorInfoKey = @"MPErrorInfoKey"; 13 | 14 | @implementation MPRPCProtocol 15 | 16 | - (NSData *)_frameData:(NSData *)data { 17 | NSError *error = nil; 18 | NSData *frameSize = [MPMessagePackWriter writeObject:@(data.length) options:0 error:&error]; 19 | NSAssert(frameSize, @"Error packing frame size: %@", error); 20 | 21 | NSMutableData *framedData = [NSMutableData dataWithCapacity:data.length + frameSize.length]; 22 | [framedData appendData:frameSize]; 23 | [framedData appendData:data]; 24 | return framedData; 25 | } 26 | 27 | - (NSData *)encodeRequestWithMethod:(NSString *)method params:(NSArray *)params messageId:(NSInteger)messageId options:(MPMessagePackWriterOptions)options framed:(BOOL)framed error:(NSError **)error { 28 | NSArray *request = @[@(0), @(messageId), method, params ? params : NSNull.null]; 29 | NSData *data = [MPMessagePackWriter writeObject:request options:options error:error]; 30 | 31 | if (!data) { 32 | return nil; 33 | } 34 | 35 | return framed ? [self _frameData:data] : data; 36 | } 37 | 38 | - (NSData *)encodeResponseWithResult:(id)result error:(id)error messageId:(NSInteger)messageId options:(MPMessagePackWriterOptions)options framed:(BOOL)framed encodeError:(NSError **)encodeError { 39 | NSArray *response = @[@(1), @(messageId), error ? error : NSNull.null, result ? result : NSNull.null]; 40 | NSData *data = [MPMessagePackWriter writeObject:response options:options error:encodeError]; 41 | 42 | if (!data) { 43 | return nil; 44 | } 45 | 46 | return framed ? [self _frameData:data] : data; 47 | } 48 | 49 | - (NSArray *)decodeMessage:(NSData *)data framed:(BOOL)framed error:(NSError **)error { 50 | MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:data]; 51 | 52 | if (framed) { 53 | NSNumber *frameSize = [reader readObject:error]; 54 | if (![frameSize isKindOfClass:NSNumber.class] || *error) { 55 | if (!error) *error = MPMakeError(-1, @"Invalid frame"); 56 | return nil; 57 | } 58 | } 59 | 60 | id obj = [reader readObject:error]; 61 | if (!obj || *error) { 62 | if (!error) *error = MPMakeError(-1, @"Invalid object"); 63 | return nil; 64 | } 65 | 66 | if (!MPVerifyMessage(obj, error)) { 67 | if (!error) *error = MPMakeError(-1, @"Invalid message"); 68 | return nil; 69 | } 70 | 71 | NSArray *message = (NSArray *)obj; 72 | return message; 73 | } 74 | 75 | @end 76 | 77 | BOOL MPVerifyMessage(id message, NSError **error) { 78 | if (![message isKindOfClass:NSArray.class]) { 79 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; Not NSArray type"); 80 | return NO; 81 | } 82 | 83 | if ([message count] != 4) { 84 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; Request should have 4 elements"); 85 | return NO; 86 | } 87 | 88 | id typeObj = MPIfNull(message[0], nil); 89 | if (!typeObj) { 90 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; First element (type) can't be null"); 91 | return NO; 92 | } 93 | if (![typeObj isKindOfClass:NSNumber.class]) { 94 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; First element (type) is not a number"); 95 | return NO; 96 | } 97 | 98 | id messageIdObj = MPIfNull(message[1], nil); 99 | if (!messageIdObj) { 100 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; Second element (messageId) can't be null"); 101 | return NO; 102 | } 103 | if (![messageIdObj isKindOfClass:NSNumber.class]) { 104 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; Second element (messageId) is not a number"); 105 | return NO; 106 | } 107 | 108 | return YES; 109 | } 110 | 111 | BOOL MPVerifyRequest(NSArray *request, NSError **error) { 112 | NSInteger type = [request[0] integerValue]; 113 | if (type != 0) { 114 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; First element (type) is not 0: %@", @(type)); // Request type=0 115 | return NO; 116 | } 117 | 118 | id methodObj = MPIfNull(request[2], nil); 119 | if (!methodObj) { 120 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; Third element (method) can't be null"); 121 | return NO; 122 | } 123 | if (![methodObj isKindOfClass:NSString.class]) { 124 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; Third element (method) is not a string"); 125 | return NO; 126 | } 127 | 128 | id paramsObj = MPIfNull(request[3], nil); 129 | if (paramsObj && ![paramsObj isKindOfClass:NSArray.class]) { 130 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid request; Fourth element (params) is not an array"); 131 | return NO; 132 | } 133 | 134 | return YES; 135 | } 136 | 137 | BOOL MPVerifyResponse(NSArray *response, NSError **error) { 138 | NSInteger type = [response[0] integerValue]; 139 | if (type != 1) { 140 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid response; First element (type) is not 1"); // Request type=1 141 | return NO; 142 | } 143 | 144 | id messageIdObj = MPIfNull(response[1], nil); 145 | if (!messageIdObj) { 146 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid response; Second element (messageId) can't be null"); 147 | return NO; 148 | } 149 | if (![messageIdObj isKindOfClass:NSNumber.class]) { 150 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid response; Second element (messageId) is not a number"); 151 | return NO; 152 | } 153 | 154 | id errorObj = MPIfNull(response[2], nil); 155 | if (errorObj && ![errorObj isKindOfClass:NSDictionary.class]) { 156 | if (error) *error = MPMakeError(MPRPCErrorRequestInvalid, @"Invalid response; Third element (error) is not a dictionary"); 157 | return NO; 158 | } 159 | 160 | return YES; 161 | } 162 | 163 | NSError *MPErrorFromErrorDict(NSString *domain, NSDictionary *dict) { 164 | NSInteger code = -1; 165 | if (dict[@"code"]) code = [dict[@"code"] integerValue]; 166 | NSString *desc = @"Oops, something wen't wrong"; 167 | if (dict[@"desc"]) desc = [dict[@"desc"] description]; 168 | return [NSError errorWithDomain:domain code:code userInfo:@{NSLocalizedDescriptionKey: desc, MPErrorInfoKey: dict}]; 169 | } 170 | -------------------------------------------------------------------------------- /MPMessagePack/RPC/MPRequestor.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPRequestor.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 10/14/15. 6 | // Copyright © 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPRequestor.h" 10 | 11 | @interface MPRequestor () 12 | @property MPRequestCompletion completion; 13 | @end 14 | 15 | @implementation MPRequestor 16 | 17 | + (instancetype)requestWithCompletion:(MPRequestCompletion)completion { 18 | MPRequestor *request = [[MPRequestor alloc] init]; 19 | request.completion = completion; 20 | return request; 21 | } 22 | 23 | - (void)completeWithResult:(id)result error:(NSError *)error { 24 | self.completion(error, result); 25 | self.completion = nil; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /MPMessagePack/XPC/MPXPCClient.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPXPCClient.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 5/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPXPCClient.h" 10 | #import "MPXDefines.h" 11 | 12 | #if ENABLE_XPC_SUPPORT 13 | 14 | #import "MPDefines.h" 15 | #import "NSArray+MPMessagePack.h" 16 | #import "NSData+MPMessagePack.h" 17 | #import "MPXPCProtocol.h" 18 | #import "MPRPCProtocol.h" 19 | 20 | 21 | @interface MPXPCClient () 22 | @property NSString *serviceName; 23 | @property BOOL privileged; 24 | @property MPMessagePackReaderOptions readOptions; 25 | 26 | @property xpc_connection_t connection; 27 | @property NSInteger messageId; 28 | @end 29 | 30 | @implementation MPXPCClient 31 | 32 | - (instancetype)initWithServiceName:(NSString *)serviceName privileged:(BOOL)privileged { 33 | return [self initWithServiceName:serviceName privileged:privileged readOptions:0]; 34 | } 35 | 36 | - (instancetype)initWithServiceName:(NSString *)serviceName privileged:(BOOL)privileged readOptions:(MPMessagePackReaderOptions)readOptions { 37 | if ((self = [super init])) { 38 | _serviceName = serviceName; 39 | _privileged = privileged; 40 | _retryMaxAttempts = 1; // No retry by default (only 1 attempt is made) 41 | _readOptions = readOptions; 42 | } 43 | return self; 44 | } 45 | 46 | - (BOOL)connect:(NSError **)error { 47 | [self.logDelegate log:MPLogLevelInfo format:@"Connecting to %@ (privileged=%@)", _serviceName, @(_privileged)]; 48 | _connection = xpc_connection_create_mach_service([_serviceName UTF8String], NULL, _privileged ? XPC_CONNECTION_MACH_SERVICE_PRIVILEGED : 0); 49 | 50 | if (!_connection) { 51 | if (error) *error = MPMakeError(MPXPCErrorCodeInvalidConnection, @"Failed to create connection"); 52 | return NO; 53 | } 54 | 55 | MPWeakSelf wself = self; 56 | xpc_connection_set_event_handler(_connection, ^(xpc_object_t event) { 57 | xpc_type_t type = xpc_get_type(event); 58 | if (type == XPC_TYPE_ERROR) { 59 | if (event == XPC_ERROR_CONNECTION_INTERRUPTED) { 60 | // Interrupted 61 | [wself.logDelegate log:MPLogLevelWarn format:@"Connection interrupted"]; 62 | } else if (event == XPC_ERROR_CONNECTION_INVALID) { 63 | [wself.logDelegate log:MPLogLevelWarn format:@"Connection invalid, clearing connection"]; 64 | if (wself.connection) { 65 | dispatch_async(dispatch_get_main_queue(), ^{ 66 | wself.connection = nil; 67 | [wself.logDelegate log:MPLogLevelWarn format:@"Cleared connection"]; 68 | }); 69 | } 70 | } else { 71 | // Unknown error 72 | } 73 | } else { 74 | // Unexpected event 75 | } 76 | }); 77 | 78 | xpc_connection_resume(_connection); 79 | [self.logDelegate log:MPLogLevelInfo format:@"Connected"]; 80 | return YES; 81 | } 82 | 83 | - (void)close { 84 | [self.logDelegate log:MPLogLevelInfo format:@"Closing connection"]; 85 | if (_connection) { 86 | xpc_connection_cancel(_connection); 87 | _connection = nil; 88 | } 89 | } 90 | 91 | - (void)sendRequest:(NSString *)method params:(NSArray *)params completion:(void (^)(NSError *error, id value))completion { 92 | __block BOOL replied = NO; 93 | static NSInteger requestId = 0; 94 | if (_timeout > 0) { 95 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, _timeout * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 96 | if (!replied) { 97 | replied = YES; 98 | completion(MPMakeError(MPXPCErrorCodeTimeout, @"Timeout"), nil); 99 | } 100 | }); 101 | } 102 | NSUInteger rid = requestId++; 103 | //[self.logDelegate log:MPLogLevelVerbose format:@"Request start (%@)", @(rid)]; 104 | [self _sendRequest:method params:params attempt:1 maxAttempts:_retryMaxAttempts retryDelay:_retryDelay requestId:rid completion:^(NSError *error, id value) { 105 | if (replied) { 106 | //[self.logDelegate log:MPLogLevelVerbose format:@"Ignoring event, we already completed (%@)", @(requestId)]; 107 | return; 108 | } 109 | 110 | replied = YES; 111 | //[self.logDelegate log:MPLogLevelVerbose format:@"Request completion (%@)", @(rid)]; 112 | completion(error, value); 113 | }]; 114 | } 115 | 116 | - (void)_sendRequest:(NSString *)method params:(NSArray *)params attempt:(NSInteger)attempt maxAttempts:(NSInteger)maxAttempts retryDelay:(NSTimeInterval)retryDelay requestId:(NSUInteger)requestId completion:(void (^)(NSError *error, id value))completion { 117 | 118 | if (attempt < 1) { 119 | completion(MPMakeError(-1, @"Invalid attempt number"), nil); 120 | return; 121 | } 122 | 123 | if (!_connection) { 124 | NSError *error = nil; 125 | if (![self connect:&error]) { 126 | if (attempt >= maxAttempts) { 127 | completion(error, nil); 128 | return; 129 | } else { 130 | [self.logDelegate log:MPLogLevelError format:@"Retrying connect after XPC connect (requestId=%@) error: %@", @(requestId), error]; 131 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, retryDelay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 132 | [self _sendRequest:method params:params attempt:attempt+1 maxAttempts:maxAttempts retryDelay:retryDelay requestId:requestId completion:completion]; 133 | }); 134 | } 135 | } 136 | } 137 | 138 | NSError *error = nil; 139 | xpc_object_t message = [MPXPCProtocol XPCObjectFromRequestWithMethod:method messageId:++_messageId params:params error:&error]; 140 | if (!message) { 141 | completion(error, nil); 142 | return; 143 | } 144 | 145 | if (!_connection) { 146 | completion(MPMakeError(MPXPCErrorCodeInvalidConnection, @"No connection"), nil); 147 | return; 148 | } 149 | 150 | //[self.logDelegate log:MPLogLevelVerbose format:@"Sending request (%@)", @(requestId)]; 151 | xpc_connection_send_message_with_reply(_connection, message, dispatch_get_main_queue(), ^(xpc_object_t event) { 152 | if (xpc_get_type(event) == XPC_TYPE_ERROR) { 153 | const char *description = xpc_dictionary_get_string(event, "XPCErrorDescription"); 154 | NSString *errorMessage = [NSString stringWithCString:description encoding:NSUTF8StringEncoding]; 155 | NSError *xpcError = MPMakeError(MPXPCErrorCodeInvalidConnection, @"XPC Error: %@", errorMessage); 156 | if (attempt >= maxAttempts) { 157 | [self.logDelegate log:MPLogLevelError format:@"Max attempts reached (%@ >= %@)", @(attempt), @(maxAttempts)]; 158 | completion(xpcError, nil); 159 | } else { 160 | [self.logDelegate log:MPLogLevelError format:@"Retrying (attempt=%@, requestId=%@) after XPC error: %@", @(attempt), @(requestId), xpcError]; 161 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, retryDelay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 162 | [self _sendRequest:method params:params attempt:attempt+1 maxAttempts:maxAttempts retryDelay:retryDelay requestId:requestId completion:completion]; 163 | }); 164 | } 165 | } else if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { 166 | NSError *error = nil; 167 | size_t length = 0; 168 | const void *buffer = xpc_dictionary_get_data(event, "data", &length); 169 | NSData *dataResponse = [NSData dataWithBytes:buffer length:length]; 170 | 171 | id response = [dataResponse mp_array:self.readOptions error:&error]; 172 | 173 | if (!response) { 174 | completion(error, nil); 175 | return; 176 | } 177 | if (!MPVerifyResponse(response, &error)) { 178 | completion(error, nil); 179 | return; 180 | } 181 | NSDictionary *errorDict = MPIfNull(response[2], nil); 182 | if (errorDict) { 183 | error = MPErrorFromErrorDict(self.serviceName, errorDict); 184 | completion(error, nil); 185 | } else { 186 | completion(nil, MPIfNull(response[3], nil)); 187 | } 188 | } 189 | }); 190 | } 191 | 192 | @end 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /MPMessagePack/XPC/MPXPCProtocol.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPXPCProtocol.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 5/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPXPCProtocol.h" 10 | #import "MPXDefines.h" 11 | 12 | #if ENABLE_XPC_SUPPORT 13 | 14 | #import "NSArray+MPMessagePack.h" 15 | #import "NSData+MPMessagePack.h" 16 | #import "MPRPCProtocol.h" 17 | #import "MPDefines.h" 18 | 19 | @implementation MPXPCProtocol 20 | 21 | + (xpc_object_t)XPCObjectFromRequestWithMethod:(NSString *)method messageId:(NSInteger)messageId params:(NSArray *)params error:(NSError **)error { 22 | NSArray *request = @[@(0), @(messageId), method, (params ? params : NSNull.null)]; 23 | NSData *dataRequest = [request mp_messagePack:0 error:error]; 24 | if (!dataRequest) { 25 | return nil; 26 | } 27 | 28 | // XPC request object must be dictionary so put data in {"data": data} dictionary. 29 | xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); 30 | xpc_dictionary_set_data(message, "data", [dataRequest bytes], [dataRequest length]); 31 | return message; 32 | } 33 | 34 | + (void)requestFromXPCObject:(xpc_object_t)event completion:(void (^)(NSError *error, NSNumber *messageId, NSString *method, NSArray *params))completion { 35 | size_t length = 0; 36 | const void *buffer = xpc_dictionary_get_data(event, "data", &length); 37 | NSData *dataRequest = [NSData dataWithBytes:buffer length:length]; 38 | 39 | NSError *error = nil; 40 | 41 | // See msgpack-rpc spec for request/response format 42 | NSArray *request = [dataRequest mp_array:&error]; 43 | if (error) { 44 | completion(error, nil, nil, nil); 45 | return; 46 | } 47 | 48 | if (!MPVerifyRequest(request, &error)) { 49 | completion(error, nil, nil, nil); 50 | return; 51 | } 52 | 53 | NSNumber *messageId = request[1]; 54 | NSString *method = request[2]; 55 | NSArray *params = MPIfNull(request[3], @[]); 56 | 57 | completion(nil, messageId, method, params); 58 | } 59 | 60 | @end 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /MPMessagePack/XPC/MPXPCService.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackXPC.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 5/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "MPXPCService.h" 10 | #import "MPXDefines.h" 11 | 12 | #if ENABLE_XPC_SUPPORT 13 | 14 | #import "NSData+MPMessagePack.h" 15 | #import "NSArray+MPMessagePack.h" 16 | #import "MPXPCProtocol.h" 17 | #import "MPDefines.h" 18 | 19 | @interface MPXPCService () 20 | @property xpc_connection_t connection; 21 | @end 22 | 23 | #import 24 | 25 | void MPSysLog(NSString *msg, ...) { 26 | va_list args; 27 | va_start(args, msg); 28 | 29 | NSString *string = [[NSString alloc] initWithFormat:msg arguments:args]; 30 | 31 | va_end(args); 32 | 33 | NSLog(@"%@", string); 34 | syslog(LOG_NOTICE, "%s", [string UTF8String]); 35 | } 36 | 37 | @implementation MPXPCService 38 | 39 | - (void)listen:(xpc_connection_t)service { 40 | [self listen:service codeRequirement:nil]; 41 | } 42 | 43 | - (void)listen:(xpc_connection_t)service codeRequirement:(NSString *)codeRequirement { 44 | xpc_connection_set_event_handler(service, ^(xpc_object_t connection) { 45 | if (codeRequirement) { 46 | pid_t pid = xpc_connection_get_pid(connection); 47 | NSError *error = nil; 48 | BOOL ok = [self checkCodeRequirement:codeRequirement pid:pid error:&error]; 49 | if (!ok) { 50 | MPSysLog(@"Failed to pass code requirement: %@", error); 51 | xpc_connection_cancel(connection); 52 | return; 53 | } 54 | } 55 | [self setEventHandler:connection]; 56 | }); 57 | 58 | xpc_connection_resume(service); 59 | } 60 | 61 | - (void)setEventHandler:(xpc_object_t)connection { 62 | xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { 63 | xpc_type_t type = xpc_get_type(event); 64 | 65 | if (type == XPC_TYPE_ERROR) { 66 | if (event == XPC_ERROR_CONNECTION_INVALID) { 67 | // The client process on the other end of the connection has either 68 | // crashed or cancelled the connection. After receiving this error, 69 | // the connection is in an invalid state, and you do not need to 70 | // call xpc_connection_cancel(). Just tear down any associated state 71 | // here. 72 | } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { 73 | // Handle per-connection termination cleanup. 74 | } else { 75 | MPSysLog(@"Error: %@", event); 76 | } 77 | } else { 78 | xpc_connection_t remote = xpc_dictionary_get_remote_connection(event); 79 | [self handleEvent:event remote:remote completion:^(NSError *error, NSData *data) { 80 | if (error) { 81 | xpc_object_t reply = xpc_dictionary_create_reply(event); 82 | xpc_dictionary_set_string(reply, "error", [[error localizedDescription] UTF8String]); 83 | xpc_connection_send_message(remote, reply); 84 | } else { 85 | xpc_object_t reply = xpc_dictionary_create_reply(event); 86 | xpc_dictionary_set_data(reply, "data", [data bytes], [data length]); 87 | xpc_connection_send_message(remote, reply); 88 | } 89 | }]; 90 | } 91 | }); 92 | 93 | xpc_connection_resume(connection); 94 | } 95 | 96 | - (void)handleEvent:(xpc_object_t)event remote:(xpc_connection_t)remote completion:(void (^)(NSError *error, NSData *data))completion { 97 | [MPXPCProtocol requestFromXPCObject:event completion:^(NSError *error, NSNumber *messageId, NSString *method, NSArray *params) { 98 | if (error) { 99 | MPSysLog(@"Request error: %@", error); 100 | completion(error, nil); 101 | } else { 102 | [self handleRequestWithMethod:method params:params messageId:messageId remote:remote completion:^(NSError *error, id value) { 103 | if (error) { 104 | NSDictionary *errorDict = @{@"code": @(error.code), @"desc": error.localizedDescription}; 105 | NSArray *response = @[@(1), messageId, errorDict, NSNull.null]; 106 | NSData *dataResponse = [response mp_messagePack]; 107 | completion(nil, dataResponse); 108 | } else { 109 | NSArray *response = @[@(1), messageId, NSNull.null, (value ? value : NSNull.null)]; 110 | NSData *dataResponse = [response mp_messagePack]; 111 | completion(nil, dataResponse); 112 | } 113 | }]; 114 | } 115 | }]; 116 | } 117 | 118 | - (void)handleRequestWithMethod:(NSString *)method params:(NSArray *)params messageId:(NSNumber *)messageId remote:(xpc_connection_t)remote completion:(void (^)(NSError *error, id value))completion { 119 | completion(MPMakeError(MPXPCErrorCodeUnknownRequest, @"Unkown request"), nil); 120 | } 121 | 122 | - (BOOL)checkCodeRequirement:(NSString *)codeRequirement path:(NSURL *)path error:(NSError **)error { 123 | SecStaticCodeRef staticCode = NULL; 124 | OSStatus statusCodePath = SecStaticCodeCreateWithPath((__bridge CFURLRef)path, kSecCSDefaultFlags, &staticCode); 125 | if (statusCodePath != errSecSuccess) { 126 | *error = MPMakeError(statusCodePath, @"Failed to create code path"); 127 | return NO; 128 | } 129 | // Code requirement must start with 'anchor apple'. 130 | // See https://www.okta.com/security-blog/2018/06/issues-around-third-party-apple-code-signing-checks/ 131 | if (![codeRequirement hasPrefix:@"anchor apple"]) { 132 | *error = MPMakeError(-1, @"Code requirement must start with 'anchor apple'"); 133 | return NO; 134 | } 135 | SecRequirementRef requirement = NULL; 136 | OSStatus statusCreate = SecRequirementCreateWithString((__bridge CFStringRef)codeRequirement, kSecCSDefaultFlags, &requirement); 137 | if (statusCreate != errSecSuccess) { 138 | *error = MPMakeError(statusCreate, @"Failed to create requirement"); 139 | return NO; 140 | } 141 | // It is important to have all these flags present. 142 | // See https://www.okta.com/security-blog/2018/06/issues-around-third-party-apple-code-signing-checks/ 143 | OSStatus statusCheck = SecStaticCodeCheckValidityWithErrors(staticCode, kSecCSDefaultFlags | kSecCSCheckNestedCode | kSecCSCheckAllArchitectures | kSecCSEnforceRevocationChecks, requirement, NULL); 144 | if (statusCheck != errSecSuccess) { 145 | *error = MPMakeError(statusCheck, @"Binary failed code requirement"); 146 | return NO; 147 | } 148 | return YES; 149 | } 150 | 151 | /*! 152 | Check code requirement for process id (from an xpc connection). 153 | 154 | "The OS’s process ID space is relatively small, which means that process IDs are commonly reused. 155 | There is a recommended alternative to process IDs, namely audit tokens (audit_token_t), but you can’t use this because a critical piece of public API is missing. 156 | While you can do step 2 with an audit token (using kSecGuestAttributeAudit), there’s no public API to get an audit token from an XPC connection. 157 | Fortunately, process ID wrapping problems aren’t a real threat in this context because, if you create an XPC connection per process, you can do your checking based on the process ID of that process. If the process dies, the connection goes away and you’ll end up rechecking the process ID on the new connection." 158 | -- https://forums.developer.apple.com/thread/72881 159 | */ 160 | - (BOOL)checkCodeRequirement:(NSString *)codeRequirement pid:(pid_t)pid error:(NSError **)error { 161 | CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pid); 162 | if (!value) { 163 | *error = MPMakeError(-1, @"Failed to alloc pid ref"); 164 | return NO; 165 | } 166 | CFDictionaryRef attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecGuestAttributePid, (const void **)&value, 1, NULL, NULL); 167 | if (!value) { 168 | *error = MPMakeError(-1, @"Failed to create sec guest attributes"); 169 | return NO; 170 | } 171 | SecCodeRef code = NULL; 172 | OSStatus statusGuest = SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code); 173 | if (statusGuest != errSecSuccess) { 174 | *error = MPMakeError(-1, @"Failed to sec copy guest"); 175 | return NO; 176 | } 177 | CFURLRef path = NULL; 178 | OSStatus statusCopy = SecCodeCopyPath(code, kSecCSDefaultFlags, &path); 179 | if (statusCopy != errSecSuccess) { 180 | *error = MPMakeError(-1, @"Failed to sec copy path"); 181 | } 182 | 183 | return [self checkCodeRequirement:codeRequirement path:(__bridge NSURL *)path error:error]; 184 | } 185 | 186 | @end 187 | 188 | #endif 189 | -------------------------------------------------------------------------------- /MPMessagePack/include/MPDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPDefines.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 12/13/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #undef MPDebug 12 | #define MPDebug(fmt, ...) do {} while(0) 13 | #undef MPErr 14 | #define MPErr(fmt, ...) do {} while(0) 15 | 16 | #if DEBUG 17 | #undef MPDebug 18 | #define MPDebug(fmt, ...) NSLog((@"%s:%d: " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) 19 | #undef MPErr 20 | #define MPErr(fmt, ...) NSLog((@"%s:%d: " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) 21 | #endif 22 | 23 | typedef void (^MPCompletion)(NSError *error); 24 | 25 | #define MPMakeError(CODE, MSG, ...) [NSError errorWithDomain:@"MPMessagePack" code:CODE userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:MSG, ##__VA_ARGS__], NSLocalizedRecoveryOptionsErrorKey: @[@"OK"]}] 26 | 27 | #define MPMakeErrorWithRecovery(CODE, MSG, RECOVERY, ...) [NSError errorWithDomain:@"MPMessagePack" code:CODE userInfo:@{NSLocalizedDescriptionKey: MSG, NSLocalizedRecoveryOptionsErrorKey: @[@"OK"], NSLocalizedRecoverySuggestionErrorKey:[NSString stringWithFormat:RECOVERY, ##__VA_ARGS__]}] 28 | 29 | 30 | #define MPIfNull(obj, val) ([obj isEqual:NSNull.null] ? val : obj) 31 | 32 | #define MPWeakObject(o) __typeof__(o) __weak 33 | #define MPWeakSelf MPWeakObject(self) 34 | -------------------------------------------------------------------------------- /MPMessagePack/include/MPLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPLog.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 9/1/16. 6 | // Copyright © 2016 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM (NSInteger, MPLogLevel) { 12 | MPLogLevelDefault = 0, 13 | MPLogLevelVerbose = 20, 14 | MPLogLevelDebug = 20, 15 | MPLogLevelInfo = 30, 16 | MPLogLevelWarn = 40, 17 | MPLogLevelError = 50, 18 | }; 19 | 20 | @protocol MPLog 21 | - (void)log:(MPLogLevel)level format:(NSString *)format, ...; 22 | @end 23 | -------------------------------------------------------------------------------- /MPMessagePack/include/MPMessagePackReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackReader.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_OPTIONS (NSInteger, MPMessagePackReaderOptions) { 12 | MPMessagePackReaderOptionsNone = 0, 13 | // If set will return a GHODictionary instead of an NSDictionary 14 | MPMessagePackReaderOptionsUseOrderedDictionary = 1 << 0, 15 | }; 16 | 17 | 18 | @interface MPMessagePackReader : NSObject 19 | 20 | @property (readonly) size_t index; 21 | 22 | - (instancetype)initWithData:(NSData *)data; 23 | - (instancetype)initWithData:(NSData *)data options:(MPMessagePackReaderOptions)options; 24 | 25 | - (id)readObject:(NSError **)error; 26 | 27 | + (id)readData:(NSData *)data error:(NSError **)error; 28 | 29 | + (id)readData:(NSData *)data options:(MPMessagePackReaderOptions)options error:(NSError **)error; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /MPMessagePack/include/MPMessagePackWriter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackWriter.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_OPTIONS (NSInteger, MPMessagePackWriterOptions) { 12 | MPMessagePackWriterOptionsNone = 0, 13 | MPMessagePackWriterOptionsSortDictionaryKeys = 1 << 0, 14 | }; 15 | 16 | @interface MPMessagePackWriter : NSObject 17 | 18 | - (NSMutableData *)writeObject:(id)obj options:(MPMessagePackWriterOptions)options error:(NSError **)error; 19 | 20 | + (NSMutableData *)writeObject:(id)obj error:(NSError **)error; 21 | 22 | + (NSMutableData *)writeObject:(id)obj options:(MPMessagePackWriterOptions)options error:(NSError **)error; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MPMessagePack/include/NSArray+MPMessagePack.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+MPMessagePack.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MPMessagePackWriter.h" 12 | 13 | @interface NSArray (MPMessagePack) 14 | 15 | - (NSData *)mp_messagePack; 16 | 17 | - (NSData *)mp_messagePack:(MPMessagePackWriterOptions)options; 18 | 19 | - (NSData *)mp_messagePack:(MPMessagePackWriterOptions)options error:(NSError **)error; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MPMessagePack/include/NSData+MPMessagePack.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MPMessagePack.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 1/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MPMessagePackReader.h" 12 | 13 | @interface NSData (MPMessagePack) 14 | 15 | - (NSString *)mp_hexString; 16 | + (NSData *)mp_dataFromHexString:(NSString *)str; 17 | 18 | - (NSArray *)mp_array:(NSError **)error; 19 | - (NSArray *)mp_array:(MPMessagePackReaderOptions)options error:(NSError **)error; 20 | 21 | - (NSDictionary *)mp_dict:(NSError **)error; 22 | 23 | - (id)mp_dict:(MPMessagePackReaderOptions)options error:(NSError **)error; 24 | 25 | - (id)mp_object:(NSError **)error; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /MPMessagePack/include/NSDictionary+MPMessagePack.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MPMessagePack.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 7/3/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MPMessagePackWriter.h" 12 | 13 | @interface NSDictionary (MPMessagePack) 14 | 15 | - (NSData *)mp_messagePack; 16 | 17 | - (NSData *)mp_messagePack:(MPMessagePackWriterOptions)options; 18 | 19 | - (NSData *)mp_messagePack:(MPMessagePackWriterOptions)options error:(NSError **)error; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MPMessagePack/include/RPC/MPDispatchRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPDispatchRequest.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 10/14/15. 6 | // Copyright © 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MPDispatchRequest : NSObject 12 | 13 | @property (readonly) dispatch_semaphore_t semaphore; 14 | 15 | @property NSError *error; 16 | @property id result; 17 | 18 | + (instancetype)dispatchRequest; 19 | 20 | @end -------------------------------------------------------------------------------- /MPMessagePack/include/RPC/MPMessagePackClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackRPClient.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 12/12/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MPDefines.h" 12 | #import "MPRPCProtocol.h" 13 | 14 | typedef NS_ENUM (NSInteger, MPMessagePackClientStatus) { 15 | MPMessagePackClientStatusNone = 0, 16 | MPMessagePackClientStatusClosed = 1, 17 | MPMessagePackClientStatusOpening, 18 | MPMessagePackClientStatusOpen, 19 | }; 20 | 21 | typedef NS_OPTIONS (NSInteger, MPMessagePackOptions) { 22 | MPMessagePackOptionsNone = 0, 23 | // If true, the message is wrapped in a frame 24 | MPMessagePackOptionsFramed = 1 << 0, 25 | }; 26 | 27 | @protocol MPMessagePackCoder 28 | - (nonnull id)encodeObject:(nonnull id)obj; 29 | @end 30 | 31 | @class MPMessagePackClient; 32 | 33 | @protocol MPMessagePackClientDelegate 34 | - (void)client:(nonnull MPMessagePackClient *)client didError:(nonnull NSError *)error fatal:(BOOL)fatal; 35 | - (void)client:(nonnull MPMessagePackClient *)client didChangeStatus:(MPMessagePackClientStatus)status; 36 | - (void)client:(nonnull MPMessagePackClient *)client didReceiveNotificationWithMethod:(nonnull NSString *)method params:(nonnull NSArray *)params; 37 | @end 38 | 39 | @interface MPMessagePackClient : NSObject 40 | 41 | @property (nullable, weak) id delegate; 42 | @property (nullable, copy) MPRequestHandler requestHandler; 43 | @property (readonly, nonatomic) MPMessagePackClientStatus status; 44 | @property (nullable) id coder; 45 | 46 | - (nonnull instancetype)initWithName:(nonnull NSString *)name options:(MPMessagePackOptions)options; 47 | 48 | - (void)openWithHost:(nonnull NSString *)host port:(UInt32)port completion:(nonnull MPCompletion)completion; 49 | 50 | - (BOOL)openWithSocket:(nonnull NSString *)unixSocket completion:(nonnull MPCompletion)completion; 51 | 52 | - (void)setInputStream:(nonnull NSInputStream *)inputStream outputStream:(nonnull NSOutputStream *)outputStream; 53 | 54 | - (void)close; 55 | 56 | /*! 57 | Send RPC request asyncronously with completion block. 58 | 59 | @param method Method name 60 | @param params Method args. If coder is set on client, we will use it to encode. 61 | @param messageId Unique message identifier. Responses will use this message ID. 62 | @param completion Response 63 | */ 64 | - (void)sendRequestWithMethod:(nonnull NSString *)method params:(nonnull NSArray *)params messageId:(NSInteger)messageId completion:(nonnull MPRequestCompletion)completion; 65 | 66 | /*! 67 | Send a response. 68 | 69 | @param result Result 70 | @param error Error 71 | @param messageId Message ID (will match request message ID) 72 | */ 73 | - (void)sendResponseWithResult:(nullable id)result error:(nullable id)error messageId:(NSInteger)messageId; 74 | 75 | /*! 76 | Send request synchronously. 77 | 78 | @param method Method name 79 | @param params Method args. If coder is set on client, we will use it to encode. 80 | @param messageId Unique message identifier. Responses will use this message ID. 81 | @param timeout Timeout 82 | @param error Out error 83 | @result Result of method invocation 84 | */ 85 | - (nullable id)sendRequestWithMethod:(nonnull NSString *)method params:(nonnull NSArray *)params messageId:(NSInteger)messageId timeout:(NSTimeInterval)timeout error:(NSError * _Nonnull * _Nonnull)error; 86 | 87 | /*! 88 | Cancel request. 89 | 90 | @param messageId Message id 91 | @result Return YES if cancelled 92 | */ 93 | - (BOOL)cancelRequestWithMessageId:(NSInteger)messageId; 94 | 95 | @end 96 | 97 | 98 | -------------------------------------------------------------------------------- /MPMessagePack/include/RPC/MPMessagePackServer.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackServer.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 12/13/14. 6 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MPMessagePackClient.h" 12 | 13 | @interface MPMessagePackServer : NSObject 14 | 15 | @property (copy, nonatomic) MPRequestHandler requestHandler; 16 | @property (copy, nonatomic) MPRequestHandler notificationHandler; 17 | 18 | - (instancetype)initWithOptions:(MPMessagePackOptions)options; 19 | 20 | - (BOOL)openWithPort:(uint16_t)port error:(NSError **)error; 21 | 22 | - (void)close; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MPMessagePack/include/RPC/MPRPCProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPRPCProtocol.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 8/30/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MPMessagePackWriter.h" 12 | #import "MPMessagePackReader.h" 13 | 14 | extern NSString *const MPErrorInfoKey; 15 | 16 | typedef NS_ENUM (NSInteger, MPRPCError) { 17 | MPRPCErrorNone = 0, 18 | MPRPCErrorSocketCreateError = -3, 19 | MPRPCErrorSocketOpenError = -6, 20 | MPRPCErrorSocketOpenTimeout = -7, 21 | MPRPCErrorRequestInvalid = -20, 22 | MPRPCErrorRequestTimeout = -21, 23 | MPRPCErrorRequestCanceled = -22, 24 | MPRPCErrorResponseInvalid = -30, 25 | }; 26 | 27 | typedef void (^MPErrorHandler)(NSError *error); 28 | // Callback after we send request 29 | typedef void (^MPRequestCompletion)(NSError *error, id result); 30 | typedef void (^MPRequestHandler)(NSNumber *messageId, NSString *method, NSArray *params, MPRequestCompletion completion); 31 | 32 | 33 | @interface MPRPCProtocol : NSObject 34 | 35 | - (NSData *)encodeRequestWithMethod:(NSString *)method params:(NSArray *)params messageId:(NSInteger)messageId options:(MPMessagePackWriterOptions)options framed:(BOOL)framed error:(NSError **)error; 36 | 37 | - (NSData *)encodeResponseWithResult:(id)result error:(id)error messageId:(NSInteger)messageId options:(MPMessagePackWriterOptions)options framed:(BOOL)framed encodeError:(NSError **)encodeError; 38 | 39 | - (NSArray *)decodeMessage:(NSData *)data framed:(BOOL)framed error:(NSError **)error; 40 | 41 | @end 42 | 43 | 44 | // Verify the object is a valid msgpack rpc message 45 | BOOL MPVerifyMessage(id request, NSError **error); 46 | 47 | // Verify the object is a valid msgpack rpc request 48 | BOOL MPVerifyRequest(NSArray *request, NSError **error); 49 | 50 | // Verify the object is a valid msgpack rpc response 51 | BOOL MPVerifyResponse(NSArray *response, NSError **error); 52 | 53 | // NSError from error dict 54 | NSError *MPErrorFromErrorDict(NSString *domain, NSDictionary *dict); 55 | -------------------------------------------------------------------------------- /MPMessagePack/include/RPC/MPRequestor.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPRequestor.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 10/14/15. 6 | // Copyright © 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MPRPCProtocol.h" 12 | 13 | @interface MPRequestor : NSObject 14 | 15 | @property (readonly) MPRequestCompletion completion; 16 | 17 | + (instancetype)requestWithCompletion:(MPRequestCompletion)completion; 18 | 19 | - (void)completeWithResult:(id)result error:(NSError *)error; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MPMessagePack/include/XPC/MPXDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPXDefines.h 3 | // MPMessagePack 4 | // 5 | // Copyright (c) 2014 Gabriel Handford. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED 11 | #define ENABLE_XPC_SUPPORT 1 12 | #else 13 | #define ENABLE_XPC_SUPPORT 0 14 | #endif 15 | -------------------------------------------------------------------------------- /MPMessagePack/include/XPC/MPXPCClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPXPCClient.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 5/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MPXDefines.h" 11 | 12 | #if ENABLE_XPC_SUPPORT 13 | 14 | #import "MPMessagePackReader.h" 15 | #import "MPLog.h" 16 | 17 | @interface MPXPCClient : NSObject 18 | 19 | @property (readonly) NSString *serviceName; 20 | @property (readonly) BOOL privileged; 21 | @property (readonly) MPMessagePackReaderOptions readOptions; 22 | @property NSTimeInterval timeout; 23 | @property BOOL retryMaxAttempts; 24 | @property NSTimeInterval retryDelay; 25 | @property (weak) id logDelegate; 26 | 27 | - (instancetype)initWithServiceName:(NSString *)serviceName privileged:(BOOL)privileged; 28 | - (instancetype)initWithServiceName:(NSString *)serviceName privileged:(BOOL)privileged readOptions:(MPMessagePackReaderOptions)readOptions ; 29 | 30 | - (BOOL)connect:(NSError **)error; 31 | 32 | - (void)sendRequest:(NSString *)method params:(NSArray *)params completion:(void (^)(NSError *error, id value))completion; 33 | 34 | - (void)close; 35 | 36 | @end 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /MPMessagePack/include/XPC/MPXPCProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPXPCProtocol.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 5/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MPXDefines.h" 11 | 12 | #if ENABLE_XPC_SUPPORT 13 | #import 14 | 15 | typedef NS_ENUM(NSInteger, MPXPCErrorCode) { 16 | MPXPCErrorCodeNone = 0, 17 | MPXPCErrorCodeInvalidRequest = -1, 18 | MPXPCErrorCodeUnknownRequest = -2, 19 | 20 | MPXPCErrorCodeInvalidConnection = -10, 21 | MPXPCErrorCodeTimeout = -11, 22 | }; 23 | 24 | @interface MPXPCProtocol : NSObject 25 | 26 | + (xpc_object_t)XPCObjectFromRequestWithMethod:(NSString *)method messageId:(NSInteger)messageId params:(NSArray *)params error:(NSError **)error; 27 | 28 | + (void)requestFromXPCObject:(xpc_object_t)event completion:(void (^)(NSError *error, NSNumber *messageId, NSString *method, NSArray *params))completion; 29 | 30 | @end 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /MPMessagePack/include/XPC/MPXPCService.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePackXPC.h 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 5/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MPXDefines.h" 11 | 12 | #if ENABLE_XPC_SUPPORT 13 | #import 14 | #import 15 | 16 | @interface MPXPCService : NSObject 17 | 18 | - (void)listen:(xpc_connection_t)service; 19 | 20 | - (void)listen:(xpc_connection_t)service codeRequirement:(NSString *)codeRequirement; 21 | 22 | // Subclasses should implement this 23 | - (void)handleRequestWithMethod:(NSString *)method params:(NSArray *)params messageId:(NSNumber *)messageId remote:(xpc_connection_t)remote completion:(void (^)(NSError *error, id value))completion; 24 | 25 | @end 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /MPMessagePack/include/cmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | Copyright (c) 2020 Charles Gunyon 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | THE SOFTWARE. 19 | */ 20 | 21 | #ifndef CMP_H__ 22 | #define CMP_H__ 23 | 24 | struct cmp_ctx_s; 25 | 26 | typedef bool (*cmp_reader)(struct cmp_ctx_s *ctx, void *data, size_t limit); 27 | typedef size_t (*cmp_writer)(struct cmp_ctx_s *ctx, const void *data, 28 | size_t count); 29 | 30 | enum { 31 | CMP_TYPE_POSITIVE_FIXNUM, /* 0 */ 32 | CMP_TYPE_FIXMAP, /* 1 */ 33 | CMP_TYPE_FIXARRAY, /* 2 */ 34 | CMP_TYPE_FIXSTR, /* 3 */ 35 | CMP_TYPE_NIL, /* 4 */ 36 | CMP_TYPE_BOOLEAN, /* 5 */ 37 | CMP_TYPE_BIN8, /* 6 */ 38 | CMP_TYPE_BIN16, /* 7 */ 39 | CMP_TYPE_BIN32, /* 8 */ 40 | CMP_TYPE_EXT8, /* 9 */ 41 | CMP_TYPE_EXT16, /* 10 */ 42 | CMP_TYPE_EXT32, /* 11 */ 43 | CMP_TYPE_FLOAT, /* 12 */ 44 | CMP_TYPE_DOUBLE, /* 13 */ 45 | CMP_TYPE_UINT8, /* 14 */ 46 | CMP_TYPE_UINT16, /* 15 */ 47 | CMP_TYPE_UINT32, /* 16 */ 48 | CMP_TYPE_UINT64, /* 17 */ 49 | CMP_TYPE_SINT8, /* 18 */ 50 | CMP_TYPE_SINT16, /* 19 */ 51 | CMP_TYPE_SINT32, /* 20 */ 52 | CMP_TYPE_SINT64, /* 21 */ 53 | CMP_TYPE_FIXEXT1, /* 22 */ 54 | CMP_TYPE_FIXEXT2, /* 23 */ 55 | CMP_TYPE_FIXEXT4, /* 24 */ 56 | CMP_TYPE_FIXEXT8, /* 25 */ 57 | CMP_TYPE_FIXEXT16, /* 26 */ 58 | CMP_TYPE_STR8, /* 27 */ 59 | CMP_TYPE_STR16, /* 28 */ 60 | CMP_TYPE_STR32, /* 29 */ 61 | CMP_TYPE_ARRAY16, /* 30 */ 62 | CMP_TYPE_ARRAY32, /* 31 */ 63 | CMP_TYPE_MAP16, /* 32 */ 64 | CMP_TYPE_MAP32, /* 33 */ 65 | CMP_TYPE_NEGATIVE_FIXNUM /* 34 */ 66 | }; 67 | 68 | typedef struct cmp_ext_s { 69 | int8_t type; 70 | uint32_t size; 71 | } cmp_ext_t; 72 | 73 | union cmp_object_data_u { 74 | bool boolean; 75 | uint8_t u8; 76 | uint16_t u16; 77 | uint32_t u32; 78 | uint64_t u64; 79 | int8_t s8; 80 | int16_t s16; 81 | int32_t s32; 82 | int64_t s64; 83 | float flt; 84 | double dbl; 85 | uint32_t array_size; 86 | uint32_t map_size; 87 | uint32_t str_size; 88 | uint32_t bin_size; 89 | cmp_ext_t ext; 90 | }; 91 | 92 | typedef struct cmp_ctx_s { 93 | uint8_t error; 94 | void *buf; 95 | cmp_reader read; 96 | cmp_writer write; 97 | } cmp_ctx_t; 98 | 99 | typedef struct cmp_object_s { 100 | uint8_t type; 101 | union cmp_object_data_u as; 102 | } cmp_object_t; 103 | 104 | #ifdef __cplusplus 105 | extern "C" { 106 | #endif 107 | 108 | /* 109 | * ============================================================================ 110 | * === Main API 111 | * ============================================================================ 112 | */ 113 | 114 | /* Initializes a CMP context */ 115 | void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader read, cmp_writer write); 116 | 117 | /* Returns CMP's version */ 118 | uint32_t cmp_version(void); 119 | 120 | /* Returns the MessagePack version employed by CMP */ 121 | uint32_t cmp_mp_version(void); 122 | 123 | /* Returns a string description of a CMP context's error */ 124 | const char* cmp_strerror(cmp_ctx_t *ctx); 125 | 126 | /* Writes a signed integer to the backend */ 127 | bool cmp_write_sint(cmp_ctx_t *ctx, int64_t d); 128 | 129 | /* Writes an unsigned integer to the backend */ 130 | bool cmp_write_uint(cmp_ctx_t *ctx, uint64_t u); 131 | 132 | /* Writes a single-precision float to the backend */ 133 | bool cmp_write_float(cmp_ctx_t *ctx, float f); 134 | 135 | /* Writes a double-precision float to the backend */ 136 | bool cmp_write_double(cmp_ctx_t *ctx, double d); 137 | 138 | /* Writes NULL to the backend */ 139 | bool cmp_write_nil(cmp_ctx_t *ctx); 140 | 141 | /* Writes true to the backend */ 142 | bool cmp_write_true(cmp_ctx_t *ctx); 143 | 144 | /* Writes false to the backend */ 145 | bool cmp_write_false(cmp_ctx_t *ctx); 146 | 147 | /* Writes a boolean value to the backend */ 148 | bool cmp_write_bool(cmp_ctx_t *ctx, bool b); 149 | 150 | /* 151 | * Writes an unsigned char's value to the backend as a boolean. This is useful 152 | * if you are using a different boolean type in your application. 153 | */ 154 | bool cmp_write_u8_as_bool(cmp_ctx_t *ctx, uint8_t b); 155 | 156 | /* 157 | * Writes a string to the backend; according to the MessagePack spec, this must 158 | * be encoded using UTF-8, but CMP leaves that job up to the programmer. 159 | */ 160 | bool cmp_write_str(cmp_ctx_t *ctx, const char *data, uint32_t size); 161 | 162 | /* 163 | * Writes the string marker to the backend. This is useful if you are writing 164 | * data in chunks instead of a single shot. 165 | */ 166 | bool cmp_write_str_marker(cmp_ctx_t *ctx, uint32_t size); 167 | 168 | /* Writes binary data to the backend */ 169 | bool cmp_write_bin(cmp_ctx_t *ctx, const void *data, uint32_t size); 170 | 171 | /* 172 | * Writes the binary data marker to the backend. This is useful if you are 173 | * writing data in chunks instead of a single shot. 174 | */ 175 | bool cmp_write_bin_marker(cmp_ctx_t *ctx, uint32_t size); 176 | 177 | /* Writes an array to the backend. */ 178 | bool cmp_write_array(cmp_ctx_t *ctx, uint32_t size); 179 | 180 | /* Writes a map to the backend. */ 181 | bool cmp_write_map(cmp_ctx_t *ctx, uint32_t size); 182 | 183 | /* Writes an extended type to the backend */ 184 | bool cmp_write_ext(cmp_ctx_t *ctx, int8_t type, uint32_t size, 185 | const void *data); 186 | 187 | /* 188 | * Writes the extended type marker to the backend. This is useful if you want 189 | * to write the type's data in chunks instead of a single shot. 190 | */ 191 | bool cmp_write_ext_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size); 192 | 193 | /* Writes an object to the backend */ 194 | bool cmp_write_object(cmp_ctx_t *ctx, cmp_object_t *obj); 195 | 196 | /* Reads a signed integer that fits inside a signed char */ 197 | bool cmp_read_char(cmp_ctx_t *ctx, int8_t *c); 198 | 199 | /* Reads a signed integer that fits inside a signed short */ 200 | bool cmp_read_short(cmp_ctx_t *ctx, int16_t *s); 201 | 202 | /* Reads a signed integer that fits inside a signed int */ 203 | bool cmp_read_int(cmp_ctx_t *ctx, int32_t *i); 204 | 205 | /* Reads a signed integer that fits inside a signed long */ 206 | bool cmp_read_long(cmp_ctx_t *ctx, int64_t *d); 207 | 208 | /* Reads a signed integer */ 209 | bool cmp_read_sinteger(cmp_ctx_t *ctx, int64_t *d); 210 | 211 | /* Reads an unsigned integer that fits inside an unsigned char */ 212 | bool cmp_read_uchar(cmp_ctx_t *ctx, uint8_t *c); 213 | 214 | /* Reads an unsigned integer that fits inside an unsigned short */ 215 | bool cmp_read_ushort(cmp_ctx_t *ctx, uint16_t *s); 216 | 217 | /* Reads an unsigned integer that fits inside an unsigned int */ 218 | bool cmp_read_uint(cmp_ctx_t *ctx, uint32_t *i); 219 | 220 | /* Reads an unsigned integer that fits inside an unsigned long */ 221 | bool cmp_read_ulong(cmp_ctx_t *ctx, uint64_t *u); 222 | 223 | /* Reads an unsigned integer */ 224 | bool cmp_read_uinteger(cmp_ctx_t *ctx, uint64_t *u); 225 | 226 | /* Reads a single-precision float from the backend */ 227 | bool cmp_read_float(cmp_ctx_t *ctx, float *f); 228 | 229 | /* Reads a double-precision float from the backend */ 230 | bool cmp_read_double(cmp_ctx_t *ctx, double *d); 231 | 232 | /* "Reads" (more like "skips") a NULL value from the backend */ 233 | bool cmp_read_nil(cmp_ctx_t *ctx); 234 | 235 | /* Reads a boolean from the backend */ 236 | bool cmp_read_bool(cmp_ctx_t *ctx, bool *b); 237 | 238 | /* 239 | * Reads a boolean as an unsigned char from the backend; this is useful if your 240 | * application uses a different boolean type. 241 | */ 242 | bool cmp_read_bool_as_u8(cmp_ctx_t *ctx, uint8_t *b); 243 | 244 | /* Reads a string's size from the backend */ 245 | bool cmp_read_str_size(cmp_ctx_t *ctx, uint32_t *size); 246 | 247 | /* 248 | * Reads a string from the backend; according to the spec, the string's data 249 | * ought to be encoded using UTF-8, 250 | */ 251 | bool cmp_read_str(cmp_ctx_t *ctx, char *data, uint32_t *size); 252 | 253 | /* Reads the size of packed binary data from the backend */ 254 | bool cmp_read_bin_size(cmp_ctx_t *ctx, uint32_t *size); 255 | 256 | /* Reads packed binary data from the backend */ 257 | bool cmp_read_bin(cmp_ctx_t *ctx, void *data, uint32_t *size); 258 | 259 | /* Reads an array from the backend */ 260 | bool cmp_read_array(cmp_ctx_t *ctx, uint32_t *size); 261 | 262 | /* Reads a map from the backend */ 263 | bool cmp_read_map(cmp_ctx_t *ctx, uint32_t *size); 264 | 265 | /* Reads the extended type's marker from the backend */ 266 | bool cmp_read_ext_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size); 267 | 268 | /* Reads an extended type from the backend */ 269 | bool cmp_read_ext(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data); 270 | 271 | /* Reads an object from the backend */ 272 | bool cmp_read_object(cmp_ctx_t *ctx, cmp_object_t *obj); 273 | 274 | /* 275 | * ============================================================================ 276 | * === Specific API 277 | * ============================================================================ 278 | */ 279 | 280 | bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c); 281 | bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c); 282 | 283 | bool cmp_write_sfix(cmp_ctx_t *ctx, int8_t c); 284 | bool cmp_write_s8(cmp_ctx_t *ctx, int8_t c); 285 | bool cmp_write_s16(cmp_ctx_t *ctx, int16_t s); 286 | bool cmp_write_s32(cmp_ctx_t *ctx, int32_t i); 287 | bool cmp_write_s64(cmp_ctx_t *ctx, int64_t l); 288 | 289 | bool cmp_write_ufix(cmp_ctx_t *ctx, uint8_t c); 290 | bool cmp_write_u8(cmp_ctx_t *ctx, uint8_t c); 291 | bool cmp_write_u16(cmp_ctx_t *ctx, uint16_t s); 292 | bool cmp_write_u32(cmp_ctx_t *ctx, uint32_t i); 293 | bool cmp_write_u64(cmp_ctx_t *ctx, uint64_t l); 294 | 295 | bool cmp_write_fixstr_marker(cmp_ctx_t *ctx, uint8_t size); 296 | bool cmp_write_fixstr(cmp_ctx_t *ctx, const char *data, uint8_t size); 297 | bool cmp_write_str8_marker(cmp_ctx_t *ctx, uint8_t size); 298 | bool cmp_write_str8(cmp_ctx_t *ctx, const char *data, uint8_t size); 299 | bool cmp_write_str16_marker(cmp_ctx_t *ctx, uint16_t size); 300 | bool cmp_write_str16(cmp_ctx_t *ctx, const char *data, uint16_t size); 301 | bool cmp_write_str32_marker(cmp_ctx_t *ctx, uint32_t size); 302 | bool cmp_write_str32(cmp_ctx_t *ctx, const char *data, uint32_t size); 303 | 304 | bool cmp_write_bin8_marker(cmp_ctx_t *ctx, uint8_t size); 305 | bool cmp_write_bin8(cmp_ctx_t *ctx, const void *data, uint8_t size); 306 | bool cmp_write_bin16_marker(cmp_ctx_t *ctx, uint16_t size); 307 | bool cmp_write_bin16(cmp_ctx_t *ctx, const void *data, uint16_t size); 308 | bool cmp_write_bin32_marker(cmp_ctx_t *ctx, uint32_t size); 309 | bool cmp_write_bin32(cmp_ctx_t *ctx, const void *data, uint32_t size); 310 | 311 | bool cmp_write_fixarray(cmp_ctx_t *ctx, uint8_t size); 312 | bool cmp_write_array16(cmp_ctx_t *ctx, uint16_t size); 313 | bool cmp_write_array32(cmp_ctx_t *ctx, uint32_t size); 314 | 315 | bool cmp_write_fixmap(cmp_ctx_t *ctx, uint8_t size); 316 | bool cmp_write_map16(cmp_ctx_t *ctx, uint16_t size); 317 | bool cmp_write_map32(cmp_ctx_t *ctx, uint32_t size); 318 | 319 | bool cmp_write_fixext1_marker(cmp_ctx_t *ctx, int8_t type); 320 | bool cmp_write_fixext1(cmp_ctx_t *ctx, int8_t type, const void *data); 321 | bool cmp_write_fixext2_marker(cmp_ctx_t *ctx, int8_t type); 322 | bool cmp_write_fixext2(cmp_ctx_t *ctx, int8_t type, const void *data); 323 | bool cmp_write_fixext4_marker(cmp_ctx_t *ctx, int8_t type); 324 | bool cmp_write_fixext4(cmp_ctx_t *ctx, int8_t type, const void *data); 325 | bool cmp_write_fixext8_marker(cmp_ctx_t *ctx, int8_t type); 326 | bool cmp_write_fixext8(cmp_ctx_t *ctx, int8_t type, const void *data); 327 | bool cmp_write_fixext16_marker(cmp_ctx_t *ctx, int8_t type); 328 | bool cmp_write_fixext16(cmp_ctx_t *ctx, int8_t type, const void *data); 329 | 330 | bool cmp_write_ext8_marker(cmp_ctx_t *ctx, int8_t type, uint8_t size); 331 | bool cmp_write_ext8(cmp_ctx_t *ctx, int8_t type, uint8_t size, 332 | const void *data); 333 | bool cmp_write_ext16_marker(cmp_ctx_t *ctx, int8_t type, uint16_t size); 334 | bool cmp_write_ext16(cmp_ctx_t *ctx, int8_t type, uint16_t size, 335 | const void *data); 336 | bool cmp_write_ext32_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size); 337 | bool cmp_write_ext32(cmp_ctx_t *ctx, int8_t type, uint32_t size, 338 | const void *data); 339 | 340 | bool cmp_read_pfix(cmp_ctx_t *ctx, uint8_t *c); 341 | bool cmp_read_nfix(cmp_ctx_t *ctx, int8_t *c); 342 | 343 | bool cmp_read_sfix(cmp_ctx_t *ctx, int8_t *c); 344 | bool cmp_read_s8(cmp_ctx_t *ctx, int8_t *c); 345 | bool cmp_read_s16(cmp_ctx_t *ctx, int16_t *s); 346 | bool cmp_read_s32(cmp_ctx_t *ctx, int32_t *i); 347 | bool cmp_read_s64(cmp_ctx_t *ctx, int64_t *l); 348 | 349 | bool cmp_read_ufix(cmp_ctx_t *ctx, uint8_t *c); 350 | bool cmp_read_u8(cmp_ctx_t *ctx, uint8_t *c); 351 | bool cmp_read_u16(cmp_ctx_t *ctx, uint16_t *s); 352 | bool cmp_read_u32(cmp_ctx_t *ctx, uint32_t *i); 353 | bool cmp_read_u64(cmp_ctx_t *ctx, uint64_t *l); 354 | 355 | bool cmp_read_fixext1_marker(cmp_ctx_t *ctx, int8_t *type); 356 | bool cmp_read_fixext1(cmp_ctx_t *ctx, int8_t *type, void *data); 357 | bool cmp_read_fixext2_marker(cmp_ctx_t *ctx, int8_t *type); 358 | bool cmp_read_fixext2(cmp_ctx_t *ctx, int8_t *type, void *data); 359 | bool cmp_read_fixext4_marker(cmp_ctx_t *ctx, int8_t *type); 360 | bool cmp_read_fixext4(cmp_ctx_t *ctx, int8_t *type, void *data); 361 | bool cmp_read_fixext8_marker(cmp_ctx_t *ctx, int8_t *type); 362 | bool cmp_read_fixext8(cmp_ctx_t *ctx, int8_t *type, void *data); 363 | bool cmp_read_fixext16_marker(cmp_ctx_t *ctx, int8_t *type); 364 | bool cmp_read_fixext16(cmp_ctx_t *ctx, int8_t *type, void *data); 365 | 366 | bool cmp_read_ext8_marker(cmp_ctx_t *ctx, int8_t *type, uint8_t *size); 367 | bool cmp_read_ext8(cmp_ctx_t *ctx, int8_t *type, uint8_t *size, void *data); 368 | bool cmp_read_ext16_marker(cmp_ctx_t *ctx, int8_t *type, uint16_t *size); 369 | bool cmp_read_ext16(cmp_ctx_t *ctx, int8_t *type, uint16_t *size, void *data); 370 | bool cmp_read_ext32_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size); 371 | bool cmp_read_ext32(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data); 372 | 373 | /* 374 | * ============================================================================ 375 | * === Object API 376 | * ============================================================================ 377 | */ 378 | 379 | bool cmp_object_is_char(cmp_object_t *obj); 380 | bool cmp_object_is_short(cmp_object_t *obj); 381 | bool cmp_object_is_int(cmp_object_t *obj); 382 | bool cmp_object_is_long(cmp_object_t *obj); 383 | bool cmp_object_is_sinteger(cmp_object_t *obj); 384 | bool cmp_object_is_uchar(cmp_object_t *obj); 385 | bool cmp_object_is_ushort(cmp_object_t *obj); 386 | bool cmp_object_is_uint(cmp_object_t *obj); 387 | bool cmp_object_is_ulong(cmp_object_t *obj); 388 | bool cmp_object_is_uinteger(cmp_object_t *obj); 389 | bool cmp_object_is_float(cmp_object_t *obj); 390 | bool cmp_object_is_double(cmp_object_t *obj); 391 | bool cmp_object_is_nil(cmp_object_t *obj); 392 | bool cmp_object_is_bool(cmp_object_t *obj); 393 | bool cmp_object_is_str(cmp_object_t *obj); 394 | bool cmp_object_is_bin(cmp_object_t *obj); 395 | bool cmp_object_is_array(cmp_object_t *obj); 396 | bool cmp_object_is_map(cmp_object_t *obj); 397 | bool cmp_object_is_ext(cmp_object_t *obj); 398 | 399 | bool cmp_object_as_char(cmp_object_t *obj, int8_t *c); 400 | bool cmp_object_as_short(cmp_object_t *obj, int16_t *s); 401 | bool cmp_object_as_int(cmp_object_t *obj, int32_t *i); 402 | bool cmp_object_as_long(cmp_object_t *obj, int64_t *d); 403 | bool cmp_object_as_sinteger(cmp_object_t *obj, int64_t *d); 404 | bool cmp_object_as_uchar(cmp_object_t *obj, uint8_t *c); 405 | bool cmp_object_as_ushort(cmp_object_t *obj, uint16_t *s); 406 | bool cmp_object_as_uint(cmp_object_t *obj, uint32_t *i); 407 | bool cmp_object_as_ulong(cmp_object_t *obj, uint64_t *u); 408 | bool cmp_object_as_uinteger(cmp_object_t *obj, uint64_t *u); 409 | bool cmp_object_as_float(cmp_object_t *obj, float *f); 410 | bool cmp_object_as_double(cmp_object_t *obj, double *d); 411 | bool cmp_object_as_bool(cmp_object_t *obj, bool *b); 412 | bool cmp_object_as_str(cmp_object_t *obj, uint32_t *size); 413 | bool cmp_object_as_bin(cmp_object_t *obj, uint32_t *size); 414 | bool cmp_object_as_array(cmp_object_t *obj, uint32_t *size); 415 | bool cmp_object_as_map(cmp_object_t *obj, uint32_t *size); 416 | bool cmp_object_as_ext(cmp_object_t *obj, int8_t *type, uint32_t *size); 417 | 418 | #ifdef __cplusplus 419 | } /* extern "C" */ 420 | #endif 421 | 422 | #endif /* CMP_H__ */ 423 | 424 | /* vi: set et ts=2 sw=2: */ 425 | -------------------------------------------------------------------------------- /MPMessagePackTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MPMessagePackTests/MPMessagePackClientTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePack 3 | // 4 | // Created by Gabriel on 5/5/15. 5 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | @import MPMessagePack; 12 | 13 | @interface MPMessagePackClientTest : XCTestCase 14 | @property MPMessagePackClient *client; 15 | @property MPMessagePackServer *server; 16 | @end 17 | 18 | @implementation MPMessagePackClientTest 19 | 20 | - (void)testClientServer { 21 | MPMessagePackServer *server = [[MPMessagePackServer alloc] initWithOptions:MPMessagePackOptionsFramed]; 22 | 23 | server.requestHandler = ^(NSNumber *messageId, NSString *method, id params, MPRequestCompletion requestCompletion) { 24 | if ([method isEqualToString:@"test"]) { 25 | requestCompletion(nil, params); 26 | } 27 | }; 28 | 29 | UInt32 port = 41112; 30 | NSError *error = nil; 31 | 32 | if (![server openWithPort:port error:&error]) { 33 | XCTFail(@"Unable to start server: %@", error); 34 | } 35 | 36 | XCTestExpectation *openExpectation = [self expectationWithDescription:@"Open"]; 37 | MPMessagePackClient *client = [[MPMessagePackClient alloc] initWithName:@"Test" options:MPMessagePackOptionsFramed]; 38 | [client openWithHost:@"localhost" port:port completion:^(NSError *error) { 39 | XCTAssertNil(error); 40 | [openExpectation fulfill]; 41 | }]; 42 | 43 | [self waitForExpectationsWithTimeout:10.0 handler:nil]; 44 | 45 | XCTestExpectation *requestExpectation1 = [self expectationWithDescription:@"Request 1"]; 46 | NSLog(@"Sending request"); 47 | [client sendRequestWithMethod:@"test" params:@[@{@"arg": @(1)}] messageId:1 completion:^(NSError *error, id result) { 48 | NSLog(@"Result 1: %@", result); 49 | XCTAssertNotNil(result); 50 | [requestExpectation1 fulfill]; 51 | }]; 52 | 53 | [self waitForExpectationsWithTimeout:10.0 handler:nil]; 54 | 55 | XCTestExpectation *requestExpectation2 = [self expectationWithDescription:@"Request 2"]; 56 | dispatch_queue_t queue = dispatch_queue_create("testQueue", NULL); 57 | dispatch_async(queue, ^{ 58 | NSError *error2 = nil; 59 | NSArray *params2 = @[@{@"arg": @(2)}]; 60 | id result2 = [client sendRequestWithMethod:@"test" params:params2 messageId:2 timeout:2 error:&error2]; 61 | NSLog(@"Result 2: %@", result2); 62 | 63 | XCTAssertNil(error2); 64 | XCTAssertNotNil(result2); 65 | XCTAssertEqualObjects(params2, result2); 66 | [requestExpectation2 fulfill]; 67 | }); 68 | 69 | [self waitForExpectationsWithTimeout:10.0 handler:nil]; 70 | 71 | // Timeout 72 | XCTestExpectation *requestExpectation3 = [self expectationWithDescription:@"Request 3"]; 73 | dispatch_async(queue, ^{ 74 | NSError *error3 = nil; 75 | NSLog(@"Request 3"); 76 | id result3 = [client sendRequestWithMethod:@"testTimeout" params:@[] messageId:3 timeout:0.5 error:&error3]; 77 | XCTAssertNil(result3); 78 | XCTAssertNotNil(error3); 79 | XCTAssertEqual(error3.code, MPRPCErrorRequestTimeout); 80 | [requestExpectation3 fulfill]; 81 | }); 82 | 83 | [self waitForExpectationsWithTimeout:10.0 handler:nil]; 84 | 85 | // Cancel 86 | XCTestExpectation *requestExpectation4 = [self expectationWithDescription:@"Request 4"]; 87 | dispatch_async(queue, ^{ 88 | NSError *error4 = nil; 89 | NSLog(@"Request 4"); 90 | id result4 = [client sendRequestWithMethod:@"testCancel" params:@[] messageId:4 timeout:2 error:&error4]; 91 | XCTAssertNil(result4); 92 | XCTAssertNotNil(error4); 93 | XCTAssertEqual(error4.code, MPRPCErrorRequestCanceled); 94 | [requestExpectation4 fulfill]; 95 | }); 96 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 97 | BOOL canceled = [client cancelRequestWithMessageId:4]; 98 | NSLog(@"Canceled 4: %@", @(canceled)); 99 | XCTAssertTrue(canceled); 100 | }); 101 | 102 | [self waitForExpectationsWithTimeout:10.0 handler:nil]; 103 | 104 | // Cancel (completion) 105 | XCTestExpectation *requestExpectation5 = [self expectationWithDescription:@"Request 5"]; 106 | NSLog(@"Request 5"); 107 | [client sendRequestWithMethod:@"testCancelCompletion" params:@[] messageId:5 completion:^(NSError *error5, id result5) { 108 | XCTAssertNil(result5); 109 | XCTAssertNotNil(error5); 110 | XCTAssertEqual(error5.code, MPRPCErrorRequestCanceled); 111 | [requestExpectation5 fulfill]; 112 | }]; 113 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 114 | BOOL canceled = [client cancelRequestWithMessageId:5]; 115 | NSLog(@"Canceled 5: %@", @(canceled)); 116 | XCTAssertTrue(canceled); 117 | }); 118 | 119 | [self waitForExpectationsWithTimeout:10.0 handler:nil]; 120 | 121 | [client close]; 122 | [server close]; 123 | } 124 | 125 | //- (void)testLocalSocket:(dispatch_block_t)completion { 126 | // XCTestExpectation *expectation = [self expectationWithDescription:@"Echo"]; 127 | // MPMessagePackServer *server = [[MPMessagePackServer alloc] initWithOptions:MPMessagePackOptionsFramed]; 128 | // server.requestHandler = ^(NSString *method, id params, MPRequestCompletion completion) { 129 | // completion(nil, @{}); 130 | // }; 131 | // 132 | // NSString *socketName = [NSString stringWithFormat:@"/tmp/msgpacktest-%@.socket", @(arc4random())]; 133 | // NSError *error = nil; 134 | // if (![server openWithSocket:socketName error:&error]) { 135 | // XCTFail(@"Unable to start server: %@", error); 136 | // } 137 | // 138 | // MPMessagePackClient *client = [[MPMessagePackClient alloc] initWithName:@"Test" options:MPMessagePackOptionsFramed]; 139 | // if (![client openWithSocket:socketName error:&error]) { 140 | // XCTFail(@"Unable to connect to local socket"); 141 | // } 142 | // 143 | // NSLog(@"Sending request"); 144 | // [client sendRequestWithMethod:@"test" params:@{} completion:^(NSError *error, id result) { 145 | // NSLog(@"Result: %@", result); 146 | // [client close]; 147 | // [server close]; 148 | // [expectation fulfill]; 149 | // }]; 150 | // 151 | // [self waitForExpectationsWithTimeout:1.0 handler:nil]; 152 | //} 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /MPMessagePackTests/MPMessagePackTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPMessagePack 3 | // 4 | // Created by Gabriel on 5/5/15. 5 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | @import MPMessagePack; 12 | 13 | @interface MPMessagePackTest : XCTestCase 14 | @end 15 | 16 | @interface Unsupported : NSObject 17 | @end 18 | 19 | @implementation Unsupported 20 | @end 21 | 22 | @implementation MPMessagePackTest 23 | 24 | - (void)testEmpty { 25 | NSData *data1 = [MPMessagePackWriter writeObject:@[] error:nil]; 26 | NSArray *read1 = [MPMessagePackReader readData:data1 options:0 error:nil]; 27 | XCTAssertEqualObjects(@[], read1); 28 | } 29 | 30 | - (void)testPackUnpack { 31 | NSDictionary *obj = 32 | @{ 33 | @"z": @(0), 34 | @"p": @(1), 35 | @"n": @(-1), 36 | @"u8": @(UINT8_MAX), 37 | @"u16": @(UINT16_MAX), 38 | @"u32": @(UINT32_MAX), 39 | @"u64": @(UINT64_MAX), 40 | @"s8": @(INT8_MAX), 41 | @"s16": @(INT16_MAX), 42 | @"s32": @(INT32_MAX), 43 | @"s64": @(INT64_MAX), 44 | @"n8": @(INT8_MIN), 45 | @"n16": @(INT16_MIN), 46 | @"n32": @(INT32_MIN), 47 | @"n64": @(INT64_MIN), 48 | @"arrayFloatDouble": @[@(1.1f), @(2.1)], 49 | @"dataEmpty": [NSData data], 50 | @"dataShort": [NSData mp_dataFromHexString:@"ff"], 51 | @"data": [NSData mp_dataFromHexString:@"1c94d7de0000000344b409a81eafc66993cbe5fd885b5f6975a3f1f03c7338452116f7200a46412437007b65304528a314756bc701cec7b493cab44b3971b18c1137c1b1ba63d6a61119a5a2298b447d0cba89071320fc2c0f66b8f8056cd043d1ac6c0e983903355310e794ddd4a532729b3c2d65d71ebff32219f2f1759b3952d686149780c8e20f6bc912e5ba44701cdb165fcf5ab266c4295bf84796f9ac01c4e2ddf91ac7932d7ed71ee6187aa5fc3177b1abefdc29d8dec5098465b31f17511f65d38285f213724fcc98fe9cc6842c28d5"], 52 | @"null": [NSNull null], 53 | @"str": @"🍆😗😂😰", 54 | }; 55 | NSLog(@"Obj: %@", obj); 56 | 57 | NSData *data2 = [obj mp_messagePack]; 58 | NSDictionary *read2 = [MPMessagePackReader readData:data2 options:0 error:nil]; 59 | XCTAssertEqualObjects(obj, read2); 60 | 61 | NSData *data3 = [MPMessagePackWriter writeObject:obj options:MPMessagePackWriterOptionsSortDictionaryKeys error:nil]; 62 | NSError *error = nil; 63 | NSDictionary *read3 = [MPMessagePackReader readData:data3 options:0 error:&error]; 64 | XCTAssertEqualObjects(obj, read3); 65 | } 66 | 67 | - (void)testBool { 68 | NSArray *obj = @[@(YES), @YES, @(NO), @NO, [NSNumber numberWithBool:YES], [NSNumber numberWithBool:NO]]; 69 | NSData *data = [obj mp_messagePack]; 70 | NSArray *read = [MPMessagePackReader readData:data options:0 error:nil]; 71 | NSLog(@"Bools: %@", read); 72 | XCTAssertEqualObjects(obj, read); 73 | XCTAssertEqual(read[0], @(YES)); 74 | XCTAssertEqual(read[1], @YES); 75 | XCTAssertEqual(read[2], @(NO)); 76 | XCTAssertEqual(read[3], @NO); 77 | } 78 | 79 | - (void)testMultiple { 80 | NSError *error = nil; 81 | NSMutableData *data = [NSMutableData dataWithData:[MPMessagePackWriter writeObject:@(1) error:&error]]; 82 | [data appendData:[MPMessagePackWriter writeObject:@{@"a": @(1)} error:&error]]; 83 | [data appendData:[MPMessagePackWriter writeObject:@[@(1), @(2)] error:&error]]; 84 | 85 | NSMutableData *subdata = [[data subdataWithRange:NSMakeRange(0, data.length - 1)] mutableCopy]; 86 | MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:subdata]; 87 | id obj1 = [reader readObject:nil]; 88 | id obj2 = [reader readObject:nil]; 89 | 90 | XCTAssertEqualObjects(obj1, @(1)); 91 | XCTAssertEqualObjects(obj2, @{@"a": @(1)}); 92 | 93 | size_t index = reader.index; 94 | id obj3 = [reader readObject:&error]; 95 | XCTAssertNil(obj3); 96 | XCTAssertNotNil(error); 97 | XCTAssertEqual(error.code, (NSInteger)200); 98 | XCTAssertEqual(reader.index, (size_t)index); // Make sure error resets index 99 | 100 | [subdata appendData:[data subdataWithRange:NSMakeRange(data.length - 1, 1)]]; 101 | obj3 = [reader readObject:nil]; 102 | id expected3 = @[@(1), @(2)]; 103 | XCTAssertEqualObjects(obj3, expected3); 104 | } 105 | 106 | - (void)testRandomData { 107 | NSUInteger length = 1024 * 32; 108 | NSMutableData *data = [NSMutableData dataWithLength:length]; 109 | int result = SecRandomCopyBytes(kSecRandomDefault, length, [data mutableBytes]); 110 | XCTAssert(result == 0); 111 | 112 | NSError *error = nil; 113 | [MPMessagePackReader readData:data options:0 error:&error]; 114 | NSLog(@"Error: %@", error); 115 | // Just don't crash 116 | } 117 | 118 | - (void)testMap { 119 | NSDictionary *d = @{@"identify": @(YES)}; 120 | NSData *data = [MPMessagePackWriter writeObject:d options:0 error:nil]; 121 | NSLog(@"Data: %@", [data mp_hexString]); 122 | } 123 | 124 | - (void)testUnsignedLongLong { 125 | uint64_t n = 9223372036854775807; //18446744073709551615; 126 | NSNumber *numberIn = [NSNumber numberWithUnsignedLongLong:n]; 127 | 128 | NSData *data = [MPMessagePackWriter writeObject:numberIn options:0 error:nil]; 129 | NSNumber *numberOut = [MPMessagePackReader readData:data error:nil]; 130 | XCTAssertTrue([numberOut longLongValue] == n); 131 | } 132 | 133 | - (void)testLongLong { 134 | int64_t n = -9223372036854775807; 135 | NSNumber *numberIn = [NSNumber numberWithLongLong:n]; 136 | 137 | NSData *data = [MPMessagePackWriter writeObject:numberIn options:0 error:nil]; 138 | NSNumber *numberOut = [MPMessagePackReader readData:data error:nil]; 139 | XCTAssertTrue([numberOut longLongValue] == n); 140 | } 141 | 142 | - (void)testInvalidDictData { 143 | NSData *data = [NSData mp_dataFromHexString:@"deadbeef"]; 144 | NSError *error = nil; 145 | XCTAssertFalse({ [data mp_dict:&error]; }); 146 | XCTAssertNotNil(error); 147 | } 148 | 149 | - (void)testInvalidArrayData { 150 | NSData *data = [NSData mp_dataFromHexString:@"deadbeef"]; 151 | NSError *error = nil; 152 | XCTAssertFalse({ [data mp_array:&error]; }); 153 | XCTAssertNotNil(error); 154 | } 155 | 156 | - (void)testStress { 157 | NSDictionary *dict = @{@("a"): @(1)}; 158 | NSData *data = [MPMessagePackWriter writeObject:dict options:0 error:nil]; 159 | for (NSInteger i = 0; i < 1000; i++) { 160 | MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:data]; 161 | NSDictionary *dictRead = [reader readObject:nil]; 162 | XCTAssertEqualObjects(dict, dictRead); 163 | } 164 | } 165 | 166 | - (void)testHex { 167 | NSString *hex = @"940001b36b6579626173652e312e746573742e746573749182a973657373696f6e494402a46e616d65a774657374417267"; 168 | NSData *data = [NSData mp_dataFromHexString:hex]; 169 | MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:data]; 170 | NSError *error = nil; 171 | id obj; 172 | while ((obj = [reader readObject:&error])) { 173 | NSLog(@"%@", obj); 174 | } 175 | } 176 | 177 | - (void)testNilOnError { 178 | NSError *error = nil; 179 | NSData *data = [MPMessagePackWriter writeObject:[[Unsupported alloc] init] options:0 error:&error]; 180 | XCTAssertNotNil(error); 181 | XCTAssertNil(data); 182 | } 183 | 184 | // For testing a compatibility issue with go msgpack 185 | //- (void)testMessage { 186 | // NSString *s = @"lAAE2gAra2V5YmFzZS4xLmlkZW50aWZ5VWkuZmluaXNoU29jaWFsUHJvb2ZDaGVja5GDo2xjcoSmY2FjaGVkg61kaXNwbGF5TWFya3Vw2gAgW2NhY2hlZCAyMDE1LTAxLTIzIDE0OjU0OjM0IFBTVF2rcHJvb2ZTdGF0dXODpXCTlc2OgpXN0YXRlAaZzdGF0dXMBqXRpbWVzdGFtcM5UwtEqpGhpbnSEpmFwaVVybNoAKGh0dHBzOi8vY29pbmJhc2UuY29tL2JpdGNveW5lL3B1YmxpYy1rZXmpY2hlY2tUZXh02gVgCgpvd0Z0VW10TUhGVVk1UTN5RUNKcWtTRHFpTFl4cTl5Wm5kbVoyVGJxVW1pcFNFT1cybXBvMmQ0N2N3ZUd4eTdNCjdsSVJhcXBFTXCT0YUlLMEYydkFRSktRVUFhMHRkV3VKUWhFSVlBa0trWnBZdHRES1E2bzEwRkJRZEpiWUh5YmUKUHpmM3UrZWM3NXd2WDNtSXQwZWc1MmlNWVhQVWlsanVPVGlMUEZLdmR5WVVFY2dpRmhMNklpSWJyMStTYk03QQpTcDRpbTIyRW51QnBDTFdRUVNJU2FZQWhRL01DUkZEaUpTUUFWdFJCbmdXa1RrQmFRa05rV3F4dWhpcURvQlcvCklGdlVtdm93eWFKYS9SKzhmZjJEMGxJNklGQUNKbm1hQWhMUElvWVRXWkZua0k0VElBQnVvQlVyWnBpTFZiU1EKcWNoVzRxQ0dVSENCSlJ1Ny9WcmxETFdGbXCTDbkVhTEVhRG5FNlJBQ1VPQkpnSGtKMGtoaUVNVXhBSEk4UzJLSwoxbUVFRUUwSldrR0xTY3lSSWt1ekRJWWN5U01nRWZ0VWJiVmRnU3lzaTk5dmE1SE43bEQvTllOa20yQXBOR08zCkgxdGhucnQwQUNQVHYzUVRrczJpT2t1VlU0QVZxMnd4RTNwU1JRbzIyYzBtYWNDU0xOQ3lwSWJBYitiSkNqYkoKYmdURDZqaWdIZzJScDJaMFR3N3pnQ1JwcUFXU0lKRmFFU0FlU2l3cnFCbDRVaUJGaGdHMGpwSWdvMk1Sd0lJawppUkt0MVhFMGtJQWtjaUlrM0lIeXpSWkNUd0ZLTlFvelZXCTjFhT1lBYUxNcnF2bkFVcThvSHcvUFFBOC9YeS8zClJuZ0VQaEIyZjAzQTJkQy9sWWZld2cxanM5YmN4SlliRHMrQnp5K0hqVjdvUzkxU2JxZ1pNNjFXdHZuK2RMdGkKQXpuWmZ0WFdhRXdobzMvYzBSM3c1WkwvN3FNZmJhYXJub3NMR2doN1p1Yk9tYzhpUnNzY3hxQ1owZStYNjBxMgpKdGp6ZThGWDMrMHNTOFJWYThkTEEwNXNQeHppTU5UNFFkOWlQOFA3bC9sbis1d1RRZnp1M0ZPTnQ5N3JYVzZZCjZxN3VieDZMVW13cjM0dzhYUkY1YmJJSkgwNTZNaUx1eUtIdFVZOGtIOXcwLzN3anlKS2FrMXoxeVl0dFBzWjMKcXh5TXYvTmlUZG5jYUhWWDh6bnYrcWt6N2I5YmxPeUYvdGpFMDEybm5NMXpYNCs0Z3QrbzdMczlIc28wRExWbgpmamk4QWw5eStRVzNaeWtqVkdIRFVHdHU4WUozN2ZMYXZIZkpiL29XVFV6UmthVmpzZllMUHdjYlA5aWlDWi9OCkp3eWtSMWhuNHcvVEZ4ZjNGUS9mU052N3R1WGFrcXCTOMDRRbTF1TDIzNDI0ZzJxRHVnVDQ4cmMrZTNZMkdSUHUKZmVwa0YrWlB0T3k0Tk40ZVVuTFBheTZ5TjVLNXCTEYlpsUkErZmVpTG1tM2cvT1N4eEdacFYvaTUxbzdndXB1ZApINmM4bHI0aGZlUE5LMzhteHU4OW1iSTYyTlBJSG5Cd3lhZi9HcW84MzVxaTN6cThiTUE1ektDOTlJL1UyRWROCjIrcGZOWDlTdjZxTCtlV1Y4RDNMTXlmOWU2NitXTHVZbnRKUmZYZkJlSHhUMWEwaS9JNnJ2NjBpWittMXFLVDQKNkpDY3JPbTB1dkdCcHh5L1RqMGMydkY0c1cxL2Qvd1RZVlVvOW5xWFpzNTVaWUtpTnpySDlkRjU5bDJ1OHZMWApIK3daK3djPQqoaHVtYW5VcmzaAChodHRwczovL2NvaW5iYXNlLmNvbS9iaXRjb3luZS9wdWJsaWMta2V5qHJlbW90ZUlkqGJpdGNveW5lp3Byb29mSWQAq3Byb29mU3RhdHVzg6RkZXNjoKVzdGF0ZQGmc3RhdHVzAaJycIatZGlzcGxheU1hcmt1cKhiaXRjb3luZaNrZXmoY29pbmJhc2WlbXRpbWXOU9+3Q6lwcm9vZlR5cGUFpXNpZ0lk2gAgxtLIJ/1ykq42o1n+860Ec2/zc5AbPbA3r3c84T23+rmldmFsdWWoYml0Y295bmWpc2Vzc2lvbklkJQ=="; 187 | // 188 | // NSData *data = [[NSData alloc] initWithBase64EncodedString:s options:0]; 189 | // MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:data]; 190 | // id obj = [reader readObject:nil]; 191 | // NSLog(@"%@", obj); 192 | //} 193 | 194 | @end 195 | -------------------------------------------------------------------------------- /MPMessagePackTests/MPRPCProtocolTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPRPCProtocolTest.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 8/30/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @import MPMessagePack; 13 | 14 | @interface MPRPCProtocolTest : XCTestCase 15 | @end 16 | 17 | @implementation MPRPCProtocolTest 18 | 19 | - (void)testRequestFramed { 20 | NSError *error = nil; 21 | MPRPCProtocol *protocol = [[MPRPCProtocol alloc] init]; 22 | NSData *data = [protocol encodeRequestWithMethod:@"test" params:@[@{@"arg1": @"val1"}] messageId:1 options:0 framed:YES error:&error]; 23 | XCTAssertNil(error); 24 | XCTAssertNotNil(data); 25 | 26 | NSError *error2 = nil; 27 | NSArray *message = [protocol decodeMessage:data framed:YES error:&error2]; 28 | XCTAssertNil(error2); 29 | XCTAssertNotNil(message); 30 | XCTAssertEqualObjects(message[2], @"test"); 31 | } 32 | 33 | - (void)testResponseFramed { 34 | NSError *error = nil; 35 | MPRPCProtocol *protocol = [[MPRPCProtocol alloc] init]; 36 | NSData *data = [protocol encodeResponseWithResult:@(1) error:nil messageId:1 options:0 framed:YES encodeError:&error]; 37 | XCTAssertNil(error); 38 | XCTAssertNotNil(data); 39 | 40 | NSArray *message = [protocol decodeMessage:data framed:YES error:&error]; 41 | XCTAssertNil(error); 42 | XCTAssertNotNil(message); 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /MPMessagePackTests/MPXPCTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPXPCTest.m 3 | // MPMessagePack 4 | // 5 | // Created by Gabriel on 5/5/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED 13 | 14 | @import MPMessagePack; 15 | 16 | @interface MPXPCTest : XCTestCase 17 | @end 18 | 19 | @interface MPXPCTestService : MPXPCService 20 | @end 21 | 22 | @implementation MPXPCTestService 23 | 24 | - (void)handleRequestWithMethod:(NSString *)method params:(NSArray *)params messageId:(NSNumber *)messageId completion:(void (^)(NSError *error, id value))completion { 25 | if ([method isEqualToString:@"test"]) { 26 | completion(nil, @"ok"); 27 | } else { 28 | completion(MPMakeError(MPXPCErrorCodeUnknownRequest, @"Unkown request"), nil); 29 | } 30 | } 31 | 32 | @end 33 | 34 | @implementation MPXPCTest 35 | 36 | - (void)testXpc { 37 | XCTestExpectation *expectation = [self expectationWithDescription:@"Handle event"]; 38 | 39 | MPXPCTestService *service = [[MPXPCTestService alloc] init]; 40 | 41 | // TODO real test 42 | [service handleRequestWithMethod:@"test" params:nil messageId:@(1) completion:^(NSError *error, id value) { 43 | XCTAssertEqualObjects(@"ok", value); 44 | [expectation fulfill]; 45 | }]; 46 | 47 | [self waitForExpectationsWithTimeout:1.0 handler:nil]; 48 | } 49 | 50 | - (void)testInvalidConnection { 51 | XCTestExpectation *expectation = [self expectationWithDescription:@"Timeout"]; 52 | MPXPCClient *client = [[MPXPCClient alloc] initWithServiceName:@"Test" privileged:YES]; 53 | [client sendRequest:@"test" params:nil completion:^(NSError *error, id value) { 54 | XCTAssertEqual(error.code, MPXPCErrorCodeInvalidConnection); 55 | [expectation fulfill]; 56 | }]; 57 | 58 | [self waitForExpectationsWithTimeout:1.0 handler:nil]; 59 | } 60 | 61 | @end 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "GHODictionary", 6 | "repositoryURL": "https://github.com/gabriel/GHODictionary", 7 | "state": { 8 | "branch": null, 9 | "revision": "a67b9df6dfc6e6af3910d104fd9900e15dc15de9", 10 | "version": "1.2.0" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "MPMessagePack", 8 | platforms: [ 9 | .iOS(.v8), .tvOS(.v10), .macOS(.v10_10) 10 | ], 11 | products: [ 12 | .library( 13 | name: "MPMessagePack", 14 | targets: ["MPMessagePack"]), 15 | ], 16 | dependencies: [ 17 | .package(url: "https://github.com/gabriel/GHODictionary", from: "1.2.0") 18 | ], 19 | targets: [ 20 | .target( 21 | name: "MPMessagePack", 22 | dependencies: ["GHODictionary"], 23 | path: "MPMessagePack", 24 | exclude: ["MPMessagePack.h"], 25 | cSettings: [ 26 | .headerSearchPath("include"), 27 | .headerSearchPath("include/RPC"), 28 | .headerSearchPath("include/XPC"), 29 | ]), 30 | .testTarget( 31 | name: "MPMessagePackTests", 32 | dependencies: ["MPMessagePack"], 33 | path: "MPMessagePackTests", 34 | exclude: ["Info.plist"]), 35 | ] 36 | ) 37 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | 2 | target "MPMessagePack" do 3 | platform :osx, "10.8" 4 | pod "GHODictionary" 5 | end 6 | 7 | target "MPMessagePack iOS" do 8 | platform :ios, "8.0" 9 | pod "GHODictionary" 10 | end 11 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - GHODictionary (1.1.0) 3 | 4 | DEPENDENCIES: 5 | - GHODictionary 6 | 7 | SPEC CHECKSUMS: 8 | GHODictionary: 225e042596a4b3d5b66b2b24250086b2f95514af 9 | 10 | PODFILE CHECKSUM: 0bbb57744609ebc36ef1f6a60bab55905103bd35 11 | 12 | COCOAPODS: 1.3.1 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MPMessagePack 2 | 3 | [MessagePack](http://msgpack.org/) framework. 4 | 5 | MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON. But it's faster and smaller. 6 | 7 | # Included Open Source Libraries 8 | 9 | - [CMP](https://github.com/camgunz/cmp) is a C implementation of the MessagePack serialization format. 10 | 11 | # Swift Package Manager 12 | 13 | ```swift 14 | .package(url: "https://github.com/gabriel/MPMessagePack", from: "1.6.0"), 15 | ``` 16 | 17 | # Podfile 18 | 19 | ```ruby 20 | pod "MPMessagePack" 21 | ``` 22 | 23 | # Cartfile 24 | 25 | ``` 26 | github "gabriel/MPMessagePack" 27 | ``` 28 | 29 | # MPMessagePack 30 | 31 | ## Writing 32 | 33 | ```objc 34 | #import 35 | 36 | NSDictionary *dict = 37 | @{ 38 | @"n": @(32134123), 39 | @"bool": @(YES), 40 | @"array": @[@(1.1f), @(2.1)], 41 | @"body": [NSData data], 42 | }; 43 | 44 | NSData *data = [dict mp_messagePack]; 45 | ``` 46 | 47 | Or via ```MPMessagePackWriter```. 48 | 49 | ```objc 50 | NSError *error = nil; 51 | NSData *data = [MPMessagePackWriter writeObject:dict error:&error]; 52 | ``` 53 | 54 | If you need to use an ordered dictionary. 55 | 56 | ```objc 57 | MPOrderedDictionary *dict = [[MPOrderedDictionary alloc] init]; 58 | [dict addEntriesFromDictionary:@{@"c": @(1), @"b": @(2), @"a": @(3)}]; 59 | [dict sortKeysUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; 60 | NSData *data = [dict mp_messagePack]; 61 | ``` 62 | 63 | ## Reading 64 | 65 | ```objc 66 | id obj = [MPMessagePackReader readData:data error:&error]; 67 | ``` 68 | 69 | ```objc 70 | MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:data]; 71 | id obj1 = [reader read:&error]; // Read an object 72 | id obj2 = [reader read:&error]; // Read another object 73 | ``` 74 | 75 | # RPC 76 | 77 | See [msgpack-rpc](https://github.com/msgpack-rpc/msgpack-rpc). 78 | 79 | It also supports a framing option where it will prefix the rpc message with the number of bytes (as a msgpack'ed number). 80 | 81 | ## Client 82 | 83 | Request with completion block: 84 | 85 | ```objc 86 | MPMessagePackClient *client = [[MPMessagePackClient alloc] init]; 87 | [client openWithHost:@"localhost" port:93434 completion:^(NSError *error) { 88 | // If error we failed 89 | [client sendRequestWithMethod:@"test" params:@[@{@"arg": @(1)}] completion:^(NSError *error, id result) { 90 | // If error we failed 91 | // Otherwise the result 92 | }]; 93 | }]; 94 | ``` 95 | 96 | You can also request synchronously: 97 | 98 | ```objc 99 | NSError *error = nil; 100 | id result = [client sendRequestWithMethod:@"test" params:@[@{@"arg": @(1)}] messageId:3 timeout:5.0 error:&error]; 101 | // error.code == MPRPCErrorRequestTimeout on timeout 102 | ``` 103 | 104 | And cancel in progress requests: 105 | 106 | ```objc 107 | BOOL cancelled = [client cancelRequestWithMessageId:3]; 108 | // cancelled == YES, if the request was in progress and we cancelled it 109 | ``` 110 | 111 | ## Server 112 | 113 | ```objc 114 | MPMessagePackServer *server = [[MPMessagePackServer alloc] initWithOptions:MPMessagePackOptionsFramed]; 115 | 116 | server.requestHandler = ^(NSString *method, id params, MPRequestCompletion completion) { 117 | if ([method isEqualToString:@"echo"]) { 118 | completion(nil, params); 119 | } else { 120 | completion(@{@"error": {@"description": @"Method not found"}}, nil); 121 | } 122 | }; 123 | 124 | NSError *error = nil; 125 | if (![server openWithPort:93434 error:&error]) { 126 | // Failed to open 127 | } 128 | ``` 129 | 130 | ## Mantle Encoding 131 | 132 | If you are using Mantle to encode objects to JSON (and then msgpack), you can specify a coder for the MPMessagePackClient: 133 | 134 | ```objc 135 | @interface KBMantleCoder : NSObject 136 | @end 137 | 138 | @implementation KBMantleCoder 139 | - (NSDictionary *)encodeModel:(id)obj { 140 | return [obj conformsToProtocol:@protocol(MTLJSONSerializing)] ? [MTLJSONAdapter JSONDictionaryFromModel:obj] : obj; 141 | } 142 | @end 143 | ``` 144 | 145 | Then in the client: 146 | 147 | ```objc 148 | MPMessagePackClient *client = [[MPMessagePackClient alloc] init]; 149 | client.coder = [[KBMantleCoder alloc] init]; 150 | ``` 151 | 152 | ## XPC 153 | 154 | There is an experimental, but functional msgpack-rpc over XPC (see XPC directory). More details soon. 155 | -------------------------------------------------------------------------------- /msgpack.org.md: -------------------------------------------------------------------------------- 1 | 2 | # Install 3 | 4 | ``` 5 | pod "MPMessagePack" 6 | ``` 7 | 8 | ## Writing 9 | 10 | ```objc 11 | #import 12 | 13 | NSDictionary *dict = 14 | @{ 15 | @"n": @(32134123), 16 | @"bool": @(YES), 17 | @"array": @[@(1.1f), @(2.1)], 18 | @"body": [NSData data], 19 | }; 20 | 21 | NSData *data = [dict mp_messagePack]; 22 | ``` 23 | 24 | Or via ```MPMessagePackWriter```. 25 | 26 | ```objc 27 | NSError *error = nil; 28 | NSData *data = [MPMessagePackWriter writeObject:dict error:&error]; 29 | ``` 30 | 31 | If you need to use an ordered dictionary. 32 | 33 | ```objc 34 | MPOrderedDictionary *dict = [[MPOrderedDictionary alloc] init]; 35 | [dict addEntriesFromDictionary:@{@"c": @(1), @"b": @(2), @"a": @(3)}]; 36 | [dict sortKeysUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; 37 | [dict mp_messagePack]; 38 | ``` 39 | 40 | ## Reading 41 | 42 | ```objc 43 | id obj = [MPMessagePackReader readData:data error:&error]; 44 | ``` 45 | 46 | ```objc 47 | MPMessagePackReader *reader = [[MPMessagePackReader alloc] initWithData:data]; 48 | id obj1 = [reader read:&error]; // Read an object 49 | id obj2 = [reader read:&error]; // Read another object 50 | ``` 51 | 52 | --------------------------------------------------------------------------------