Compare commits

...

3 Commits

Author SHA1 Message Date
xsean
bebdfa0794 修改超时时间 2025-11-10 11:08:47 +08:00
xsean
b2cfb485af 修改超时时间 2025-11-06 14:20:59 +08:00
xsean
1fb432a784 修改sleep 问题和udp服务问题 2025-11-06 11:38:46 +08:00
30 changed files with 71858 additions and 2250 deletions

View File

@ -6,5 +6,5 @@ Author: XYZShell
Section: Utilities Section: Utilities
Tag: role::developer Tag: role::developer
Architecture: iphoneos-arm Architecture: iphoneos-arm
Version: 0.0.7-10-62+debug Version: 0.0.7-10-68+debug
Installed-Size: 1604 Installed-Size: 1624

View File

@ -1 +1 @@
./packages/com.xyzshell.ioscontrol_0.0.7-10-62+debug_iphoneos-arm.deb ./packages/com.xyzshell.ioscontrol_0.0.7-10-68+debug_iphoneos-arm.deb

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
62 68

View File

@ -11,6 +11,7 @@ TWEAK_NAME = AppRunMan
AppRunMan_FRAMEWORKS = CoreLocation CFNetwork CoreTelephony Security UIKit IOSurface JavaScriptCore network AppRunMan_FRAMEWORKS = CoreLocation CFNetwork CoreTelephony Security UIKit IOSurface JavaScriptCore network
AppRunMan_PRIVATE_FRAMEWORKS = IOKit AppRunMan_PRIVATE_FRAMEWORKS = IOKit
AppRunMan_FILES = Tweak.x $(wildcard server/*.m) $(wildcard server/GCD/*.m) AppRunMan_FILES = Tweak.x $(wildcard server/*.m) $(wildcard server/GCD/*.m)
AppRunMan_LDFLAGS = -v
AppRunMan_CFLAGS = -Wno-error -Wno-module-import-in-extern-c -fobjc-arc AppRunMan_CFLAGS = -Wno-error -Wno-module-import-in-extern-c -fobjc-arc
include $(THEOS_MAKE_PATH)/tweak.mk include $(THEOS_MAKE_PATH)/tweak.mk

View File

@ -157,7 +157,7 @@
self.ip = [[XSPhoneInfo sharedInstance] IPAddress]; self.ip = [[XSPhoneInfo sharedInstance] IPAddress];
self.remoteIp = [[XSPhoneInfo sharedInstance] remoteIp]; self.remoteIp = [[XSPhoneInfo sharedInstance] remoteIp];
self.diskSize = [[XSPhoneInfo sharedInstance] IPhoneStatus]; self.diskSize = [[XSPhoneInfo sharedInstance] IPhoneStatus];
self.message = @"251103-nt"; self.message = @"251106-nt";
// //
NSDictionary *heartbeatData = [self constructHeartbeatData]; NSDictionary *heartbeatData = [self constructHeartbeatData];
if (!heartbeatData) { if (!heartbeatData) {

View File

@ -11,7 +11,6 @@
#import "XSPhoneInfo.h" #import "XSPhoneInfo.h"
#import "XSHelper.h" #import "XSHelper.h"
#import "XSHackIos.h" #import "XSHackIos.h"
#import "MyScriptTask.h"
#import "MyEventBus.h" #import "MyEventBus.h"
#import "XSHttpHelper.h" #import "XSHttpHelper.h"
#import "MyAdTask2.h" #import "MyAdTask2.h"

View File

@ -1,10 +1,3 @@
//
// MyAdTask2.m
// nochange
//
// Created by mac on 2024/11/6.
//
#include "XUDPServer.h" #include "XUDPServer.h"
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "IPhoneHertbeat.h" #import "IPhoneHertbeat.h"
@ -16,16 +9,13 @@
#import "MyAdTask2.h" #import "MyAdTask2.h"
#import "MyEventBus.h" #import "MyEventBus.h"
BOOL myadTaskManualStop = NO; BOOL myadTaskManualStop = NO;
@interface MyAdTask2Mangger() @interface MyAdTask2Mangger()
{ {
@private @private
BOOL running; BOOL running;
// NSTimer *timer; dispatch_source_t _timer;
dispatch_source_t _timer; // 使GCD timerNSTimer
NSDate *lastRun; NSDate *lastRun;
NSDate *lastGetCountry; NSDate *lastGetCountry;
NSString *_lastIdfa; NSString *_lastIdfa;
@ -39,7 +29,6 @@ BOOL myadTaskManualStop = NO;
NSString *dataId; NSString *dataId;
NSString *remoteIp; NSString *remoteIp;
NSString *country; NSString *country;
} }
@end @end
@ -49,11 +38,12 @@ BOOL myadTaskManualStop = NO;
+(instancetype)sharedInstance { +(instancetype)sharedInstance {
static MyAdTask2Mangger* _sharedInstance = nil; static MyAdTask2Mangger* _sharedInstance = nil;
static dispatch_once_t oncePredicate; static dispatch_once_t oncePredicate;
dispatch_once (&oncePredicate, ^{ dispatch_once(&oncePredicate, ^{
_sharedInstance = [[MyAdTask2Mangger alloc] init]; _sharedInstance = [[MyAdTask2Mangger alloc] init];
}); });
return _sharedInstance; return _sharedInstance;
} }
-(instancetype)init { -(instancetype)init {
if (self = [super init]) { if (self = [super init]) {
self->running = NO; self->running = NO;
@ -70,7 +60,7 @@ BOOL myadTaskManualStop = NO;
return nil; return nil;
} }
- (int) onShow: (NSDictionary *)dic { - (int)onShow:(NSDictionary *)dic {
if(dic == nil || [dic isEqual:[NSNull null]] || [dic count] <= 0) { if(dic == nil || [dic isEqual:[NSNull null]] || [dic count] <= 0) {
return 4000; return 4000;
} }
@ -80,35 +70,13 @@ BOOL myadTaskManualStop = NO;
NSNumber *t_ecpm = [self getNum:@"ecpm" dic:dic]; NSNumber *t_ecpm = [self getNum:@"ecpm" dic:dic];
BOOL ad = dic[@"ad"]; BOOL ad = dic[@"ad"];
NSString *iphoneId = [[XSPhoneConfig sharedInstance] IPhoneName]; NSString *iphoneId = [[XSPhoneConfig sharedInstance] IPhoneName];
// NSString *ipAddr = [[XSPhoneInfo sharedInstance] IPAddress];
/*
saveAdTaskLog(@{
@"title": @"广告展示",
@"message": [XSHelper dic2Json:dic],
@"level": @(1),
@"appid": t_appid,
@"idfa":t_idfa,
@"adid": t_adId,
@"ecpm": [NSString stringWithFormat:@"%@", t_ecpm],
@"taskId": self->taskId,
@"iphoneId":iphoneId,
@"ipAddr":ipAddr
});
*/
/* --
if (self->current > -1 && self->current < (NSInteger)self->tasks.count) {
cur = self->tasks[self->current];
}
*/
if(!ad) { if(!ad) {
NSLog(@"XS- no ad show"); NSLog(@"XS- no ad show");
return 0; return 0;
} }
int close = 4000; int close = 4000;
//--new
AdLoadInfo adloadInfo = getAdLoadInfo(@{ AdLoadInfo adloadInfo = getAdLoadInfo(@{
@"idfa": t_idfa ?: @"", @"idfa": t_idfa ?: @"",
@"adId": t_adId ?: @"", @"adId": t_adId ?: @"",
@ -117,11 +85,6 @@ BOOL myadTaskManualStop = NO;
@"deviceId":iphoneId ?: @"" @"deviceId":iphoneId ?: @""
}); });
// cur.loads = adloadInfo.loads;
//cur.adTouchBeforeMs = adloadInfo.adTouchBeforeMs;
// cur.adTime= adloadInfo.adTime;
close = [adloadInfo.adTime intValue]; close = [adloadInfo.adTime intValue];
int before = [adloadInfo.adTouchBeforeMs intValue]; int before = [adloadInfo.adTouchBeforeMs intValue];
if (before >= close) { if (before >= close) {
@ -134,19 +97,24 @@ BOOL myadTaskManualStop = NO;
self->adAfter = 1000; self->adAfter = 1000;
} }
NSInteger random1 = arc4random_uniform(101); // 0-100 NSInteger random1 = arc4random_uniform(101);
NSInteger tr = [adloadInfo.touchRate intValue]; NSInteger tr = [adloadInfo.touchRate intValue];
if (tr > random1) { if (tr > random1) {
[self touchAppTask: before / 1000]; double beforeSec = before / 1000.0;
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(beforeSec * NSEC_PER_SEC)),
self.manQueue, ^{
[weakSelf touchAppTask:0];
});
} }
return close; return close;
} }
- (void) showStatus: (NSString *)data { - (void)showStatus:(NSString *)data {
[[MyEventBus sharedInstance] postEvent:@"UpdateStatus" withObject:data]; [[MyEventBus sharedInstance] postEvent:@"UpdateStatus" withObject:data];
} }
- (void) setRemoteInfo { - (void)setRemoteInfo {
NSString *url = @"https://ipapi.co/json/"; NSString *url = @"https://ipapi.co/json/";
XSHttpHelper *http = [[XSHttpHelper alloc] init]; XSHttpHelper *http = [[XSHttpHelper alloc] init];
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
@ -164,8 +132,10 @@ BOOL myadTaskManualStop = NO;
} }
NSString *isoCode = dic[@"country_code"]; NSString *isoCode = dic[@"country_code"];
NSString *ip = dic[@"ip"]; NSString *ip = dic[@"ip"];
// callback(ip, isoCode);
__strong typeof(weakSelf) strongSelf = weakSelf; __strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
strongSelf->remoteIp = [ip copy]; strongSelf->remoteIp = [ip copy];
strongSelf->country = [isoCode copy]; strongSelf->country = [isoCode copy];
[XSPhoneInfo sharedInstance].remoteIp = [NSString stringWithFormat:@"%@:%@", isoCode, ip]; [XSPhoneInfo sharedInstance].remoteIp = [NSString stringWithFormat:@"%@:%@", isoCode, ip];
@ -176,8 +146,8 @@ BOOL myadTaskManualStop = NO;
}]; }];
} }
- (void) setRemoteInfo1 { - (void)setRemoteInfo1 {
NSString *url = [[XSPhoneConfig sharedInstance] GetRemoteIPURL]; NSString *url = [[XSPhoneConfig sharedInstance] GetRemoteIPURL];
[self showStatus:url]; [self showStatus:url];
if (!url) { if (!url) {
NSLog(@"!setRemoteInfo url"); NSLog(@"!setRemoteInfo url");
@ -207,9 +177,11 @@ BOOL myadTaskManualStop = NO;
NSString *isoCode = _data[@"isoCode"]; NSString *isoCode = _data[@"isoCode"];
NSString *ip = _data[@"ip"]; NSString *ip = _data[@"ip"];
NSLog(@"setRemoteInfo:%@", _data); NSLog(@"setRemoteInfo:%@", _data);
__strong typeof(weakSelf) strongSelf = weakSelf; __strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
strongSelf->remoteIp = [ip copy]; strongSelf->remoteIp = [ip copy];
strongSelf->country = [isoCode copy]; strongSelf->country = [isoCode copy];
[XSPhoneInfo sharedInstance].remoteIp = [NSString stringWithFormat:@"%@:%@", isoCode, ip]; [XSPhoneInfo sharedInstance].remoteIp = [NSString stringWithFormat:@"%@:%@", isoCode, ip];
[weakSelf showStatus:[XSPhoneInfo sharedInstance].remoteIp]; [weakSelf showStatus:[XSPhoneInfo sharedInstance].remoteIp];
@ -217,13 +189,9 @@ BOOL myadTaskManualStop = NO;
NSLog(@"!setRemoteInfo err:%@",err); NSLog(@"!setRemoteInfo err:%@",err);
[weakSelf showStatus:[NSString stringWithFormat:@"%@", err.description]]; [weakSelf showStatus:[NSString stringWithFormat:@"%@", err.description]];
}]; }];
} }
- (BOOL)onEnd:(NSDictionary *)dic {
- (BOOL) onEnd: (NSDictionary *)dic {
NSNumber *maxEcpm = dic[@"max_ecpm"]; NSNumber *maxEcpm = dic[@"max_ecpm"];
int sec = self->adAfter / 1000; int sec = self->adAfter / 1000;
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
@ -244,11 +212,10 @@ BOOL myadTaskManualStop = NO;
[weakSelf startApp]; [weakSelf startApp];
} }
}); });
return NO; return NO;
} }
- (void) startApp { - (void)startApp {
@autoreleasepool { @autoreleasepool {
if(!self->running){ if(!self->running){
return; return;
@ -266,32 +233,24 @@ BOOL myadTaskManualStop = NO;
} }
} }
/*
if(![@"US" isEqual:self->country]) {
[self showStatus:[NSString stringWithFormat:@"%@:%@, Not US", self->country, self->remoteIp]];
return;
}
*/
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
getChangeInfo(self->_lastIdfa, ^(NSDictionary *dic) { getChangeInfo(self->_lastIdfa, ^(NSDictionary *dic) {
dispatch_async(weakSelf.manQueue, ^{ dispatch_async(weakSelf.manQueue, ^{
// [weakSelf onChangeInfo:dic];
[weakSelf onChangeInfo: dic];
}); });
}, ^(NSError *err) { }, ^(NSError *err) {
NSLog(@"XS- startTask NSError is null, %@", err); NSLog(@"XS- startTask NSError is null, %@", err);
}); });
} }
} }
- (void) start { - (void)start {
self->running = YES; self->running = YES;
myadTaskManualStop = NO; myadTaskManualStop = NO;
[[IPhoneHertbeat sharedInstance] setStatus: @"运行中"]; [[IPhoneHertbeat sharedInstance] setStatus:@"运行中"];
[self startApp]; [self startApp];
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
// 使 dispatch_source timer
if (!_timer) { if (!_timer) {
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.manQueue); _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.manQueue);
dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), 10 * NSEC_PER_SEC, 1 * NSEC_PER_SEC); dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), 10 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
@ -305,7 +264,7 @@ BOOL myadTaskManualStop = NO;
[[MyEventBus sharedInstance] postEvent:@"UpdateRunStatus" withObject:@(YES)]; [[MyEventBus sharedInstance] postEvent:@"UpdateRunStatus" withObject:@(YES)];
} }
- (void) proc { - (void)proc {
if (!self->running) { if (!self->running) {
return; return;
} }
@ -314,20 +273,24 @@ BOOL myadTaskManualStop = NO;
NSDate* curRunTime = [NSDate date]; NSDate* curRunTime = [NSDate date];
NSTimeInterval elapsed = [curRunTime timeIntervalSinceDate:self->lastRun]; NSTimeInterval elapsed = [curRunTime timeIntervalSinceDate:self->lastRun];
if (elapsed >= 30) { if (elapsed >= 100) {
//[self onStop];
[self start]; [self start];
} else { } else {
NSString* appId = [ self frontMostAppId]; NSString* appId = [self frontMostAppId];
if (![appId isEqual: self->taskAppId]) { if (![appId isEqual:self->taskAppId]) {
[self appKill:appId]; [self appKill:appId];
sleep(1);
[self appRun:self->taskAppId]; // : strong使
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), self.manQueue, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
[strongSelf appRun:strongSelf->taskAppId];
});
} }
} }
} }
- (NSString *)toggle { - (NSString *)toggle {
@ -339,7 +302,7 @@ BOOL myadTaskManualStop = NO;
return [IPhoneHertbeat sharedInstance].status; return [IPhoneHertbeat sharedInstance].status;
} }
- (void) stop { - (void)stop {
myadTaskManualStop = YES; myadTaskManualStop = YES;
self->running = NO; self->running = NO;
[IPhoneHertbeat sharedInstance].status = @"已停止"; [IPhoneHertbeat sharedInstance].status = @"已停止";
@ -350,14 +313,12 @@ BOOL myadTaskManualStop = NO;
[[MyEventBus sharedInstance] postEvent:@"UpdateRunStatus" withObject:@(NO)]; [[MyEventBus sharedInstance] postEvent:@"UpdateRunStatus" withObject:@(NO)];
} }
- (void)onChangeInfo:(NSDictionary *)dic {
- (void) onChangeInfo: (NSDictionary *)dic { NSString* t_idfa = [self getStr:@"idfa" dic:dic];
NSString* t_idfa = [self getStr: @"idfa" dic:dic];
if (![XSHelper strIsEmpty:t_idfa]) { if (![XSHelper strIsEmpty:t_idfa]) {
self->_lastIdfa = [t_idfa copy]; self->_lastIdfa = [t_idfa copy];
} else { } else {
NSLog(@"XS- startTask t_idfa is null"); NSLog(@"XS- startTask t_idfa is null");
return; return;
} }
@ -369,14 +330,12 @@ BOOL myadTaskManualStop = NO;
if (![XSHelper strIsEmpty:_dataId]) { if (![XSHelper strIsEmpty:_dataId]) {
self->dataId = [_dataId copy]; self->dataId = [_dataId copy];
} }
NSString* t_taskId = [self getStr:@"id" dic:dic]; NSString* t_taskId = [self getStr:@"id" dic:dic];
if (![XSHelper strIsEmpty:t_taskId]) { if (![XSHelper strIsEmpty:t_taskId]) {
self->taskId = [t_taskId copy]; self->taskId = [t_taskId copy];
} else { } else {
NSLog(@"XS- startTask t_taskId is null"); NSLog(@"XS- startTask t_taskId is null");
return; return;
} }
NSString* t_taskAppId = [self getStr:@"appId" dic:dic]; NSString* t_taskAppId = [self getStr:@"appId" dic:dic];
@ -385,16 +344,14 @@ BOOL myadTaskManualStop = NO;
[IPhoneHertbeat sharedInstance].appId = self->taskAppId; [IPhoneHertbeat sharedInstance].appId = self->taskAppId;
} else { } else {
NSLog(@"XS- startTask t_taskAppId is null"); NSLog(@"XS- startTask t_taskAppId is null");
return; return;
} }
NSDictionary *workerInfo = dic[@"workerInfo"]; NSDictionary *workerInfo = dic[@"workerInfo"];
if(workerInfo && ![workerInfo isEqual:[NSNull null]]) { if(workerInfo && ![workerInfo isEqual:[NSNull null]]) {
} else { } else {
NSLog(@"XS- startTask workerInfo is null"); NSLog(@"XS- startTask workerInfo is null");
return; return;
} }
@ -403,29 +360,39 @@ BOOL myadTaskManualStop = NO;
self->workType = t_workType; self->workType = t_workType;
} else { } else {
NSLog(@"XS- startTask workType is null"); NSLog(@"XS- startTask workType is null");
} }
__weak typeof(self) weakSelf = self;
[self restart:^{ [self restart:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
saveChangeDataFile(dic); saveChangeDataFile(dic);
self->running = YES; strongSelf->running = YES;
sleep(1);
[self appRun:self->taskAppId]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC),
strongSelf.manQueue, ^{
__strong typeof(weakSelf) strongSelf2 = weakSelf;
if (!strongSelf2) return;
[strongSelf2 appRun:strongSelf2->taskAppId];
});
}]; }];
//sleep(1);
} }
- (void)appKill:(NSString*)app {
- (void) appKill: (NSString*) app {
NSLog(@"XS- appKill"); NSLog(@"XS- appKill");
XSKillAppByName(app); XSKillAppByName(app);
} }
- (void) unlock {
- (void)unlock {
NSLog(@"XS- unlock"); NSLog(@"XS- unlock");
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
XSRemoteUnlock(); XSRemoteUnlock();
}); });
} }
- (void) resetApp: (NSString*) appId callback:(OnEndCallback) callback {
- (void)resetApp:(NSString*)appId callback:(OnEndCallback)callback {
NSLog(@"XS- JSApi resetApp"); NSLog(@"XS- JSApi resetApp");
NSString *appInfoPath = XSGetAppInfoPath(appId); NSString *appInfoPath = XSGetAppInfoPath(appId);
NSDictionary *appInfo = XSGetAppInfo(appInfoPath); NSDictionary *appInfo = XSGetAppInfo(appInfoPath);
@ -437,25 +404,27 @@ BOOL myadTaskManualStop = NO;
tempBfaceDictKey = [[NSMutableDictionary alloc] init]; tempBfaceDictKey = [[NSMutableDictionary alloc] init];
} }
NSString *serverUrl = [[XSPhoneConfig sharedInstance] ServerURL]; NSString *serverUrl = [[XSPhoneConfig sharedInstance] ServerURL];
[tempBfaceDictKey setValue:@"http://127.0.0.1:6000" forKey:@"adbrush_local_url"]; [tempBfaceDictKey setValue:@"http://127.0.0.1:6000" forKey:@"adbrush_local_url"];
[tempBfaceDictKey setValue:serverUrl forKey:@"adbrush_base_url"]; [tempBfaceDictKey setValue:serverUrl forKey:@"adbrush_base_url"];
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
getLowEcpm(^(NSNumber *lowEcpm) { getLowEcpm(^(NSNumber *lowEcpm) {
__strong typeof(weakSelf) strongSelf = weakSelf; __strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
BOOL washParam = strongSelf->workType == 0 ? YES : NO; BOOL washParam = strongSelf->workType == 0 ? YES : NO;
[tempBfaceDictKey setValue:@(washParam) forKey:@"washParam"]; [tempBfaceDictKey setValue:@(washParam) forKey:@"washParam"];
[tempBfaceDictKey setValue:lowEcpm forKey:@"adbrush_ecpm"]; [tempBfaceDictKey setValue:lowEcpm forKey:@"adbrush_ecpm"];
if(strongSelf->linkId) { if(strongSelf->linkId) {
[tempBfaceDictKey setValue:strongSelf->linkId forKey:@"linkId"]; [tempBfaceDictKey setValue:strongSelf->linkId forKey:@"linkId"];
} else { } else {
NSString *linkId = [[NSUUID UUID] UUIDString]; NSString *linkId = [[NSUUID UUID] UUIDString];
[tempBfaceDictKey setValue:linkId forKey:@"linkId"]; [tempBfaceDictKey setValue:linkId forKey:@"linkId"];
} }
if(strongSelf->dataId) { if(strongSelf->dataId) {
[tempBfaceDictKey setValue:strongSelf->dataId forKey:@"dataId"]; [tempBfaceDictKey setValue:strongSelf->dataId forKey:@"dataId"];
} else { } else {
NSString *dataId = @"0"; NSString *dataId = @"0";
[tempBfaceDictKey setValue:dataId forKey:@"dataId"]; [tempBfaceDictKey setValue:dataId forKey:@"dataId"];
} }
@ -464,7 +433,7 @@ BOOL myadTaskManualStop = NO;
} }
uint16_t udp_port = [XUDPServer sharedInstance].udp_port; uint16_t udp_port = [XUDPServer sharedInstance].udp_port;
[tempBfaceDictKey setValue:@(udp_port) forKey:@"udp_port"]; [tempBfaceDictKey setValue:@(udp_port) forKey:@"udp_port"];
NSLog(@"XS- resetApp 1"); NSLog(@"XS- resetApp 1");
NSMutableDictionary *tempAppInfo = [[NSMutableDictionary alloc] init]; NSMutableDictionary *tempAppInfo = [[NSMutableDictionary alloc] init];
[tempAppInfo setValue:tempBfaceDictKey forKey:@"bfaceDictKey"]; [tempAppInfo setValue:tempBfaceDictKey forKey:@"bfaceDictKey"];
@ -475,12 +444,14 @@ BOOL myadTaskManualStop = NO;
callback(); callback();
}); });
} }
- (NSString *) frontMostAppId {
- (NSString *)frontMostAppId {
return XSFrontMostAppId(); return XSFrontMostAppId();
} }
- (void) appRun:(NSString *)appId {
- (void)appRun:(NSString *)appId {
if ([XSHelper strIsEmpty:appId]) return; if ([XSHelper strIsEmpty:appId]) return;
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
@try { @try {
bringAppToForeground(appId); bringAppToForeground(appId);
@ -490,22 +461,27 @@ BOOL myadTaskManualStop = NO;
}); });
} }
- (void) tap: (int) i x:(int)x y:(int)y { - (void)tap:(int)i x:(int)x y:(int)y {
} }
- (void) restart: (OnEndCallback) callback { - (void)restart:(OnEndCallback)callback {
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
dispatch_async(self.manQueue, ^{ dispatch_async(self.manQueue, ^{
@try { @try {
__strong typeof(weakSelf) strongSelf = weakSelf; __strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
[weakSelf appKill:@"com.apple.AppStore"]; [weakSelf appKill:@"com.apple.AppStore"];
[weakSelf appKill:@"com.apple.mobilesafari"]; [weakSelf appKill:@"com.apple.mobilesafari"];
if (strongSelf->taskAppId && ![strongSelf->taskAppId isEqual:[NSNull null]] && [strongSelf->taskAppId length] > 0) { if (strongSelf->taskAppId && ![strongSelf->taskAppId isEqual:[NSNull null]] && [strongSelf->taskAppId length] > 0) {
[weakSelf appKill:strongSelf->taskAppId]; [weakSelf appKill:strongSelf->taskAppId];
[weakSelf unlock]; [weakSelf unlock];
sleep(1);
[weakSelf unlock]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC),
[weakSelf resetApp:strongSelf->taskAppId callback:callback]; strongSelf.manQueue, ^{
[weakSelf unlock];
[weakSelf resetApp:strongSelf->taskAppId callback:callback];
});
} }
} @catch (NSException *exception) { } @catch (NSException *exception) {
NSLog(@"Error in restart: %@", exception); NSLog(@"Error in restart: %@", exception);
@ -513,44 +489,73 @@ BOOL myadTaskManualStop = NO;
}); });
} }
- (void)rndTouchApp {
- (void) rndTouchApp {
int times = [XSHelper random:2 and:4]; int times = [XSHelper random:2 and:4];
for (int i = 1; i <= times; i++) { [self _rndTouchAppRecursive:0 totalTimes:times];
int x = [XSHelper random:40 and:screen_w - 20];
int y = [XSHelper random:50 and:screen_h - 240];
NSString* appId = [self frontMostAppId];
if ([appId isEqual:self->taskAppId]) {
[self tap:1 x:x y:y];
usleep(2000);
} else {
break;
}
}
} }
- (void) touchAppTask: (int) beforeTouch { - (void)_rndTouchAppRecursive:(int)currentIndex totalTimes:(int)times {
if (beforeTouch > 0) { if (currentIndex >= times) {
sleep(beforeTouch); return;
} }
[self rndTouchApp];
sleep(2);
int x = [XSHelper random:40 and:screen_w - 20]; int x = [XSHelper random:40 and:screen_w - 20];
int y = [XSHelper random:50 and:screen_h - 240]; int y = [XSHelper random:50 and:screen_h - 240];
[self tap:1 x:x y:y]; NSString* appId = [self frontMostAppId];
NSString* appId = [ self frontMostAppId]; if ([appId isEqual:self->taskAppId]) {
[self tap:1 x:x y:y];
if (![appId isEqual: self->taskAppId]) {
// [self appKill:appId]; __weak typeof(self) weakSelf = self;
sleep(1); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.002 * NSEC_PER_SEC)),
self.manQueue, ^{
[weakSelf _rndTouchAppRecursive:currentIndex + 1 totalTimes:times];
});
} }
[self appRun:self->taskAppId];
} }
- (NSString*) getStr: (NSString *) key dic: (NSDictionary*) dic {
- (void)touchAppTask:(int)beforeTouch {
__weak typeof(self) weakSelf = self;
double delaySec = beforeTouch;
void (^touchBlock)(void) = ^{
[weakSelf rndTouchApp];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
weakSelf.manQueue, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
int x = [XSHelper random:40 and:strongSelf->screen_w - 20];
int y = [XSHelper random:50 and:strongSelf->screen_h - 240];
[strongSelf tap:1 x:x y:y];
NSString* appId = [strongSelf frontMostAppId];
if (![appId isEqual:strongSelf->taskAppId]) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC),
strongSelf.manQueue, ^{
__strong typeof(weakSelf) strongSelf2 = weakSelf;
if (!strongSelf2) return;
[strongSelf2 appRun:strongSelf2->taskAppId];
});
} else {
[strongSelf appRun:strongSelf->taskAppId];
}
});
};
if (delaySec > 0) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySec * NSEC_PER_SEC)),
self.manQueue, touchBlock);
} else {
touchBlock();
}
}
- (NSString*)getStr:(NSString *)key dic:(NSDictionary*)dic {
NSLog(@"getStr: %@", key); NSLog(@"getStr: %@", key);
id t_idfa = dic[key]; id t_idfa = dic[key];
if (t_idfa && ![t_idfa isEqual:[NSNull null]] && ![t_idfa isEqual:@""]) { if (t_idfa && ![t_idfa isEqual:[NSNull null]] && ![t_idfa isEqual:@""]) {
@ -560,29 +565,29 @@ BOOL myadTaskManualStop = NO;
return @""; return @"";
} }
} }
- (NSNumber*) getNum: (NSString *) key dic: (NSDictionary*) dic {
- (NSNumber*)getNum:(NSString *)key dic:(NSDictionary*)dic {
NSLog(@"getNum: %@", key); NSLog(@"getNum: %@", key);
id t_idfa = dic[key]; id t_idfa = dic[key];
NSString *ecpm_str = [NSString stringWithFormat:@"%@" , t_idfa]; NSString *ecpm_str = [NSString stringWithFormat:@"%@", t_idfa];
NSNumber *ecpm = @0.0; NSNumber *ecpm = @0.0;
if (ecpm_str && ![ecpm_str isEqual:[NSNull null]] && ![ecpm_str isEqual:@""]) { if (ecpm_str && ![ecpm_str isEqual:[NSNull null]] && ![ecpm_str isEqual:@""]) {
ecpm = [XSHelper str2num: ecpm_str]; ecpm = [XSHelper str2num:ecpm_str];
} }
return ecpm; return ecpm;
} }
- (int) getInt: (NSString *) key dic: (NSDictionary*) dic { - (int)getInt:(NSString *)key dic:(NSDictionary*)dic {
NSLog(@"getInt: %@", key); NSLog(@"getInt: %@", key);
id t_idfa = dic[key]; id t_idfa = dic[key];
NSString *ecpm_str = [NSString stringWithFormat:@"%@" , t_idfa]; NSString *ecpm_str = [NSString stringWithFormat:@"%@", t_idfa];
NSNumber *ecpm = @(-99); NSNumber *ecpm = @(-99);
if (ecpm_str && ![ecpm_str isEqual:[NSNull null]] && ![ecpm_str isEqual:@""]) { if (ecpm_str && ![ecpm_str isEqual:[NSNull null]] && ![ecpm_str isEqual:@""]) {
ecpm = [XSHelper str2num: ecpm_str]; ecpm = [XSHelper str2num:ecpm_str];
} }
return [ecpm intValue]; return [ecpm intValue];
} }
@ -591,5 +596,4 @@ BOOL myadTaskManualStop = NO;
[self stop]; [self stop];
} }
@end @end

