FileDocCategorySizeDatePackage
MessageChannel.javaAPI DocphoneME MR2 API (J2ME)10113Wed May 02 18:00:42 BST 2007gov.nist.siplite.stack

MessageChannel.java

/*
 * Portions Copyright  2000-2007 Sun Microsystems, Inc. All Rights
 * Reserved.  Use is subject to license terms.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program 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
 * General Public License version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */
/*
 */
package gov.nist.siplite.stack;

import gov.nist.siplite.header.*;
import gov.nist.siplite.address.*;
import gov.nist.siplite.message.*;
import java.util.Enumeration;
import java.io.IOException;
import gov.nist.core.*;

/**
 * Message channel abstraction for the SIP stack.
 *
 * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
 */
public abstract class MessageChannel {
    /**
     * Message processor to whom I belong (if set).
     */
    protected MessageProcessor messageProcessor;
    
    /**
     * Closes the message channel.
     */
    public abstract void close();
    
    /**
     * Gets the SIPMessageStack object from this message channel.
     * @return SIPMessageStack object of this message channel
     */
    public abstract SIPMessageStack getSIPStack();
    
    /**
     * Gets transport string of this message channel.
     * @return Transport string of this message channel.
     */
    public abstract String getTransport();
    
    /**
     * Gets whether this channel is reliable or not.
     * @return True if reliable, false if not.
     */
    public abstract boolean isReliable();
    
    /**
     * Returns true if this is a secure channel.
     * @return true if connection is secure
     */
    public abstract boolean isSecure();
    
    /**
     * Sends the message (after it has been formatted)
     * @param sipMessage Message to send.
     */
    public abstract void sendMessage(Message sipMessage)
    throws IOException;
    
    /**
     * Gets the peer address of the machine that sent us this message.
     * @return a string contianing the ip address or host name of the sender
     * of the message.
     */
    public abstract String getPeerAddress();
    
    /**
     * Gets the name of the machine that sent us this message.
     * @return a string contianing the ip address or host name of the sender
     * of the message.
     * public abstract String getPeerName();
     */
    
    /**
     * Gets the sender port (the port of the other end that sent me
     * the message).
     * @return the peer port
     */
    public abstract int getPeerPort();
    
    /**
     * Generates a key which identifies the message channel.
     * This allows us to cache the message channel.
     * @return the key
     */
    public abstract String getKey();
    
    /**
     * Gets the host to assign for an outgoing Request via header.
     * @return the via host
     */
    public abstract String getViaHost();
    
    /**
     * Gets the port to assign for the via header of an outgoing message.
     * @return the via port
     */
    public abstract int getViaPort();
    
    /**
     * Sends the message (after it has been formatted), to a specified
     * address and a specified port
     * @param message Message to send.
     * @param receiverAddress Address of the receiver.
     * @param receiverPort Port of the receiver.
     */
    protected abstract void sendMessage(byte[] message,
            String receiverAddress,
            int receiverPort)
            throws IOException;
    
    /**
     * Gets the host of this message channel.
     * @return host of this messsage channel.
     */
    public String getHost() {
        return this.getSIPStack().getHostAddress();
    }
    
    /**
     * Gets port of this message channel.
     * @return Port of this message channel.
     */
    public int getPort() {
        if (this.messageProcessor != null)
            return messageProcessor.getPort();
        else return -1;
    }
    
    /**
     * Handles an exception.
     * @param ex the exception to process
     */
    public abstract void handleException(SIPServerException ex);
    
    /**
     * Sends a message given SIP message.
     * @param sipMessage is the messge to send.
     * @param receiverAddress is the address to which we want to send
     * @param receiverPort is the port to which we want to send
     */
    public void sendMessage(Message sipMessage,
            String receiverAddress,
            int receiverPort) throws IOException {
        long time = System.currentTimeMillis();
        byte[] bytes = sipMessage.encodeAsBytes();
        sendMessage(bytes, receiverAddress, receiverPort);
        logMessage(sipMessage, receiverAddress, receiverPort, time);
    }
    
