1
25
26 package java.net;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.io.FileDescriptor;
32
33 import sun.net.ConnectionResetException;
34 import sun.net.NetHooks;
35 import sun.net.ResourceManager;
36
37
44 abstract class AbstractPlainSocketImpl extends SocketImpl
45 {
46
47 int timeout;
48
49 private int trafficClass;
50
51 private boolean shut_rd = false;
52 private boolean shut_wr = false;
53
54 private SocketInputStream socketInputStream = null;
55 private SocketOutputStream socketOutputStream = null;
56
57
58 protected int fdUseCount = 0;
59
60
61 protected final Object fdLock = new Object();
62
63
64 protected boolean closePending = false;
65
66
67 private int CONNECTION_NOT_RESET = 0;
68 private int CONNECTION_RESET_PENDING = 1;
69 private int CONNECTION_RESET = 2;
70 private int resetState;
71 private final Object resetLock = new Object();
72
73
75 protected boolean stream;
76
77
80 static {
81 java.security.AccessController.doPrivileged(
82 new java.security.PrivilegedAction<Void>() {
83 public Void run() {
84 System.loadLibrary("net");
85 return null;
86 }
87 });
88 }
89
90
94 protected synchronized void create(boolean stream) throws IOException {
95 this.stream = stream;
96 if (!stream) {
97 ResourceManager.beforeUdpCreate();
98
99 fd = new FileDescriptor();
100 try {
101 socketCreate(false);
102 } catch (IOException ioe) {
103 ResourceManager.afterUdpClose();
104 fd = null;
105 throw ioe;
106 }
107 } else {
108 fd = new FileDescriptor();
109 socketCreate(true);
110 }
111 if (socket != null)
112 socket.setCreated();
113 if (serverSocket != null)
114 serverSocket.setCreated();
115 }
116
117
123 protected void connect(String host, int port)
124 throws UnknownHostException, IOException
125 {
126 boolean connected = false;
127 try {
128 InetAddress address = InetAddress.getByName(host);
129 this.port = port;
130 this.address = address;
131
132 connectToAddress(address, port, timeout);
133 connected = true;
134 } finally {
135 if (!connected) {
136 try {
137 close();
138 } catch (IOException ioe) {
139
141 }
142 }
143 }
144 }
145
146
152 protected void connect(InetAddress address, int port) throws IOException {
153 this.port = port;
154 this.address = address;
155
156 try {
157 connectToAddress(address, port, timeout);
158 return;
159 } catch (IOException e) {
160
161 close();
162 throw e;
163 }
164 }
165
166
176 protected void connect(SocketAddress address, int timeout)
177 throws IOException {
178 boolean connected = false;
179 try {
180 if (address == null || !(address instanceof InetSocketAddress))
181 throw new IllegalArgumentException("unsupported address type");
182 InetSocketAddress addr = (InetSocketAddress) address;
183 if (addr.isUnresolved())
184 throw new UnknownHostException(addr.getHostName());
185 this.port = addr.getPort();
186 this.address = addr.getAddress();
187
188 connectToAddress(this.address, port, timeout);
189 connected = true;
190 } finally {
191 if (!connected) {
192 try {
193 close();
194 } catch (IOException ioe) {
195
197 }
198 }
199 }
200 }
201
202 private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
203 if (address.isAnyLocalAddress()) {
204 doConnect(InetAddress.getLocalHost(), port, timeout);
205 } else {
206 doConnect(address, port, timeout);
207 }
208 }
209
210 public void setOption(int opt, Object val) throws SocketException {
211 if (isClosedOrPending()) {
212 throw new SocketException("Socket Closed");
213 }
214 boolean on = true;
215 switch (opt) {
216
220 case SO_LINGER:
221 if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
222 throw new SocketException("Bad parameter for option");
223 if (val instanceof Boolean) {
224
225 on = false;
226 }
227 break;
228 case SO_TIMEOUT:
229 if (val == null || (!(val instanceof Integer)))
230 throw new SocketException("Bad parameter for SO_TIMEOUT");
231 int tmp = ((Integer) val).intValue();
232 if (tmp < 0)
233 throw new IllegalArgumentException("timeout < 0");
234 timeout = tmp;
235 break;
236 case IP_TOS:
237 if (val == null || !(val instanceof Integer)) {
238 throw new SocketException("bad argument for IP_TOS");
239 }
240 trafficClass = ((Integer)val).intValue();
241 break;
242 case SO_BINDADDR:
243 throw new SocketException("Cannot re-bind socket");
244 case TCP_NODELAY:
245 if (val == null || !(val instanceof Boolean))
246 throw new SocketException("bad parameter for TCP_NODELAY");
247 on = ((Boolean)val).booleanValue();
248 break;
249 case SO_SNDBUF:
250 case SO_RCVBUF:
251 if (val == null || !(val instanceof Integer) ||
252 !(((Integer)val).intValue() > 0)) {
253 throw new SocketException("bad parameter for SO_SNDBUF " +
254 "or SO_RCVBUF");
255 }
256 break;
257 case SO_KEEPALIVE:
258 if (val == null || !(val instanceof Boolean))
259 throw new SocketException("bad parameter for SO_KEEPALIVE");
260 on = ((Boolean)val).booleanValue();
261 break;
262 case SO_OOBINLINE:
263 if (val == null || !(val instanceof Boolean))
264 throw new SocketException("bad parameter for SO_OOBINLINE");
265 on = ((Boolean)val).booleanValue();
266 break;
267 case SO_REUSEADDR:
268 if (val == null || !(val instanceof Boolean))
269 throw new SocketException("bad parameter for SO_REUSEADDR");
270 on = ((Boolean)val).booleanValue();
271 break;
272 default:
273 throw new SocketException("unrecognized TCP option: " + opt);
274 }
275 socketSetOption(opt, on, val);
276 }
277 public Object getOption(int opt) throws SocketException {
278 if (isClosedOrPending()) {
279 throw new SocketException("Socket Closed");
280 }
281 if (opt == SO_TIMEOUT) {
282 return new Integer(timeout);
283 }
284 int ret = 0;
285
292
293 switch (opt) {
294 case TCP_NODELAY:
295 ret = socketGetOption(opt, null);
296 return Boolean.valueOf(ret != -1);
297 case SO_OOBINLINE:
298 ret = socketGetOption(opt, null);
299 return Boolean.valueOf(ret != -1);
300 case SO_LINGER:
301 ret = socketGetOption(opt, null);
302 return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret));
303 case SO_REUSEADDR:
304 ret = socketGetOption(opt, null);
305 return Boolean.valueOf(ret != -1);
306 case SO_BINDADDR:
307 InetAddressContainer in = new InetAddressContainer();
308 ret = socketGetOption(opt, in);
309 return in.addr;
310 case SO_SNDBUF:
311 case SO_RCVBUF:
312 ret = socketGetOption(opt, null);
313 return new Integer(ret);
314 case IP_TOS:
315 try {
316 ret = socketGetOption(opt, null);
317 if (ret == -1) {
318 return trafficClass;
319 } else {
320 return ret;
321 }
322 } catch (SocketException se) {
323
324 return trafficClass;
325 }
326 case SO_KEEPALIVE:
327 ret = socketGetOption(opt, null);
328 return Boolean.valueOf(ret != -1);
329
330 default:
331 return null;
332 }
333 }
334
335
340
341 synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
342 synchronized (fdLock) {
343 if (!closePending && (socket == null || !socket.isBound())) {
344 NetHooks.beforeTcpConnect(fd, address, port);
345 }
346 }
347 try {
348 acquireFD();
349 try {
350 socketConnect(address, port, timeout);
351
352 synchronized (fdLock) {
353 if (closePending) {
354 throw new SocketException ("Socket closed");
355 }
356 }
357
358
359
360
361 if (socket != null) {
362 socket.setBound();
363 socket.setConnected();
364 }
365 } finally {
366 releaseFD();
367 }
368 } catch (IOException e) {
369 close();
370 throw e;
371 }
372 }
373
374
379 protected synchronized void bind(InetAddress address, int lport)
380 throws IOException
381 {
382 synchronized (fdLock) {
383 if (!closePending && (socket == null || !socket.isBound())) {
384 NetHooks.beforeTcpBind(fd, address, lport);
385 }
386 }
387 socketBind(address, lport);
388 if (socket != null)
389 socket.setBound();
390 if (serverSocket != null)
391 serverSocket.setBound();
392 }
393
394
398 protected synchronized void listen(int count) throws IOException {
399 socketListen(count);
400 }
401
402
406 protected void accept(SocketImpl s) throws IOException {
407 acquireFD();
408 try {
409 socketAccept(s);
410 } finally {
411 releaseFD();
412 }
413 }
414
415
418 protected synchronized InputStream getInputStream() throws IOException {
419 synchronized (fdLock) {
420 if (isClosedOrPending())
421 throw new IOException("Socket Closed");
422 if (shut_rd)
423 throw new IOException("Socket input is shutdown");
424 if (socketInputStream == null)
425 socketInputStream = new SocketInputStream(this);
426 }
427 return socketInputStream;
428 }
429
430 void setInputStream(SocketInputStream in) {
431 socketInputStream = in;
432 }
433
434
437 protected synchronized OutputStream getOutputStream() throws IOException {
438 synchronized (fdLock) {
439 if (isClosedOrPending())
440 throw new IOException("Socket Closed");
441 if (shut_wr)
442 throw new IOException("Socket output is shutdown");
443 if (socketOutputStream == null)
444 socketOutputStream = new SocketOutputStream(this);
445 }
446 return socketOutputStream;
447 }
448
449 void setFileDescriptor(FileDescriptor fd) {
450 this.fd = fd;
451 }
452
453 void setAddress(InetAddress address) {
454 this.address = address;
455 }
456
457 void setPort(int port) {
458 this.port = port;
459 }
460
461 void setLocalPort(int localport) {
462 this.localport = localport;
463 }
464
465
468 protected synchronized int available() throws IOException {
469 if (isClosedOrPending()) {
470 throw new IOException("Stream closed.");
471 }
472
473
477 if (isConnectionReset() || shut_rd) {
478 return 0;
479 }
480
481
488 int n = 0;
489 try {
490 n = socketAvailable();
491 if (n == 0 && isConnectionResetPending()) {
492 setConnectionReset();
493 }
494 } catch (ConnectionResetException exc1) {
495 setConnectionResetPending();
496 try {
497 n = socketAvailable();
498 if (n == 0) {
499 setConnectionReset();
500 }
501 } catch (ConnectionResetException exc2) {
502 }
503 }
504 return n;
505 }
506
507
510 protected void close() throws IOException {
511 synchronized(fdLock) {
512 if (fd != null) {
513 if (!stream) {
514 ResourceManager.afterUdpClose();
515 }
516 if (fdUseCount == 0) {
517 if (closePending) {
518 return;
519 }
520 closePending = true;
521
529 try {
530 socketPreClose();
531 } finally {
532 socketClose();
533 }
534 fd = null;
535 return;
536 } else {
537
543 if (!closePending) {
544 closePending = true;
545 fdUseCount--;
546 socketPreClose();
547 }
548 }
549 }
550 }
551 }
552
553 void reset() throws IOException {
554 if (fd != null) {
555 socketClose();
556 }
557 fd = null;
558 super.reset();
559 }
560
561
562
565 protected void shutdownInput() throws IOException {
566 if (fd != null) {
567 socketShutdown(SHUT_RD);
568 if (socketInputStream != null) {
569 socketInputStream.setEOF(true);
570 }
571 shut_rd = true;
572 }
573 }
574
575
578 protected void shutdownOutput() throws IOException {
579 if (fd != null) {
580 socketShutdown(SHUT_WR);
581 shut_wr = true;
582 }
583 }
584
585 protected boolean supportsUrgentData () {
586 return true;
587 }
588
589 protected void sendUrgentData (int data) throws IOException {
590 if (fd == null) {
591 throw new IOException("Socket Closed");
592 }
593 socketSendUrgentData (data);
594 }
595
596
599 protected void finalize() throws IOException {
600 close();
601 }
602
603
609 FileDescriptor acquireFD() {
610 synchronized (fdLock) {
611 fdUseCount++;
612 return fd;
613 }
614 }
615
616
621 void releaseFD() {
622 synchronized (fdLock) {
623 fdUseCount--;
624 if (fdUseCount == -1) {
625 if (fd != null) {
626 try {
627 socketClose();
628 } catch (IOException e) {
629 } finally {
630 fd = null;
631 }
632 }
633 }
634 }
635 }
636
637 public boolean isConnectionReset() {
638 synchronized (resetLock) {
639 return (resetState == CONNECTION_RESET);
640 }
641 }
642
643 public boolean isConnectionResetPending() {
644 synchronized (resetLock) {
645 return (resetState == CONNECTION_RESET_PENDING);
646 }
647 }
648
649 public void setConnectionReset() {
650 synchronized (resetLock) {
651 resetState = CONNECTION_RESET;
652 }
653 }
654
655 public void setConnectionResetPending() {
656 synchronized (resetLock) {
657 if (resetState == CONNECTION_NOT_RESET) {
658 resetState = CONNECTION_RESET_PENDING;
659 }
660 }
661
662 }
663
664
667 public boolean isClosedOrPending() {
668
672 synchronized (fdLock) {
673 if (closePending || (fd == null)) {
674 return true;
675 } else {
676 return false;
677 }
678 }
679 }
680
681
684 public int getTimeout() {
685 return timeout;
686 }
687
688
692 private void socketPreClose() throws IOException {
693 socketClose0(true);
694 }
695
696
699 protected void socketClose() throws IOException {
700 socketClose0(false);
701 }
702
703 abstract void socketCreate(boolean isServer) throws IOException;
704 abstract void socketConnect(InetAddress address, int port, int timeout)
705 throws IOException;
706 abstract void socketBind(InetAddress address, int port)
707 throws IOException;
708 abstract void socketListen(int count)
709 throws IOException;
710 abstract void socketAccept(SocketImpl s)
711 throws IOException;
712 abstract int socketAvailable()
713 throws IOException;
714 abstract void socketClose0(boolean useDeferredClose)
715 throws IOException;
716 abstract void socketShutdown(int howto)
717 throws IOException;
718 abstract void socketSetOption(int cmd, boolean on, Object value)
719 throws SocketException;
720 abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
721 abstract void socketSendUrgentData(int data)
722 throws IOException;
723
724 public final static int SHUT_RD = 0;
725 public final static int SHUT_WR = 1;
726 }
727