forked from docker-java/docker-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFrameReader.java
More file actions
109 lines (82 loc) · 3.18 KB
/
Copy pathFrameReader.java
File metadata and controls
109 lines (82 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package com.github.dockerjava.core.command;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import com.github.dockerjava.api.model.Frame;
import com.github.dockerjava.api.model.StreamType;
import javax.annotation.CheckForNull;
/**
* Breaks the input into frame. Similar to how a buffered reader would readLies.
* <p/>
* See: {@link }http://docs.docker.com/v1.6/reference/api/docker_remote_api_v1.13/#attach-to-a-container}
*/
public class FrameReader implements AutoCloseable {
private static final int HEADER_SIZE = 8;
private final byte[] rawBuffer = new byte[1000];
private final InputStream inputStream;
private Boolean rawStreamDetected = false;
public FrameReader(InputStream inputStream) {
this.inputStream = inputStream;
}
private static StreamType streamType(byte streamType) {
switch (streamType) {
case 0:
return StreamType.STDIN;
case 1:
return StreamType.STDOUT;
case 2:
return StreamType.STDERR;
default:
return StreamType.RAW;
}
}
/**
* @return A frame, or null if no more frames.
*/
@CheckForNull
public Frame readFrame() throws IOException {
if (rawStreamDetected) {
int read = inputStream.read(rawBuffer);
if (read == -1) {
return null;
}
return new Frame(StreamType.RAW, Arrays.copyOf(rawBuffer, read));
} else {
byte[] header = new byte[HEADER_SIZE];
int actualHeaderSize = 0;
do {
int headerCount = inputStream.read(header, actualHeaderSize, HEADER_SIZE - actualHeaderSize);
if (headerCount == -1) {
return null;
}
actualHeaderSize += headerCount;
} while (actualHeaderSize < HEADER_SIZE);
// HexDump.dump(header, 0, System.err, 0);
StreamType streamType = streamType(header[0]);
if (streamType.equals(StreamType.RAW)) {
rawStreamDetected = true;
return new Frame(StreamType.RAW, Arrays.copyOf(header, HEADER_SIZE));
}
int payloadSize = ((header[4] & 0xff) << 24) + ((header[5] & 0xff) << 16) + ((header[6] & 0xff) << 8)
+ (header[7] & 0xff);
byte[] payload = new byte[payloadSize];
int actualPayloadSize = 0;
do {
int count = inputStream.read(payload, actualPayloadSize, payloadSize - actualPayloadSize);
if (count == -1) {
if (actualPayloadSize != payloadSize) {
throw new IOException(String.format("payload must be %d bytes long, but was %d", payloadSize,
actualPayloadSize));
}
break;
}
actualPayloadSize += count;
} while (actualPayloadSize < payloadSize);
return new Frame(streamType, payload);
}
}
@Override
public void close() throws IOException {
inputStream.close();
}
}