/**
  * a DatagramChannel has data ready - process all the pending packets, whether its for a
  * rdpserversocket or rdpconnection.
  */
 void processActiveChannel(DatagramChannel dc) throws ClosedChannelException {
   RDPPacket packet;
   int count = 0;
   // read in the packet
   try {
     Set<RDPConnection> needsAckConnections = new HashSet<RDPConnection>();
     while ((packet = RDPServer.receivePacket(dc)) != null) {
       if (Log.loggingNet)
         Log.net(
             "RDPServer.processActiveChannel: Starting iteration with count of "
                 + count
                 + " packets");
       // see if there is a connection already for this packet
       InetAddress remoteAddr = packet.getInetAddress();
       int remotePort = packet.getPort();
       int localPort = dc.socket().getLocalPort();
       ConnectionInfo conInfo = new ConnectionInfo(remoteAddr, remotePort, localPort);
       RDPConnection con = RDPServer.getConnection(dc, conInfo);
       if (con != null) {
         if (Log.loggingNet)
           Log.net("RDPServer.processActiveChannel: found an existing connection: " + con);
         count++;
         if (processExistingConnection(con, packet)) needsAckConnections.add(con);
         // Prevent this from blocking getActiveChannels by
         // putting an upper bound on the number of packets
         // processed
         if (count >= 20) break;
         continue;
       } else {
         Log.net("RDPServer.processActiveChannel: did not find an existing connection");
       }
       // there is no connection,
       // see if there is a socket listening for new connection
       RDPServerSocket rdpSocket = RDPServer.getRDPSocket(dc);
       if (rdpSocket != null) {
         count++;
         processNewConnection(rdpSocket, packet);
         return;
       }
       return;
     }
     // Finally, send out the acks
     for (RDPConnection con : needsAckConnections) {
       RDPPacket replyPacket = new RDPPacket(con);
       con.sendPacketImmediate(replyPacket, false);
     }
   } catch (ClosedChannelException ex) {
     Log.error("RDPServer.processActiveChannel: ClosedChannel " + dc.socket());
     throw ex;
   } finally {
     if (Log.loggingNet)
       Log.net("RDPServer.processActiveChannel: Returning after processing " + count + " packets");
   }
 }
  /** rdpserversocket wants to bind on a local port */
  static DatagramChannel bind(Integer port, int receiveBufferSize)
      throws java.net.BindException, java.io.IOException, java.net.SocketException {
    lock.lock();
    try {
      // see if there is an existing datagramchannel bound to this port
      DatagramChannel dc = channelMap.get(port);
      if (dc != null) {
        throw new java.net.BindException("RDPServer.bind: port is already used");
      }

      // make a new datagram channel
      dc = DatagramChannel.open();
      dc.configureBlocking(false);
      dc.socket().setReceiveBufferSize(receiveBufferSize);
      if (port == null) {
        if (Log.loggingNet) Log.net("RDPServer.bind: binding to a random system port");
        dc.socket().bind(null);
      } else {
        if (Log.loggingNet) Log.net("RDPServer.bind: binding to port " + port);
        dc.socket().bind(new InetSocketAddress(port));
      }
      int resultingPort = dc.socket().getLocalPort();
      if (Log.loggingNet) Log.net("RDPServer.bind: resulting port=" + resultingPort);

      // add the channel to the channel map
      channelMap.put(resultingPort, dc);
      if (Log.loggingNet) Log.net("RDPServer.bind: added dc to channel map");

      // add the channel to the newChannelsSet
      // we want to register this channel with the selector
      // but the selector thread needs to do that,
      // so place it in this set, and wake up the selector
      newChannelSet.add(dc);
      if (Log.loggingNet) Log.net("RDPServer.bind: added dc to newChannelSet");

      // in case the rdpserver was waiting while it had no sockets,
      // signal it
      channelMapNotEmpty.signal();
      Log.net("RDPServer.bind: signalled channel map not empty condition");

      // wakeup the selector -
      // it needs to register the new channel with itself
      selector.wakeup();

      if (Log.loggingNet) Log.net("RDPServer.bind: woke up selector");
      return dc;
    } finally {
      lock.unlock();
    }
  }
  /**
   * removes this connection from the connections map the datagram channel still sticks around in
   * case it needs to be reused
   */
  static void removeConnection(RDPConnection con) {
    lock.lock();
    try {
      if (Log.loggingNet) Log.net("RDPServer.removeConnection: removing con " + con);
      con.setState(RDPConnection.CLOSED);

      DatagramChannel dc = con.getDatagramChannel();

      // first we get the set of connections attached to the given dc
      Map<ConnectionInfo, RDPConnection> dcConMap = allConMap.get(dc);
      if (dcConMap == null) {
        throw new MVRuntimeException("RDPServer.removeConnection: cannot find dc");
      }

      int localPort = con.getLocalPort();
      int remotePort = con.getRemotePort();
      InetAddress remoteAddr = con.getRemoteAddr();
      ConnectionInfo conInfo = new ConnectionInfo(remoteAddr, remotePort, localPort);
      Object rv = dcConMap.remove(conInfo);
      if (rv == null) {
        throw new MVRuntimeException("RDPServer.removeConnection: could not find the connection");
      }

      // close the datagramchannel if needed
      // conditions: no other connections on this datagramchannel
      // no socket listening on this datagramchannel
      if (dcConMap.isEmpty()) {
        Log.net("RDPServer.removeConnection: no other connections for this datagramchannel (port)");
        // there are no more connections on this datagram channel
        // check if there is a serversocket listening
        if (getRDPSocket(dc) == null) {
          Log.net("RDPServer.removeConnection: no socket listening on this port - closing");
          // no socket either, close the datagramchannel
          dc.socket().close();
          channelMap.remove(localPort);
          Log.net("RDPServer.removeConnection: closed and removed datagramchannel/socket");
        } else {
          Log.net("RDPServer.removeConnection: there is a socket listening on this port");
        }
      } else {
        Log.net("RDPServer.removeConnection: there are other connections on this port");
      }
    } finally {
      lock.unlock();
    }
  }