Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docker-java-transport-okhttp/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>docker-java-transport-okhttp</artifactId>
<packaging>bundle</packaging>

<name>docker-java-transport-okhttp</name>
<url>https://github.com/docker-java/docker-java</url>
<description>Java API Client for Docker</description>

<dependencies>
<dependency>
<groupId>${groupId}</groupId>
<artifactId>docker-java-core</artifactId>
<version>${version}</version>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.4</version>
</dependency>

<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.4.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>com.github.dockerjava.okhttp.*</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.github.dockerjava.okhttp;

import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.model.Frame;
import com.github.dockerjava.api.model.StreamType;
import okio.BufferedSource;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.function.Consumer;

class FramedSink implements Consumer<BufferedSource> {

private static final int HEADER_SIZE = 8;

private final ResultCallback<Frame> resultCallback;

FramedSink(ResultCallback<Frame> resultCallback) {
this.resultCallback = resultCallback;
}

@Override
public void accept(BufferedSource source) {
try {
while (!source.exhausted()) {
// See https://docs.docker.com/engine/api/v1.37/#operation/ContainerAttach
// [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT}

if (!source.request(HEADER_SIZE)) {
return;
}
byte[] bytes = source.readByteArray(HEADER_SIZE);

StreamType streamType = streamType(bytes[0]);

if (streamType == StreamType.RAW) {
resultCallback.onNext(new Frame(StreamType.RAW, bytes));
byte[] buffer = new byte[1024];
while (!source.exhausted()) {
int readBytes = source.read(buffer);
if (readBytes != -1) {
resultCallback.onNext(new Frame(StreamType.RAW, Arrays.copyOf(buffer, readBytes)));
}
}
return;
}

int payloadSize = ByteBuffer.wrap(bytes, 4, 4).getInt();
if (!source.request(payloadSize)) {
return;
}
byte[] payload = source.readByteArray(payloadSize);

resultCallback.onNext(new Frame(streamType, payload));
}
} catch (Exception e) {
resultCallback.onError(e);
}
}

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;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.github.dockerjava.okhttp;

import com.sun.jna.platform.win32.Kernel32;

import javax.net.SocketFactory;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;

class NamedPipeSocketFactory extends SocketFactory {

final String socketFileName;

NamedPipeSocketFactory(String socketFileName) {
this.socketFileName = socketFileName;
}

@Override
public Socket createSocket() {
return new Socket() {

RandomAccessFile file;
InputStream is;
OutputStream os;

@Override
public void close() throws IOException {
if (file != null) {
file.close();
file = null;
}
}

@Override
public void connect(SocketAddress endpoint) {
connect(endpoint, 0);
}

@Override
public void connect(SocketAddress endpoint, int timeout) {
long startedAt = System.currentTimeMillis();
timeout = Math.max(timeout, 10_000);
while (true) {
try {
file = new RandomAccessFile(socketFileName, "rw");
break;
} catch (FileNotFoundException e) {
if (System.currentTimeMillis() - startedAt >= timeout) {
throw new RuntimeException(e);
} else {
Kernel32.INSTANCE.WaitNamedPipe(socketFileName, 100);
}
}
}

is = new InputStream() {
@Override
public int read(byte[] bytes, int off, int len) throws IOException {
if (OkHttpInvocationBuilder.CLOSING.get()) {
return 0;
}
return file.read(bytes, off, len);
}

@Override
public int read() throws IOException {
if (OkHttpInvocationBuilder.CLOSING.get()) {
return 0;
}
return file.read();
}

@Override
public int read(byte[] bytes) throws IOException {
if (OkHttpInvocationBuilder.CLOSING.get()) {
return 0;
}
return file.read(bytes);
}
};

os = new OutputStream() {
@Override
public void write(byte[] bytes, int off, int len) throws IOException {
file.write(bytes, off, len);
}

@Override
public void write(int value) throws IOException {
file.write(value);
}

@Override
public void write(byte[] bytes) throws IOException {
file.write(bytes);
}
};
}

@Override
public InputStream getInputStream() {
return is;
}

@Override
public OutputStream getOutputStream() {
return os;
}
};
}

@Override
public Socket createSocket(String s, int i) {
throw new UnsupportedOperationException();
}

@Override
public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) {
throw new UnsupportedOperationException();
}

@Override
public Socket createSocket(InetAddress inetAddress, int i) {
throw new UnsupportedOperationException();
}

@Override
public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) {
throw new UnsupportedOperationException();
}
}
Loading