1 /* |
1 /* |
2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
24 */ |
24 */ |
25 |
25 |
26 package jdk.incubator.http.internal.websocket; |
26 package jdk.incubator.http.internal.websocket; |
27 |
27 |
28 import jdk.incubator.http.WebSocket.MessagePart; |
28 import jdk.incubator.http.WebSocket.MessagePart; |
29 import jdk.incubator.http.internal.common.Log; |
|
30 import jdk.incubator.http.internal.websocket.Frame.Opcode; |
29 import jdk.incubator.http.internal.websocket.Frame.Opcode; |
31 |
30 |
32 import java.nio.ByteBuffer; |
31 import java.nio.ByteBuffer; |
33 import java.nio.CharBuffer; |
32 import java.nio.CharBuffer; |
34 import java.nio.charset.CharacterCodingException; |
33 import java.nio.charset.CharacterCodingException; |
48 * form a message. |
47 * form a message. |
49 */ |
48 */ |
50 /* Non-final for testing purposes only */ |
49 /* Non-final for testing purposes only */ |
51 class FrameConsumer implements Frame.Consumer { |
50 class FrameConsumer implements Frame.Consumer { |
52 |
51 |
|
52 private final static boolean DEBUG = true; |
53 private final MessageStreamConsumer output; |
53 private final MessageStreamConsumer output; |
54 private final UTF8AccumulatingDecoder decoder = new UTF8AccumulatingDecoder(); |
54 private final UTF8AccumulatingDecoder decoder = new UTF8AccumulatingDecoder(); |
55 private boolean fin; |
55 private boolean fin; |
56 private Opcode opcode, originatingOpcode; |
56 private Opcode opcode, originatingOpcode; |
57 private MessagePart part = MessagePart.WHOLE; |
57 private MessagePart part = MessagePart.WHOLE; |
68 return output; |
68 return output; |
69 } |
69 } |
70 |
70 |
71 @Override |
71 @Override |
72 public void fin(boolean value) { |
72 public void fin(boolean value) { |
73 Log.logTrace("Reading fin: {0}", value); |
73 if (DEBUG) { |
|
74 System.out.printf("Reading fin: %s%n", value); |
|
75 } |
74 fin = value; |
76 fin = value; |
75 } |
77 } |
76 |
78 |
77 @Override |
79 @Override |
78 public void rsv1(boolean value) { |
80 public void rsv1(boolean value) { |
79 Log.logTrace("Reading rsv1: {0}", value); |
81 if (DEBUG) { |
|
82 System.out.printf("Reading rsv1: %s%n", value); |
|
83 } |
80 if (value) { |
84 if (value) { |
81 throw new FailWebSocketException("Unexpected rsv1 bit"); |
85 throw new FailWebSocketException("Unexpected rsv1 bit"); |
82 } |
86 } |
83 } |
87 } |
84 |
88 |
85 @Override |
89 @Override |
86 public void rsv2(boolean value) { |
90 public void rsv2(boolean value) { |
87 Log.logTrace("Reading rsv2: {0}", value); |
91 if (DEBUG) { |
|
92 System.out.printf("Reading rsv2: %s%n", value); |
|
93 } |
88 if (value) { |
94 if (value) { |
89 throw new FailWebSocketException("Unexpected rsv2 bit"); |
95 throw new FailWebSocketException("Unexpected rsv2 bit"); |
90 } |
96 } |
91 } |
97 } |
92 |
98 |
93 @Override |
99 @Override |
94 public void rsv3(boolean value) { |
100 public void rsv3(boolean value) { |
95 Log.logTrace("Reading rsv3: {0}", value); |
101 if (DEBUG) { |
|
102 System.out.printf("Reading rsv3: %s%n", value); |
|
103 } |
96 if (value) { |
104 if (value) { |
97 throw new FailWebSocketException("Unexpected rsv3 bit"); |
105 throw new FailWebSocketException("Unexpected rsv3 bit"); |
98 } |
106 } |
99 } |
107 } |
100 |
108 |
101 @Override |
109 @Override |
102 public void opcode(Opcode v) { |
110 public void opcode(Opcode v) { |
103 Log.logTrace("Reading opcode: {0}", v); |
111 if (DEBUG) { |
|
112 System.out.printf("Reading opcode: %s%n", v); |
|
113 } |
104 if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) { |
114 if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) { |
105 if (!fin) { |
115 if (!fin) { |
106 throw new FailWebSocketException("Fragmented control frame " + v); |
116 throw new FailWebSocketException("Fragmented control frame " + v); |
107 } |
117 } |
108 opcode = v; |
118 opcode = v; |
120 throw new FailWebSocketException( |
130 throw new FailWebSocketException( |
121 format("Unexpected frame %s (fin=%s)", v, fin)); |
131 format("Unexpected frame %s (fin=%s)", v, fin)); |
122 } |
132 } |
123 opcode = v; |
133 opcode = v; |
124 } else { |
134 } else { |
125 throw new FailWebSocketException("Unknown opcode " + v); |
135 throw new FailWebSocketException("Unexpected opcode " + v); |
126 } |
136 } |
127 } |
137 } |
128 |
138 |
129 @Override |
139 @Override |
130 public void mask(boolean value) { |
140 public void mask(boolean value) { |
131 Log.logTrace("Reading mask: {0}", value); |
141 if (DEBUG) { |
|
142 System.out.printf("Reading mask: %s%n", value); |
|
143 } |
132 if (value) { |
144 if (value) { |
133 throw new FailWebSocketException("Masked frame received"); |
145 throw new FailWebSocketException("Masked frame received"); |
134 } |
146 } |
135 } |
147 } |
136 |
148 |
137 @Override |
149 @Override |
138 public void payloadLen(long value) { |
150 public void payloadLen(long value) { |
139 Log.logTrace("Reading payloadLen: {0}", value); |
151 if (DEBUG) { |
|
152 System.out.printf("Reading payloadLen: %s%n", value); |
|
153 } |
140 if (opcode.isControl()) { |
154 if (opcode.isControl()) { |
141 if (value > 125) { |
155 if (value > 125) { |
142 throw new FailWebSocketException( |
156 throw new FailWebSocketException( |
143 format("%s's payload length %s", opcode, value)); |
157 format("%s's payload length %s", opcode, value)); |
144 } |
158 } |
162 throw new InternalError(); |
176 throw new InternalError(); |
163 } |
177 } |
164 |
178 |
165 @Override |
179 @Override |
166 public void payloadData(ByteBuffer data) { |
180 public void payloadData(ByteBuffer data) { |
167 Log.logTrace("Reading payloadData: data={0}", data); |
181 if (DEBUG) { |
|
182 System.out.printf("Reading payloadData: %s%n", data); |
|
183 } |
168 unconsumedPayloadLen -= data.remaining(); |
184 unconsumedPayloadLen -= data.remaining(); |
169 boolean isLast = unconsumedPayloadLen == 0; |
185 boolean isLast = unconsumedPayloadLen == 0; |
170 if (opcode.isControl()) { |
186 if (opcode.isControl()) { |
171 if (binaryData != null) { // An intermediate or the last chunk |
187 if (binaryData != null) { // An intermediate or the last chunk |
172 binaryData.put(data); |
188 binaryData.put(data); |