Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9e56dce

Browse files
add frame fragmentation support (continuation)
1 parent d8853a9 commit 9e56dce

File tree

1 file changed

+45
-14
lines changed

1 file changed

+45
-14
lines changed

‎src/main/java/tech/gusavila92/websocketclient/WebSocketClient.java

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -943,17 +943,28 @@ private void send(int opcode, byte[] payload) throws IOException {
943943
* @throws IOException
944944
*/
945945
private void read() throws IOException {
946+
// If message contains fragmented parts we should put it all together.
947+
LinkedList<byte[]> messageParts = new LinkedList<byte[]>();
948+
946949
// The first byte of every data frame
947950
int firstByte;
951+
int opcode = 0;
948952

949953
// Loop until end of stream is reached.
950954
while ((firstByte = bis.read()) != -1) {
951955
// Data contained in the first byte
952-
// int fin = (firstByte << 24) >>> 31;
956+
// If the flag is on we have more frames for this message.
957+
int fin = (firstByte << 24) >>> 31;
953958
// int rsv1 = (firstByte << 25) >>> 31;
954959
// int rsv2 = (firstByte << 26) >>> 31;
955960
// int rsv3 = (firstByte << 27) >>> 31;
956-
int opcode = (firstByte << 28) >>> 28;
961+
962+
// Only first frame will have real opcode (text or binary),
963+
// In next frames opcode will be zero (continuation)
964+
if (messageParts.isEmpty())
965+
opcode = (firstByte << 28) >>> 28;
966+
967+
boolean isLast = fin == 1;
957968

958969
// Reads the second byte
959970
int secondByte = bis.read();
@@ -969,10 +980,7 @@ private void read() throws IOException {
969980
if (payloadLength == 126) {
970981
// Attempts to read the next 2 bytes
971982
byte[] nextTwoBytes = new byte[2];
972-
for (int i = 0; i < 2; i++) {
973-
byte b = (byte) bis.read();
974-
nextTwoBytes[i] = b;
975-
}
983+
if (bis.read(nextTwoBytes) == -1) break;
976984

977985
// Those last 2 bytes will be interpreted as a 16-bit
978986
// unsigned
@@ -982,10 +990,7 @@ private void read() throws IOException {
982990
} else if (payloadLength == 127) {
983991
// Attempts to read the next 8 bytes
984992
byte[] nextEightBytes = new byte[8];
985-
for (int i = 0; i < 8; i++) {
986-
byte b = (byte) bis.read();
987-
nextEightBytes[i] = b;
988-
}
993+
if (bis.read(nextEightBytes) == -1) break;
989994

990995
// Only the last 4 bytes matter because Java doesn't support
991996
// arrays with more than 2^31 -1 elements, so a 64-bit
@@ -1001,15 +1006,41 @@ private void read() throws IOException {
10011006

10021007
// Attempts to read the payload data
10031008
byte[] data = new byte[payloadLength];
1004-
for (int i = 0; i < payloadLength; i++) {
1005-
byte b = (byte) bis.read();
1006-
data[i] = b;
1009+
if (bis.read(data) == -1) break;
1010+
1011+
if (isLast) {
1012+
// If we already have some fragments, just add last and put it together
1013+
if (!messageParts.isEmpty()) {
1014+
messageParts.add(data);
1015+
// Calculate total size of all parts
1016+
int fullSize = 0;
1017+
int offset = 0;
1018+
for (byte[] fragment : messageParts)
1019+
fullSize += fragment.length;
1020+
1021+
byte[] fullMessage = new byte[fullSize];
1022+
1023+
// Copy all parts into one array
1024+
for (byte[] fragment : messageParts) {
1025+
System.arraycopy(fragment, 0, fullMessage, offset, fragment.length);
1026+
offset += fragment.length;
1027+
}
1028+
1029+
data = fullMessage;
1030+
messageParts.clear();
1031+
}
1032+
// else: Single framed message - do nothing
1033+
} else {
1034+
// Collect this fragment and go read next frame.
1035+
messageParts.add(data);
1036+
continue;
10071037
}
10081038

10091039
// Execute the action depending on the opcode
10101040
switch (opcode) {
10111041
case OPCODE_CONTINUATION:
1012-
// Should be implemented
1042+
// Implemented above
1043+
// I think this case should never happen
10131044
break;
10141045
case OPCODE_TEXT:
10151046
notifyOnTextReceived(new String(data, Charset.forName("UTF-8")));

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /