在Openfire的插件里面,有一個(gè)Sip插件,但是該Sip插件不是一個(gè)Sip服務(wù)器,只是一個(gè)Sip客戶端,下面主要介紹如何在Openfire上集成一個(gè)簡單的Sip服務(wù)器插件。
1、遵守Sip標(biāo)準(zhǔn)協(xié)議
2、標(biāo)準(zhǔn)Sip客戶端能夠注冊(cè)該Sip服務(wù)器
3、能夠完成一次完整的呼叫流程和掛斷流程
4、能夠?qū)τ脩暨M(jìn)行管理以及用戶的在線狀態(tài)進(jìn)行管理(未呈現(xiàn),用心跳檢測(cè)和線程處理)
5、基于Sip的Java開發(fā)包(JainSipApi.jar、JainSipRi.jar、concurrent.jar、log4j.jar)
注冊(cè)信息 = REGISTER sip:SIPServer@172.16.7.85:8888 SIP/2.0
Via: SIP/2.0/UDP 172.16.10.51:5060;rport=5060;branch=z9hG4bK-524287-1---4c518269a1efa15b;received=172.16.10.51
Max-Forwards: 70
Contact: <sip:test@172.16.10.51:5060;rinstance=d683c6b6819cc373>
To: <sip:test@172.16.10.51>
From: <sip:test@172.16.10.51>;tag=59501018
Call-ID: KcEz2oIKiX7gTRccriDi5w..
CSeq: 1 REGISTER
Expires: 3600
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,UPDATE,REGISTER,INFO,MESSAGE,SUBSCRIBE,NOTIFY,PUBLISH,REFER
Supported: resource-priority,timer
User-Agent: xt_sip/1.0
Channel: type=satellite/fixed;delay=100;packetloss=5;mtu=1500;bandwidth=2048
Content-Length: 0
回復(fù)200OK : SIP/2.0 200 OK
Via: SIP/2.0/UDP 172.16.10.51:5060;rport=5060;branch=z9hG4bK-524287-1---55994f7fd27ea93b;received=172.16.10.51
To: <sip:test@172.16.10.51>
From: <sip:test@172.16.10.51>;tag=59501018
Call-ID: KcEz2oIKiX7gTRccriDi5w..
CSeq: 32 REGISTER
Content-Length: 0
收到呼叫請(qǐng)求
收到的呼叫請(qǐng)求:INVITE sip:YPSQ06720040@172.16.7.85:8888 SIP/2.0
Via: SIP/2.0/UDP 172.16.10.51:5060;rport=5060;branch=z9hG4bK-524287-1---b92653756e52b813;received=172.16.10.51
Max-Forwards: 70
Contact: <sip:test@172.16.10.51:5060>
To: <sip:YPSQ06720040@172.16.7.85:8888>
From: <sip:test@172.16.10.51>;tag=4862ae20
Call-ID: Gd_5NlNEurlhgtCXTweqAA..
CSeq: 1 INVITE
Session-Expires: 1800
Min-SE: 90
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,UPDATE,REGISTER,INFO,MESSAGE,SUBSCRIBE,NOTIFY,PUBLISH,REFER
Content-Type: application/sdp
Supported: resource-priority,timer
User-Agent: xt_sip/1.0
Content-Length: 368
v=0
o=userName 1 1 IN IP4 172.16.10.51
s=Play
i=2?videoCodecType=H.264
c=IN IP4 172.16.10.51
b=AS:1024
t=0 0
m=video 40000 RTP/AVP 96 97
c=IN IP4 172.16.10.51
a=rtpmap:96 H264/90000
a=rtpmap:97 H265/90000
a=control:track1
a=recvonly
m=audio 40002 RTP/AVP 100 100
c=IN IP4 172.16.10.51
a=rtpmap:100 MPEG4-GENERIC/8000
a=rtpmap:100 PCMA/8000
a=control:track2
a=recvonly
contact = sip:YPSQ06720040@172.16.10.190:5060;rinstance=41b242381416fe37
轉(zhuǎn)發(fā)呼叫請(qǐng)求:INVITE sip:YPSQ06720040@172.16.10.190:5060;rinstance=41b242381416fe37 SIP/2.0
Max-Forwards: 70
To: <sip:YPSQ06720040@172.16.7.85:8888>
From: <sip:test@172.16.10.51>;tag=4862ae20
Call-ID: Gd_5NlNEurlhgtCXTweqAA..
CSeq: 1 INVITE
Session-Expires: 1800
Min-SE: 90
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,UPDATE,REGISTER,INFO,MESSAGE,SUBSCRIBE,NOTIFY,PUBLISH,REFER
Content-Type: application/sdp
Supported: resource-priority,timer
User-Agent: xt_sip/1.0
Via: SIP/2.0/UDP 172.16.7.85:8888;branch=z9hG4bK-524287-1---b92653756e52b813sipphone
Contact: <sip:sipsoft@172.16.7.85:8888>;expires=3600
Content-Length: 368
v=0
o=userName 1 1 IN IP4 172.16.10.51
s=Play
i=2?videoCodecType=H.264
c=IN IP4 172.16.10.51
b=AS:1024
t=0 0
m=video 40000 RTP/AVP 96 97
c=IN IP4 172.16.10.51
a=rtpmap:96 H264/90000
a=rtpmap:97 H265/90000
a=control:track1
a=recvonly
m=audio 40002 RTP/AVP 100 100
c=IN IP4 172.16.10.51
a=rtpmap:100 MPEG4-GENERIC/8000
a=rtpmap:100 PCMA/8000
a=control:track2
a=recvonly
收到Ringing
收到的ring:SIP/2.0 180 Ringing
Via: SIP/2.0/UDP 172.16.7.85:8888;branch=z9hG4bK-524287-1---b92653756e52b813sipphone
Contact: <sip:YPSQ06720040@172.16.10.190:5060>
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=920bce1e
From: <sip:test@172.16.10.51>;tag=4862ae20
Call-ID: Gd_5NlNEurlhgtCXTweqAA..
CSeq: 1 INVITE
User-Agent: xt_sip/1.0
Content-Length: 0
sdp is null.
發(fā)送回復(fù)ring : SIP/2.0 180 Ringing
Via: SIP/2.0/UDP 172.16.10.51:5060;rport=5060;branch=z9hG4bK-524287-1---b92653756e52b813;received=172.16.10.51
From: <sip:test@172.16.10.51>;tag=4862ae20
Call-ID: Gd_5NlNEurlhgtCXTweqAA..
CSeq: 1 INVITE
Contact: <sip:sipsoft@172.16.7.85:8888>;expires=3600
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=920bce1e
Content-Length: 0
收到200OK
收到的200OK:SIP/2.0 200 OK
Via: SIP/2.0/UDP 172.16.7.85:8888;branch=z9hG4bK-524287-1---b92653756e52b813sipphone
Require: timer
Contact: <sip:YPSQ06720040@172.16.10.190:5060>
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=920bce1e
From: <sip:test@172.16.10.51>;tag=4862ae20
Call-ID: Gd_5NlNEurlhgtCXTweqAA..
CSeq: 1 INVITE
Session-Expires: 1800;refresher=uas
Min-SE: 90
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,UPDATE,REGISTER,INFO,MESSAGE
Content-Type: application/sdp
Supported: resource-priority,timer
User-Agent: xt_sip/1.0
Content-Length: 580
v=0
o=YPSQ06720040 2400244997 1 IN IP4 172.16.10.190
s=-
i=stream
c=IN IP4 172.16.10.190
t=0 0
a=tool:XTXK Stream Server V2015.5.14
a=control:*
a=range:npt=0-
a=x-qt-text-nam:-
a=x-qt-text-inf:stream
m=video 6982 RTP/AVP 96
c=IN IP4 172.16.10.190
a=control:track1
a=rtcp-fb:* fir
a=sendonly
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=42000a;sprop-parameter-sets=Z00ACpWosTpuAgICBA==,aO48gA==
m=audio 40002 RTP/AVP 100 100
c=IN IP4 172.16.10.190
a=rtpmap:100 MPEG4-GENERIC/8000
a=rtpmap:100 PCMA/8000
a=control:track2
a=inactive
the sdp contenttype is Content-Type: application/sdp
發(fā)送回復(fù)200OK :SIP/2.0 200 OK
Via: SIP/2.0/UDP 172.16.10.51:5060;rport=5060;branch=z9hG4bK-524287-1---b92653756e52b813;received=172.16.10.51
From: <sip:test@172.16.10.51>;tag=4862ae20
Call-ID: Gd_5NlNEurlhgtCXTweqAA..
CSeq: 1 INVITE
Contact: <sip:sipsoft@172.16.7.85:8888>;expires=3600
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=920bce1e
Content-Type: application/sdp
Content-Length: 580
v=0
o=YPSQ06720040 2400244997 1 IN IP4 172.16.10.190
s=-
i=stream
c=IN IP4 172.16.10.190
t=0 0
a=tool:XTXK Stream Server V2015.5.14
a=control:*
a=range:npt=0-
a=x-qt-text-nam:-
a=x-qt-text-inf:stream
m=video 6982 RTP/AVP 96
c=IN IP4 172.16.10.190
a=control:track1
a=rtcp-fb:* fir
a=sendonly
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=42000a;sprop-parameter-sets=Z00ACpWosTpuAgICBA==,aO48gA==
m=audio 40002 RTP/AVP 100 100
c=IN IP4 172.16.10.190
a=rtpmap:100 MPEG4-GENERIC/8000
a=rtpmap:100 PCMA/8000
a=control:track2
a=inactive
ACK請(qǐng)求
收到的ACK:ACK sip:sipsoft@172.16.7.85:8888 SIP/2.0
Via: SIP/2.0/UDP 172.16.10.51:5060;rport=5060;branch=z9hG4bK-524287-1---f9c3fe0d0d945038;received=172.16.10.51
Max-Forwards: 70
Contact: <sip:test@172.16.10.51:5060>
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=920bce1e
From: <sip:test@172.16.10.51>;tag=4862ae20
Call-ID: Gd_5NlNEurlhgtCXTweqAA..
CSeq: 1 ACK
User-Agent: xt_sip/1.0
Content-Length: 0
回復(fù)ACK:ACK sip:YPSQ06720040@172.16.10.190:5060 SIP/2.0
Via: SIP/2.0/UDP 172.16.7.85:8888;branch=z9hG4bK15888b8cae76785dffea07618fb89591
CSeq: 1 ACK
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=920bce1e
From: <sip:test@172.16.10.51>;tag=4862ae20
Call-ID: Gd_5NlNEurlhgtCXTweqAA..
Session-Expires: 1800;refresher=uas
Min-SE: 90
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,UPDATE,REGISTER,INFO,MESSAGE
Supported: resource-priority,timer
User-Agent: xt_sip/1.0
Max-Forwards: 70
Content-Length: 0
Bye請(qǐng)求
收到bye:BYE sip:sipsoft@172.16.7.85:8888 SIP/2.0
Via: SIP/2.0/UDP 172.16.10.51:5060;rport=5060;branch=z9hG4bK-524287-1---e74c8841515e606c;received=172.16.10.51
Max-Forwards: 70
Contact: <sip:test@172.16.10.51:5060>
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=d94e4440
From: <sip:test@172.16.10.51>;tag=61880555
Call-ID: d1FfqZ_j708LZiRjUJ1UmQ..
CSeq: 2 BYE
User-Agent: xt_sip/1.0
Content-Length: 0
轉(zhuǎn)發(fā)bye:BYE sip:YPSQ06720040@172.16.10.190:5060 SIP/2.0
Via: SIP/2.0/UDP 172.16.7.85:8888;branch=z9hG4bKe1d85d1b6a6f94dc79e959145437ad8f
CSeq: 2 BYE
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=d94e4440
From: <sip:test@172.16.10.51>;tag=61880555
Call-ID: d1FfqZ_j708LZiRjUJ1UmQ..
Session-Expires: 1800;refresher=uas
Min-SE: 90
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,UPDATE,REGISTER,INFO,MESSAGE
Supported: resource-priority,timer
User-Agent: xt_sip/1.0
Max-Forwards: 70
Content-Length: 0
收到200OK
收到的200OK:SIP/2.0 200 OK
Via: SIP/2.0/UDP 172.16.7.85:8888;branch=z9hG4bKe1d85d1b6a6f94dc79e959145437ad8f
Contact: <sip:YPSQ06720040@172.16.10.190:5060>
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=d94e4440
From: <sip:test@172.16.10.51>;tag=61880555
Call-ID: d1FfqZ_j708LZiRjUJ1UmQ..
CSeq: 2 BYE
User-Agent: xt_sip/1.0
Content-Length: 0
發(fā)送回復(fù)200OK :SIP/2.0 200 OK
Via: SIP/2.0/UDP 172.16.10.51:5060;rport=5060;branch=z9hG4bK-524287-1---a2b8d8182899f615;received=172.16.10.51
From: <sip:test@172.16.10.51>;tag=61880555
Call-ID: d1FfqZ_j708LZiRjUJ1UmQ..
CSeq: 1 INVITE
Contact: <sip:sipsoft@172.16.7.85:8888>;expires=3600
To: <sip:YPSQ06720040@172.16.7.85:8888>;tag=d94e4440
Content-Length: 0
實(shí)現(xiàn)SipListener接口,主要有processRequest與processResponse需要實(shí)現(xiàn),processRequest主要處理的是Request請(qǐng)求,processResponse主要處理的是Response請(qǐng)求,init主要對(duì)Sip進(jìn)行初始化
package org.jivesoftware.openfire.sip;
import java.util.Hashtable;
import java.util.Properties;
import javax.sip.*;
import javax.sip.address.AddressFactory;
import javax.sip.address.URI;
import javax.sip.header.HeaderFactory;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
public class SipManagerimplements SipListener {
public static Hashtable<String, URI>allUsers = new Hashtable<String, URI>();
public static StringipAddr = "172.16.7.85";
public static int port = 8888;
public static SipStacksipStack = null;
public static AddressFactoryaddressFactory = null;
public static MessageFactorymsgFactory = null;
public static HeaderFactoryheaderFactory = null;
public static SipProvidersipProvider = null;
//以下三個(gè)變量需要根據(jù)Call-ID進(jìn)行統(tǒng)一匹配管理
public static ServerTransactionserverTransactionId = null;
public static DialogcallerDialog = null;
public static DialogcalleeDialog = null;
private void init() {
SipFactory sipFactory = null;
sipFactory = SipFactory.getInstance();
if (null == sipFactory) {
System.out.println("init sipFactory is null.");
return;
}
sipFactory.setPathName("gov.nist");
Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME","sipphone");
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL","32");
properties.setProperty("gov.nist.javax.sip.DEBUG_LOG",
"sipphonedebug.txt");
properties.setProperty("gov.nist.javax.sip.SERVER_LOG",
"sipphonelog.txt");
try {
sipStack = sipFactory.createSipStack(properties);
} catch (PeerUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
try {
headerFactory = sipFactory.createHeaderFactory();
addressFactory = sipFactory.createAddressFactory();
msgFactory = sipFactory.createMessageFactory();
ListeningPoint udp = sipStack.createListeningPoint(ipAddr,
port, "udp");
//ListeningPoint tcp = sipStack.createListeningPoint(ipAddr,
//port, "tcp");
SipManager listener = this;
sipProvider = sipStack.createSipProvider(udp);
System.out.println("udp provider " +sipProvider.toString());
sipProvider.addSipListener(listener);
//sipProvider = sipStack.createSipProvider(tcp);
//System.out.println("tcp provider " + sipProvider.toString());
sipProvider.addSipListener(listener);
//
} catch (Exception ex) {
ex.printStackTrace();
return;
}
}
public static void main(String[] args) {
new SipManager().init();
}
@Override
public void processDialogTerminated(DialogTerminatedEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void processIOException(IOExceptionEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void processRequest(RequestEvent arg0) {
// TODO Auto-generated method stub
Request request = arg0.getRequest();
if (null == request) {
System.out.println("processRequest request is null.");
return;
}
if (Request.INVITE.equals(request.getMethod())) {
System.out.println("收到呼叫請(qǐng)求");
SipInvite.invite(request, arg0);
} else if (Request.REGISTER.equals(request.getMethod())) {
System.out.println("注冊(cè)請(qǐng)求");
SipRegister.register(request, arg0);
} else if (Request.SUBSCRIBE.equals(request.getMethod())) {
} else if (Request.ACK.equalsIgnoreCase(request.getMethod())) {
System.out.println("ACK請(qǐng)求");
SipAck.ack(request, arg0);
} else if (Request.BYE.equalsIgnoreCase(request.getMethod())) {
System.out.println("Bye請(qǐng)求");
SipBye.bye(request, arg0);
} else if (Request.CANCEL.equalsIgnoreCase(request.getMethod())) {
} else if (Request.OPTIONS.equalsIgnoreCase(request.getMethod())) {
System.out.println("收到心跳檢測(cè)");
SipOption.option(request, arg0);
} else if (Request.SUBSCRIBE.equalsIgnoreCase(request.getMethod())) {
System.out.println("收到訂閱信息");
} else {
System.out.println("no support the method!");
}
}
@Override
public void processResponse(ResponseEvent arg0) {
// TODO Auto-generated method stub
Response response = arg0.getResponse();
if (response.getStatusCode() == Response.RINGING) {
System.out.println("收到Ringing");
SipResponseRing.ring(response, arg0);
} else if (response.getStatusCode() == Response.OK) {
System.out.println("收到200OK");
SipResponseOK.ok(response, arg0);
}
}
@Override
public void processTimeout(TimeoutEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void processTransactionTerminated(TransactionTerminatedEvent arg0) {
// TODO Auto-generated method stub
}
}
Register功能主要是將Sip客戶端的信息進(jìn)行統(tǒng)一管理,在該代碼實(shí)現(xiàn)處則是將用戶的唯一標(biāo)識(shí)與URI進(jìn)映射,同時(shí)對(duì)于注冊(cè)的用戶都回復(fù)200OK。
package org.jivesoftware.openfire.sip;
import java.text.ParseException;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.address.Address;
import javax.sip.address.URI;
import javax.sip.header.ContactHeader;
import javax.sip.header.ToHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
public class SipRegister
{
public static void register(Request request, RequestEvent requestEvent)
{
if (null == request) {
System.out.println("processInvite request is null.");
return;
}
System.out.println("注冊(cè)信息 = " + request.toString());
ServerTransaction serverTransactionId = requestEvent
.getServerTransaction();
try {
Response response = null;
ToHeader head = (ToHeader) request.getHeader(ToHeader.NAME);
Address toAddress = head.getAddress();
URI toURI = toAddress.getURI();
ContactHeader contactHeader = (ContactHeader) request
.getHeader("Contact");
Address contactAddr = contactHeader.getAddress();
URI contactURI = contactAddr.getURI();
int expires = request.getExpires().getExpires();
// ???expires??????0,??????????????
System.out.println("-------contactURI------" + contactURI);
String contact = Util.getContact(contactURI);
if (expires != 0 || contactHeader.getExpires() != 0) {
if (contact != null && contact.length() > 0) {
System.out.println("注冊(cè) 成功" + contact);
SipManager.allUsers.put(contact, contactURI);
}
} else {
if (contact != null && contact.length() > 0) {
System.out.println("注銷 成功" + contact);
SipManager.allUsers.remove(toURI);
}
}
response = SipManager.msgFactory.createResponse(200, request);
System.out.println("回復(fù)200OK : " + response.toString());
if (serverTransactionId == null) {
serverTransactionId = SipManager.sipProvider
.getNewServerTransaction(request);
serverTransactionId.sendResponse(response);
} else {
System.out
.println("processRequest serverTransactionId is null.");
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package org.jivesoftware.openfire.sip;
import gov.nist.javax.sip.header.Via;
import java.text.ParseException;
import javax.sip.ClientTransaction;
import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.TransactionUnavailableException;
import javax.sip.address.Address;
import javax.sip.address.URI;
import javax.sip.header.ContactHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
public class SipInvite
{
public static void invite(Request request, RequestEvent requestEvent)
{
System.out.println("收到的呼叫請(qǐng)求:" + request.toString());
ClientTransaction clientTransactionId = null;
if (null == request) {
System.out.println("processInvite request is null.");
return;
}
try {
SipManager.serverTransactionId = requestEvent.getServerTransaction();
if (SipManager.serverTransactionId ==null) {
SipManager.serverTransactionId = SipManager.sipProvider
.getNewServerTransaction(request);
SipManager.callerDialog = SipManager.serverTransactionId.getDialog();
Response response = SipManager.msgFactory.createResponse(Response.TRYING,
request);
SipManager.serverTransactionId.sendResponse(response);
}
URI contactURI = request.getRequestURI();
String contact = Util.getContact(contactURI);
if (contact == null) {
return ;
}
contactURI = SipManager.allUsers.get(contact);
System.out.println("contact = " + contactURI);
Request cliReq = SipManager.msgFactory.createRequest(request.toString());
cliReq.setRequestURI(contactURI);
Via callerVia = (Via) request.getHeader(Via.NAME);
Via via = (Via) SipManager.headerFactory.createViaHeader(SipManager.ipAddr, SipManager.port,"UDP",
callerVia.getBranch() + "sipphone");
cliReq.removeHeader(Via.NAME);
cliReq.addHeader(via);
// ????contact????
ContactHeader contactHeader = SipManager.headerFactory.createContactHeader();
Address address = SipManager.addressFactory.createAddress("sip:sipsoft@"
+ SipManager.ipAddr + ":" + SipManager.port);
contactHeader.setAddress(address);
contactHeader.setExpires(3600);
cliReq.setHeader(contactHeader);
clientTransactionId = SipManager.sipProvider.getNewClientTransaction(cliReq);
clientTransactionId.sendRequest();
System.out.println("轉(zhuǎn)發(fā)呼叫請(qǐng)求:" + cliReq);
} catch (TransactionUnavailableException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package org.jivesoftware.openfire.sip;
import gov.nist.javax.sip.header.ContentLength;
import gov.nist.javax.sip.header.ContentType;
import java.text.ParseException;
import javax.sip.ClientTransaction;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
import javax.sip.SipException;
import javax.sip.address.Address;
import javax.sip.header.ContactHeader;
import javax.sip.header.ToHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
public class SipResponseRing {
public static void ring(Response response, ResponseEvent arg0) {
System.out.println("收到的ring:" + response.toString());
try {
ClientTransaction clientTran = (ClientTransaction) arg0
.getClientTransaction();
if (Request.INVITE.equalsIgnoreCase(clientTran.getRequest()
.getMethod())) {
int statusCode = response.getStatusCode();
Response callerResp = null;
callerResp = SipManager.msgFactory.createResponse(statusCode,
SipManager.serverTransactionId.getRequest());
// 更新contact頭域值,因?yàn)楹竺娴南⑹歉鶕?jù)該URI來路由的
ContactHeader contactHeader = SipManager.headerFactory
.createContactHeader();
Address address = SipManager.addressFactory.createAddress("sip:sipsoft@"
+ SipManager.ipAddr + ":" + SipManager.port);
contactHeader.setAddress(address);
contactHeader.setExpires(3600);
callerResp.addHeader(contactHeader);
// 拷貝to頭域
ToHeader toHeader = (ToHeader) response
.getHeader(ToHeader.NAME);
callerResp.setHeader(toHeader);
// 拷貝相應(yīng)的消息體
ContentLength contentLen = (ContentLength) response
.getContentLength();
if (contentLen != null && contentLen.getContentLength() != 0) {
ContentType contentType = (ContentType) response
.getHeader(ContentType.NAME);
System.out.println("the sdp contenttype is " + contentType);
callerResp.setContentLength(contentLen);
// callerResp.addHeader(contentType);
callerResp.setContent(response.getContent(), contentType);
} else {
System.out.println("sdp is null.");
}
if (SipManager.serverTransactionId != null) {
SipManager.callerDialog = SipManager.serverTransactionId.getDialog();
SipManager.calleeDialog = clientTran.getDialog();
SipManager.serverTransactionId.sendResponse(callerResp);
} else {
System.out.println("serverTransactionId is null.");
}
System.out.println("發(fā)送回復(fù)ring : " + callerResp.toString());
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
package org.jivesoftware.openfire.sip;
import gov.nist.javax.sip.header.ContentLength;
import gov.nist.javax.sip.header.ContentType;
import java.text.ParseException;
import javax.sip.ClientTransaction;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
import javax.sip.SipException;
import javax.sip.address.Address;
import javax.sip.header.ContactHeader;
import javax.sip.header.ToHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
public class SipResponseOK {
public static void ok(Response response, ResponseEvent arg0) {
try {
System.out.println("收到的200OK:" + response.toString());
ClientTransaction clientTran = (ClientTransaction) arg0
.getClientTransaction();
if (Request.INVITE.equalsIgnoreCase(clientTran.getRequest()
.getMethod()) ||Request.BYE.equalsIgnoreCase(clientTran.getRequest()
.getMethod()) ) {
int statusCode = response.getStatusCode();
Response callerResp = null;
callerResp = SipManager.msgFactory.createResponse(statusCode,
SipManager.serverTransactionId.getRequest());
// 更新contact頭域值,因?yàn)楹竺娴南⑹歉鶕?jù)該URI來路由的
ContactHeader contactHeader = SipManager.headerFactory
.createContactHeader();
Address address = SipManager.addressFactory.createAddress("sip:sipsoft@"
+ SipManager.ipAddr + ":" + SipManager.port);
contactHeader.setAddress(address);
contactHeader.setExpires(3600);
callerResp.addHeader(contactHeader);
// 拷貝to頭域
ToHeader toHeader = (ToHeader) response
.getHeader(ToHeader.NAME);
callerResp.setHeader(toHeader);
// 拷貝相應(yīng)的消息體
ContentLength contentLen = (ContentLength) response
.getContentLength();
if (contentLen != null && contentLen.getContentLength() != 0) {
ContentType contentType = (ContentType) response
.getHeader(ContentType.NAME);
System.out.println("the sdp contenttype is " + contentType);
callerResp.setContentLength(contentLen);
// callerResp.addHeader(contentType);
callerResp.setContent(response.getContent(), contentType);
} else {
System.out.println("sdp is null.");
}
if (SipManager.serverTransactionId != null) {
SipManager.callerDialog = SipManager.serverTransactionId.getDialog();
SipManager.calleeDialog = clientTran.getDialog();
SipManager.serverTransactionId.sendResponse(callerResp);
} else {
System.out.println("serverTransactionId is null.");
}
System.out.println("發(fā)送回復(fù)200OK : " + callerResp.toString());
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
package org.jivesoftware.openfire.sip;
import gov.nist.javax.sip.header.CSeq;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.message.Request;
public class SipAck {
public static void ack(Request request, RequestEvent requestEvent) {
if (null == request) {
System.out.println("processAck request is null.");
return;
}
System.out.println("收到的ACK:" + request.toString());
try {
Request ackRequest = null;
CSeq csReq = (CSeq) request.getHeader(CSeq.NAME);
ackRequest = SipManager.calleeDialog.createAck(csReq.getSeqNumber());
SipManager.calleeDialog.sendAck(ackRequest);
System.out.println("回復(fù)ACK:" + ackRequest.toString());
} catch (SipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package org.jivesoftware.openfire.sip;
import java.text.ParseException;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.address.Address;
import javax.sip.header.ContactHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
public class SipOption
{
public static void option(Request request, RequestEvent requestEvent)
{
if (null == request) {
System.out.println("processInvite request is null.");
return;
}
System.out.println("心跳信息 = " + request.toString());
ServerTransaction serverTransactionId = requestEvent
.getServerTransaction();
System.out.println("serverTransactionId = " + serverTransactionId);
try {
Response response = null;
response = SipManager.msgFactory.createResponse(200, request);
ContactHeader contactHeader = SipManager.headerFactory.createContactHeader();
Address address = SipManager.addressFactory.createAddress("sip:sipsoft@"
+ SipManager.ipAddr + ":" + SipManager.port);
contactHeader.setAddress(address);
response.setHeader(contactHeader);
if (serverTransactionId == null) {
serverTransactionId = SipManager.sipProvider
.getNewServerTransaction(request);
serverTransactionId.sendResponse(response);
} else {
System.out
.println("processRequest serverTransactionId is null.");
}
System.out.println("回復(fù)Option200OK : " + response.toString());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package org.jivesoftware.openfire.sip;
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.message.Request;
public class SipBye
{
public static void bye(Request request, RequestEvent requestEvent) {
if (null == request ||null == requestEvent) {
System.out.println("processBye request is null.");
return;
}
System.out.println("收到bye:" + request.toString());
Request byeReq = null;
Dialog dialog = requestEvent.getDialog();
System.out.println("calleeDialog : " + SipManager.calleeDialog);
System.out.println("callerDialog : " + SipManager.callerDialog);
try {
if (dialog.equals(SipManager.calleeDialog)) {
byeReq = SipManager.callerDialog.createRequest(request.getMethod());
ClientTransaction clientTran = SipManager.sipProvider
.getNewClientTransaction(byeReq);
SipManager.callerDialog.sendRequest(clientTran);
SipManager.calleeDialog.setApplicationData(requestEvent
.getServerTransaction());
} else if (dialog.equals(SipManager.callerDialog)) {
byeReq = SipManager.calleeDialog.createRequest(request.getMethod());
ClientTransaction clientTran = SipManager.sipProvider
.getNewClientTransaction(byeReq);
SipManager.calleeDialog.sendRequest(clientTran);
SipManager.callerDialog.setApplicationData(requestEvent
.getServerTransaction());
} else {
System.out.println("");
}
System.out.println("轉(zhuǎn)發(fā)bye:" +byeReq.toString());
} catch (SipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package org.jivesoftware.openfire.sip;
import javax.sip.address.URI;
public class Util {
public static String getContact(URI uri) {
if (uri != null) {
String contact = uri.toString().split(":")[1].split("@")[0];
if (contact != null && contact.length() > 0) {
return contact;
}
return null;
}
return null;
}
}
Openfire插件編寫過程可以按照本人之前博客介紹
聯(lián)系客服