StatusCodes.java revision 16234:3b25414eb6af
1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.incubator.http.internal.websocket;
27
28import static jdk.incubator.http.WebSocket.CLOSED_ABNORMALLY;
29
30/*
31 * Utilities and common constants for WebSocket status codes. For more details
32 * on status codes and their meaning see:
33 *
34 *     1. https://tools.ietf.org/html/rfc6455#section-7.4
35 *     2. http://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number
36 */
37final class StatusCodes {
38
39    static final int PROTOCOL_ERROR        = 1002;
40    static final int CANNOT_ACCEPT         = 1003;
41    static final int NO_STATUS_CODE        = 1005;
42    static final int NOT_CONSISTENT        = 1007;
43    static final int TOO_BIG               = 1009;
44    static final int NO_EXTENSION          = 1010;
45    static final int SERVICE_RESTART       = 1012;
46    static final int TRY_AGAIN_LATER       = 1013;
47    static final int TLS_HANDSHAKE_FAILURE = 1015;
48
49    private StatusCodes() { }
50
51    /*
52     * Returns the given code if it doesn't violate any rules for outgoing
53     * codes, otherwise throws a CFE with a detailed description.
54     */
55    static int checkOutgoingCode(int code) {
56        checkCommon(code);
57        if (code > 4999) {
58            throw new CheckFailedException("Unspecified: " + code);
59        }
60        if (isNotUserSettable(code)) {
61            throw new CheckFailedException("Cannot set: " + code);
62        }
63        return code;
64    }
65
66    /*
67     * Returns the given code if it doesn't violate any rules for incoming
68     * codes, otherwise throws a CFE with a detailed description.
69     */
70    static int checkIncomingCode(int code) {
71        checkCommon(code);
72        if (code == NO_EXTENSION) {
73            throw new CheckFailedException("Bad server code: " + code);
74        }
75        return code;
76    }
77
78    private static int checkCommon(int code) {
79        if (isOutOfRange(code)) {
80            throw new CheckFailedException("Out of range: " + code);
81        }
82        if (isForbidden(code)) {
83            throw new CheckFailedException("Forbidden: " + code);
84        }
85        if (isUnassigned(code)) {
86            throw new CheckFailedException("Unassigned: " + code);
87        }
88        return code;
89    }
90
91    /*
92     * Returns true if the given code cannot be set by a user of the WebSocket
93     * API. e.g. this code means something which only a WebSocket implementation
94     * is responsible for or it doesn't make sense to be send by a WebSocket
95     * client.
96     */
97    private static boolean isNotUserSettable(int code) {
98        switch (code) {
99            case PROTOCOL_ERROR:
100            case CANNOT_ACCEPT:
101            case NOT_CONSISTENT:
102            case TOO_BIG:
103            case NO_EXTENSION:
104            case TRY_AGAIN_LATER:
105            case SERVICE_RESTART:
106                return true;
107            default:
108                return false;
109        }
110    }
111
112    /*
113     * Returns true if the given code cannot appear on the wire. It's always an
114     * error to send a frame with such a code or to receive one.
115     */
116    private static boolean isForbidden(int code) {
117        switch (code) {
118            case NO_STATUS_CODE:
119            case CLOSED_ABNORMALLY:
120            case TLS_HANDSHAKE_FAILURE:
121                return true;
122            default:
123                return false;
124        }
125    }
126
127    /*
128     * Returns true if the given code has no known meaning under the WebSocket
129     * specification (i.e. unassigned/undefined).
130     */
131    private static boolean isUnassigned(int code) {
132        return (code >= 1016 && code <= 2999) || code == 1004 || code == 1014;
133    }
134
135    /*
136     * Returns true if the given code is not in domain of status codes:
137     *
138     * 2-byte unsigned integer minus first 1000 numbers from the range [0, 999]
139     * that are never used.
140     */
141    private static boolean isOutOfRange(int code) {
142        return code < 1000 || code > 65535;
143    }
144}
145