FileDocCategorySizeDatePackage
ViaHeader.javaAPI DocphoneME MR2 API (J2ME)14828Wed May 02 18:00:42 BST 2007gov.nist.siplite.header

ViaHeader.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.header;

import gov.nist.siplite.parser.*;
import gov.nist.core.*;

/**
 * Via Header (these are strung together in a ViaList).
 *
 * @version JAIN-SIP-1.1
 *
 *
 * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
 *
 */
public class ViaHeader extends gov.nist.siplite.header.ParametersHeader {
    /** Class handle. */
    public static Class clazz;
    /** Via header field label. */
    public static final String NAME = Header.VIA;

    /**
     * The branch parameter is included by every forking proxy.
     */
    public static final String BRANCH = "branch";

    /**
     * The "hidden" paramter is included if this header field
     * was hidden by the upstream proxy.
     */
    public static final String HIDDEN = "hidden";

    /**
     * The "received" parameter is added only for receiver-added Via Fields.
     */
    public static final String RECEIVED = "received";

    /**
     * The "maddr" parameter is designating the multicast address.
     */
    public static final String MADDR = "maddr";

    /**
     * The "TTL" parameter is designating the time-to-live value.
     */
    public static final String TTL = "ttl";

    /**
     * Sent protocol field.
     */
    protected Protocol sentProtocol;

    /**
     * Sent by field.
     */
    protected HostPort sentBy;

    /**
     * Comment field.
     */
    protected String comment;


    static {
        clazz = new ViaHeader().getClass();
    }

    /**
     * Default constructor.
     */
    public ViaHeader() {
        super(VIA);
        this.sentBy = new HostPort();

        sentProtocol = new Protocol();
    }

    /**
     * Compares two via headers for equaltiy.
     * @param other Object to set.
     * @return true if the two via headers are the same.
     */
    public boolean equals(Object other) {
        if (! this.getClass().equals(other.getClass())) {
            return false;
        }

        ViaHeader that = (ViaHeader) other;

        if (! this.sentProtocol.equals(that.sentProtocol)) {
            return false;
        }

        if (! this.parameters.equals(that.parameters)) {
            return false;
        }

        if (! this.sentBy.equals(that.sentBy)) {
            return false;
        }

        return true;
    }

    /**
     * Encodes the via header into a cannonical string.
     * @return String containing cannonical encoding of via header.
     */
    public String encodeBody() {
        String encoding = "";
        encoding += sentProtocol.encode() + Separators.SP + sentBy.encode();

        // Add the default port if there is no port specified.
        if (! sentBy.hasPort()) encoding += Separators.COLON + "5060";

        if (comment != null) {
            encoding += Separators.LPAREN + comment + Separators.RPAREN;
        }

        encoding += encodeWithSep();

        return encoding;
    }

    /**
     * Gets the Protocol Version.
     * @return String
     */
    public String getProtocolVersion() {
        if (sentProtocol == null)
            return null;
        else
            return sentProtocol.getProtocolVersion();
    }

    /**
     * Accessor for the sentProtocol field.
     * @return Protocol field
     */
    public Protocol getSentProtocol() {

        return sentProtocol;
    }

    /**
     * Accessor for the sentBy field
     * @return SentBy field
     */
    public HostPort getSentBy() {
        return sentBy;
    }

    /**
     * Gest the host name. (null if not yet set).
     * @return host name from the via header.
     */
    public String getHost() {
        if (sentBy == null)
            return null;
        else {
            Host host = sentBy.getHost();
            if (host == null)
                return null;
            else return host.getHostname();
        }
    }

    /**
     * Port of the Via header.
     * @return port field.
     */
    public int getPort() {
        if (sentBy == null)
            return -1;
        return sentBy.getPort();
    }

    /**
     * Port of the Via Header.
     * @return true if Port exists.
     */
    public boolean hasPort() {
        if (sentBy == null)
            return false;
        return (getSentBy()).hasPort();
    }

    /**
     * Accessor for the comment field.
     * @return comment field.
     */
    public String getComment() {
        return comment;
    }

    /**
     * Gets the Branch parameter if it exists.
     * @return Branch field.
     */
    public String getBranch() {
        return super.getParameter(ViaHeader.BRANCH);
    }

