Exemplo n.º 1
0
  /**
   * Registers a new channel with this Selector. If we've already stored over the limit of channels,
   * this will store the channel in a temporary list to be cancelled on the next selection.
   */
  @Override
  protected synchronized SelectionKey register(AbstractSelectableChannel ch, int ops, Object att) {
    int connID;

    if (!(ch instanceof UDPSocketChannel)) throw new IllegalSelectorException();

    UDPSocketChannel channel = (UDPSocketChannel) ch;

    UDPSocketChannel[] copy = new UDPSocketChannel[_channels.length];
    for (int i = 0; i < _channels.length; i++) copy[i] = _channels[i];

    for (int i = 1; i <= copy.length; i++) {
      connID = (_lastConnectionID + i) % 256;

      // We don't assign zero.
      if (connID == 0) continue;

      // If the slot is open, take it.
      if (copy[connID] == null) {
        _lastConnectionID = connID;
        copy[connID] = channel;
        channel.getProcessor().setConnectionId((byte) connID);
        _channels = copy;
        return new UDPSelectionKey(this, att, ch, ops);
      }
    }

    // We don't have enough space for this connection.  Add it to a temporary
    // list of bad connections which will be removed during selectNow.
    LOG.warn("Attempting to add over connection limit");
    channelsToRemove.add(ch);
    return new UDPSelectionKey(this, att, ch, ops);
  }
Exemplo n.º 2
0
  /** Polls through all available channels and returns those that are ready. */
  @Override
  public int selectNow() throws IOException {
    UDPSocketChannel[] array = _channels;
    UDPSocketChannel[] removed = null;

    selectedKeys.clear();

    for (int i = 0; i < array.length; i++) {
      UDPSocketChannel channel = array[i];
      if (channel == null) continue;

      UDPSelectionKey key = (UDPSelectionKey) channel.keyFor(this);
      if (key != null) {
        if (key.isValid() && channel.isOpen()) {
          int currentOps = channel.getProcessor().readyOps();
          int readyOps = currentOps & key.interestOps();
          if (readyOps != 0) {
            key.setReadyOps(readyOps);
            selectedKeys.add(key);
          }
        } else {
          if (removed == null) removed = new UDPSocketChannel[array.length];
          removed[i] = channel;
        }
      }
    }

    // Go through the removed list & remove them from _connections.
    // _connections may have changed (since we didn't lock while polling),
    // so we need to check and ensure the given UDPConnectionProcessor
    // is the same.
    synchronized (this) {
      if (removed != null) {
        UDPSocketChannel[] copy = new UDPSocketChannel[_channels.length];
        for (int i = 0; i < _channels.length; i++) {
          if (_channels[i] == removed[i]) copy[i] = null;
          else copy[i] = _channels[i];
        }
        _channels = copy;
      }

      if (!channelsToRemove.isEmpty()) {
        for (SelectableChannel next : channelsToRemove) {
          UDPSelectionKey key = (UDPSelectionKey) next.keyFor(this);
          key.cancel();
          key.setReadyOps(0);
          selectedKeys.add(key);
        }
        channelsToRemove.clear();
      }
    }

    return selectedKeys.size();
  }
Exemplo n.º 3
0
  /** Determines if we're connected to the given host. */
  public boolean isConnectedTo(InetAddress host) {
    UDPSocketChannel[] array = _channels;

    if (_lastConnectionID == 0) return false;
    for (int i = 0; i < array.length; i++) {
      UDPSocketChannel channel = array[i];
      if (channel != null && host.equals(channel.getRemoteSocketAddress().getAddress())) {
        return true;
      }
    }
    return false;
  }
Exemplo n.º 4
0
  /**
   * Route a message to the {@link UDPConnectionProcessor} identified via the message's connection
   * ID. Notifies the provided listener (if any) if the channel is ready to produce events.
   */
  public void routeMessage(RUDPMessage msg, InetSocketAddress addr) {
    UDPSocketChannel[] array = _channels;
    int connID = msg.getConnectionID() & 0xff;
    UDPSocketChannel channel = null;
    // If connID equals 0 and SynMessage then associate with a connection
    // that appears to want it (connecting and with knowledge of it).
    if (connID == 0 && msg instanceof SynMessage) {
      LOG.debugf("route sym: {0}", msg);
      for (int i = 1; i < array.length; i++) {
        channel = array[i];
        if (channel == null) continue;

        LOG.debugf("non-empty index: {0}, addr: {1}", i, channel.getRemoteSocketAddress());

        if (channel.isConnectionPending() && channel.isForMe(addr, (SynMessage) msg)) {
          LOG.debugf(
              "found index: {0}, sender id: {1}", i, ((SynMessage) msg).getSenderConnectionID());
          channel.getProcessor().handleMessage(msg);
          break;
        }
      }
      // Note: eventually these messages should find a match
      // so it is safe to throw away premature ones

    } else if (array[connID] != null) { // If valid connID then send on to connection
      channel = array[connID];
      if (msg instanceof SynMessage) {
        LOG.debugf("already assigned syn: {0}", msg);
      }
      if (channel.getRemoteSocketAddress().equals(addr)) channel.getProcessor().handleMessage(msg);
    } else {
      LOG.debugf("message for non-existing connection: {0}", msg);
    }

    if (channel != null && channel.getProcessor().readyOps() != 0)
      context.getTransportListener().eventPending();
  }