// // webRtcManager+StatisticsReport.m // Private-X // // Created by xd h on 2024/9/10. // #import "webRtcManager+StatisticsReport.h" @implementation webRtcManager (StatisticsReport) // IsChannel:是否是P2P通道 - (void)reportWebRtcRePoportTypeIsChannel:(BOOL)IsChannel withStats:(RTC_OBJC_TYPE(RTCStatisticsReport) *)stats withSessionId:(NSString*)sessionId withLogKey:(NSString*)logkey { //HLog(@"444444 %@",stats) if(!stats){ [self reportWebRtcRePoportTypeIsChannel:IsChannel withStatus:0 withPublicIp:@"" withPublicPort:@"" withPrivateIp:@"" withPrivatePort:@"" withSessionId:@"" withLogKey:logkey]; return; } // NSDictionary *jsonTransport = nil; NSMutableArray *pairMapArr = [NSMutableArray new]; NSMutableArray *remoteCandidateMapArr = [NSMutableArray new]; NSMutableArray *localCandidateMapArr = [NSMutableArray new]; //1.先拿到 jsonTransport 的信息 for (NSString *key in [stats.statistics allKeys]) { RTCStatistics *rtcStatistics = [stats.statistics objectForKey:key]; //HLog(@"222 %@",rtcStatistics.type) if ([rtcStatistics.type isEqualToString:@"transport"]) { jsonTransport = rtcStatistics.values; continue; } if ([rtcStatistics.type isEqualToString:@"candidate-pair"]) { [pairMapArr addObject:rtcStatistics]; continue; } if ([rtcStatistics.type isEqualToString:@"remote-candidate"]) { [remoteCandidateMapArr addObject:rtcStatistics]; continue; } if ([rtcStatistics.type isEqualToString:@"local-candidate"]) { [localCandidateMapArr addObject:rtcStatistics]; continue; } } NSString *selectedCandidatePairId = @""; NSString *localCandidateId = @""; NSString *remoteCandidateId = @""; if([[jsonTransport allKeys] containsObject:@"selectedCandidatePairId"]){ selectedCandidatePairId = jsonTransport[@"selectedCandidatePairId"]; } //2.找到 localCandidateId remoteCandidateId for (RTCStatistics *rtcStatistics in pairMapArr) { if([rtcStatistics isKindOfClass:[RTCStatistics class]]){ NSString *curId = rtcStatistics.id; if([curId isEqualToString:selectedCandidatePairId]){ NSDictionary *valuesDict = rtcStatistics.values; if([valuesDict isKindOfClass:[NSDictionary class]]){ if ([[valuesDict allKeys] containsObject:@"localCandidateId"]) { localCandidateId = valuesDict[@"localCandidateId"]; } if ([[valuesDict allKeys] containsObject:@"remoteCandidateId"]) { remoteCandidateId = valuesDict[@"remoteCandidateId"]; } } break; } } } //3.找到 localCandidateDict NSDictionary *localCandidateDict = nil; NSString*privateIp = @""; NSString*privatePort = @""; NSString *localCandidateType = @""; for (RTCStatistics *rtcStatistics in localCandidateMapArr) { if([rtcStatistics isKindOfClass:[RTCStatistics class]]){ NSString *curId = rtcStatistics.id; if([curId isEqualToString:localCandidateId]){ localCandidateDict = rtcStatistics.values; if([localCandidateDict isKindOfClass:[NSDictionary class]]){ if([[localCandidateDict allKeys] containsObject:@"ip"]){ privateIp = localCandidateDict[@"ip"]; } if([[localCandidateDict allKeys] containsObject:@"port"]){ privatePort = localCandidateDict[@"port"]; } if([[localCandidateDict allKeys] containsObject:@"candidateType"]){ localCandidateType = localCandidateDict[@"candidateType"]; } } break; } } } //4.找到 remoteCandidateDict NSDictionary *remoteCandidateDict = nil; NSString*publicIp = @""; NSString*publicPort = @""; NSString *remoteCandidateType = @""; for (RTCStatistics *rtcStatistics in remoteCandidateMapArr) { if([rtcStatistics isKindOfClass:[RTCStatistics class]]){ NSString *curId = rtcStatistics.id; if([curId isEqualToString:remoteCandidateId]){ remoteCandidateDict = rtcStatistics.values; if([remoteCandidateDict isKindOfClass:[NSDictionary class]]){ if([[remoteCandidateDict allKeys] containsObject:@"ip"]){ publicIp = remoteCandidateDict[@"ip"]; } if([[remoteCandidateDict allKeys] containsObject:@"port"]){ publicPort = remoteCandidateDict[@"port"]; } if([[remoteCandidateDict allKeys] containsObject:@"candidateType"]){ remoteCandidateType = remoteCandidateDict[@"candidateType"]; } } break; } } } // int linkState = 1; if([localCandidateType isEqualToString:@"host"] && [remoteCandidateType isEqualToString:@"host"]){//内网 linkState = 3; } else if([localCandidateType isEqualToString:@"relay"] ||[remoteCandidateType isEqualToString:@"relay"]){ linkState = 2; //[self reportWebRtcRePoportTypeIsChannel:IsChannel withStatus:2 withPublicIp:publicIp withPublicPort:publicPort withPrivateIp:privateIp withPrivatePort:privatePort]; } else{ linkState = 1; //[self reportWebRtcRePoportTypeIsChannel:IsChannel withStatus:1 withPublicIp:publicIp withPublicPort:publicPort withPrivateIp:privateIp withPrivatePort:privatePort]; } [self reportWebRtcRePoportTypeIsChannel:IsChannel withStatus:linkState withPublicIp:publicIp withPublicPort:publicPort withPrivateIp:privateIp withPrivatePort:privatePort withSessionId:sessionId withLogKey:logkey]; } - (void)reportWebRtcRePoportTypeIsChannel:(BOOL)IsChannel withStatus:(int)linkState withPublicIp:(NSString*)publicIp withPublicPort:(NSString*)publicPort withPrivateIp:(NSString*)privateIp withPrivatePort:(NSString*)privatePort withSessionId:(NSString*)sessionId withLogKey:(NSString*)logkey { NSMutableDictionary *paraDict = [NSMutableDictionary new]; [paraDict setValue:@2 forKey:@"type"]; [paraDict setValue:[NSNumber numberWithInt:linkState] forKey:@"status"]; int channelType = IsChannel ? 1 : 2; [paraDict setValue:[NSNumber numberWithInt:channelType] forKey:@"channelType"]; int clientNetworkStatus = [pingManager shareManager].isPingOk ? 0 : 1; [paraDict setValue:[NSNumber numberWithInt:clientNetworkStatus] forKey:@"clientNetworkStatus"]; if(sessionId){ [paraDict setValue:sessionId forKey:@"sessionId"]; } if(publicIp){ [paraDict setValue:publicIp forKey:@"publicIp"]; } if(publicPort){ [paraDict setValue:publicPort forKey:@"publicPort"]; } if(privateIp){ [paraDict setValue:privateIp forKey:@"privateIp"]; } if(privatePort){ [paraDict setValue:privatePort forKey:@"privatePort"]; } if(logkey){ [paraDict setValue:logkey forKey:@"failureReason"]; } if(ksharedAppDelegate.bestWebrtcServerModel){ NSString * turnMsg = [[NSString alloc] initWithFormat:@"%@",ksharedAppDelegate.bestWebrtcServerModel.turnIp]; [paraDict setValue:turnMsg forKey:@"coturnIp"]; NSString * signalMsg = [[NSString alloc] initWithFormat:@"%@",ksharedAppDelegate.bestWebrtcServerModel.signallingIp]; [paraDict setValue:signalMsg forKey:@"signalingIp"]; } [[netWorkManager shareInstance] CommonPostCallBackCode:webrctLogAdd Parameters:paraDict success:^(id _Nonnull responseObject){ SuperModel *curModel = [[SuperModel alloc] initWithDictionary:responseObject error:nil]; if(curModel && curModel.status == 0){ } else { } } failure:^(NSError * _Nonnull error) { HLog(@"") }]; } // IsChannel:是否是P2P通道 - (void)reportWebRtcRePoportTypeIsChannel:(BOOL)IsChannel withLocal:(RTC_OBJC_TYPE(RTCIceCandidate) *)local remoteCandidate:(RTC_OBJC_TYPE(RTCIceCandidate) *)remote withSessionId:(NSString*)sessionId withLogKey:(NSString*)logkey{ // candidate:504853897 1 udp 41885695 115.227.9.195 35762 typ relay raddr 115.227.9.184 rport 43877 generation 0 ufrag OP7P network-id 1 NSString*localSdpStr = local.sdp; if(!localSdpStr || localSdpStr.length==0){ return; } //正常可以分割到20个非空格元素 NSArray *localSdpArr = [localSdpStr componentsSeparatedByString:@" "]; if(localSdpArr.count < 12){ return; } NSString* localIp = localSdpArr[4]; NSString* localPort = localSdpArr[5]; NSString* localType = localSdpArr[7]; //NSString* localRelatedAddress = localSdpArr[9];// 可能为 null //NSString* localRelatedPort = localSdpArr[11]; //NSString* localNetworkId = localSdpArr[11];// 可能为 null NSString*remoteSdpStr = remote.sdp; if(!remoteSdpStr || remoteSdpStr.length==0){ return; } //正常可以分割到20个非空格元素 NSArray *remoteSdpArr = [remoteSdpStr componentsSeparatedByString:@" "]; if(remoteSdpArr.count < 12){ return; } NSString* remoteIp = remoteSdpArr[4]; NSString* remotePort = remoteSdpArr[5]; NSString* remoteType = remoteSdpArr[7]; //NSString* remoteRelatedAddress = remoteSdpArr[9];// 可能为 null //NSString* remoteRelatedPort = remoteSdpArr[11]; //NSString* remoteNetworkId = remoteSdpArr[11];// 可能为 null int linkState = 1; if([localType isEqualToString:@"host"] && [remoteType isEqualToString:@"host"]){//内网 linkState = 3; } else if([localType isEqualToString:@"relay"] ||[remoteType isEqualToString:@"relay"]){ linkState = 2; } else{ linkState = 1; } [self reportWebRtcRePoportTypeIsChannel:IsChannel withStatus:linkState withPublicIp:remoteIp withPublicPort:remotePort withPrivateIp:localIp withPrivatePort:localPort withSessionId:sessionId withLogKey:logkey]; } @end