基于JAINSIP协议栈的一个简单SIP服务器实现流程.docx
- 文档编号:6351918
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:25
- 大小:19.64KB
基于JAINSIP协议栈的一个简单SIP服务器实现流程.docx
《基于JAINSIP协议栈的一个简单SIP服务器实现流程.docx》由会员分享,可在线阅读,更多相关《基于JAINSIP协议栈的一个简单SIP服务器实现流程.docx(25页珍藏版)》请在冰豆网上搜索。
基于JAINSIP协议栈的一个简单SIP服务器实现流程
基于JAINSIP协议栈的一个简单SIP服务器实现流程
基于JAINSIP协议栈的一个简单SIP服务器实现流程收藏
SIP服务器采用B2BUA,sip呼叫控制实现流程(暂时只支持两个终端之间的通话):
INVITE的请求:
收到INVITE后,克隆INVITE消息。
替换RequestURI被叫注册的地址。
替换VIA头为服务器地址。
通过该INVITE请求得到客户端事务并通过该事务来发送INVITE请求。
180,200OK响应的处理:
根据返回的响应码创建新的响应。
替换CONTACT头地址为服务器的地址。
拷贝原响应中的媒体内容至新的响应中。
通过INVITE中保存下来的服务端事务发送响应消息。
ACK的处理:
从ACK请求中得到序列数。
通过被叫对话来创建新的ACK请求。
通过被叫对话发送ACK请求。
BYE的处理流程:
根据被叫端的客户端事务得到发送给被叫的INVITE请求,根据INVITE请求创建BYE消息。
BYE响应消息处理流程:
根据DIALOG得到服务端事务,并由此得到BYE请求。
根据BYE请求创建响应。
CANCEL的处理流程:
向主叫响应CANCEL200OK。
根据客户端事务得到发送给主叫的INVITE请求中的URI,CALLID,FROM,TO,VIA头域来创建CANCEL请求。
注:
非200OK的ACK响应是由协议栈来实现的,不需要应用层来发送。
也就是说,ACK消息不会经过应用层。
附源代码:
packagecom.voip.sipphone;
importgov.nist.javax.sip.address.SipUri;
importgov.nist.javax.sip.header.CSeq;
importgov.nist.javax.sip.header.Contact;
importgov.nist.javax.sip.header.ContentLength;
importgov.nist.javax.sip.header.ContentType;
importgov.nist.javax.sip.header.From;
importgov.nist.javax.sip.header.Via;
importjava.text.ParseException;
importjava.util.ArrayList;
importjava.util.Hashtable;
importjava.util.List;
importjava.util.Properties;
importjava.util.Timer;
importjavax.sip.*;
importjavax.sip.address.Address;
importjavax.sip.address.AddressFactory;
importjavax.sip.address.URI;
importjavax.sip.header.CallIdHeader;
importjavax.sip.header.ContactHeader;
importjavax.sip.header.ExpiresHeader;
importjavax.sip.header.FromHeader;
importjavax.sip.header.Header;
importjavax.sip.header.HeaderFactory;
importjavax.sip.header.MaxForwardsHeader;importjavax.sip.header.RecordRouteHeader;importjavax.sip.header.ToHeader;
importjavax.sip.header.ViaHeader;
importjavax.sip.message.MessageFactory;
importjavax.sip.message.Request;
importjavax.sip.message.Response;
publicclassSipPhoneimplementsSipListener{
publicvoidprocessDialogTerminated(DialogTerminatedEventarg0){
//TODOAuto-generatedmethodstub
System.out.println("processDialogTerminated"+arg0.toString());
}
publicvoidprocessIOException(IOExceptionEventarg0){
//TODOAuto-generatedmethodstub
System.out.println("processIOException"+arg0.toString());
}
/**
*保存当前注册的用户
*/
privatestaticHashtable
/**
*@authorsoftware
*注册定时器
*/
classTimerTaskextendsTimer
{
/**
*defaultconstructor
*/
publicTimerTask()
{
}
/**
*如果定时任务到,则删除该用户的注册信息
*/
publicvoidrun()
{
}
}
/**
*服务器侦听IP地址
*/
privateStringipAddr="192.168.0.20";
/**
*服务器侦听端口
*/
privateintport=5060;
/**
*处理register请求
*@paramrequest请求消息
*/
privatevoidprocessRegister(Requestrequest,RequestEventrequestEvent)
{
if(null==request)
{
System.out.println("processInviterequestisnull.");
return;
}
//System.out.println("Request"+request.toString());
ServerTransactionserverTransactionId=requestEvent.getServerTransaction();
try
{
Responseresponse=null;
ToHeaderhead=(ToHeader)request.getHeader(ToHeader.NAME);
AddresstoAddress=head.getAddress();
URItoURI=toAddress.getURI();
ContactHeadercontactHeader=(ContactHeader)request.getHeader("Contact");
AddresscontactAddr=contactHeader.getAddress();
URIcontactURI=contactAddr.getURI();
System.out.println("processRegisterfrom:
"+toURI+"requeststr:
"+contactURI);
intexpires=request.getExpires().getExpires();
//如果expires不等于0,则为注册,否则为注销。
if(expires!
=0||contactHeader.getExpires()!
=0)
{
currUser.put(toURI,contactURI);
System.out.println("registeruser"+toURI);
}
else
{
currUser.remove(toURI);
System.out.println("unregisteruser"+toURI);
}
response=msgFactory.createResponse(200,request);
System.out.println("sendregisterresponse:
"+response.toString());
if(serverTransactionId==null)
{
serverTransactionId=sipProvider.getNewServerTransaction(request);
serverTransactionId.sendResponse(response);
//serverTransactionId.terminate();
System.out.println("registerserverTransaction:
"+serverTransactionId);
}
else
{
System.out.println("processRequestserverTransactionIdisnull.");
}
}
catch(ParseExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
catch(SipExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
catch(InvalidArgumentExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
/**
*处理invite请求
*@paramrequest请求消息
*/
privatevoidprocessInvite(Requestrequest,RequestEventrequestEvent)
{
if(null==request)
{
System.out.println("processInviterequestisnull.");
return;
}
try
{
//发送100Trying
serverTransactionId=requestEvent.getServerTransaction();
if(serverTransactionId==null)
{
serverTransactionId=sipProvider.getNewServerTransaction(request);
callerDialog=serverTransactionId.getDialog();
Responseresponse=msgFactory.createResponse(Response.TRYING,request);
serverTransactionId.sendResponse(response);
}
//查询目标地址
URIreqUri=request.getRequestURI();
URIcontactURI=currUser.get(reqUri);
System.out.println("processInviterqStr="+reqUri+"contact="+contactURI);
//根据Requesturi来路由,后续的响应消息通过VIA来路由
RequestcliReq=msgFactory.createRequest(request.toString());
cliReq.setRequestURI(contactURI);
ViacallerVia=(Via)request.getHeader(Via.NAME);
Viavia=(Via)headerFactory.createViaHeader(ipAddr,port,"UDP",callerVia.getBranch()+"sipphone");
//FIXME需要测试是否能够通过设置VIA头域来修改VIA头域值
cliReq.removeHeader(Via.NAME);
cliReq.addHeader(via);
//更新contact的地址
ContactHeadercontactHeader=headerFactory.createContactHeader();
Addressaddress=addressFactory.createAddress("sip:
sipsoft@"+ipAddr+":
"+port);
contactHeader.setAddress(address);
contactHeader.setExpires(3600);
cliReq.setHeader(contactHeader);
clientTransactionId=sipProvider.getNewClientTransaction(cliReq);
clientTransactionId.sendRequest();
System.out.println("processInviteclientTransactionId="+clientTransactionId.toString());
System.out.println("sendinvitetocallee:
"+cliReq);
}
catch(TransactionUnavailableExceptione1)
{
//TODOAuto-generatedcatchblock
e1.printStackTrace();
}
catch(SipExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
catch(ParseExceptione)
{
e.printStackTrace();
}
catch(Exceptione)
{
e.printStackTrace();
}
}
/**
*处理SUBSCRIBE请求
*@paramrequest请求消息
*/
privatevoidprocessSubscribe(Requestrequest)
{
if(null==request)
{
System.out.println("processSubscriberequestisnull.");
return;
}
ServerTransactionserverTransactionId=null;
try
{
serverTransactionId=sipProvider.getNewServerTransaction(request);
}
catch(TransactionAlreadyExistsExceptione1)
{
//TODOAuto-generatedcatchblock
e1.printStackTrace();
}catch(TransactionUnavailableExceptione1)
{
//TODOAuto-generatedcatchblock
e1.printStackTrace();
}
try
{
Responseresponse=null;
response=msgFactory.createResponse(200,request);
if(response!
=null)
{
ExpiresHeaderexpireHeader=headerFactory.createExpiresHeader(30);
response.setExpires(expireHeader);
}
System.out.println("response:
"+response.toString());
if(serverTransactionId!
=null)
{
serverTransactionId.sendResponse(response);
serverTransactionId.terminate();
}
else
{
System.out.println("processRequestserverTransactionIdisnull.");
}
}
catch(ParseExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
catch(SipExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
catch(InvalidArgumentExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
/**
*处理BYE请求
*@paramrequest请求消息
*/
privatevoidprocessBye(Requestrequest,RequestEventrequestEvent)
{
if(null==request||null==requestEvent)
{
System.out.println("processByerequestisnull.");
return;
}
RequestbyeReq=null;
Dialogdialog=requestEvent.getDialog();
System.out.println("calleeDialog:
"+calleeDialog);
System.out.println("callerDialog:
"+callerDialog);
try
{
if(dialog.equals(calleeDialog))
{
byeReq=callerDialog.createRequest(request.getMethod());
ClientTransactionclientTran=sipProvider.getNewClientTransaction(byeReq);
callerDialog.sendRequest(clientTran);
calleeDialog.setApplicationData(requestEvent.getServerTransaction());
}
elseif(dialog.equals(callerDialog))
{
byeReq=calleeDialog.createRequest(request.getMethod());
ClientTransactionclientTran=sipProvider.getNewClientTransaction(byeReq);
calleeDialog.sendRequest(clientTran);
callerDialog.setApplicationData(requestEvent.getServerTransaction());
}
else
{
System.out.println("");
}
System.out.println("sendbyetopeer:
"+byeReq.toString());
}
catch(SipExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
/**
*处理CANCEL请求
*@paramrequest请求消息
*/
privatevoidprocessCancel(Requestrequest)
{
if(null==request)
{
System.out.println("processCancelrequestisnull.");
return;
}
}
/**
*处理INFO请求
*@paramrequest请求消息
*/
privatevoidprocessInfo(Requestrequest)
{
if(null==request)
{
System.out.println("processInforequestisnull.");
return;
}
}
/**
*处理ACK请求
*@paramrequest请求消息
*/
privatevoidprocessAck(Requestrequest,RequestEventrequestEvent)
{
if(null==request)
{
System.out.println("processAckrequestisnull.");
return;
}
try
{
RequestackRequest=null;
CSeqcsReq=(CSeq)request.getHeader(CSeq.NAME);
ackRequest=calleeDialog.createAck(csReq.getSeqNumber());
calleeDialog.sendAck(ackRequest);
System.out.println("sendack
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 JAINSIP 协议 一个 简单 SIP 服务器 实现 流程
![提示](https://static.bdocx.com/images/bang_tan.gif)