cdts/xdts-ios 3/TUICalling/Source/Model/Impl/TRTCCalling+Signal.m

935 lines
45 KiB
Mathematica
Raw Permalink Normal View History

2023-07-27 09:20:00 +08:00
//
// TRTCCall+Signal.m
// TXIMSDK_TUIKit_iOS
//
// Created by xiangzhang on 2020/7/3.
//
#import "TRTCCalling+Signal.h"
#import "TRTCCallingUtils.h"
#import "TRTCCallingHeader.h"
#import <ImSDK_Plus/ImSDK_Plus.h>
#import "TUILogin.h"
#import "CallingLocalized.h"
#import "TRTCSignalFactory.h"
#import "TUICallingConstants.h"
@implementation TRTCCalling (Signal)
- (void)addSignalListener {
[[V2TIMManager sharedInstance] addSignalingListener:self];
[[V2TIMManager sharedInstance] addSimpleMsgListener:self];
}
- (void)removeSignalListener {
[[V2TIMManager sharedInstance] removeSignalingListener:self];
}
- (NSString *)invite:(NSString *)receiver action:(CallAction)action model:(CallModel *)model cmdInfo:(NSString *)cmdInfo {
return [self invite:receiver action:action model:model cmdInfo:cmdInfo userIds:nil];
}
- (NSString *)invite:(NSString *)receiver
action:(CallAction)action
model:(CallModel *)model
cmdInfo:(NSString *)cmdInfo
userIds:(NSArray<NSString *> *)userIds {
TRTCLog(@"Calling - invite receiver:%@ action:%ld cmdInfo:%@", receiver, action, cmdInfo);
NSString *callID = @"";
CallModel *realModel = [self generateModel:action];
BOOL isGroup = [self.curGroupID isEqualToString:receiver];
if (model) {
realModel = [model copy];
realModel.action = action;
if (model.groupid.length > 0) {
isGroup = YES;
}
}
/// ID, GroupID C to C, MapuserID inviteID GroupID C to C inviteID Model
NSString *inviteID = [self getCallIDWithUserID:receiver] ?: realModel.callid;
switch (realModel.action) {
case CallAction_Call: {
NSString *cmd = @"";
switch (realModel.calltype) {
case CallType_Video:
cmd = SIGNALING_CMD_VIDEOCALL;
break;
case CallType_Audio:
cmd = SIGNALING_CMD_AUDIOCALL;
break;
default:
break;
}
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:realModel.roomid
cmd:cmd
cmdInfo:@""
userIds:userIds ?: @[]
message:@""
callType:realModel.calltype];
[dataDic setValue:@(realModel.roomid) forKey:SIGNALING_EXTRA_KEY_ROOM_ID];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
if (isGroup) {
@weakify(self)
callID = [[V2TIMManager sharedInstance] inviteInGroup:realModel.groupid
inviteeList:realModel.invitedList
data:data
onlineUserOnly:self.onlineUserOnly
timeout:SIGNALING_EXTRA_KEY_TIME_OUT succ:^{
TRTCLog(@"Calling - CallAction_Call inviteInGroup success");
@strongify(self)
// Apns ,
for (NSString *invitee in realModel.invitedList) {
[self sendAPNsForCall:invitee
inviteeList:realModel.invitedList
callID:self.callID
groupid:realModel.groupid
roomid:realModel.roomid];
}
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_Call inviteInGroup failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
self.callID = callID;
} else {
@weakify(self)
V2TIMOfflinePushInfo *info = [self getOfflinePushInfoWithInviteeList:realModel.invitedList
callID:nil groupid:nil
roomid:realModel.roomid];
callID = [[V2TIMManager sharedInstance] invite:receiver data:data
onlineUserOnly:self.onlineUserOnly
offlinePushInfo:info
timeout:SIGNALING_EXTRA_KEY_TIME_OUT
succ:^{
TRTCLog(@"Calling - CallAction_Call invite success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_Call invite failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
self.callID = callID;
}
} break;
case CallAction_Accept: {
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:realModel.roomid
cmd:@""
cmdInfo:@""
message:@""
callType:realModel.calltype];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
@weakify(self)
[[V2TIMManager sharedInstance] accept:inviteID data:data succ:^{
TRTCLog(@"Calling - CallAction_Accept accept success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_Accept accept failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
} break;
case CallAction_Reject: {
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:realModel.roomid
cmd:@""
cmdInfo:@""
message:@""
callType:realModel.calltype];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
@weakify(self)
[[V2TIMManager sharedInstance] reject:inviteID data:data succ:^{
TRTCLog(@"Calling - CallAction_Reject reject success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_Reject reject failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
} break;
case CallAction_Linebusy: {
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:realModel.roomid
cmd:@""
cmdInfo:@""
message:SIGNALING_MESSAGE_LINEBUSY
callType:realModel.calltype];
[dataDic setValue:SIGNALING_EXTRA_KEY_LINE_BUSY forKey:SIGNALING_EXTRA_KEY_LINE_BUSY];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
@weakify(self)
[[V2TIMManager sharedInstance] reject:inviteID data:data succ:^{
TRTCLog(@"Calling - CallAction_Linebusy reject success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_Linebusy reject failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
} break;
case CallAction_Cancel: {
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:realModel.roomid
cmd:@""
cmdInfo:@""
message:@""
callType:realModel.calltype];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
@weakify(self)
[[V2TIMManager sharedInstance] cancel:inviteID data:data succ:^{
TRTCLog(@"Calling - CallAction_Cancel cancel success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_Cancel cancel failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
} break;
case CallAction_End: {
if (isGroup) {
//
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:realModel.roomid
cmd:SIGNALING_CMD_HANGUP
cmdInfo:@"0"
message:@""
callType:realModel.calltype];
[dataDic setValue:@(0) forKey:SIGNALING_EXTRA_KEY_CALL_END];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
// inviteeList nil
// timeout 0
@weakify(self)
callID = [[V2TIMManager sharedInstance] inviteInGroup:realModel.groupid
inviteeList:@[@"inviteeList"]
data:data
onlineUserOnly:self.onlineUserOnly
timeout:0
succ:^{
TRTCLog(@"Calling - CallAction_End inviteInGroup success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_End inviteInGroup failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
} else {
NSDate *now = [NSDate date];
NSString *cmdInfo = [NSString stringWithFormat:@"%llu", (UInt64)[now timeIntervalSince1970] - self.startCallTS];
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:realModel.roomid
cmd:SIGNALING_CMD_HANGUP
cmdInfo:cmdInfo
message:@""
callType:realModel.calltype];
[dataDic setValue:@((UInt64)[now timeIntervalSince1970] - self.startCallTS) forKey:SIGNALING_EXTRA_KEY_CALL_END];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
@weakify(self)
callID = [[V2TIMManager sharedInstance] invite:receiver
data:data
onlineUserOnly:self.onlineUserOnly
offlinePushInfo:nil
timeout:0
succ:^{
TRTCLog(@"Calling - CallAction_End invite success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_End invite failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
self.startCallTS = 0;
}
} break;
case CallAction_SwitchToAudio: {
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:realModel.roomid
cmd:SIGNALING_CMD_SWITCHTOVOICECALL
cmdInfo:@""
message:@""
callType:realModel.calltype];
[dataDic setValue:SIGNALING_EXTRA_KEY_SWITCH_AUDIO_CALL forKey:SIGNALING_EXTRA_KEY_SWITCH_AUDIO_CALL];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
@weakify(self)
[[V2TIMManager sharedInstance] invite:receiver
data:data
onlineUserOnly:self.onlineUserOnly
offlinePushInfo:nil
timeout:SIGNALING_EXTRA_KEY_TIME_OUT
succ:^{
TRTCLog(@"Calling - CallAction_SwitchToAudio invite success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - CallAction_SwitchToAudio invite failed, code: %d desc: %@", code, desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onError:msg:)]) {
[self.delegate onError:code msg:desc];
};
}];
} break;
default:
break;
}
if (realModel.action != CallAction_Reject &&
realModel.action != CallAction_Accept &&
realModel.action != CallAction_End &&
realModel.action != CallAction_Cancel &&
realModel.action != CallAction_SwitchToAudio &&
realModel.action != CallAction_AcceptSwitchToAudio &&
realModel.action != CallAction_RejectSwitchToAudio &&
model == nil) {
self.curLastModel = [realModel copy];
}
return callID;
}
- (void)sendAPNsForCall:(NSString *)receiver
inviteeList:(NSArray *)inviteeList
callID:(NSString *)callID
groupid:(NSString *)groupid
roomid:(UInt32)roomid {
TRTCLog(@"Calling - sendAPNsForCall receiver:%@ inviteeList:%@ groupid:%@ roomid:%d", receiver, inviteeList, groupid, roomid);
if (callID.length == 0 || inviteeList.count == 0 || roomid == 0) {
TRTCLog(@"sendAPNsForCall failed");
return;
}
V2TIMOfflinePushInfo *info = [self getOfflinePushInfoWithInviteeList:inviteeList
callID:callID
groupid:groupid
roomid:roomid];
NSData *customMessage = [TRTCCallingUtils dictionary2JsonData:@{@"version" : @(Version) , @"businessID" : SIGNALING_BUSINESSID}];
V2TIMMessage *msg = [[V2TIMManager sharedInstance] createCustomMessage:customMessage];
//
[[V2TIMManager sharedInstance] sendMessage:msg
receiver:receiver
groupID:nil
priority:V2TIM_PRIORITY_HIGH
onlineUserOnly:YES
offlinePushInfo:info
progress:nil
succ:nil
fail:nil];
}
- (V2TIMOfflinePushInfo *)getOfflinePushInfoWithInviteeList:(NSArray *)inviteeList
callID:(NSString *)callID
groupid:(NSString *)groupid
roomid:(UInt32)roomid{
int chatType; //1 2
if (groupid.length > 0) {
chatType = 2;
} else {
chatType = 1;
groupid = @"";
}
/**
{"entity":{"version":1,"content":"{\"action\":1,\"call_type\":2,\"room_id\":804544637,\"call_id\":\"144115224095613335-1595234230-3304653590\",\"timeout\":30,\"version\":4,\"invited_list\":[\"2019\"],\"group_id\":\"@TGS#1PWYXLTGA\"}","sendTime":1595234231,"sender":"10457","chatType":2,"action":2}}
*/
NSDictionary *contentParam = @{@"action":@(SignalingActionType_Invite),
@"call_id":callID ?: @"",
@"call_type":@(self.curType),
@"invited_list":inviteeList.count > 0 ? inviteeList : @[],
@"room_id":@(roomid),
@"group_id":groupid,
@"timeout":@(SIGNALING_EXTRA_KEY_TIME_OUT),
@"version":@(Version)}; // TUIkit
NSDictionary *entityParam = @{@"action" : @(APNs_Business_Call), //
@"chatType" : @(chatType),
@"content" : [TRTCCallingUtils dictionary2JsonStr:contentParam],
@"sendTime" : @((UInt32)[[V2TIMManager sharedInstance] getServerTime]),
@"sender" : TUILogin.getUserID ?: @"",
@"version" : @(APNs_Version)}; //
NSDictionary *extParam = @{@"entity" : entityParam};
V2TIMOfflinePushInfo *info = [[V2TIMOfflinePushInfo alloc] init];
info.desc = TUICallingLocalize(@"Demo.TRTC.calling.callingrequest");
info.ext = [TRTCCallingUtils dictionary2JsonStr:extParam];
info.iOSSound = @"phone_ringing.mp3";
return info;
}
- (void)onReceiveGroupCallAPNs:(V2TIMSignalingInfo *)signalingInfo {
if (signalingInfo.inviteID.length > 0 &&
signalingInfo.inviter.length > 0 &&
signalingInfo.inviteeList.count > 0 &&
signalingInfo.groupID.length > 0) {
[[V2TIMManager sharedInstance] addInvitedSignaling:signalingInfo succ:^{
[self onReceiveNewInvitation:signalingInfo.inviteID
inviter:signalingInfo.inviter
groupID:signalingInfo.groupID
inviteeList:signalingInfo.inviteeList
data:signalingInfo.data];
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - onReceiveAPNsForGroupCall failed,code:%d desc:%@",code,desc);
}];
}
}
#pragma mark - V2TIMSignalingListener
/// -
- (void)onReceiveNewInvitation:(NSString *)inviteID
inviter:(NSString *)inviter
groupID:(NSString *)groupID
inviteeList:(NSArray<NSString *> *)inviteeList
data:(NSString *)data {
TRTCLog(@"Calling - onReceiveNewInvitation inviteID:%@ inviter:%@ inviteeList:%@ data:%@", inviteID, inviter, inviteeList, data);
NSDictionary *param = [self check:data];
if (param) {
self.isBeingCalled = YES;
NSString *cmdInfoStr = @"";
NSArray *userIds = nil;
if ([param.allKeys containsObject:SIGNALING_EXTRA_KEY_DATA]) {
NSDictionary *data = param[SIGNALING_EXTRA_KEY_DATA];
if ([data.allKeys containsObject:SIGNALING_EXTRA_KEY_CMDINFO]) {
cmdInfoStr = data[SIGNALING_EXTRA_KEY_CMDINFO];
}
if ([data.allKeys containsObject:SIGNALING_EXTRA_KEY_USERIDS]) {
userIds = data[SIGNALING_EXTRA_KEY_USERIDS];
}
}
NSDictionary *data = [TRTCSignalFactory getDataDictionary:param];
CallModel *model = [[CallModel alloc] init];
model.callid = inviteID;
model.groupid = groupID;
model.inviter = inviter;
model.invitedList = [NSMutableArray arrayWithArray:inviteeList];
model.calltype = [TRTCSignalFactory convertCmdToCallType:data[SIGNALING_EXTRA_KEY_CMD]];
model.roomid = [data[SIGNALING_EXTRA_KEY_ROOMID] intValue];
if ([data[SIGNALING_EXTRA_KEY_CMD] isEqualToString:SIGNALING_CMD_SWITCHTOVOICECALL]) {
/// A1A2AA1BBBA2A1
///
if (!self.isOnCalling) {
return;
}
model.action = CallAction_SwitchToAudio;
self.switchToAudioCallID = inviteID;
} else {
/// A1A2AA1B A1A2
if ([self checkLoginUserIsEqualTo:inviter]) {
return;
}
self.currentCallingUserID = inviter;
model.action = CallAction_Call;
}
[self handleCallModel:inviter model:model message:cmdInfoStr userIds:userIds];
}
}
/// -
- (void)onInvitationCancelled:(NSString *)inviteID inviter:(NSString *)inviter data:(NSString *)data {
TRTCLog(@"Calling - onInvitationCancelled inviteID:%@ inviter:%@ data:%@", inviteID, inviter, data);
/// A1A2AAB AA1A2
if ([self checkLoginUserIsEqualTo:inviter]) {
return;
}
NSDictionary *param = [self check:data];
if (!(param && [param isKindOfClass:[NSDictionary class]])) {
return;
}
CallModel *model = [[CallModel alloc] init];
model.callid = inviteID;
model.action = CallAction_Cancel;
[self handleCallModel:inviter model:model message:@""];
}
/// -
- (void)onInviteeAccepted:(NSString *)inviteID invitee:(NSString *)invitee data:(NSString *)data {
TRTCLog(@"Calling - onInviteeAccepted inviteID:%@ invitee:%@ data:%@", inviteID, invitee, data);
/// A1A2AA1BBA2 B
///
if (!self.isOnCalling) {
return;
}
NSDictionary *param = [self check:data];
if (!(param && [param isKindOfClass:[NSDictionary class]])) {
return;
}
[TRTCCloud sharedInstance].delegate = self;
CallModel *model = [[CallModel alloc] init];
model.callid = inviteID;
NSDictionary *paramData = [TRTCSignalFactory getDataDictionary:param];
if ([paramData[SIGNALING_EXTRA_KEY_CMD] isEqualToString:SIGNALING_CMD_SWITCHTOVOICECALL]) {
model.action = CallAction_AcceptSwitchToAudio;
} else {
/// A1A2ABA A1A2退
if (!self.isProcessedBySelf && [self checkLoginUserIsEqualTo:invitee]) {
[self exitRoom];
return;
}
model.action = CallAction_Accept;
}
[self handleCallModel:invitee model:model message:@""];
}
/// -
- (void)onInviteeRejected:(NSString *)inviteID invitee:(NSString *)invitee data:(NSString *)data {
TRTCLog(@"Calling - onInviteeRejected inviteID:%@ invitee:%@ data:%@", inviteID, invitee, data);
/// A1A2AA1BBA2 B
///
if (!self.isOnCalling) {
return;
}
NSDictionary *param = [self check:data];
if (!param || ![param isKindOfClass:[NSDictionary class]]) {
return;
}
CallModel *model = [[CallModel alloc] init];
model.callid = inviteID;
NSDictionary *dataDic = [TRTCSignalFactory getDataDictionary:param];
if ([dataDic[SIGNALING_EXTRA_KEY_MESSAGE] isEqualToString:SIGNALING_MESSAGE_LINEBUSY]) {
model.action = CallAction_Linebusy;
} else if ([dataDic[SIGNALING_EXTRA_KEY_CMD] isEqualToString:SIGNALING_CMD_SWITCHTOVOICECALL]) {
model.action = CallAction_AcceptSwitchToAudio;
} else {
/// A1A2ABA A1A2退
if (!self.isProcessedBySelf && [self checkLoginUserIsEqualTo:invitee]) {
[self exitRoom];
return;
}
model.action = CallAction_Reject;
}
[self handleCallModel:invitee model:model message:@"Other status error"];
}
/// -
- (void)onInvitationTimeout:(NSString *)inviteID inviteeList:(NSArray<NSString *> *)invitedList {
TRTCLog(@"Calling - onInvitationTimeout inviteID:%@ invitedList:%@", inviteID, invitedList);
/// A1A2AA1BBA2 B
///
if (!self.isOnCalling) {
return;
}
CallModel *model = [[CallModel alloc] init];
model.callid = inviteID;
model.invitedList = [NSMutableArray arrayWithArray:invitedList];
model.action = CallAction_Timeout;
[self handleCallModel:[invitedList firstObject] model:model message:@"Timeout"];
}
- (NSDictionary *)check:(NSString *)data {
NSDictionary *signalingDictionary = [TRTCCallingUtils jsonSring2Dictionary:data];
if(!signalingDictionary[SIGNALING_EXTRA_KEY_PLATFORM] || !signalingDictionary[SIGNALING_EXTRA_KEY_DATA]) {
signalingDictionary = [TRTCSignalFactory convertOldSignalingToNewSignaling:signalingDictionary];
}
if (!signalingDictionary[SIGNALING_EXTRA_KEY_BUSINESSID] ||
![signalingDictionary[SIGNALING_EXTRA_KEY_BUSINESSID] isKindOfClass:[NSString class]] ||
![signalingDictionary[SIGNALING_EXTRA_KEY_BUSINESSID] isEqualToString:SIGNALING_BUSINESSID]) {
return nil;
}
NSInteger version = [signalingDictionary[SIGNALING_EXTRA_KEY_VERSION] integerValue];
if (version > Version) {
return nil;
}
NSDictionary *dataDictionary = [TRTCSignalFactory getDataDictionary:signalingDictionary];
if (dataDictionary[SIGNALING_EXTRA_KEY_CMD] &&
[dataDictionary[SIGNALING_EXTRA_KEY_CMD] isKindOfClass:[NSString class]] &&
[dataDictionary[SIGNALING_EXTRA_KEY_CMD] isEqualToString:SIGNALING_CMD_HANGUP]) {
// UI
return nil;
}
return signalingDictionary;
}
- (void)handleCallModel:(NSString *)user model:(CallModel *)model message:(NSString *)message {
[self handleCallModel:user model:model message:message userIds:nil];
}
- (void)handleCallModel:(NSString *)user model:(CallModel *)model message:(NSString *)message userIds:(NSArray *)userIds {
TRTCLog(@"Calling - handleCallModel user:%@ model:%@ message:%@ userIds:%@", user, model, message, userIds);
BOOL checkCallID = [self.curCallID isEqualToString:model.callid] || [[self getCallIDWithUserID:user] isEqualToString:model.callid];
switch (model.action) {
case CallAction_Call: {
[self sendInviteAction:CallAction_Call user:user model:model];
void(^syncInvitingList)(void) = ^(){
for (NSString *invitee in model.invitedList) {
if (![self.curInvitingList containsObject:invitee]) {
[self.curInvitingList addObject:invitee];
}
}
};
if (model.groupid != nil && ![model.invitedList containsObject:TUILogin.getUserID]
) { //
if ([self.curCallID isEqualToString:model.callid]) { //
syncInvitingList();
if (self.curInvitingList.count > 0) {
if ([self canDelegateRespondMethod:@selector(onGroupCallInviteeListUpdate:)]) {
[self.delegate onGroupCallInviteeListUpdate:self.curInvitingList];
}
}
}
return;
}
if (self.isOnCalling) { // tell busy
if (!checkCallID) {
BOOL isGroup = (model.groupid && model.groupid > 0);
[self invite:isGroup ? model.groupid : user action:CallAction_Linebusy model:model cmdInfo:nil];
}
} else {
self.isOnCalling = true;
self.curCallID = model.callid;
self.curRoomID = model.roomid;
if (model.groupid.length > 0) {
self.curGroupID = model.groupid;
}
self.curType = model.calltype;
self.curSponsorForMe = user;
syncInvitingList();
if ([self canDelegateRespondMethod:@selector(onInvited:userIds:isFromGroup:callType:)]) {
NSMutableArray *userIdAry = model.invitedList;
[userIds enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (![userIdAry containsObject:obj]) {
[userIdAry addObject:obj];
}
}];
[self.delegate onInvited:user userIds:userIdAry isFromGroup:self.curGroupID.length > 0 ? YES : NO callType:model.calltype];
}
}
} break;
case CallAction_Cancel: {
[self sendInviteAction:CallAction_Cancel user:user model:model];
if (checkCallID && self.delegate) {
[self preExitRoom];
self.isOnCalling = NO;
[self.delegate onCallingCancel:user];
}
} break;
case CallAction_Reject: {
[self sendInviteAction:CallAction_Reject user:user model:model];
if (checkCallID && self.delegate) {
if ([self.curInvitingList containsObject:user]) {
[self.curInvitingList removeObject:user];
}
if ([self canDelegateRespondMethod:@selector(onReject:)]) {
[self.delegate onReject:user];
}
[self preExitRoom];
}
} break;
case CallAction_Timeout: {
[self sendInviteAction:CallAction_Timeout user:user model:model];
if (checkCallID && self.delegate) {
// 退
if ([model.invitedList containsObject:TUILogin.getUserID] && self.delegate) {
self.isOnCalling = false;
if ([self canDelegateRespondMethod:@selector(onCallingTimeOut)]) {
[self.delegate onCallingTimeOut];
}
} else {
for (NSString *userID in model.invitedList) {
if ([self canDelegateRespondMethod:@selector(onNoResp:)]) {
[self.delegate onNoResp:userID];
}
if ([self.curInvitingList containsObject:userID]) {
[self.curInvitingList removeObject:userID];
}
}
}
//
[self preExitRoom];
}
} break;
case CallAction_Linebusy: {
TRTCLog(@"Calling - CallAction_Linebusy_out user:%@ userIds:%@ curCallID:%@ model: %@", user, userIds, self.curCallID, model);
[self sendInviteAction:CallAction_Linebusy user:user model:model];
if (checkCallID && self.delegate) {
TRTCLog(@"Calling - CallAction_Linebusy_in user:%@ userIds:%@", user, userIds);
if ([self.curInvitingList containsObject:user]) {
[self.curInvitingList removeObject:user];
}
[self.delegate onLineBusy:user];
[self preExitRoom];
}
} break;
case CallAction_Error: {
[self sendInviteAction:CallAction_Error user:user model:model];
if (checkCallID && self.delegate) {
if ([self.curInvitingList containsObject:user]) {
[self.curInvitingList removeObject:user];
}
[self.delegate onError:-1 msg:TUICallingLocalize(@"Demo.TRTC.calling.syserror")];
[self preExitRoom];
}
} break;
case CallAction_SwitchToAudio: {
if (!self.switchToAudioCallID) {
break;
}
int res = [self checkAudioStatus];
if (res == 0) {
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:0
cmd:SIGNALING_CMD_SWITCHTOVOICECALL
cmdInfo:@""
message:@""
callType:CallType_Video];
[dataDic setValue:@(1) forKey:SIGNALING_EXTRA_KEY_SWITCH_AUDIO_CALL];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
@weakify(self)
[[V2TIMManager sharedInstance] accept:self.switchToAudioCallID data:data succ:^{
TRTCLog(@"res==0 - accept success");
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onSwitchToAudio:message:)]) {
[self.delegate onSwitchToAudio:YES message:@""];
}
} fail:^(int code, NSString *desc) {
TRTCLog(@"res==0 - accept failed, code: %d desc: %@",code,desc);
@strongify(self)
if ([self canDelegateRespondMethod:@selector(onSwitchToAudio:message:)]) {
[self.delegate onSwitchToAudio:NO message:desc];
}
}];
} else {
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:0
cmd:@""
cmdInfo:@""
message:@""
callType:CallType_Video];
[dataDic setValue:@(0) forKey:SIGNALING_EXTRA_KEY_SWITCH_AUDIO_CALL];
NSString *data = [TRTCCallingUtils dictionary2JsonStr:dataDic];
[[V2TIMManager sharedInstance] reject:self.switchToAudioCallID data:data succ:^{
TRTCLog(@"res!=0 - reject success");
} fail:^(int code, NSString *desc) {
TRTCLog(@"res!=0 - reject failed, code: %d desc: %@",code,desc);
}];
if ([self canDelegateRespondMethod:@selector(onSwitchToAudio:message:)]) {
[self.delegate onSwitchToAudio:NO message:@"Local status error"];
}
}
} break;
case CallAction_AcceptSwitchToAudio: {
if ([self canDelegateRespondMethod:@selector(onSwitchToAudio:message:)]) {
[self.delegate onSwitchToAudio:YES message:@""];
}
} break;
case CallAction_RejectSwitchToAudio: {
if ([self canDelegateRespondMethod:@selector(onSwitchToAudio:message:)]) {
[self.delegate onSwitchToAudio:NO message:message];
}
} break;
default: {
TRTCLog(@"Default CallAction");
} break;
}
}
#pragma mark - V2TIMSimpleMsgListener
/// C2C
- (void)onRecvC2CCustomMessage:(NSString *)msgID sender:(V2TIMUserInfo *)info customData:(NSData *)data {
TRTCLog(@"Calling - onRecvC2CCustomMessage inviteID:%@ inviter:%@", msgID, data);
if (!self.isBeingCalled) return;
NSDictionary *param = [self check:[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]];
if (!param || ![param isKindOfClass:[NSDictionary class]]) {
return;
}
NSDictionary *dataDic;
NSString *cmdStr;
if ([param.allKeys containsObject:SIGNALING_EXTRA_KEY_DATA] ) {
dataDic = param[SIGNALING_EXTRA_KEY_DATA];
if ([dataDic.allKeys containsObject:SIGNALING_EXTRA_KEY_CMD]) {
cmdStr = dataDic[SIGNALING_EXTRA_KEY_CMD];
}
}
if (![cmdStr isEqualToString:@"sync_info"]) return;
CallModel *model = [[CallModel alloc] init];
model.callid = param[SIGNALING_CUSTOM_CALLID];
model.inviter = param[SIGNALING_CUSTOM_USER];
model.action = [param[SIGNALING_CUSTOM_CALL_ACTION] integerValue];
model.roomid = [dataDic[SIGNALING_EXTRA_KEY_ROOMID] intValue];
if (model.inviter && model.action == CallAction_Timeout) {
model.invitedList = [@[model.inviter] mutableCopy];
}
[self handleCallModel:model.inviter model:model message:@"" userIds:nil];
}
#pragma mark - Utils
- (CallModel *)generateModel:(CallAction)action {
CallModel *model = [self.curLastModel copy];
model.action = action;
return model;
}
- (void)preExitRoom {
[self preExitRoom:nil];
}
- (void)preExitRoom:(NSString *)leaveUser {
if (!self.isInRoom && self.curInvitingList.count == 0) {
[self exitRoom];
return;
}
// 退
if (self.curRoomList.count > 0) return;
if (self.curGroupID.length > 0) {
// IM
if (self.curInvitingList.count == 0) {
if (leaveUser) {
[self invite:@"" action:CallAction_End model:nil cmdInfo:nil];
}
[self exitRoom];
}
return;
}
// C2C
if (self.curInvitingList.count >= 1) {
return;
}
if (leaveUser) {
[self invite:leaveUser action:CallAction_End model:nil cmdInfo:nil];
}
[self exitRoom];
}
- (void)exitRoom {
TRTCLog(@"Calling - autoHangUp");
if ([self canDelegateRespondMethod:@selector(onCallEnd)]) {
[self.delegate onCallEnd];
}
[self quitRoom];
self.isOnCalling = NO;
}
#pragma mark - private method
/// /
- (BOOL)checkLoginUserIsEqualTo:(NSString *)inviteUser {
if (inviteUser && [inviteUser isKindOfClass:NSString.class] && inviteUser.length > 0 && [inviteUser isEqualToString:TUILogin.getUserID]) {
return YES;
}
return NO;
}
- (void)sendInviteAction:(CallAction)action user:(NSString *)user model:(CallModel *)model {
BOOL isGroupidCall = (model.groupid && model.groupid > 0);
if (self.isBeingCalled || isGroupidCall || [user isEqualToString:TUILogin.getUserID]) {
return;
}
@weakify(self)
[self.calleeUserIDs enumerateObjectsUsingBlock:^(NSString * _Nonnull calleeUserID, NSUInteger idx, BOOL * _Nonnull stop) {
if (![calleeUserID isEqualToString:user]) {
@strongify(self)
NSString *callid = [self getCallIDWithUserID:calleeUserID];
if (callid && callid.length > 0) {
NSMutableDictionary *dataDic = [TRTCSignalFactory packagingSignalingWithExtInfo:@""
roomID:model.roomid
cmd:@"sync_info"
cmdInfo:@""
message:@""
callType:model.calltype];
[dataDic setValue:@(action) forKey:SIGNALING_CUSTOM_CALL_ACTION];
[dataDic setValue:callid forKey:SIGNALING_CUSTOM_CALLID];
[dataDic setValue:user ?: @"" forKey:SIGNALING_CUSTOM_USER];
[[V2TIMManager sharedInstance] sendC2CCustomMessage:[TRTCCallingUtils dictionary2JsonData:dataDic] to:calleeUserID succ:^{
TRTCLog(@"Calling - sendC2CCustomMessage success %@ %@", dataDic, calleeUserID);
} fail:^(int code, NSString *desc) {
TRTCLog(@"Calling - sendC2CCustomMessage failed, code: %d desc: %@", code, desc);
}];
} else {
TRTCLog(@"Calling - sendInviteAction callid error");
}
}
}];
}
- (BOOL)canDelegateRespondMethod:(SEL)selector {
return self.delegate && [self.delegate respondsToSelector:selector];
}
- (NSString * _Nullable)getCallIDWithUserID:(NSString *)userID {
NSString *callID;
if (userID && [userID isKindOfClass:NSString.class] && userID.length > 0) {
callID = self.curCallIdDic[userID];
}
if ([callID isKindOfClass:NSString.class]) {
return callID;
}
return nil;
}
@end