blob: d5ac86c9072d132393c37c9b725f914d12543970 [file] [log] [blame]
simonma77d97062014-07-18 10:22:35 -07001package com.google.net.stubby.newtransport.okhttp;
2
3import com.google.common.util.concurrent.SerializingExecutor;
4import com.google.common.util.concurrent.Service;
5
6import com.squareup.okhttp.internal.spdy.ErrorCode;
7import com.squareup.okhttp.internal.spdy.FrameWriter;
8import com.squareup.okhttp.internal.spdy.Header;
9import com.squareup.okhttp.internal.spdy.Settings;
10
11import okio.Buffer;
12
13import java.io.IOException;
14import java.util.List;
15import java.util.concurrent.Executor;
16
17class AsyncFrameWriter implements FrameWriter {
18 private final FrameWriter frameWriter;
19 private final Executor executor;
20 private final Service transport;
21
22 public AsyncFrameWriter(FrameWriter frameWriter, Service transport, Executor executor) {
23 this.frameWriter = frameWriter;
24 this.transport = transport;
25 // Although writes are thread-safe, we serialize them to prevent consuming many Threads that are
26 // just waiting on each other.
27 this.executor = new SerializingExecutor(executor);
28 }
29
30 @Override
brettmorgan56f5ec32014-07-18 16:54:50 -070031 public void connectionPreface() {
simonma77d97062014-07-18 10:22:35 -070032 executor.execute(new WriteRunnable() {
33 @Override
34 public void doRun() throws IOException {
brettmorgan56f5ec32014-07-18 16:54:50 -070035 frameWriter.connectionPreface();
simonma77d97062014-07-18 10:22:35 -070036 }
37 });
38 }
39
40 @Override
41 public void ackSettings() {
42 executor.execute(new WriteRunnable() {
43 @Override
44 public void doRun() throws IOException {
45 frameWriter.ackSettings();
46 }
47 });
48 }
49
50 @Override
51 public void pushPromise(final int streamId, final int promisedStreamId,
52 final List<Header> requestHeaders) {
53 executor.execute(new WriteRunnable() {
54 @Override
55 public void doRun() throws IOException {
56 frameWriter.pushPromise(streamId, promisedStreamId, requestHeaders);
57 }
58 });
59 }
60
61 @Override
62 public void flush() {
63 executor.execute(new WriteRunnable() {
64 @Override
65 public void doRun() throws IOException {
66 frameWriter.flush();
67 }
68 });
69 }
70
71 @Override
72 public void synStream(final boolean outFinished, final boolean inFinished, final int streamId,
brettmorgan56f5ec32014-07-18 16:54:50 -070073 final int associatedStreamId, final List<Header> headerBlock) {
simonma77d97062014-07-18 10:22:35 -070074 executor.execute(new WriteRunnable() {
75 @Override
76 public void doRun() throws IOException {
brettmorgan56f5ec32014-07-18 16:54:50 -070077 frameWriter.synStream(outFinished, inFinished, streamId, associatedStreamId, headerBlock);
simonma77d97062014-07-18 10:22:35 -070078 }
79 });
80 }
81
82 @Override
83 public void synReply(final boolean outFinished, final int streamId,
84 final List<Header> headerBlock) {
85 executor.execute(new WriteRunnable() {
86 @Override
87 public void doRun() throws IOException {
88 frameWriter.synReply(outFinished, streamId, headerBlock);
89 }
90 });
91 }
92
93 @Override
94 public void headers(final int streamId, final List<Header> headerBlock) {
95 executor.execute(new WriteRunnable() {
96 @Override
97 public void doRun() throws IOException {
98 frameWriter.headers(streamId, headerBlock);
99 }
100 });
101 }
102
103 @Override
104 public void rstStream(final int streamId, final ErrorCode errorCode) {
105 executor.execute(new WriteRunnable() {
106 @Override
107 public void doRun() throws IOException {
108 frameWriter.rstStream(streamId, errorCode);
109 }
110 });
111 }
112
113 @Override
114 public void data(final boolean outFinished, final int streamId, final Buffer source,
115 final int byteCount) {
116 executor.execute(new WriteRunnable() {
117 @Override
118 public void doRun() throws IOException {
119 frameWriter.data(outFinished, streamId, source, byteCount);
120 }
121 });
122 }
123
124 @Override
125 public void data(final boolean outFinished, final int streamId, final Buffer source) {
126 executor.execute(new WriteRunnable() {
127 @Override
128 public void doRun() throws IOException {
129 frameWriter.data(outFinished, streamId, source);
130 }
131 });
132 }
133
134 @Override
135 public void settings(final Settings okHttpSettings) {
136 executor.execute(new WriteRunnable() {
137 @Override
138 public void doRun() throws IOException {
139 frameWriter.settings(okHttpSettings);
140 }
141 });
142 }
143
144 @Override
145 public void ping(final boolean ack, final int payload1, final int payload2) {
146 executor.execute(new WriteRunnable() {
147 @Override
148 public void doRun() throws IOException {
149 frameWriter.ping(ack, payload1, payload2);
150 }
151 });
152 }
153
154 @Override
155 public void goAway(final int lastGoodStreamId, final ErrorCode errorCode,
156 final byte[] debugData) {
157 executor.execute(new WriteRunnable() {
158 @Override
159 public void doRun() throws IOException {
160 frameWriter.goAway(lastGoodStreamId, errorCode, debugData);
161 }
162 });
163 }
164
165 @Override
166 public void windowUpdate(final int streamId, final long windowSizeIncrement) {
167 executor.execute(new WriteRunnable() {
168 @Override
169 public void doRun() throws IOException {
170 frameWriter.windowUpdate(streamId, windowSizeIncrement);
171 }
172 });
173 }
174
175 @Override
176 public void close() {
177 executor.execute(new WriteRunnable() {
178 @Override
179 public void doRun() throws IOException {
180 frameWriter.close();
181 }
182 });
183 }
184
185 private abstract class WriteRunnable implements Runnable {
186 @Override
187 public final void run() {
188 try {
189 doRun();
190 } catch (IOException ex) {
191 transport.stopAsync();
192 throw new RuntimeException(ex);
193 }
194 }
195
196 public abstract void doRun() throws IOException;
197 }
198}