    /**
     * Generates a key given the inet address port and transport.
     * @param inetAddr internet address
     * @param port the connection end point
     * @param transport the connection type
     * @return the connection key
     */
    public static String
            getKey(String inetAddr, int port, String transport) {
        return transport+":"+ inetAddr +":"+port;
    }
    
    /**
     * Gets the hostport structure of this message channel.
     * @return the host and port
     */
    public HostPort getHostPort() {
        HostPort retval = new HostPort();
        retval.setHost(new Host(this.getHost()));
        retval.setPort(this.getPort());
        return retval;
    }
    
    /**
     * Gets the peer host and port.
     *
     * @return a HostPort structure for the peer.
     */
    public HostPort getPeerHostPort() {
        HostPort retval = new HostPort();
        retval.setHost(new Host(this.getPeerAddress()));
        retval.setPort(this.getPeerPort());
        return retval;
    }
    
    /**
     * Gets the Via header for this transport.
     * Note that this does not set a branch identifier.
     *
     * @return a via header for outgoing messages sent from this channel.
     */
    public ViaHeader getViaHeader() {
        ViaHeader channelViaHeader;
        
        channelViaHeader = new ViaHeader();
        
        channelViaHeader.setTransport(getTransport());
        
        channelViaHeader.setSentBy(getHostPort());
        return channelViaHeader;
    }
    
    /**
     * Gets the via header host:port structure.
     * This is extracted from the topmost via header of the request.
     *
     * @return a host:port structure
     */
    public HostPort getViaHostPort() {
        HostPort retval = new HostPort();
        retval.setHost(new Host(this.getViaHost()));
        retval.setPort(this.getViaPort());
        return retval;
    }
    
    /**
     * Logs a message sent to an address and port via the default interface.
     * @param sipMessage is the message to log.
     * @param address is the inet address to which the message is sent.
     * @param port is the port to which the message is directed.
     * @param time timestamp for the logged message
     */
    protected void logMessage(Message sipMessage,
            String address, int port, long time) {
        String firstLine = sipMessage.getFirstLine();
        CSeqHeader cseq = (CSeqHeader) sipMessage.getCSeqHeader();
        CallIdHeader callid = (CallIdHeader) sipMessage.getCallId();
        String cseqBody = cseq.encodeBody();
        String callidBody = callid.encodeBody();
        // Default port.
        if (port == -1) port = 5060;
        if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES)) {
            Enumeration extList = sipMessage.getHeaders("NISTExtension");
            String status = null;
            if (extList != null && extList.hasMoreElements()) {
                Header exthdr = null;
                exthdr = (Header) extList.nextElement();
                status = exthdr.getHeaderValue();
            }
            ServerLog.logMessage(sipMessage.encode(),
                    this.getHost()+":"+this.getPort(),
                    address +
                    ":" + port, true, callidBody,
                    firstLine, status,
                    sipMessage.getTransactionId(), time);
        }
    }
    
    /**
     * Logs a response received at this message channel.
     * This is used for processing incoming responses to a client transaction.
     * @param sipResponse the response object to be logged
     * @param receptionTime is the time at which the response was received.
     * @param status is the processing status of the message.
     */
    public void
            logResponse(Response sipResponse,
            long receptionTime,
            String status) {
        try {
            int peerport = getPeerPort();
            if (peerport == 0 && sipResponse.getContactHeaders() != null) {
                ContactHeader contact =
		    (ContactHeader) sipResponse.getContactHeaders().getFirst();
                peerport = ((Address)contact.getAddress()).getPort();
                
            }
            String from = getPeerAddress() + ":" + peerport;
            String to = this.getHost() + ":" + getPort();
            ServerLog.logMessage(sipResponse,
                    from, to, status, false, receptionTime);
        } catch (RuntimeException ex) {
            ex.printStackTrace();
        }
    }
    
    /**
     * Gets the message processor.
     * @return the message processor
     */
    public MessageProcessor getMessageProcessor() {
        return this.messageProcessor;
    }
}