<commit_before>/*
 * Copyright 2010-2012 <NAME> (l.garulli--at--orientechnologies.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.orientechnologies.orient.server.network;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.BindException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.config.OContextConfiguration;
import com.orientechnologies.orient.core.config.OGlobalConfiguration;
import com.orientechnologies.orient.core.serialization.serializer.OStringSerializerHelper;
import com.orientechnologies.orient.enterprise.channel.binary.ONetworkProtocolException;
import com.orientechnologies.orient.server.OClientConnectionManager;
import com.orientechnologies.orient.server.OServer;
import com.orientechnologies.orient.server.config.OServerCommandConfiguration;
import com.orientechnologies.orient.server.config.OServerParameterConfiguration;
import com.orientechnologies.orient.server.network.protocol.ONetworkProtocol;
import com.orientechnologies.orient.server.network.protocol.http.command.OServerCommand;

public class OServerNetworkListener extends Thread {
  private ServerSocket                      serverSocket;
  private InetSocketAddress                 inboundAddr;
  private Class<? extends ONetworkProtocol> protocolType;
  private volatile boolean                  active            = true;
  private List<OServerCommandConfiguration> statefulCommands  = new ArrayList<OServerCommandConfiguration>();
  private List<OServerCommand>              statelessCommands = new ArrayList<OServerCommand>();
  private int                               socketBufferSize;
  private OContextConfiguration             configuration;
  private OServer                           server;
  private ONetworkProtocol                  protocol;
  private int                               protocolVersion   = -1;

  public OServerNetworkListener(final OServer iServer, final String iHostName, final String iHostPortRange,
      final String iProtocolName, final Class<? extends ONetworkProtocol> iProtocol,
      final OServerParameterConfiguration[] iParameters, final OServerCommandConfiguration[] iCommands) {
    super(Orient.instance().getThreadGroup(), "OrientDB " + iProtocol.getSimpleName() + " listen at " + iHostName + ":"
        + iHostPortRange);
    server = iServer;

    // DETERMINE THE PROTOCOL VERSION BY CREATING A NEW ONE AND THEN THROW IT AWAY
    // TODO: CREATE PROTOCOL FACTORIES INSTEAD
    try {
      protocolVersion = iProtocol.newInstance().getVersion();
    } catch (Exception e) {
      OLogManager.instance().error(this, "Error on reading protocol version for %s", e, ONetworkProtocolException.class,
          protocolType);
    }

    listen(iHostName, iHostPortRange, iProtocolName);
    protocolType = iProtocol;

    readParameters(iServer.getContextConfiguration(), iParameters);

    if (iCommands != null) {
      for (int i = 0; i < iCommands.length; ++i) {
        if (iCommands[i].stateful)
          // SAVE STATEFUL COMMAND CFG
          statefulCommands.add(iCommands[i]);
        else
          // EARLY CREATE STATELESS COMMAND
          statelessCommands.add(OServerNetworkListener.createCommand(server, iCommands[i]));
      }
    }

    start();
  }

  public void shutdown() {
    this.active = false;

    if (protocol != null) {
      protocol.sendShutdown();
      protocol = null;
    }

    if (serverSocket != null)
      try {
        serverSocket.close();
      } catch (IOException e) {
      }
  }

  /**
   * Initialize a server socket for communicating with the client.
   * 
   * @param iHostPortRange
   * @param iHostName
   */
  private void listen(final String iHostName, final String iHostPortRange, final String iProtocolName) {
    final int[] ports = getPorts(iHostPortRange);

    for (int port : ports) {
      inboundAddr = new InetSocketAddress(iHostName, port);
      try {
        serverSocket = new java.net.ServerSocket(port, 0, InetAddress.getByName(iHostName));

        if (serverSocket.isBound()) {
          OLogManager.instance().info(
              this,
              "Listening " + iProtocolName + " connections on " + inboundAddr.getAddress().getHostAddress() + ":"
                  + inboundAddr.getPort() + " (protocol v." + protocolVersion + ")");
          return;
        }
      } catch (BindException be) {
        OLogManager.instance().info(this, "Port %s:%d busy, trying the next available...", iHostName, port);
      } catch (SocketException se) {
        OLogManager.instance().error(this, "Unable to create socket", se);
        System.exit(1);
      } catch (IOException ioe) {
        OLogManager.instance().error(this, "Unable to read data from an open socket", ioe);
        System.err.println("Unable to read data from an open socket.");
        System.exit(1);
      }
    }

    OLogManager.instance().error(this, "Unable to listen for connections using the configured ports '%s' on host '%s'",
        iHostPortRange, iHostName);
    System.exit(1);
  }

  public boolean isActive() {
    return active;
  }

  @Override
  public void run() {
    try {
      while (active) {
        try {
          // listen for and accept a client connection to serverSocket
          final Socket socket = serverSocket.accept();

          final int conns = OClientConnectionManager.instance().getTotal();
          if (conns >= OGlobalConfiguration.NETWORK_MAX_CONCURRENT_SESSIONS.getValueAsInteger()) {
            // MAXIMUM OF CONNECTIONS EXCEEDED
            OLogManager.instance().warn(this,
                "Reached maximum number of concurrent connections (%d), reject incoming connection from %s", conns,
                socket.getRemoteSocketAddress());
            socket.close();

            // PAUSE CURRENT THREAD TO SLOW DOWN ANY POSSIBLE ATTACK
            Thread.sleep(100);
          }

          socket.setPerformancePreferences(0, 2, 1);
          socket.setSendBufferSize(socketBufferSize);
          socket.setReceiveBufferSize(socketBufferSize);

          // CREATE A NEW PROTOCOL INSTANCE
          protocol = protocolType.newInstance();

          // CONFIGURE THE PROTOCOL FOR THE INCOMING CONNECTION
          protocol.config(server, socket, configuration, statelessCommands, statefulCommands);

        } catch (Throwable e) {
          if (active)
            OLogManager.instance().error(this, "Error on client connection", e);<commit_msg>Fixed issue on DOS server attack<commit_after>/*
 * Copyright 2010-2012 <NAME> (l.garulli--at--orientechnologies.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.orientechnologies.orient.server.network;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.BindException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.config.OContextConfiguration;
import com.orientechnologies.orient.core.config.OGlobalConfiguration;
import com.orientechnologies.orient.core.serialization.serializer.OStringSerializerHelper;
import com.orientechnologies.orient.enterprise.channel.binary.ONetworkProtocolException;
import com.orientechnologies.orient.server.OClientConnectionManager;
import com.orientechnologies.orient.server.OServer;
import com.orientechnologies.orient.server.config.OServerCommandConfiguration;
import com.orientechnologies.orient.server.config.OServerParameterConfiguration;
import com.orientechnologies.orient.server.network.protocol.ONetworkProtocol;
import com.orientechnologies.orient.server.network.protocol.http.command.OServerCommand;

public class OServerNetworkListener extends Thread {
  private ServerSocket                      serverSocket;
  private InetSocketAddress                 inboundAddr;
  private Class<? extends ONetworkProtocol> protocolType;
  private volatile boolean                  active            = true;
  private List<OServerCommandConfiguration> statefulCommands  = new ArrayList<OServerCommandConfiguration>();
  private List<OServerCommand>              statelessCommands = new ArrayList<OServerCommand>();
  private int                               socketBufferSize;
  private OContextConfiguration             configuration;
  private OServer                           server;
  private ONetworkProtocol                  protocol;
  private int                               protocolVersion   = -1;

  public OServerNetworkListener(final OServer iServer, final String iHostName, final String iHostPortRange,
      final String iProtocolName, final Class<? extends ONetworkProtocol> iProtocol,
      final OServerParameterConfiguration[] iParameters, final OServerCommandConfiguration[] iCommands) {
    super(Orient.instance().getThreadGroup(), "OrientDB " + iProtocol.getSimpleName() + " listen at " + iHostName + ":"
        + iHostPortRange);
    server = iServer;

    // DETERMINE THE PROTOCOL VERSION BY CREATING A NEW ONE AND THEN THROW IT AWAY
    // TODO: CREATE PROTOCOL FACTORIES INSTEAD
    try {
      protocolVersion = iProtocol.newInstance().getVersion();
    } catch (Exception e) {
      OLogManager.instance().error(this, "Error on reading protocol version for %s", e, ONetworkProtocolException.class,
          protocolType);
    }

    listen(iHostName, iHostPortRange, iProtocolName);
    protocolType = iProtocol;

    readParameters(iServer.getContextConfiguration(), iParameters);

    if (iCommands != null) {
      for (int i = 0; i < iCommands.length; ++i) {
        if (iCommands[i].stateful)
          // SAVE STATEFUL COMMAND CFG
          statefulCommands.add(iCommands[i]);
        else
          // EARLY CREATE STATELESS COMMAND
          statelessCommands.add(OServerNetworkListener.createCommand(server, iCommands[i]));
      }
    }

    start();
  }

  public void shutdown() {
    this.active = false;

    if (protocol != null) {
      protocol.sendShutdown();
      protocol = null;
    }

    if (serverSocket != null)
      try {
        serverSocket.close();
      } catch (IOException e) {
      }
  }

  /**
   * Initialize a server socket for communicating with the client.
   * 
   * @param iHostPortRange
   * @param iHostName
   */
  private void listen(final String iHostName, final String iHostPortRange, final String iProtocolName) {
    final int[] ports = getPorts(iHostPortRange);

    for (int port : ports) {
      inboundAddr = new InetSocketAddress(iHostName, port);
      try {
        serverSocket = new java.net.ServerSocket(port, 0, InetAddress.getByName(iHostName));

        if (serverSocket.isBound()) {
          OLogManager.instance().info(
              this,
              "Listening " + iProtocolName + " connections on " + inboundAddr.getAddress().getHostAddress() + ":"
                  + inboundAddr.getPort() + " (protocol v." + protocolVersion + ")");
          return;
        }
      } catch (BindException be) {
        OLogManager.instance().info(this, "Port %s:%d busy, trying the next available...", iHostName, port);
      } catch (SocketException se) {
        OLogManager.instance().error(this, "Unable to create socket", se);
        System.exit(1);
      } catch (IOException ioe) {
        OLogManager.instance().error(this, "Unable to read data from an open socket", ioe);
        System.err.println("Unable to read data from an open socket.");
        System.exit(1);
      }
    }

    OLogManager.instance().error(this, "Unable to listen for connections using the configured ports '%s' on host '%s'",
        iHostPortRange, iHostName);
    System.exit(1);
  }

  public boolean isActive() {
    return active;
  }

  @Override
  public void run() {
    try {
      while (active) {
        try {
          // listen for and accept a client connection to serverSocket
          final Socket socket = serverSocket.accept();

          final int conns = OClientConnectionManager.instance().getTotal();
          if (conns >= OGlobalConfiguration.NETWORK_MAX_CONCURRENT_SESSIONS.getValueAsInteger()) {
            // MAXIMUM OF CONNECTIONS EXCEEDED
            OLogManager.instance().warn(this,
                "Reached maximum number of concurrent connections (%d), reject incoming connection from %s", conns,
                socket.getRemoteSocketAddress());
            socket.close();

            // PAUSE CURRENT THREAD TO SLOW DOWN ANY POSSIBLE ATTACK
            Thread.sleep(100);
            continue;
          }

          socket.setPerformancePreferences(0, 2, 1);
          socket.setSendBufferSize(socketBufferSize);
          socket.setReceiveBufferSize(socketBufferSize);

          // CREATE A NEW PROTOCOL INSTANCE
          protocol = protocolType.newInstance();

          // CONFIGURE THE PROTOCOL FOR THE INCOMING CONNECTION
          protocol.config(server, socket, configuration, statelessCommands, statefulCommands);

        } catch (Throwable e) {
          if (active)
            OLogManager.instance().error(this, "Error on client connection", e);
{'fraction_non_alphanumeric': 0.09250497154220667, 'fraction_numerical': 0.0032915038058012754, 'mean_word_length': 3.0231724137931035, 'pattern_counts': {'":': 4, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3233425', 'n_tokens_mistral': 3935, 'n_tokens_neox': 3849, 'n_words': 1033}