| /* |
| * Conditions Of Use |
| * |
| * This software was developed by employees of the National Institute of |
| * Standards and Technology (NIST), an agency of the Federal Government. |
| * Pursuant to title 15 Untied States Code Section 105, works of NIST |
| * employees are not subject to copyright protection in the United States |
| * and are considered to be in the public domain. As a result, a formal |
| * license is not needed to use the software. |
| * |
| * This software is provided by NIST as a service and is expressly |
| * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED |
| * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT |
| * AND DATA ACCURACY. NIST does not warrant or make any representations |
| * regarding the use of the software or the results thereof, including but |
| * not limited to the correctness, accuracy, reliability or usefulness of |
| * the software. |
| * |
| * Permission to use this software is contingent upon your acceptance |
| * of the terms of this agreement |
| * |
| * . |
| * |
| */ |
| package gov.nist.javax.sip.stack; |
| |
| import gov.nist.core.Host; |
| import gov.nist.core.HostPort; |
| import gov.nist.core.InternalErrorHandler; |
| import gov.nist.javax.sip.ListeningPointImpl; |
| import gov.nist.javax.sip.header.Via; |
| |
| import java.io.IOException; |
| import java.net.InetAddress; |
| import java.text.ParseException; |
| |
| import javax.sip.InvalidArgumentException; |
| |
| /** |
| * This is the Stack abstraction for the active object that waits for messages |
| * to appear on the wire and processes these messages by calling the |
| * MessageFactory interface to create a ServerRequest or ServerResponse object. |
| * The main job of the message processor is to instantiate message channels for |
| * the given transport. |
| * |
| * @version 1.2 $Revision: 1.18 $ $Date: 2009/10/16 22:58:41 $ |
| * |
| * @author M. Ranganathan <br/> |
| * |
| */ |
| public abstract class MessageProcessor implements Runnable { |
| /** |
| * A string containing the 0.0.0.0 IPv4 ANY address. |
| */ |
| protected static final String IN_ADDR_ANY = "0.0.0.0"; |
| |
| /** |
| * A string containing the ::0 IPv6 ANY address. |
| */ |
| protected static final String IN6_ADDR_ANY = "::0"; |
| /** |
| * My Sent by string ( which I use to set the outgoing via header) |
| */ |
| private String sentBy; |
| |
| private HostPort sentByHostPort; |
| |
| /* |
| * The IP Address that was originally assigned ( Can be ANY ) |
| */ |
| |
| private String savedIpAddress; |
| |
| /** |
| * The IP address where I am listening. |
| */ |
| private InetAddress ipAddress; |
| |
| /** |
| * The port where I am listening |
| */ |
| private int port; |
| |
| /** |
| * The transport where I am listening |
| */ |
| protected String transport; |
| |
| /** |
| * The Listening Point to which I am assigned. |
| */ |
| private ListeningPointImpl listeningPoint; |
| |
| private boolean sentBySet; |
| |
| /** |
| * Our stack (that created us). |
| */ |
| protected SIPTransactionStack sipStack; |
| |
| protected MessageProcessor( String transport ) { |
| this.transport = transport; |
| } |
| |
| /** |
| * Constructor |
| * |
| * @param ipAddress -- ip address where I am listening for incoming requests. |
| * @param port -- port where i am listening for incoming requests. |
| * @param transport -- transport to use for the message processor (UDP/TCP/TLS). |
| */ |
| protected MessageProcessor( InetAddress ipAddress, int port, String transport, |
| SIPTransactionStack transactionStack ) { |
| this( transport ); |
| this.initialize(ipAddress, port, transactionStack); |
| } |
| |
| /** |
| * Initializes this MessageProcessor. Needed for extensions |
| * that use classloading |
| * |
| * @param ipAddress2 |
| * @param transactionStack |
| * @param port2 |
| */ |
| public final void initialize( InetAddress ipAddress, int port, |
| SIPTransactionStack transactionStack ) { |
| |
| this.sipStack = transactionStack; |
| this.savedIpAddress = ipAddress.getHostAddress(); |
| this.ipAddress = ipAddress; |
| this.port = port; |
| this.sentByHostPort = new HostPort(); |
| this.sentByHostPort.setHost(new Host(ipAddress.getHostAddress())); |
| this.sentByHostPort.setPort(port); |
| } |
| |
| /** |
| * Get the transport string. |
| * |
| * @return A string that indicates the transport. (i.e. "tcp" or "udp") |
| */ |
| public String getTransport() { |
| return this.transport; |
| } |
| |
| /** |
| * Get the port identifier. |
| * |
| * @return the port for this message processor. This is where you receive |
| * messages. |
| */ |
| public int getPort() { |
| return this.port; |
| } |
| |
| /** |
| * Get the Via header to assign for this message processor. The topmost via |
| * header of the outoging messages use this. |
| * |
| * @return the ViaHeader to be used by the messages sent via this message processor. |
| */ |
| public Via getViaHeader() { |
| try { |
| Via via = new Via(); |
| if (this.sentByHostPort != null) { |
| via.setSentBy(sentByHostPort); |
| via.setTransport(this.getTransport()); |
| } else { |
| Host host = new Host(); |
| host.setHostname(this.getIpAddress().getHostAddress()); |
| via.setHost(host); |
| via.setPort(this.getPort()); |
| via.setTransport(this.getTransport()); |
| } |
| return via; |
| } catch (ParseException ex) { |
| ex.printStackTrace(); |
| return null; |
| } catch (InvalidArgumentException ex) { |
| ex.printStackTrace(); |
| return null; |
| } |
| } |
| public ListeningPointImpl getListeningPoint() { |
| if ( listeningPoint == null ) { |
| if ( this.getSIPStack().isLoggingEnabled()) { |
| this.getSIPStack().getStackLogger().logError("getListeningPoint" + this + |
| " returning null listeningpoint"); |
| |
| } |
| } |
| return listeningPoint; |
| } |
| |
| public void setListeningPoint(ListeningPointImpl lp) { |
| if ( this.getSIPStack().isLoggingEnabled()) { |
| this.getSIPStack().getStackLogger().logDebug("setListeningPoint" + this + |
| " listeningPoint = " + lp); |
| |
| } |
| if ( lp.getPort() != this.getPort()) |
| InternalErrorHandler.handleException |
| ("lp mismatch with provider",getSIPStack().getStackLogger()); |
| this.listeningPoint = lp; |
| |
| } |
| |
| /** |
| * Get the saved IP Address. |
| */ |
| public String getSavedIpAddress() { |
| return this.savedIpAddress; |
| } |
| /** |
| * @return the ip address for this message processor. |
| */ |
| public InetAddress getIpAddress() { |
| return this.ipAddress; |
| } |
| /** |
| * @param ipAddress the ipAddress to set |
| */ |
| protected void setIpAddress(InetAddress ipAddress) { |
| this.sentByHostPort.setHost( new Host(ipAddress.getHostAddress())); |
| this.ipAddress = ipAddress; |
| } |
| |
| /** |
| * Set the sentby string. This is used for stamping outgoing messages sent |
| * from this listening point. |
| * |
| * @param sentBy |
| */ |
| public void setSentBy(String sentBy) throws ParseException { |
| |
| int ind = sentBy.indexOf(":"); |
| if (ind == -1) { |
| this.sentByHostPort = new HostPort(); |
| this.sentByHostPort.setHost(new Host(sentBy)); |
| } else { |
| this.sentByHostPort = new HostPort(); |
| this.sentByHostPort.setHost(new Host(sentBy.substring(0, ind))); |
| String portStr = sentBy.substring(ind + 1); |
| try { |
| int port = Integer.parseInt(portStr); |
| this.sentByHostPort.setPort(port); |
| } catch (NumberFormatException ex) { |
| throw new ParseException("Bad format encountered at ", ind); |
| } |
| } |
| this.sentBySet = true; |
| this.sentBy = sentBy; |
| |
| } |
| |
| /** |
| * Get the sentby string. |
| * |
| */ |
| public String getSentBy() { |
| if ( this.sentBy == null && this.sentByHostPort != null) { |
| this.sentBy = this.sentByHostPort.toString(); |
| } |
| return this.sentBy; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////// |
| // Abstract methods |
| /////////////////////////////////////////////////////////////////////////////////////// |
| /** |
| * Get the SIP Stack. |
| * |
| * @return the sip stack. |
| */ |
| public abstract SIPTransactionStack getSIPStack(); |
| |
| /** |
| * Create a message channel for the specified host/port. |
| * |
| * @return New MessageChannel for this processor. |
| */ |
| public abstract MessageChannel createMessageChannel(HostPort targetHostPort) |
| throws IOException; |
| |
| /** |
| * Create a message channel for the specified host/port. |
| * |
| * @return New MessageChannel for this processor. |
| */ |
| public abstract MessageChannel createMessageChannel(InetAddress targetHost, |
| int port) throws IOException; |
| |
| |
| /** |
| * Start our thread. |
| */ |
| public abstract void start() throws IOException; |
| |
| /** |
| * Stop method. |
| */ |
| public abstract void stop(); |
| |
| /** |
| * Default target port used by this processor. This is 5060 for TCP / UDP |
| */ |
| public abstract int getDefaultTargetPort(); |
| |
| /** |
| * Flags whether this processor is secure or not. |
| */ |
| public abstract boolean isSecure(); |
| |
| /** |
| * Maximum number of bytes that this processor can handle. |
| */ |
| public abstract int getMaximumMessageSize(); |
| |
| /** |
| * Return true if there are pending messages to be processed (which prevents |
| * the message channel from being closed). |
| */ |
| public abstract boolean inUse(); |
| |
| |
| |
| /** |
| * Run method. |
| */ |
| public abstract void run(); |
| |
| /** |
| * @return Returns the sentBySet. |
| */ |
| public boolean isSentBySet() { |
| return sentBySet; |
| } |
| |
| |
| /** |
| * Get the defalt port for the message processor. |
| * |
| * @param transport |
| * @return -- the default port for the message processor. |
| */ |
| |
| public static int getDefaultPort(String transport) { |
| |
| return transport.equalsIgnoreCase("TLS")?5061:5060; |
| } |
| |
| |
| |
| } |