< prev index next >
1 /*
2 * Copyright (c) 2015, 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 */
24 package java.net.http;
25
26 import java.io.IOException;
27 import java.nio.ByteBuffer;
28
29 /**
30 * When sending a frame, the length field must be set in sub-class
31 * by calling setLength()
32 */
33 abstract class Http2Frame {
34
35 int length = -1;
36 int type;
37 int streamid;
38 int flags;
39
40 // called when reading in only
41 void initCommon(int length, int type, int streamid, int flags) {
42 this.length = length;
43 this.type = type;
44 this.streamid = streamid;
45 this.flags = flags;
46 }
47
48 public int length() {
49 return length;
50 }
51
52 public int type() {
53 return type;
54 }
55
56 public int streamid() {
57 return streamid;
58 }
59
60 public void setFlag(int flag) {
61 flags |= flag;
62 }
63
64 public void setFlags(int flags) {
65 this.flags = flags;
66 }
67
68 public int getFlags() {
69 return flags;
70 }
71
72 public boolean getFlag(int flag) {
73 return (flags & flag) != 0;
74 }
75
76 public void clearFlag(int flag) {
77 flags &= 0xffffffff ^ flag;
78 }
79
80 public void streamid(int streamid) {
81 this.streamid = streamid;
82 }
83
84 abstract void readIncomingImpl(ByteBufferConsumer bc) throws IOException;
85
86 /**
87 * assume given array contains at least one complete frame.
88 */
89 static Http2Frame readIncoming(ByteBufferConsumer bc) throws IOException {
90 int x = bc.getInt();
91 int length = x >> 8;
92 int type = x & 0xff;
93 int flags = bc.getByte();
94 int streamid = bc.getInt();
95 Http2Frame f = null;
96 switch (type) {
97 case DataFrame.TYPE:
98 f = new DataFrame();
99 break;
100 case HeadersFrame.TYPE:
101 f = new HeadersFrame();
102 break;
103 case ContinuationFrame.TYPE:
104 f = new ContinuationFrame();
105 break;
106 case ResetFrame.TYPE:
107 f = new ResetFrame();
108 break;
109 case PriorityFrame.TYPE:
110 f = new PriorityFrame();
111 break;
112 case SettingsFrame.TYPE:
113 f = new SettingsFrame();
114 break;
115 case GoAwayFrame.TYPE:
116 f = new GoAwayFrame();
117 break;
118 case PingFrame.TYPE:
119 f = new PingFrame();
120 break;
121 case PushPromiseFrame.TYPE:
122 f = new PushPromiseFrame();
123 break;
124 case WindowUpdateFrame.TYPE:
125 f = new WindowUpdateFrame();
126 break;
127 default:
128 String msg = Integer.toString(type);
129 throw new IOException("unknown frame type " + msg);
130 }
131 f.initCommon(length, type, streamid, flags);
132 f.readIncomingImpl(bc);
133 return f;
134 }
135
136 public String typeAsString() {
137 return asString(this.type);
138 }
139
140 public static String asString(int type) {
141 switch (type) {
142 case DataFrame.TYPE:
143 return "DATA";
144 case HeadersFrame.TYPE:
145 return "HEADERS";
146 case ContinuationFrame.TYPE:
147 return "CONTINUATION";
148 case ResetFrame.TYPE:
149 return "RESET";
150 case PriorityFrame.TYPE:
151 return "PRIORITY";
152 case SettingsFrame.TYPE:
153 return "SETTINGS";
154 case GoAwayFrame.TYPE:
155 return "GOAWAY";
156 case PingFrame.TYPE:
157 return "PING";
158 case PushPromiseFrame.TYPE:
159 return "PUSH_PROMISE";
160 case WindowUpdateFrame.TYPE:
161 return "WINDOW_UPDATE";
162 default:
163 return "UNKNOWN";
164 }
165 }
166
167 @Override
168 public String toString() {
169 StringBuilder sb = new StringBuilder();
170 sb.append(typeAsString())
171 .append(": length=")
172 .append(Integer.toString(length))
173 .append(", streamid=")
174 .append(streamid)
175 .append(", flags=");
176
177 int f = flags;
178 int i = 0;
179 if (f == 0) {
180 sb.append("0 ");
181 } else {
182 while (f != 0) {
183 if ((f & 1) == 1) {
184 sb.append(flagAsString(1 << i))
185 .append(' ');
186 }
187 f = f >> 1;
188 i++;
189 }
190 }
191 return sb.toString();
192 }
193
194 // Override
195 String flagAsString(int f) {
196 return "unknown";
197 }
198
199 abstract void setLength();
200
201 void writeOutgoing(ByteBufferGenerator bg) {
202 if (length == -1) {
203 throw new InternalError("Length not set on outgoing frame");
204 }
205 ByteBuffer buf = bg.getBuffer(9);
206 int x = (length << 8) + type;
207 buf.putInt(x);
208 buf.put((byte)flags);
209 buf.putInt(streamid);
210 }
211 }
< prev index next >