    /**
     * Gets the received parameter if it exists.
     * @return received parameter.
     */
    public String getReceived() {
        return super.getParameter(ViaHeader.RECEIVED);

    }

    /**
     * Gets the maddr parameter if it exists.
     * @return maddr parameter.
     */
    public String getMaddr() {
        return super.getParameter(ViaHeader.MADDR);

    }

    /**
     * get the ttl parameter if it exists.
     * @return ttl parameter.
     */
    public String getTTL() {
        return super.getParameter(ViaHeader.TTL);
    }

    /**
     * Comment of the Via Header.
     *
     * @return false if comment does not exist and true otherwise.
     */
    public boolean hasComment() {
        return comment != null;
    }

    /**
     * Removes the comment field.
     */
    public void removeComment() {
        comment = null;
    }

    /**
     * Sets the Protocol Version.
     *
     * BNF (RFC3261, p. 222, 232):
     *     protocol-version = token
     *
     * @param protocolVersion String to set
     */
    public void setProtocolVersion(String protocolVersion) {
        if (sentProtocol == null) sentProtocol = new Protocol();
        sentProtocol.setProtocolVersion(protocolVersion);
    }

    /**
     * Sets the sentProtocol member
     * @param s Protocol to set.
     */
    public void setSentProtocol(Protocol s) {
        sentProtocol = s;
    }

    /**
     * Sets the transport string.
     *
     * BNF (RFC3261, p. 222, 232):
     *     transport = "UDP" / "TCP" / "TLS" / "SCTP" / other-transport
     *
     * @param transport String to set
     */
    public void setTransport(String transport) {
        if (sentProtocol == null) sentProtocol = new Protocol();
        sentProtocol.setTransport(transport);
    }

    /**
     * Sets the sentBy member
     * @param s HostPort to set.
     */
    public void setSentBy(HostPort s) {
        sentBy = s;
    }

    /**
     * Sets the comment member
     * @param c String to set.
     */
    public void setComment(String c) {
        comment = c;
    }

    /**
     * Clone - do a deep copy.
     * @return Object Via
     */
    public Object clone() {
        ViaHeader retval = new ViaHeader();

        if (this.comment != null) retval.comment = new String(this.comment);
        if (this.parameters != null) retval.parameters =
                (NameValueList) parameters.clone();
        if (this.sentBy != null) retval.sentBy = (HostPort)sentBy.clone();
        if (this.sentProtocol != null)
            retval.sentProtocol = (Protocol)sentProtocol.clone();
        return retval;
    }

    /**
     * Gets the value portion of this header (does nto include the parameters).
     * @return the via header field value
     */
    public Object getValue() {
        return sentProtocol.encode() + " " + sentBy.encode();

    }

    /**
     * Sets the header value field (without parameters).
     * @param value is the value field to set.
     * @throws IllegalArgumentException if the value is invalid.
     */
    public void setHeaderValue(String value)
            throws IllegalArgumentException {

        StringMsgParser smp = new StringMsgParser();
        ViaList hl = null;
        String strNewHeader = NAME + Separators.COLON + value;

        try {
            hl = (ViaList)smp.parseHeader(strNewHeader);
        } catch (ParseException e) {
            throw new IllegalArgumentException(e.toString());
        }

        if (hl.size() > 1) {
            throw new IllegalArgumentException("Ivalid Via header " +
                                               "value: " + value);
        }

        ViaHeader header = (ViaHeader)hl.elementAt(0);

        // Copy the values from the header created from the parsed value
        setSentBy(header.getSentBy());
        setSentProtocol(header.getSentProtocol());

        if (sentProtocol != null) {
            setProtocolVersion(header.getProtocolVersion());
            setTransport(header.getTransport());
        }

        if (sentBy != null) {
            setHost(header.getHost());
            setPort(header.getPort());
        }

        // IMPL_NOTE:
        // System.out.println("new: '" + strNewHeader + "'");
        // System.out.println("this: '" + strNewHeader + "'");
    }

