修改linphonec

        Linphone是一个开源的SIP客户端,底层协议栈使用osip和eXosip,在linphone的源码包中,包含了一个exosip目录,这里是完整的exosip代码,这个exosip大概是0.9版的,0.9版与最新的2.*版相差很大。所以在使用linphone之前,只要先安装好osip库就行了。
        我在 www.antisip.com 注册了两个SIP用户,准备在我的机器上同时开两个linphone来试试,研究一下linphone的实现。
        Linphone在编译后主要生成两个可执行的程序,一个是linphone,它是有图形界面的UA;另一个是linphonec,没有图形界面,是一个命令行的UA,我喜欢用命令行,所以只用linphonec。
        我在本机注册了两个用户,一个raysan一个raypan,它们分别对应我在antisip服务器上的两个SIP帐户。在本机分别登录两个用户,分别启动linphonec程序,会自动在用户目录下生成.linphonerc文件,里面是一些配置信息,进行适当的修改后,重新启动linphonec,过一会儿提示已顺利注册。
        使用call命令从raysan向raypan发起呼叫,raypan很快收到呼叫,但两边都开始报出很多alsa方面的错误,一定是因为两边都要响铃(一边是ringing,一边是coming call),造成了声卡资源争用,所以出了错。修改代码,从coreapi/exevents.c里的事件响应部分开始,找到在收到RINGING和NEW_CALL消息时所要调用的函数,在其中注掉几个发出声音的函数,就不会再响了,也不会再报错了,收到call的时候只会有一条文本信息打出来。不过要是回复answer命令来接听的话,还是会报错的,因为两边都要争设备嘛。
        先从简单的研究入手。发现linphonec所提供的几种命令中没有用于即时消息的,于是想实现这个功能。Linphonec的代码比较简单,我对代码做了如下的添加和修改:
在linphonecore.c中加入函数:
 
int linphone_core_chat(LinphoneCore *lc, const char *url, const char *message)  {

        
char *route=
NULL;
        
const char *from=
NULL;
        LinphoneProxyConfig 
*proxy=
NULL;
        osip_to_t 
*to_parsed=
NULL;
        
char *to=
NULL;
        
int err=0
;

        linphone_core_get_default_proxy(lc,
&
proxy);
        
if (!linphone_core_interpret_url(lc,url,&to,&to_parsed))
{
                
return -1
;
        }

        
if (proxy!=NULL) {
                route
=
linphone_proxy_config_get_route(proxy);
                from
=
linphone_proxy_config_get_identity(proxy);
        }

        
/* if no proxy or no identity defined for this proxy, default to primary contact*/
        
if (from==NULL) from=linphone_core_get_primary_contact(lc);
        printf(
"## : linphone_core_chat() :  "
);
        printf(
"## : url = %s "
, url);
        printf(
"## : to = %s "
, to);
        printf(
"## : from = %s "
, from);
        printf(
"## : route = %s "
,route);
        printf(
"## : message = %s "
,message);

        eXosip_lock();
        err 
= eXosip_message(to, (char *)from, route, (char *
)message);
        eXosip_unlock();
        printf(
"## : err = %d "
,err);
        
return 0
;
}
在commands.c中修改命令表:
 
/*
 * Commands table.
 
*/

LPC_COMMAND commands[] 
=  {
    
"help", lpc_cmd_help, "Print commands help", NULL }
,
    
"call", lpc_cmd_call, "Call a SIP uri",
        
"'call <sip-url>' or 'c <sip-url>' "

        
": initiate a call to the specified destination."
        }
,
    
"terminate", lpc_cmd_terminate, "Terminate the current call",
        NULL }
,
    
"answer", lpc_cmd_answer, "Answer a call",
        
"Accept an incoming call."

    }
,
    
"proxy", lpc_cmd_proxy, "Manage proxies",
        
"'proxy list' : list all proxy setups. "

        
"'proxy add' : add a new proxy setup. "
        
