您的位置:首页 > 其它

linphone-LinphoneAddressImpl文件对应的JNI层文件分析

2017-12-27 14:57 716 查看


说明

本篇是java及对应的c语言的分析的第一篇,旨在通过每一个文件对jni层部分的主要逻辑进行分析。


UML类图




newLinphoneAddressImpl函数分析

/**
*@params uri  网址
*@params displayName 要显示的名称
*/
private native long newLinphoneAddressImpl(String uri,String displayName);
1
2
3
4
5
[/code]

linphonecore_jni.cc 中对应的文件
extern "C" jlong Java_org_linphone_core_LinphoneAddressImpl_newLinphoneAddressImpl(JNIEnv*  env,jobject  thiz,jstring juri,jstring jdisplayName) {
const char* uri = juri?env->GetStringUTFChars(juri, NULL):NULL;
LinphoneAddress* address = linphone_address_new(uri);
if (jdisplayName && address) {
const char* displayName = env->GetStringUTFChars(jdisplayName, NULL);
linphone_address_set_display_name(address,displayName);
env->ReleaseStringUTFChars(jdisplayName, displayName);
}
if (uri) env->ReleaseStringUTFChars(juri, uri);

return  (jlong) address;
}
1
2
3
4
5
6
7
8
9
10
11
12
[/code]

这里清楚明了, 主要是创建一个LinphonAddress, 其中需要注意的是,调用字符串一定要释放字符串。

其中:LinphoneAddress * 的定义是
linphoncore.h
/**
* Object that represents a SIP address.
*
* The LinphoneAddress is an opaque object to represents SIP addresses, ie
* the content of SIP's 'from' and 'to' headers.
* A SIP address is made of display name, username, domain name, port, and various
* uri headers (such as tags). It looks like 'Alice <sip:alice@example.net>'.
* The LinphoneAddress has methods to extract and manipulate all parts of the address.
* When some part of the address (for example the username) is empty, the accessor methods
* return NULL.
*
* @ingroup linphone_address
*/
typedef struct SalAddress LinphoneAddress;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[/code]

是由SalAddress定义的。

其中SalAddress怎么来的呢?
sal.h
struct SalAddress;
typedef struct SalAddress SalAddress
1
2
3
[/code]

查找linphone_address_new函数
linphonecore.h
LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr);
1
2
[/code]

其中LINPHONE_PUBLIC是一个扩展修饰符:如果有兴趣,请看下面的文章。但是我不建议看,我C++不是很好, 我也没有看。

c++ 中__declspec 的用法

然后,这个函数是在哪里实例化的呢, 一位我的目的是通过linphone来学习C/C++所以,我还是要一探究竟。

