📄 sipclient.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 SipClient * * SipClient is master class responsible for sending and receiving SIP * messages. * * SipClient hosts two main lists: a list of active SIP calls * (SipCall), and a list of users of this class (SipUser). It is also * responsible for the Contact URI in all messages. * * 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.io.*;import java.util.*;import java.net.InetAddress;import java.net.UnknownHostException;import org.mitre.jsip.event.*;import org.mitre.jsip.proxy.*;public class SipClient extends Object{ public static SipClient getSipClient() { if ( _instance == null ) _instance = new SipClient(); return _instance; } /** * Creates a new SIP client with the specified explicit proxy. This * starts up the client listening on a UDP port. By default, it tries * to listen on port 5060, or whatever is specified in the sip.dissipate.port * environment variable. */ protected SipClient ( ) { setupSocketStuff(); setupContactUri(); // Keep a log file, please try { loggerfd = new PrintWriter( new FileOutputStream( new File("jsip.log") ) ); } catch (FileNotFoundException fnfe) { System.err.println("error opening log file: " + fnfe ); System.exit( 1 ); } useproxy = false; proxyport = 5060; fwmode = false; busymode = false; defusermode = false; defuser = null; hidemode = DontHideVia; maxforwards = 0; } /** * This call does the select on all the client's listening sockets and * performs any pending actions. It should be called in some main loop * somewhere. --- NOT USED!!! * * @param block */ public void timerTask() { Date timeout; // fd_set read_fds; int read_fds; int highest_fd; // auditPending(); } /** * Returns the full contact URI for this client. This is placed in all * outgoing messages (except for when clearing registrations). * * @return SipUri */ public SipUri getContactUri() { return contacturi; } /** * Turn on default user mode. If incoming calls arrive at this client * and there is no associated user matching the To line in the request, * the default user will be used. * * Dissipate always uses a common contact URI for all registrations. * This means that all incoming requests should have a request URI * matching that of the announced Contact URI. So, in order to check * for a matching user, we match on the To header. * * When default user mode is off and a message is received when there * is no user associated, the call is rejected with a 404 Not Found. * * @param onoff */ public void setDefaultUserMode(boolean onoff) { defusermode = onoff; } /** * Returns true if we accept calls with a default user * * @return bool */ public boolean getDefaultUserMode() { return defusermode; } /** * Returns the current default user. * * @return SipUser * */ public SipUser getDefaultUser() { return defuser; } /** * Sets the current default user. * * @param user */ public void setDefaultUser(SipUser user) { defuser = user; if( !users.contains( user ) ) { users.add( user ); } } /** * Sets the URI to forward calls to if call forwarding is enabled. * * @param u */ public void setCallForwardUri(SipUri u) { forwarduri = u; } /** * Returns the URI we are currently forwarding to. * * @return SipUri & */ public SipUri getCallForwardUri() { return forwarduri; } /** * Turns of or off call forwarding. * * @param onoff */ public void setCallForward(boolean onoff) { fwmode = onoff; } /** * Returns the current state of call forwarding. * * @return bool */ public boolean getCallForward() { return fwmode; } /** * Allows the user to set a message to be displayed when a client is * forwarded. * * @param newmessage */ public void setCallForwardMessage(String newmessage) { fwbody = newmessage; } /** * Returns our current forward message. * * @return String */ public String getCallForwardMessage() { return fwbody; } /** * Turns of or off busy mode. * * @param onoff */ public void setBusy(boolean onoff) { busymode = onoff; } /** * Returns the current state of busy mode. * * @return bool */ public boolean getBusy() { return busymode; } /** * Allows the user to set a message to be displayed when the client * discovers we are busy. * * @param newmessage */ public void setBusyMessage(String newmessage) { busybody = newmessage; } /** * Returns our current busy message. * * @return String */ public String getBusyMessage() { return busybody; } /** * Turn on explicit proxying. When SipClient is acting in explicit * proxy mode, all outgoing SIP messages will be sent to the proxy * specified, regardless of what the Via dictates. * * @param eproxy */ public void setExplicitProxyMode(boolean eproxy) { useproxy = eproxy; } /** * Returns true if we are currently sending outgoing requests to the * explicit proxy. * * @return bool */ public boolean getExplicitProxyMode() { return useproxy; } /** * Specify the explicit proxy address for this client. Address is in * the format address[:port], defaulting to 5060 if the port is not * specified. * * @param newproxy */ public void setExplicitProxyAddress(String newproxy) { if( newproxy.indexOf( ':' ) >= 0 ) { proxy = newproxy.substring( 0, newproxy.indexOf( ':' ) - 1); String pport = newproxy.substring( newproxy.indexOf( ':' ) + 1 ); try { proxyport = Integer.parseInt(pport); } catch (NumberFormatException nfe) { System.err.println("Error setting proxy port. Set to default (5060)"); proxyport = 5060; } } else { proxy = newproxy; proxyport = 5060; } } /** * Sets our current max forwards. * * @param newmax */ public void setMaxForwards(int newmax) { maxforwards = newmax; } /** * Returns our current max forwards. * * @return int */ public int getMaxForwards() { return maxforwards; } /** * Returns the explicit proxy for this client, in the same format as * above. * * @return String & */ public String getExplicitProxyAddress() { return proxy; } /** * Set Via hiding mode. * * @param newmode */ public void setHideViaMode(int newmode) { hidemode = newmode; } /** * Returns the current Via hiding mode. * * @return HideViaMode */ public int getHideViaMode() { return hidemode; } /** * Returns an iterator to teh list of active SIP calls. * * @return SipCallIterator */ public ArrayList getCallList() { return calls; } /** * Returns an iterator to the list of users of this client. * * @return SipUserIterator */ public ArrayList getUserList() { return users; } /** * Returns our User-Agent string (library version) * * @return String */ public String getUserAgent() { return "jSIP/0.0.1"; } /** * Initiated when a new SIP call is created from an incoming message. */ // *** LOOK AT *** - signal public void incomingCall(SipCall call, SipCallMember member) {} /** * An external trigger for checking incoming messages */ public void incomingMessage() { while ( haveMessages() ) { incomingMessage( mQueue.getQueueMessage() ); } } /** * Triggered when a call is deleted or added to the internal list of * calls, or when a call has its type changed. */ // *** LOOK AT *** - signal public void callListUpdated() {} /** * Method for adding CallEvent listeners */ public synchronized void addCallListener( CallListener cl ) { callListener = CallEventMulticaster.add( callListener, cl ); } /** * Method for removing CallEvent listeners */ public synchronized void removeCallListener( CallListener cl ) { callListener = CallEventMulticaster.remove( callListener, cl ); } /** * Method for accessing the CallListener */ public CallListener getCallListener() { return callListener; } /** * auditPending -- moved this to the SipTransaction itself * private void auditPending() { SipCall curcall = null; SipTransaction curtrans = null; for( ListIterator li = calls.listIterator(); li.hasNext(); ) { curcall = (SipCall)li.next(); ArrayList translist = curcall.getTransactionList(); for( ListIterator lit = translist.listIterator(); lit.hasNext(); ) { curtrans = (SipTransaction)lit.next(); curtrans.auditPending(); } } } */ /** * setupSocketStuff */ private void setupSocketStuff() { int listenport = 5060; listener = MessageSocketFactory.getMessageSocket( MessageSocket.UDP ); // listenport = String::fromUtf8( getenv( "DISSIPATE_PORT" ) ).toUInt(); try { String sport = System.getProperty("sip.dissipate.port"); listenport = Integer.parseInt(sport); } catch (NumberFormatException nfe) { System.err.println("Property sip.dissipate.port not defined; setting to default (5060)"); } listener.connect( (String)null, listenport ); // make sure we have queue to pass to listener mQueue = new MessageQueue( "Sip Message Queue" ); listener.listen( mQueue ); //listener.forcePortNumber( listenport ); if (SipClient.DEBUG) System.out.println( "SipClient: Listening on port: " + listener.getPortNumber() ); if (SipClient.DEBUG) System.out.println( "SipClient: Our address: " + Sip.getLocalAddress() ); } /** * setupContactUri */ private void setupContactUri() { String username; String fullname; username = System.getProperty("user.name", "Unknown"); fullname = System.getProperty("sip.dissipate.fullname", null); // fullname = String::fromUtf8( pwent.pw_gecos ); if ( contacturi == null ) contacturi = new SipUri(); contacturi.setFullname( fullname ); contacturi.setUsername( username ); contacturi.setHostname( Sip.getLocalAddress() ); contacturi.setPortNumber( listener.getPortNumber() ); } /** * incomingMessage */ private void incomingMessage( SipMessage curmessage ) { // Announce that we got the message if (SipClient.DEBUG) System.out.println( "SipClient: Received: \n" + curmessage.message() ); String logmessage = ""; logmessage += ": Parsed message:\n" + curmessage.message() + "\n: End parsed message\n"; loggerfd.print(logmessage); // Grab CallId from message String callid = curmessage.getHeaderData( SipHeader.Call_ID ); if ( callid == null ) return; // catch for sipd // Grab address in To: header SipUri touri = new SipUri( curmessage.getHeaderData( SipHeader.To ) ); // If the CallId exists already, pass the message to that call for( ListIterator li = calls.listIterator(); li.hasNext(); ) { SipCall curcall = (SipCall)li.next(); if( callid.equals( curcall.getCallId() ) ) { if( ( curmessage.getType() == SipMessage.Request ) && touri.hasTag() ) { String toTag = touri.getTag(); if( ( toTag != null ) && ( toTag.compareTo( curcall.localAddress().getTag() ) != 0 ) ) { if( curmessage.getMethod() != Sip.ACK && curmessage.getMethod() != Sip.CANCEL ) { sendQuickResponse( curmessage, new SipStatus( 481 ) ); return; } else { if (SipClient.DEBUG) System.out.println( "SipClient: Dropping ACK/CANCEL which deserved a 481" ); } // return; } } curcall.incomingMessage( curmessage ); return; } } // Check message type // Need to do this now... looks like this is an error in the testing software if( curmessage.getType() == Sip.OPTIONS ) { touri.setTag(null); } if( curmessage.getType() != SipMessage.Request ) { System.out.println( "SipClient: No call found for incoming response. Dropping." ); return; } // Check method if( curmessage.getMethod() == Sip.ACK ) { System.out.println( "SipClient: ACK received, but nobody was listening. Dropping." ); return; } if( curmessage.getMethod() == Sip.CANCEL ) { System.out.println( "SipClient: No listener for this CANCEL, returning a 481." ); sendQuickResponse( curmessage, new SipStatus( 481 ) ); } // if( touri.hasTag() ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -