Home | History | Annotate | Download | only in internal
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.apache.harmony.nio.internal;
     19 
     20 // BEGIN android-note
     21 // In this class the address length was changed from long to int.
     22 // END android-note
     23 
     24 import java.io.FileDescriptor;
     25 import java.io.IOException;
     26 import java.io.InterruptedIOException;
     27 import java.net.ConnectException;
     28 import java.net.DatagramPacket;
     29 import java.net.DatagramSocket;
     30 import java.net.DatagramSocketImpl;
     31 import java.net.InetAddress;
     32 import java.net.InetSocketAddress;
     33 import java.net.SocketAddress;
     34 import java.net.SocketException;
     35 import java.nio.ByteBuffer;
     36 import java.nio.channels.AlreadyConnectedException;
     37 import java.nio.channels.ClosedChannelException;
     38 import java.nio.channels.DatagramChannel;
     39 import java.nio.channels.IllegalBlockingModeException;
     40 import java.nio.channels.NotYetConnectedException;
     41 import java.nio.channels.spi.SelectorProvider;
     42 
     43 import org.apache.harmony.luni.net.PlainDatagramSocketImpl;
     44 import org.apache.harmony.luni.platform.FileDescriptorHandler;
     45 import org.apache.harmony.luni.platform.INetworkSystem;
     46 import org.apache.harmony.luni.platform.Platform;
     47 //import org.apache.harmony.luni.util.ErrorCodeException; android-removed
     48 import org.apache.harmony.nio.AddressUtil;
     49 
     50 /*
     51  * The default implementation class of java.nio.channels.DatagramChannel.
     52  */
     53 class DatagramChannelImpl extends DatagramChannel implements
     54         FileDescriptorHandler {
     55 
     56     // The singleton to do the native network operation.
     57     private static final INetworkSystem networkSystem = Platform
     58             .getNetworkSystem();
     59 
     60     // default timeout used to nonblocking mode.
     61     private static final int DEFAULT_TIMEOUT = 1;
     62 
     63     // android-removed: private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
     64 
     65     private static final byte[] stubArray = new byte[0];
     66 
     67     // The fd to interact with native code
     68     private FileDescriptor fd;
     69 
     70     // Our internal DatagramSocket.
     71     private DatagramSocket socket = null;
     72 
     73     // The address to be connected.
     74     InetSocketAddress connectAddress = null;
     75 
     76     // local port
     77     private int localPort;
     78 
     79     // At first, uninitialized.
     80     boolean connected = false;
     81 
     82     // whether the socket is bound
     83     boolean isBound = false;
     84 
     85     private static class ReadLock {}
     86     private final Object readLock = new ReadLock();
     87 
     88     private static class WriteLock {}
     89     private final Object writeLock = new WriteLock();
     90 
     91     // used to store the trafficClass value which is simply returned
     92     // as the value that was set. We also need it to pass it to methods
     93     // that specify an address packets are going to be sent to
     94     private int trafficClass = 0;
     95 
     96     /*
     97      * Constructor
     98      */
     99     protected DatagramChannelImpl(SelectorProvider selectorProvider)
    100             throws IOException {
    101         super(selectorProvider);
    102         fd = new FileDescriptor();
    103         networkSystem.createDatagramSocket(fd, true);
    104     }
    105 
    106     /*
    107      * for native call
    108      */
    109     @SuppressWarnings("unused")
    110     private DatagramChannelImpl() {
    111         super(SelectorProvider.provider());
    112         fd = new FileDescriptor();
    113         connectAddress = new InetSocketAddress(0);
    114     }
    115 
    116     /*
    117      * Getting the internal DatagramSocket If we have not the socket, we create
    118      * a new one.
    119      */
    120     @Override
    121     synchronized public DatagramSocket socket() {
    122         if (null == socket) {
    123             socket = new DatagramSocketAdapter(
    124                     new PlainDatagramSocketImpl(fd, localPort), this);
    125         }
    126         return socket;
    127     }
    128 
    129     /**
    130      * Answer the local address from the IP stack. This method should not be
    131      * called directly as it does not check the security policy.
    132      *
    133      * @return InetAddress the local address to which the socket is bound.
    134      * @see DatagramSocket
    135      */
    136     InetAddress getLocalAddress() {
    137         return networkSystem.getSocketLocalAddress(fd);
    138     }
    139 
    140     /**
    141      * @see java.nio.channels.DatagramChannel#isConnected()
    142      */
    143     @Override
    144     synchronized public boolean isConnected() {
    145         return connected;
    146     }
    147 
    148     /**
    149      * @see java.nio.channels.DatagramChannel#connect(java.net.SocketAddress)
    150      */
    151     @Override
    152     synchronized public DatagramChannel connect(SocketAddress address)
    153             throws IOException {
    154         // must open
    155         checkOpen();
    156         // status must be un-connected.
    157         if (connected) {
    158             throw new IllegalStateException();
    159         }
    160 
    161         // check the address
    162         InetSocketAddress inetSocketAddress = SocketChannelImpl
    163                 .validateAddress(address);
    164 
    165         // security check
    166         SecurityManager sm = System.getSecurityManager();
    167         if (null != sm) {
    168             if (inetSocketAddress.getAddress().isMulticastAddress()) {
    169                 sm.checkMulticast(inetSocketAddress.getAddress());
    170             } else {
    171                 sm.checkConnect(inetSocketAddress.getAddress().getHostName(),
    172                         inetSocketAddress.getPort());
    173             }
    174         }
    175 
    176         try {
    177             begin();
    178             networkSystem.connectDatagram(fd, inetSocketAddress.getPort(),
    179                     trafficClass, inetSocketAddress.getAddress());
    180         } catch (ConnectException e) {
    181             // ConnectException means connect fail, not exception
    182         } finally {
    183             end(true);
    184         }
    185 
    186         // set the connected address.
    187         connectAddress = inetSocketAddress;
    188         connected = true;
    189         isBound = true;
    190         return this;
    191     }
    192 
    193     /**
    194      * @see java.nio.channels.DatagramChannel#disconnect()
    195      */
    196     @Override
    197     synchronized public DatagramChannel disconnect() throws IOException {
    198         if (!isConnected() || !isOpen()) {
    199             return this;
    200         }
    201         connected = false;
    202         connectAddress = null;
    203         networkSystem.disconnectDatagram(fd);
    204         if (null != socket) {
    205             socket.disconnect();
    206         }
    207         return this;
    208     }
    209 
    210     /**
    211      * @see java.nio.channels.DatagramChannel#receive(java.nio.ByteBuffer)
    212      */
    213     @Override
    214     public SocketAddress receive(ByteBuffer target) throws IOException {
    215         // must not null and not readonly
    216         checkWritable(target);
    217         // must open
    218         checkOpen();
    219 
    220         if (!isBound) {
    221             return null;
    222         }
    223 
    224         SocketAddress retAddr = null;
    225         try {
    226             begin();
    227 
    228             // receive real data packet, (not peek)
    229             synchronized (readLock) {
    230                 boolean loop = isBlocking();
    231                 if (!target.isDirect()) {
    232                     retAddr = receiveImpl(target, loop);
    233                 } else {
    234                     retAddr = receiveDirectImpl(target, loop);
    235                 }
    236             }
    237         } catch (InterruptedIOException e) {
    238             // this line used in Linux
    239             return null;
    240         } finally {
    241             end(null != retAddr);
    242         }
    243         return retAddr;
    244     }
    245 
    246     private SocketAddress receiveImpl(ByteBuffer target, boolean loop)
    247             throws IOException {
    248         SocketAddress retAddr = null;
    249         DatagramPacket receivePacket;
    250         int oldposition = target.position();
    251         int received = 0;
    252         if (target.hasArray()) {
    253             receivePacket = new DatagramPacket(target.array(), target
    254                     .position()
    255                     + target.arrayOffset(), target.remaining());
    256         } else {
    257             receivePacket = new DatagramPacket(new byte[target.remaining()],
    258                     target.remaining());
    259         }
    260         do {
    261             if (isConnected()) {
    262                 received = networkSystem.recvConnectedDatagram(fd,
    263                         receivePacket, receivePacket.getData(), receivePacket
    264                                 .getOffset(), receivePacket.getLength(),
    265                         isBlocking() ? 0 : DEFAULT_TIMEOUT, false);
    266             } else {
    267                 received = networkSystem.receiveDatagram(fd, receivePacket,
    268                         receivePacket.getData(), receivePacket.getOffset(),
    269                         receivePacket.getLength(), isBlocking() ? 0
    270                                 : DEFAULT_TIMEOUT, false);
    271             }
    272 
    273             // security check
    274             SecurityManager sm = System.getSecurityManager();
    275             if (!isConnected() && null != sm) {
    276                 try {
    277                     sm.checkAccept(receivePacket.getAddress().getHostAddress(),
    278                             receivePacket.getPort());
    279                 } catch (SecurityException e) {
    280                     // do discard the datagram packet
    281                     receivePacket = null;
    282                 }
    283             }
    284             if (null != receivePacket && null != receivePacket.getAddress()) {
    285 
    286                 if (received > 0) {
    287                     if (target.hasArray()) {
    288                         target.position(oldposition + received);
    289                     } else {
    290                         // copy the data of received packet
    291                         target.put(receivePacket.getData(), 0, received);
    292                     }
    293                 }
    294                 retAddr = receivePacket.getSocketAddress();
    295                 break;
    296             }
    297         } while (loop);
    298         return retAddr;
    299     }
    300 
    301     private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop)
    302             throws IOException {
    303         SocketAddress retAddr = null;
    304         DatagramPacket receivePacket = new DatagramPacket(stubArray, 0);
    305         int oldposition = target.position();
    306         int received = 0;
    307         do {
    308             int address = AddressUtil.getDirectBufferAddress(target);
    309             if (isConnected()) {
    310                 received = networkSystem.recvConnectedDatagramDirect(fd,
    311                         receivePacket, address, target.position(), target
    312                                 .remaining(), isBlocking() ? 0
    313                                 : DEFAULT_TIMEOUT, false);
    314             } else {
    315                 received = networkSystem.receiveDatagramDirect(fd,
    316                         receivePacket, address, target.position(), target
    317                                 .remaining(), isBlocking() ? 0
    318                                 : DEFAULT_TIMEOUT, false);
    319             }
    320 
    321             // security check
    322             SecurityManager sm = System.getSecurityManager();
    323             if (!isConnected() && null != sm) {
    324                 try {
    325                     sm.checkAccept(receivePacket.getAddress().getHostAddress(),
    326                             receivePacket.getPort());
    327                 } catch (SecurityException e) {
    328                     // do discard the datagram packet
    329                     receivePacket = null;
    330                 }
    331             }
    332             if (null != receivePacket && null != receivePacket.getAddress()) {
    333                 // copy the data of received packet
    334                 if (received > 0) {
    335                     target.position(oldposition + received);
    336                 }
    337                 retAddr = receivePacket.getSocketAddress();
    338                 break;
    339             }
    340         } while (loop);
    341         return retAddr;
    342     }
    343 
    344     /**
    345      * @see java.nio.channels.DatagramChannel#send(java.nio.ByteBuffer,
    346      *      java.net.SocketAddress)
    347      */
    348     @Override
    349     public int send(ByteBuffer source, SocketAddress socketAddress)
    350             throws IOException {
    351         // must not null
    352         checkNotNull(source);
    353         // must open
    354         checkOpen();
    355 
    356         // transfer socketAddress
    357         InetSocketAddress isa = (InetSocketAddress) socketAddress;
    358         if (null == isa.getAddress()) {
    359             throw new IOException();
    360         }
    361 
    362         if (isConnected()) {
    363             if (!connectAddress.equals(isa)) {
    364                 throw new IllegalArgumentException();
    365             }
    366         } else {
    367             // not connected, check security
    368             SecurityManager sm = System.getSecurityManager();
    369             if (sm != null) {
    370                 if (isa.getAddress().isMulticastAddress()) {
    371                     sm.checkMulticast(isa.getAddress());
    372                 } else {
    373                     sm.checkConnect(isa.getAddress().getHostAddress(), isa
    374                             .getPort());
    375                 }
    376             }
    377         }
    378 
    379         // the return value.
    380         int sendCount = 0;
    381         try {
    382             begin();
    383             byte[] array = null;
    384             int length = source.remaining();
    385             int oldposition = source.position();
    386             int start = oldposition;
    387             if (source.isDirect()) {
    388                 synchronized (writeLock) {
    389                     int data_address = AddressUtil
    390                             .getDirectBufferAddress(source);
    391                     sendCount = networkSystem.sendDatagramDirect(fd,
    392                             data_address, start, length, isa.getPort(), false,
    393                             trafficClass, isa.getAddress());
    394                 }
    395             } else {
    396                 if (source.hasArray()) {
    397                     array = source.array();
    398                     start += source.arrayOffset();
    399                 } else {
    400                     array = new byte[length];
    401                     source.get(array);
    402                     start = 0;
    403                 }
    404                 synchronized (writeLock) {
    405                     sendCount = networkSystem.sendDatagram(fd, array, start,
    406                             length, isa.getPort(), false, trafficClass, isa
    407                                     .getAddress());
    408                 }
    409             }
    410             source.position(oldposition + sendCount);
    411             return sendCount;
    412         } finally {
    413             end(sendCount >= 0);
    414         }
    415     }
    416 
    417     /**
    418      * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer)
    419      */
    420     @Override
    421     public int read(ByteBuffer target) throws IOException {
    422         if (null == target) {
    423             throw new NullPointerException();
    424         }
    425         // status must be open and connected
    426         checkOpenConnected();
    427         // target buffer must be not null and not readonly
    428         checkWritable(target);
    429 
    430         if (!target.hasRemaining()) {
    431             return 0;
    432         }
    433 
    434         int readCount = 0;
    435         if (target.isDirect() || target.hasArray()) {
    436             readCount = readImpl(target);
    437             if (readCount > 0) {
    438                 target.position(target.position() + readCount);
    439             }
    440 
    441         } else {
    442             byte[] readArray = new byte[target.remaining()];
    443             ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
    444             readCount = readImpl(readBuffer);
    445             if (readCount > 0) {
    446                 target.put(readArray, 0, readCount);
    447             }
    448         }
    449         return readCount;
    450     }
    451 
    452     /**
    453      * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer[], int,
    454      *      int)
    455      */
    456     @Override
    457     public long read(ByteBuffer[] targets, int offset, int length)
    458             throws IOException {
    459         if (length < 0 || offset < 0
    460                 || (long) length + (long) offset > targets.length) {
    461             throw new IndexOutOfBoundsException();
    462         }
    463 
    464         // status must be open and connected
    465         checkOpenConnected();
    466 
    467         int totalCount = 0;
    468         for (int val = offset; val < length; val++) {
    469             // target buffer must be not null and not readonly
    470             checkWritable(targets[val]);
    471             totalCount += targets[val].remaining();
    472         }
    473 
    474         // read data to readBuffer, and then transfer data from readBuffer to
    475         // targets.
    476         ByteBuffer readBuffer = ByteBuffer.allocate(totalCount);
    477         int readCount;
    478         readCount = readImpl(readBuffer);
    479         int left = readCount;
    480         int index = offset;
    481         // transfer data from readBuffer to targets
    482         byte[] readArray = readBuffer.array();
    483         while (left > 0) {
    484             int putLength = Math.min(targets[index].remaining(), left);
    485             targets[index].put(readArray, readCount - left, putLength);
    486             index++;
    487             left -= putLength;
    488         }
    489         return readCount;
    490     }
    491 
    492     /*
    493      * read from channel, and store the result in the target.
    494      */
    495     private int readImpl(ByteBuffer readBuffer) throws IOException {
    496         synchronized (readLock) {
    497             int readCount = 0;
    498             try {
    499                 begin();
    500                 // timeout == 0 means block read.
    501                 // DEFAULT_TIMEOUT is used in non-block mode.
    502                 int timeout = isBlocking() ? 0 : DEFAULT_TIMEOUT;
    503                 int start = readBuffer.position();
    504                 int length = readBuffer.remaining();
    505                 if (readBuffer.isDirect()) {
    506                     int address = AddressUtil.getDirectBufferAddress(readBuffer);
    507                     if (isConnected()) {
    508                         readCount = networkSystem.recvConnectedDatagramDirect(
    509                                 fd, null, address, start, length, timeout,
    510                                 false);
    511                     } else {
    512                         readCount = networkSystem.receiveDatagramDirect(fd,
    513                                 null, address, start, length, timeout, false);
    514                     }
    515                 } else {
    516                     // the target is assured to have array.
    517                     byte[] target = readBuffer.array();
    518                     start += readBuffer.arrayOffset();
    519                     if (isConnected()) {
    520                         readCount = networkSystem.recvConnectedDatagram(fd,
    521                                 null, target, start, length, timeout, false);
    522                     } else {
    523                         readCount = networkSystem.receiveDatagram(fd, null,
    524                                 target, start, length, timeout, false);
    525                     }
    526                 }
    527                 return readCount;
    528             } catch (InterruptedIOException e) {
    529                 // InterruptedIOException will be thrown when timeout.
    530                 return 0;
    531             } finally {
    532                 end(readCount > 0);
    533             }
    534         }
    535     }
    536 
    537     /**
    538      * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer)
    539      */
    540     @Override
    541     public int write(ByteBuffer source) throws IOException {
    542         // source buffer must be not null
    543         checkNotNull(source);
    544         // status must be open and connected
    545         checkOpenConnected();
    546         // return immediately if source is full
    547         if (!source.hasRemaining()) {
    548             return 0;
    549         }
    550 
    551         ByteBuffer writeBuffer = null;
    552         byte[] writeArray = null;
    553         int oldposition = source.position();
    554         int result;
    555         if (source.isDirect() || source.hasArray()) {
    556             writeBuffer = source;
    557         } else {
    558             writeArray = new byte[source.remaining()];
    559             source.get(writeArray);
    560             writeBuffer = ByteBuffer.wrap(writeArray);
    561         }
    562         result = writeImpl(writeBuffer);
    563         if (result > 0) {
    564             source.position(oldposition + result);
    565         }
    566         return result;
    567     }
    568 
    569     /**
    570      * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int,
    571      *      int)
    572      */
    573     @Override
    574     public long write(ByteBuffer[] sources, int offset, int length)
    575             throws IOException {
    576         if (length < 0 || offset < 0
    577                 || (long) length + (long) offset > sources.length) {
    578             throw new IndexOutOfBoundsException();
    579         }
    580 
    581         // status must be open and connected
    582         checkOpenConnected();
    583         int count = calculateByteBufferArray(sources, offset, length);
    584         if (0 == count) {
    585             return 0;
    586         }
    587         ByteBuffer writeBuf = ByteBuffer.allocate(count);
    588         for (int val = offset; val < length + offset; val++) {
    589             ByteBuffer source = sources[val];
    590             int oldPosition = source.position();
    591             writeBuf.put(source);
    592             source.position(oldPosition);
    593         }
    594         writeBuf.flip();
    595         int result = writeImpl(writeBuf);
    596         int val = offset;
    597         int written = result;
    598         while (result > 0) {
    599             ByteBuffer source = sources[val];
    600             int gap = Math.min(result, source.remaining());
    601             source.position(source.position() + gap);
    602             val++;
    603             result -= gap;
    604         }
    605         return written;
    606     }
    607 
    608     /*
    609      * Write the source. Return the count of bytes written.
    610      */
    611     private int writeImpl(ByteBuffer buf) throws IOException {
    612         synchronized (writeLock) {
    613             int result = 0;
    614             try {
    615                 begin();
    616                 int length = buf.remaining();
    617                 int start = buf.position();
    618 
    619                 if (buf.isDirect()) {
    620                     int address = AddressUtil.getDirectBufferAddress(buf);
    621                     result = networkSystem.sendConnectedDatagramDirect(fd,
    622                             address, start, length, isBound);
    623                 } else {
    624                     // buf is assured to have array.
    625                     start += buf.arrayOffset();
    626                     result = networkSystem.sendConnectedDatagram(fd, buf
    627                             .array(), start, length, isBound);
    628                 }
    629                 return result;
    630                 // android-removed: bogus catch (SocketException e) and use of ErrorCodeException.
    631             } finally {
    632                 end(result > 0);
    633             }
    634         }
    635     }
    636 
    637     /*
    638      * Do really closing action here.
    639      */
    640     @Override
    641     synchronized protected void implCloseSelectableChannel() throws IOException {
    642         connected = false;
    643         if (null != socket && !socket.isClosed()) {
    644             socket.close();
    645         } else {
    646             networkSystem.socketClose(fd);
    647         }
    648     }
    649 
    650     /**
    651      * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
    652      */
    653     @Override
    654     @SuppressWarnings("unused")
    655     protected void implConfigureBlocking(boolean blockingMode)
    656             throws IOException {
    657         // Do nothing here. For real read/write operation in nonblocking mode,
    658         // it uses select system call. Whether a channel is blocking can be
    659         // decided by isBlocking() method.
    660     }
    661 
    662     /*
    663      * Status check, must be open.
    664      */
    665     private void checkOpen() throws IOException {
    666         if (!isOpen()) {
    667             throw new ClosedChannelException();
    668         }
    669     }
    670 
    671     /*
    672      * Status check, must be open and connected, for read and write.
    673      */
    674     private void checkOpenConnected() throws IOException {
    675         checkOpen();
    676         if (!isConnected()) {
    677             throw new NotYetConnectedException();
    678         }
    679     }
    680 
    681     /*
    682      * Buffer check, must not null
    683      */
    684     private void checkNotNull(ByteBuffer source) {
    685         if (null == source) {
    686             throw new NullPointerException();
    687         }
    688     }
    689 
    690     /*
    691      * Buffer check, must not null and not read only buffer, for read and
    692      * receive.
    693      */
    694     private void checkWritable(ByteBuffer target) {
    695         // including checking of NPE.
    696         if (target.isReadOnly()) {
    697             throw new IllegalArgumentException();
    698         }
    699     }
    700 
    701     /*
    702      * Get the fd for internal use.
    703      */
    704     public FileDescriptor getFD() {
    705         return fd;
    706     }
    707 
    708     private int calculateByteBufferArray(ByteBuffer[] sources, int offset,
    709             int length) {
    710         int sum = 0;
    711         for (int val = offset; val < offset + length; val++) {
    712             sum += sources[val].remaining();
    713         }
    714         return sum;
    715     }
    716 
    717     /*
    718      * The adapter class of DatagramSocket
    719      */
    720     private static class DatagramSocketAdapter extends DatagramSocket {
    721 
    722         /*
    723          * The internal datagramChannelImpl.
    724          */
    725         private DatagramChannelImpl channelImpl;
    726 
    727         /*
    728          * Constructor initialize the datagramSocketImpl and datagramChannelImpl
    729          */
    730         DatagramSocketAdapter(DatagramSocketImpl socketimpl,
    731                 DatagramChannelImpl channelImpl) {
    732             super(socketimpl);
    733             this.channelImpl = channelImpl;
    734         }
    735 
    736         /*
    737          * Get the internal datagramChannelImpl
    738          */
    739         @Override
    740         public DatagramChannel getChannel() {
    741             return channelImpl;
    742         }
    743 
    744         /**
    745          * @see java.net.DatagramSocket#isBound()
    746          */
    747         @Override
    748         public boolean isBound() {
    749             return channelImpl.isBound;
    750         }
    751 
    752         /**
    753          * @see java.net.DatagramSocket#isConnected()
    754          */
    755         @Override
    756         public boolean isConnected() {
    757             return channelImpl.isConnected();
    758         }
    759 
    760         /**
    761          * @see java.net.DatagramSocket#getInetAddress()
    762          */
    763         @Override
    764         public InetAddress getInetAddress() {
    765             if (null == channelImpl.connectAddress) {
    766                 return null;
    767             }
    768             return channelImpl.connectAddress.getAddress();
    769         }
    770 
    771         /**
    772          * @see java.net.DatagramSocket#getLocalAddress()
    773          */
    774         @Override
    775         public InetAddress getLocalAddress() {
    776             return channelImpl.getLocalAddress();
    777         }
    778 
    779         /**
    780          * @see java.net.DatagramSocket#getPort()
    781          */
    782         @Override
    783         public int getPort() {
    784             if (null == channelImpl.connectAddress) {
    785                 return -1;
    786             }
    787             return channelImpl.connectAddress.getPort();
    788         }
    789 
    790         /**
    791          * @see java.net.DatagramSocket#bind(java.net.SocketAddress)
    792          */
    793         @Override
    794         public void bind(SocketAddress localAddr) throws SocketException {
    795             if (channelImpl.isConnected()) {
    796                 throw new AlreadyConnectedException();
    797             }
    798             super.bind(localAddr);
    799             channelImpl.isBound = true;
    800         }
    801 
    802         /**
    803          * @see java.net.DatagramSocket#receive(java.net.DatagramPacket)
    804          */
    805         @Override
    806         public void receive(DatagramPacket packet) throws IOException {
    807             if (!channelImpl.isBlocking()) {
    808                 throw new IllegalBlockingModeException();
    809             }
    810             super.receive(packet);
    811         }
    812 
    813         /**
    814          * @see java.net.DatagramSocket#send(java.net.DatagramPacket)
    815          */
    816         @Override
    817         public void send(DatagramPacket packet) throws IOException {
    818             if (!channelImpl.isBlocking()) {
    819                 throw new IllegalBlockingModeException();
    820             }
    821             super.send(packet);
    822         }
    823 
    824         /**
    825          * @see java.net.DatagramSocket#close()
    826          */
    827         @Override
    828         public void close() {
    829             synchronized (channelImpl) {
    830                 if (channelImpl.isOpen()) {
    831                     try {
    832                         channelImpl.close();
    833                     } catch (IOException e) {
    834                         // Ignore
    835                     }
    836                 }
    837                 super.close();
    838             }
    839         }
    840 
    841         /**
    842          * @see java.net.DatagramSocket#disconnect()
    843          */
    844         @Override
    845         public void disconnect() {
    846             try {
    847                 channelImpl.disconnect();
    848             } catch (IOException e) {
    849                 // Ignore
    850             }
    851             super.disconnect();
    852         }
    853     }
    854 }
    855