Mercurial Hosting > luan
view src/goodjava/lucene/backup/BackupServer.java @ 1828:09e90d94b7b5
add DomainFilter
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 15 Sep 2024 19:51:16 -0600 |
parents | 2dbcc8360a3e |
children |
line wrap: on
line source
package goodjava.lucene.backup; import java.io.File; import java.io.IOException; import java.util.Map; import java.net.InetAddress; import java.net.Socket; import java.net.ServerSocket; import java.net.UnknownHostException; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLServerSocket; import goodjava.util.SoftCacheMap; import goodjava.io.IoUtils; import goodjava.rpc.RpcServer; import goodjava.rpc.RpcCall; import goodjava.rpc.RpcClient; import goodjava.rpc.RpcResult; import goodjava.rpc.Rpc; import goodjava.rpc.RpcException; import goodjava.logging.Logger; import goodjava.logging.LoggerFactory; public final class BackupServer { private static final Logger logger = LoggerFactory.getLogger(BackupServer.class); public static int port = 9102; public static String[] cipherSuites = new String[] { "TLS_DH_anon_WITH_AES_128_GCM_SHA256", "TLS_DH_anon_WITH_AES_128_CBC_SHA256", "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", "TLS_DH_anon_WITH_AES_128_CBC_SHA", "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", "TLS_ECDH_anon_WITH_RC4_128_SHA", "SSL_DH_anon_WITH_RC4_128_MD5", "SSL_DH_anon_WITH_DES_CBC_SHA", "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", }; private final File backupDir; private static final ExecutorService threadPool = Executors.newCachedThreadPool(); private static final Map<String,Backup> backups = new SoftCacheMap<String,Backup>(); public BackupServer(File backupDir) throws IOException { this.backupDir = backupDir; IoUtils.mkdirs(backupDir); } public synchronized void start() throws IOException { final ServerSocket ss; if( cipherSuites == null ) { ss = new ServerSocket(port); } else { ss = IoUtils.getSSLServerSocketFactory().createServerSocket(port); ((SSLServerSocket)ss).setEnabledCipherSuites(cipherSuites); } threadPool.execute(new Runnable(){public void run() { try { while(!threadPool.isShutdown()) { final Socket socket = ss.accept(); threadPool.execute(new Runnable(){public void run() { handle(socket); }}); } } catch(IOException e) { logger.error("",e); } }}); logger.info("started server on port "+port); } private static String getName(RpcServer rpc,Object[] args) { String domain = (String)args[0]; InetAddress addr; try { addr = InetAddress.getByName(domain); } catch(UnknownHostException e) { rpc.write( new RpcException("domain lookup failed") ); rpc.close(); return null; } if( !rpc.socket.getInetAddress().equals(addr) ) { rpc.write( new RpcException("domain doesn't match client") ); rpc.close(); return null; } String name = (String)args[1]; return name==null ? domain : domain + "~" + name; } private Backup getBackup(String name) { synchronized(backups) { Backup backup = backups.get(name); if( backup == null ) { backup = new Backup( new File(backupDir,name) ); backups.put(name,backup); } return backup; } } private void handle(Socket socket) { RpcServer rpc = new RpcServer(socket); Backup backup = null; while( !rpc.isClosed() ) { RpcCall call = rpc.read(); if( call == null ) break; if( call.cmd.equals("exists") ) { String name = getName(rpc,call.args); if( name==null ) return; rpc.write( new RpcResult(new Object[]{new File(backupDir,name).exists()}) ); } else if( call.cmd.equals("login") ) { String name = getName(rpc,call.args); if( name==null ) return; backup = getBackup(name); rpc.write(Rpc.OK); } else if( backup != null ) { backup.handle(rpc,call); } else if( call.cmd.equals("copy") ) { try { if( !IoUtils.getInetAddresses().contains(rpc.socket.getInetAddress()) ) { rpc.write( new RpcException("only localhost allowed") ); rpc.close(); return; } } catch(IOException e) { throw new RuntimeException(e); } String dirName = (String)call.args[0]; copy(new File(dirName)); rpc.write(Rpc.OK); } else { rpc.write( new RpcException("login expected") ); rpc.close(); return; } } } private void copy(File dir) { try { IoUtils.deleteRecursively(dir); IoUtils.mkdirs(dir); for( File f : backupDir.listFiles() ) { if( f.isDirectory() && new File(f,"index.json").exists() ) { String name = f.getName(); Backup backup = getBackup(name); backup.copyTo( new File(dir,name) ); } } } catch(IOException e) { throw new RuntimeException(e); } } // for client public static RpcClient rpcClient(String backupDomain) throws IOException { Socket socket; if( BackupServer.cipherSuites == null ) { socket = new Socket(backupDomain,BackupServer.port); } else { socket = IoUtils.getSSLSocketFactory().createSocket(backupDomain,BackupServer.port); ((SSLSocket)socket).setEnabledCipherSuites(BackupServer.cipherSuites); } return new RpcClient(socket); } public static void copyBackupTo(String dirName) throws IOException, RpcException { RpcClient rpc = BackupServer.rpcClient("localhost"); rpc.write( new RpcCall("copy",dirName) ); RpcResult result = rpc.read(); rpc.close(); } }