Coverage Report - com.sun.grizzly.UDPConnectorHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
UDPConnectorHandler
47 %
66/139
36 %
21/58
0
UDPConnectorHandler$1
0 %
0/5
N/A
0
 
 1  
 /*
 2  
  * 
 3  
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 4  
  * 
 5  
  * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved.
 6  
  * 
 7  
  * The contents of this file are subject to the terms of either the GNU
 8  
  * General Public License Version 2 only ("GPL") or the Common Development
 9  
  * and Distribution License("CDDL") (collectively, the "License").  You
 10  
  * may not use this file except in compliance with the License. You can obtain
 11  
  * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 12  
  * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 13  
  * language governing permissions and limitations under the License.
 14  
  * 
 15  
  * When distributing the software, include this License Header Notice in each
 16  
  * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 17  
  * Sun designates this particular file as subject to the "Classpath" exception
 18  
  * as provided by Sun in the GPL Version 2 section of the License file that
 19  
  * accompanied this code.  If applicable, add the following below the License
 20  
  * Header, with the fields enclosed by brackets [] replaced by your own
 21  
  * identifying information: "Portions Copyrighted [year]
 22  
  * [name of copyright owner]"
 23  
  * 
 24  
  * Contributor(s):
 25  
  * 
 26  
  * If you wish your version of this file to be governed by only the CDDL or
 27  
  * only the GPL Version 2, indicate your decision by adding "[Contributor]
 28  
  * elects to include this software in this distribution under the [CDDL or GPL
 29  
  * Version 2] license."  If you don't indicate a single choice of license, a
 30  
  * recipient has the option to distribute your version of this file under
 31  
  * either the CDDL, the GPL Version 2 or to extend the choice of license to
 32  
  * its licensees as provided above.  However, if you add GPL Version 2 code
 33  
  * and therefore, elected the GPL Version 2 license, then the option applies
 34  
  * only if the new code is made subject to such option by the copyright
 35  
  * holder.
 36  
  *
 37  
  */
 38  
 
 39  
 package com.sun.grizzly;
 40  
 
 41  
 import com.sun.grizzly.async.AsyncQueueDataProcessor;
 42  
 import com.sun.grizzly.async.AsyncQueueReadable;
 43  
 import com.sun.grizzly.async.AsyncWriteCallbackHandler;
 44  
 import com.sun.grizzly.async.AsyncQueueWritable;
 45  
 import com.sun.grizzly.async.AsyncReadCallbackHandler;
 46  
 import com.sun.grizzly.async.AsyncReadCondition;
 47  
 import com.sun.grizzly.util.InputReader;
 48  
 import java.io.IOException;
 49  
 import java.net.SocketAddress;
 50  
 import java.nio.ByteBuffer;
 51  
 import java.nio.channels.AlreadyConnectedException;
 52  
 import java.nio.channels.NotYetConnectedException;
 53  
 import java.nio.channels.SelectableChannel;
 54  
 import java.nio.channels.SelectionKey;
 55  
 import java.nio.channels.DatagramChannel;
 56  
 import java.util.concurrent.CountDownLatch;
 57  
 import java.util.concurrent.TimeUnit;
 58  
 import java.util.logging.Level;
 59  
 
 60  
 /**
 61  
  * Client side interface used to implement non blocking client operation.
 62  
  * Implementation of this class must make sure the following methods are
 63  
  * invoked in that order:
 64  
  * <p><pre><code>
 65  
  * (1) connect()
 66  
  * (2) read() or write().
 67  
  * </code></pre></p>
 68  
  *
 69  
  * @author Jeanfrancois Arcand
 70  
  */
 71  4
 public class UDPConnectorHandler implements 
 72  
         ConnectorHandler<UDPSelectorHandler, CallbackHandler>, 
 73  
         AsyncQueueWritable, AsyncQueueReadable {
 74  
     
 75  
     /**
 76  
      * The underlying UDPSelectorHandler used to mange SelectionKeys.
 77  
      */
 78  
     protected UDPSelectorHandler selectorHandler;
 79  
     
 80  
     
 81  
     /**
 82  
      * A {@link CallbackHandler} handler invoked by the UDPSelectorHandler
 83  
      * when a non blocking operation is ready to be processed.
 84  
      */
 85  
     protected CallbackHandler callbackHandler;
 86  
     
 87  
     
 88  
     /**
 89  
      * The connection's DatagramChannel.
 90  
      */
 91  
     protected DatagramChannel datagramChannel;
 92  
     
 93  
     
 94  
     /**
 95  
      * Is the connection established.
 96  
      */
 97  
     protected volatile boolean isConnected;
 98  
     
 99  
     
 100  
     /**
 101  
      * The internal Controller used (in case not specified).
 102  
      */
 103  
     protected Controller controller;
 104  
     
 105  
     
 106  
     /**
 107  
      * IsConnected Latch related
 108  
      */
 109  
     protected CountDownLatch isConnectedLatch;
 110  
     
 111  
     
 112  
     /**
 113  
      * Are we creating a controller every run.
 114  
      */
 115  4
     private boolean isStandalone = false;
 116  
     
 117  
     
 118  
     /**
 119  
      * A blocking {@link InputStream} that use a pool of Selector
 120  
      * to execute a blocking read operation.
 121  
      */
 122  
     protected InputReader inputStream;
 123  
     
 124  
     
 125  
     /**
 126  
      * Connect to hostname:port. When an aysnchronous event happens (e.g
 127  
      * OP_READ or OP_WRITE), the {@link Controller} will invoke
 128  
      * the CallBackHandler.
 129  
      * @param remoteAddress remote address to connect
 130  
      * @param callbackHandler the handler invoked by its associated {@link SelectorHandler} when
 131  
      *        a non blocking operation is ready to be handled. When null, all 
 132  
      *        read and write operation will be delegated to the default
 133  
      *        {@link ProtocolChain} and its list of {@link ProtocolFilter} 
 134  
      *        . When null, this {@link ConnectorHandler} will create an instance of {@link DefaultCallbackHandler}.
 135  
      */
 136  
     public void connect(SocketAddress remoteAddress,
 137  
             CallbackHandler callbackHandler) throws IOException {
 138  
         
 139  31
         connect(remoteAddress,null,callbackHandler);
 140  31
     }
 141  
     
 142  
     
 143  
     /**
 144  
      * Connect to hostname:port. When an aysnchronous event happens (e.g
 145  
      * OP_READ or OP_WRITE), the {@link Controller} will invoke
 146  
      * the CallBackHandler.
 147  
      * @param remoteAddress remote address to connect
 148  
      * @param localAddress local address to bind
 149  
      * @param callbackHandler the handler invoked by its associated {@link SelectorHandler} when
 150  
      *        a non blocking operation is ready to be handled. When null, all 
 151  
      *        read and write operation will be delegated to the default
 152  
      *        {@link ProtocolChain} and its list of {@link ProtocolFilter} 
 153  
      *        . When null, this {@link ConnectorHandler} will create an instance of {@link DefaultCallbackHandler}.
 154  
      */
 155  
     public void connect(SocketAddress remoteAddress, SocketAddress localAddress,
 156  
             CallbackHandler callbackHandler) throws IOException {
 157  
         
 158  31
         if (controller == null){
 159  0
             throw new IllegalStateException("Controller cannot be null");
 160  
         }
 161  
         
 162  31
         connect(remoteAddress,localAddress,callbackHandler,
 163  
                 (UDPSelectorHandler)controller.getSelectorHandler(protocol()));
 164  31
     }
 165  
     
 166  
     
 167  
     /**
 168  
      * Connect to hostname:port. When an aysnchronous event happens (e.g
 169  
      * OP_READ or OP_WRITE), the {@link Controller} will invoke
 170  
      * the CallBackHandler.
 171  
      * @param remoteAddress remote address to connect
 172  
      * @param callbackHandler the handler invoked by its associated {@link SelectorHandler} when
 173  
      *        a non blocking operation is ready to be handled. When null, all 
 174  
      *        read and write operation will be delegated to the default
 175  
      *        {@link ProtocolChain} and its list of {@link ProtocolFilter} 
 176  
      *        . When null, this {@link ConnectorHandler} will create an instance of {@link DefaultCallbackHandler}.
 177  
      * @param selectorHandler an instance of SelectorHandler.
 178  
      */
 179  
     public void connect(SocketAddress remoteAddress,
 180  
             CallbackHandler callbackHandler,
 181  
             UDPSelectorHandler selectorHandler) throws IOException {
 182  
         
 183  0
         connect(remoteAddress,null,callbackHandler,selectorHandler);
 184  0
     }
 185  
     
 186  
     /**
 187  
      * Connect to hostname:port. When an aysnchronous event happens (e.g
 188  
      * OP_READ or OP_WRITE), the {@link Controller} will invoke
 189  
      * the CallBackHandler.
 190  
      * @param remoteAddress remote address to connect
 191  
      * @param localAddress local address to bin
 192  
      * @param callbackHandler the handler invoked by its associated {@link SelectorHandler} when
 193  
      *        a non blocking operation is ready to be handled. When null, all 
 194  
      *        read and write operation will be delegated to the default
 195  
      *        {@link ProtocolChain} and its list of {@link ProtocolFilter} 
 196  
      *        . When null, this {@link ConnectorHandler} will create an instance of {@link DefaultCallbackHandler}.
 197  
      * @param selectorHandler an instance of SelectorHandler.
 198  
      */
 199  
     public void connect(SocketAddress remoteAddress, SocketAddress localAddress,
 200  
             CallbackHandler callbackHandler,
 201  
             UDPSelectorHandler selectorHandler) throws IOException {
 202  
         
 203  31
         if (isConnected){
 204  0
             throw new AlreadyConnectedException();
 205  
         }
 206  
         
 207  31
         if (controller == null){
 208  0
             throw new IllegalStateException("Controller cannot be null");
 209  
         }
 210  
         
 211  31
         if (selectorHandler == null){
 212  0
             throw new IllegalStateException("Controller cannot be null");
 213  
         }
 214  
         
 215  31
         this.selectorHandler = selectorHandler;
 216  31
         if (callbackHandler == null){
 217  0
             callbackHandler = new DefaultCallbackHandler(this);
 218  
         } else {
 219  31
             this.callbackHandler = callbackHandler;
 220  
         }
 221  
         
 222  
         // Wait for the onConnect to be invoked.
 223  31
         isConnectedLatch = new CountDownLatch(1);
 224  
         
 225  31
         selectorHandler.connect(remoteAddress,localAddress,callbackHandler);
 226  
         
 227  
         try {
 228  31
             isConnectedLatch.await(30, TimeUnit.SECONDS);
 229  0
         } catch (InterruptedException ex) {
 230  0
             throw new IOException(ex.getMessage());
 231  31
         }
 232  31
     }
 233  
     
 234  
     
 235  
     /**
 236  
      * Connect to hostname:port. Internally an instance of Controller and
 237  
      * its default SelectorHandler will be created everytime this method is
 238  
      * called. This method should be used only and only if no external
 239  
      * Controller has been initialized.
 240  
      * @param remoteAddress remote address to connect
 241  
      */
 242  
     public void connect(SocketAddress remoteAddress) throws IOException {
 243  0
         connect(remoteAddress,(SocketAddress)null);
 244  0
     }
 245  
     
 246  
     
 247  
     /**
 248  
      * Connect to hostname:port. Internally an instance of Controller and
 249  
      * its default SelectorHandler will be created everytime this method is
 250  
      * called. This method should be used only and only if no external
 251  
      * Controller has been initialized.
 252  
      * @param remoteAddress remote address to connect
 253  
      * @param localAddress local address to bin
 254  
      */
 255  
     public void connect(SocketAddress remoteAddress, SocketAddress localAddress)
 256  
             throws IOException {
 257  
         
 258  0
         if (isConnected){
 259  0
             throw new AlreadyConnectedException();
 260  
         }
 261  
         
 262  0
         if (controller == null){
 263  0
             isStandalone = true;
 264  0
             controller = new Controller();
 265  0
             controller.setSelectorHandler(new UDPSelectorHandler(true));
 266  0
             DefaultPipeline pipeline = new DefaultPipeline();
 267  0
             pipeline.initPipeline();
 268  0
             pipeline.startPipeline();
 269  0
             controller.setPipeline(pipeline);
 270  
             
 271  0
             final CountDownLatch latch = new CountDownLatch(1);
 272  0
             controller.addStateListener(new ControllerStateListenerAdapter() {
 273  
                 @Override
 274  
                 public void onReady() {
 275  0
                     latch.countDown();
 276  0
                 }
 277  
                 
 278  
                 @Override
 279  
                 public void onException(Throwable e) {
 280  0
                     latch.countDown();
 281  0
                 }
 282  
             });                     
 283  0
             callbackHandler = new DefaultCallbackHandler(this, false);
 284  0
             new Thread(controller, "GrizzlyUDPConnectorHandler-Controller").start();
 285  
             
 286  
             try {
 287  0
                 latch.await();
 288  0
             } catch (InterruptedException ex) {
 289  0
             }
 290  
         }
 291  
         
 292  0
         connect(remoteAddress,localAddress,callbackHandler,
 293  
                 (UDPSelectorHandler)controller.getSelectorHandler(protocol()));
 294  0
     }
 295  
     
 296  
     
 297  
     /**
 298  
      * Read bytes. If blocking is set to <tt>true</tt>, a pool of temporary
 299  
      * {@link Selector} will be used to read bytes.
 300  
      * @param byteBuffer The byteBuffer to store bytes.
 301  
      * @param blocking <tt>true</tt> if a a pool of temporary Selector
 302  
      *        is required to handle a blocking read.
 303  
      */
 304  
     public long read(ByteBuffer byteBuffer, boolean blocking) throws IOException {
 305  2229
         if (!isConnected){
 306  0
             throw new NotYetConnectedException();
 307  
         }
 308  
         
 309  2229
         SelectionKey key = datagramChannel.keyFor(selectorHandler.getSelector());
 310  2229
         if (blocking){
 311  0
             if (inputStream == null) {
 312  0
                 inputStream = new InputReader();
 313  
             }
 314  0
             inputStream.setSelectionKey(key);
 315  0
             inputStream.setChannelType(
 316  
                     InputReader.ChannelType.DatagramChannel);
 317  0
             int nRead = inputStream.read(byteBuffer);
 318  0
             return nRead;
 319  
         } else {
 320  2229
             if (callbackHandler == null){
 321  0
                 throw new IllegalStateException
 322  
                         ("Non blocking read needs a CallbackHandler");
 323  
             }
 324  2229
             int nRead = datagramChannel.read(byteBuffer);
 325  
             
 326  2229
             if (nRead == 0){
 327  1086
                 selectorHandler.register(key, SelectionKey.OP_READ);
 328  
             }
 329  2229
             return nRead;
 330  
         }
 331  
     }
 332  
     
 333  
     
 334  
     /**
 335  
      * Writes bytes. If blocking is set to <tt>true</tt>, a pool of temporary
 336  
      * {@link Selector} will be used to writes bytes.
 337  
      * @param byteBuffer The byteBuffer to write.
 338  
      * @param blocking <tt>true</tt> if a a pool of temporary Selector
 339  
      *        is required to handle a blocking write.
 340  
      */
 341  
     public long write(ByteBuffer byteBuffer, boolean blocking) throws IOException {
 342  1001
         if (!isConnected){
 343  0
             throw new NotYetConnectedException();
 344  
         }
 345  
                 
 346  1001
         if (blocking){
 347  0
             throw new IllegalStateException("Blocking mode not supported");
 348  
         } else {
 349  1001
             if (callbackHandler == null){
 350  0
                 throw new IllegalStateException
 351  
                         ("Non blocking write needs a CallbackHandler");
 352  
             }
 353  1001
             SelectionKey key = datagramChannel.keyFor(selectorHandler.getSelector());
 354  1001
             int nWrite = datagramChannel.write(byteBuffer);
 355  
             
 356  1001
             if (nWrite == 0){
 357  0
                 selectorHandler.register(key, SelectionKey.OP_WRITE);
 358  
             }
 359  1001
             return nWrite;
 360  
         }
 361  
     }
 362  
     
 363  
     
 364  
     /**
 365  
      * {@inheritDoc}
 366  
      */
 367  
     public void readFromAsyncQueue(ByteBuffer buffer, 
 368  
             AsyncReadCallbackHandler callbackHandler) throws IOException {
 369  100
         readFromAsyncQueue(buffer, callbackHandler, null);
 370  100
     }
 371  
 
 372  
     /**
 373  
      * {@inheritDoc}
 374  
      */
 375  
     public void readFromAsyncQueue(ByteBuffer buffer, 
 376  
             AsyncReadCallbackHandler callbackHandler, 
 377  
             AsyncReadCondition condition) throws IOException {
 378  100
         readFromAsyncQueue(buffer, callbackHandler, condition, null);
 379  100
     }
 380  
 
 381  
     /**
 382  
      * {@inheritDoc}
 383  
      */
 384  
     public void readFromAsyncQueue(ByteBuffer buffer, 
 385  
             AsyncReadCallbackHandler callbackHandler, 
 386  
             AsyncReadCondition condition, 
 387  
             AsyncQueueDataProcessor readPostProcessor) throws IOException {
 388  100
         selectorHandler.getAsyncQueueReader().read(
 389  
                 datagramChannel.keyFor(selectorHandler.getSelector()), buffer, 
 390  
                 callbackHandler, condition, readPostProcessor);
 391  100
     }
 392  
 
 393  
     /**
 394  
      * {@inheritDoc}
 395  
      */
 396  
     public void writeToAsyncQueue(ByteBuffer buffer) throws IOException {
 397  20000
         writeToAsyncQueue(buffer, null);
 398  20000
     }
 399  
 
 400  
 
 401  
     /**
 402  
      * {@inheritDoc}
 403  
      */
 404  
     public void writeToAsyncQueue(ByteBuffer buffer, 
 405  
             AsyncWriteCallbackHandler callbackHandler) throws IOException {
 406  20000
         writeToAsyncQueue(buffer, callbackHandler, null);
 407  20000
     }
 408  
 
 409  
 
 410  
     /**
 411  
      * {@inheritDoc}
 412  
      */
 413  
     public void writeToAsyncQueue(ByteBuffer buffer, 
 414  
             AsyncWriteCallbackHandler callbackHandler,
 415  
             AsyncQueueDataProcessor writePreProcessor) throws IOException {
 416  20000
         writeToAsyncQueue(buffer, callbackHandler, writePreProcessor, false);
 417  20000
     }
 418  
 
 419  
     
 420  
     /**
 421  
      * {@inheritDoc}
 422  
      */
 423  
     public void writeToAsyncQueue(ByteBuffer buffer, 
 424  
             AsyncWriteCallbackHandler callbackHandler, 
 425  
             AsyncQueueDataProcessor writePreProcessor,
 426  
             boolean isCloneByteBuffer) throws IOException {
 427  20000
         selectorHandler.getAsyncQueueWriter().write(
 428  
                 datagramChannel.keyFor(selectorHandler.getSelector()), buffer,
 429  
                 callbackHandler, writePreProcessor, isCloneByteBuffer);
 430  20000
     }
 431  
 
 432  
     
 433  
     /**
 434  
      * {@inheritDoc}
 435  
      */
 436  
     public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer)
 437  
             throws IOException {
 438  0
         writeToAsyncQueue(dstAddress, buffer, null);
 439  0
     }
 440  
 
 441  
 
 442  
     /**
 443  
      * {@inheritDoc}
 444  
      */
 445  
     public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer, 
 446  
             AsyncWriteCallbackHandler callbackHandler) throws IOException {
 447  0
         writeToAsyncQueue(dstAddress, buffer, callbackHandler, null);
 448  0
     }
 449  
 
 450  
 
 451  
     /**
 452  
      * {@inheritDoc}
 453  
      */
 454  
     public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer, 
 455  
             AsyncWriteCallbackHandler callbackHandler,
 456  
             AsyncQueueDataProcessor writePreProcessor) throws IOException {
 457  0
         writeToAsyncQueue(dstAddress, buffer, callbackHandler, writePreProcessor,
 458  
                 false);
 459  0
     }
 460  
 
 461  
     
 462  
     /**
 463  
      * {@inheritDoc}
 464  
      */
 465  
     public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer, 
 466  
             AsyncWriteCallbackHandler callbackHandler, 
 467  
             AsyncQueueDataProcessor writePreProcessor, boolean isCloneByteBuffer)
 468  
             throws IOException {
 469  0
         selectorHandler.getAsyncQueueWriter().write(
 470  
                 datagramChannel.keyFor(selectorHandler.getSelector()), dstAddress,
 471  
                 buffer, callbackHandler, writePreProcessor, isCloneByteBuffer);
 472  0
     }
 473  
 
 474  
     
 475  
     /**
 476  
      * Receive bytes.
 477  
      * @param byteBuffer The byteBuffer to store bytes.
 478  
      * @param socketAddress
 479  
      * @return number bytes sent
 480  
      * @throws java.io.IOException
 481  
      */
 482  
     public long send(ByteBuffer byteBuffer, SocketAddress socketAddress)
 483  
     throws IOException {
 484  0
         if (!isConnected){
 485  0
             throw new NotYetConnectedException();
 486  
         }
 487  
         
 488  0
         if (callbackHandler == null){
 489  0
             throw new IllegalStateException
 490  
                     ("Non blocking read needs a CallbackHandler");
 491  
         }
 492  
         
 493  0
         return datagramChannel.send(byteBuffer,socketAddress);
 494  
     }
 495  
     
 496  
     
 497  
     /**
 498  
      * Receive bytes.
 499  
      * @param byteBuffer The byteBuffer to store bytes.
 500  
      * @return {@link SocketAddress}
 501  
      * @throws java.io.IOException
 502  
      */
 503  
     public SocketAddress receive(ByteBuffer byteBuffer) throws IOException {
 504  0
         if (!isConnected){
 505  0
             throw new NotYetConnectedException();
 506  
         }
 507  
         
 508  0
         SelectionKey key = datagramChannel.keyFor(selectorHandler.getSelector());
 509  
         
 510  0
         if (callbackHandler == null){
 511  0
             throw new IllegalStateException
 512  
                     ("Non blocking read needs a CallbackHandler");
 513  
         }
 514  
         
 515  0
         SocketAddress socketAddress = datagramChannel.receive(byteBuffer);
 516  0
         return socketAddress;
 517  
     }
 518  
     
 519  
     
 520  
     /**
 521  
      * Close the underlying connection.
 522  
      */
 523  
     public void close() throws IOException{
 524  31
         if (datagramChannel != null){
 525  31
             if (selectorHandler != null){
 526  31
                 SelectionKey key =
 527  
                         datagramChannel.keyFor(selectorHandler.getSelector());
 528  
                 
 529  31
                 if (key == null) return;
 530  
                 
 531  31
                 selectorHandler.getSelectionKeyHandler().cancel(key);
 532  31
             } else {
 533  0
                 datagramChannel.close();
 534  
             }
 535  
         }
 536  
         
 537  31
         if (controller != null && isStandalone){
 538  0
             controller.stop();
 539  0
             controller = null;
 540  
         }
 541  
         
 542  31
         isStandalone = false;
 543  31
         isConnected = false;
 544  31
     }
 545  
     
 546  
     
 547  
     /**
 548  
      * Finish handling the OP_CONNECT interest ops.
 549  
      */
 550  
     public void finishConnect(SelectionKey key) throws IOException {
 551  31
         if (Controller.logger().isLoggable(Level.FINE)) {
 552  0
             Controller.logger().log(Level.FINE, "Finish connect");
 553  
         }
 554  
         
 555  31
         datagramChannel = (DatagramChannel)key.channel();
 556  31
         isConnected = datagramChannel.isConnected();
 557  31
         if (isConnectedLatch != null) {
 558  31
             isConnectedLatch.countDown();
 559  
         }
 560  31
     }
 561  
     
 562  
     
 563  
     /**
 564  
      * A token decribing the protocol supported by an implementation of this
 565  
      * interface
 566  
      */
 567  
     public Controller.Protocol protocol(){
 568  62
         return Controller.Protocol.UDP;
 569  
     }
 570  
     
 571  
     
 572  
     /**
 573  
      * Is the underlying DatagramChannel connected.
 574  
      * @return true if connected, othewise false
 575  
      */
 576  
     public boolean isConnected(){
 577  0
         return isConnected && datagramChannel.isOpen();
 578  
     }
 579  
     
 580  
     
 581  
     /**
 582  
      * Return the  {@link Controller}
 583  
      * @return the  {@link Controller}
 584  
      */
 585  
     public Controller getController() {
 586  0
         return controller;
 587  
     }
 588  
     
 589  
     
 590  
     /**
 591  
      * Set the {@link Controller} to use with this instance.
 592  
      * @param controller the {@link Controller} to use with this instance.
 593  
      */
 594  
     public void setController(Controller controller) {
 595  62
         this.controller = controller;
 596  62
     }
 597  
     
 598  
     
 599  
     /**
 600  
      * Return the current {@link SocketChannel} used.
 601  
      * @return the current {@link SocketChannel} used.
 602  
      */
 603  
     public SelectableChannel getUnderlyingChannel() {
 604  0
         return datagramChannel;
 605  
     }
 606  
     
 607  
     
 608  
     /**
 609  
      * Return the {@link CallbackHandler}. 
 610  
      * @return the {@link CallbackHandler}. 
 611  
      */
 612  
     public CallbackHandler getCallbackHandler() {
 613  0
         return callbackHandler;
 614  
     }
 615  
     
 616  
 
 617  
     /**
 618  
      * Set the {@link CallbackHandler}. 
 619  
      * @param callbackHandler the {@link CallbackHandler}. 
 620  
      */   
 621  
     public void setCallbackHandler(CallbackHandler callbackHandler) {
 622  0
         this.callbackHandler = callbackHandler;
 623  0
     }   
 624  
     
 625  
         
 626  
     /**
 627  
      * Return the associated {@link SelectorHandler}.
 628  
      * @return the associated {@link SelectorHandler}.
 629  
      */
 630  
     public UDPSelectorHandler getSelectorHandler() {
 631  0
         return selectorHandler;
 632  
     }
 633  
 }