    /**
     * This function is overloaded in order to validate the parameters.
     * Sets the value of the specified parameter. If the parameter already
     * had a value it will be overwritten. A zero-length String indicates flag
     * parameter.
     *
     * IMPL_NOTE: add a support for all parameters that are stored as
     *       members of this class.
     *
     * @param name a String specifying the parameter name
     * @param value a String specifying the parameter value
     * @throws IllegalArgumentException if the parameter's name or its value
     * is invalid.
     */
    public void setParameter(String name, String value)
            throws IllegalArgumentException {
        if (name.equalsIgnoreCase(ViaHeader.TTL)) {
            setTTL(value);
        } else if (name.equalsIgnoreCase(ViaHeader.RECEIVED)) {
            setReceived(value);
        } else {
            super.setParameter(name, value);
        }
    }

    /**
     * Sets the 'received' parameter.
     *
     * BNF (RFC3261, p. 223, 232):
     *     via-received = "received" EQUAL (IPv4address / IPv6address)
     *     IPv4address  =  1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
     *     IPv6address  =  hexpart [ ":" IPv4address ]
     *     hexpart      =  hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ]
     *     hexseq       =  hex4 *( ":" hex4)
     *     hex4         =  1*4HEXDIG
     *
     * @param received the new 'received' value.
     * @throws IllegalArgumentException if the new 'received' value is invalid.
     */
    public void setReceived(String received) throws IllegalArgumentException {
        if (!Lexer.isValidIpv4Address(received) &&
            !Lexer.isValidIpv6Address(received)) {
            throw new IllegalArgumentException("Invalid IP address");
        }
        
        super.setParameter(RECEIVED, received);
    }

    /**
     * Sets the maddr parameter.
     *
     * BNF (RFC3261, p. 222, 232):
     *     via-maddr   = "maddr" EQUAL host
     *     host        =  hostname / IPv4address / IPv6reference
     *     hostname    =  *( domainlabel "." ) toplabel [ "." ]
     *     domainlabel =  alphanum / alphanum *( alphanum / "-" ) alphanum
     *     toplabel    =  ALPHA / ALPHA *( alphanum / "-" ) alphanum
     *
     *     IPv4address   =  1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
     *     IPv6reference =  "[" IPv6address "]"
     *     IPv6address   =  hexpart [ ":" IPv4address ]
     *     hexpart       =  hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ]
     *     hexseq        =  hex4 *( ":" hex4)
     *     hex4          =  1*4HEXDIG
     *
     * IMPL_NOTE: check maddr for validity.
     * @param maddr the new maddr value.
     * @throws IllegalArgumentException if the new maddr value is invalid.
     */
    public void setMaddr(String maddr) throws IllegalArgumentException {
        super.setParameter(MADDR, maddr);
    }

    /**
     * Sets the ttl parameter.
     *
     * BNF (RFC3261, p. 232):
     *     ttl = 1*3DIGIT ; 0 to 255
     *
     * @param strTTL the new ttl value given in a string form.
     * @throws IllegalArgumentException if the new ttl value is invalid.
     */
    public void setTTL(String strTTL) throws IllegalArgumentException {
        int ttl = 0;

        try {
            ttl = Integer.parseInt(strTTL);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Cannot parse TTL '" +
                strTTL + "': " + e);
        }

        if (ttl < 0 || ttl > 255) {
            throw new IllegalArgumentException("Invalid TTL: " + strTTL);
        }

        super.setParameter(TTL, strTTL);
    }

    /**
     * Sets the branch field.
     *
     * BNF (RFC3261, p. 232):
     *     via-branch = "branch" EQUAL token
     *
     * @param branch the new branch value
     */
    public void setBranch(String branch) {
        super.setParameter(BRANCH, branch);
    }

    /**
     * Sets the host field.
     *
     * BNF (RFC3261, p. 222):
     *     host =  hostname / IPv4address / IPv6reference
     * See setMaddr() for the full BNF.
     *
     * @param host the new host value
     */
    public void setHost(String host) {
        this.sentBy.setHost(new Host(host));
    }

    /**
     * Sets the host field.
     * @param host the new host value
     */
    public void setHost(Host host) {
        this.sentBy.setHost(host);
    }

    /**
     * Sets the port field.
     *
     * BNF (RFC3261, p. 232):
     *     port = 1*DIGIT
     *
     * @param port the new port value
     */
    public void setPort(int port) {
        this.sentBy.setPort(port);
    }

    /**
     * Gets the current transport.
     * @return the current transport
     */
    public String getTransport() {
        if (this.sentProtocol == null)
            return null;
        else return this.sentProtocol.getTransport();
    }

}