iOS linPhone 源碼編譯和應(yīng)用

  • 最近兩三個月會研究網(wǎng)絡(luò)電話linPhone的iOS應(yīng)用,網(wǎng)上的學習資料比較少,所以這里記錄整理一下學習到的東西,分享一下,希望可以幫助到其他人。

1.linPhone源碼編譯

  • linphone源碼GitLab
  • linphone源碼GitHub
    源碼編譯完成可以得到linphoneiOS集成用到的SDK,同時源碼中還有一個官方的linphoneDemo應(yīng)用。所有的API調(diào)用基本都是需要從這個官方的linphoneDemo中學習。
    源碼編譯方法,只有官方上面兩個源碼地址的ReadMe文件中的幾步,寫的很簡單,但是實際操作起來問題會比較多。
    這邊提供當時看的幾篇文章,應(yīng)該可以解決大部分問題。
    1.linphone-iphone的安裝與調(diào)試
    2.快速移植Linphone到自己的項目
    3.最新linphone-iphone Demo編譯運行
    另外遇到問題也可以去GitHub上的issues欄搜索下問題。我之前是在移動硬盤中進行源碼編譯,移動硬盤的名字要是英文的,如果是中文可能會遇到問題。我之前一直編譯不成功之后改了英文就可以了。
  • 另外linphone支持cocoapods安裝了,具體如何操作沒有研究

2.linphoneSDK 方法介紹

  • 源碼編譯雖然問題比較多,但是本文還是專注方法介紹。

2.1初始化、注冊、撥打、接聽、掛斷、狀態(tài)監(jiān)聽

可以參考快速移植Linphone到自己的項目 基本已經(jīng)列出
transport有三種方式UDP、TCP、TLS。前面兩個不需要配置什么,TLS應(yīng)該是需要配置證書,具體如何操作還沒有弄明白。
每次調(diào)用注冊方法都會把配置信息添加到LinphoneCore中,LinphoneCore做了本地持久處理,所以LinphoneCore中的帳號配置信息會越來越多,需要調(diào)用

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

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

2.2 部分操作方法

每個LinphoneCore的有一個默認的配置信息,和多個其他配置信息。一個配置信息對應(yīng)一個sip帳號。
配置信息對應(yīng)結(jié)構(gòu)體 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;
}
//獲取注冊狀態(tài)
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);
    //結(jié)束編輯
    linphone_proxy_config_done(proxy);

  • LinphoneCore操作方法(大部分初始化和配置設(shè)置都是通過linphone_core設(shè)置)
//設(shè)置超時
    linphone_core_set_inc_timeout(LC, 60);
//創(chuàng)建配置表
    LinphoneProxyConfig *proxyCfg = linphone_core_create_proxy_config(LC);
//添加注冊認證證書
    linphone_core_add_auth_info(LC, authInfo);
//添加到配置表,添加到linphone_core
    linphone_core_add_proxy_config(LC, proxyCfg);
//設(shè)置成默認配置表
        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);
//重新注冊所有配置信息(刷新狀態(tài))
linphone_core_refresh_registers(LC);

2.3音視頻編碼設(shè)置(注冊帳號的時候設(shè)置)

  • 音頻編碼設(shè)置
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
        //設(shè)置音頻編碼格式  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);
        }
        
    }
}
  • 視頻編碼設(shè)置
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鈴聲設(shè)置

鈴聲設(shè)置調(diào)用API設(shè)置

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)];
//通話狀態(tài)類型
        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安裝官網(wǎng)

安裝流程鏈接: https://pan.baidu.com/s/1ZamVLvc-fXjmRTyjKvIWIw 提取碼: e7h4

4.sip協(xié)議通話流程

sip協(xié)議呼叫流程詳解

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

linphone源碼都是在執(zhí)行sdk編譯命令的目錄下的submodules里面,如果需要修改就需要看這部分的內(nèi)容。
可以通過命令 查找文件名或者文件內(nèi)容一個個找。。。。
列舉一下我修改的源碼。主要是sip信令的內(nèi)容。
5.1 CSeq數(shù)字修改
Sequence Number linphone 默認從20開始
修改的地方在 Submodules/linphone/src/sal/op.cpp 522行


image.png

5.2 去除Contact參數(shù)后面的+sip.instance +org.linphone.specs
修改的地方也在oc.cpp 710行


image.png

5.3 修改401 unauthorized 之后register 中的Authorization中的CNonce
Submodules/belle-sip/src/auth_helper 25 行 修改生成的位數(shù) 默認16位


image.png

修改生成規(guī)則 Submodules/belle-sip/src/belle_sip_utils.c 267行和278行
選取的字符串數(shù)組


image.png

生成隨機字符串,如果改了symbols,需要修改下圖中的63。修改為symbols的長度-1;順便提一下 我沒見過 (val & 63)這樣取數(shù)字的方法。??
image.png

其他可以通過sdk api設(shè)置

5.4修改自定義header頭

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

5.5修改Contact參數(shù)

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");
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • feisky云計算、虛擬化與Linux技術(shù)筆記posts - 1014, comments - 298, trac...
    不排版閱讀 4,393評論 0 5
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,699評論 1 32
  • 點擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個完善的 IM 系統(tǒng)...
    layjoy閱讀 14,527評論 0 15
  • 很多人舉辦婚禮講究是和和美美,因此會在選擇酒的時候也要用寓意明顯、價格適中、大眾容易接受的口感來作為婚宴用酒。下面...
    酒會開花閱讀 3,728評論 0 0
  • 崢嶸已成回首,磅礴渾然而出。 2015歲在乙未,過往一切終化為所成,未來氣象已昭然若見。 不勝欣慰。 阿彌陀佛。
    木子哲學閱讀 215評論 2 0

友情鏈接更多精彩內(nèi)容