<commit_before>/*
   Copyright 2011 <NAME>

   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 uk.org.cowgill.james.jircd.network;

import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.security.SecureRandom;
import java.util.Arrays;

import org.apache.log4j.Logger;

import uk.org.cowgill.james.jircd.Client;
import uk.org.cowgill.james.jircd.ConnectionClass;
import uk.org.cowgill.james.jircd.IRCMask;
import uk.org.cowgill.james.jircd.Message;
import uk.org.cowgill.james.jircd.Server;

/**
 * A networking client implementation
 * 
 * @author James
 */
class NetworkClient extends Client
{
	private static final ConnectionClass DEFAULT_CONN_CLASS = new ConnectionClass();
	
	private static final SecureRandom randomGen = new SecureRandom();
	
	/**
	 * Timeout after a ping has been sent to the client
	 */
	public static final int AFTER_PING_TIMEOUT = 5;
	
	//----------------------------------

	private static final Logger logger = Logger.getLogger(NetworkClient.class);
	
	/**
	 * UTF-8 character set encoder
	 */
	private static final CharsetEncoder cEncoder = Charset.forName("UTF-8").newEncoder();
	
	/**
	 * UTF-8 character set decoder
	 */
	private static final CharsetDecoder cDecoder = Charset.forName("UTF-8").newDecoder();
	
	/**
	 * ByteBuffer containing a carriage return then a line feed
	 */
	private static final byte[] CRLF = new byte[] { '\r', '\n' };

	//-----------------------------------
	
	/**
	 * Channel this client is connected to
	 */
	private SocketChannel channel;

	/**
	 * Data for byte buffer
	 */
	private byte[] localBufferData = new byte[1025];
	
	/**
	 * Byte buffer to recent messages
	 */
	private ByteBuffer localBuffer = ByteBuffer.wrap(localBufferData);
	
	/**
	 * Time of the last message to be received by the server
	 */
	private long lastMessageTime;
	
	/**
	 * Timer used for the flood limiter
	 */
	private FloodTimer floodTimer = new FloodTimer(this);
	
	/**
	 * Spoof check string
	 */
	String spoofCheckChars;
	
	/**
	 * Default connection class
	 */
	private ConnectionClass defaultConnClass;
	
	/**
	 * Current connection class
	 */
	private ConnectionClass connClass;
	
	//Static constructor
	static
	{
		//Setup default connection class
		DEFAULT_CONN_CLASS.maxLinks = Integer.MAX_VALUE;
		DEFAULT_CONN_CLASS.pingFreq = 0;	//No "extra" ping frequency
		DEFAULT_CONN_CLASS.readQueue = 1024;
		DEFAULT_CONN_CLASS.sendQueue = 1024;
	}

	/**
	 * Creates a new NetworkClient from a SocketChannel
	 * 
	 * You almost always want to call setup() after this
	 * 
	 * @param channel channel to setup from
	 * @throws IOException thrown when an error occurs in setting socket options
	 */
	NetworkClient(SocketChannel channel) throws IOException
	{
		this(channel, 0);
	}

	/**
	 * Creates a new NetworkClient from a SocketChannel
	 * 
	 * You almost always want to call setup() after this
	 * 
	 * @param channel channel to setup from
	 * @param mode the initial mode of the client
	 * @throws IOException thrown when an error occurs in setting socket options
	 */
	NetworkClient(SocketChannel channel, long mode) throws IOException
	{
		super(new IRCMask(), mode);
		this.channel = channel;
	}
	
	/**
	 * Called to complete setting up a new connection
	 * 
	 * Only call immediately after creating the NetworkClient
	 */
	void setup() throws IOException
	{
		//Setup channel options
		channel.configureBlocking(false);
		channel.socket().setReceiveBufferSize(1024);
		channel.socket().setSoLinger(true, 5);
		changeClass(DEFAULT_CONN_CLASS, true);
		
		//Begin spoof check
		final StringBuffer buffer = new StringBuffer(10);
		for(int i = 0; i < 10; ++i)
		{
			buffer.append((char) (randomGen.nextInt('z' - 'A') + 'A'));
		}
		
		spoofCheckChars = buffer.toString();
		
		send(Message.newStringFromServer("PING :" + spoofCheckChars));
	}
	
