All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.netty.handler.codec.spdy.SpdyCodecUtil Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.netty.handler.codec.spdy;

import io.netty.buffer.ChannelBuffer;

final class SpdyCodecUtil {

    static final int SPDY_VERSION = 2;

    static final int SPDY_HEADER_TYPE_OFFSET   = 2;
    static final int SPDY_HEADER_FLAGS_OFFSET  = 4;
    static final int SPDY_HEADER_LENGTH_OFFSET = 5;
    static final int SPDY_HEADER_SIZE          = 8;

    static final int SPDY_MAX_LENGTH = 0xFFFFFF; // Length is a 24-bit field

    static final byte SPDY_DATA_FLAG_FIN      = 0x01;
    static final byte SPDY_DATA_FLAG_COMPRESS = 0x02;

    static final int SPDY_SYN_STREAM_FRAME    = 1;
    static final int SPDY_SYN_REPLY_FRAME     = 2;
    static final int SPDY_RST_STREAM_FRAME    = 3;
    static final int SPDY_SETTINGS_FRAME      = 4;
    static final int SPDY_NOOP_FRAME          = 5;
    static final int SPDY_PING_FRAME          = 6;
    static final int SPDY_GOAWAY_FRAME        = 7;
    static final int SPDY_HEADERS_FRAME       = 8;
    static final int SPDY_WINDOW_UPDATE_FRAME = 9;

    static final byte SPDY_FLAG_FIN            = 0x01;
    static final byte SPDY_FLAG_UNIDIRECTIONAL = 0x02;

    static final byte SPDY_SETTINGS_CLEAR         = 0x01;
    static final byte SPDY_SETTINGS_PERSIST_VALUE = 0x01;
    static final byte SPDY_SETTINGS_PERSISTED     = 0x02;

    static final int SPDY_SETTINGS_MAX_ID = 0xFFFFFF; // ID is a 24-bit field

    static final int SPDY_MAX_NV_LENGTH = 0xFFFF; // Length is a 16-bit field

    // Zlib Dictionary
    private static final String SPDY_DICT_S =
        "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" +
        "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" +
        "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" +
        "-agent10010120020120220320420520630030130230330430530630740040140240340440" +
        "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" +
        "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" +
        "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" +
        "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" +
        "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" +
        "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" +
        "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" +
        "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" +
        ".1statusversionurl ";
    static final byte[] SPDY_DICT;
    static {
        byte[] SPDY_DICT_ = null;

        try {
            SPDY_DICT_ = SPDY_DICT_S.getBytes("US-ASCII");
            // dictionary is null terminated
            SPDY_DICT_[SPDY_DICT_.length - 1] = (byte) 0;
        } catch (Exception e) {
            SPDY_DICT_ = new byte[1];
        }

        SPDY_DICT = SPDY_DICT_;
    }


    private SpdyCodecUtil() {
    }


    /**
     * Reads a big-endian unsigned short integer from the buffer.
     */
    static int getUnsignedShort(ChannelBuffer buf, int offset) {
        return (int) ((buf.getByte(offset)     & 0xFF) << 8 |
                      (buf.getByte(offset + 1) & 0xFF));
    }

    /**
     * Reads a big-endian unsigned medium integer from the buffer.
     */
    static int getUnsignedMedium(ChannelBuffer buf, int offset) {
        return (int) ((buf.getByte(offset)     & 0xFF) << 16 |
                      (buf.getByte(offset + 1) & 0xFF) <<  8 |
                      (buf.getByte(offset + 2) & 0xFF));
    }

    /**
     * Reads a big-endian (31-bit) integer from the buffer.
     */
    static int getUnsignedInt(ChannelBuffer buf, int offset) {
        return (int) ((buf.getByte(offset)     & 0x7F) << 24 |
                      (buf.getByte(offset + 1) & 0xFF) << 16 |
                      (buf.getByte(offset + 2) & 0xFF) <<  8 |
                      (buf.getByte(offset + 3) & 0xFF));
    }

    /**
     * Reads a big-endian signed integer from the buffer.
     */
    static int getSignedInt(ChannelBuffer buf, int offset) {
        return (int) ((buf.getByte(offset)     & 0xFF) << 24 |
                      (buf.getByte(offset + 1) & 0xFF) << 16 |
                      (buf.getByte(offset + 2) & 0xFF) <<  8 |
                      (buf.getByte(offset + 3) & 0xFF));
    }

    /**
     * Returns {@code true} if ID is for a server initiated stream or ping.
     */
    static boolean isServerID(int ID) {
        // Server initiated streams and pings have even IDs
        return ID % 2 == 0;
    }

    /**
     * Validate a SPDY header name.
     */
    static void validateHeaderName(String name) {
        if (name == null) {
            throw new NullPointerException("name");
        }
        if (name.length() == 0) {
            throw new IllegalArgumentException(
                    "name cannot be length zero");
        }
        // Since name may only contain ascii characters, for valid names
        // name.length() returns the number of bytes when UTF-8 encoded.
        if (name.length() > SPDY_MAX_NV_LENGTH) {
            throw new IllegalArgumentException(
                    "name exceeds allowable length: " + name);
        }
        for (int i = 0; i < name.length(); i ++) {
            char c = name.charAt(i);
            if (c == 0) {
                throw new IllegalArgumentException(
                        "name contains null character: " + name);
            }
            if (c > 127) {
                throw new IllegalArgumentException(
                        "name contains non-ascii character: " + name);
            }
        }
    }

    /**
     * Validate a SPDY header value. Does not validate max length.
     */
    static void validateHeaderValue(String value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        if (value.length() == 0) {
            throw new IllegalArgumentException(
                    "value cannot be length zero");
        }
        for (int i = 0; i < value.length(); i ++) {
            char c = value.charAt(i);
            if (c == 0) {
                throw new IllegalArgumentException(
                        "value contains null character: " + value);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy