package fr.titionfire.ffsaf.net2; import com.fasterxml.jackson.databind.JsonNode; import fr.titionfire.ffsaf.domain.service.ClubService; import fr.titionfire.ffsaf.domain.service.MembreService; import fr.titionfire.ffsaf.net2.packet.IAction; import fr.titionfire.ffsaf.net2.packet.RegisterAction; import fr.titionfire.ffsaf.utils.Pair; import io.quarkus.runtime.ShutdownEvent; import io.quarkus.runtime.StartupEvent; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.jboss.logging.Logger; import org.quartz.Scheduler; import javax.net.ssl.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; import java.security.*; import java.util.ArrayList; import java.util.HashMap; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; @Singleton public class ServerCustom extends Thread { private static final Logger LOGGER = Logger.getLogger("SocketServer"); protected ConcurrentHashMap>> jobData = new ConcurrentHashMap<>(); protected HashMap iMap = new HashMap<>(); public final ArrayList clients = new ArrayList<>(); private SSLServerSocket server; private boolean run; private static ServerCustom serverCustom; @ConfigProperty(name = "internal-port") int port; @ConfigProperty(name = "certificate_password") String certificate_password; @ConfigProperty(name = "certificate_file") String certificate_file; @Inject protected Scheduler quartz; @Inject public MembreService membreService; @Inject public ClubService clubService; private PublicKey publicKey; private X509TrustManager tm(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { TrustManagerFactory trustMgrFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustMgrFactory.init(keystore); TrustManager[] trustManagers = trustMgrFactory.getTrustManagers(); for (TrustManager trustManager : trustManagers) { if (trustManager instanceof X509TrustManager) { return (X509TrustManager) trustManager; } } return null; } private X509KeyManager km(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException { KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyMgrFactory.init(keystore, certificate_password.toCharArray()); KeyManager[] keyManagers = keyMgrFactory.getKeyManagers(); for (KeyManager keyManager : keyManagers) { if (keyManager instanceof X509KeyManager) { return (X509KeyManager) keyManager; } } return null; } private SSLServerSocket getServerSocketWithCert(int port, InputStream pathToCert) throws Exception { TrustManager[] tmm = new TrustManager[1]; KeyManager[] kmm = new KeyManager[1]; KeyStore ks = KeyStore.getInstance("JKS"); ks.load(pathToCert, certificate_password.toCharArray()); tmm[0] = tm(ks); kmm[0] = km(ks); SSLContext ctx = SSLContext.getInstance("TLSv1.2"); ctx.init(kmm, tmm, null); publicKey = ks.getCertificate("ffsaf").getPublicKey(); SSLServerSocketFactory socketFactory = ctx.getServerSocketFactory(); return (SSLServerSocket) socketFactory.createServerSocket(port); } @Override public void run() { try { this.run = true; this.server = getServerSocketWithCert(this.port, new FileInputStream(new File(this.certificate_file))); RegisterAction.register(iMap); LOGGER.info("Starting socket server!!"); while (this.run) { Socket socket = this.server.accept(); Client_Thread cThread = new Client_Thread(this, socket, publicKey); synchronized (clients) { this.clients.add(cThread); } cThread.start(); } LOGGER.info("Shutting down Socket server!!"); } catch (Exception e) { LOGGER.info("Server start failed! (" + e.getMessage() + ")"); this.interrupt(); } } public void onCloseClient(Client_Thread cThread) { synchronized (clients) { clients.remove(cThread); } } public void stop2() { this.run = false; try { this.server.close(); clients.forEach(Client_Thread::stopSoket); } catch (IOException ignored) { } } void onStart(@Observes StartupEvent ev) { LOGGER.info("The server is starting..."); serverCustom = this; this.start(); } void onStop(@Observes ShutdownEvent ev) { LOGGER.info("The server is stopping..."); this.stop2(); } public static ServerCustom getInstance(){ return serverCustom; } public Stream get_clients() { return clients.stream(); } }