src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java
changeset 49001 ce06058197a4
parent 48761 74c1fa26435a
child 54620 13b67c1420b8
equal deleted inserted replaced
49000:a406a9c451a0 49001:ce06058197a4
    39 import java.net.StandardSocketOptions;
    39 import java.net.StandardSocketOptions;
    40 import java.nio.ByteBuffer;
    40 import java.nio.ByteBuffer;
    41 import java.nio.channels.ClosedChannelException;
    41 import java.nio.channels.ClosedChannelException;
    42 import java.nio.channels.DatagramChannel;
    42 import java.nio.channels.DatagramChannel;
    43 import java.nio.channels.IllegalBlockingModeException;
    43 import java.nio.channels.IllegalBlockingModeException;
       
    44 import java.util.Objects;
    44 
    45 
    45 
    46 
    46 // Make a datagram-socket channel look like a datagram socket.
    47 // Make a datagram-socket channel look like a datagram socket.
    47 //
    48 //
    48 // The methods in this class are defined in exactly the same order as in
    49 // The methods in this class are defined in exactly the same order as in
    51 //
    52 //
    52 
    53 
    53 public class DatagramSocketAdaptor
    54 public class DatagramSocketAdaptor
    54     extends DatagramSocket
    55     extends DatagramSocket
    55 {
    56 {
    56 
       
    57     // The channel being adapted
    57     // The channel being adapted
    58     private final DatagramChannelImpl dc;
    58     private final DatagramChannelImpl dc;
    59 
    59 
    60     // Timeout "option" value for receives
    60     // Timeout "option" value for receives
    61     private volatile int timeout;
    61     private volatile int timeout;
    62 
    62 
    63     // ## super will create a useless impl
    63     // ## super will create a useless impl
    64     private DatagramSocketAdaptor(DatagramChannelImpl dc) throws IOException {
    64     private DatagramSocketAdaptor(DatagramChannelImpl dc) throws IOException {
    65         // Invoke the DatagramSocketAdaptor(SocketAddress) constructor,
    65         // Invoke the DatagramSocketAdaptor(SocketAddress) constructor,
    66         // passing a dummy DatagramSocketImpl object to aovid any native
    66         // passing a dummy DatagramSocketImpl object to avoid any native
    67         // resource allocation in super class and invoking our bind method
    67         // resource allocation in super class and invoking our bind method
    68         // before the dc field is initialized.
    68         // before the dc field is initialized.
    69         super(dummyDatagramSocket);
    69         super(dummyDatagramSocket);
    70         this.dc = dc;
    70         this.dc = dc;
    71     }
    71     }
    85         int port = isa.getPort();
    85         int port = isa.getPort();
    86         if (port < 0 || port > 0xFFFF)
    86         if (port < 0 || port > 0xFFFF)
    87             throw new IllegalArgumentException("connect: " + port);
    87             throw new IllegalArgumentException("connect: " + port);
    88         if (remote == null)
    88         if (remote == null)
    89             throw new IllegalArgumentException("connect: null address");
    89             throw new IllegalArgumentException("connect: null address");
    90         if (isClosed())
       
    91             return;
       
    92         try {
    90         try {
    93             dc.connect(remote);
    91             dc.connect(remote);
       
    92         } catch (ClosedChannelException e) {
       
    93             // ignore
    94         } catch (Exception x) {
    94         } catch (Exception x) {
    95             Net.translateToSocketException(x);
    95             Net.translateToSocketException(x);
    96         }
    96         }
    97     }
    97     }
    98 
    98 
   113             // Yes, j.n.DatagramSocket really does this
   113             // Yes, j.n.DatagramSocket really does this
   114         }
   114         }
   115     }
   115     }
   116 
   116 
   117     public void connect(SocketAddress remote) throws SocketException {
   117     public void connect(SocketAddress remote) throws SocketException {
   118         if (remote == null)
   118         Objects.requireNonNull(remote, "Address can't be null");
   119             throw new IllegalArgumentException("Address can't be null");
       
   120         connectInternal(remote);
   119         connectInternal(remote);
   121     }
   120     }
   122 
   121 
   123     public void disconnect() {
   122     public void disconnect() {
   124         try {
   123         try {
   135     public boolean isConnected() {
   134     public boolean isConnected() {
   136         return dc.remoteAddress() != null;
   135         return dc.remoteAddress() != null;
   137     }
   136     }
   138 
   137 
   139     public InetAddress getInetAddress() {
   138     public InetAddress getInetAddress() {
   140         return (isConnected()
   139         InetSocketAddress remote = dc.remoteAddress();
   141                 ? Net.asInetSocketAddress(dc.remoteAddress()).getAddress()
   140         return (remote != null) ? remote.getAddress() : null;
   142                 : null);
       
   143     }
   141     }
   144 
   142 
   145     public int getPort() {
   143     public int getPort() {
   146         return (isConnected()
   144         InetSocketAddress remote = dc.remoteAddress();
   147                 ? Net.asInetSocketAddress(dc.remoteAddress()).getPort()
   145         return (remote != null) ? remote.getPort() : -1;
   148                 : -1);
       
   149     }
   146     }
   150 
   147 
   151     public void send(DatagramPacket p) throws IOException {
   148     public void send(DatagramPacket p) throws IOException {
   152         synchronized (dc.blockingLock()) {
   149         synchronized (dc.blockingLock()) {
   153             if (!dc.isBlocking())
   150             if (!dc.isBlocking())
   159                                                     p.getLength());
   156                                                     p.getLength());
   160                     if (dc.isConnected()) {
   157                     if (dc.isConnected()) {
   161                         if (p.getAddress() == null) {
   158                         if (p.getAddress() == null) {
   162                             // Legacy DatagramSocket will send in this case
   159                             // Legacy DatagramSocket will send in this case
   163                             // and set address and port of the packet
   160                             // and set address and port of the packet
   164                             InetSocketAddress isa = (InetSocketAddress)
   161                             InetSocketAddress isa = dc.remoteAddress();
   165                                                     dc.remoteAddress();
       
   166                             p.setPort(isa.getPort());
   162                             p.setPort(isa.getPort());
   167                             p.setAddress(isa.getAddress());
   163                             p.setAddress(isa.getAddress());
   168                             dc.write(bb);
   164                             dc.write(bb);
   169                         } else {
   165                         } else {
   170                             // Target address may not match connected address
   166                             // Target address may not match connected address
   179                 Net.translateException(x);
   175                 Net.translateException(x);
   180             }
   176             }
   181         }
   177         }
   182     }
   178     }
   183 
   179 
   184     // Must hold dc.blockingLock()
       
   185     //
       
   186     private SocketAddress receive(ByteBuffer bb) throws IOException {
   180     private SocketAddress receive(ByteBuffer bb) throws IOException {
   187         if (timeout == 0) {
   181         assert Thread.holdsLock(dc.blockingLock()) && dc.isBlocking();
       
   182 
       
   183         long to = this.timeout;
       
   184         if (to == 0) {
   188             return dc.receive(bb);
   185             return dc.receive(bb);
   189         }
   186         } else {
   190 
       
   191         dc.configureBlocking(false);
       
   192         try {
       
   193             SocketAddress sender;
       
   194             if ((sender = dc.receive(bb)) != null)
       
   195                 return sender;
       
   196             long to = timeout;
       
   197             for (;;) {
   187             for (;;) {
   198                 if (!dc.isOpen())
   188                 if (!dc.isOpen())
   199                      throw new ClosedChannelException();
   189                     throw new ClosedChannelException();
   200                 long st = System.currentTimeMillis();
   190                 long st = System.currentTimeMillis();
   201                 int result = dc.poll(Net.POLLIN, to);
   191                 if (dc.pollRead(to)) {
   202                 if (result > 0 && ((result & Net.POLLIN) != 0)) {
   192                     return dc.receive(bb);
   203                     if ((sender = dc.receive(bb)) != null)
       
   204                         return sender;
       
   205                 }
   193                 }
   206                 to -= System.currentTimeMillis() - st;
   194                 to -= System.currentTimeMillis() - st;
   207                 if (to <= 0)
   195                 if (to <= 0)
   208                     throw new SocketTimeoutException();
   196                     throw new SocketTimeoutException();
   209             }
   197             }
   210         } finally {
       
   211             try {
       
   212                 dc.configureBlocking(true);
       
   213             } catch (ClosedChannelException e) { }
       
   214         }
   198         }
   215     }
   199     }
   216 
   200 
   217     public void receive(DatagramPacket p) throws IOException {
   201     public void receive(DatagramPacket p) throws IOException {
   218         synchronized (dc.blockingLock()) {
   202         synchronized (dc.blockingLock()) {
   234     }
   218     }
   235 
   219 
   236     public InetAddress getLocalAddress() {
   220     public InetAddress getLocalAddress() {
   237         if (isClosed())
   221         if (isClosed())
   238             return null;
   222             return null;
   239         SocketAddress local = dc.localAddress();
   223         InetSocketAddress local = dc.localAddress();
   240         if (local == null)
   224         if (local == null)
   241             local = new InetSocketAddress(0);
   225             local = new InetSocketAddress(0);
   242         InetAddress result = ((InetSocketAddress)local).getAddress();
   226         InetAddress result = local.getAddress();
   243         SecurityManager sm = System.getSecurityManager();
   227         SecurityManager sm = System.getSecurityManager();
   244         if (sm != null) {
   228         if (sm != null) {
   245             try {
   229             try {
   246                 sm.checkConnect(result.getHostAddress(), -1);
   230                 sm.checkConnect(result.getHostAddress(), -1);
   247             } catch (SecurityException x) {
   231             } catch (SecurityException x) {
   253 
   237 
   254     public int getLocalPort() {
   238     public int getLocalPort() {
   255         if (isClosed())
   239         if (isClosed())
   256             return -1;
   240             return -1;
   257         try {
   241         try {
   258             SocketAddress local = dc.getLocalAddress();
   242             InetSocketAddress local = dc.localAddress();
   259             if (local != null) {
   243             if (local != null) {
   260                 return ((InetSocketAddress)local).getPort();
   244                 return local.getPort();
   261             }
   245             }
   262         } catch (Exception x) {
   246         } catch (Exception x) {
   263         }
   247         }
   264         return 0;
   248         return 0;
   265     }
   249     }