All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.bloodshura.x.network.tcp.Server Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2013-2018, João Vitor Verona Biazibetti - All Rights Reserved
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see .
 *
 * https://www.github.com/BloodShura
 */

package com.github.bloodshura.x.network.tcp;

import com.github.bloodshura.x.activity.logging.XLogger;
import com.github.bloodshura.x.collection.list.XList;
import com.github.bloodshura.x.collection.list.impl.XArrayList;
import com.github.bloodshura.x.network.packet.Packet;
import com.github.bloodshura.x.network.packet.PacketList;
import com.github.bloodshura.x.network.tcp.controller.ServerReceptionThread;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.net.ServerSocketFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.function.BiConsumer;

public abstract class Server implements PacketHandler {
	private BiConsumer onUserError;
	private final PacketList packetList;
	private final int port;
	private final ServerReceptionThread receptionThread;
	private ServerSocket socket;
	private final XList userList;

	public Server(int port) {
		this.onUserError = (user, throwable) -> XLogger.warnln(throwable);
		this.packetList = new PacketList();
		this.port = port;
		this.receptionThread = new ServerReceptionThread<>(this);
		this.userList = new XArrayList<>();
	}

	public void disconnect(@Nonnull E user) {
		closeConnection(user);
		getConnectedUsers().remove(user);
		userDisconnected(user);
	}

	@Nonnull
	public abstract E generateUser(@Nonnull Socket socket) throws IOException;

	@Nonnull
	public synchronized XList getConnectedUsers() {
		return userList;
	}

	@Nonnull
	public BiConsumer getOnUserError() {
		return onUserError;
	}

	@Nonnull
	@Override
	public PacketList getPacketList() {
		return packetList;
	}

	public int getPort() {
		return port;
	}

	@Nullable
	public ServerSocket getSocket() {
		return socket;
	}

	public boolean isAlive() {
		return getSocket() != null && !getSocket().isClosed();
	}

	public abstract void packetReceived(@Nonnull E user, @Nonnull Packet packet) throws Exception;

	public void sendGlobalPacket(@Nonnull Packet packet) {
		getConnectedUsers().forEach(user -> user.writePacket(packet));
	}

	public void setOnUserError(@Nullable BiConsumer onUserError) {
		this.onUserError = onUserError != null ? onUserError : (user, throwable) -> {
		};
	}

	public void start() throws IOException {
		if (isAlive()) {
			throw new IOException("Already started");
		}

		try {
			this.socket = ServerSocketFactory.getDefault().createServerSocket();

			socket.setPerformancePreferences(0, 2, 1);
			socket.bind(new InetSocketAddress((InetAddress) null, getPort()), 50);
			receptionThread.start();
		}
		catch (IOException exception) {
			try {
				if (socket != null) {
					socket.close();
				}
			}
			catch (IOException exception2) {
			}

			throw exception;
		}
	}

	public void stop() throws IOException {
		receptionThread.interrupt();
		getConnectedUsers().forEach(this::closeConnection);
		getConnectedUsers().forEach(this::userDisconnected);
		getConnectedUsers().clear();
		getSocket().close();
	}

	public void userConnected(@Nonnull E user) {
	}

	public void userDisconnected(@Nonnull E user) {
	}

	protected void closeConnection(@Nonnull E user) {
		user.inputThread.interrupt();
		user.outputThread.interrupt();

		try {
			user.getInput().close();
		}
		catch (IOException exception) {
		}

		try {
			user.getOutput().close();
		}
		catch (IOException exception) {
		}

		try {
			user.getSocket().close();
		}
		catch (IOException exception) {
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy