⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 message.java

📁 stun的java实现
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
    public void setTransactionID(byte[] tranID)
        throws StunException
    {
        if(tranID == null
           || tranID.length != TRANSACTION_ID_LENGTH)
            throw new StunException(StunException.ILLEGAL_ARGUMENT,
                                    "Invalid transaction id");

        this.transactionID = new byte[TRANSACTION_ID_LENGTH];
        System.arraycopy(tranID, 0,
                         this.transactionID, 0, TRANSACTION_ID_LENGTH);
    }

    /**
     * Returns a reference to this message's transaction id.
     * @return a reference to this message's transaction id.
     */
    public byte[] getTransactionID()
    {
        return this.transactionID;
    }

    /**
     * Returns whether an attribute could be present in this message.
     * @param attributeType the id of the attribute to check .
     * @return Message.N_A - for not applicable <br/>
     *         Message.C   - for case depending <br/>
     *         Message.N_A - for not applicable <br/>
     */
    protected byte getAttributePresentity(char attributeType)
    {
        byte msgIndex = -1;
        byte attributeIndex = -1;

        switch (messageType)
        {
            case BINDING_REQUEST:              msgIndex = BINDING_REQUEST_PRESENTITY_INDEX; break;
            case BINDING_RESPONSE:             msgIndex = BINDING_RESPONSE_PRESENTITY_INDEX; break;
            case BINDING_ERROR_RESPONSE:       msgIndex = BINDING_ERROR_RESPONSE_PRESENTITY_INDEX; break;
            case SHARED_SECRET_REQUEST:        msgIndex = SHARED_SECRET_REQUEST_PRESENTITY_INDEX; break;
            case SHARED_SECRET_RESPONSE:       msgIndex = SHARED_SECRET_RESPONSE_PRESENTITY_INDEX; break;
            case SHARED_SECRET_ERROR_RESPONSE: msgIndex = SHARED_SECRET_ERROR_RESPONSE_PRESENTITY_INDEX; break;
        }

        switch (attributeType)
        {
            case Attribute.MAPPED_ADDRESS:     attributeIndex = MAPPED_ADDRESS_PRESENTITY_INDEX; break;
            case Attribute.RESPONSE_ADDRESS:   attributeIndex = RESPONSE_ADDRESS_PRESENTITY_INDEX; break;
            case Attribute.CHANGE_REQUEST:     attributeIndex = CHANGE_REQUEST_PRESENTITY_INDEX; break;
            case Attribute.SOURCE_ADDRESS:     attributeIndex = SOURCE_ADDRESS_PRESENTITY_INDEX; break;
            case Attribute.CHANGED_ADDRESS:    attributeIndex = CHANGED_ADDRESS_PRESENTITY_INDEX; break;
            case Attribute.USERNAME:           attributeIndex = USERNAME_PRESENTITY_INDEX; break;
            case Attribute.PASSWORD:           attributeIndex = PASSWORD_PRESENTITY_INDEX; break;
            case Attribute.MESSAGE_INTEGRITY:  attributeIndex = MESSAGE_INTEGRITY_PRESENTITY_INDEX; break;
            case Attribute.ERROR_CODE:         attributeIndex = ERROR_CODE_PRESENTITY_INDEX; break;
            case Attribute.UNKNOWN_ATTRIBUTES: attributeIndex = UNKNOWN_ATTRIBUTES_PRESENTITY_INDEX; break;
            case Attribute.REFLECTED_FROM:     attributeIndex = REFLECTED_FROM_PRESENTITY_INDEX; break;
            case Attribute.XOR_MAPPED_ADDRESS: attributeIndex = XOR_MAPPED_ADDRESS_PRESENTITY_INDEX; break;
            case Attribute.XOR_ONLY:           attributeIndex = XOR_ONLY_PRESENTITY_INDEX; break;
            case Attribute.SERVER:             attributeIndex = SERVER_PRESENTITY_INDEX; break;
            default: attributeIndex = UNKNOWN_OPTIONAL_ATTRIBUTES_PRESENTITY_INDEX; break;
        }









        return attributePresentities[ attributeIndex ][ msgIndex ];
    }

    /**
     * Returns the human readable name of this message. Message names do
     * not really matter from the protocol point of view. They are only used
     * for debugging and readability.
     * @return this message's name.
     */
    public String getName()
    {
        switch (messageType)
        {
            case BINDING_REQUEST:              return "BINDING-REQUEST";
            case BINDING_RESPONSE:             return "BINDING-RESPONSE";
            case BINDING_ERROR_RESPONSE:       return "BINDING-ERROR-RESPONSE";
            case SHARED_SECRET_REQUEST:        return "SHARED-SECRET-REQUEST";
            case SHARED_SECRET_RESPONSE:       return "SHARED-SECRET-RESPONSE";
            case SHARED_SECRET_ERROR_RESPONSE: return "SHARED-SECRET-ERROR-RESPONSE";
        }

        return "UNKNOWN-MESSAGE";
    }

    /**
     * Compares two STUN Messages. Messages are considered equal when their
     * type, length, and all their attributes are equal.
     *
     * @param obj the object to compare this message with.
     * @return true if the messages are equal and false otherwise.
     */
    public boolean equals(Object obj)
    {
        if(!(obj instanceof Message)
           || obj == null)
            return false;

        if(obj == this)
            return true;

        Message msg = (Message) obj;
        if( msg.getMessageType()   != getMessageType())
            return false;
        if(msg.getDataLength() != getDataLength())
            return false;

        //compare attributes
        Iterator iter = attributes.entrySet().iterator();
        while (iter.hasNext()) {
            Attribute localAtt = (Attribute)((Map.Entry)iter.next()).getValue();

            if(!localAtt.equals(msg.getAttribute(localAtt.getAttributeType())))
                return false;
        }

        return true;
    }


    /**
     * Returns a binary representation of this message.
     * @return a binary representation of this message.
     * @throws StunException if the message does not have all required
     * attributes.
     */
    public byte[] encode()
        throws StunException
    {
        //make sure we have everything necessary to encode a proper message
        validateAttributePresentity();
        char dataLength = getDataLength();
        byte binMsg[] = new byte[HEADER_LENGTH + dataLength];
        int offset    = 0;

        binMsg[offset++] = (byte)(getMessageType()>>8);
        binMsg[offset++] = (byte)(getMessageType()&0xFF);

        binMsg[offset++] = (byte)(dataLength >> 8);
        binMsg[offset++] = (byte)(dataLength & 0xFF);

        System.arraycopy(getTransactionID(), 0, binMsg, offset, TRANSACTION_ID_LENGTH);
        offset+=TRANSACTION_ID_LENGTH;

        Iterator iter = attributes.entrySet().iterator();
        while (iter.hasNext()) {

            Attribute attribute = (Attribute)((Map.Entry)iter.next()).getValue();

            byte[] attBinValue = attribute.encode();
            System.arraycopy(attBinValue, 0, binMsg, offset, attBinValue.length);
            offset += attBinValue.length;
        }

        return binMsg;
    }

    /**
     * Constructs a message from its binary representation.
     * @param binMessage the binary array that contains the encoded message
     * @param offset the index where the message starts.
     * @param arrayLen the length of the message
     * @return a Message object constructed from the binMessage array
     * @throws StunException ILLEGAL_ARGUMENT if one or more of the arguments
     * have invalid values.
     */
    public static Message decode(byte binMessage[], char offset, char arrayLen)
        throws StunException
    {
        arrayLen = (char)Math.min(binMessage.length, arrayLen);

        if(binMessage == null || arrayLen - offset < Message.HEADER_LENGTH)
            throw new StunException(StunException.ILLEGAL_ARGUMENT,
                                    "The given binary array is not a valid StunMessage");

        char messageType = (char)((binMessage[offset++]<<8) | (binMessage[offset++]&0xFF));
        Message message;
        if (Message.isResponseType(messageType))
        {
            message = new Response();
        }
        else
        {
            message = new Request();
        }
        message.setMessageType(messageType);

        int length = (char)((binMessage[offset++]<<8) | (binMessage[offset++]&0xFF));

        if(arrayLen - offset - TRANSACTION_ID_LENGTH < length)
            throw new StunException(StunException.ILLEGAL_ARGUMENT,
                                    "The given binary array does not seem to "
                                    +"contain a whole StunMessage");

        byte tranID[] = new byte[TRANSACTION_ID_LENGTH];
        System.arraycopy(binMessage, offset, tranID, 0, TRANSACTION_ID_LENGTH);
        message.setTransactionID(tranID);
        offset+=TRANSACTION_ID_LENGTH;

        while(offset - Message.HEADER_LENGTH< length)
        {
            Attribute att = AttributeDecoder.decode(binMessage,
                                                    (char)offset,
                                                    (char)(length - offset));
            message.addAttribute(att);
            offset += att.getDataLength() + Attribute.HEADER_LENGTH;
        }

        return message;

    }

    /**
     * Verify that the message has all obligatory attributes and throw an
     * exception if this is not the case.
     *
     * @return true if the message has all obligatory attributes, false
     * otherwise.
     * @throws StunException (ILLEGAL_STATE)if the message does not have all
     * required attributes.
     */
    protected void validateAttributePresentity()
        throws StunException
    {
        for(char i = Attribute.MAPPED_ADDRESS; i < Attribute.REFLECTED_FROM; i++)
            if(getAttributePresentity(i) == M && getAttribute(i) == null)
                throw new StunException(StunException.ILLEGAL_STATE,
                                        "A mandatory attribute (type="
                                        +(int)i
                                        + ") is missing!");

    }

    /**
     * Determines whether type could be the type of a STUN Response (as opposed
     * to STUN Request).
     * @param type the type to test.
     * @return true if type is a valid response type.
     */
    public static boolean isResponseType(char type)
    {
        return (((type >> 8) & 1) != 0);
    }

    /**
     * Determines whether type could be the type of a STUN Request (as opposed
     * to STUN Response).
     * @param type the type to test.
     * @return true if type is a valid request type.
     */
    public static boolean isRequestType(char type)
    {
        return !isResponseType(type);
    }

    public String toString()
    {
        return getName()+"("+getMessageType()
            +")[attrib.count=" + getAttributeCount()
            +" len=" + this.getDataLength()
            +" tranID=" + this.getTransactionID() + "]";
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -