Example #1
0
  /**
   * Method parseClientPacket.
   *
   * @param handler IPacketHandler<T>
   * @param buf ByteBuffer
   * @param dataSize int
   * @param con MMOConnection<T>
   * @return boolean
   */
  protected boolean parseClientPacket(
      IPacketHandler<T> handler, ByteBuffer buf, int dataSize, MMOConnection<T> con) {
    T client = con.getClient();

    int pos = buf.position();

    client.decrypt(buf, dataSize);
    buf.position(pos);

    if (buf.hasRemaining()) {
      // apply limit
      int limit = buf.limit();
      buf.limit(pos + dataSize);
      ReceivablePacket<T> rp = handler.handlePacket(buf, client);

      if (rp != null) {
        rp.setByteBuffer(buf);
        rp.setClient(client);

        if (rp.read()) {
          con.recvPacket(rp);
        }

        rp.setByteBuffer(null);
      }
      buf.limit(limit);
    }
    return true;
  }
Example #2
0
  /**
   * Method acceptConnection.
   *
   * @param key SelectionKey
   */
  protected void acceptConnection(SelectionKey key) {
    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
    SocketChannel sc;
    SelectionKey clientKey;
    try {
      while ((sc = ssc.accept()) != null) {
        if ((getAcceptFilter() == null) || getAcceptFilter().accept(sc)) {
          sc.configureBlocking(false);
          clientKey = sc.register(getSelector(), SelectionKey.OP_READ);

          MMOConnection<T> con = new MMOConnection<>(this, sc.socket(), clientKey);
          T client = getClientFactory().create(con);
          client.setConnection(con);
          con.setClient(client);
          clientKey.attach(con);

          _connections.add(con);
          stats.increaseOpenedConnections();
        } else {
          sc.close();
        }
      }
    } catch (IOException e) {
      _log.error("Error in " + getName(), e);
    }
  }
Example #3
0
  /**
   * Method tryReadPacket2.
   *
   * @param key SelectionKey
   * @param con MMOConnection<T>
   * @param buf ByteBuffer
   * @return boolean
   */
  protected boolean tryReadPacket2(SelectionKey key, MMOConnection<T> con, ByteBuffer buf) {
    if (con.isClosed()) {
      return false;
    }

    int pos = buf.position();
    if (buf.remaining() > _sc.HEADER_SIZE) {
      int size = buf.getShort() & 0xffff;

      if ((size <= _sc.HEADER_SIZE) || (size > _sc.PACKET_SIZE)) {
        _log.error(
            "Incorrect packet size : "
                + size
                + "! Client : "
                + con.getClient()
                + ". Closing connection.");
        closeConnectionImpl(con);
        return false;
      }

      size -= _sc.HEADER_SIZE;

      if (size <= buf.remaining()) {
        stats.increaseIncomingPacketsCount();
        parseClientPacket(getPacketHandler(), buf, size, con);
        buf.position(pos + size + _sc.HEADER_SIZE);

        if (!buf.hasRemaining()) {
          freeBuffer(buf, con);
          return false;
        }

        return true;
      }

      buf.position(pos);
    }

    if (pos == buf.capacity()) {
      _log.warn(
          "Read buffer exhausted for client : "
              + con.getClient()
              + ", try to adjust buffer size, current : "
              + buf.capacity()
              + ", primary : "
              + (buf == READ_BUFFER)
              + ".");
    }

    if (buf == READ_BUFFER) {
      allocateReadBuffer(con);
    } else {
      buf.compact();
    }

    return false;
  }
Example #4
0
 /**
  * Method finishConnection.
  *
  * @param key SelectionKey
  */
 protected void finishConnection(SelectionKey key) {
   try {
     ((SocketChannel) key.channel()).finishConnect();
   } catch (IOException e) {
     MMOConnection<T> con = (MMOConnection<T>) key.attachment();
     T client = con.getClient();
     client.getConnection().onForcedDisconnection();
     closeConnectionImpl(client.getConnection());
   }
 }
Example #5
0
 /**
  * Method freeBuffer.
  *
  * @param buf ByteBuffer
  * @param con MMOConnection<T>
  */
 protected void freeBuffer(ByteBuffer buf, MMOConnection<T> con) {
   if (buf == READ_BUFFER) {
     READ_BUFFER.clear();
   } else {
     con.setReadBuffer(null);
     recycleBuffer(buf);
   }
 }
Example #6
0
  /**
   * Method writePacket.
   *
   * @param key SelectionKey
   */
  protected void writePacket(SelectionKey key) {
    MMOConnection<T> con = (MMOConnection<T>) key.attachment();

    prepareWriteBuffer(con);

    DIRECT_WRITE_BUFFER.flip();
    int size = DIRECT_WRITE_BUFFER.remaining();

    int result = -1;

    try {
      result = con.getWritableChannel().write(DIRECT_WRITE_BUFFER);
    } catch (IOException e) {
      // error handling goes on the if bellow
    }

    // check if no error happened
    if (result >= 0) {
      stats.increaseOutgoingBytes(result);

      // check if we written everything
      if (result != size) {
        con.createWriteBuffer(DIRECT_WRITE_BUFFER);
      }

      if (!con.getSendQueue().isEmpty() || con.hasPendingWriteBuffer()) {
        con.scheduleWriteInterest();
      }
    } else {
      con.onForcedDisconnection();
      closeConnectionImpl(con);
    }
  }
Example #7
0
  /**
   * Method readPacket.
   *
   * @param key SelectionKey
   */
  protected void readPacket(SelectionKey key) {
    MMOConnection<T> con = (MMOConnection<T>) key.attachment();

    if (con.isClosed()) {
      return;
    }

    ByteBuffer buf;
    int result = -2;

    if ((buf = con.getReadBuffer()) == null) {
      buf = READ_BUFFER;
    }

    // if we try to to do a read with no space in the buffer it will read 0 bytes
    // going into infinite loop
    if (buf.position() == buf.limit()) {
      _log.error(
          "Read buffer exhausted for client : "
              + con.getClient()
              + ", try to adjust buffer size, current : "
              + buf.capacity()
              + ", primary : "
              + (buf == READ_BUFFER)
              + ". Closing connection.");
      closeConnectionImpl(con);
    } else {

      try {
        result = con.getReadableByteChannel().read(buf);
      } catch (IOException e) {
        // error handling goes bellow
      }

      if (result > 0) {
        buf.flip();

        stats.increaseIncomingBytes(result);

        @SuppressWarnings("unused")
        int i;
        for (i = 0; this.tryReadPacket2(key, con, buf); i++) {}
      } else if (result == 0) {
        closeConnectionImpl(con);
      } else if (result == -1) {
        closeConnectionImpl(con);
      } else {
        con.onForcedDisconnection();
        closeConnectionImpl(con);
      }
    }

    if (buf == READ_BUFFER) {
      buf.clear();
    }
  }
Example #8
0
  /**
   * Method prepareWriteBuffer.
   *
   * @param con MMOConnection<T>
   */
  protected void prepareWriteBuffer(MMOConnection<T> con) {
    WRITE_CLIENT = con.getClient();
    DIRECT_WRITE_BUFFER.clear();

    if (con.hasPendingWriteBuffer()) {
      con.movePendingWriteBufferTo(DIRECT_WRITE_BUFFER);
    }

    if (DIRECT_WRITE_BUFFER.hasRemaining() && !con.hasPendingWriteBuffer()) {
      int i;
      Queue<SendablePacket<T>> sendQueue = con.getSendQueue();
      SendablePacket<T> sp;

      for (i = 0; i < _sc.MAX_SEND_PER_PASS; i++) {
        synchronized (con) {
          if ((sp = sendQueue.poll()) == null) {
            break;
          }
        }

        try {
          stats.increaseOutgoingPacketsCount();
          putPacketIntoWriteBuffer(sp, true);
          WRITE_BUFFER.flip();
          if (DIRECT_WRITE_BUFFER.remaining() >= WRITE_BUFFER.limit()) {
            DIRECT_WRITE_BUFFER.put(WRITE_BUFFER);
          } else {
            con.createWriteBuffer(WRITE_BUFFER);
            break;
          }
        } catch (Exception e) {
          _log.error("Error in " + getName(), e);
          break;
        }
      }
    }

    WRITE_BUFFER.clear();
    WRITE_CLIENT = null;
  }
Example #9
0
  /**
   * Method closeConnectionImpl.
   *
   * @param con MMOConnection<T>
   */
  protected void closeConnectionImpl(MMOConnection<T> con) {
    try {
      // notify connection
      con.onDisconnection();
    } finally {
      try {
        // close socket and the SocketChannel
        con.close();
      } catch (IOException e) {
        // ignore, we are closing anyway
      } finally {
        con.releaseBuffers();
        con.clearQueues();
        con.getClient().setConnection(null);
        con.getSelectionKey().attach(null);
        con.getSelectionKey().cancel();

        _connections.remove(con);

        stats.decreseOpenedConnections();
      }
    }
  }
Example #10
0
 /**
  * Method allocateReadBuffer.
  *
  * @param con MMOConnection<T>
  */
 protected void allocateReadBuffer(MMOConnection<T> con) {
   con.setReadBuffer(getPooledBuffer().put(READ_BUFFER));
   READ_BUFFER.clear();
 }
Example #11
0
  /**
   * Method run.
   *
   * @see java.lang.Runnable#run()
   */
  @Override
  public void run() {
    int totalKeys = 0;
    Set<SelectionKey> keys = null;
    Iterator<SelectionKey> itr = null;
    Iterator<MMOConnection<T>> conItr = null;
    SelectionKey key = null;
    MMOConnection<T> con = null;
    long currentMillis = 0L;

    // main loop
    for (; ; ) {
      try {

        if (isShuttingDown()) {
          closeSelectorThread();
          break;
        }

        currentMillis = System.currentTimeMillis();

        conItr = _connections.iterator();
        while (conItr.hasNext()) {
          con = conItr.next();
          if (con.isPengingClose()) {
            if (!con.isPendingWrite() || ((currentMillis - con.getPendingCloseTime()) >= 10000L)) {
              closeConnectionImpl(con);
              continue;
            }
          }
          if (con.isPendingWrite()) {
            if ((currentMillis - con.getPendingWriteTime()) >= _sc.INTEREST_DELAY) {
              con.enableWriteInterest();
            }
          }
        }

        totalKeys = getSelector().selectNow();

        if (totalKeys > 0) {
          keys = getSelector().selectedKeys();
          itr = keys.iterator();

          while (itr.hasNext()) {
            key = itr.next();
            itr.remove();

            if (key.isValid()) {
              try {
                if (key.isAcceptable()) {
                  acceptConnection(key);
                  continue;
                } else if (key.isConnectable()) {
                  finishConnection(key);
                  continue;
                }

                if (key.isReadable()) {
                  readPacket(key);
                }
                if (key.isValid()) {
                  if (key.isWritable()) {
                    writePacket(key);
                  }
                }
              } catch (CancelledKeyException cke) {

              }
            }
          }
        }

        try {
          Thread.sleep(_sc.SLEEP_TIME);
        } catch (InterruptedException ie) {

        }
      } catch (IOException e) {
        _log.error("Error in " + getName(), e);

        try {
          Thread.sleep(1000L);
        } catch (InterruptedException ie) {

        }
      }
    }
  }