	/**
	 * Called when a read event occurs
	 */
	void processReadEvent()
	{
		try
		{
			//Read data
			switch(readWrapper(localBuffer))
			{
				case -1:<commit_msg>Do not send server name with nospoof characters<commit_after>/*
   Copyright 2011 <NAME>

   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 uk.org.cowgill.james.jircd.network;

import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.security.SecureRandom;
import java.util.Arrays;

import org.apache.log4j.Logger;

import uk.org.cowgill.james.jircd.Client;
import uk.org.cowgill.james.jircd.ConnectionClass;
import uk.org.cowgill.james.jircd.IRCMask;
import uk.org.cowgill.james.jircd.Message;
import uk.org.cowgill.james.jircd.Server;

/**
 * A networking client implementation
 * 
 * @author James
 */
class NetworkClient extends Client
{
	private static final ConnectionClass DEFAULT_CONN_CLASS = new ConnectionClass();
	
	private static final SecureRandom randomGen = new SecureRandom();
	
	/**
	 * Timeout after a ping has been sent to the client
	 */
	public static final int AFTER_PING_TIMEOUT = 5;
	
	//----------------------------------

	private static final Logger logger = Logger.getLogger(NetworkClient.class);
	
	/**
	 * UTF-8 character set encoder
	 */
	private static final CharsetEncoder cEncoder = Charset.forName("UTF-8").newEncoder();
	
	/**
	 * UTF-8 character set decoder
	 */
	private static final CharsetDecoder cDecoder = Charset.forName("UTF-8").newDecoder();
	
	/**
	 * ByteBuffer containing a carriage return then a line feed
	 */
	private static final byte[] CRLF = new byte[] { '\r', '\n' };

	//-----------------------------------
	
	/**
	 * Channel this client is connected to
	 */
	private SocketChannel channel;

	/**
	 * Data for byte buffer
	 */
	private byte[] localBufferData = new byte[1025];
	
	/**
	 * Byte buffer to recent messages
	 */
	private ByteBuffer localBuffer = ByteBuffer.wrap(localBufferData);
	
	/**
	 * Time of the last message to be received by the server
	 */
	private long lastMessageTime;
	
	/**
	 * Timer used for the flood limiter
	 */
	private FloodTimer floodTimer = new FloodTimer(this);
	
	/**
	 * Spoof check string
	 */
	String spoofCheckChars;
	
	/**
	 * Default connection class
	 */
	private ConnectionClass defaultConnClass;
	
	/**
	 * Current connection class
	 */
	private ConnectionClass connClass;
	
	//Static constructor
	static
	{
		//Setup default connection class
		DEFAULT_CONN_CLASS.maxLinks = Integer.MAX_VALUE;
		DEFAULT_CONN_CLASS.pingFreq = 0;	//No "extra" ping frequency
		DEFAULT_CONN_CLASS.readQueue = 1024;
		DEFAULT_CONN_CLASS.sendQueue = 1024;
	}

	/**
	 * Creates a new NetworkClient from a SocketChannel
	 * 
	 * You almost always want to call setup() after this
	 * 
	 * @param channel channel to setup from
	 * @throws IOException thrown when an error occurs in setting socket options
	 */
	NetworkClient(SocketChannel channel) throws IOException
	{
		this(channel, 0);
	}

	/**
	 * Creates a new NetworkClient from a SocketChannel
	 * 
	 * You almost always want to call setup() after this
	 * 
	 * @param channel channel to setup from
	 * @param mode the initial mode of the client
	 * @throws IOException thrown when an error occurs in setting socket options
	 */
	NetworkClient(SocketChannel channel, long mode) throws IOException
	{
		super(new IRCMask(), mode);
		this.channel = channel;
	}
	
	/**
	 * Called to complete setting up a new connection
	 * 
	 * Only call immediately after creating the NetworkClient
	 */
	void setup() throws IOException
	{
		//Setup channel options
		channel.configureBlocking(false);
		channel.socket().setReceiveBufferSize(1024);
		channel.socket().setSoLinger(true, 5);
		changeClass(DEFAULT_CONN_CLASS, true);
		
		//Begin spoof check
		final StringBuffer buffer = new StringBuffer(10);
		for(int i = 0; i < 10; ++i)
		{
			buffer.append((char) (randomGen.nextInt('z' - 'A') + 'A'));
		}
		
		spoofCheckChars = buffer.toString();
		
		send("PING :" + spoofCheckChars);
	}
	
	/**
	 * Called when a read event occurs
	 */
	void processReadEvent()
	{
		try
		{
			//Read data
			switch(readWrapper(localBuffer))
			{
				case -1:
{'fraction_non_alphanumeric': 0.11015073258142721, 'fraction_numerical': 0.008221777168757247, 'mean_word_length': 3.4191895668374475, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '418662', 'n_tokens_mistral': 3029, 'n_tokens_neox': 2686, 'n_words': 896}