- 最近兩三個月會研究網(wǎng)絡(luò)電話linPhone的iOS應(yīng)用莺奔,網(wǎng)上的學(xué)習(xí)資料比較少鸠珠,所以這里記錄整理一下學(xué)習(xí)到的東西饺蔑,分享一下锌介,希望可以幫助到其他人。
1.linPhone源碼編譯
- linphone源碼GitLab
-
linphone源碼GitHub
源碼編譯完成可以得到linphoneiOS集成用到的SDK猾警,同時源碼中還有一個官方的linphoneDemo應(yīng)用孔祸。所有的API調(diào)用基本都是需要從這個官方的linphoneDemo中學(xué)習(xí)。
源碼編譯方法发皿,只有官方上面兩個源碼地址的ReadMe文件中的幾步崔慧,寫的很簡單,但是實(shí)際操作起來問題會比較多穴墅。
這邊提供當(dāng)時看的幾篇文章惶室,應(yīng)該可以解決大部分問題。
1.linphone-iphone的安裝與調(diào)試
2.快速移植Linphone到自己的項(xiàng)目
3.最新linphone-iphone Demo編譯運(yùn)行
另外遇到問題也可以去GitHub上的issues欄搜索下問題玄货。我之前是在移動硬盤中進(jìn)行源碼編譯皇钞,移動硬盤的名字要是英文的,如果是中文可能會遇到問題松捉。我之前一直編譯不成功之后改了英文就可以了夹界。 - 另外linphone支持cocoapods安裝了,具體如何操作沒有研究
2.linphoneSDK 方法介紹
- 源碼編譯雖然問題比較多隘世,但是本文還是專注方法介紹掉盅。
2.1初始化、注冊以舒、撥打趾痘、接聽、掛斷蔓钟、狀態(tài)監(jiān)聽
可以參考快速移植Linphone到自己的項(xiàng)目 基本已經(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的有一個默認(rèn)的配置信息踪央,和多個其他配置信息。一個配置信息對應(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);
//添加注冊認(rèn)證證書
linphone_core_add_auth_info(LC, authInfo);
//添加到配置表,添加到linphone_core
linphone_core_add_proxy_config(LC, proxyCfg);
//設(shè)置成默認(rèn)配置表
linphone_core_set_default_proxy_config(LC, proxyCfg);
//獲取默認(rèn)配置表
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";
//獲取通話類型 撥出 打進(jìn)
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安裝
安裝流程鏈接: https://pan.baidu.com/s/1ZamVLvc-fXjmRTyjKvIWIw 提取碼: e7h4
4.sip協(xié)議通話流程
5.linphone源碼修改 (sip信令修改)
linphone源碼都是在執(zhí)行sdk編譯命令的目錄下的submodules里面液斜,如果需要修改就需要看這部分的內(nèi)容。
可以通過命令 查找文件名或者文件內(nèi)容一個個找叠穆。少漆。。硼被。
列舉一下我修改的源碼检疫。主要是sip信令的內(nèi)容。
5.1 CSeq數(shù)字修改
Sequence Number linphone 默認(rèn)從20開始
修改的地方在 Submodules/linphone/src/sal/op.cpp 522行
5.2 去除Contact參數(shù)后面的+sip.instance +org.linphone.specs
修改的地方也在oc.cpp 710行
5.3 修改401 unauthorized 之后register 中的Authorization中的CNonce
Submodules/belle-sip/src/auth_helper 25 行 修改生成的位數(shù) 默認(rèn)16位
修改生成規(guī)則 Submodules/belle-sip/src/belle_sip_utils.c 267行和278行
選取的字符串?dāng)?shù)組
生成隨機(jī)字符串祷嘶,如果改了symbols,需要修改下圖中的63夺溢。修改為symbols的長度-1论巍;順便提一下 我沒見過 (val & 63)這樣取數(shù)字的方法。??
其他可以通過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");