说明
本篇是java及对应的c语言的分析的第一篇,旨在通过每一个文件对jni层部分的主要逻辑进行分析。
UML类图
newLinphoneAddressImpl函数分析
/**
*@params uri 网址
*@params displayName 要显示的名称
*/
private native long newLinphoneAddressImpl(String uri,String displayName);
- 1
- 2
- 3
- 4
- 5
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
这里清楚明了, 主要是创建一个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
是由SalAddress定义的。
其中SalAddress怎么来的呢?
sal.h
struct SalAddress;
typedef struct SalAddress SalAddress
- 1
- 2
- 3
查找linphone_address_new函数
linphonecore.h
LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr);
- 1
- 2
其中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
他妈的,终于找到这个函数的实现了:
/**
* 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
无语了, 这里竟然又调用了一个函数, 真是坑爹啊。不过还是要找一找,找之前,看一下这个函数的其它地方。 好的,就一个报错函数, 这个报错函数看不看, 最后看心情。
开始找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
和其实现
/* 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
其中用到了,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
这下就懵懵懂懂的明白了, 声称一个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
具体的方法实现
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
这里调用了linphone_address_ref()函数, 看看这个函数在哪里呢?
在submodules/linphone/coreapi/linphonecore.h中有声明
LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr);
- 1
在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
这里又莫名奇妙的遇到了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
这里我们找到了这个函数的实现
SalAddress *sal_address_ref(SalAddress *addr){
return (SalAddress*)belle_sip_object_ref(BELLE_SIP_HEADER_ADDRESS(addr));
}
- 1
- 2
- 3
通过 重点内容 命令,我们大海捞针的找到了这个
submodules/belle-sip/include/belle-sip/headers.h:#define BELLE_SIP_HEADER_ADDRESS(t) BELLE_SIP_CAST(t,belle_sip_header_address_t)
- 1
原来是一个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
怎么又是一个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
其中
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
看这个
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
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
好想知道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
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
算了,不分析了, 太难了,把这个放到下一个步骤吧。这里有点好高骛远了。但是这个函数是干什么的,这个得搞明白了啊。
最后结果:我也不知道这是干什么的。
感言: 感觉自己不是在写博客,而是在自娱自乐。就算是吧, 我怎么也得有个开头啊。要不怎么能写好博客呢!
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
这个就是具体实现, 跟上面有相反的作用。
看这里
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr);
- 1
submodules/linphone/coreapi/address.c:void linphone_address_unref(LinphoneAddress *addr){
- 1
找到了实现
/**
* 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
接下来调用的这个函数是在这里声明的
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
哈哈,在这里
void sal_address_unref(SalAddress *addr){
belle_sip_object_unref(BELLE_SIP_HEADER_ADDRESS(addr));
}
- 1
- 2
- 3
- 4
这个函数就到这里吧, 搞得我头疼的很。
总结
就是跟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
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
/**
* Clones a LinphoneAddress object.
**/
LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){
return sal_address_clone(addr);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
不往下看了, 大约就是复制了一份传上来了。想到这里, 不禁发现,我还不知道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
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
这也太懒了吧, 我竟然连名字都不写了,够可以的。
/**
* 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
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
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
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
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
反正先生出来的两个函数,都是调用同一个函数进入。
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
linphone_address_get_username
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u);
- 1
submodules/linphone/coreapi/address.c:const char *linphone_address_get_username(const LinphoneAddress *u){
- 1
/**
* 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
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
const char *sal_address_get_username(const SalAddress *addr){
SAL_ADDRESS_GET(addr,user)
}
- 1
- 2
- 3
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
我擦,神乎其神的, 竟然出现了一个“##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
追踪
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
/**
* 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
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
const char *sal_address_get_domain(const SalAddress *addr){
SAL_ADDRESS_GET(addr,host)
}
- 1
- 2
- 3
SAL_ADDRESS_GET
submodules/linphone/coreapi/bellesip_sal/sal_address_impl.c:#define SAL_ADDRESS_GET(addr,param) \
- 1
#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
这个跟上面的调用的是同一个函数。旧这个就让我费解了,
容我任性的再往下追踪一下, 看看能不能找到最下面的东西。
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
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
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
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
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
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
到底应该分析的这么清楚, 如果深入了会不会导致忘记了当初分析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
#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
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
__belle_sip_logv_out
static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args);
- 1
- 2
- 3
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
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
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
belle_sip_uri_t* belle_sip_header_address_get_uri(const belle_sip_header_address_t* address) {
return address->uri;
}
- 1
- 2
- 3
今天快要疯了, 竟然还想要无耻的往下找,好吧,那就找吧。
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
_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
/************************
* 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
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
追踪
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
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
/**
* Get the transport.
**/
LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri){
return (LinphoneTransportType)sal_address_get_transport(uri);
}
- 1
- 2
- 3
- 4
- 5
- 6
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
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
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
可以看出就是个枚举。
typedef enum {
SalTransportUDP, /*UDP*/
SalTransportTCP, /*TCP*/
SalTransportTLS, /*TLS*/
SalTransportDTLS, /*DTLS*/
}SalTransport;
- 1
- 2
- 3
- 4
- 5
- 6
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
到这里, 一定要有个小插曲: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
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
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
最后我就不明白这是什么东西了。
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
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
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
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
/**
* 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
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
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
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
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
linphone_address_as_string_uri_only
submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
- 1
/**
* 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
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
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
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
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
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
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
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
/**
* 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
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
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
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
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
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
/**
* 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
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
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
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
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;
}