iOS linPhone 源码编译和应用

  • 最近两三个月会研究网络电话linPhone的iOS应用,网上的学习资料比较少,所以这里记录整理一下学习到的东西,分享一下,希望可以帮助到其他人。

1.linPhone源码编译

  • linphone源码GitLab
  • linphone源码GitHub
    源码编译完成可以得到linphoneiOS集成用到的SDK,同时源码中还有一个官方的linphoneDemo应用。所有的API调用基本都是需要从这个官方的linphoneDemo中学习。
    源码编译方法,只有官方上面两个源码地址的ReadMe文件中的几步,写的很简单,但是实际操作起来问题会比较多。
    这边提供当时看的几篇文章,应该可以解决大部分问题。
    1.linphone-iphone的安装与调试
    2.快速移植Linphone到自己的项目
    3.最新linphone-iphone Demo编译运行
    另外遇到问题也可以去GitHub上的issues栏搜索下问题。我之前是在移动硬盘中进行源码编译,移动硬盘的名字要是英文的,如果是中文可能会遇到问题。我之前一直编译不成功之后改了英文就可以了。
  • 另外linphone支持cocoapods安装了,具体如何操作没有研究

2.linphoneSDK 方法介绍

  • 源码编译虽然问题比较多,但是本文还是专注方法介绍。

2.1初始化、注册、拨打、接听、挂断、状态监听

可以参考快速移植Linphone到自己的项目 基本已经列出
transport有三种方式UDP、TCP、TLS。前面两个不需要配置什么,TLS应该是需要配置证书,具体如何操作还没有弄明白。
每次调用注册方法都会把配置信息添加到LinphoneCore中,LinphoneCore做了本地持久处理,所以LinphoneCore中的帐号配置信息会越来越多,需要调用

    linphone_core_clear_proxy_config([LinphoneManager getLc]);
    linphone_core_clear_all_auth_info([LinphoneManager getLc]);

可以清理到所有配置信息。

2.2 部分操作方法

每个LinphoneCore的有一个默认的配置信息,和多个其他配置信息。一个配置信息对应一个sip帐号。
配置信息对应结构体 LinphoneProxyConfig

  • LinphoneProxyConfig操作方法
//获取所有配置列表
const bctbx_list_t *accounts = linphone_core_get_proxy_config_list(LC);
size_t count = bctbx_list_size(accounts);
for (size_t i = 1; i <= count; i++, accounts = accounts->next) {
    LinphoneProxyConfig *proxy = (LinphoneProxyConfig *)accounts->data;
}
//获取注册状态
LinphoneRegistrationState state = linphone_proxy_config_get_state(proxy);
//获取整个sip注册帐号地址信息
const LinphoneAddress *adrs = linphone_proxy_config_get_identity_address(proxy);
//获取注册地址
NSString *domain = [[NSString alloc] initWithUTF8String:linphone_address_get_domain(adrs)];
//获取注册sip帐号
NSString *userName = [[NSString alloc] initWithUTF8String:linphone_address_get_username(adrs)];
//获取注册sip昵称
NSString *domain = [[NSString alloc] initWithUTF8String:linphone_address_get_display_name(adrs)];
//获取注册端口
NSString *domain = [[NSString alloc] initWithUTF8String:linphone_address_get_port(adrs)];
//获取注册transport
LinphoneTransportType transport = linphone_address_get_transport(adrs);

//编辑配置信息
    //开始编辑
    linphone_proxy_config_edit(proxy);
    linphone_proxy_config_enable_register(proxy, TRUE);
    //结束编辑
    linphone_proxy_config_done(proxy);

  • LinphoneCore操作方法(大部分初始化和配置设置都是通过linphone_core设置)
//设置超时
    linphone_core_set_inc_timeout(LC, 60);
//创建配置表
    LinphoneProxyConfig *proxyCfg = linphone_core_create_proxy_config(LC);
//添加注册认证证书
    linphone_core_add_auth_info(LC, authInfo);
//添加到配置表,添加到linphone_core
    linphone_core_add_proxy_config(LC, proxyCfg);
//设置成默认配置表
        linphone_core_set_default_proxy_config(LC, proxyCfg);
//获取默认配置表
        LinphoneProxyConfig *default_proxy = linphone_core_get_default_proxy_config(LC);
