修改sleep 问题和udp服务问题

This commit is contained in:
xsean 2025-11-06 11:38:46 +08:00
parent a8a122a6e0
commit 1fb432a784
27 changed files with 71847 additions and 2249 deletions

View File

@ -6,5 +6,5 @@ Author: XYZShell
Section: Utilities
Tag: role::developer
Architecture: iphoneos-arm
Version: 0.0.7-10-62+debug
Installed-Size: 1604
Version: 0.0.7-10-66+debug
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-66+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
66

View File

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

View File

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

View File

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

View File

@ -9,16 +9,18 @@
#define FALLBACK_PORT_START 6001
#define FALLBACK_PORT_END 7000
#define PORT 6001
#define SEND_TIMEOUT 5.0 //
#define SEND_TIMEOUT 5.0
@interface XUDPServer() {
@private
GCDAsyncUdpSocket *serverSocket;
dispatch_queue_t serverQueue;
dispatch_source_t restartTimer;
dispatch_source_t healthCheckTimer; // dispatch_source
NSUInteger restartAttempts;
uint16_t currentPort;
NSTimer *healthCheckTimer;
BOOL isStarting;
BOOL isStopping;
}
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSDictionary *> *pendingSends;
@ -34,24 +36,28 @@
static XUDPServer* _sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[XUDPServer alloc] init];
_sharedInstance = [[super allocWithZone:NULL] init];
});
return _sharedInstance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [XUDPServer sharedInstance];
}
- (instancetype)init {
if (self = [super init]) {
self = [super init];
if (self) {
restartAttempts = 0;
currentPort = PORT;
_currentTag = 0;
isStarting = NO;
isStopping = NO;
_pendingSends = [NSMutableDictionary dictionary];
//
serverQueue = dispatch_queue_create("com.xudpserver.queue", DISPATCH_QUEUE_SERIAL);
return self;
}
return nil;
return self;
}
- (void)start {
@ -61,42 +67,71 @@
}
- (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 {
NSLog(@"XS- Starting UDP server on port %d", currentPort);
if (isStarting) {
NSLog(@"⚠️ Server is already starting");
return;
}
//
if (serverSocket && !serverSocket.isClosed) {
NSLog(@"⚠️ UDP server already running on port %d", currentPort);
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
delegateQueue:serverQueue];
NSError *error = nil;
//
// 使IPv4
[serverSocket setIPv4Enabled:YES];
[serverSocket setIPv6Enabled:NO];
if (![serverSocket enableReusePort:YES error:&error]) {
NSLog(@"❌ Error enabling reuse port: %@", error);
}
// socket
[self _configureSocketOptions];
//
if (![serverSocket bindToPort:currentPort error:&error]) {
NSLog(@"❌ Error binding to port %d: %@", currentPort, error);
[serverSocket close];
serverSocket = nil;
[self _forceCloseSocket];
isStarting = NO;
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];
return;
}
@ -105,75 +140,137 @@
return;
}
[self _configureSocketOptions];
if (![serverSocket beginReceiving:&error]) {
NSLog(@"❌ Error starting server (recv): %@", error);
[serverSocket close];
serverSocket = nil;
[self _forceCloseSocket];
isStarting = NO;
[self _scheduleRestartWithBackoff];
return;
}
isStarting = NO;
restartAttempts = 0;
[self _logSocketInfo];
NSLog(@"✅ UDP server started successfully on port %d", currentPort);
//
[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 {
if (!serverSocket) return;
int fd = [serverSocket socketFD];
if (fd == -1) {
NSLog(@"⚠️ Invalid socket file descriptor");
return;
}
if (fd == -1) return;
// 1. SO_REUSEADDR - ,TIME_WAIT
// SO_REUSEADDR
int reuseAddr = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) == -1) {
NSLog(@"❌ Error setting SO_REUSEADDR: %s", strerror(errno));
}
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
// 2. SO_REUSEPORT - socket()
int reusePort = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reusePort, sizeof(reusePort)) == -1) {
NSLog(@"⚠️ SO_REUSEPORT not supported or error: %s", strerror(errno));
}
//
int recvBufferSize = 256 * 1024;
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvBufferSize, sizeof(recvBufferSize));
// 3. ,
int recvBufferSize = 256 * 1024; // 256KB
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);
}
int sendBufferSize = 256 * 1024;
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendBufferSize, sizeof(sendBufferSize));
// 4.
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
// SO_NOSIGPIPE
#ifdef SO_NOSIGPIPE
int noSigpipe = 1;
if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &noSigpipe, sizeof(noSigpipe)) == -1) {
NSLog(@"⚠️ Failed to set SO_NOSIGPIPE: %s", strerror(errno));
}
setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &noSigpipe, sizeof(noSigpipe));
#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);
if (flags != -1) {
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
@ -187,84 +284,126 @@
}
- (void)_stopInternal {
if (isStopping) {
NSLog(@"⚠️ Server is already stopping");
return;
}
isStopping = YES;
NSLog(@"XS- Stopping UDP server on port %d", currentPort);
[self _cancelRestartTimer];
[self _stopHealthCheck];
if (serverSocket) {
// 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;
}
[self _forceCloseSocket];
[_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
//
- (void)_startHealthCheck {
dispatch_async(dispatch_get_main_queue(), ^{
if (self->healthCheckTimer) {
[self->healthCheckTimer invalidate];
}
self->healthCheckTimer = [NSTimer scheduledTimerWithTimeInterval:30.0
target:self
selector:@selector(_performHealthCheck)
userInfo:nil
repeats:YES];
// 使dispatch_sourceNSTimer,线
if (healthCheckTimer) {
dispatch_source_cancel(healthCheckTimer);
healthCheckTimer = nil;
}
healthCheckTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, serverQueue);
dispatch_source_set_timer(healthCheckTimer,
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 {
dispatch_async(dispatch_get_main_queue(), ^{
if (self->healthCheckTimer) {
[self->healthCheckTimer invalidate];
self->healthCheckTimer = nil;
}
});
if (healthCheckTimer) {
dispatch_source_cancel(healthCheckTimer);
healthCheckTimer = nil;
}
}
- (void)_performHealthCheck {
dispatch_async(serverQueue, ^{
if (!self->serverSocket || self->serverSocket.isClosed) {
NSLog(@"⚠️ Health check failed: socket is closed");
[self _startInternal];
return;
}
// socket
int fd = [self->serverSocket socketFD];
if (fd == -1) {
NSLog(@"⚠️ Health check failed: invalid socket");
[self _startInternal];
return;
}
//
struct sockaddr_in addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(fd, (struct sockaddr *)&addr, &addrLen) == -1) {
NSLog(@"⚠️ Health check failed: socket not bound");
[self _startInternal];
return;
}
NSLog(@"✅ Health check passed for port %d", self->currentPort);
if (isStarting || isStopping) {
return;
}
if (!serverSocket || serverSocket.isClosed) {
NSLog(@"⚠️ Health check failed: socket is closed");
[self _startInternal];
return;
}
int fd = [serverSocket socketFD];
if (fd == -1) {
NSLog(@"⚠️ Health check failed: invalid socket");
[self _startInternal];
return;
}
struct sockaddr_in addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(fd, (struct sockaddr *)&addr, &addrLen) == -1) {
NSLog(@"⚠️ Health check failed: socket not bound");
[self _startInternal];
return;
}
// 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
@ -281,17 +420,14 @@
const NSUInteger maxAttempts = 10;
if (restartAttempts >= maxAttempts) {
NSLog(@"❌ Maximum restart attempts (%lu) reached, giving up",
(unsigned long)maxAttempts);
NSLog(@"❌ Maximum restart attempts reached");
return;
}
restartAttempts++;
NSTimeInterval delay = MIN(pow(2, restartAttempts - 1), 60.0);
NSLog(@"⏰ Scheduling restart attempt %lu in %.1f seconds",
(unsigned long)restartAttempts, delay);
NSLog(@"⏰ Scheduling restart in %.1f seconds", delay);
restartTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, serverQueue);
@ -308,10 +444,12 @@
}
- (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]) {
currentPort = port;
NSLog(@"✅ Found available port: %d", port);
@ -320,20 +458,23 @@
}
}
NSLog(@"❌ No available fallback ports found in range %d-%d",
FALLBACK_PORT_START, FALLBACK_PORT_END);
NSLog(@"❌ No available fallback ports");
[self _scheduleRestartWithBackoff];
}
// ()
- (BOOL)_isPortAvailable:(uint16_t)port {
int testSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (testSocket < 0) {
NSLog(@"⚠️ Cannot create test socket");
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;
setsockopt(testSocket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
@ -346,14 +487,7 @@
int result = bind(testSocket, (struct sockaddr *)&addr, sizeof(addr));
close(testSocket);
if (result == 0) {
return YES;
} else {
if (errno == EADDRINUSE) {
NSLog(@"⚠️ Port %d is in use", port);
}
return NO;
}
return (result == 0);
}
- (void)scheduleRestart {
@ -366,7 +500,7 @@
#pragma mark - GCDAsyncUdpSocket Delegate
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address {
NSLog(@"✅ Connected to client");
NSLog(@"✅ Connected");
}
- (void)udpSocket:(GCDAsyncUdpSocket *)sock
@ -374,75 +508,57 @@
fromAddress:(NSData *)address
withFilterContext:(id)filterContext {
@autoreleasepool {
// ,
if (data.length > 65507) { // UDP
NSLog(@"⚠️ Received oversized packet: %lu bytes", (unsigned long)data.length);
if (data.length > 65507) {
NSLog(@"⚠️ Oversized packet: %lu bytes", (unsigned long)data.length);
return;
}
NSString *datastr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (!datastr) {
NSLog(@"⚠️ Failed to decode received data (length: %lu)", (unsigned long)data.length);
NSLog(@"⚠️ Failed to decode data");
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), ^{
UDPHandler *handle = [UDPHandler sharedInstance];
NSString *res = [handle handle:datastr];
if (res) {
[self _sendResponse:res toAddress:address fromSocket:sock];
@autoreleasepool {
UDPHandler *handle = [UDPHandler sharedInstance];
NSString *res = [handle handle:datastr];
if (res) {
[self _sendResponse:res toAddress:address fromSocket:sock];
}
}
});
}
}
// ()
- (void)_sendResponse:(NSString *)response
toAddress:(NSData *)address
fromSocket:(GCDAsyncUdpSocket *)sock {
dispatch_async(serverQueue, ^{
if (!sock || sock.isClosed) {
NSLog(@"⚠️ Cannot send response: socket is closed");
return;
}
NSData *responseData = [response dataUsingEncoding:NSUTF8StringEncoding];
if (!responseData) {
NSLog(@"⚠️ Failed to encode response");
return;
}
//
if (responseData.length > 65507) {
NSLog(@"⚠️ Response too large: %lu bytes (max 65507)",
(unsigned long)responseData.length);
if (!responseData || responseData.length > 65507) {
return;
}
long tag = ++self->_currentTag;
//
self->_pendingSends[@(tag)] = @{
@"response": response,
@"address": address,
@"timestamp": @([[NSDate date] timeIntervalSince1970])
};
NSLog(@"📤 Sending response (tag: %ld, size: %lu bytes)",
tag, (unsigned long)responseData.length);
[sock sendData:responseData
toAddress:address
withTimeout:SEND_TIMEOUT
tag:tag];
//
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((SEND_TIMEOUT + 1.0) * NSEC_PER_SEC)),
self->serverQueue, ^{
[self _checkSendTimeout:tag];
@ -450,14 +566,9 @@ withFilterContext:(id)filterContext {
});
}
//
- (void)_checkSendTimeout:(long)tag {
NSDictionary *pendingData = _pendingSends[@(tag)];
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)];
}
}
@ -467,47 +578,36 @@ withFilterContext:(id)filterContext {
}
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag {
NSLog(@"✅ Data sent successfully (tag: %ld)", tag);
[_pendingSends removeObjectForKey:@(tag)];
}
- (void)udpSocket:(GCDAsyncUdpSocket *)sock
didNotSendDataWithTag:(long)tag
dueToError:(NSError *)error {
NSLog(@"❌ Failed to send data (tag: %ld): %@", tag, error);
[_pendingSends removeObjectForKey:@(tag)];
//
if (error.code == 55) { // ENOBUFS
NSLog(@"⚠️ Buffer full (ENOBUFS) - system may be overloaded");
} else if (error.code == 57) { // ENOTCONN
NSLog(@"⚠️ Socket disconnected (ENOTCONN)");
if (error.code == 57) { // ENOTCONN
[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 {
NSLog(@"⚠️ Socket closed. Error: %@", error);
NSLog(@"⚠️ Socket closed: %@", error);
if (sock == serverSocket) {
serverSocket = nil;
}
if (error) {
NSLog(@"❌ Unexpected closure, scheduling restart");
if (error && !isStopping) {
[self scheduleRestart];
}
}
#pragma mark - Utility Methods
//
- (NSString *)_addressToString:(NSData *)addressData {
if (addressData.length < sizeof(struct sockaddr_in)) {
return @"unknown";
}
struct sockaddr_in *addr = (struct sockaddr_in *)addressData.bytes;
char ipStr[INET_ADDRSTRLEN];
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

View File

@ -1,3 +1 @@
172.28.4.29
172.28.7.13
172.28.7.22
172.28.1.12

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.