//
|
// ESSipManager.m
|
// EasySip
|
//
|
// Created by Weller Zhao on 2018/7/27.
|
// Copyright © 2018 weller. All rights reserved.
|
//
|
|
#import "ESSipManager.h"
|
#import "LinphoneManager.h"
|
|
#define LC ([LinphoneManager getLc])
|
|
NSString *const ES_ON_REMOTE_OPEN_CEMERA = @"ES_ON_REMOTE_OPEN_CEMERA";
|
NSString *const ES_ON_CALL_COMMING = @"ES_ON_CALL_COMMING";
|
NSString *const ES_ON_CALL_END = @"ES_ON_CALL_END";
|
NSString *const ES_ON_CALL_STREAM_UPDATE = @"ES_ON_CALL_STREAM_UPDATE";
|
|
@implementation ESSipManager
|
|
static ESSipManager* _instance = nil;
|
|
+(instancetype) instance
|
{
|
static dispatch_once_t onceToken ;
|
dispatch_once(&onceToken, ^{
|
_instance = [[super allocWithZone:NULL] init] ;
|
}) ;
|
|
return _instance ;
|
}
|
|
+(id)allocWithZone:(struct _NSZone *)zone
|
{
|
return [ESSipManager instance];
|
}
|
|
-(id)copyWithZone:(struct _NSZone *)zone
|
{
|
return [ESSipManager instance];
|
}
|
|
- (instancetype)init {
|
self = [super init];
|
if (self) {
|
[[LinphoneManager instance] startLinphoneCore];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onCallUpdate:) name:kLinphoneCallUpdate object:nil];
|
}
|
return self;
|
}
|
|
- (void)dealloc {
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
}
|
|
- (void) login: (NSString*) username password: (NSString*) password displayName: (NSString*) displayName domain: (NSString*) domain port: (NSString *) port withTransport: (NSString*) transport {
|
LinphoneProxyConfig *config = linphone_core_create_proxy_config(LC);
|
LinphoneAddress *addr = linphone_address_new(NULL);
|
LinphoneAddress *tmpAddr = linphone_address_new([NSString stringWithFormat:@"sip:%@",domain].UTF8String);
|
linphone_address_set_username(addr, username.UTF8String);
|
linphone_address_set_port(addr, linphone_address_get_port(tmpAddr));
|
linphone_address_set_domain(addr, linphone_address_get_domain(tmpAddr));
|
if (displayName && ![displayName isEqualToString:@""]) {
|
linphone_address_set_display_name(addr, displayName.UTF8String);
|
}
|
linphone_proxy_config_set_identity_address(config, addr);
|
if (transport) {
|
linphone_proxy_config_set_route(
|
config,
|
[NSString stringWithFormat:@"%s;transport=%s", domain.UTF8String, transport.lowercaseString.UTF8String]
|
.UTF8String);
|
linphone_proxy_config_set_server_addr(
|
config,
|
[NSString stringWithFormat:@"%s;transport=%s", domain.UTF8String, transport.lowercaseString.UTF8String]
|
.UTF8String);
|
}
|
|
linphone_proxy_config_enable_publish(config, FALSE);
|
linphone_proxy_config_enable_register(config, TRUE);
|
|
LinphoneAuthInfo *info =
|
linphone_auth_info_new(linphone_address_get_username(addr), // username
|
NULL, // user id
|
password.UTF8String, // passwd
|
NULL, // ha1
|
linphone_address_get_domain(addr), // realm - assumed to be domain
|
linphone_address_get_domain(addr) // domain
|
);
|
linphone_core_add_auth_info(LC, info);
|
linphone_address_unref(addr);
|
linphone_address_unref(tmpAddr);
|
|
if (config) {
|
[[LinphoneManager instance] configurePushTokenForProxyConfig:config];
|
if (linphone_core_add_proxy_config(LC, config) != -1) {
|
linphone_core_set_default_proxy_config(LC, config);
|
// reload address book to prepend proxy config domain to contacts' phone number
|
// todo: STOP doing that!
|
// [[LinphoneManager.instance fastAddressBook] fetchContactsInBackGroundThread];
|
// [PhoneMainView.instance changeCurrentView:DialerView.compositeViewDescription];
|
} else {
|
// [self displayAssistantConfigurationError];
|
}
|
} else {
|
// [self displayAssistantConfigurationError];
|
}
|
|
NSLog(@"登陆信息配置成功!\nusername:%@,\npassword:%@,\ndisplayName:%@\ndomain:%@,\nport:%@\ntransport:%@", username, password, displayName, domain, port, transport);
|
}
|
|
- (void) logout {
|
[[LinphoneManager instance] lpConfigSetBool:FALSE forKey:@"pushnotification_preference"];
|
|
LinphoneCore *lc = [LinphoneManager getLc];
|
LCSipTransports transportValue = {5060,5060,-1,-1};
|
|
if (linphone_core_set_sip_transports(lc, &transportValue)) {
|
NSLog(@"cannot set transport");
|
}
|
|
[[LinphoneManager instance] lpConfigSetString:@"" forKey:@"sharing_server_preference"];
|
[[LinphoneManager instance] lpConfigSetBool:FALSE forKey:@"ice_preference"];
|
[[LinphoneManager instance] lpConfigSetString:@"" forKey:@"stun_preference"];
|
linphone_core_set_stun_server(lc, NULL);
|
linphone_core_set_firewall_policy(lc, LinphonePolicyNoFirewall);
|
}
|
|
- (LinphoneCall *)callByUsername:(NSString *)username {
|
LinphoneCore * lc = [LinphoneManager getLc];
|
LinphoneAddress* linphoneAddress = linphone_core_interpret_url(lc, [username cStringUsingEncoding:[NSString defaultCStringEncoding]]);
|
if (linphoneAddress == NULL) {
|
return NULL;
|
}
|
LinphoneCall *call = linphone_core_invite_address(lc, linphoneAddress);
|
return call;
|
}
|
|
- (void) call: (NSString*) username displayName: (NSString*) displayName {
|
|
LinphoneCall *call = [self callByUsername:username];
|
if (call == nil) {
|
NSLog(@"拨打失败");
|
} else {
|
NSLog(@"正在拨叫...\naddress:%@,\ndisplayName:%@", username, displayName);
|
}
|
}
|
|
- (void) callWithPhoneNumber:(NSString *)phone withVideo:(BOOL)video{
|
LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(LC);
|
if (!cfg) {
|
return;
|
}
|
|
LinphoneAddress *addr = [LinphoneManager.instance normalizeSipOrPhoneAddress:phone];
|
linphone_core_enable_video_display(LC,video);
|
|
[LinphoneManager.instance call:addr];
|
if (addr) {
|
linphone_address_unref(addr);
|
}
|
}
|
|
//- (void) acceptCall: (LinphoneCall*) call {
|
// [[LinphoneManager instance] acceptCall:call evenWithVideo:true];
|
// NSLog(@"接听电话");
|
//}
|
- (void)acceptCall{
|
|
LinphoneCall *call = linphone_core_get_current_call(LC);
|
if (call) {
|
[[LinphoneManager instance] acceptCall:call evenWithVideo:YES];
|
NSLog(@"接听电话");
|
}
|
}
|
|
- (void) hangUpCall {
|
LinphoneCore* lc = [LinphoneManager getLc];
|
LinphoneCall* currentcall = linphone_core_get_current_call(lc);
|
if (linphone_core_is_in_conference(lc) || // In conference
|
(linphone_core_get_conference_size(lc) > 0) // Only one conf
|
) {
|
linphone_core_terminate_conference(lc);
|
} else if(currentcall != NULL) { // In a call
|
linphone_core_terminate_call(lc, currentcall);
|
} else {
|
const MSList* calls = linphone_core_get_calls(lc);
|
if (ms_list_size(calls) == 1) { // Only one call
|
linphone_core_terminate_call(lc,(LinphoneCall*)(calls->data));
|
}
|
}
|
NSLog(@"挂断");
|
}
|
|
- (void) configVideo: (UIView*) videoView cameraView: (UIView*) cameraView {
|
if (videoView) {
|
linphone_core_set_native_video_window_id([LinphoneManager getLc], (__bridge void *)(videoView));
|
}
|
|
if(cameraView){
|
linphone_core_set_native_preview_window_id([LinphoneManager getLc], (__bridge void *)(cameraView));
|
}
|
}
|
|
- (void) requestOpenCamera {
|
|
if (!linphone_core_video_display_enabled(LC))
|
return;
|
|
LinphoneCall *call = linphone_core_get_current_call(LC);
|
if (call) {
|
LinphoneCallAppData *callAppData = (__bridge LinphoneCallAppData *)linphone_call_get_user_data(call);
|
callAppData->videoRequested = TRUE; /* will be used later to notify user if video was not activated because of the linphone core*/
|
LinphoneCallParams *call_params = linphone_core_create_call_params(LC,call);
|
linphone_call_params_enable_video(call_params, TRUE);
|
linphone_core_update_call(LC, call, call_params);
|
linphone_call_params_destroy(call_params);
|
} else {
|
NSLog(@"Cannot toggle video button, because no current call");
|
}
|
}
|
|
- (void) closeCamera {
|
if (!linphone_core_video_display_enabled(LC))
|
return;
|
[LinphoneManager.instance setSpeakerEnabled:FALSE];
|
|
LinphoneCall *call = linphone_core_get_current_call(LC);
|
if (call) {
|
LinphoneCallParams *call_params = linphone_core_create_call_params(LC,call);
|
linphone_call_params_enable_video(call_params, FALSE);
|
linphone_core_update_call(LC, call, call_params);
|
linphone_call_params_destroy(call_params);
|
} else {
|
NSLog(@"Cannot toggle video button, because no current call");
|
}
|
}
|
|
- (BOOL) isVideoEnabled: (ESCall*) call {
|
return linphone_call_params_video_enabled(linphone_call_get_current_params(call));
|
}
|
|
|
- (void) onCallUpdate: (NSNotification*) notification {
|
NSDictionary* userInfo = [notification userInfo];
|
NSValue* c = [userInfo valueForKey:@"call"];
|
// int state = (int)[userInfo valueForKey:@"state"];
|
LinphoneCallState state = [[userInfo objectForKey:@"state"] intValue];
|
NSString* message = [userInfo valueForKey:@"message"];
|
NSLog(@"========== onCallUpdatestate: %d, message: %@", state, message);
|
LinphoneCall* call = c.pointerValue;
|
|
NSDictionary *dict = @{@"call" : [NSValue valueWithPointer:call],
|
@"state" : [NSNumber numberWithInt:state],
|
@"message" : message};
|
|
switch (state) {
|
case LinphoneCallIncomingReceived:
|
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_CALL_COMMING object: self userInfo:dict];
|
case LinphoneCallOutgoingInit:
|
case LinphoneCallConnected:
|
case LinphoneCallStreamsRunning: {
|
// check video
|
if (![self isVideoEnabled:call]) {
|
const LinphoneCallParams *param = linphone_call_get_current_params(call);
|
const LinphoneCallAppData *callAppData =
|
(__bridge const LinphoneCallAppData *)(linphone_call_get_user_data(call));
|
if (state == LinphoneCallStreamsRunning && callAppData->videoRequested &&
|
linphone_call_params_low_bandwidth_enabled(param)) {
|
// too bad video was not enabled because low bandwidth
|
|
NSLog(@"带宽太低,无法开启视频通话");
|
|
callAppData->videoRequested = FALSE; /*reset field*/
|
}
|
}
|
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_CALL_STREAM_UPDATE object:self userInfo:dict];
|
break;
|
}
|
case LinphoneCallUpdatedByRemote: {
|
const LinphoneCallParams *current = linphone_call_get_current_params(call);
|
const LinphoneCallParams *remote = linphone_call_get_remote_params(call);
|
|
/* remote wants to add video */
|
if ((linphone_core_video_display_enabled([LinphoneManager getLc]) && !linphone_call_params_video_enabled(current) &&
|
linphone_call_params_video_enabled(remote)) &&
|
(!linphone_core_get_video_policy([LinphoneManager getLc])->automatically_accept ||
|
(([UIApplication sharedApplication].applicationState != UIApplicationStateActive) &&
|
floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max))) {
|
linphone_core_defer_call_update([LinphoneManager getLc], call);
|
|
|
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_REMOTE_OPEN_CEMERA object: self userInfo:dict];
|
|
// [self allowToOpenCameraByRemote:call];
|
|
} else if (linphone_call_params_video_enabled(current) && !linphone_call_params_video_enabled(remote)) {
|
|
}
|
break;
|
}
|
case LinphoneCallUpdating:
|
break;
|
case LinphoneCallPausing:
|
case LinphoneCallPaused:
|
break;
|
case LinphoneCallPausedByRemote:
|
break;
|
case LinphoneCallEnd://LinphoneCallEnd
|
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_CALL_END object: self userInfo:NULL];
|
case LinphoneCallError:
|
default:
|
break;
|
}
|
}
|
|
-(void) allowToOpenCameraByRemote: (ESCall*)call {
|
LinphoneCallParams *params = linphone_core_create_call_params([LinphoneManager getLc], call);
|
linphone_call_params_enable_video(params, TRUE);
|
linphone_call_accept_update(call, params);
|
linphone_call_params_destroy(params);
|
}
|
|
-(void) refuseToOpenCameraByRemote: (ESCall*)call {
|
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
|
linphone_call_params_enable_video(params, FALSE);
|
linphone_call_accept_update(call, params);
|
linphone_call_params_destroy(params);
|
}
|
|
//-(NSString*) getCallName: (ESCall*)call {
|
// if (call == NULL)
|
// return NULL;
|
// LinphoneAddress *addr = linphone_call_get_remote_address(call);
|
// return [FastAddressBook displayNameForAddress:addr];
|
//}
|
|
@end
|