//获取所有配置列表
const bctbx_list_t *accounts = linphone_core_get_proxy_config_list(LC);
//重新注册所有配置信息(刷新状态)
linphone_core_refresh_registers(LC);

2.3音视频编码设置(注册帐号的时候设置)

  • 音频编码设置
const bctbx_list_t *codescs = linphone_core_get_audio_codecs(LC);

- (void)synchronizeCodecs:(const MSList *)codecs {
    
    PayloadType *pt;
    const MSList *elem;
    
    for (elem = codecs; elem != NULL; elem = elem->next) {
        
        pt = (PayloadType *)elem->data;
        
        NSString *sreung = [NSString stringWithFormat:@"%s", pt->mime_type];
        NSString *normalBt = [NSString stringWithFormat:@"%d",pt->clock_rate];
//sreung 有这些值 opus,speex,PCMU,PCMA,GSM,G722,G729,iLBC,mpeg4-generic,iSAC,L16
        //设置音频编码格式  G711-u,G711-a
       if ([sreung isEqualToString:@"PCMU"]||[sreung isEqualToString:@"PCMA"]) {

           linphone_core_enable_payload_type(LC,pt, TRUE);

        }else
        {

            linphone_core_enable_payload_type(LC, pt, FALSE);
        }
        
    }
}
  • 视频编码设置
const bctbx_list_t *codescs = linphone_core_get_video_codecs(LC);
- (void)synchronizeVideoCodecs:(const MSList *)codecs {
    
    PayloadType *pt;
    const MSList *elem;
    
    for (elem = codecs; elem != NULL; elem = elem->next) {
        
        pt = (PayloadType *)elem->data;
        NSString *sreung = [NSString stringWithFormat:@"%s", pt->mime_type];
        if ([sreung isEqualToString:@"H264"]) {
            
            linphone_core_enable_payload_type(LC, pt, 1);
            
        }else {
            
            linphone_core_enable_payload_type(LC, pt, 0);
        }
    }
}

2.4铃声设置

铃声设置调用API设置

NSString *path = [[NSBundle mainBundle] pathForResource:@"notes_of_the_optimistic" ofType:@"caf"];
        const char *cPath = [path UTF8String];
        linphone_core_set_ring(LC, cPath);

2.5通话记录获取

官方Demo中的 HistoryListTableView.m 中有代码。通话记录存储在本地DB中

NSString *db = [NSString stringWithUTF8String:linphone_core_get_call_logs_database_path(LC)];
    NSLog(@"history DB:%@",db);

历史记录


//获取所有本地通话logs
    const bctbx_list_t *logs = linphone_core_get_call_logs(LC);
//获取1001帐号本地通话logs
// LinphoneAddress *adr = [LinphoneUtils normalizeSipOrPhoneAddress:@"1001"];
// bctbx_list_t *logs = linphone_core_get_call_history_for_address(LC, adr);

//遍历所有通话记录
//    while (logs != NULL) {
//    LinphoneCallLog *log = (LinphoneCallLog *)logs->data;
//}

