📄 sipcall.java
字号:
/* * This file was derived from libdissipate, an open source SIP library. The original file * was modified on 1/23/2001. Please see * http://www.div8.net/dissipate for more information. * * Copyright (c) 2000 Billy Biggs <bbiggs@div8.net> * * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * *//** * class SipCall * * A classfor referencing a specific SIP call. * * This code has been generated using C2J++ * C2J++ is based on Chris Laffra's C2J (laffra@watson.ibm.com) * Read general disclaimer distributed with C2J++ before using this code * For information about C2J++, send mail to Ilya_Tilevich@ibi.com */package org.mitre.jsip;import java.util.ArrayList;import java.util.ListIterator;import java.util.Date;import java.util.Random;public class SipCall extends Object{ /** * Creates a new call for a given SipUser */ public SipCall( SipUser local, String id ) { this( local, id, UnknownCall ); } public SipCall( SipUser local, String id, int ctype ) { callstatus = Unconnected; if ( id == null ) { callid = SipMessage.createCallId(); } else { callid = id; } // Remember to nuke all members and transactions members = new ArrayList(); transactions = new ArrayList(); Date tv = new Date(); Random rand = new Random(tv.getTime()); lastseq = rand.nextInt( 8000 ); parent = local.parent(); calltype = ctype; hasroute = false; localuri = local.getUri(); localuri.generateTag(); parent.addCall( this ); } /** * getCallStatus * @return CallStatus */ public int getCallStatus() { return callstatus; } /** * @return CallType */ public int getCallType() { return calltype; } /** * setCallType * @param newtype */ public void setCallType(int newtype) { calltype = newtype; parent.callTypeUpdated(); } /** * Returns the local URI that we are known by for this call. * If there is none, returns the URI of our client parent. * @return SipUri & */ public SipUri localAddress() { return localuri; } /** * Returns the associated call ID * @return String & */ public String getCallId() { return callid; } /** * Tries to find a SipCallMember for the given URI. * * @param uri * @return SipCallMember* */ public SipCallMember getMember(SipUri uri) { SipCallMember scm; for (ListIterator li = members.listIterator(); li.hasNext(); ) { scm = (SipCallMember)li.next(); if ( uri.equals( scm.getUri() ) ) { return scm; } } return null; } /** * Returns the subject for this call. * * @return String */ public String getSubject() { return subject; } /** * Set the subject for this call. Will be used on all outgoing INVITEs sent afterwards. * * @param newsubject */ public void setSubject(String newsubject) { subject = newsubject; subjectChanged(); } /** * getTransactionList * @return Tranlist */ public ArrayList getTransactionList() { return transactions; } /** * Sends a SIP request under this call to the given call member. * Returns a SipTransaction for tracking */ public SipTransaction newRequest( SipCallMember member, int meth, String body, MimeContentType bodytype ) { return newRequest( member, meth, body, bodytype, null ); } public SipTransaction newRequest( SipCallMember member, int meth, String body, MimeContentType bodytype, SipUri transferto ) { SipTransaction trans = new SipTransaction( lastseq++, member, this ); transactions.add( trans ); // Send the request trans.sendRequest( meth, body, bodytype, transferto ); // Audit the call auditCall(); // Return the transaction object for tracking return trans; } /** * Sends a SIP register under this call to the given call member. * Returns a SipTransaction for tracking. */ public SipTransaction newRegister( SipUri registerserver, boolean clear ) { return newRegister( registerserver, clear, null, null, null, null ); } public SipTransaction newRegister( SipUri registerserver, boolean clear, String authentication, String proxyauthentication, String body, MimeContentType bodytype ) { localuri.setTag( null ); SipTransaction trans = new SipTransaction( lastseq++, new SipCallMember( this, localuri ), this ); transactions.add( trans ); trans.sendRegister( registerserver, clear, authentication, proxyauthentication, body, bodytype ); return trans; } /** * Returns an iterator for the list of all current members of this call. * * @return SipCallMemberIterator */ public ArrayList getMemberList() { return members; } /** * Triggered whenever the call status changes. */ public void callStatusUpdated() {} /** * Triggered whenever the call subject changes. */ public void subjectChanged() {} /** * auditCall */ private void auditCall() { boolean foundmemb = false; // If there are no active call members, set the call status to 'Dead' for( ListIterator li = members.listIterator(); li.hasNext(); ) { SipCallMember memb = (SipCallMember)li.next(); if( ( memb.getStatus() != SipCallMember.Disconnecting ) && ( memb.getStatus() != SipCallMember.Disconnected ) ) { foundmemb = true; } } if( !foundmemb ) { callstatus = Dead; callStatusUpdated(); } } /** * incomingRequest * @param message * @return SipCallMember* */ private SipCallMember incomingRequest(SipMessage message) { SipUri incominguri = new SipUri( message.getHeaderData( SipHeader.From ) ); String cseq = message.getHeaderData( SipHeader.CSeq ); String snum = cseq.substring( 0, cseq.indexOf(" ") ); int seqnum = 0; SipTransaction curtrans = null; try { seqnum = Integer.parseInt(snum); } catch (NumberFormatException nfe) { System.err.println("Error parsing sequence number: [" + snum + "]. set to 0"); } if (SipClient.DEBUG) System.out.println( "SipCall: Incoming request" ); // check first to see if we've already received this message for( ListIterator li = transactions.listIterator(); li.hasNext(); ) { curtrans = (SipTransaction)li.next(); if( ( incominguri.equals( curtrans.getCallMember().getUri() ) ) && ( seqnum == curtrans.getSeqNum() ) && ( curtrans.getDirection() == SipTransaction.RemoteRequest ) ) { if (SipClient.DEBUG) System.out.println( "SipCall: Request is a retransmission, ignoring" ); return null; } } // Update our identity if necessary SipUri touri = new SipUri( message.getHeaderData( SipHeader.To ) ); if( touri != localuri ) { localuri = touri; if( !localuri.hasTag() ) { localuri.generateTag(); } } if( ( message.getMethod() == Sip.ACK ) || ( message.getMethod() == Sip.CANCEL ) ) { for ( ListIterator transli = transactions.listIterator(); transli.hasNext(); ) { curtrans = (SipTransaction)transli.next(); if (SipClient.DEBUG) System.out.println("Found transaction with CSeq of " + curtrans.getCSeq() ); if( ( incominguri.equals( curtrans.getCallMember().getUri() ) ) && ( seqnum == curtrans.getSeqNum() ) && ( curtrans.getDirection() == SipTransaction.RemoteRequest ) ) { curtrans.incomingRequest( message ); return null; } } if (SipClient.DEBUG) System.out.println( "SipCall: ACK/CANCEL recieved, but no matching transaction found\n" ); return null; } // took dup check out here // Find or create a member for this request SipCallMember member = getMember( incominguri ); if ( member == null ) { member = new SipCallMember( this, incominguri ); } // Update the Contact for this member if( message.getContactList().getListLength() > 0 ) { member.setContactUri( message.getContactList().getHead() ); } // Update the route if( message.getRecordRoute().getListLength() > 0 ) { hasrecordroute = true; recordroute = message.getRecordRoute(); hasroute = true; route = recordroute; route.addToEnd( member.getContactUri() ); } // Create a new transaction and process it if (SipClient.DEBUG) System.out.println( "SipCall: New transaction created" ); SipTransaction transaction = new SipTransaction( seqnum, member, this ); transactions.add( transaction ); transaction.incomingRequest( message ); // Update member status based on this transaction member.incomingTransaction( transaction ); return member; } /** * incomingResponse * @param message */ private void incomingResponse(SipMessage message) { SipUri incominguri = new SipUri( message.getHeaderData( SipHeader.To ) ); // *** LOOK AT *** message.getRequestUri? String cseq = message.getHeaderData( SipHeader.CSeq ); String snum = cseq.substring( 0, cseq.indexOf(" ") ); int seqnum = 0; try { seqnum = Integer.parseInt(snum); } catch (NumberFormatException nfe) { System.err.println("Error parsing sequence number. set to 0"); } if (SipClient.DEBUG) System.out.println( "SipCall: Incoming response" ); SipTransaction curtrans; for ( ListIterator li = transactions.listIterator(); li.hasNext(); ) { curtrans = (SipTransaction)li.next(); if ( ( incominguri.equals( curtrans.getCallMember().getUri() ) ) && ( seqnum == curtrans.getSeqNum() ) && ( curtrans.getDirection() == SipTransaction.LocalRequest ) ) { SipCallMember member = getMember( incominguri ); if( member == null ) { System.out.println( "SipCall: Billy, you really messed something up\n" ); } else if( message.getStatus().getCode() == 200 ) { if (SipClient.DEBUG) System.out.println( "SipCall: Checking for Contact and Record-Route\n" ); // Update the Contact for this member if( message.getContactList().getListLength() > 0 ) { if (SipClient.DEBUG) System.out.println( "SipCall: Setting Contact for this Call Member\n" ); member.setContactUri( message.getContactList().getHead() ); } // Update the route if( message.getRecordRoute().getListLength() > 0 ) { hasroute = true; route = message.getRecordRoute(); route.reverseList(); route.addToEnd( member.getContactUri() ); } } curtrans.incomingResponse( message ); return; } } if (SipClient.DEBUG) System.out.println( "SipCall: Response dropped: No transaction found\n" ); } /** * sendRequest * @param reqmsg * @param contact */ void sendRequest(SipMessage reqmsg) { sendRequest(reqmsg, true); } void sendRequest(SipMessage reqmsg, boolean contact) { if ( reqmsg.getMethod() == Sip.MESSAGE ) { // localuri.setProtocolName( "im" ); } reqmsg.insertHeader( SipHeader.From, localuri.nameAddr() ); reqmsg.insertHeader( SipHeader.Call_ID, callid ); if( ( reqmsg.getMethod() == Sip.INVITE ) || ( reqmsg.getMethod() == Sip.MESSAGE ) ) { reqmsg.insertHeader( SipHeader.Subject, getSubject() ); } if( hasroute ) { reqmsg.setRequestUri( route.getHead() ); SipUriList routewithouthead = route; routewithouthead.removeHead(); reqmsg.insertHeader( SipHeader.Route, routewithouthead.getUriList() ); } parent.sendRequest( reqmsg, contact ); } void sendResponse(SipMessage responsemsg) { sendResponse(responsemsg, true); } /** * sendResponse * @param responsemsg * @param contact */ private void sendResponse(SipMessage responsemsg, boolean contact) { responsemsg.insertHeader( SipHeader.Call_ID, callid ); responsemsg.insertHeader( SipHeader.To, localuri.nameAddr() ); if( hasrecordroute ) { responsemsg.setRecordRoute( recordroute ); } parent.sendResponse( responsemsg, contact ); } /** * sendRaw * @param msg */ void sendRaw(SipMessage msg) { parent.sendRaw( msg ); } /** * incomingMessage * @param message * @return SipCallMember* */ SipCallMember incomingMessage(SipMessage message) { if( message.getType() == SipMessage.Request ) { return incomingRequest( message ); } else if( message.getType() == SipMessage.Response ) { incomingResponse( message ); } else { if (SipClient.DEBUG) System.out.println( "SipCall: Incoming message dropped (bad message type)" ); } return null; } /** * addMember * @param newmember */ void addMember(SipCallMember newmember) { members.add( newmember ); } /** * statusUpdated - do this for now */ public static void statusUpdated() {} // class variables static final int StandardCall = 0; static final int OptionsCall = 1; static final int RegisterCall = 2; static final int MessageCall = 3; static final int BrokenCall = 4; static final int UnknownCall = 5; static final int Unconnected = 0; static final int InviteRequested = 1; static final int RequestingInvite = 2; static final int InProgress = 3; static final int Dead = 4; private SipClient parent; private SipUri localuri; private ArrayList members; private ArrayList transactions; private int lastremoteseq; private static int lastseq = 0; private int calltype; private int callstatus; private String callid; private String subject; private boolean hasrecordroute; private SipUriList recordroute; private boolean hasroute; private SipUriList route;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -