linphone源码中其实暂无提供自定义头消息的解析功能,所以这里需要添加一部分代码,至于在什么地方添加自定义头消息,就需要了解linphone处理来电的sip请求的过程。
个人梳理了下大概分为以下几个过程:
- 接到请求后,从socket中解析出完整的SIP字符串,经过多次转换后生成event类型的结构体。
- 归类到INVITE类型的event后,通过provider来处理,过程中会生成SalOp对象。
- 生成JAVA层可以使用的LinphoneCall对象后,通过callState()接口回调给java层;
第一部分
首先看接收到来电INVITE类型的SIP请求时,触发了什么?
通过底层的log,来电后大致会触发到belle_sip_channel_process_data,位于channel.c line 705;
int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents){
belle_sip_message("belle_sip_channel_process_data");
int ret=BELLE_SIP_CONTINUE;
if (revents & BELLE_SIP_EVENT_READ) {
int rret=belle_sip_channel_process_read_data(obj);
if (rret==BELLE_SIP_STOP) ret=BELLE_SIP_STOP;
}
if (revents & BELLE_SIP_EVENT_WRITE){
/*if we are here, this is because we had an EWOULDBLOCK while sending a message*/
/*continue to send pending messages but before check the channel is still alive because
it may have been closed by belle_sip_channel_process_read_data() above.*/
if (obj->state == BELLE_SIP_CHANNEL_READY){
channel_process_queue(obj);
}
}
return ret;
}
入参的obj是已经经过初步解析的来电请求,revents是来电的事件类别;这里是一个READ的事件;
进入belle_sip_channel_process_read_data(obj);
static int belle_sip_channel_process_read_data(belle_sip_channel_t *obj){
belle_sip_message("belle_sip_channel_process_read_data");
int num;
int ret=BELLE_SIP_CONTINUE;
/*prevent system to suspend the process until we have finish reading everything from the socket and notified the upper layer*/
if (obj->input_stream.state == WAITING_MESSAGE_START) {
channel_begin_recv_background_task(obj);
}
if (obj->simulated_recv_return>0) {
num=belle_sip_channel_recv(obj,obj->input_stream.write_ptr,belle_sip_channel_input_stream_get_buff_length(&obj->input_stream)-1);
} else {
belle_sip_message("channel [%p]: simulating recv() returning %i",obj,obj->simulated_recv_return);
num=obj->simulated_recv_return;
}
if (num>0){
char *begin=obj->input_stream.write_ptr;
obj->input_stream.write_ptr+=num;
/*first null terminate the read buff*/
*obj->input_stream.write_ptr='\0';
....
belle_sip_channel_process_stream(obj,FALSE);
if (obj->input_stream.state == WAITING_MESSAGE_START){
channel_end_recv_background_task(obj);
}/*if still in message acquisition state, keep the backgroud task*/
}
......
return ret;
}
过程分析:
1、因为是刚接收到来电,通过channel_begin_recv_background_task(obj),这个主要是开启android的wake lock,
2、进入belle_sip_channel_recv(xxxx),这个过程主要是根据obj中存的的channel_recv回调,我们这边使用的是udp,所以这里最终是调用了udp_channel_recv(obj,buf,buflen),在udp_channel.c中,将obj此时指定的socket中的sip消息读取并存到obj->input_stream.write_ptr中,返回值是读取的消息长度;
3、判断是否读取到消息,也就是num>0?如果有的话,调用belle_sip_channel_process_stream(obj,FALSE);
4、最后调用channel_end_recv_background_task(obj)来关闭android的wake lock;
接着看第三步的belle_sip_channel_process_stream(obj,FALSE);
static void belle_sip_channel_process_stream(belle_sip_channel_t *obj, int eos){
belle_sip_channel_parse_stream(obj,eos);
if (obj->incoming_messages) {
if (obj->simulated_recv_return == 1500) {
belle_sip_list_t *elem;
for(elem=obj->incoming_messages;elem!=NULL;elem=elem->next){
belle_sip_message_t *msg=(belle_sip_message_t*)elem->data;
char* dump = belle_sip_message_to_string(msg);
belle_sip_message("Silently discarding incoming message [%.50s...] on channel [%p]",dump, obj);
belle_sip_free(dump);
}
belle_sip_list_free_with_data(obj->incoming_messages,belle_sip_object_unref);
obj->incoming_messages=NULL;
} else {
notify_incoming_messages(obj);
}
}
}
过程分析:
1、调用belle_sip_channel_parse_stream(obj,eos)来进行第一次的解析;
2、调用notify_incoming_messages(obj)来通知有来电接入;
先看第一步的belle_sip_channel_parse_stream(obj,eos); 还在channel.c中;
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream){
belle_sip_message("belle_sip_channel_parse_stream");
int offset;
size_t read_size=0;
int num;
while ((num=(int)(obj->input_stream.write_ptr-obj->input_stream.read_ptr))>0){
// belle_sip_message("num = %i",num);
if (obj->input_stream.state == WAITING_MESSAGE_START) {
int i;
/*first, make sure there is \r\n in the buffer, otherwise, micro parser cannot conclude, because we need a complete request or response line somewhere*/
for (i=0;i<num-1;i++) {
if ((obj->input_stream.read_ptr[i]=='\r' && obj->input_stream.read_ptr[i+1]=='\n')
|| belle_sip_channel_input_stream_get_buff_length(&obj->input_stream) <= 1 /*1 because null terminated*/ /*if buffer full try to parse in any case*/) {