diff --git a/README.md b/README.md index 97c8070..25808b8 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ FEC enhanced KCP client session library for iOS/Android, compatible with [kcp-go 1. Optimized for ***Online Games***. 1. Stream based interface, you can easily switch from your TCP based protocol to libkcp or dualstack. 1. [FEC(Forward Error Correction)](https://en.wikipedia.org/wiki/Forward_error_correction) Support with [Reed-Solomon Codes](https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction) - +1. Add iOS/macOs Framework and Test target +1. MAS app https://itunes.apple.com/us/app/a-big-t/id1114040100?l=zh&ls=1&mt=12 support kcptun use this lib ## ***Usage*** libkcp has been designed as a ***Frame-Driven*** library, the main loop was supposed as: ``` @@ -42,7 +43,7 @@ $go run kcpserver.go compile and run libkcp(Best with CLion), and watch output. ## ***Caveats*** -1. Packet level encryption has not been implemented yet. +1. Packet level encryption use CommonCrypto, dose not pass test,need test and debug ## ***Troubleshooting*** 1. C++11 is required for compiling. diff --git a/fec.cpp b/fec.cpp index 47c3577..231d9b2 100644 --- a/fec.cpp +++ b/fec.cpp @@ -47,7 +47,7 @@ FEC::Decode(byte *data, size_t sz) { void FEC::MarkData(byte *data, uint16_t sz) { data = encode32u(data,this->next); - data = encode16u(data,typeData); + data = encode16u(data,kcptypeData); encode16u(data,static_cast(sz + 2)); // including size itself this->next++; } @@ -125,7 +125,7 @@ FEC::Input(fecPacket &pkt) { shardVec[seqid%totalShards] = rx[i].data; shardflag[seqid%totalShards] = true; numshard++; - if (rx[i].flag == typeData) { + if (rx[i].flag == kcptypeData) { numDataShard++; } if (numshard == 1) { diff --git a/fec.h b/fec.h index 361d4fe..f9a722f 100644 --- a/fec.h +++ b/fec.h @@ -12,8 +12,9 @@ #include "reedsolomon.h" const size_t fecHeaderSize = 6; +//const size_t cryptHeaderSize = 20;//nonce 16 crc 4 const size_t fecHeaderSizePlus2{fecHeaderSize + 2}; -const uint16_t typeData = 0xf1; +const uint16_t kcptypeData = 0xf1; const uint16_t typeFEC = 0xf2; const int fecExpire = 30000; diff --git a/iOSLib/libkcp/kcpOSX/Info.plist b/iOSLib/libkcp/kcpOSX/Info.plist new file mode 100644 index 0000000..7f86576 --- /dev/null +++ b/iOSLib/libkcp/kcpOSX/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2017 Kong XiangBo. All rights reserved. + NSPrincipalClass + + + diff --git a/iOSLib/libkcp/kcpOSX/kcp.h b/iOSLib/libkcp/kcpOSX/kcp.h new file mode 100644 index 0000000..a3d9065 --- /dev/null +++ b/iOSLib/libkcp/kcpOSX/kcp.h @@ -0,0 +1,21 @@ +// +// kcpOSX.h +// kcpOSX +// +// Created by 孔祥波 on 02/06/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import + +//! Project version number for kcpOSX. +FOUNDATION_EXPORT double kcpOSXVersionNumber; + +//! Project version string for kcpOSX. +FOUNDATION_EXPORT const unsigned char kcpOSXVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + +#import +#import diff --git a/iOSLib/libkcp/kcptest/AppDelegate.h b/iOSLib/libkcp/kcptest/AppDelegate.h new file mode 100644 index 0000000..343adf7 --- /dev/null +++ b/iOSLib/libkcp/kcptest/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// kcptest +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/iOSLib/libkcp/kcptest/AppDelegate.mm b/iOSLib/libkcp/kcptest/AppDelegate.mm new file mode 100644 index 0000000..2f07d95 --- /dev/null +++ b/iOSLib/libkcp/kcptest/AppDelegate.mm @@ -0,0 +1,51 @@ +// +// AppDelegate.m +// kcptest +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + + +@end diff --git a/iOSLib/libkcp/kcptest/Assets.xcassets/AppIcon.appiconset/Contents.json b/iOSLib/libkcp/kcptest/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..118c98f --- /dev/null +++ b/iOSLib/libkcp/kcptest/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/iOSLib/libkcp/kcptest/Base.lproj/LaunchScreen.storyboard b/iOSLib/libkcp/kcptest/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..fdf3f97 --- /dev/null +++ b/iOSLib/libkcp/kcptest/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSLib/libkcp/kcptest/Base.lproj/Main.storyboard b/iOSLib/libkcp/kcptest/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f1f2b3b --- /dev/null +++ b/iOSLib/libkcp/kcptest/Base.lproj/Main.storyboard @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSLib/libkcp/kcptest/Info.plist b/iOSLib/libkcp/kcptest/Info.plist new file mode 100644 index 0000000..38e98af --- /dev/null +++ b/iOSLib/libkcp/kcptest/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/iOSLib/libkcp/kcptest/ViewController.h b/iOSLib/libkcp/kcptest/ViewController.h new file mode 100644 index 0000000..6b77835 --- /dev/null +++ b/iOSLib/libkcp/kcptest/ViewController.h @@ -0,0 +1,16 @@ +// +// ViewController.h +// kcptest +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import +#import "kcp.h" +//#include "sodium.h" +@interface ViewController : UIViewController + + +@end + diff --git a/iOSLib/libkcp/kcptest/ViewController.mm b/iOSLib/libkcp/kcptest/ViewController.mm new file mode 100644 index 0000000..ebae1d5 --- /dev/null +++ b/iOSLib/libkcp/kcptest/ViewController.mm @@ -0,0 +1,178 @@ +// +// ViewController.m +// kcptest +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import "ViewController.h" +#import "BlockCrypt.h" +#import "Crypt.h" +@interface ViewController () +@property (weak, nonatomic) IBOutlet UITextField *addr; +@property (weak, nonatomic) IBOutlet UITextField *port; +@property (strong,nonatomic) SFKcpTun *tun; +@property (strong,nonatomic) dispatch_queue_t dispatchqueue; +@property (nonatomic,strong) NSTimer *t; + +@end + +@implementation ViewController +{ + NSDate *last; + dispatch_source_t dispatchSource; + dispatch_queue_t tqueue ; + dispatch_queue_t socketqueue ; + +} +- (void)viewDidLoad { + + [super viewDidLoad]; +// self.dispatchqueue = dispatch_queue_create("test", NULL); +// [self testCrypto]; +// [self testSodium]; + tqueue = dispatch_queue_create("test.yarshure", DISPATCH_QUEUE_SERIAL); + // Do any additional setup after loading the view, typically from a nib. +} +-(IBAction)tThread:(id)sender{ + last = [NSDate date]; + [NSThread detachNewThreadWithBlock:^{ + for (; ; ) { + NSDate *n = [NSDate date]; + //NSLog(@"timer come %0.6f",[n timeIntervalSinceDate:last]); + last = n; + [NSThread sleepForTimeInterval:0.003]; + } + }]; +} +-(IBAction)testTimer:(id)sender{ + + // Create a dispatch source that'll act as a timer on the concurrent queue + // You'll need to store this somewhere so you can suspend and remove it later on + NSLog(@"go"); + dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,tqueue); + last = [NSDate date]; + // Setup params for creation of a recurring timer + double interval = 3.0; + dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0); + uint64_t intervalTime = (int64_t)(interval * NSEC_PER_MSEC); + dispatch_source_set_timer(dispatchSource, startTime, intervalTime, 0); + + // Attach the block you want to run on the timer fire + dispatch_source_set_event_handler(dispatchSource, ^{ + // Your code here + NSDate *n = [NSDate date]; + //NSLog(@"timer come %0.6f",[n timeIntervalSinceDate:last]); + last = n; + }); + + + dispatch_resume(dispatchSource); + + + + +} +-(void)testCrypto2 +{ + +} +- (void)testSodium +{ + //sodium_init(); + //NSData *s = [@"0123456789ABCDEF0123456789ABCDEF" dataUsingEncoding:NSUTF8StringEncoding]; +} +- (void)testCrypto{ + NSData *s = [@"0123456789ABCDEF0123456789ABCDEF" dataUsingEncoding:NSUTF8StringEncoding]; + NSLog(@"org %@",s); + Crypt *block = [[Crypt alloc] initWithKey:s crypto:@"aes"]; //blockWith(s.bytes, "aes"); + size_t outlen = 0; + [block encrypt:s] ;//encrypt(s.bytes, 32, &outlen); + //NSData *outData = [NSData dataWithBytes:outbuffer length:outlen]; + NSLog(@"en %@",s); + + [block decrypt:s]; + NSLog(@"de %@",s); + [self testB]; + +} +-(void)testB{ + NSData *s = [@"0123456789ABCDEF0123456789ABCDEF" dataUsingEncoding:NSUTF8StringEncoding]; + NSLog(@"org %@",s); + BlockCrypt *block = BlockCrypt::blockWith(s.bytes, "aes"); //blockWith(s.bytes, "aes"); + size_t outlen = 0; + block->encrypt((void *)s.bytes, 32, &outlen); + NSData *outData = [NSData dataWithBytes:s.bytes length:outlen]; + NSLog(@"en %@",s); + + block->decrypt((void*)s.bytes, s.length, &outlen); + + NSLog(@"en %@",s); + free(block); + +} +- (IBAction)go:(id)sender { + //kcptest(, ); + const char *addr = [self.addr.text UTF8String]; + NSString *port= self.port.text; + if (self.dispatchqueue == nil) { + self.dispatchqueue = dispatch_queue_create("tun", nil); + } + if (self.tun == nil) { + TunConfig *c = [[TunConfig alloc] init]; + c.dataShards = 2; + c.parityShards = 2; + c.iptos = 46; + c.crypt = @"none"; + c.key = [@"" dataUsingEncoding:NSUTF8StringEncoding]; + self.tun = [[SFKcpTun alloc] initWithConfig:c ipaddr:self.addr.text port:port queue:self.dispatchqueue]; + [self.tun startWith:^(SFKcpTun * _Nonnull tun) { + printf("connected"); + } recv:^(SFKcpTun * _Nonnull tun, NSData * _Nonnull d) { + NSLog(@"recv:%@",d); + } disConnect:^(SFKcpTun * _Nonnull tun) { + printf("disConnect"); + }]; + } + +} +- (IBAction)send:(id)sender { + + if ( self.tun == nil ){ + return; + } + [self sendtest]; + //self.t = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(sendtest) userInfo:nil repeats:true]; +} +- (IBAction)stop:(id)sender { + [self.t invalidate]; +} +-(void)sendtest +{ + for (int i = 0; i < 1; i++) { + NSString *msg = [NSString stringWithFormat:@"message %d",i]; + NSData *d = [msg dataUsingEncoding:NSUTF8StringEncoding]; + //char *ptr = (char *)BlockCrypt::ramdonBytes(40960); + //NSData *d = [NSData dataWithBytes:(void*)ptr length:40960]; + //free(ptr); + [self.tun input:d]; + } +} +-(IBAction)shutdown:(id)sender +{ + if (self.tun != nil){ + [self.tun shutdownUDPSession]; + self.tun = nil; + } +} +-(void)didRecevied:(NSData*)data{ + NSLog(@"recv: %@",data); +} +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + +@end diff --git a/iOSLib/libkcp/kcptest/main.m b/iOSLib/libkcp/kcptest/main.m new file mode 100644 index 0000000..d34d434 --- /dev/null +++ b/iOSLib/libkcp/kcptest/main.m @@ -0,0 +1,16 @@ +// +// main.m +// kcptest +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/iOSLib/libkcp/libkcp.xcodeproj/project.pbxproj b/iOSLib/libkcp/libkcp.xcodeproj/project.pbxproj new file mode 100644 index 0000000..8e5c52c --- /dev/null +++ b/iOSLib/libkcp/libkcp.xcodeproj/project.pbxproj @@ -0,0 +1,844 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 692AE3261EB2EE59006A4B9D /* kcp.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3241EB2EE59006A4B9D /* kcp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 692AE32D1EB2EE98006A4B9D /* fec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE32C1EB2EE98006A4B9D /* fec.cpp */; }; + 692AE32F1EB2EEB0006A4B9D /* ikcp.c in Sources */ = {isa = PBXBuildFile; fileRef = 692AE32E1EB2EEB0006A4B9D /* ikcp.c */; }; + 692AE3311EB2EEBD006A4B9D /* sess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3301EB2EEBD006A4B9D /* sess.cpp */; }; + 692AE3331EB2EEE6006A4B9D /* sess.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3321EB2EEE6006A4B9D /* sess.h */; }; + 692AE3361EB2EEEF006A4B9D /* reedsolomon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3341EB2EEEF006A4B9D /* reedsolomon.cpp */; }; + 692AE3371EB2EEEF006A4B9D /* reedsolomon.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3351EB2EEEF006A4B9D /* reedsolomon.h */; }; + 692AE33A1EB2EEF9006A4B9D /* matrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3381EB2EEF9006A4B9D /* matrix.cpp */; }; + 692AE33B1EB2EEF9006A4B9D /* matrix.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3391EB2EEF9006A4B9D /* matrix.h */; }; + 692AE33E1EB2EF0B006A4B9D /* inversion_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE33C1EB2EF0B006A4B9D /* inversion_tree.cpp */; }; + 692AE33F1EB2EF0B006A4B9D /* inversion_tree.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE33D1EB2EF0B006A4B9D /* inversion_tree.h */; }; + 692AE3411EB2EF11006A4B9D /* ikcp.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3401EB2EF11006A4B9D /* ikcp.h */; }; + 692AE3481EB2EF1C006A4B9D /* fec.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3421EB2EF1C006A4B9D /* fec.h */; }; + 692AE3491EB2EF1C006A4B9D /* galois_noasm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3431EB2EF1C006A4B9D /* galois_noasm.cpp */; }; + 692AE34A1EB2EF1C006A4B9D /* galois_noasm.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3441EB2EF1C006A4B9D /* galois_noasm.h */; }; + 692AE34B1EB2EF1C006A4B9D /* galois_table.c in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3451EB2EF1C006A4B9D /* galois_table.c */; }; + 692AE34C1EB2EF1C006A4B9D /* galois.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3461EB2EF1C006A4B9D /* galois.cpp */; }; + 692AE34D1EB2EF1C006A4B9D /* galois.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3471EB2EF1C006A4B9D /* galois.h */; }; + 692AE34F1EB2EF25006A4B9D /* encoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE34E1EB2EF25006A4B9D /* encoding.h */; }; + 692AE3581EB2EF83006A4B9D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3571EB2EF83006A4B9D /* main.m */; }; + 692AE35B1EB2EF83006A4B9D /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 692AE35A1EB2EF83006A4B9D /* AppDelegate.mm */; }; + 692AE35E1EB2EF83006A4B9D /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 692AE35D1EB2EF83006A4B9D /* ViewController.mm */; }; + 692AE3611EB2EF83006A4B9D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 692AE35F1EB2EF83006A4B9D /* Main.storyboard */; }; + 692AE3631EB2EF83006A4B9D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 692AE3621EB2EF83006A4B9D /* Assets.xcassets */; }; + 692AE3661EB2EF83006A4B9D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 692AE3641EB2EF83006A4B9D /* LaunchScreen.storyboard */; }; + 692AE3711EB2F191006A4B9D /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 692AE3701EB2F191006A4B9D /* libc++.tbd */; }; + 695165F51EBB2663008DCF66 /* BlockCrypt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 695165F31EBB2663008DCF66 /* BlockCrypt.cpp */; }; + 695165F61EBB2663008DCF66 /* BlockCrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 695165F41EBB2663008DCF66 /* BlockCrypt.h */; }; + 695165F91EBB32D2008DCF66 /* Crypt.mm in Sources */ = {isa = PBXBuildFile; fileRef = 695165F81EBB32D2008DCF66 /* Crypt.mm */; }; + 6959B7471EBB7DEC00B0BC58 /* CRC32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6959B7451EBB7DEC00B0BC58 /* CRC32.cpp */; }; + 6959B7481EBB7DEC00B0BC58 /* CRC32.h in Headers */ = {isa = PBXBuildFile; fileRef = 6959B7461EBB7DEC00B0BC58 /* CRC32.h */; }; + 6959B74A1EBB8B0C00B0BC58 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6959B7491EBB8B0C00B0BC58 /* Security.framework */; }; + 69639BD91EE1AAC100893D18 /* kcp.h in Headers */ = {isa = PBXBuildFile; fileRef = 69639BD71EE1AAC100893D18 /* kcp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69639BDD1EE1AAD700893D18 /* SFKcpTun.h in Headers */ = {isa = PBXBuildFile; fileRef = 69FFC69E1EB30985008A030D /* SFKcpTun.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69639BDE1EE1AAE000893D18 /* SFKcpTun.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69FFC69F1EB30985008A030D /* SFKcpTun.mm */; }; + 69639BDF1EE1AAE400893D18 /* TunConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 69FFC6A31EB309E8008A030D /* TunConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69639BE01EE1AAEC00893D18 /* TunConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 69FFC6A41EB309E8008A030D /* TunConfig.m */; }; + 69639BE11EE1AAF500893D18 /* encoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE34E1EB2EF25006A4B9D /* encoding.h */; }; + 69639BE21EE1AAF900893D18 /* galois_noasm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3431EB2EF1C006A4B9D /* galois_noasm.cpp */; }; + 69639BE31EE1AAFD00893D18 /* galois_noasm.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3441EB2EF1C006A4B9D /* galois_noasm.h */; }; + 69639BE41EE1AB0100893D18 /* galois_table.c in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3451EB2EF1C006A4B9D /* galois_table.c */; }; + 69639BE51EE1AB0900893D18 /* galois.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3461EB2EF1C006A4B9D /* galois.cpp */; }; + 69639BE61EE1AB0D00893D18 /* galois.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3471EB2EF1C006A4B9D /* galois.h */; }; + 69639BE71EE1AB1300893D18 /* inversion_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE33C1EB2EF0B006A4B9D /* inversion_tree.cpp */; }; + 69639BE81EE1AB1700893D18 /* inversion_tree.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE33D1EB2EF0B006A4B9D /* inversion_tree.h */; }; + 69639BE91EE1AB1B00893D18 /* matrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3381EB2EEF9006A4B9D /* matrix.cpp */; }; + 69639BEA1EE1AB1E00893D18 /* matrix.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3391EB2EEF9006A4B9D /* matrix.h */; }; + 69639BEB1EE1AB2200893D18 /* reedsolomon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3341EB2EEEF006A4B9D /* reedsolomon.cpp */; }; + 69639BEC1EE1AB2800893D18 /* reedsolomon.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3351EB2EEEF006A4B9D /* reedsolomon.h */; }; + 69639BED1EE1AB2D00893D18 /* sess.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3321EB2EEE6006A4B9D /* sess.h */; }; + 69639BEE1EE1AB3100893D18 /* sess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE3301EB2EEBD006A4B9D /* sess.cpp */; }; + 69639BEF1EE1AB3500893D18 /* ikcp.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3401EB2EF11006A4B9D /* ikcp.h */; }; + 69639BF01EE1AB3900893D18 /* ikcp.c in Sources */ = {isa = PBXBuildFile; fileRef = 692AE32E1EB2EEB0006A4B9D /* ikcp.c */; }; + 69639BF21EE1AB4C00893D18 /* fec.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AE3421EB2EF1C006A4B9D /* fec.h */; }; + 69639BF31EE1AB5000893D18 /* fec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AE32C1EB2EE98006A4B9D /* fec.cpp */; }; + 69639BF41EE1AB5500893D18 /* BlockCrypt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 695165F31EBB2663008DCF66 /* BlockCrypt.cpp */; }; + 69639BF51EE1AB5900893D18 /* BlockCrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 695165F41EBB2663008DCF66 /* BlockCrypt.h */; }; + 69639BF61EE1AB5D00893D18 /* CRC32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6959B7451EBB7DEC00B0BC58 /* CRC32.cpp */; }; + 69639BF71EE1AB6100893D18 /* CRC32.h in Headers */ = {isa = PBXBuildFile; fileRef = 6959B7461EBB7DEC00B0BC58 /* CRC32.h */; }; + 69639BF91EE1ABA200893D18 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69639BF81EE1ABA200893D18 /* Security.framework */; }; + 69B917C221785876004CC106 /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69B917C121785876004CC106 /* Network.framework */; }; + 69B917C42178587F004CC106 /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69B917C32178587F004CC106 /* Network.framework */; }; + 69C757811EB2F96D00139321 /* kcp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692AE3211EB2EE59006A4B9D /* kcp.framework */; }; + 69C757821EB2F96D00139321 /* kcp.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 692AE3211EB2EE59006A4B9D /* kcp.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69FFC6A01EB30985008A030D /* SFKcpTun.h in Headers */ = {isa = PBXBuildFile; fileRef = 69FFC69E1EB30985008A030D /* SFKcpTun.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69FFC6A11EB30985008A030D /* SFKcpTun.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69FFC69F1EB30985008A030D /* SFKcpTun.mm */; }; + 69FFC6A51EB309E8008A030D /* TunConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 69FFC6A31EB309E8008A030D /* TunConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69FFC6A61EB309E8008A030D /* TunConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 69FFC6A41EB309E8008A030D /* TunConfig.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 69C757831EB2F96D00139321 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 692AE3181EB2EE59006A4B9D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 692AE3201EB2EE59006A4B9D; + remoteInfo = libkcp; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 69C757851EB2F96D00139321 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 69C757821EB2F96D00139321 /* kcp.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 692AE3211EB2EE59006A4B9D /* kcp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = kcp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 692AE3241EB2EE59006A4B9D /* kcp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kcp.h; sourceTree = ""; }; + 692AE3251EB2EE59006A4B9D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 692AE32C1EB2EE98006A4B9D /* fec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fec.cpp; path = ../../../fec.cpp; sourceTree = ""; }; + 692AE32E1EB2EEB0006A4B9D /* ikcp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ikcp.c; path = ../../../ikcp.c; sourceTree = ""; }; + 692AE3301EB2EEBD006A4B9D /* sess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sess.cpp; path = ../../../sess.cpp; sourceTree = ""; }; + 692AE3321EB2EEE6006A4B9D /* sess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sess.h; path = ../../../sess.h; sourceTree = ""; }; + 692AE3341EB2EEEF006A4B9D /* reedsolomon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = reedsolomon.cpp; path = ../../../reedsolomon.cpp; sourceTree = ""; }; + 692AE3351EB2EEEF006A4B9D /* reedsolomon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = reedsolomon.h; path = ../../../reedsolomon.h; sourceTree = ""; }; + 692AE3381EB2EEF9006A4B9D /* matrix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = matrix.cpp; path = ../../../matrix.cpp; sourceTree = ""; }; + 692AE3391EB2EEF9006A4B9D /* matrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = matrix.h; path = ../../../matrix.h; sourceTree = ""; }; + 692AE33C1EB2EF0B006A4B9D /* inversion_tree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = inversion_tree.cpp; path = ../../../inversion_tree.cpp; sourceTree = ""; }; + 692AE33D1EB2EF0B006A4B9D /* inversion_tree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = inversion_tree.h; path = ../../../inversion_tree.h; sourceTree = ""; }; + 692AE3401EB2EF11006A4B9D /* ikcp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ikcp.h; path = ../../../ikcp.h; sourceTree = ""; }; + 692AE3421EB2EF1C006A4B9D /* fec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fec.h; path = ../../../fec.h; sourceTree = ""; }; + 692AE3431EB2EF1C006A4B9D /* galois_noasm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = galois_noasm.cpp; path = ../../../galois_noasm.cpp; sourceTree = ""; }; + 692AE3441EB2EF1C006A4B9D /* galois_noasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = galois_noasm.h; path = ../../../galois_noasm.h; sourceTree = ""; }; + 692AE3451EB2EF1C006A4B9D /* galois_table.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = galois_table.c; path = ../../../galois_table.c; sourceTree = ""; }; + 692AE3461EB2EF1C006A4B9D /* galois.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = galois.cpp; path = ../../../galois.cpp; sourceTree = ""; }; + 692AE3471EB2EF1C006A4B9D /* galois.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = galois.h; path = ../../../galois.h; sourceTree = ""; }; + 692AE34E1EB2EF25006A4B9D /* encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = encoding.h; path = ../../../encoding.h; sourceTree = ""; }; + 692AE3541EB2EF83006A4B9D /* kcptest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = kcptest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 692AE3571EB2EF83006A4B9D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 692AE3591EB2EF83006A4B9D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 692AE35A1EB2EF83006A4B9D /* AppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AppDelegate.mm; sourceTree = ""; }; + 692AE35C1EB2EF83006A4B9D /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 692AE35D1EB2EF83006A4B9D /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; + 692AE3601EB2EF83006A4B9D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 692AE3621EB2EF83006A4B9D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 692AE3651EB2EF83006A4B9D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 692AE3671EB2EF83006A4B9D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 692AE36B1EB2EF91006A4B9D /* kcp_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = kcp_test.cpp; path = ../../../kcp_test.cpp; sourceTree = ""; }; + 692AE3701EB2F191006A4B9D /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; + 695165F31EBB2663008DCF66 /* BlockCrypt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockCrypt.cpp; sourceTree = ""; }; + 695165F41EBB2663008DCF66 /* BlockCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockCrypt.h; sourceTree = ""; }; + 695165F71EBB32D2008DCF66 /* Crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Crypt.h; path = libkcp/Crypt.h; sourceTree = SOURCE_ROOT; }; + 695165F81EBB32D2008DCF66 /* Crypt.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Crypt.mm; path = libkcp/Crypt.mm; sourceTree = SOURCE_ROOT; }; + 6959B7451EBB7DEC00B0BC58 /* CRC32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CRC32.cpp; sourceTree = ""; }; + 6959B7461EBB7DEC00B0BC58 /* CRC32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CRC32.h; sourceTree = ""; }; + 6959B7491EBB8B0C00B0BC58 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 69639BD51EE1AAC100893D18 /* kcp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = kcp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 69639BD71EE1AAC100893D18 /* kcp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kcp.h; sourceTree = ""; }; + 69639BD81EE1AAC100893D18 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 69639BF81EE1ABA200893D18 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 698D5CFB1F0A0E6B008C2335 /* Sodium.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sodium.framework; sourceTree = ""; }; + 69B917C121785876004CC106 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; }; + 69B917C32178587F004CC106 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Network.framework; sourceTree = DEVELOPER_DIR; }; + 69FFC69E1EB30985008A030D /* SFKcpTun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SFKcpTun.h; path = libkcp/SFKcpTun.h; sourceTree = SOURCE_ROOT; }; + 69FFC69F1EB30985008A030D /* SFKcpTun.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SFKcpTun.mm; path = libkcp/SFKcpTun.mm; sourceTree = SOURCE_ROOT; }; + 69FFC6A31EB309E8008A030D /* TunConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TunConfig.h; path = libkcp/TunConfig.h; sourceTree = ""; }; + 69FFC6A41EB309E8008A030D /* TunConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TunConfig.m; path = libkcp/TunConfig.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 692AE31D1EB2EE59006A4B9D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 69B917C221785876004CC106 /* Network.framework in Frameworks */, + 6959B74A1EBB8B0C00B0BC58 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 692AE3511EB2EF83006A4B9D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 692AE3711EB2F191006A4B9D /* libc++.tbd in Frameworks */, + 69C757811EB2F96D00139321 /* kcp.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69639BD11EE1AAC100893D18 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 69B917C42178587F004CC106 /* Network.framework in Frameworks */, + 69639BF91EE1ABA200893D18 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 692AE3171EB2EE59006A4B9D = { + isa = PBXGroup; + children = ( + 69FFC6A21EB3098C008A030D /* tun */, + 692AE3231EB2EE59006A4B9D /* libkcp */, + 692AE3551EB2EF83006A4B9D /* kcptest */, + 69639BD61EE1AAC100893D18 /* kcpOSX */, + 692AE3221EB2EE59006A4B9D /* Products */, + 692AE36F1EB2F191006A4B9D /* Frameworks */, + ); + sourceTree = ""; + }; + 692AE3221EB2EE59006A4B9D /* Products */ = { + isa = PBXGroup; + children = ( + 692AE3211EB2EE59006A4B9D /* kcp.framework */, + 692AE3541EB2EF83006A4B9D /* kcptest.app */, + 69639BD51EE1AAC100893D18 /* kcp.framework */, + ); + name = Products; + sourceTree = ""; + }; + 692AE3231EB2EE59006A4B9D /* libkcp */ = { + isa = PBXGroup; + children = ( + 692AE34E1EB2EF25006A4B9D /* encoding.h */, + 692AE3431EB2EF1C006A4B9D /* galois_noasm.cpp */, + 692AE3441EB2EF1C006A4B9D /* galois_noasm.h */, + 692AE3451EB2EF1C006A4B9D /* galois_table.c */, + 692AE3461EB2EF1C006A4B9D /* galois.cpp */, + 692AE3471EB2EF1C006A4B9D /* galois.h */, + 692AE33C1EB2EF0B006A4B9D /* inversion_tree.cpp */, + 692AE33D1EB2EF0B006A4B9D /* inversion_tree.h */, + 692AE3381EB2EEF9006A4B9D /* matrix.cpp */, + 692AE3391EB2EEF9006A4B9D /* matrix.h */, + 692AE3341EB2EEEF006A4B9D /* reedsolomon.cpp */, + 692AE3351EB2EEEF006A4B9D /* reedsolomon.h */, + 692AE3321EB2EEE6006A4B9D /* sess.h */, + 692AE3301EB2EEBD006A4B9D /* sess.cpp */, + 692AE3401EB2EF11006A4B9D /* ikcp.h */, + 692AE32E1EB2EEB0006A4B9D /* ikcp.c */, + 692AE3241EB2EE59006A4B9D /* kcp.h */, + 692AE3421EB2EF1C006A4B9D /* fec.h */, + 692AE32C1EB2EE98006A4B9D /* fec.cpp */, + 692AE3251EB2EE59006A4B9D /* Info.plist */, + 695165F31EBB2663008DCF66 /* BlockCrypt.cpp */, + 695165F41EBB2663008DCF66 /* BlockCrypt.h */, + 6959B7451EBB7DEC00B0BC58 /* CRC32.cpp */, + 6959B7461EBB7DEC00B0BC58 /* CRC32.h */, + ); + path = libkcp; + sourceTree = ""; + }; + 692AE3551EB2EF83006A4B9D /* kcptest */ = { + isa = PBXGroup; + children = ( + 695165F71EBB32D2008DCF66 /* Crypt.h */, + 695165F81EBB32D2008DCF66 /* Crypt.mm */, + 692AE36B1EB2EF91006A4B9D /* kcp_test.cpp */, + 692AE3591EB2EF83006A4B9D /* AppDelegate.h */, + 692AE35A1EB2EF83006A4B9D /* AppDelegate.mm */, + 692AE35C1EB2EF83006A4B9D /* ViewController.h */, + 692AE35D1EB2EF83006A4B9D /* ViewController.mm */, + 692AE35F1EB2EF83006A4B9D /* Main.storyboard */, + 692AE3621EB2EF83006A4B9D /* Assets.xcassets */, + 692AE3641EB2EF83006A4B9D /* LaunchScreen.storyboard */, + 692AE3671EB2EF83006A4B9D /* Info.plist */, + 692AE3561EB2EF83006A4B9D /* Supporting Files */, + ); + path = kcptest; + sourceTree = ""; + }; + 692AE3561EB2EF83006A4B9D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 692AE3571EB2EF83006A4B9D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 692AE36F1EB2F191006A4B9D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 69B917C121785876004CC106 /* Network.framework */, + 69B917C32178587F004CC106 /* Network.framework */, + 698D5CFB1F0A0E6B008C2335 /* Sodium.framework */, + 69639BF81EE1ABA200893D18 /* Security.framework */, + 6959B7491EBB8B0C00B0BC58 /* Security.framework */, + 692AE3701EB2F191006A4B9D /* libc++.tbd */, + ); + name = Frameworks; + sourceTree = ""; + }; + 69639BD61EE1AAC100893D18 /* kcpOSX */ = { + isa = PBXGroup; + children = ( + 69639BD71EE1AAC100893D18 /* kcp.h */, + 69639BD81EE1AAC100893D18 /* Info.plist */, + ); + path = kcpOSX; + sourceTree = ""; + }; + 69FFC6A21EB3098C008A030D /* tun */ = { + isa = PBXGroup; + children = ( + 69FFC69E1EB30985008A030D /* SFKcpTun.h */, + 69FFC69F1EB30985008A030D /* SFKcpTun.mm */, + 69FFC6A31EB309E8008A030D /* TunConfig.h */, + 69FFC6A41EB309E8008A030D /* TunConfig.m */, + ); + name = tun; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 692AE31E1EB2EE59006A4B9D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 692AE34A1EB2EF1C006A4B9D /* galois_noasm.h in Headers */, + 69FFC6A01EB30985008A030D /* SFKcpTun.h in Headers */, + 69FFC6A51EB309E8008A030D /* TunConfig.h in Headers */, + 692AE34F1EB2EF25006A4B9D /* encoding.h in Headers */, + 6959B7481EBB7DEC00B0BC58 /* CRC32.h in Headers */, + 692AE33F1EB2EF0B006A4B9D /* inversion_tree.h in Headers */, + 692AE3371EB2EEEF006A4B9D /* reedsolomon.h in Headers */, + 692AE3481EB2EF1C006A4B9D /* fec.h in Headers */, + 692AE3331EB2EEE6006A4B9D /* sess.h in Headers */, + 692AE3261EB2EE59006A4B9D /* kcp.h in Headers */, + 692AE33B1EB2EEF9006A4B9D /* matrix.h in Headers */, + 692AE3411EB2EF11006A4B9D /* ikcp.h in Headers */, + 692AE34D1EB2EF1C006A4B9D /* galois.h in Headers */, + 695165F61EBB2663008DCF66 /* BlockCrypt.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69639BD21EE1AAC100893D18 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 69639BED1EE1AB2D00893D18 /* sess.h in Headers */, + 69639BEC1EE1AB2800893D18 /* reedsolomon.h in Headers */, + 69639BDD1EE1AAD700893D18 /* SFKcpTun.h in Headers */, + 69639BD91EE1AAC100893D18 /* kcp.h in Headers */, + 69639BF21EE1AB4C00893D18 /* fec.h in Headers */, + 69639BDF1EE1AAE400893D18 /* TunConfig.h in Headers */, + 69639BEA1EE1AB1E00893D18 /* matrix.h in Headers */, + 69639BE11EE1AAF500893D18 /* encoding.h in Headers */, + 69639BE81EE1AB1700893D18 /* inversion_tree.h in Headers */, + 69639BE31EE1AAFD00893D18 /* galois_noasm.h in Headers */, + 69639BE61EE1AB0D00893D18 /* galois.h in Headers */, + 69639BF71EE1AB6100893D18 /* CRC32.h in Headers */, + 69639BEF1EE1AB3500893D18 /* ikcp.h in Headers */, + 69639BF51EE1AB5900893D18 /* BlockCrypt.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 692AE3201EB2EE59006A4B9D /* kcp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 692AE3291EB2EE59006A4B9D /* Build configuration list for PBXNativeTarget "kcp" */; + buildPhases = ( + 692AE31C1EB2EE59006A4B9D /* Sources */, + 692AE31D1EB2EE59006A4B9D /* Frameworks */, + 692AE31E1EB2EE59006A4B9D /* Headers */, + 692AE31F1EB2EE59006A4B9D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = kcp; + productName = libkcp; + productReference = 692AE3211EB2EE59006A4B9D /* kcp.framework */; + productType = "com.apple.product-type.framework"; + }; + 692AE3531EB2EF83006A4B9D /* kcptest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 692AE3681EB2EF83006A4B9D /* Build configuration list for PBXNativeTarget "kcptest" */; + buildPhases = ( + 692AE3501EB2EF83006A4B9D /* Sources */, + 692AE3511EB2EF83006A4B9D /* Frameworks */, + 692AE3521EB2EF83006A4B9D /* Resources */, + 69C757851EB2F96D00139321 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 69C757841EB2F96D00139321 /* PBXTargetDependency */, + ); + name = kcptest; + productName = kcptest; + productReference = 692AE3541EB2EF83006A4B9D /* kcptest.app */; + productType = "com.apple.product-type.application"; + }; + 69639BD41EE1AAC100893D18 /* kcpOSX */ = { + isa = PBXNativeTarget; + buildConfigurationList = 69639BDC1EE1AAC100893D18 /* Build configuration list for PBXNativeTarget "kcpOSX" */; + buildPhases = ( + 69639BD01EE1AAC100893D18 /* Sources */, + 69639BD11EE1AAC100893D18 /* Frameworks */, + 69639BD21EE1AAC100893D18 /* Headers */, + 69639BD31EE1AAC100893D18 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = kcpOSX; + productName = kcpOSX; + productReference = 69639BD51EE1AAC100893D18 /* kcp.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 692AE3181EB2EE59006A4B9D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1000; + ORGANIZATIONNAME = "Kong XiangBo"; + TargetAttributes = { + 692AE3201EB2EE59006A4B9D = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = 745WQDK4L7; + LastSwiftMigration = 0830; + ProvisioningStyle = Automatic; + }; + 692AE3531EB2EF83006A4B9D = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = 745WQDK4L7; + ProvisioningStyle = Automatic; + }; + 69639BD41EE1AAC100893D18 = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = 745WQDK4L7; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 692AE31B1EB2EE59006A4B9D /* Build configuration list for PBXProject "libkcp" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 692AE3171EB2EE59006A4B9D; + productRefGroup = 692AE3221EB2EE59006A4B9D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 692AE3201EB2EE59006A4B9D /* kcp */, + 692AE3531EB2EF83006A4B9D /* kcptest */, + 69639BD41EE1AAC100893D18 /* kcpOSX */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 692AE31F1EB2EE59006A4B9D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 692AE3521EB2EF83006A4B9D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 692AE3661EB2EF83006A4B9D /* LaunchScreen.storyboard in Resources */, + 692AE3631EB2EF83006A4B9D /* Assets.xcassets in Resources */, + 692AE3611EB2EF83006A4B9D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69639BD31EE1AAC100893D18 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 692AE31C1EB2EE59006A4B9D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 692AE3491EB2EF1C006A4B9D /* galois_noasm.cpp in Sources */, + 692AE33A1EB2EEF9006A4B9D /* matrix.cpp in Sources */, + 692AE33E1EB2EF0B006A4B9D /* inversion_tree.cpp in Sources */, + 6959B7471EBB7DEC00B0BC58 /* CRC32.cpp in Sources */, + 69FFC6A61EB309E8008A030D /* TunConfig.m in Sources */, + 692AE32F1EB2EEB0006A4B9D /* ikcp.c in Sources */, + 692AE34C1EB2EF1C006A4B9D /* galois.cpp in Sources */, + 692AE32D1EB2EE98006A4B9D /* fec.cpp in Sources */, + 692AE34B1EB2EF1C006A4B9D /* galois_table.c in Sources */, + 69FFC6A11EB30985008A030D /* SFKcpTun.mm in Sources */, + 695165F51EBB2663008DCF66 /* BlockCrypt.cpp in Sources */, + 692AE3311EB2EEBD006A4B9D /* sess.cpp in Sources */, + 692AE3361EB2EEEF006A4B9D /* reedsolomon.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 692AE3501EB2EF83006A4B9D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 692AE35E1EB2EF83006A4B9D /* ViewController.mm in Sources */, + 692AE35B1EB2EF83006A4B9D /* AppDelegate.mm in Sources */, + 695165F91EBB32D2008DCF66 /* Crypt.mm in Sources */, + 692AE3581EB2EF83006A4B9D /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69639BD01EE1AAC100893D18 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 69639BF41EE1AB5500893D18 /* BlockCrypt.cpp in Sources */, + 69639BF01EE1AB3900893D18 /* ikcp.c in Sources */, + 69639BDE1EE1AAE000893D18 /* SFKcpTun.mm in Sources */, + 69639BE71EE1AB1300893D18 /* inversion_tree.cpp in Sources */, + 69639BEE1EE1AB3100893D18 /* sess.cpp in Sources */, + 69639BE41EE1AB0100893D18 /* galois_table.c in Sources */, + 69639BE91EE1AB1B00893D18 /* matrix.cpp in Sources */, + 69639BE21EE1AAF900893D18 /* galois_noasm.cpp in Sources */, + 69639BE51EE1AB0900893D18 /* galois.cpp in Sources */, + 69639BF31EE1AB5000893D18 /* fec.cpp in Sources */, + 69639BF61EE1AB5D00893D18 /* CRC32.cpp in Sources */, + 69639BE01EE1AAEC00893D18 /* TunConfig.m in Sources */, + 69639BEB1EE1AB2200893D18 /* reedsolomon.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 69C757841EB2F96D00139321 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 692AE3201EB2EE59006A4B9D /* kcp */; + targetProxy = 69C757831EB2F96D00139321 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 692AE35F1EB2EF83006A4B9D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 692AE3601EB2EF83006A4B9D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 692AE3641EB2EF83006A4B9D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 692AE3651EB2EF83006A4B9D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 692AE3271EB2EE59006A4B9D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 692AE3281EB2EE59006A4B9D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 692AE32A1EB2EE59006A4B9D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + INFOPLIST_FILE = libkcp/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.squash.kcp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include"; + }; + name = Debug; + }; + 692AE32B1EB2EE59006A4B9D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + INFOPLIST_FILE = libkcp/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.squash.kcp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include"; + }; + name = Release; + }; + 692AE3691EB2EF83006A4B9D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 745WQDK4L7; + INFOPLIST_FILE = kcptest/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.squash.kcptest; + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include"; + }; + name = Debug; + }; + 692AE36A1EB2EF83006A4B9D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 745WQDK4L7; + INFOPLIST_FILE = kcptest/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.squash.kcptest; + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include"; + }; + name = Release; + }; + 69639BDA1EE1AAC100893D18 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = kcpOSX/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = com.squash.kcp; + PRODUCT_MODULE_NAME = kcp; + PRODUCT_NAME = kcp; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 69639BDB1EE1AAC100893D18 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = kcpOSX/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = com.squash.kcp; + PRODUCT_MODULE_NAME = kcp; + PRODUCT_NAME = kcp; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 692AE31B1EB2EE59006A4B9D /* Build configuration list for PBXProject "libkcp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 692AE3271EB2EE59006A4B9D /* Debug */, + 692AE3281EB2EE59006A4B9D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 692AE3291EB2EE59006A4B9D /* Build configuration list for PBXNativeTarget "kcp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 692AE32A1EB2EE59006A4B9D /* Debug */, + 692AE32B1EB2EE59006A4B9D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 692AE3681EB2EF83006A4B9D /* Build configuration list for PBXNativeTarget "kcptest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 692AE3691EB2EF83006A4B9D /* Debug */, + 692AE36A1EB2EF83006A4B9D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 69639BDC1EE1AAC100893D18 /* Build configuration list for PBXNativeTarget "kcpOSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 69639BDA1EE1AAC100893D18 /* Debug */, + 69639BDB1EE1AAC100893D18 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 692AE3181EB2EE59006A4B9D /* Project object */; +} diff --git a/iOSLib/libkcp/libkcp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/iOSLib/libkcp/libkcp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..909aebb --- /dev/null +++ b/iOSLib/libkcp/libkcp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/iOSLib/libkcp/libkcp.xcodeproj/xcshareddata/xcschemes/kcpOSX.xcscheme b/iOSLib/libkcp/libkcp.xcodeproj/xcshareddata/xcschemes/kcpOSX.xcscheme new file mode 100644 index 0000000..35813c0 --- /dev/null +++ b/iOSLib/libkcp/libkcp.xcodeproj/xcshareddata/xcschemes/kcpOSX.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSLib/libkcp/libkcp.xcodeproj/xcshareddata/xcschemes/libkcp.xcscheme b/iOSLib/libkcp/libkcp.xcodeproj/xcshareddata/xcschemes/libkcp.xcscheme new file mode 100644 index 0000000..cba17c6 --- /dev/null +++ b/iOSLib/libkcp/libkcp.xcodeproj/xcshareddata/xcschemes/libkcp.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSLib/libkcp/libkcp.xcodeproj/xcuserdata/yarshure.xcuserdatad/xcschemes/kcptest.xcscheme b/iOSLib/libkcp/libkcp.xcodeproj/xcuserdata/yarshure.xcuserdatad/xcschemes/kcptest.xcscheme new file mode 100644 index 0000000..ce43b9a --- /dev/null +++ b/iOSLib/libkcp/libkcp.xcodeproj/xcuserdata/yarshure.xcuserdatad/xcschemes/kcptest.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSLib/libkcp/libkcp/BlockCrypt.cpp b/iOSLib/libkcp/libkcp/BlockCrypt.cpp new file mode 100644 index 0000000..a1685a4 --- /dev/null +++ b/iOSLib/libkcp/libkcp/BlockCrypt.cpp @@ -0,0 +1,118 @@ +// +// BlockCrypt.cpp +// libkcp +// +// Created by 孔祥波 on 04/05/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#include "BlockCrypt.h" +#import +#include +const uint8_t iv[] = {167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107}; +BlockCrypt* +BlockCrypt::blockWith(const void* key,const char* crypto){ + if (strcmp(crypto, "none") == 0) { + return NULL; + } + BlockCrypt *block = new (BlockCrypt); + + + const void *ivPtr = iv; + size_t keyLen = 0; + if (strcmp(crypto,"aes") == 0){ + keyLen = 32; + }else if (strcmp(crypto,"aes-128") == 0){ + keyLen = 16; + }else { + keyLen = 24; + } + + + CCCryptorStatus st = CCCryptorCreateWithMode( + kCCEncrypt, + kCCModeCFB, + kCCAlgorithmAES, + ccNoPadding, + ivPtr, key, keyLen, + NULL, 0, 0, 0, + &(block->send_ctx)); + + if (st != kCCSuccess){ + printf("send_ctx create error\n"); + } + st = CCCryptorCreateWithMode( + kCCDecrypt, + kCCModeCFB, + kCCAlgorithmAES, + ccNoPadding, + ivPtr, key, keyLen, + NULL, 0, 0, 0, + &(block->recv_ctx)); + if (st != kCCSuccess){ + printf("recv_ctx create error \n"); + } + + return block; + +} +// output udp packet +void +BlockCrypt::encrypt(void *buffer, size_t length,size_t *outlen) +{ + if (send_ctx == NULL ){ + return; + } + size_t len = length + kCCBlockSizeAES128; + + void *dataOut = malloc(len); + + CCCryptorStatus st = CCCryptorUpdate(send_ctx, buffer, length, dataOut, len, outlen); + if (st != kCCSuccess){ + printf("encrypt data error"); + + }else { + memcpy(buffer, dataOut, *outlen); + + } + free(dataOut); +} +void +BlockCrypt::decrypt(void *buffer, size_t length,size_t *outlen) +{ + size_t len = length + kCCBlockSizeAES128; + if (recv_ctx == NULL ){ + return; + } + void *dataOut = malloc(len); + + CCCryptorStatus st = CCCryptorUpdate(recv_ctx, buffer, length, dataOut, len, outlen); + if (st != kCCSuccess){ + printf("encrypt data error"); + + }else { + memcpy(buffer, dataOut, *outlen); + } + free(dataOut); +} +void +BlockCrypt::Destroy(BlockCrypt *block) { + if (block->send_ctx != NULL) { + CCCryptorRelease(block->send_ctx); + } + if (block->recv_ctx != NULL) { + CCCryptorRelease(block->recv_ctx); + } + delete block; +} +uint8_t * +BlockCrypt::ramdonBytes(size_t len){ + + uint8_t *ptr = (uint8_t *)malloc(len); + // Gen random bytes + if (SecRandomCopyBytes(kSecRandomDefault, len, (uint8_t *)ptr) == 0){ + return ptr; + } + free(ptr); + return nil; +} diff --git a/iOSLib/libkcp/libkcp/BlockCrypt.h b/iOSLib/libkcp/libkcp/BlockCrypt.h new file mode 100644 index 0000000..c311fd1 --- /dev/null +++ b/iOSLib/libkcp/libkcp/BlockCrypt.h @@ -0,0 +1,32 @@ +// +// BlockCrypt.hpp +// libkcp +// +// Created by 孔祥波 on 04/05/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#ifndef BlockCrypt_hpp +#define BlockCrypt_hpp +#import + +#include +//#include "sodium.h" +class BlockCrypt { +private: + CCCryptorRef send_ctx; + CCCryptorRef recv_ctx; +public: + static BlockCrypt* blockWith(const void* key,const char* crypt); + // output udp packet + void encrypt(void *buffer, size_t length,size_t *outlen); + void decrypt(void *buffer, size_t length,size_t *outlen); + static uint8_t *ramdonBytes(size_t len); +private: + BlockCrypt() = default; + + ~BlockCrypt() = default; + static void Destroy(BlockCrypt *block); +}; + +#endif /* BlockCrypt_hpp */ diff --git a/iOSLib/libkcp/libkcp/CRC32.cpp b/iOSLib/libkcp/libkcp/CRC32.cpp new file mode 100644 index 0000000..4f984cd --- /dev/null +++ b/iOSLib/libkcp/libkcp/CRC32.cpp @@ -0,0 +1,111 @@ +// +// CRC32.c +// libkcp +// +// Created by 孔祥波 on 04/05/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#include "CRC32.h" + +int32_t crc32(uint8_t *bytes, size_t len) +{ + uint32_t *table = (uint32_t *)malloc(sizeof(uint32_t) * 256); + uint32_t crc = 0xffffffff; + + uint8_t *ptr = bytes; + for (uint32_t i=0; i<256; i++) { + table[i] = i; + for (int j=0; j<8; j++) { + if (table[i] & 1) { + table[i] = (table[i] >>= 1) ^ 0xedb88320; + } else { + table[i] >>= 1; + } + } + } + + for (int i=0; i< len; i++) { + crc = (crc >> 8) ^ table[(crc & 0xff) ^ *ptr]; + ptr++; + } + crc ^= 0xffffffff; + + free(table); + return crc; +} +unsigned int cal_crc(unsigned char *ptr, unsigned char len) { + unsigned char i; + unsigned int crc=0; + while(len--!=0) { + for(i=0x80; i!=0; i/=2) { + if((crc&0x8000)!=0) {crc*=2; crc^=0x1021;} /* 余式 CRC 乘以 2 再求 CRC */ + else crc*=2; + if((*ptr&i)!=0) crc^=0x1021; /* 再加上本位的 CRC */ + } + ptr++; + } + return(crc); +} +#include +//#include + +static uint32_t crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +uint32_t +crc32_kr(uint32_t crc, const uint8_t *buf, size_t size) +{ + const uint8_t *p; + + p = buf; + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} diff --git a/iOSLib/libkcp/libkcp/CRC32.h b/iOSLib/libkcp/libkcp/CRC32.h new file mode 100644 index 0000000..b07dcd3 --- /dev/null +++ b/iOSLib/libkcp/libkcp/CRC32.h @@ -0,0 +1,19 @@ +// +// CRC32.h +// libkcp +// +// Created by 孔祥波 on 04/05/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#ifndef CRC32_h +#define CRC32_h + +#include +#include +int32_t crc32(uint8_t *bytes, size_t len); + +unsigned int cal_crc(unsigned char *ptr, unsigned char len); +uint32_t +crc32_kr(uint32_t crc, const uint8_t *buf, size_t size); +#endif /* CRC32_h */ diff --git a/iOSLib/libkcp/libkcp/Crypt.h b/iOSLib/libkcp/libkcp/Crypt.h new file mode 100644 index 0000000..a4bc479 --- /dev/null +++ b/iOSLib/libkcp/libkcp/Crypt.h @@ -0,0 +1,18 @@ +// +// BlockCrypt.h +// libkcp +// +// Created by 孔祥波 on 04/05/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import +#import +@interface Crypt : NSObject +@property (strong,nonatomic) NSData *initialVector; +@property (nonatomic) CCCryptorRef send_ctx; +@property (nonatomic) CCCryptorRef recv_ctx; +-(instancetype)initWithKey:(NSData*)key crypto:(NSString*)crypto; +-(NSData*)encrypt:(NSData*)data; +-(NSData*)decrypt:(NSData*)data; +@end diff --git a/iOSLib/libkcp/libkcp/Crypt.mm b/iOSLib/libkcp/libkcp/Crypt.mm new file mode 100644 index 0000000..35f2d96 --- /dev/null +++ b/iOSLib/libkcp/libkcp/Crypt.mm @@ -0,0 +1,78 @@ +// +// BlockCrypt.m +// libkcp +// +// Created by 孔祥波 on 04/05/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import "Crypt.h" + +static NSString *saltxor = @"sH3CIVoF#rWLtJo6"; +@implementation Crypt +-(instancetype)initWithKey:(NSData*)key crypto:(NSString*)crypto{ + if (self = [super init]){ + uint8_t iv[] = {167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107}; + self.initialVector = [NSData dataWithBytes:iv length:16]; + const void *ckey = key.bytes; + const void *ivPtr = iv; + size_t keyLen = 0; + if ([crypto isEqualToString:@"aes"]){ + keyLen = 32; + }else if ([crypto isEqualToString:@"aes-128"]){ + keyLen = 16; + }else { + keyLen = 24; + } + CCCryptorRef s = self.send_ctx; + CCCryptorStatus st = CCCryptorCreate(kCCEncrypt, kCCAlgorithmDES, 0, ckey, keyLen, ivPtr, &s); + if (st != kCCSuccess){ + NSLog(@"send_ctx create error"); + } + CCCryptorRef r = self.send_ctx; + st = CCCryptorCreate(kCCDecrypt, kCCAlgorithmDES, 0, ckey, keyLen, ivPtr, &r); + if (st != kCCSuccess){ + NSLog(@"recv_ctx create error"); + } + } + return self; +} +-(NSData*)encrypt:(NSData*)data +{ + const void *dataIn = data.bytes; + size_t len = data.length + kCCBlockSizeAES128; + int outLen = 0; + NSMutableData *o = [NSMutableData dataWithLength:len]; + void *dataOut =(void *) o.bytes; + CCCryptorStatus st = CCCryptorUpdate(self.send_ctx, dataIn, data.length, dataOut, len, &len); + if (st != kCCSuccess){ + NSLog(@"encrypt data error"); + return nil; + }else { + o.length = outLen; + return o; + } +} +-(NSData*)decrypt:(NSData*)data +{ + const void *dataIn = data.bytes; + size_t len = data.length + kCCBlockSizeAES128; + int outLen = 0; + NSMutableData *o = [NSMutableData dataWithLength:len]; + void *dataOut =(void *) o.bytes; + CCCryptorStatus st = CCCryptorUpdate(self.recv_ctx, dataIn, data.length, dataOut, len, &len); + if (st != kCCSuccess){ + NSLog(@"encrypt data error"); + return nil; + }else { + o.length = outLen; + return o; + } +} +-(void)dealloc +{ + CCCryptorRelease(self.send_ctx); + CCCryptorRelease(self.recv_ctx); + //super.dealloc(); +} +@end diff --git a/iOSLib/libkcp/libkcp/Info.plist b/iOSLib/libkcp/libkcp/Info.plist new file mode 100644 index 0000000..fbe1e6b --- /dev/null +++ b/iOSLib/libkcp/libkcp/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/iOSLib/libkcp/libkcp/SFKcpTun.h b/iOSLib/libkcp/libkcp/SFKcpTun.h new file mode 100644 index 0000000..3f9d43c --- /dev/null +++ b/iOSLib/libkcp/libkcp/SFKcpTun.h @@ -0,0 +1,40 @@ +// +// SFKcpTun.h +// libkcp +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import +#import "TunConfig.h" +@class SFKcpTun; + +typedef void (^tunConnected)(SFKcpTun * _Nonnull tun); +typedef void (^tunDisConnected)(SFKcpTun * _Nonnull tun); +typedef void (^tundidFoundError)(SFKcpTun * _Nonnull tun ,NSError * _Nonnull e); +typedef void (^didRecvdata)(SFKcpTun * _Nonnull tun,NSData * _Nonnull d); + +@interface SFKcpTun : NSObject + @property (strong,nonatomic) TunConfig * _Nonnull config; + @property (strong,nonatomic) NSString * _Nonnull server; + +@property (nonatomic) NSString * _Nonnull port; +@property (nonatomic) BOOL connected; + +@property (nonatomic,copy) didRecvdata _Nonnull recvData; +@property (nonatomic,copy) tunDisConnected _Nonnull disConnected; +@property (nonatomic,copy) tunConnected _Nonnull tunConnected; +//callback queue + @property (nonatomic) dispatch_queue_t _Nonnull dispatchqueue ; +-(instancetype _Nonnull )initWithConfig:(TunConfig *_Nonnull)c ipaddr:(NSString*_Nonnull)ip port:(NSString*_Nonnull)port queue:(dispatch_queue_t _Nonnull )dqueue; +-(void)startWith:(tunConnected _Nonnull )connectd recv:(didRecvdata _Nonnull )recv disConnect:(tunConnected _Nonnull )disConnect; +-(void)startUDPSession; +-(void)restartUDPSessionWithIpaddr:(NSString*_Nonnull)ip port:(NSString *_Nonnull)port; +-(void)shutdownUDPSession; +-(void)input:(NSData*_Nonnull)data; +//-(void)upDate; +-(NSString*_Nonnull)localAddress; +-(NSInteger)localPort; +-(BOOL)useCell; +@end diff --git a/iOSLib/libkcp/libkcp/SFKcpTun.mm b/iOSLib/libkcp/libkcp/SFKcpTun.mm new file mode 100644 index 0000000..734c26e --- /dev/null +++ b/iOSLib/libkcp/libkcp/SFKcpTun.mm @@ -0,0 +1,464 @@ +// +// SFKcpTun.m +// libkcp +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// +#include +#include +#include +#include +#include "sess.h" +#import "SFKcpTun.h" + +#include + +#include + +#include +UDPSession *sess; + +void +itimeofday(long *sec, long *usec) { + struct timeval time; + gettimeofday(&time, NULL); + if (sec) *sec = time.tv_sec; + if (usec) *usec = time.tv_usec; +} + +IUINT64 iclock64(void) { + long s, u; + IUINT64 value; + itimeofday(&s, &u); + value = ((IUINT64) s) * 1000 + (u / 1000); + return value; +} + +IUINT32 iclock() { + return (IUINT32) (iclock64() & 0xfffffffful); +} +@interface SFKcpTun () +//@property (weak, nonatomic) UDPSession *sess; +//@property (strong, nonatomic) UITextField *port; + +@end + +@implementation SFKcpTun +{ + dispatch_source_t _timer; + dispatch_queue_t queue ; + dispatch_queue_t socketqueue ; + +} +-(instancetype)initWithConfig:(TunConfig *)c ipaddr:(NSString*)ip port:(NSString* )port queue:(dispatch_queue_t)dqueue +{ + if (self = [super init]){ + self.config = c; + self.server = ip; + self.port = port; + + self.dispatchqueue = dqueue; + queue = dispatch_queue_create("com.abigt.kcpread", DISPATCH_QUEUE_SERIAL);//dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + socketqueue = dispatch_queue_create("com.abigt.kcpwrite", DISPATCH_QUEUE_SERIAL);//input data + [self startUDPSession]; + } + return self; +} +-(void)startUDPSession +{ + if (self.config.key.length > 0 && ![self.config.crypt isEqualToString:@"none"]){ + NSLog(@"tun config crypt %@,key:%@",self.config.crypt,self.config.key); + BlockCrypt *block = BlockCrypt::blockWith(self.config.key.bytes, self.config.crypt.UTF8String); + sess = UDPSession::DialWithOptions(self.server.UTF8String, self.port.UTF8String, self.config.dataShards,self.config.parityShards,block); + }else { + sess = UDPSession::DialWithOptions(self.server.UTF8String, self.port.UTF8String, self.config.dataShards,self.config.parityShards); + } + assert(sess != nullptr); + + sess->NoDelay(self.config.nodelay, self.config.interval, self.config.resend, self.config.nc); + sess->WndSize(self.config.sndwnd, self.config.rcvwnd); + sess->SetMtu(self.config.mtu); + sess->SetStreamMode(true); + sess->SetDSCP(self.config.iptos); + + self.connected = true; + + +} +-(void)startWith:(tunConnected)connectd recv:(didRecvdata)recv disConnect:(tunConnected)disConnect + { + __weak SFKcpTun *weakSelf = self; + if ( self.connected ) { + dispatch_async(self.dispatchqueue, ^{ + weakSelf.tunConnected(weakSelf); + }); + } + + self.tunConnected = connectd; + self.recvData = recv; + self.disConnected = disConnect; + + if (__builtin_available(iOS 12, macOS 10.14,*)) { + sess->start_send_receive_loop(^(char *buffer, size_t len) { + NSData *d = [NSData dataWithBytes:buffer length:len]; + + dispatch_async(self.dispatchqueue, ^{ + weakSelf.recvData(weakSelf, d); + + }); + + }); + }else { + [self checkLoop]; + } + } +-(void)restartUDPSessionWithIpaddr:(NSString*)ip port:(NSString*)port +{ + if (sess != nil) { + UDPSession::Destroy(sess); + } + if (self.config.key.length > 0 && ![self.config.crypt isEqualToString:@"none"]){ + + BlockCrypt *block = BlockCrypt::blockWith(self.config.key.bytes, self.config.crypt.UTF8String); + sess = UDPSession::DialWithOptions(self.server.UTF8String, self.port.UTF8String, self.config.dataShards,self.config.parityShards,block); + }else { + sess = UDPSession::DialWithOptions(self.server.UTF8String, self.port.UTF8String, self.config.dataShards,self.config.parityShards); + } + + assert(sess != nullptr); + sess->NoDelay(self.config.nodelay, self.config.interval, self.config.resend, self.config.nc); + sess->WndSize(self.config.sndwnd, self.config.rcvwnd); + sess->SetMtu(self.config.mtu); + sess->SetStreamMode(true); + sess->SetDSCP(self.config.iptos); + self.connected = true; + + + [self checkLoop]; + +} +-(void)runDispatchTimer +{ + // Create a dispatch source that'll act as a timer on the concurrent queue + // You'll need to store this somewhere so you can suspend and remove it later on + dispatch_source_t dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,self->queue); + + // Setup params for creation of a recurring timer + double interval = 3300.0; + dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0); + uint64_t intervalTime = (int64_t)(interval * NSEC_PER_MSEC); + dispatch_source_set_timer(dispatchSource, startTime, intervalTime, 0); + + // Attach the block you want to run on the timer fire + __weak SFKcpTun *weakSelf = self; + dispatch_source_set_event_handler(dispatchSource, ^{ + // Your code here + + + if (sess != nil) { + + + char *buf = (char *) malloc(4096); + + memset(buf, 0, 4096); + ssize_t n = sess->Read(buf, 4096); + + if (__builtin_available(iOS 12, macOS 10.14,*)) { + + }else { + sess->Update(iclock()); + } + + + + if (n > 0 ){ + @autoreleasepool { + NSData *d = [NSData dataWithBytes:buf length:n]; + + dispatch_async(self.dispatchqueue, ^{ + weakSelf.recvData(weakSelf, d); + + }); + + // total += n ; + //NSDate *now = [NSDate date]; + + + + } + } + free(buf); + + + + } + }); + + // Start the timer + dispatch_resume(dispatchSource); + + // ---- + + // When you want to stop the timer, you need to suspend the source + //dispatch_suspend(dispatchSource); + + // If on iOS5 and/or using MRC, you'll need to release the source too + +} +-(void)shutdownUDPSession +{ + self.connected = false; + UDPSession::Destroy(sess); + +} + +-(void)input:(NSData*)data{ + + assert(sess != nullptr); + + __weak SFKcpTun *weakSelf = self; + dispatch_async(socketqueue, ^{ + SFKcpTun* strongSelf = weakSelf; + + size_t tosend = data.length; + size_t sended = 0 ; + char *ptr = (char *)data.bytes; + + if (strongSelf.connected) { + dispatch_suspend(strongSelf->queue); + while (sended < tosend) { + + + size_t sendt = sess->Write(ptr, data.length - sended); + sended += sendt ; + ptr += sended; + //NSLog(@"KCPTun sended:%zu, totoal:= %zu",sended,tosend); + //不能并行接收网络数据,效率有折扣 + if (__builtin_available(iOS 12,macOS 10.14, *)) { + sess->NWUpdate(iclock()); + }else { + sess->Update(iclock()); + } + + } + if (sended == [data length]) { + NSLog(@"KCPTun sent %zu",sended); + }else { + exit(-1); + } + dispatch_resume(strongSelf->queue); + } + + + }); + + + +} + +-(void)checkLoop +{ __weak SFKcpTun *weakSelf = self; + dispatch_async(self->queue, ^{ + size_t total = 0; + NSDate *start = [NSDate date]; + SFKcpTun* strongSelf = weakSelf; + while (strongSelf.connected) { + + if (total == 0) { + start = [NSDate date]; + } + int zeroCount = 0; + int valueCont = 0 ; + + if (strongSelf) { + if (sess != nil) { + + + char *buf = (char *) malloc(4096); + + memset(buf, 0, 4096); + + ssize_t n = 0; + n = sess->Read(buf, 4096); + sess->Update(iclock()); + + if (n > 0 ){ + @autoreleasepool { + NSData *d = [NSData dataWithBytes:buf length:n]; + //NSData *d= [NSData dataWithBytesNoCopy:buf length:n]; + dispatch_async(strongSelf.dispatchqueue, ^{ + weakSelf.recvData(weakSelf, d); + + }); + + total += n ; + //NSDate *now = [NSDate date]; + + } + +#include "TargetConditionals.h" +#if TARGET_IPHONE_SIMULATOR + +#elif TARGET_OS_IPHONE + +#elif TARGET_OS_MAC +#else +# error "Unknown Apple platform" +#endif + + }else { +#if TARGET_IPHONE_SIMULATOR + // iOS Simulator +#elif TARGET_OS_IPHONE + if (zeroCount > 3) { + zeroCount = 0; + usleep(3300); + }else { + usleep(1000); + } + zeroCount++; + + // iOS device +#elif TARGET_OS_MAC + //NSLog(@"session Update"); + usleep(1000); + // Other kinds of Mac OS +#else +# error "Unknown Apple platform" +#endif + } + free(buf); + } + } + + } + }); +} +-(void)testPorformce +{ + __weak SFKcpTun *weakSelf = self; + dispatch_async(self->queue, ^{ + SFKcpTun* strongSelf = weakSelf; + while (strongSelf.connected) { + + + if (strongSelf) { + if (sess != nil) { + + + @autoreleasepool { + char *ptr = (char *)BlockCrypt::ramdonBytes(1326); + + size_t sendt = sess->Write(ptr, 1326); + free(ptr); + + } + + + char *buf = (char *) malloc(4096); + + memset(buf, 0, 4096); + ssize_t n = sess->Read(buf, 4096); + //sess->Update(iclock()); + if (__builtin_available(iOS 12, macOS 10.14,*)) { + }else { + sess->Update(iclock()); + } + if (n > 0 ){ + @autoreleasepool { + NSData *d = [NSData dataWithBytes:buf length:n]; + + dispatch_async(strongSelf.dispatchqueue, ^{ + weakSelf.recvData(weakSelf, d); + + }); + } + + + }else { + //NSLog(@"##### kcp recv null\n"); + } + free(buf); + if (n != 1326) { + usleep(330); + } + + } + } + + } + }); + +} +-(NSString*)localAddress{ + if (sess != nil) { + char *addr = sess->getLocalIPAddr(); + + NSString *addrs = [NSString stringWithUTF8String:addr]; + return addrs; + }else { + return @""; + } +} +-(NSInteger)localPort{ + if (sess != nil) { + + NSInteger port = sess->getLocalPort(); + + return port; + }else { + return 0; + } +} +-(BOOL)useCell +{ + NSString *ipaddr = [self localAddress]; + NSDictionary *infos = [self address]; + for (NSString *key in infos.allKeys) { + if ([ipaddr isEqualToString:infos[key]]) { + if ([key isEqualToString:@"en"]) { + return false; + } + } + } + return true; +} +-(NSDictionary *)address +{ + // On iPhone, 3G is "pdp_ipX", where X is usually 0, but may possibly be 0-3 (i'm guessing...) + + NSData *result = nil; + + struct ifaddrs *addrs; + const struct ifaddrs *cursor; + NSMutableDictionary *info = [NSMutableDictionary dictionary]; + if ((getifaddrs(&addrs) == 0)) + { + cursor = addrs; + while (cursor != NULL) + { + NSLog(@"cursor->ifa_name = %s", cursor->ifa_name); + if (cursor->ifa_addr->sa_family == AF_INET) + { + struct sockaddr_in *addr = (struct sockaddr_in *)cursor->ifa_addr; + NSLog(@"cursor->ifa_addr = %s", inet_ntoa(addr->sin_addr)); + + result = [NSData dataWithBytes:addr length:sizeof(struct sockaddr_in)]; + + NSString *ifname = [NSString stringWithUTF8String:cursor->ifa_name]; + [info setObject:[NSString stringWithUTF8String:inet_ntoa(addr->sin_addr)] forKey:ifname]; + cursor = cursor->ifa_next; + } + else + { + cursor = cursor->ifa_next; + } + + } + freeifaddrs(addrs); + } + + return info; +} +@end diff --git a/iOSLib/libkcp/libkcp/TunConfig.h b/iOSLib/libkcp/libkcp/TunConfig.h new file mode 100644 index 0000000..9d51a56 --- /dev/null +++ b/iOSLib/libkcp/libkcp/TunConfig.h @@ -0,0 +1,33 @@ +// +// TunConfig.h +// libkcp +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import + +@interface TunConfig : NSObject +//DialWithOptions +@property (nonatomic) int dataShards; +@property (nonatomic) int parityShards; + +@property (nonatomic) int nodelay; +@property (nonatomic) int interval; +@property (nonatomic) int resend; +@property (nonatomic) int nc; + +@property (nonatomic) int sndwnd; +@property (nonatomic) int rcvwnd; + +@property (nonatomic) int mtu; + +@property (nonatomic) int iptos; + +@property (nonatomic) int keepAliveInterval; +@property (nonatomic) int keepAliveTimeout; +@property (strong,nonatomic) NSData *key; //pkbdf2Key driven +//"aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none", +@property (strong,nonatomic) NSString *crypt; +@end diff --git a/iOSLib/libkcp/libkcp/TunConfig.m b/iOSLib/libkcp/libkcp/TunConfig.m new file mode 100644 index 0000000..503624b --- /dev/null +++ b/iOSLib/libkcp/libkcp/TunConfig.m @@ -0,0 +1,31 @@ +// +// TunConfig.m +// libkcp +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import "TunConfig.h" + +@implementation TunConfig + +- (instancetype)init{ + if (self = [super init]){ + self.dataShards = 10; + self.parityShards = 3; + + self.nodelay = 0; + self.interval = 30; + self.resend = 2; + self.nc = 1; + + self.resend = 128; + self.rcvwnd = 128; + self.mtu = 1350 ; + self.iptos = 46; + self.crypt = @"none"; + } + return self; +} +@end diff --git a/iOSLib/libkcp/libkcp/kcp.h b/iOSLib/libkcp/libkcp/kcp.h new file mode 100644 index 0000000..82ae30b --- /dev/null +++ b/iOSLib/libkcp/libkcp/kcp.h @@ -0,0 +1,21 @@ +// +// libkcp.h +// libkcp +// +// Created by 孔祥波 on 28/04/2017. +// Copyright © 2017 Kong XiangBo. All rights reserved. +// + +#import + +//! Project version number for libkcp. +FOUNDATION_EXPORT double kcpVersionNumber; + +//! Project version string for libkcp. +FOUNDATION_EXPORT const unsigned char kcpVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like +#import +#import + + diff --git a/ikcp.c b/ikcp.c index 6d564f7..9f12b0d 100644 --- a/ikcp.c +++ b/ikcp.c @@ -545,7 +545,7 @@ static void ikcp_update_ack(ikcpcb *kcp, IINT32 rtt) kcp->rx_srtt = rtt; kcp->rx_rttval = rtt / 2; } else { - long delta = rtt - kcp->rx_srtt; + IINT32 delta = rtt - kcp->rx_srtt; if (delta < 0) delta = -delta; kcp->rx_rttval = (3 * kcp->rx_rttval + delta) / 4; kcp->rx_srtt = (7 * kcp->rx_srtt + rtt) / 8; @@ -772,7 +772,7 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size) size -= IKCP_OVERHEAD; - if ((long)size < (long)len) return -2; + if ((long)size < (long)len || (int)len < 0) return -2; if (cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK && cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS) @@ -1030,6 +1030,7 @@ void ikcp_flush(ikcpcb *kcp) for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = p->next) { IKCPSEG *segment = iqueue_entry(p, IKCPSEG, node); int needsend = 0; + //EXC_BAD_ACCESS (code=1, address=0xf00000000000003c) if (segment->xmit == 0) { needsend = 1; segment->xmit++; diff --git a/kcpserver.go b/kcpserver.go index 7802525..60d6715 100644 --- a/kcpserver.go +++ b/kcpserver.go @@ -1,15 +1,27 @@ package main import ( - "fmt" + "crypto/sha1" "github.com/xtaci/kcp-go" + "golang.org/x/crypto/pbkdf2" + "time" ) const port = ":9999" +var ( + // VERSION is injected by buildflags + VERSION = "SELFBUILD" + // SALT is use for pbkdf2 key expansion + SALT = "kcp-go" +) func ListenTest() (*kcp.Listener, error) { - return kcp.ListenWithOptions(port, nil, 2, 2) + var block kcp.BlockCrypt + pass := pbkdf2.Key([]byte("it's a secrect"), []byte(SALT), 4096, 32, sha1.New) + fmt.Println("key",pass) + block, _ = kcp.NewAESBlockCrypt([]byte("1234567890123456789012345678901234567890")) + return kcp.ListenWithOptions(port, block, 2, 2) } func server() { @@ -40,11 +52,14 @@ func handle_client(conn *kcp.UDPSession) { panic(err) } count++ + + //fmt.Println("received :" ,time.Now().Format("2006-01-02 15:04:05"),n) fmt.Println("received:", string(buf[:n])) conn.Write(buf[:n]) } } func main() { + fmt.Println("start :" ,time.Now().Format("2006-01-02 15:04:05")) server() } diff --git a/sess.cpp b/sess.cpp index f5230f2..e873f38 100644 --- a/sess.cpp +++ b/sess.cpp @@ -5,8 +5,73 @@ #include #include #include +#include #include +#include "CRC32.h" +#include + +// Global Options nw +char *g_psk = NULL; // TLS PSK +char *g_local_port = NULL; // Local port flag +char *g_local_addr = NULL; // Source Address +bool g_use_bonjour = false; // Use Bonjour rather than hostnames +bool g_detached = true; // Ignore stdin +bool g_listener = false; // Create a listener +bool g_use_tls = false; // Use TLS or DTLS +bool g_use_udp = true; // Use UDP instead of TCP +bool g_verbose = false; // Verbose +int g_family = AF_UNSPEC; // Required address family + +dispatch_queue_t q = dispatch_queue_create("nw.socket.queue",NULL); +#define NWCAT_BONJOUR_SERVICE_TCP_TYPE "_nwcat._tcp" +#define NWCAT_BONJOUR_SERVICE_UDP_TYPE "_nwcat._udp" +#define NWCAT_BONJOUR_SERVICE_DOMAIN "local" + +//end +void +_itimeofday(long *sec, long *usec) { + struct timeval time; + gettimeofday(&time, NULL); + if (sec) *sec = time.tv_sec; + if (usec) *usec = time.tv_usec; +} +// 16-bytes magic number for each packet +const size_t nonceSize = 16; + +// 4-bytes packet checksum +const size_t crcSize = 4; +// overall crypto header size +const size_t cryptHeaderSize = nonceSize + crcSize; + +// maximum packet size +//const size_t mtuLimit = 1500; + +// FEC keeps rxFECMulti* (dataShard+parityShard) ordered packets in memory +const size_t rxFECMulti = 3; +#define KCP_DEBUG 1 +void +dump(char *tag, byte *text, size_t len) +{ +#if KCP_DEBUG + int i; + printf("%s: \n", tag); + for (i = 0; i < len; i++){ + if ((i % 16) == 0 && i != 0){ + printf("\n"); + } + if ((i % 4) == 0 && ((i%16) != 0)){ + printf(" "); + + } + printf("%02x", (uint8_t)text[i]); + + + } + printf("\n"); +#endif +} +#define debug_print(args ...) if (KCP_DEBUG) fprintf(stderr, args) UDPSession * UDPSession::Dial(const char *ip, uint16_t port) { struct sockaddr_in saddr; @@ -31,25 +96,65 @@ UDPSession::Dial(const char *ip, uint16_t port) { return nullptr; } + struct sockaddr_in localAddress; + //socklen_t addressLength; + socklen_t addressLength = sizeof(localAddress); + getsockname(sockfd, (struct sockaddr*)&localAddress, \ + &addressLength); + printf("local address: %s\n", inet_ntoa( localAddress.sin_addr)); + printf("local port: %d\n", (int) ntohs(localAddress.sin_port)); + return UDPSession::createSession(sockfd); } UDPSession * -UDPSession::DialWithOptions(const char *ip, uint16_t port, size_t dataShards, size_t parityShards) { - auto sess = UDPSession::Dial(ip, port); - if (sess == nullptr) { - return nullptr; +UDPSession::DialWithOptions(const char *ip, const char *port, size_t dataShards, size_t parityShards) { + UDPSession *sess; + if (__builtin_available(iOS 12,macOS 10.14, *)) { + printf("nw event base udp socket"); + + nw_connection_t connection = create_outbound_connection(ip , port); + if (connection == NULL) { + err(1, NULL); + } + sess = UDPSession::createSession(connection); + sess->start_connection(connection); + // + + }else { + uint16_t arrToInt = 0; + for(int i=0;i<=1;i++) + arrToInt =(arrToInt<<8) | port[i]; + sess = UDPSession::Dial(ip, arrToInt); + if (sess == nullptr) { + return nullptr; + } } + + if (dataShards > 0 && parityShards > 0) { - sess->fec = FEC::New(3 * (dataShards + parityShards), dataShards, parityShards); + sess->fec = FEC::New(rxFECMulti * (dataShards + parityShards), dataShards, parityShards); sess->shards.resize(dataShards + parityShards, nullptr); sess->dataShards = dataShards; sess->parityShards = parityShards; } + + sess->block = NULL; + printf("sess->block:%p",sess->block); return sess; }; - +// DialWithOptions connects to the remote address "raddr" on the network "udp" with packet encryption with block +UDPSession* +UDPSession::DialWithOptions(const char *ip, const char *port, size_t dataShards, size_t parityShards,BlockCrypt *block){ + auto sess = UDPSession::DialWithOptions(ip, port, dataShards, parityShards); + if (sess == nullptr) { + return nullptr; + } + + sess->block = block; + return sess; +} UDPSession * UDPSession::dialIPv6(const char *ip, uint16_t port) { @@ -88,58 +193,124 @@ UDPSession::createSession(int sockfd) { sess->m_sockfd = sockfd; sess->m_kcp = ikcp_create(IUINT32(rand()), sess); sess->m_kcp->output = sess->out_wrapper; + return sess; } - - +UDPSession * +UDPSession::createSession(nw_connection_t sockfd) { + UDPSession *sess = new(UDPSession); + sess->outbound_connection = sockfd; + sess->m_kcp = ikcp_create(IUINT32(rand()), sess); + sess->m_kcp->output = sess->out_wrapper; + //sess->buffer_used = 0; + return sess; +} +//recv data from udp socket +/// void UDPSession::Update(uint32_t current) noexcept { for (;;) { ssize_t n = recv(m_sockfd, m_buf, sizeof(m_buf), 0); + if (n < 0) { + //perror("read fopen( \"null test.txt\", \"r\" )"); + + debug_print("kcp udp socket read error"); + //break; + } if (n > 0) { - if (fec.isEnabled()) { - // decode FEC packet - auto pkt = fec.Decode(m_buf, static_cast(n)); - if (pkt.flag == typeData) { - auto ptr = pkt.data->data(); - // we have 2B size, ignore for typeData - ikcp_input(m_kcp, (char *) (ptr + 2), pkt.data->size() - 2); + dump((char*)"UDP Update", m_buf, n); + //change by abigt + bool dataValid = false; + size_t outlen = n; + //size_t orgsize = n; + char *out = (char *)m_buf; + //outlen -= nonceSize; + out += nonceSize; + uint32_t sum = 0; + if (block != NULL) { + + block->decrypt(m_buf, n, &outlen); + + memcpy(&sum, (uint8_t *)out, sizeof(uint32_t)); + out += crcSize; + int32_t checksum = crc32_kr(0,(uint8_t *)out, n-cryptHeaderSize); + if (checksum == sum){ + dataValid = true; + } - - // allow FEC packet processing with correct flags. - if (pkt.flag == typeData || pkt.flag == typeFEC) { - // input to FEC, and see if we can recover data. - auto recovered = fec.Input(pkt); - - // we have some data recovered. - for (auto &r : recovered) { - // recovered data has at least 2B size. - if (r->size() > 2) { - auto ptr = r->data(); - // decode packet size, which is also recovered. - uint16_t sz; - decode16u(ptr, &sz); - - // the recovered packet size must be in the correct range. - if (sz >= 2 && sz <= r->size()) { - // input proper data to kcp - ikcp_input(m_kcp, (char *) (ptr + 2), sz - 2); - // std::cout << "sz:" << sz << std::endl; - } - } - } + }else { + + memcpy(&sum, (uint8_t *)out, sizeof(uint32_t)); + out += crcSize; + int32_t checksum = crc32_kr(0,(uint8_t *)out, n - cryptHeaderSize); + if (checksum == sum){ + dataValid = true; } - } else { // fec disabled - ikcp_input(m_kcp, (char *) (m_buf), n); + + } + if (outlen != n) { + debug_print("decrypt error outlen= %lu n = %lu\n",outlen,n); + } + if (dataValid == true) { + memmove(m_buf, m_buf + cryptHeaderSize, n-cryptHeaderSize); + KcpInPut(n - cryptHeaderSize); } + } else { + if (n == 0){ + debug_print("UDPSession recv nil"); + } break; } } + this->NWUpdate(current); +} +void +UDPSession::NWUpdate(uint32_t current) noexcept { m_kcp->current = current; ikcp_flush(m_kcp); } - +void +UDPSession::KcpInPut(size_t len) noexcept { + if (fec.isEnabled()) { + // decode FEC packet + auto pkt = fec.Decode(m_buf, static_cast(len)); + if (pkt.flag == kcptypeData) { + auto ptr = pkt.data->data(); + // we have 2B size, ignore for typeData + dump((char*)"ikcp input data:", (byte *) (ptr + 2), pkt.data->size() - 2); + ikcp_input(m_kcp, (char *) (ptr + 2), pkt.data->size() - 2); + } + + // allow FEC packet processing with correct flags. + if (pkt.flag == kcptypeData || pkt.flag == typeFEC) { + // input to FEC, and see if we can recover data. + auto recovered = fec.Input(pkt); + + // we have some data recovered. + for (auto &r : recovered) { + // recovered data has at least 2B size. + if (r->size() > 2) { + auto ptr = r->data(); + // decode packet size, which is also recovered. + uint16_t sz; + decode16u(ptr, &sz); + + // the recovered packet size must be in the correct range. + if (sz >= 2 && sz <= r->size()) { + // input proper data to kcp + dump((char*)"ikcp input data2:", (byte *) (ptr + 2), sz - 2); + ikcp_input(m_kcp, (char *) (ptr + 2), sz - 2); + + // std::cout << "sz:" << sz << std::endl; + } + } + } + } + } else { // fec disabled + ikcp_input(m_kcp, (char *) (m_buf), len); + } +} void UDPSession::Destroy(UDPSession *sess) { if (nullptr == sess) return; @@ -193,7 +364,26 @@ UDPSession::SetDSCP(int iptos) noexcept { iptos = (iptos << 2) & 0xFF; return setsockopt(this->m_sockfd, IPPROTO_IP, IP_TOS, &iptos, sizeof(iptos)); } - +char * UDPSession::getLocalIPAddr() noexcept{ + struct sockaddr_in localAddress; + //socklen_t addressLength; + socklen_t addressLength = sizeof(localAddress); + getsockname(this->m_sockfd, (struct sockaddr*)&localAddress, \ + &addressLength); + printf("local address: %s\n", inet_ntoa( localAddress.sin_addr)); + printf("local port: %d\n", (int) ntohs(localAddress.sin_port)); + return inet_ntoa( localAddress.sin_addr); +} +int UDPSession::getLocalPort() noexcept{ + struct sockaddr_in localAddress; + //socklen_t addressLength; + socklen_t addressLength = sizeof(localAddress); + getsockname(this->m_sockfd, (struct sockaddr*)&localAddress, \ + &addressLength); + printf("local address: %s\n", inet_ntoa( localAddress.sin_addr)); + printf("local port: %d\n", (int) ntohs(localAddress.sin_port)); + return (int) ntohs(localAddress.sin_port); +} void UDPSession::SetStreamMode(bool enable) noexcept { if (enable) { @@ -202,42 +392,94 @@ UDPSession::SetStreamMode(bool enable) noexcept { this->m_kcp->stream = 0; } } - +// output pipeline entry +// steps for output data processing: +// 0. Header extends +// 1. FEC +// 2. CRC32 +// 3. Encryption +// 4. WriteTo kernel int UDPSession::out_wrapper(const char *buf, int len, struct IKCPCB *, void *user) { assert(user != nullptr); UDPSession *sess = static_cast(user); - + //test no cover + dump((char*)"UDPSession kcp packet", (byte*)buf, (size_t)len); if (sess->fec.isEnabled()) { // append FEC header + BlockCrypt *block = sess->block; + + // extend to len + fecHeaderSizePlus2 // i.e. 4B seqid + 2B flag + 2B size - memcpy(sess->m_buf + fecHeaderSizePlus2, buf, static_cast(len)); - sess->fec.MarkData(sess->m_buf, static_cast(len)); - sess->output(sess->m_buf, len + fecHeaderSizePlus2); - + //crypto none also add nonce and crc + + uint8_t *nonce = BlockCrypt::ramdonBytes(nonceSize); + + memcpy(sess->m_buf, nonce, nonceSize); + free(nonce); + byte *ptr = sess->m_buf + cryptHeaderSize; + + memcpy(ptr + fecHeaderSizePlus2, buf, static_cast(len)); + sess->fec.MarkData(ptr, static_cast(len)); + + int32_t sum = crc32_kr(0,ptr ,len + fecHeaderSizePlus2); + memcpy(sess->m_buf + nonceSize, &sum, 4); + //dump("UDPSession header", (char *)header, nonceSize + crcSize); + //sess->output(header, nonceSize + crcSize ); + + + // FEC calculation // copy "2B size + data" to shards auto slen = len + 2; sess->shards[sess->pkt_idx] = - std::make_shared>(&sess->m_buf[fecHeaderSize], &sess->m_buf[fecHeaderSize + slen]); - + std::make_shared>(&sess->m_buf[fecHeaderSize + cryptHeaderSize], &sess->m_buf[fecHeaderSize + cryptHeaderSize + slen]); + size_t outlen = 0; + if (block != NULL ) { + block->encrypt(sess->m_buf, len + fecHeaderSizePlus2 + cryptHeaderSize, &outlen); + sess->output(sess->m_buf, outlen); + }else { + sess->output(sess->m_buf, len + fecHeaderSizePlus2 + cryptHeaderSize); + } + + // count number of data shards sess->pkt_idx++; if (sess->pkt_idx == sess->dataShards) { // we've collected enough data shards sess->fec.Encode(sess->shards); // send parity shards + //should add nonce and crc? + for (size_t i = sess->dataShards; i < sess->dataShards + sess->parityShards; i++) { // append header to parity shards // i.e. fecHeaderSize + data(2B size included) - memcpy(sess->m_buf + fecHeaderSize, sess->shards[i]->data(), sess->shards[i]->size()); - sess->fec.MarkFEC(sess->m_buf); - sess->output(sess->m_buf, sess->shards[i]->size() + fecHeaderSize); + // add nonce and crc + uint8_t *nonce = BlockCrypt::ramdonBytes(nonceSize); + + memcpy(sess->m_buf, nonce, nonceSize); + + free(nonce); + memcpy(ptr + fecHeaderSize, sess->shards[i]->data(), sess->shards[i]->size()); + sess->fec.MarkFEC(ptr); + + int32_t sum = crc32_kr(0,ptr ,sess->shards[i]->size() + fecHeaderSize); + memcpy(sess->m_buf + nonceSize, &sum, 4); + + //go version write ecc to remote? + if (block != NULL) { + block->encrypt(sess->m_buf, sess->shards[i]->size() + fecHeaderSize + cryptHeaderSize, &outlen); + sess->output(sess->m_buf,outlen); + }else { + sess->output(sess->m_buf, sess->shards[i]->size() + fecHeaderSize + cryptHeaderSize); + } + } - + // reset indexing sess->pkt_idx = 0; } } else { // No FEC, just send raw bytes, + //kcp-tun no use this sess->output(buf, static_cast(len)); } return 0; @@ -245,6 +487,311 @@ UDPSession::out_wrapper(const char *buf, int len, struct IKCPCB *, void *user) { ssize_t UDPSession::output(const void *buffer, size_t length) { - ssize_t n = send(m_sockfd, buffer, length, 0); - return n; + dump((char*)"UDPSession write socket", (byte *)buffer, length); + if (__builtin_available(iOS 12,macOS 10.14, *)) { + //send error check + this->send_loop(this->outbound_connection, dispatch_data_create(buffer,length,nil,DISPATCH_DATA_DESTRUCTOR_DEFAULT)); + return length; + }else { + + ssize_t n = send(m_sockfd, buffer, length, 0); + if (n != length) { + debug_print("not full send\n"); + } + if (n==-1) { + perror("send error fopen( \"nulltest.txt\", \"r\" )"); + } + return n; + } + + +} +/* + * create_outbound_connection() + * Returns a retained connection to a remote hostname and port. + * Sets up TLS and local address/port as necessary. + */ +nw_connection_t +UDPSession::create_outbound_connection(const char *name, const char *port) +{ + // If we are using bonjour to connect, treat the name as a bonjour name + // Otherwise, treat the name as a hostname + if (__builtin_available(iOS 12,macOS 10.14, *)) { + nw_endpoint_t endpoint = nw_endpoint_create_host(name, port); + + nw_parameters_t parameters = NULL; + nw_parameters_configure_protocol_block_t configure_tls = NW_PARAMETERS_DISABLE_PROTOCOL; + if (g_use_tls) { + if (g_psk) { + configure_tls = ^(nw_protocol_options_t tls_options) { + sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options); + dispatch_data_t psk = dispatch_data_create(g_psk, strlen(g_psk), nil, DISPATCH_DATA_DESTRUCTOR_DEFAULT); + sec_protocol_options_add_pre_shared_key(sec_options, psk, psk); + dispatch_release(psk); + sec_protocol_options_add_tls_ciphersuite(sec_options, (SSLCipherSuite)TLS_PSK_WITH_AES_128_GCM_SHA256); + nw_release(sec_options); + }; + } else { + configure_tls = NW_PARAMETERS_DEFAULT_CONFIGURATION; + } + } + + if (g_use_udp) { + // Create a UDP connection + parameters = nw_parameters_create_secure_udp(configure_tls, + NW_PARAMETERS_DEFAULT_CONFIGURATION); + } else { + // Create a TCP connection + parameters = nw_parameters_create_secure_tcp(configure_tls, + NW_PARAMETERS_DEFAULT_CONFIGURATION); + } + + nw_protocol_stack_t protocol_stack = nw_parameters_copy_default_protocol_stack(parameters); + if (g_family == AF_INET || g_family == AF_INET6) { + nw_protocol_options_t ip_options = nw_protocol_stack_copy_internet_protocol(protocol_stack); + if (g_family == AF_INET) { + // Force IPv4 + nw_ip_options_set_version(ip_options, nw_ip_version_4); + } else if (g_family == AF_INET6) { + // Force IPv6 + nw_ip_options_set_version(ip_options, nw_ip_version_6); + } + nw_release(ip_options); + } + nw_release(protocol_stack); + + // Bind to local address and port + if (g_local_addr || g_local_port) { + nw_endpoint_t local_endpoint = nw_endpoint_create_host(g_local_addr ? g_local_addr : "::", g_local_port ? g_local_port : "0"); + nw_parameters_set_local_endpoint(parameters, local_endpoint); + nw_release(local_endpoint); + } + + nw_connection_t connection = nw_connection_create(endpoint, parameters); + nw_release(endpoint); + nw_release(parameters); + + return connection; + } else { + return nil; + } + + +} +void UDPSession::start_connection(nw_connection_t connection) +{ + if (__builtin_available(iOS 12, macOS 10.14,*)) { + nw_connection_set_queue(connection,q); + + nw_retain(connection); // Hold a reference until cancelled + nw_connection_set_state_changed_handler(connection, ^(nw_connection_state_t state, nw_error_t error) { + nw_endpoint_t remote = nw_connection_copy_endpoint(connection); + errno = error ? nw_error_get_error_code(error) : 0; + if (state == nw_connection_state_waiting) { + warn("connect to %s port %u (%s) failed, is waiting", + nw_endpoint_get_hostname(remote), + nw_endpoint_get_port(remote), + g_use_udp ? "udp" : "tcp"); + } else if (state == nw_connection_state_failed) { + warn("connect to %s port %u (%s) failed", + nw_endpoint_get_hostname(remote), + nw_endpoint_get_port(remote), + g_use_udp ? "udp" : "tcp"); + } else if (state == nw_connection_state_ready) { + if (g_verbose) { + fprintf(stderr, "Connection to %s port %u (%s) succeeded!\n", + nw_endpoint_get_hostname(remote), + nw_endpoint_get_port(remote), + g_use_udp ? "udp" : "tcp"); + } + } else if (state == nw_connection_state_cancelled) { + // Release the primary reference on the connection + // that was taken at creation time + nw_release(connection); + } + nw_release(remote); + }); + + nw_connection_start(connection); + } + +} +/* + * start_send_receive_loop() + * Start reading from stdin (when not detached) and from the given connection. + * Every read on stdin becomes a send on the connection, and every receive on the + * connection becomes a write on stdout. + */ +void UDPSession::start_send_receive_loop(recvBlock didRecv) +{ + // Start reading from connection + this->didRecv = Block_copy(didRecv); + this->receive_loop(); +} +/* + * receive_loop() + * Perform a single read on the supplied connection, and write data to + * stdout as it is received. + * If no error is encountered, schedule another read on the same connection. + */ +void +UDPSession::receive_loop() +{ + nw_connection_t connection = this->outbound_connection; + printf("nw start recvloop\n"); + if (__builtin_available(iOS 12, macOS 10.14,*)) { + nw_connection_receive(connection, 1, 2048, ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t receive_error) { + + CFRetain(context); + dispatch_block_t schedule_next_receive = ^{ + // If the context is marked as complete, and is the final context, + // we're read-closed. + if (is_complete && + + context != NULL && nw_content_context_get_is_final(context)) { + CFRelease(context); + exit(0); + } + + // If there was no error in receiving, request more data + + + + if (is_complete) { + + long s, u; + IUINT64 value; + struct timeval time; + gettimeofday(&time, NULL); + _itimeofday(&s, &u); + value = ((IUINT64) s) * 1000 + (u / 1000); + this->NWUpdate(value & 0xfffffffful); + // this->buffer_used = 0 ; + }else { + printf("is_complete false \n"); + } + + + if (receive_error == NULL) { + + receive_loop(); + + } + CFRelease(context); + }; + + if (content != NULL) { + // If there is content, write it to stdout asynchronously + schedule_next_receive = Block_copy(schedule_next_receive); + + if (is_complete) { + + + //change by abigt + bool dataValid = false; + + size_t n = dispatch_data_get_size(content); + printf("current read complete new data:%ld\n",n); + __block size_t buffer_used = 0; + dispatch_data_apply(content, ^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) { + fprintf(stderr, "region with offset %zu, size %zu\n", offset, size); + memcpy(m_buf+buffer_used, (char*)buffer + offset, size); + buffer_used += size; + return true; + }); + + dump((char*)"UDP Update", m_buf, n); + size_t outlen = n; + char *out = (char *)m_buf; + + + //outlen -= nonceSize; + out += nonceSize; + uint32_t sum = 0; + if (block != NULL) { + + block->decrypt(m_buf, n, &outlen); + + memcpy(&sum, (uint8_t *)out, sizeof(uint32_t)); + out += crcSize; + int32_t checksum = crc32_kr(0,(uint8_t *)out, n-cryptHeaderSize); + if (checksum == sum){ + dataValid = true; + + } + }else { + //dump((char*)"check sum", out, n - (size_t)nonceSize); + memcpy(&sum, (uint8_t *)out, sizeof(uint32_t)); + out += crcSize; + int32_t checksum = crc32_kr(0,(uint8_t *)out, n - cryptHeaderSize); + if (checksum == sum){ + dataValid = true; + } + } + + if (dataValid == true) { + memmove(m_buf, m_buf + cryptHeaderSize, n-cryptHeaderSize); + + KcpInPut( n-cryptHeaderSize); + char *buf = (char *) malloc(4096); + memset(buf, 0, 4096); + ssize_t nn = 0; + nn = this->Read(buf, 4096); + if(nn > 0 && this->didRecv != nil){ + this->didRecv(buf,nn); + }else { + printf("no date recv!\n"); + } + free(buf); + }else { + fprintf(stderr," dataValid failure\n"); + } + + + + + }else { + //don't go here + fprintf(stderr," don't go here\n"); +// size_t n = dispatch_data_get_size(content); +// memcpy(m_buf+this->buffer_used, content, n); +// this->buffer_used += n; + } + + dispatch_async( q, ^{ + // Block_retain(schedule_next_receive); + schedule_next_receive(); + Block_release(schedule_next_receive); + }); + } else { + // Content was NULL, so directly schedule the next receive + //update kcp + + schedule_next_receive(); + } + }); + } + +} +/* + * send_loop() + * Start reading from stdin on a dispatch source, and send any bytes on the given connection. + */ +void +UDPSession::send_loop(nw_connection_t connection, dispatch_data_t _Nonnull write_data){ + // Every send is marked as complete. This has no effect with the default message context for TCP, + // but is required for UDP to indicate the end of a packet. + printf("nw send data!\n"); + if (__builtin_available(iOS 12,macOS 10.14, *)) { + nw_connection_send(connection, write_data, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, ^(nw_error_t _Nullable error) { + if (error != NULL) { + errno = nw_error_get_error_code(error); + warn("send error %d",errno); + } else { + //send_loop(connection); + printf("send fin\n"); + } + }); + } + } diff --git a/sess.h b/sess.h index f856fce..e20d73b 100644 --- a/sess.h +++ b/sess.h @@ -5,10 +5,17 @@ #include "fec.h" #include #include - +#include +#include +#import "BlockCrypt.h" +typedef void (^recvBlock)(char* buffer,size_t len); +void +dump(char *tag, char *text, int len); class UDPSession { private: int m_sockfd{0}; + //size_t buffer_used; + nw_connection_t outbound_connection = NULL; ikcpcb *m_kcp{nullptr}; byte m_buf[2048]; byte m_streambuf[65535]; @@ -19,6 +26,8 @@ class UDPSession { std::vector shards; size_t dataShards{0}; size_t parityShards{0}; + BlockCrypt *block; + public: UDPSession(const UDPSession &) = delete; @@ -28,11 +37,15 @@ class UDPSession { static UDPSession *Dial(const char *ip, uint16_t port); // DialWithOptions connects to the remote address "raddr" on the network "udp" with packet encryption - static UDPSession *DialWithOptions(const char *ip, uint16_t port, size_t dataShards, size_t parityShards); + static UDPSession *DialWithOptions(const char *ip, const char *port, size_t dataShards, size_t parityShards); + // DialWithOptions connects to the remote address "raddr" on the network "udp" with packet encryption with block + static UDPSession *DialWithOptions(const char *ip, const char *port, size_t dataShards, size_t parityShards,BlockCrypt *block); // Update will try reading/writing udp packet, pass current unix millisecond void Update(uint32_t current) noexcept; - + void NWUpdate(uint32_t current) noexcept; + //kcpInput go UDPpsession + void KcpInPut(size_t len) noexcept; // Destroy release all resource related. static void Destroy(UDPSession *sess); @@ -45,6 +58,9 @@ class UDPSession { // Set DSCP value int SetDSCP(int dscp) noexcept; + char *getLocalIPAddr() noexcept; + recvBlock didRecv; + int getLocalPort() noexcept; // SetStreamMode toggles the stream mode on/off void SetStreamMode(bool enable) noexcept; @@ -56,7 +72,8 @@ class UDPSession { inline int WndSize(int sndwnd, int rcvwnd) { return ikcp_wndsize(m_kcp, sndwnd, rcvwnd); } inline int SetMtu(int mtu) { return ikcp_setmtu(m_kcp, mtu); } - + void receive_loop(); + void start_send_receive_loop(recvBlock didRecv); private: UDPSession() = default; @@ -72,8 +89,13 @@ class UDPSession { ssize_t output(const void *buffer, size_t length); static UDPSession *createSession(int sockfd); - - + static UDPSession *createSession(nw_connection_t sockfd); + //new + static nw_connection_t create_outbound_connection(const char *, const char *); + void start_connection(nw_connection_t connection); + + void send_loop(nw_connection_t connection,dispatch_data_t _Nonnull read_data); + }; inline uint32_t currentMs() {