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 package org.apache.hc.client5.http.impl.async;
29
30 import java.io.IOException;
31 import java.net.SocketAddress;
32 import java.nio.ByteBuffer;
33 import java.nio.channels.ByteChannel;
34 import java.nio.channels.SelectionKey;
35 import java.util.concurrent.locks.Lock;
36
37 import org.apache.hc.client5.http.impl.Wire;
38 import org.apache.hc.core5.io.CloseMode;
39 import org.apache.hc.core5.reactor.Command;
40 import org.apache.hc.core5.reactor.IOEventHandler;
41 import org.apache.hc.core5.reactor.IOSession;
42 import org.apache.hc.core5.util.Timeout;
43 import org.slf4j.Logger;
44
45 class LoggingIOSession implements IOSession {
46
47 private final Logger log;
48 private final Wire wireLog;
49 private final String id;
50 private final IOSession session;
51
52 public LoggingIOSession(final IOSession session, final Logger log, final Logger wireLog) {
53 super();
54 this.session = session;
55 this.id = session.getId();
56 this.log = log;
57 this.wireLog = new Wire(wireLog, this.id);
58 }
59
60 @Override
61 public String getId() {
62 return session.getId();
63 }
64
65 @Override
66 public Lock getLock() {
67 return this.session.getLock();
68 }
69
70 @Override
71 public boolean hasCommands() {
72 return this.session.hasCommands();
73 }
74
75 @Override
76 public Command poll() {
77 return this.session.poll();
78 }
79
80 @Override
81 public void enqueue(final Command command, final Command.Priority priority) {
82 this.session.enqueue(command, priority);
83 if (log.isDebugEnabled()) {
84 log.debug("{} Enqueued {} with priority {}", this.session, command.getClass().getSimpleName(), priority);
85 }
86 }
87
88 @Override
89 public ByteChannel channel() {
90 return this.session.channel();
91 }
92
93 @Override
94 public SocketAddress getLocalAddress() {
95 return this.session.getLocalAddress();
96 }
97
98 @Override
99 public SocketAddress getRemoteAddress() {
100 return this.session.getRemoteAddress();
101 }
102
103 @Override
104 public int getEventMask() {
105 return this.session.getEventMask();
106 }
107
108 private static String formatOps(final int ops) {
109 final StringBuilder buffer = new StringBuilder(6);
110 buffer.append('[');
111 if ((ops & SelectionKey.OP_READ) > 0) {
112 buffer.append('r');
113 }
114 if ((ops & SelectionKey.OP_WRITE) > 0) {
115 buffer.append('w');
116 }
117 if ((ops & SelectionKey.OP_ACCEPT) > 0) {
118 buffer.append('a');
119 }
120 if ((ops & SelectionKey.OP_CONNECT) > 0) {
121 buffer.append('c');
122 }
123 buffer.append(']');
124 return buffer.toString();
125 }
126
127 @Override
128 public void setEventMask(final int ops) {
129 this.session.setEventMask(ops);
130 if (log.isDebugEnabled()) {
131 log.debug("{} {}: Event mask set {}", this.id, this.session, formatOps(ops));
132 }
133 }
134
135 @Override
136 public void setEvent(final int op) {
137 this.session.setEvent(op);
138 if (log.isDebugEnabled()) {
139 log.debug("{} {}: Event set {}", this.id, this.session, formatOps(op));
140 }
141 }
142
143 @Override
144 public void clearEvent(final int op) {
145 this.session.clearEvent(op);
146 if (log.isDebugEnabled()) {
147 log.debug("{} {}: Event cleared {}", this.id, this.session, formatOps(op));
148 }
149 }
150
151 @Override
152 public boolean isOpen() {
153 return session.isOpen();
154 }
155
156 @Override
157 public void close() {
158 if (log.isDebugEnabled()) {
159 log.debug("{} {}: Close", this.id, this.session);
160 }
161 this.session.close();
162 }
163
164 @Override
165 public Status getStatus() {
166 return this.session.getStatus();
167 }
168
169 @Override
170 public void close(final CloseMode closeMode) {
171 if (log.isDebugEnabled()) {
172 log.debug("{} {}: Close {}", this.id, this.session, closeMode);
173 }
174 this.session.close(closeMode);
175 }
176
177 @Override
178 public Timeout getSocketTimeout() {
179 return this.session.getSocketTimeout();
180 }
181
182 @Override
183 public void setSocketTimeout(final Timeout timeout) {
184 if (log.isDebugEnabled()) {
185 log.debug("{} {}: Set timeout {}", this.id, this.session, timeout);
186 }
187 this.session.setSocketTimeout(timeout);
188 }
189
190 @Override
191 public long getLastReadTime() {
192 return this.session.getLastReadTime();
193 }
194
195 @Override
196 public long getLastWriteTime() {
197 return this.session.getLastWriteTime();
198 }
199
200 @Override
201 public void updateReadTime() {
202 this.session.updateReadTime();
203 }
204
205 @Override
206 public void updateWriteTime() {
207 this.session.updateWriteTime();
208 }
209
210 @Override
211 public long getLastEventTime() {
212 return this.session.getLastEventTime();
213 }
214
215 @Override
216 public IOEventHandler getHandler() {
217 return this.session.getHandler();
218 }
219
220 @Override
221 public void upgrade(final IOEventHandler handler) {
222 this.session.upgrade(handler);
223 }
224
225 @Override
226 public int read(final ByteBuffer dst) throws IOException {
227 final int bytesRead = this.session.channel().read(dst);
228 if (log.isDebugEnabled()) {
229 log.debug("{} {}: {} bytes read", this.id, this.session, bytesRead);
230 }
231 if (bytesRead > 0 && this.wireLog.isEnabled()) {
232 final ByteBuffer b = dst.duplicate();
233 final int p = b.position();
234 b.limit(p);
235 b.position(p - bytesRead);
236 this.wireLog.input(b);
237 }
238 return bytesRead;
239 }
240
241
242 @Override
243 public int write(final ByteBuffer src) throws IOException {
244 final int byteWritten = session.channel().write(src);
245 if (log.isDebugEnabled()) {
246 log.debug("{} {}: {} bytes written", this.id, this.session, byteWritten);
247 }
248 if (byteWritten > 0 && this.wireLog.isEnabled()) {
249 final ByteBuffer b = src.duplicate();
250 final int p = b.position();
251 b.limit(p);
252 b.position(p - byteWritten);
253 this.wireLog.output(b);
254 }
255 return byteWritten;
256 }
257
258 @Override
259 public String toString() {
260 return this.id + " " + this.session;
261 }
262
263 }