use of okio.BufferedSink in project okhttp by square.
the class RealWebSocket method writeOneFrame.
/**
* Attempts to remove a single frame from a queue and send it. This prefers to write urgent pongs
* before less urgent messages and close frames. For example it's possible that a caller will
* enqueue messages followed by pongs, but this sends pongs followed by messages. Pongs are always
* written in the order they were enqueued.
*
* <p>If a frame cannot be sent - because there are none enqueued or because the web socket is not
* connected - this does nothing and returns false. Otherwise this returns true and the caller
* should immediately invoke this method again until it returns false.
*
* <p>This method may only be invoked by the writer thread. There may be only thread invoking this
* method at a time.
*/
boolean writeOneFrame() throws IOException {
WebSocketWriter writer;
ByteString pong;
Object messageOrClose = null;
int receivedCloseCode = -1;
String receivedCloseReason = null;
Streams streamsToClose = null;
synchronized (RealWebSocket.this) {
if (failed) {
// Failed web socket.
return false;
}
writer = this.writer;
pong = pongQueue.poll();
if (pong == null) {
messageOrClose = messageAndCloseQueue.poll();
if (messageOrClose instanceof Close) {
receivedCloseCode = this.receivedCloseCode;
receivedCloseReason = this.receivedCloseReason;
if (receivedCloseCode != -1) {
streamsToClose = this.streams;
this.streams = null;
this.executor.shutdown();
} else {
// When we request a graceful close also schedule a cancel of the websocket.
cancelFuture = executor.schedule(new CancelRunnable(), ((Close) messageOrClose).cancelAfterCloseMillis, MILLISECONDS);
}
} else if (messageOrClose == null) {
// The queue is exhausted.
return false;
}
}
}
try {
if (pong != null) {
writer.writePong(pong);
} else if (messageOrClose instanceof Message) {
ByteString data = ((Message) messageOrClose).data;
BufferedSink sink = Okio.buffer(writer.newMessageSink(((Message) messageOrClose).formatOpcode, data.size()));
sink.write(data);
sink.close();
synchronized (this) {
queueSize -= data.size();
}
} else if (messageOrClose instanceof Close) {
Close close = (Close) messageOrClose;
writer.writeClose(close.code, close.reason);
// We closed the writer: now both reader and writer are closed.
if (streamsToClose != null) {
listener.onClosed(this, receivedCloseCode, receivedCloseReason);
}
} else {
throw new AssertionError();
}
return true;
} finally {
closeQuietly(streamsToClose);
}
}
use of okio.BufferedSink in project okhttp by square.
the class RequestBody method create.
/** Returns a new request body that transmits the content of {@code file}. */
public static RequestBody create(final MediaType contentType, final File file) {
if (file == null)
throw new NullPointerException("content == null");
return new RequestBody() {
@Override
public MediaType contentType() {
return contentType;
}
@Override
public long contentLength() {
return file.length();
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
Source source = null;
try {
source = Okio.source(file);
sink.writeAll(source);
} finally {
Util.closeQuietly(source);
}
}
};
}
use of okio.BufferedSink in project okhttp by square.
the class PublicSuffixListGenerator method main.
public static void main(String... args) throws IOException {
OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().url("https://publicsuffix.org/list/public_suffix_list.dat").build();
SortedSet<ByteString> sortedRules = new TreeSet<>();
SortedSet<ByteString> sortedExceptionRules = new TreeSet<>();
try (Response response = client.newCall(request).execute()) {
BufferedSource source = response.body().source();
int totalRuleBytes = 0;
int totalExceptionRuleBytes = 0;
while (!source.exhausted()) {
String line = source.readUtf8LineStrict();
if (line.trim().isEmpty() || line.startsWith("//"))
continue;
if (line.contains(WILDCARD_CHAR)) {
assertWildcardRule(line);
}
ByteString rule = ByteString.encodeUtf8(line);
if (rule.startsWith(EXCEPTION_RULE_MARKER)) {
rule = rule.substring(1);
// We use '\n' for end of value.
totalExceptionRuleBytes += rule.size() + 1;
sortedExceptionRules.add(rule);
} else {
// We use '\n' for end of value.
totalRuleBytes += rule.size() + 1;
sortedRules.add(rule);
}
}
File resources = new File(OKHTTP_RESOURCE_DIR);
if (!resources.mkdirs() && !resources.exists()) {
throw new RuntimeException("Unable to create resource directory!");
}
Sink fileSink = Okio.sink(new File(resources, PublicSuffixDatabase.PUBLIC_SUFFIX_RESOURCE));
try (BufferedSink sink = Okio.buffer(new GzipSink(fileSink))) {
sink.writeInt(totalRuleBytes);
for (ByteString domain : sortedRules) {
sink.write(domain).writeByte('\n');
}
sink.writeInt(totalExceptionRuleBytes);
for (ByteString domain : sortedExceptionRules) {
sink.write(domain).writeByte('\n');
}
}
}
}
use of okio.BufferedSink in project okhttp by square.
the class CacheInterceptor method cacheWritingResponse.
/**
* Returns a new source that writes bytes to {@code cacheRequest} as they are read by the source
* consumer. This is careful to discard bytes left over when the stream is closed; otherwise we
* may never exhaust the source stream and therefore not complete the cached response.
*/
private Response cacheWritingResponse(final CacheRequest cacheRequest, Response response) throws IOException {
// Some apps return a null body; for compatibility we treat that like a null cache request.
if (cacheRequest == null)
return response;
Sink cacheBodyUnbuffered = cacheRequest.body();
if (cacheBodyUnbuffered == null)
return response;
final BufferedSource source = response.body().source();
final BufferedSink cacheBody = Okio.buffer(cacheBodyUnbuffered);
Source cacheWritingSource = new Source() {
boolean cacheRequestClosed;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead;
try {
bytesRead = source.read(sink, byteCount);
} catch (IOException e) {
if (!cacheRequestClosed) {
cacheRequestClosed = true;
// Failed to write a complete cache response.
cacheRequest.abort();
}
throw e;
}
if (bytesRead == -1) {
if (!cacheRequestClosed) {
cacheRequestClosed = true;
// The cache response is complete!
cacheBody.close();
}
return -1;
}
sink.copyTo(cacheBody.buffer(), sink.size() - bytesRead, bytesRead);
cacheBody.emitCompleteSegments();
return bytesRead;
}
@Override
public Timeout timeout() {
return source.timeout();
}
@Override
public void close() throws IOException {
if (!cacheRequestClosed && !discard(this, HttpCodec.DISCARD_STREAM_TIMEOUT_MILLIS, MILLISECONDS)) {
cacheRequestClosed = true;
cacheRequest.abort();
}
source.close();
}
};
return response.newBuilder().body(new RealResponseBody(response.headers(), Okio.buffer(cacheWritingSource))).build();
}
use of okio.BufferedSink in project okhttp by square.
the class Http2Server method send404.
private void send404(Http2Stream stream, String path) throws IOException {
List<Header> responseHeaders = Arrays.asList(new Header(":status", "404"), new Header(":version", "HTTP/1.1"), new Header("content-type", "text/plain"));
stream.sendResponseHeaders(responseHeaders, true);
BufferedSink out = Okio.buffer(stream.getSink());
out.writeUtf8("Not found: " + path);
out.close();
}
Aggregations