通过grep -r “linphone_address_new(“ 找到了如下的结果:
linphone/coreapi/address.c:LinphoneAddress * linphone_address_new(const char *addr){
1
[/code]

他妈的,终于找到这个函数的实现了:
/**
* Constructs a LinphoneAddress object by parsing the user supplied address,
* given as a string.
**/
LinphoneAddress * linphone_address_new(const char *addr){
SalAddress *saddr=sal_address_new(addr);
if (saddr==NULL)
ms_error("Cannot create LinphoneAddress, bad uri [%s]",addr);
return saddr;
}
1
2
3
4
5
6
7
8
9
10
[/code]

无语了, 这里竟然又调用了一个函数, 真是坑爹啊。不过还是要找一找,找之前,看一下这个函数的其它地方。 好的,就一个报错函数, 这个报错函数看不看, 最后看心情。

开始找sal_address_new()函数, 通过grep -r “sal_address_new(“ 找到了
linphone/include/sal/sal.h:SalAddress * sal_address_new(const char *uri);

linphone/coreapi/bellesip_sal/sal_address_impl.c:SalAddress * sal_address_new(const char *uri){
1
2
3
[/code]

和其实现
/* Address manipulation API*/
SalAddress * sal_address_new(const char *uri){
belle_sip_header_address_t*  result;
if (uri) {
result=belle_sip_header_address_parse (uri);
/*may return NULL*/
} else {
result = belle_sip_header_address_new();
belle_sip_header_address_set_uri(result,belle_sip_uri_new());
}
if (result) belle_sip_object_ref(result);
return (SalAddress *)result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
[/code]

其中用到了,bellesip中的库, 这里就不往下分析了, 已经超出的初步计划的内容了。我们的目标是~没有蛀牙(要慢慢的来)

等会会儿,还不着急, 分析了下下底层,我们也得要看看谁调用了它。这里主来是看LinphoneAddress<-LinphoneAddressImpl 。

看看java代码
protected LinphoneAddressImpl(String identity)  throws LinphoneCoreException{
nativePtr = newLinphoneAddressImpl(identity, null);
if(nativePtr==0) {
throw new LinphoneCoreException("Cannot create LinphoneAdress from ["+identity+"]");
}
}
protected LinphoneAddressImpl(String username,String domain,String displayName)  {
nativePtr = newLinphoneAddressImpl(null, displayName);
this.setUserName(username);
this.setDomain(domain);
}
1
2
3
4
5
6
7
8
9
10
11
[/code]

这下就懵懵懂懂的明白了, 声称一个nativePtr标识符。 这个可大有用处呢。应不应该深入研究一下这个nativePtr, 算了, 技术不行,慢慢啃吧。

总结

这里是通过LinphoneAddress 强转成jlong, 的地址返回给java上层。

主要生成nativePtr


ref 函数分析


对应的jni函数

/*
* Class:     org_linphone_core_LinphoneAddressImpl
* Method:    ref
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneAddressImpl_ref
(JNIEnv *, jobject, jlong);
1
2
3
4
5
6
7
[/code]


具体的方法实现

linphonecore_jni.cc
extern "C" jlong Java_org_linphone_core_LinphoneAddressImpl_ref(
JNIEnv*  env,
jobject thiz,jlong ptr) {
return (jlong)linphone_address_ref((LinphoneAddress*)ptr);
}
1
2
3
4
5
6
[/code]

这里调用了linphone_address_ref()函数, 看看这个函数在哪里呢?

在submodules/linphone/coreapi/linphonecore.h中有声明
LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr);
1
[/code]

在submodules/linphone/coreapi/address.c中有实现
/**
* Increment reference count of LinphoneAddress object.
**/
LinphoneAddress * linphone_address_ref(LinphoneAddress *addr){
return sal_address_ref(addr);
}
1
2
3
4
5
6
[/code]

这里又莫名奇妙的遇到了sal_address_ref(addr)函数, 让我们来看看这个函数吧。靠!它不在这个文件中,让我来找找它在哪里。

通过 grep -r “sal_addres_ref” 找到了下面的结果。
submodules/linphone/include/sal/sal.h:SalAddress * sal_address_ref(SalAddress *addr);
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:SalAddress *sal_address_ref(SalAddress *addr){
submodules/linphone/coreapi/address.c:  return sal_address_ref(addr);
1
2
3
[/code]

这里我们找到了这个函数的实现
SalAddress *sal_address_ref(SalAddress *addr){
return (SalAddress*)belle_sip_object_ref(BELLE_SIP_HEADER_ADDRESS(addr));
}
1
2
3
[/code]

通过 重点内容 命令,我们大海捞针的找到了这个
submodules/belle-sip/include/belle-sip/headers.h:#define BELLE_SIP_HEADER_ADDRESS(t) BELLE_SIP_CAST(t,belle_sip_header_address_t)
1
[/code]

原来是一个define定义。
// BELLE_SIP_HEADER_ADDRESS  用的就是这个
submodules/belle-sip/include/belle-sip/object.h:#define BELLE_SIP_CAST(obj,_type)       ((_type*)belle_sip_object_cast((belle_sip_object_t *)(obj), _type##_id, #_type, __FILE__, __LINE__)
1
2
3
[/code]

怎么又是一个define定义, 在C/C++语言中, 这种定义也太频繁了吧。

找到了这个
submodules/belle-sip/include/belle-sip/object.h:BELLESIP_EXPORT void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno);

submodules/belle-sip/include/belle-sip/object.h:#define BELLE_SIP_CAST(obj,_type)       ((_type*)belle_sip_object_cast((belle_sip_object_t *)(obj), _type##_id, #_type, __FILE__, __LINE__))

submodules/belle-sip/src/belle_sip_object.c:void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno){
1
2
3
4
5
6
[/code]

其中
void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno){
if (obj!=NULL){
if (has_type(obj,id)==0){
belle_sip_fatal("Bad cast to %s at %s:%i",castname,file,fileno);
return NULL;
}
}
return obj;
}
1
2
3
4
5
6
7
8
9
[/code]

看这个
submodules/belle-sip/include/belle-sip/utils.h:static BELLESIP_INLINE void BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_fatal(const char *fmt,...)
1
[/code]
static BELLESIP_INLINE void BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_fatal(const char *fmt,...)
{
va_list args;
va_start (args, fmt);
belle_sip_logv(BELLE_SIP_LOG_FATAL, fmt, args);
va_end (args);
}
1
2
3
4
5
6
7
8
[/code]

好想知道va_start函数和belle_sip_logv函数和va_end函数是干什么的啊,好, 想就做:
static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args);

belle_sip_log_function_t belle_sip_logv_out=__belle_sip_logv_out;
1
2
3
4
[/code]
static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args){
const char *lname="undef";
char *msg;
struct timeval tp;
struct tm *lt;
#ifndef _WIN32
struct tm tmstorage;
#endif
time_t curtime;

belle_sip_gettimeofday(&tp,NULL);
curtime=tp.tv_sec;
#ifdef _WIN32
lt = localtime(&curtime);
#else
lt = localtime_r(&curtime,&tmstorage);
#endif

if (__log_file==NULL) __log_file=stderr;
switch(lev){
case BELLE_SIP_LOG_DEBUG:
lname="debug";
break;
case BELLE_SIP_LOG_MESSAGE:
lname="message";
break;
case BELLE_SIP_LOG_WARNING:
lname="warning";
break;
case BELLE_SIP_LOG_ERROR:
lname="error";
break;
case BELLE_SIP_LOG_FATAL:
lname="fatal";
break;
default:
belle_sip_fatal("Bad level !");
}
msg=belle_sip_strdup_vprintf(fmt,args);
#if defined(_MSC_VER) && !defined(_WIN32_WCE)
#ifndef _UNICODE
OutputDebugStringA(msg);
OutputDebugStringA("\r\n");
#else
{
int len=strlen(msg);
wchar_t *tmp=(wchar_t*)belle_sip_malloc0((len+1)*sizeof(wchar_t));
mbstowcs(tmp,msg,len);
OutputDebugStringW(tmp);
OutputDebugStringW(L"\r\n");
belle_sip_free(tmp);
}
#endif
#endif
fprintf(__log_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i belle-sip-%s-%s" ENDLINE,1900+lt->tm_year,lt->tm_mon+1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec,(int)(tp.tv_usec/1000), lname,msg);
fflush(__log_file);
// fatal messages should go to stderr too, even if we are using a file since application will abort right after
if (__log_file != stderr && lev == BELLE_SIP_LOG_FATAL) {
fprintf(stderr,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i belle-sip-%s-%s" ENDLINE,1900+lt->tm_year,lt->tm_mon+1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec,(int)(tp.tv_usec/1000), lname,msg);
fflush(stderr);
}
free(msg);
}
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
[/code]

算了,不分析了, 太难了,把这个放到下一个步骤吧。这里有点好高骛远了。但是这个函数是干什么的,这个得搞明白了啊。

最后结果:我也不知道这是干什么的。

感言: 感觉自己不是在写博客,而是在自娱自乐。就算是吧, 我怎么也得有个开头啊。要不怎么能写好博客呢!


unref函数分析

不想细细的分析了, 就这个样子吧。不过还得稍微看一下;
extern "C" void Java_org_linphone_core_LinphoneAddressImpl_unref(
JNIEnv*  env,
jobject  thiz,
jlong ptr) {

linphone_address_unref((LinphoneAddress*)ptr);
}
1
2
3
4
5
6
7
8
[/code]

这个就是具体实现, 跟上面有相反的作用。

看这里
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr);
1
[/code]
submodules/linphone/coreapi/address.c:void linphone_address_unref(LinphoneAddress *addr){
1
[/code]

找到了实现
/**
* Decrement reference count of LinphoneAddress object. When dropped to zero, memory is freed.
**/
void linphone_address_unref(LinphoneAddress *addr){
sal_address_unref(addr);
}
1
2
3
4
5
6
7
[/code]

接下来调用的这个函数是在这里声明的
submodules/linphone/include/sal/sal.h:void sal_address_unref(SalAddress *addr);

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:void sal_address_unref(SalAddress *addr){

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:    sal_address_unref(addr);

submodules/linphone/coreapi/address.c:  sal_address_unref(addr);

submodules/linphone/coreapi/address.c:  sal_address_unref(u);
1
2
3
4
5
6
7
8
9
10
[/code]

哈哈,在这里
void sal_address_unref(SalAddress *addr){
belle_sip_object_unref(BELLE_SIP_HEADER_ADDRESS(addr));
}
1
2
3
4
[/code]

这个函数就到这里吧, 搞得我头疼的很。

总结

就是跟ref函数相对应的, 我看着想什么格式化之类的,准不准就不说了, 反正是每搞明白。但是还是不影响往下分析。

脑洞大开

还是坚持把每个native函数对应的jni层及调用的库函数大致追踪一遍,不要求弄明白,大概有个了解, 知道有这个东西就可以了。毕竟,是一个初学者,想细究的也不差这点时间。


clone函数分析


对应jni函数

extern "C" jlong Java_org_linphone_core_LinphoneAddressImpl_clone(JNIEnv*  env
,jobject  thiz
,jlong ptr) {
return (jlong) (ptr ? linphone_address_clone((const LinphoneAddress*)ptr) : NULL);
}
1
2
3
4
5
[/code]

linphone_address_clone
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr);

submodules/linphone/coreapi/address.c:LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){
1
2
3
[/code]
/**
* Clones a LinphoneAddress object.
**/
LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){
return sal_address_clone(addr);
}
1
2
3
4
5
6
7
[/code]

不往下看了, 大约就是复制了一份传上来了。想到这里, 不禁发现,我还不知道nativePtr是干什么的,不行改天得去看看文档,看看前人都是怎么做的。


getDisplayName函数分析


对应jni函数

extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_getDisplayName(JNIEnv*  env
,jobject  thiz
,jlong ptr) {
const char* displayName = linphone_address_get_display_name((LinphoneAddress*)ptr);
if (displayName) {
return env->NewStringUTF(displayName);
} else {
return NULL;
}
}
1
2
3
4
5
6
7
8
9
10
[/code]

linphone_address_get_display_name
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC  const char *linphone_address_get_display_name(const LinphoneAddress* u);

submodules/linphone/coreapi/address.c:const char *linphone_address_get_display_name(const LinphoneAddress* u){
1
2
3
[/code]

这也太懒了吧, 我竟然连名字都不写了,够可以的。
/**
* Returns the display name.
**/
const char *linphone_address_get_display_name(const LinphoneAddress* u){
return sal_address_get_display_name(u);
}
1
2
3
4
5
6
[/code]

sal_address_get_display_name
submodules/linphone/include/sal/sal.h:const char *sal_address_get_display_name(const SalAddress* addr);

submodules/linphone/include/sal/sal.h:const char *sal_address_get_display_name_unquoted(const SalAddress *addr);

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:const char *sal_address_get_display_name(const SalAddress* addr){

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:const char *sal_address_get_display_name_unquoted(const SalAddress *addr){

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:    return sal_address_get_display_name(addr);
1
2
3
4
5
6
7
8
9
[/code]
const char *sal_address_get_display_name(const SalAddress* addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
return belle_sip_header_address_get_displayname(header_addr);

}
const char *sal_address_get_display_name_unquoted(const SalAddress *addr){
return sal_address_get_display_name(addr);
}
1
2
3
4
5
6
7
8
9
[/code]

belle_sip_header_address_get_displayname
submodules/belle-sip/include/belle-sip/headers.h:BELLESIP_EXPORT const char* belle_sip_header_address_get_displayname(const belle_sip_header_address_t* address);
1
2
[/code]

sal_address_get_display_name
submodules/linphone/include/sal/sal.h:const char *sal_address_get_display_name(const SalAddress* addr);

submodules/linphone/include/sal/sal.h:const char *sal_address_get_display_name_unquoted(const SalAddress *addr);

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:const char *sal_address_get_display_name(const SalAddress* addr){

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:const char *sal_address_get_display_name_unquoted(const SalAddress *addr){
1
2
3
4
5
6
7
8
[/code]

反正先生出来的两个函数,都是调用同一个函数进入。


getUserName函数分析


对应jni函数

extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_getUserName(JNIEnv*  env
,jobject  thiz
,jlong ptr) {
const char* userName = linphone_address_get_username((LinphoneAddress*)ptr);
if (userName) {
return env->NewStringUTF(userName);
} else {
return NULL;
}
}
1
2
3
4
5
6
7
8
9
10
[/code]

linphone_address_get_username
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC  const char *linphone_address_get_username(const LinphoneAddress *u);
1
[/code]
submodules/linphone/coreapi/address.c:const char *linphone_address_get_username(const LinphoneAddress *u){
1
[/code]
/**
* Returns the username.
**/
const char *linphone_address_get_username(const LinphoneAddress *u){
return sal_address_get_username(u);
}
1
2
3
4
5
6
7
[/code]

sal_address_get_username
submodules/linphone/include/sal/sal.h:const char *sal_address_get_username(const SalAddress *addr);
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:const char *sal_address_get_username(const SalAddress *addr){
1
2
[/code]
const char *sal_address_get_username(const SalAddress *addr){
SAL_ADDRESS_GET(addr,user)
}
1
2
3
[/code]

SAL_ADDRESS_GET
#define SAL_ADDRESS_GET(addr,param) \
{belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
if (uri) {\
return belle_sip_uri_get_##param(uri);\
} else\
return NULL;}
1
2
3
4
5
6
7
8
[/code]

我擦,神乎其神的, 竟然出现了一个“##param” ,真心看不懂啊, 这个真是难坏我了, 不过不用着急,毕竟这是C++部分了,并不是很闹心。除了分析linphone之外,我还不断的加强我在工程性的C++部分下手, 主要还是要看基础, 一切牛逼得到技术都离不开技术。


getDomain函数分析


对应的jni函数

extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_getDomain(JNIEnv*  env
,jobject  thiz
,jlong ptr) {
const char* domain = linphone_address_get_domain((LinphoneAddress*)ptr);
if (domain) {
return env->NewStringUTF(domain);
} else {
return NULL;
}
}
1
2
3
4
5
6
7
8
9
10
[/code]


追踪

linphone_address_get_domain
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC  const char *linphone_address_get_domain(const LinphoneAddress *u);

submodules/linphone/coreapi/address.c:const char *linphone_address_get_domain(const LinphoneAddress *u){
1
2
3
[/code]
/**
* Returns the domain name.
**/
const char *linphone_address_get_domain(const LinphoneAddress *u){
return sal_address_get_domain(u);
}
1
2
3
4
5
6
[/code]

sal_address_get_domain
submodules/linphone/include/sal/sal.h:const char *sal_address_get_domain(const SalAddress *addr);

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:const char *sal_address_get_domain(const SalAddress *addr){
1
2
3
[/code]
const char *sal_address_get_domain(const SalAddress *addr){
SAL_ADDRESS_GET(addr,host)
}
1
2
3
[/code]

SAL_ADDRESS_GET
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:#define SAL_ADDRESS_GET(addr,param) \
1
[/code]
#define SAL_ADDRESS_GET(addr,param) \
{belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
if (uri) {\
return belle_sip_uri_get_##param(uri);\
} else\
return NULL;}
1
2
3
4
5
6
7
[/code]

这个跟上面的调用的是同一个函数。旧这个就让我费解了,

容我任性的再往下追踪一下, 看看能不能找到最下面的东西。

BELLE_SIP_HEADER_ADDRESS
submodules/belle-sip/include/belle-sip/headers.h:#define BELLE_SIP_HEADER_ADDRESS(t) BELLE_SIP_CAST(t,belle_sip_header_address_t)
1
[/code]

BELLE_SIP_CAST
submodules/belle-sip/include/belle-sip/object.h:#define BELLE_SIP_CAST(obj,_type)       ((_type*)belle_sip_object_cast((belle_sip_object_t *)(obj), _type##_id, #_type, __FILE__, __LINE__))
1
[/code]

belle_sip_object_cast
submodules/belle-sip/include/belle-sip/object.h:BELLESIP_EXPORT void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno);
1
[/code]
void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno){
if (obj!=NULL){
if (has_type(obj,id)==0){
belle_sip_fatal("Bad cast to %s at %s:%i",castname,file,fileno);
return NULL;
}
}
return obj;
}
1
2
3
4
5
6
7
8
9
10
[/code]

belle_sip_fatal
static BELLESIP_INLINE void BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_fatal(const char *fmt,...)
{
va_list args;
va_start (args, fmt);
belle_sip_logv(BELLE_SIP_LOG_FATAL, fmt, args);
va_end (args);
}
1
2
3
4
5
6
7
[/code]

has_type
static int has_type(belle_sip_object_t *obj, belle_sip_type_id_t id){
belle_sip_object_vptr_t *vptr=obj->vptr;

while(vptr!=NULL){
if (vptr->id==id) return TRUE;
vptr=vptr->get_parent();
}
return FALSE;
}
1
2
3
4
5
6
7
8
9
[/code]

到底应该分析的这么清楚, 如果深入了会不会导致忘记了当初分析linphone的初衷。应该不会吧,毕竟并不是每一次都要分析这么深入。现在正在逐渐探索分析的方式。

其中《va_start》和《va_end》是系统的函数

va_start和va_end使用详解

竟然找到了va_start和va_end函数是系统函数,操作c语言中的可变参数。

一鼓作气, 继续深入, 哈哈。

belle_sip_logv
submodules/belle-sip/include/belle-sip/utils.h:BELLESIP_EXPORT void belle_sip_logv(int level, const char *fmt, va_list args);

submodules/belle-sip/include/belle-sip/utils.h:static BELLESIP_INLINE void belle_sip_logv(belle_sip_log_level level, const char *fmt, va_list args) {
1
2
3
[/code]
#if !defined(_WIN32) && !defined(_WIN32_WCE)
static BELLESIP_INLINE void belle_sip_logv(belle_sip_log_level level, const char *fmt, va_list args) {
if (belle_sip_logv_out!=NULL && belle_sip_log_level_enabled(level))
belle_sip_logv_out(level,fmt,args);
if (level==BELLE_SIP_LOG_FATAL) abort();
}
#else
BELLESIP_EXPORT void belle_sip_logv(int level, const char *fmt, va_list args);
#endif
1
2
3
4
5
6
7
8
9
10
[/code]

belle_sip_logv_out
submodules/belle-sip/include/belle-sip/utils.h:BELLESIP_VAR_EXPORT belle_sip_log_function_t belle_sip_logv_out;

submodules/belle-sip/src/belle_sip_utils.c:belle_sip_log_function_t belle_sip_logv_out=__belle_sip_logv_out
1
2
3
[/code]

__belle_sip_logv_out
static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args);
1
2
3
[/code]
static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args){
const char *lname="undef";
char *msg;
struct timeval tp;
struct tm *lt;
#ifndef _WIN32
struct tm tmstorage;
#endif
time_t curtime;

belle_sip_gettimeofday(&tp,NULL);
curtime=tp.tv_sec;
#ifdef _WIN32
lt = localtime(&curtime);
#else
lt = localtime_r(&curtime,&tmstorage);
#endif

if (__log_file==NULL) __log_file=stderr;
switch(lev){
case BELLE_SIP_LOG_DEBUG:
lname="debug";
break;
case BELLE_SIP_LOG_MESSAGE:
lname="message";
break;
case BELLE_SIP_LOG_WARNING:
lname="warning";
break;
case BELLE_SIP_LOG_ERROR:
lname="error";
break;
case BELLE_SIP_LOG_FATAL:
lname="fatal";
break;
default:
belle_sip_fatal("Bad level !");
}
msg=belle_sip_strdup_vprintf(fmt,args);
#if defined(_MSC_VER) && !defined(_WIN32_WCE)
#ifndef _UNICODE
OutputDebugStringA(msg);
OutputDebugStringA("\r\n");
#else
{
int len=strlen(msg);
wchar_t *tmp=(wchar_t*)belle_sip_malloc0((len+1)*sizeof(wchar_t));
mbstowcs(tmp,msg,len);
OutputDebugStringW(tmp);
OutputDebugStringW(L"\r\n");
belle_sip_free(tmp);
}
#endif
#endif
fprintf(__log_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i belle-sip-%s-%s" ENDLINE,1900+lt->tm_year,lt->tm_mon+1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec,(int)(tp.tv_usec/1000), lname,msg);
fflush(__log_file);
// fatal messages should go to stderr too, even if we are using a file since application will abort right after
if (__log_file != stderr && lev == BELLE_SIP_LOG_FATAL) {
fprintf(stderr,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i belle-sip-%s-%s" ENDLINE,1900+lt->tm_year,lt->tm_mon+1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec,(int)(tp.tv_usec/1000), lname,msg);
fflush(stderr);
}
free(msg);
}
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
[/code]


belle_sip_header_address_get_uri

submodules/belle-sip/include/belle-sip/headers.h:BELLESIP_EXPORT belle_sip_uri_t* belle_sip_header_address_get_uri(const belle_sip_header_address_t* address);
1
[/code]
flannery@flannery:~/oschina/linephone-android$ grep -r "*.belle_sip_header_address_get_uri"
submodules/belle-sip/include/belle-sip/headers.h:BELLESIP_EXPORT belle_sip_uri_t* belle_sip_header_address_get_uri(const belle_sip_header_address_t* address);
submodules/belle-sip/src/belle_sip_headers_impl.c:belle_sip_uri_t* belle_sip_header_address_get_uri(const belle_sip_header_address_t* address) {
1
2
3
[/code]
belle_sip_uri_t* belle_sip_header_address_get_uri(const belle_sip_header_address_t* address) {
return address->uri;
}
1
2
3
[/code]

今天快要疯了, 竟然还想要无耻的往下找,好吧,那就找吧。

belle_sip_header_address_t
submodules/belle-sip/include/belle-sip/headers.h:typedef struct _belle_sip_header_address belle_sip_header_address_t;
1
[/code]

_belle_sip_header_address
submodules/belle-sip/include/belle-sip/headers.h:typedef struct _belle_sip_header_address belle_sip_header_address_t;
submodules/belle-sip/src/belle_sip_headers_impl.c:struct _belle_sip_header_address {
1
2
[/code]
/************************
* header_address
***********************/
struct _belle_sip_header_address {
belle_sip_parameters_t base;
char* displayname;
belle_sip_uri_t* uri;
belle_generic_uri_t* absolute_uri;
};
1
2
3
4
5
6
7
8
9
[/code]


getTransport函数分析


对应jni函数

extern "C" jint Java_org_linphone_core_LinphoneAddressImpl_getTransport(JNIEnv*  env
,jobject  thiz
,jlong ptr) {
LinphoneTransportType transporttype = linphone_address_get_transport((LinphoneAddress*)ptr);
return (jint)transporttype;
}
1
2
3
4
5
6
[/code]


追踪

LinphoneTransportType
submodules/linphone/coreapi/linphonecore.h:typedef enum _LinphoneTransportType LinphoneTransportType;

submodules/linphone/coreapi/linphonecore.h:enum _LinphoneTransportType{

/**
* Enum describing transport type for LinphoneAddress.
* @ingroup linphone_address
**/
enum _LinphoneTransportType{
LinphoneTransportUdp,
LinphoneTransportTcp,
LinphoneTransportTls,
LinphoneTransportDtls
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[/code]

linphone_address_get_transport
submodules/linphone/coreapi/address.c:LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri){
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri);
1
2
[/code]
/**
* Get the transport.
**/
LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri){
return (LinphoneTransportType)sal_address_get_transport(uri);
}
1
2
3
4
5
6
[/code]

sal_address_get_transport
submodules/linphone/include/sal/sal.h:SalTransport sal_address_get_transport(const SalAddress* addr);

submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:SalTransport sal_address_get_transport(const SalAddress* addr){
1
2
3
[/code]
SalTransport sal_address_get_transport(const SalAddress* addr){
const char *transport=sal_address_get_transport_name(addr);
if (transport)
return sal_transport_parse(transport);
else
return SalTransportUDP;
};
1
2
3
4
5
6
7
[/code]

SalTransport
submodules/linphone/include/sal/sal.h:  SalTransportUDP, /*UDP*/
submodules/linphone/include/sal/sal.h:  SalTransportTCP, /*TCP*/
submodules/linphone/include/sal/sal.h:  SalTransportTLS, /*TLS*/
submodules/linphone/include/sal/sal.h:  SalTransportDTLS, /*DTLS*/
submodules/linphone/include/sal/sal.h:}SalTransport;
1
2
3
4
5
[/code]

可以看出就是个枚举。
typedef enum {
SalTransportUDP, /*UDP*/
SalTransportTCP, /*TCP*/
SalTransportTLS, /*TLS*/
SalTransportDTLS, /*DTLS*/
}SalTransport;
1
2
3
4
5
6
[/code]

SalAddress
submodules/linphone/include/sal/sal.h:struct SalAddress;
submodules/linphone/include/sal/sal.h:typedef struct SalAddress SalAddress;

submodules/linphone/coreapi/linphonecore.h:typedef struct SalAddress LinphoneAddress;
1
2
3
4
[/code]

到这里, 一定要有个小插曲:grep的重要性, 熟练的使用grep的用法是多么的重要。下面给个链接。

grep的用法

自己慢慢去看吧。

sal_address_get_transport_name
submodules/linphone/include/sal/sal.h:const char* sal_address_get_transport_name(const SalAddress* addr);
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:    const char *transport=sal_address_get_transport_name(addr);
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:const char* sal_address_get_transport_name(const SalAddress* addr){
1
2
3
4
[/code]
const char* sal_address_get_transport_name(const SalAddress* addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
if (uri) {
return belle_sip_uri_get_transport_param(uri);
}
return NULL;
}
1
2
3
4
5
6
7
8
[/code]

belle_sip_uri_get_transport_param
submodules/belle-sip/include/belle-sip/sip-uri.h:BELLESIP_EXPORT const char*    belle_sip_uri_get_transport_param(const belle_sip_uri_t* uri) ;
1
[/code]

最后我就不明白这是什么东西了。

sal_transport_parse
submodules/linphone/include/sal/sal.h:SalTransport sal_transport_parse(const char*);

submodules/linphone/coreapi/sal.c:SalTransport sal_transport_parse(const char* param) {
1
2
3
[/code]
SalTransport sal_transport_parse(const char* param) {
if (!param) return SalTransportUDP;
if (strcasecmp("udp",param)==0) return SalTransportUDP;
if (strcasecmp("tcp",param)==0) return SalTransportTCP;
if (strcasecmp("tls",param)==0) return SalTransportTLS;
if (strcasecmp("dtls",param)==0) return SalTransportDTLS;
ms_error("Unknown transport type[%s], returning UDP", param);
return SalTransportUDP;
}
1
2
3
4
5
6
7
8
9
10
[/code]


getPort 函数分析


Java_org_linphone_core_LinphoneAddressImpl_getPort

extern "C" jint Java_org_linphone_core_LinphoneAddressImpl_getPort(JNIEnv*  env
,jobject  thiz
,jlong ptr) {
int port = linphone_address_get_port((LinphoneAddress*)ptr);
return (jint)port;
}
1
2
3
4
5
6
7
[/code]


linphone_address_get_port

submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u);

submodules/linphone/coreapi/address.c:int linphone_address_get_port(const LinphoneAddress *u) {
1
2
3
[/code]
/**
* Get port number, 0 if not present.
*/
int linphone_address_get_port(const LinphoneAddress *u) {
return sal_address_get_port(u);
}
1
2
3
4
5
6
[/code]


sal_address_get_port

submodules/linphone/include/sal/sal.h:int sal_address_get_port(const SalAddress *addr);
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:int sal_address_get_port(const SalAddress *addr){
1
2
[/code]
int sal_address_get_port(const SalAddress *addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
if (uri) {
return belle_sip_uri_get_port(uri);
} else
return -1;
}
1
2
3
4
5
6
7
8
[/code]


belle_sip_uri_get_port

submodules/belle-sip/include/belle-sip/sip-uri.h:BELLESIP_EXPORT int    belle_sip_uri_get_port(const belle_sip_uri_t* uri) ;
1
[/code]


toUri函数分析


Java_org_linphone_core_LinphoneAddressImpl_toUri

extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_toUri(JNIEnv*  env
,jobject  thiz
,jlong ptr) {
char* uri = linphone_address_as_string_uri_only((LinphoneAddress*)ptr);
jstring juri =env->NewStringUTF(uri);
ms_free(uri);
return juri;
}
1
2
3
4
5
6
7
8
[/code]


linphone_address_as_string_uri_only

submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC  char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
1
[/code]
/**
* Returns the SIP uri only as a string, that is display name is removed.
* The returned char * must be freed by the application. Use ms_free().
**/
char *linphone_address_as_string_uri_only(const LinphoneAddress *u){
return sal_address_as_string_uri_only(u);
}
1
2
3
4
5
6
7
[/code]


sal_address_as_string_uri_only

submodules/linphone/include/sal/sal.h:char *sal_address_as_string_uri_only(const SalAddress *u);
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:char *sal_address_as_string_uri_only(const SalAddress *addr){
1
2
3
[/code]
char *sal_address_as_string_uri_only(const SalAddress *addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_uri_t* sip_uri = belle_sip_header_address_get_uri(header_addr);
belle_generic_uri_t* absolute_uri = belle_sip_header_address_get_absolute_uri(header_addr);
char tmp[1024]={0};
size_t off=0;
belle_sip_object_t* uri;

if (sip_uri) {
uri=(belle_sip_object_t*)sip_uri;
} else if (absolute_uri) {
uri=(belle_sip_object_t*)absolute_uri;
} else {
ms_error("Cannot generate string for addr [%p] with null uri",addr);
return NULL;
}
belle_sip_object_marshal(uri,tmp,sizeof(tmp),&off);
return ms_strdup(tmp);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[/code]


belle_sip_object_marshal

submodules/belle-sip/include/belle-sip/object.h:

/**
* Writes a string representation of the object into the supplied buffer.
* Same as belle_sip_object_to_string(), but without allocating space for the output string.
**/
BELLESIP_EXPORT belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset);
1
2
3
4
5
6
7
[/code]
submodules/belle-sip/src/belle_sip_object.c:belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset) {
1
[/code]
belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset) {
belle_sip_object_vptr_t *vptr=obj->vptr;
while (vptr != NULL) {
if (vptr->marshal != NULL) {
if (_belle_sip_object_marshal_check_enabled == TRUE)
return checked_marshal(vptr,obj,buff,buff_size,offset);
else
return vptr->marshal(obj,buff,buff_size,offset);
} else {
vptr=vptr->get_parent();
}
}
return BELLE_SIP_NOT_IMPLEMENTED; /*no implementation found*/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[/code]


setDisplayName函数分析


Java_org_linphone_core_LinphoneAddressImpl_setDisplayName

extern "C" void Java_org_linphone_core_LinphoneAddressImpl_setDisplayName(JNIEnv*  env
,jobject  thiz
,jlong address
,jstring jdisplayName) {
const char* displayName = jdisplayName!= NULL?env->GetStringUTFChars(jdisplayName, NULL):NULL;
linphone_address_set_display_name((LinphoneAddress*)address,displayName);
if (displayName != NULL) env->ReleaseStringUTFChars(jdisplayName, displayName);
}
1
2
3
4
5
6
7
8
[/code]


linphone_address_set_display_name

submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC  int linphone_address_set_display_name(LinphoneAddress *u, const char *display_name);

submodules/linphone/coreapi/address.c:int linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){
1
2
3
4
[/code]
/**
* Sets the display name.
**/
int linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){
sal_address_set_display_name(u,display_name);
return 0;
}
1
2
3
4
5
6
7
[/code]


sal_address_set_display_name

submodules/linphone/include/sal/sal.h:void sal_address_set_display_name(SalAddress *addr, const char *display_name);
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:void sal_address_set_display_name(SalAddress *addr, const char *display_name){
1
2
3
[/code]
void sal_address_set_display_name(SalAddress *addr, const char *display_name){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_header_address_set_displayname(header_addr,display_name);
}
1
2
3
4
[/code]


belle_sip_header_address_set_displayname

submodules/belle-sip/include/belle-sip/headers.h:BELLESIP_EXPORT void belle_sip_header_address_set_displayname(belle_sip_header_address_t* address, const char* uri);
1
[/code]


setDomain函数分析


Java_org_linphone_core_LinphoneAddressImpl_setDomain

extern "C" void Java_org_linphone_core_LinphoneAddressImpl_setDomain(JNIEnv*  env
,jobject  thiz
,jlong address
,jstring jdomain) {
const char* domain = jdomain!= NULL?env->GetStringUTFChars(jdomain, NULL):NULL;
linphone_address_set_domain((LinphoneAddress*)address,domain);
if (domain != NULL) env->ReleaseStringUTFChars(jdomain, domain);
}
1
2
3
4
5
6
7
8
[/code]


linphone_address_set_domain

submodules/linphone/coreapi/address.c:int linphone_address_set_domain(LinphoneAddress *uri, const char *host){

submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC  int linphone_address_set_domain(LinphoneAddress *uri, const char *host);
1
2
3
[/code]
/**
* Sets the domain.
**/
int linphone_address_set_domain(LinphoneAddress *uri, const char *host){
if (host) {
char *identity = ms_strdup_printf("sip:%s", host);
LinphoneAddress* test = linphone_address_new(identity);
ms_free(identity);
if (test) {
sal_address_set_domain(uri,host);
linphone_address_destroy(test);
return 0;
}
}
return -1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[/code]


setUserName函数分析


Java_org_linphone_core_LinphoneAddressImpl_setUserName

extern "C" void Java_org_linphone_core_LinphoneAddressImpl_setUserName(JNIEnv*  env
,jobject  thiz
,jlong address
,jstring juserName) {
const char* userName = juserName!= NULL?env->GetStringUTFChars(juserName, NULL):NULL;
linphone_address_set_username((LinphoneAddress*)address,userName);
if (userName != NULL) env->ReleaseStringUTFChars(juserName, userName);
}
1
2
3
4
5
6
7
8
[/code]


setTransport函数分析


Java_org_linphone_core_LinphoneAddressImpl_setTransport

extern "C" void Java_org_linphone_core_LinphoneAddressImpl_setTransport(JNIEnv*  env
,jobject  thiz
,jlong address
,jint jtransport) {
linphone_address_set_transport((LinphoneAddress*)address, (LinphoneTransportType) jtransport);
}
1
2
3
4
5
6
[/code]


setPort函数分析


Java_org_linphone_core_LinphoneAddressImpl_setPort

extern "C" void Java_org_linphone_core_LinphoneAddressImpl_setPort(JNIEnv*  env
,jobject  thiz
,jlong address
,jint jport) {
linphone_address_set_port((LinphoneAddress*)address, (LinphoneTransportType) jport);
}
1
2
3
4
5
6
[/code]


toString函数分析


Java_org_linphone_core_LinphoneAddressImpl_toString

extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_toString(JNIEnv*  env
,jobject  thiz
,jlong ptr) {
char* uri = linphone_address_as_string((LinphoneAddress*)ptr);
jstring juri =env->NewStringUTF(uri);
ms_free(uri);
return juri;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: