JLChen
2021-08-02 38f4fb064df09f344fc3237409c76a9fba2a8a9e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
//
//  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