View File

@ -9,16 +9,18 @@
#define FALLBACK_PORT_START 6001 #define FALLBACK_PORT_START 6001
#define FALLBACK_PORT_END 7000 #define FALLBACK_PORT_END 7000
#define PORT 6001 #define PORT 6001
#define SEND_TIMEOUT 5.0 // #define SEND_TIMEOUT 5.0
@interface XUDPServer() { @interface XUDPServer() {
@private @private
GCDAsyncUdpSocket *serverSocket; GCDAsyncUdpSocket *serverSocket;
dispatch_queue_t serverQueue; dispatch_queue_t serverQueue;
dispatch_source_t restartTimer; dispatch_source_t restartTimer;
dispatch_source_t healthCheckTimer; // dispatch_source
NSUInteger restartAttempts; NSUInteger restartAttempts;
uint16_t currentPort; uint16_t currentPort;
NSTimer *healthCheckTimer; BOOL isStarting;
BOOL isStopping;
} }
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSDictionary *> *pendingSends; @property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSDictionary *> *pendingSends;
@ -34,24 +36,28 @@
static XUDPServer* _sharedInstance = nil; static XUDPServer* _sharedInstance = nil;
static dispatch_once_t oncePredicate; static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{ dispatch_once(&oncePredicate, ^{
_sharedInstance = [[XUDPServer alloc] init]; _sharedInstance = [[super allocWithZone:NULL] init];
}); });
return _sharedInstance; return _sharedInstance;
} }
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [XUDPServer sharedInstance];
}
- (instancetype)init { - (instancetype)init {
if (self = [super init]) { self = [super init];
if (self) {
restartAttempts = 0; restartAttempts = 0;
currentPort = PORT; currentPort = PORT;
_currentTag = 0; _currentTag = 0;
isStarting = NO;
isStopping = NO;
_pendingSends = [NSMutableDictionary dictionary]; _pendingSends = [NSMutableDictionary dictionary];
//
serverQueue = dispatch_queue_create("com.xudpserver.queue", DISPATCH_QUEUE_SERIAL); serverQueue = dispatch_queue_create("com.xudpserver.queue", DISPATCH_QUEUE_SERIAL);
return self;
} }
return nil; return self;
} }
- (void)start { - (void)start {
@ -61,42 +67,71 @@
} }
- (uint16_t)udp_port { - (uint16_t)udp_port {
return currentPort; __block uint16_t port = 0;
// ,使
if (dispatch_get_specific((__bridge const void *)serverQueue)) {
// serverQueue
port = currentPort;
} else {
dispatch_sync(serverQueue, ^{
port = self->currentPort;
});
}
return port;
} }
- (void)_startInternal { - (void)_startInternal {
NSLog(@"XS- Starting UDP server on port %d", currentPort); if (isStarting) {
NSLog(@"⚠️ Server is already starting");
return;
}
//
if (serverSocket && !serverSocket.isClosed) { if (serverSocket && !serverSocket.isClosed) {
NSLog(@"⚠️ UDP server already running on port %d", currentPort); NSLog(@"⚠️ UDP server already running on port %d", currentPort);
return; return;
} }
[self _stopInternal]; isStarting = YES;
NSLog(@"XS- Starting UDP server on port %d (PID: %d)", currentPort, getpid());
[self _forceCloseSocket];
// 使dispatch_afterusleep,
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)),
serverQueue, ^{
[self _startInternalContinue];
});
}
- (void)_startInternalContinue {
serverSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self serverSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self
delegateQueue:serverQueue]; delegateQueue:serverQueue];
NSError *error = nil; NSError *error = nil;
// // 使IPv4
[serverSocket setIPv4Enabled:YES];
[serverSocket setIPv6Enabled:NO];
if (![serverSocket enableReusePort:YES error:&error]) { if (![serverSocket enableReusePort:YES error:&error]) {
NSLog(@"❌ Error enabling reuse port: %@", error); NSLog(@"❌ Error enabling reuse port: %@", error);
} }
// socket
[self _configureSocketOptions];
//
if (![serverSocket bindToPort:currentPort error:&error]) { if (![serverSocket bindToPort:currentPort error:&error]) {
NSLog(@"❌ Error binding to port %d: %@", currentPort, error); NSLog(@"❌ Error binding to port %d: %@", currentPort, error);
[serverSocket close]; [self _forceCloseSocket];
serverSocket = nil; isStarting = NO;
if (error.code == 48) { // EADDRINUSE if (error.code == 48) { // EADDRINUSE
NSLog(@"⚠️ Port %d is in use (possibly TIME_WAIT)", currentPort); NSLog(@"⚠️ Port %d is in use", currentPort);
// ,
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self _cleanupZombieSockets];
});
[self _tryFallbackPorts]; [self _tryFallbackPorts];
return; return;
} }
@ -105,75 +140,137 @@
return; return;
} }
[self _configureSocketOptions];
if (![serverSocket beginReceiving:&error]) { if (![serverSocket beginReceiving:&error]) {
NSLog(@"❌ Error starting server (recv): %@", error); NSLog(@"❌ Error starting server (recv): %@", error);
[serverSocket close]; [self _forceCloseSocket];
serverSocket = nil; isStarting = NO;
[self _scheduleRestartWithBackoff]; [self _scheduleRestartWithBackoff];
return; return;
} }
isStarting = NO;
restartAttempts = 0; restartAttempts = 0;
[self _logSocketInfo];
NSLog(@"✅ UDP server started successfully on port %d", currentPort); NSLog(@"✅ UDP server started successfully on port %d", currentPort);
//
[self _startHealthCheck]; [self _startHealthCheck];
} }
// socket - (void)_forceCloseSocket {
if (serverSocket) {
int fd = [serverSocket socketFD];
if (fd != -1) {
//
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
struct linger lingerOption = {1, 0};
setsockopt(fd, SOL_SOCKET, SO_LINGER, &lingerOption, sizeof(lingerOption));
// shutdown,使dispatch_async
int fdCopy = fd;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
shutdown(fdCopy, SHUT_RDWR);
});
}
[serverSocket close];
serverSocket = nil;
NSLog(@"🔒 Socket closed (fd: %d)", fd);
}
}
- (void)_cleanupZombieSockets {
NSLog(@"🧹 Cleaning up zombie sockets on port %d", currentPort);
int testSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (testSocket < 0) {
return;
}
//
fcntl(testSocket, F_SETFL, fcntl(testSocket, F_GETFL, 0) | O_NONBLOCK);
int reuseAddr = 1;
setsockopt(testSocket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
struct linger lingerOption = {1, 0};
setsockopt(testSocket, SOL_SOCKET, SO_LINGER, &lingerOption, sizeof(lingerOption));
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(currentPort);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(testSocket, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
shutdown(testSocket, SHUT_RDWR);
NSLog(@"✅ Cleaned up zombie socket on port %d", currentPort);
}
close(testSocket);
}
- (void)_logSocketInfo {
if (!serverSocket) return;
int fd = [serverSocket socketFD];
if (fd == -1) return;
struct sockaddr_in addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(fd, (struct sockaddr *)&addr, &addrLen) == 0) {
char ipStr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr.sin_addr, ipStr, sizeof(ipStr));
NSLog(@"📊 Socket - FD: %d, Addr: %s:%d, PID: %d",
fd, ipStr, ntohs(addr.sin_port), getpid());
}
int recvBuf, sendBuf;
socklen_t optLen = sizeof(int);
getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvBuf, &optLen);
getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendBuf, &optLen);
NSLog(@"📊 Buffers - Recv: %d, Send: %d", recvBuf, sendBuf);
}
- (void)_configureSocketOptions { - (void)_configureSocketOptions {
if (!serverSocket) return; if (!serverSocket) return;
int fd = [serverSocket socketFD]; int fd = [serverSocket socketFD];
if (fd == -1) { if (fd == -1) return;
NSLog(@"⚠️ Invalid socket file descriptor");
return;
}
// 1. SO_REUSEADDR - ,TIME_WAIT // SO_REUSEADDR
int reuseAddr = 1; int reuseAddr = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) == -1) { setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
NSLog(@"❌ Error setting SO_REUSEADDR: %s", strerror(errno));
}
// 2. SO_REUSEPORT - socket() //
int reusePort = 1; int recvBufferSize = 256 * 1024;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reusePort, sizeof(reusePort)) == -1) { setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvBufferSize, sizeof(recvBufferSize));
NSLog(@"⚠️ SO_REUSEPORT not supported or error: %s", strerror(errno));
}
// 3. , int sendBufferSize = 256 * 1024;
int recvBufferSize = 256 * 1024; // 256KB setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendBufferSize, sizeof(sendBufferSize));
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvBufferSize, sizeof(recvBufferSize)) == -1) {
NSLog(@"⚠️ Failed to set receive buffer size: %s", strerror(errno));
} else {
//
socklen_t optlen = sizeof(recvBufferSize);
getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvBufferSize, &optlen);
NSLog(@"✅ Receive buffer size set to: %d bytes", recvBufferSize);
}
// 4. // SO_NOSIGPIPE
int sendBufferSize = 256 * 1024; // 256KB
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendBufferSize, sizeof(sendBufferSize)) == -1) {
NSLog(@"⚠️ Failed to set send buffer size: %s", strerror(errno));
} else {
socklen_t optlen = sizeof(sendBufferSize);
getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendBufferSize, &optlen);
NSLog(@"✅ Send buffer size set to: %d bytes", sendBufferSize);
}
// 5. SO_NOSIGPIPE - socketSIGPIPE
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
int noSigpipe = 1; int noSigpipe = 1;
if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &noSigpipe, sizeof(noSigpipe)) == -1) { setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &noSigpipe, sizeof(noSigpipe));
NSLog(@"⚠️ Failed to set SO_NOSIGPIPE: %s", strerror(errno));
}
#endif #endif
// 6. (GCDAsyncUdpSocket,) // SO_LINGER
struct linger lingerOption = {1, 0};
setsockopt(fd, SOL_SOCKET, SO_LINGER, &lingerOption, sizeof(lingerOption));
//
int flags = fcntl(fd, F_GETFL, 0); int flags = fcntl(fd, F_GETFL, 0);
if (flags != -1) { if (flags != -1) {
fcntl(fd, F_SETFL, flags | O_NONBLOCK); fcntl(fd, F_SETFL, flags | O_NONBLOCK);
@ -187,84 +284,126 @@
} }
- (void)_stopInternal { - (void)_stopInternal {
if (isStopping) {
NSLog(@"⚠️ Server is already stopping");
return;
}
isStopping = YES;
NSLog(@"XS- Stopping UDP server on port %d", currentPort); NSLog(@"XS- Stopping UDP server on port %d", currentPort);
[self _cancelRestartTimer]; [self _cancelRestartTimer];
[self _stopHealthCheck]; [self _stopHealthCheck];
if (serverSocket) { [self _forceCloseSocket];
// SO_LINGER0,,TIME_WAIT
int fd = [serverSocket socketFD];
if (fd != -1) {
struct linger lingerOption = {1, 0}; // l_onoff=1, l_linger=0
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lingerOption, sizeof(lingerOption)) == -1) {
NSLog(@"⚠️ Failed to set SO_LINGER: %s", strerror(errno));
}
}
if (!serverSocket.isClosed) {
[serverSocket close];
}
serverSocket = nil;
}
[_pendingSends removeAllObjects]; [_pendingSends removeAllObjects];
// 使dispatch_afterusleep
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)),
serverQueue, ^{
self->isStopping = NO;
NSLog(@"✅ UDP server stopped");
});
} }
#pragma mark - Health Check #pragma mark - Health Check
//
- (void)_startHealthCheck { - (void)_startHealthCheck {
dispatch_async(dispatch_get_main_queue(), ^{ // 使dispatch_sourceNSTimer,线
if (self->healthCheckTimer) { if (healthCheckTimer) {
[self->healthCheckTimer invalidate]; dispatch_source_cancel(healthCheckTimer);
} healthCheckTimer = nil;
}
self->healthCheckTimer = [NSTimer scheduledTimerWithTimeInterval:30.0
target:self healthCheckTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, serverQueue);
selector:@selector(_performHealthCheck)
userInfo:nil dispatch_source_set_timer(healthCheckTimer,
repeats:YES]; dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC),
30 * NSEC_PER_SEC,
1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(healthCheckTimer, ^{
[self _performHealthCheck];
}); });
dispatch_resume(healthCheckTimer);
} }
- (void)_stopHealthCheck { - (void)_stopHealthCheck {
dispatch_async(dispatch_get_main_queue(), ^{ if (healthCheckTimer) {
if (self->healthCheckTimer) { dispatch_source_cancel(healthCheckTimer);
[self->healthCheckTimer invalidate]; healthCheckTimer = nil;
self->healthCheckTimer = nil; }
}
});
} }
- (void)_performHealthCheck { - (void)_performHealthCheck {
dispatch_async(serverQueue, ^{ if (isStarting || isStopping) {
if (!self->serverSocket || self->serverSocket.isClosed) { return;
NSLog(@"⚠️ Health check failed: socket is closed"); }
[self _startInternal];
return; if (!serverSocket || serverSocket.isClosed) {
} NSLog(@"⚠️ Health check failed: socket is closed");
[self _startInternal];
// socket return;
int fd = [self->serverSocket socketFD]; }
if (fd == -1) {
NSLog(@"⚠️ Health check failed: invalid socket"); int fd = [serverSocket socketFD];
[self _startInternal]; if (fd == -1) {
return; NSLog(@"⚠️ Health check failed: invalid socket");
} [self _startInternal];
return;
// }
struct sockaddr_in addr;
socklen_t addrLen = sizeof(addr); struct sockaddr_in addr;
if (getsockname(fd, (struct sockaddr *)&addr, &addrLen) == -1) { socklen_t addrLen = sizeof(addr);
NSLog(@"⚠️ Health check failed: socket not bound"); if (getsockname(fd, (struct sockaddr *)&addr, &addrLen) == -1) {
[self _startInternal]; NSLog(@"⚠️ Health check failed: socket not bound");
return; [self _startInternal];
} return;
}
NSLog(@"✅ Health check passed for port %d", self->currentPort);
// socket,
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self _checkDuplicateSockets];
}); });
NSLog(@"✅ Health check passed (Port: %d, FD: %d)", currentPort, fd);
}
- (void)_checkDuplicateSockets {
// ,popen
NSString *command = [NSString stringWithFormat:@"timeout 2 lsof -i UDP:%d -n -P 2>/dev/null || echo timeout", currentPort];
FILE *pipe = popen([command UTF8String], "r");
if (!pipe) {
return;
}
char buffer[256];
int count = 0;
BOOL timedOut = NO;
while (fgets(buffer, sizeof(buffer), pipe) != NULL) {
if (strstr(buffer, "timeout") != NULL) {
timedOut = YES;
break;
}
count++;
}
pclose(pipe);
if (timedOut) {
NSLog(@"⚠️ Socket check timed out");
return;
}
count = MAX(0, count - 1);
if (count > 1) {
NSLog(@"⚠️ WARNING: Found %d sockets on port %d!", count, currentPort);
}
} }
#pragma mark - Restart Logic #pragma mark - Restart Logic
@ -281,17 +420,14 @@
const NSUInteger maxAttempts = 10; const NSUInteger maxAttempts = 10;
if (restartAttempts >= maxAttempts) { if (restartAttempts >= maxAttempts) {
NSLog(@"❌ Maximum restart attempts (%lu) reached, giving up", NSLog(@"❌ Maximum restart attempts reached");
(unsigned long)maxAttempts);
return; return;
} }
restartAttempts++; restartAttempts++;
NSTimeInterval delay = MIN(pow(2, restartAttempts - 1), 60.0); NSTimeInterval delay = MIN(pow(2, restartAttempts - 1), 60.0);
NSLog(@"⏰ Scheduling restart attempt %lu in %.1f seconds", NSLog(@"⏰ Scheduling restart in %.1f seconds", delay);
(unsigned long)restartAttempts, delay);
restartTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, serverQueue); restartTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, serverQueue);
@ -308,10 +444,12 @@
} }
- (void)_tryFallbackPorts { - (void)_tryFallbackPorts {
NSLog(@"🔍 Searching for available fallback port..."); NSLog(@"🔍 Searching for fallback port...");
for (uint16_t port = FALLBACK_PORT_START; port <= FALLBACK_PORT_END; port++) { // ,
// uint16_t scanLimit = MIN(FALLBACK_PORT_END, FALLBACK_PORT_START + 100);
for (uint16_t port = FALLBACK_PORT_START; port <= scanLimit; port++) {
if ([self _isPortAvailable:port]) { if ([self _isPortAvailable:port]) {
currentPort = port; currentPort = port;
NSLog(@"✅ Found available port: %d", port); NSLog(@"✅ Found available port: %d", port);
@ -320,20 +458,23 @@
} }
} }
NSLog(@"❌ No available fallback ports found in range %d-%d", NSLog(@"❌ No available fallback ports");
FALLBACK_PORT_START, FALLBACK_PORT_END);
[self _scheduleRestartWithBackoff]; [self _scheduleRestartWithBackoff];
} }
// ()
- (BOOL)_isPortAvailable:(uint16_t)port { - (BOOL)_isPortAvailable:(uint16_t)port {
int testSocket = socket(AF_INET, SOCK_DGRAM, 0); int testSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (testSocket < 0) { if (testSocket < 0) {
NSLog(@"⚠️ Cannot create test socket");
return NO; return NO;
} }
// SO_REUSEADDR //
fcntl(testSocket, F_SETFL, fcntl(testSocket, F_GETFL, 0) | O_NONBLOCK);
struct timeval timeout = {1, 0}; // 1
setsockopt(testSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
setsockopt(testSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
int reuseAddr = 1; int reuseAddr = 1;
setsockopt(testSocket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)); setsockopt(testSocket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
@ -346,14 +487,7 @@
int result = bind(testSocket, (struct sockaddr *)&addr, sizeof(addr)); int result = bind(testSocket, (struct sockaddr *)&addr, sizeof(addr));
close(testSocket); close(testSocket);
if (result == 0) { return (result == 0);
return YES;
} else {
if (errno == EADDRINUSE) {
NSLog(@"⚠️ Port %d is in use", port);
}
return NO;
}
} }
- (void)scheduleRestart { - (void)scheduleRestart {
@ -366,7 +500,7 @@
#pragma mark - GCDAsyncUdpSocket Delegate #pragma mark - GCDAsyncUdpSocket Delegate
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address { - (void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address {
NSLog(@"✅ Connected to client"); NSLog(@"✅ Connected");
} }
- (void)udpSocket:(GCDAsyncUdpSocket *)sock - (void)udpSocket:(GCDAsyncUdpSocket *)sock
@ -374,75 +508,57 @@
fromAddress:(NSData *)address fromAddress:(NSData *)address
withFilterContext:(id)filterContext { withFilterContext:(id)filterContext {
@autoreleasepool { @autoreleasepool {
// , if (data.length > 65507) {
if (data.length > 65507) { // UDP NSLog(@"⚠️ Oversized packet: %lu bytes", (unsigned long)data.length);
NSLog(@"⚠️ Received oversized packet: %lu bytes", (unsigned long)data.length);
return; return;
} }
NSString *datastr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSString *datastr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (!datastr) { if (!datastr) {
NSLog(@"⚠️ Failed to decode received data (length: %lu)", (unsigned long)data.length); NSLog(@"⚠️ Failed to decode data");
return; return;
} }
NSLog(@"📨 UDP Request from %@: %@", // ,
[self _addressToString:address],
[datastr substringToIndex:MIN(100, datastr.length)]);
// ,
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UDPHandler *handle = [UDPHandler sharedInstance]; @autoreleasepool {
NSString *res = [handle handle:datastr]; UDPHandler *handle = [UDPHandler sharedInstance];
NSString *res = [handle handle:datastr];
if (res) {
[self _sendResponse:res toAddress:address fromSocket:sock]; if (res) {
[self _sendResponse:res toAddress:address fromSocket:sock];
}
} }
}); });
} }
} }
// ()
- (void)_sendResponse:(NSString *)response - (void)_sendResponse:(NSString *)response
toAddress:(NSData *)address toAddress:(NSData *)address
fromSocket:(GCDAsyncUdpSocket *)sock { fromSocket:(GCDAsyncUdpSocket *)sock {
dispatch_async(serverQueue, ^{ dispatch_async(serverQueue, ^{
if (!sock || sock.isClosed) { if (!sock || sock.isClosed) {
NSLog(@"⚠️ Cannot send response: socket is closed");
return; return;
} }
NSData *responseData = [response dataUsingEncoding:NSUTF8StringEncoding]; NSData *responseData = [response dataUsingEncoding:NSUTF8StringEncoding];
if (!responseData) { if (!responseData || responseData.length > 65507) {
NSLog(@"⚠️ Failed to encode response");
return;
}
//
if (responseData.length > 65507) {
NSLog(@"⚠️ Response too large: %lu bytes (max 65507)",
(unsigned long)responseData.length);
return; return;
} }
long tag = ++self->_currentTag; long tag = ++self->_currentTag;
//
self->_pendingSends[@(tag)] = @{ self->_pendingSends[@(tag)] = @{
@"response": response, @"response": response,
@"address": address, @"address": address,
@"timestamp": @([[NSDate date] timeIntervalSince1970]) @"timestamp": @([[NSDate date] timeIntervalSince1970])
}; };
NSLog(@"📤 Sending response (tag: %ld, size: %lu bytes)",
tag, (unsigned long)responseData.length);
[sock sendData:responseData [sock sendData:responseData
toAddress:address toAddress:address
withTimeout:SEND_TIMEOUT withTimeout:SEND_TIMEOUT
tag:tag]; tag:tag];
//
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((SEND_TIMEOUT + 1.0) * NSEC_PER_SEC)), dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((SEND_TIMEOUT + 1.0) * NSEC_PER_SEC)),
self->serverQueue, ^{ self->serverQueue, ^{
[self _checkSendTimeout:tag]; [self _checkSendTimeout:tag];
@ -450,14 +566,9 @@ withFilterContext:(id)filterContext {
}); });
} }
//
- (void)_checkSendTimeout:(long)tag { - (void)_checkSendTimeout:(long)tag {
NSDictionary *pendingData = _pendingSends[@(tag)]; NSDictionary *pendingData = _pendingSends[@(tag)];
if (pendingData) { if (pendingData) {
NSTimeInterval timestamp = [pendingData[@"timestamp"] doubleValue];
NSTimeInterval elapsed = [[NSDate date] timeIntervalSince1970] - timestamp;
NSLog(@"⏱️ Send timeout for tag %ld (elapsed: %.1fs)", tag, elapsed);
[_pendingSends removeObjectForKey:@(tag)]; [_pendingSends removeObjectForKey:@(tag)];
} }
} }
@ -467,47 +578,36 @@ withFilterContext:(id)filterContext {
} }
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag { - (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag {
NSLog(@"✅ Data sent successfully (tag: %ld)", tag);
[_pendingSends removeObjectForKey:@(tag)]; [_pendingSends removeObjectForKey:@(tag)];
} }
- (void)udpSocket:(GCDAsyncUdpSocket *)sock - (void)udpSocket:(GCDAsyncUdpSocket *)sock
didNotSendDataWithTag:(long)tag didNotSendDataWithTag:(long)tag
dueToError:(NSError *)error { dueToError:(NSError *)error {
NSLog(@"❌ Failed to send data (tag: %ld): %@", tag, error);
[_pendingSends removeObjectForKey:@(tag)]; [_pendingSends removeObjectForKey:@(tag)];
// if (error.code == 57) { // ENOTCONN
if (error.code == 55) { // ENOBUFS
NSLog(@"⚠️ Buffer full (ENOBUFS) - system may be overloaded");
} else if (error.code == 57) { // ENOTCONN
NSLog(@"⚠️ Socket disconnected (ENOTCONN)");
[self _startInternal]; [self _startInternal];
} else if (error.code == 64) { // EHOSTDOWN
NSLog(@"⚠️ Host is down (EHOSTDOWN)");
} else if (error.code == 65) { // EHOSTUNREACH
NSLog(@"⚠️ Host unreachable (EHOSTUNREACH)");
} }
} }
- (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error { - (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error {
NSLog(@"⚠️ Socket closed. Error: %@", error); NSLog(@"⚠️ Socket closed: %@", error);
if (sock == serverSocket) { if (sock == serverSocket) {
serverSocket = nil; serverSocket = nil;
} }
if (error) { if (error && !isStopping) {
NSLog(@"❌ Unexpected closure, scheduling restart");
[self scheduleRestart]; [self scheduleRestart];
} }
} }
#pragma mark - Utility Methods
//
- (NSString *)_addressToString:(NSData *)addressData { - (NSString *)_addressToString:(NSData *)addressData {
if (addressData.length < sizeof(struct sockaddr_in)) {
return @"unknown";
}
struct sockaddr_in *addr = (struct sockaddr_in *)addressData.bytes; struct sockaddr_in *addr = (struct sockaddr_in *)addressData.bytes;
char ipStr[INET_ADDRSTRLEN]; char ipStr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr->sin_addr, ipStr, sizeof(ipStr)); inet_ntop(AF_INET, &addr->sin_addr, ipStr, sizeof(ipStr));

69455
a1.log Normal file

File diff suppressed because it is too large Load Diff

13
ips.txt
View File

@ -1,3 +1,10 @@
172.28.4.29 192.168.1.15
172.28.7.13 192.168.1.19
172.28.7.22 192.168.1.18
192.168.1.20
192.168.1.11
192.168.1.21
192.168.1.14
192.168.1.16
192.168.1.13
192.168.1.17

BIN
packages/20251109.deb Normal file

Binary file not shown.

BIN
packages/251105-nt.deb Normal file

Binary file not shown.

BIN
packages/251106-nt.deb Normal file

Binary file not shown.

BIN
packages/251106a-nt.deb Normal file

Binary file not shown.

BIN
packages/251106b-nt.deb Normal file

Binary file not shown.