"'proxy remove <index>' : remove proxy setup with number index. "
        
"'proxy use <index>' : use proxy with number index as default proxy. "
        
"'proxy unuse' : don't use a default proxy."
    }
,
    
"soundcard", lpc_cmd_soundcard, "Manage soundcards",
        
"'soundcard list' : list all sound devices. "

        
"'soundcard use <index>' : select a sound device. "
        
"'soundcard use files' : use .wav files instead of soundcard "
    }
,
    
"ipv6", lpc_cmd_ipv6, "Use IPV6",
        
"'ipv6 status' : show ipv6 usage status. "

        
"'ipv6 enable' : enable the use of the ipv6 network. "
        
"'ipv6 disable' : do not use ipv6 network."
    }
,
    
"refer", lpc_cmd_refer,
        
"Refer the current call to the specified destination."
,
        
"'refer <sip-url>' or 'r <sip-url>' "

        
": refer the current call to the specified destination."
    }
,
    
"nat", lpc_cmd_nat, "Set nat address",
        
"'nat'        : show nat settings. "

        
"'nat <addr>' : set nat address (and enable its use). "
        
"'nat use'    : enable nat use (ip must be set). "
        
"'nat unuse'  : disable nat use. "
    }
,
        
"call-logs", lpc_cmd_call_logs, "Calls history",
                NULL }
,
    
"friend", lpc_cmd_friend, "Manage friends",
        
"'friend list [<pattern>]'    : list friends. "

        
"'friend call <index>         : call a friend."
    }
,
    
"play", lpc_cmd_play, "play from a wav file",
        
"This feature is available only in file mode (see 'help soundcard') "

        
"'play <wav file>'    : play a wav file."
    }
,
    
"record", lpc_cmd_record, "record to a wav file",
        
"This feature is available only in file mode (see 'help soundcard') "

        
"'record <wav file>'    : record into wav file."
    }
,
    
"quit", lpc_cmd_quit, "Exit linphonec", NULL }
,
    
//Rayman

    "chat", lpc_cmd_chat, "Chat with someone","'chat <someone> <message>'" },
    
{ (char *)NULL, (lpc_cmd_handler)NULL, (char *)NULL, (char *)NULL }

}
;
并加入函数:
static int
lpc_cmd_chat
(LinphoneCore *lc, char *args)
 {
    char *url
=args;

    char *message
=NULL;
    
    while
(*url && !isspace(*url)) ++url;
    
if (*url)  {
        *url
='0';

        message
=url+1;
        while
(*message && isspace(*message)) ++message;
    }
    linphone_core_chat
(lc,args,message);
    
return 1;
}
        上面程序最核心的目的就是要调用eXosip_message这个函数,这是0.9版exosip里的,在最新版中已面目全非。
        顺利通过编译。运行!在raysan一端键入命令chat raypan hahaha,但遗憾的是在raypan这端并没有显示出有消息到来。用wireshark抓包,以下是其中两个包的截屏:
   
        表明raysan这端的确发出了一个MESSAGE请求,但是从服务器回来了一个unauthored错误信息,有点想不通,试了很多次,结果一样,google一下,未果。
        修改.linphonerc文件,把两个用户都作为本地用户,不向任何公共服务器注册,即本地用户raysan只向同是本地用户的raypan发MESSAGE请问,结果出人意料,MESSAGE消息收到了,但收到消息的不是raypan而是raysan自己,仔细想想,呵呵,也对,注意到上面的截图了吗,MESSAGE消息所在的UDP包的目标端口是5060,它的本意是SIP服务器开5060端口来接收SIP请求,但现在是在本机,raysan用的是5060,而raypan用的是5070,所以这个消息就又发给raysan了。如果是从raypan发给raysan的话,就一定能收到了。
 
        尽管通过公共SIP服务器来发即时消息还没有实现,但经过上面的实验说明使用eXosip_message来发送即时消息是对的,离成功还差一步。
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值