//打印一条记录
if(logs!=NULL){
LinphoneCallLog *log = (LinphoneCallLog *)logs->data;
        //通话开始时间
        NSDate *startDate = [NSDate
                             dateWithTimeIntervalSince1970:linphone_call_log_get_start_date(log)];
//通话状态类型
        LinphoneCallStatus status = linphone_call_log_get_status(log);
//拨打方 LinphoneAddress
        LinphoneAddress *fromAddress = linphone_call_log_get_from_address(log);
//接听方 LinphoneAddress
        LinphoneAddress *toAddress = linphone_call_log_get_to_address(log);
//对方 LinphoneAddress 
        LinphoneAddress *remoteAddress = linphone_call_log_get_remote_address(log);
        NSString *callStatus = @"None";
        switch (status) {
            case LinphoneCallSuccess:
                callStatus = @"LinphoneCallSuccess";
                break;
            case LinphoneCallAborted:
                callStatus = @"LinphoneCallAborted";
                break;
            case LinphoneCallMissed:
                callStatus = @"LinphoneCallMissed";
                break;
            case LinphoneCallDeclined:
                callStatus = @"LinphoneCallDeclined";
                break;
            case LinphoneCallEarlyAborted:
                callStatus = @"LinphoneCallEarlyAborted";
                break;
            case LinphoneCallAcceptedElsewhere:
                callStatus = @"LinphoneCallAcceptedElsewhere";
                break;
            case LinphoneCallDeclinedElsewhere:
                callStatus = @"LinphoneCallDeclinedElsewhere";
            default:
                break;
        }
//通过address 获取名字 地址等等
        NSString *fromName = [NSString stringWithUTF8String:linphone_address_get_username(fromAddress)];
        NSString *toName = [NSString stringWithUTF8String:linphone_address_get_username(toAddress)];
        NSString *remoteName = [NSString stringWithUTF8String:linphone_address_get_username(remoteAddress)];
        
        NSString *fromDomain = [NSString stringWithUTF8String:linphone_address_get_domain(fromAddress)];
         NSString *toDomain = [NSString stringWithUTF8String:linphone_address_get_domain(toAddress)];
         NSString *remoteDomain = [NSString stringWithUTF8String:linphone_address_get_domain(remoteAddress)];
        NSString *callDir = @"None";
//获取通话类型 拨出 打进
        LinphoneCallDir direction = linphone_call_log_get_dir(log);
        switch (direction) {
            case LinphoneCallIncoming:
                callDir = @"LinphoneCallIncoming";
                break;
            case LinphoneCallOutgoing:
                callDir = @"LinphoneCallOutgoing";
                break;
            default:
                break;
        }
//通话时长 s
        int duration = linphone_call_log_get_duration(log);
        NSLog(@"startTime:%@,LinphoneCallStatus:%@,fromName:%@,fromDomain:%@,toName:%@,toDomain:%@,remoteName:%@,remoteDomain:%@,callDir:%@,duration:%d",startDate,callStatus,fromName,fromDomain,toName,toDomain,remoteName,remoteDomain,callDir,duration);
}

3.freeSwitch安装

freeswitch安装官网

安装流程链接: https://pan.baidu.com/s/1ZamVLvc-fXjmRTyjKvIWIw 提取码: e7h4

4.sip协议通话流程

sip协议呼叫流程详解

5.linphone源码修改 (sip信令修改)

linphone源码都是在执行sdk编译命令的目录下的submodules里面,如果需要修改就需要看这部分的内容。
可以通过命令 查找文件名或者文件内容一个个找。。。。
列举一下我修改的源码。主要是sip信令的内容。
5.1 CSeq数字修改
Sequence Number linphone 默认从20开始
修改的地方在 Submodules/linphone/src/sal/op.cpp 522行


image.png

5.2 去除Contact参数后面的+sip.instance +org.linphone.specs
修改的地方也在oc.cpp 710行


image.png

5.3 修改401 unauthorized 之后register 中的Authorization中的CNonce
Submodules/belle-sip/src/auth_helper 25 行 修改生成的位数 默认16位


image.png

修改生成规则 Submodules/belle-sip/src/belle_sip_utils.c 267行和278行
选取的字符串数组


image.png

生成随机字符串,如果改了symbols,需要修改下图中的63。修改为symbols的长度-1;顺便提一下 我没见过 (val & 63)这样取数字的方法。
image.png

其他可以通过sdk api设置

5.4修改自定义header头

linphone_proxy_config_set_custom_header(proxyCfg, [@"Accept" UTF8String], [@"application/sdp" UTF8String]);

5.5修改Contact参数

linphone_proxy_config_set_contact_parameters(proxyCfg, [@"expires=3600" UTF8String]);

5.6修改信令中的expires

linphone_proxy_config_set_expires(proxyCfg,3600);

5.7修改User-Agent

NSString *device = [[NSMutableString alloc]
                        initWithString:[NSString
                                        stringWithFormat:@"%@_iOS%@",
                                        [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"],
                                        UIDevice.currentDevice.systemVersion]];
    device = [device stringByReplacingOccurrencesOfString:@"," withString:@"."];
    device = [device stringByReplacingOccurrencesOfString:@" " withString:@"."];
    linphone_core_set_user_agent(theLinphoneCore, device.UTF8String, "3.16-122-g79a8bb2");

你可能感兴趣的:(iOS linPhone 源码编译和应用)