52 { |
52 { |
53 |
53 |
54 // The channel being adapted |
54 // The channel being adapted |
55 private final SocketChannelImpl sc; |
55 private final SocketChannelImpl sc; |
56 |
56 |
57 // Option adaptor object, created on demand |
|
58 private volatile OptionAdaptor opts = null; |
|
59 |
|
60 // Timeout "option" value for reads |
57 // Timeout "option" value for reads |
61 private volatile int timeout = 0; |
58 private volatile int timeout = 0; |
62 |
|
63 // Traffic-class/Type-of-service |
|
64 private volatile int trafficClass = 0; |
|
65 |
|
66 |
59 |
67 // ## super will create a useless impl |
60 // ## super will create a useless impl |
68 private SocketAdaptor(SocketChannelImpl sc) { |
61 private SocketAdaptor(SocketChannelImpl sc) { |
69 this.sc = sc; |
62 this.sc = sc; |
70 } |
63 } |
143 |
136 |
144 } |
137 } |
145 |
138 |
146 public void bind(SocketAddress local) throws IOException { |
139 public void bind(SocketAddress local) throws IOException { |
147 try { |
140 try { |
148 if (local == null) |
|
149 local = new InetSocketAddress(0); |
|
150 sc.bind(local); |
141 sc.bind(local); |
151 } catch (Exception x) { |
142 } catch (Exception x) { |
152 Net.translateException(x); |
143 Net.translateException(x); |
153 } |
144 } |
154 } |
145 } |
155 |
146 |
156 public InetAddress getInetAddress() { |
147 public InetAddress getInetAddress() { |
157 if (!sc.isConnected()) |
148 SocketAddress remote = sc.remoteAddress(); |
|
149 if (remote == null) { |
158 return null; |
150 return null; |
159 return Net.asInetSocketAddress(sc.remoteAddress()).getAddress(); |
151 } else { |
|
152 return ((InetSocketAddress)remote).getAddress(); |
|
153 } |
160 } |
154 } |
161 |
155 |
162 public InetAddress getLocalAddress() { |
156 public InetAddress getLocalAddress() { |
163 if (!sc.isBound()) |
157 if (sc.isOpen()) { |
164 return new InetSocketAddress(0).getAddress(); |
158 SocketAddress local = sc.localAddress(); |
165 return Net.asInetSocketAddress(sc.localAddress()).getAddress(); |
159 if (local != null) |
|
160 return ((InetSocketAddress)local).getAddress(); |
|
161 } |
|
162 return new InetSocketAddress(0).getAddress(); |
166 } |
163 } |
167 |
164 |
168 public int getPort() { |
165 public int getPort() { |
169 if (!sc.isConnected()) |
166 SocketAddress remote = sc.remoteAddress(); |
|
167 if (remote == null) { |
170 return 0; |
168 return 0; |
171 return Net.asInetSocketAddress(sc.remoteAddress()).getPort(); |
169 } else { |
|
170 return ((InetSocketAddress)remote).getPort(); |
|
171 } |
172 } |
172 } |
173 |
173 |
174 public int getLocalPort() { |
174 public int getLocalPort() { |
175 if (!sc.isBound()) |
175 SocketAddress local = sc.localAddress(); |
|
176 if (local == null) { |
176 return -1; |
177 return -1; |
177 return Net.asInetSocketAddress(sc.localAddress()).getPort(); |
178 } else { |
|
179 return ((InetSocketAddress)local).getPort(); |
|
180 } |
178 } |
181 } |
179 |
182 |
180 private class SocketInputStream |
183 private class SocketInputStream |
181 extends ChannelInputStream |
184 extends ChannelInputStream |
182 { |
185 { |
274 throw (IOException)e.getException(); |
277 throw (IOException)e.getException(); |
275 } |
278 } |
276 return os; |
279 return os; |
277 } |
280 } |
278 |
281 |
279 private OptionAdaptor opts() { |
282 private void setBooleanOption(SocketOption<Boolean> name, boolean value) |
280 if (opts == null) |
283 throws SocketException |
281 opts = new OptionAdaptor(sc); |
284 { |
282 return opts; |
285 try { |
|
286 sc.setOption(name, value); |
|
287 } catch (IOException x) { |
|
288 Net.translateToSocketException(x); |
|
289 } |
|
290 } |
|
291 |
|
292 private void setIntOption(SocketOption<Integer> name, int value) |
|
293 throws SocketException |
|
294 { |
|
295 try { |
|
296 sc.setOption(name, value); |
|
297 } catch (IOException x) { |
|
298 Net.translateToSocketException(x); |
|
299 } |
|
300 } |
|
301 |
|
302 private boolean getBooleanOption(SocketOption<Boolean> name) throws SocketException { |
|
303 try { |
|
304 return sc.getOption(name).booleanValue(); |
|
305 } catch (IOException x) { |
|
306 Net.translateToSocketException(x); |
|
307 return false; // keep compiler happy |
|
308 } |
|
309 } |
|
310 |
|
311 private int getIntOption(SocketOption<Integer> name) throws SocketException { |
|
312 try { |
|
313 return sc.getOption(name).intValue(); |
|
314 } catch (IOException x) { |
|
315 Net.translateToSocketException(x); |
|
316 return -1; // keep compiler happy |
|
317 } |
283 } |
318 } |
284 |
319 |
285 public void setTcpNoDelay(boolean on) throws SocketException { |
320 public void setTcpNoDelay(boolean on) throws SocketException { |
286 opts().setTcpNoDelay(on); |
321 setBooleanOption(StandardSocketOption.TCP_NODELAY, on); |
287 } |
322 } |
288 |
323 |
289 public boolean getTcpNoDelay() throws SocketException { |
324 public boolean getTcpNoDelay() throws SocketException { |
290 return opts().getTcpNoDelay(); |
325 return getBooleanOption(StandardSocketOption.TCP_NODELAY); |
291 } |
326 } |
292 |
327 |
293 public void setSoLinger(boolean on, int linger) throws SocketException { |
328 public void setSoLinger(boolean on, int linger) throws SocketException { |
294 opts().setSoLinger(on, linger); |
329 if (!on) |
|
330 linger = -1; |
|
331 setIntOption(StandardSocketOption.SO_LINGER, linger); |
295 } |
332 } |
296 |
333 |
297 public int getSoLinger() throws SocketException { |
334 public int getSoLinger() throws SocketException { |
298 return opts().getSoLinger(); |
335 return getIntOption(StandardSocketOption.SO_LINGER); |
299 } |
336 } |
300 |
337 |
301 public void sendUrgentData(int data) throws IOException { |
338 public void sendUrgentData(int data) throws IOException { |
302 throw new SocketException("Urgent data not supported"); |
339 throw new SocketException("Urgent data not supported"); |
303 } |
340 } |
304 |
341 |
305 public void setOOBInline(boolean on) throws SocketException { |
342 public void setOOBInline(boolean on) throws SocketException { |
306 opts().setOOBInline(on); |
343 setBooleanOption(ExtendedSocketOption.SO_OOBINLINE, on); |
307 } |
344 } |
308 |
345 |
309 public boolean getOOBInline() throws SocketException { |
346 public boolean getOOBInline() throws SocketException { |
310 return opts().getOOBInline(); |
347 return getBooleanOption(ExtendedSocketOption.SO_OOBINLINE); |
311 } |
348 } |
312 |
349 |
313 public void setSoTimeout(int timeout) throws SocketException { |
350 public void setSoTimeout(int timeout) throws SocketException { |
314 if (timeout < 0) |
351 if (timeout < 0) |
315 throw new IllegalArgumentException("timeout can't be negative"); |
352 throw new IllegalArgumentException("timeout can't be negative"); |
319 public int getSoTimeout() throws SocketException { |
356 public int getSoTimeout() throws SocketException { |
320 return timeout; |
357 return timeout; |
321 } |
358 } |
322 |
359 |
323 public void setSendBufferSize(int size) throws SocketException { |
360 public void setSendBufferSize(int size) throws SocketException { |
324 opts().setSendBufferSize(size); |
361 // size 0 valid for SocketChannel, invalid for Socket |
|
362 if (size <= 0) |
|
363 throw new IllegalArgumentException("Invalid send size"); |
|
364 setIntOption(StandardSocketOption.SO_SNDBUF, size); |
325 } |
365 } |
326 |
366 |
327 public int getSendBufferSize() throws SocketException { |
367 public int getSendBufferSize() throws SocketException { |
328 return opts().getSendBufferSize(); |
368 return getIntOption(StandardSocketOption.SO_SNDBUF); |
329 } |
369 } |
330 |
370 |
331 public void setReceiveBufferSize(int size) throws SocketException { |
371 public void setReceiveBufferSize(int size) throws SocketException { |
332 opts().setReceiveBufferSize(size); |
372 // size 0 valid for SocketChannel, invalid for Socket |
|
373 if (size <= 0) |
|
374 throw new IllegalArgumentException("Invalid receive size"); |
|
375 setIntOption(StandardSocketOption.SO_RCVBUF, size); |
333 } |
376 } |
334 |
377 |
335 public int getReceiveBufferSize() throws SocketException { |
378 public int getReceiveBufferSize() throws SocketException { |
336 return opts().getReceiveBufferSize(); |
379 return getIntOption(StandardSocketOption.SO_RCVBUF); |
337 } |
380 } |
338 |
381 |
339 public void setKeepAlive(boolean on) throws SocketException { |
382 public void setKeepAlive(boolean on) throws SocketException { |
340 opts().setKeepAlive(on); |
383 setBooleanOption(StandardSocketOption.SO_KEEPALIVE, on); |
341 } |
384 } |
342 |
385 |
343 public boolean getKeepAlive() throws SocketException { |
386 public boolean getKeepAlive() throws SocketException { |
344 return opts().getKeepAlive(); |
387 return getBooleanOption(StandardSocketOption.SO_KEEPALIVE); |
345 } |
388 } |
346 |
389 |
347 public void setTrafficClass(int tc) throws SocketException { |
390 public void setTrafficClass(int tc) throws SocketException { |
348 opts().setTrafficClass(tc); |
391 setIntOption(StandardSocketOption.IP_TOS, tc); |
349 trafficClass = tc; |
|
350 } |
392 } |
351 |
393 |
352 public int getTrafficClass() throws SocketException { |
394 public int getTrafficClass() throws SocketException { |
353 int tc = opts().getTrafficClass(); |
395 return getIntOption(StandardSocketOption.IP_TOS); |
354 if (tc < 0) { |
|
355 tc = trafficClass; |
|
356 } |
|
357 return tc; |
|
358 } |
396 } |
359 |
397 |
360 public void setReuseAddress(boolean on) throws SocketException { |
398 public void setReuseAddress(boolean on) throws SocketException { |
361 opts().setReuseAddress(on); |
399 setBooleanOption(StandardSocketOption.SO_REUSEADDR, on); |
362 } |
400 } |
363 |
401 |
364 public boolean getReuseAddress() throws SocketException { |
402 public boolean getReuseAddress() throws SocketException { |
365 return opts().getReuseAddress(); |
403 return getBooleanOption(StandardSocketOption.SO_REUSEADDR); |
366 } |
404 } |
367 |
405 |
368 public void close() throws IOException { |
406 public void close() throws IOException { |
369 try { |
407 try { |
370 sc.close(); |
408 sc.close(); |