Linphone 被叫方如何解析来电SIP消息中的自定义头消息

本文详细介绍了如何在Linphone中解析来电SIP消息中的自定义头消息。由于linphone源码中没有内置此功能,因此需要添加代码。文章通过分析Linphone处理SIP请求的过程,包括从socket读取SIP字符串、解析消息、构建SalOp对象,最终回调到Java层。解析自定义头消息的关键在于将消息头保存到LinphoneCallParams的custom_headers中,以便在Java层通过getCustomHeader()获取。
摘要由CSDN通过智能技术生成

linphone源码中其实暂无提供自定义头消息的解析功能,所以这里需要添加一部分代码,至于在什么地方添加自定义头消息,就需要了解linphone处理来电的sip请求的过程。

个人梳理了下大概分为以下几个过程:

  1. 接到请求后,从socket中解析出完整的SIP字符串,经过多次转换后生成event类型的结构体
  2. 归类到INVITE类型的event后,通过provider来处理,过程中会生成SalOp对象。
  3. 生成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*/) {
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值