//CYCLONE MATRIX HOST NODE APPLICATION //Hermann L. Johnson, 2019 //Free for unmodified distribution and non-commercial use. import java.io.*; import java.net.*; import java.util.*; import java.util.zip.*; public class ServerThread extends Thread { private Socket theSocket; //The timeout is set in the ServerConnectionThread. private boolean isIntakeServer; private boolean ZIPPED; private static int SOCKET_TIMEOUT_A = 2000; private static int SOCKET_TIMEOUT_B = 5000; private byte[] blankbytes; private InputStream u_in; //Accept data private BufferedReader d_in; //Accept queries private BufferedOutputStream d_out; //Output responses private boolean running, isClosed, shutdownNow; private DataManager data_manager; //NOTE: Do not even look up mac addresses from IP if nothing is blacklisted //or whitelisted. This will waste a lot of time. //TEST LONG ENTRY DOWNLOADS public ServerThread(Socket theSocket, DataManager dataManager, boolean intakeServer, boolean zipped) { super("ServerThread-Upload:"+intakeServer); setRunning(false); isClosed = false; //The zipping is only for the upload ports. The downloader gives //whatever is requested. ZIPPED = zipped; //Boolean for running as the upload ports, which is generally 443, 444 isIntakeServer = intakeServer; data_manager = dataManager; this.theSocket = theSocket; try { if(intakeServer) theSocket.setSoTimeout(SOCKET_TIMEOUT_A); else theSocket.setSoTimeout(SOCKET_TIMEOUT_B); } catch (Exception e) { System.err.println("Problem setting server socket timeout."); } blankbytes = new byte[10000]; for(int count=0;count<10000;count++) { blankbytes[count] = 127; } } public boolean isClosed() { return isClosed; } public synchronized boolean running() { return running; } public synchronized void setRunning(boolean newValue) { running = newValue; } public void killThread() { setRunning(false); } private void intake() { String entryLine = new String(""); TrueStringTokenizer sttok; boolean breakWhile = false; try { u_in = theSocket.getInputStream(); byte[] readBytes = new byte[10000]; int bufferContentSize = 0; BufferedInputStream bis = new BufferedInputStream(u_in); ZipInputStream zis = new ZipInputStream(bis); InputStream genericis; sttok = new TrueStringTokenizer("","%LBK%"); if(ZIPPED) { try { zis.getNextEntry(); } catch(Exception e) { System.err.println("Server ZIP input stream error."); //Error reading ZIP when it should work. Exit. setRunning(false); breakWhile = true; } genericis = zis; } else genericis = bis; while(!breakWhile) { try { System.arraycopy(blankbytes, 0, readBytes, 0 , 10000); bufferContentSize = genericis.read(readBytes,0,10000); } catch(Exception e) { //Likely a port timeout. breakWhile = true; bufferContentSize = 0; for(int count=0;count<10000;count++) { if(readBytes[count]==127) { bufferContentSize = count; count = 10000; } } } if(bufferContentSize<=0) breakWhile = true; //The buffer has data, add it to entryLine. else { entryLine = entryLine + new String( readBytes,0,bufferContentSize); if(entryLine.contains("%EOF%")) { entryLine = entryLine.substring( 0,entryLine.indexOf("%EOF%")); breakWhile = true; } sttok = new TrueStringTokenizer(entryLine,"%LBK%"); while(sttok.hasMoreTokens() && sttok.getRemainder().contains("%LBK%")) { entryLine = sttok.nextToken(); if(!entryLine.equals("")) { data_manager.takeDataLine(entryLine+ "%LBK%"); } } entryLine = sttok.getRemainder(); } } } catch(Exception e) { System.err.println( "Problem accepting upload data. Server failure."); } try { theSocket.close(); } catch(Exception closeException) { System.err.println("Problem closing upload socket."); } isClosed = true; setRunning(false); return; } private void outtake() { String inputString = ""; String outputString = ""; boolean breakWhile = false; boolean shutdownNow = false; boolean streamWriteResults = false; StringTokenizer sttok; String hashSpan = ""; boolean hashZipped = false; try { //Open the streams. d_in = new BufferedReader(new InputStreamReader( theSocket.getInputStream())); d_out = new BufferedOutputStream(theSocket.getOutputStream()); ZipOutputStream zos = new ZipOutputStream(d_out); Vector stringVector = new Vector(); while(!breakWhile) { inputString = d_in.readLine(); if(inputString.equals("GET /")|| inputString.equals("GET /index.txt")) { stringVector = data_manager.getIndex(); if(!writeStreamData(stringVector, d_out, false, "")) { shutdownNow = true; breakWhile = true; } } else if(inputString.equals("GET /index.zip")) { stringVector = data_manager.getIndex(); if(!writeStreamData(stringVector, zos, true, "index.txt")) { shutdownNow = true; breakWhile = true; } } else if(inputString.endsWith("headerhashlist.txt")) { inputString = getDataFileNameFromString(inputString); stringVector = data_manager.getHeaderHashList(inputString); if(!writeStreamData(stringVector, d_out, false, "")) { shutdownNow = true; breakWhile = true; } } else if(inputString.endsWith("headerhashlist.zip")) { inputString = getDataFileNameFromString(inputString); stringVector = data_manager.getHeaderHashList(inputString); if(!writeStreamData(stringVector, zos, true, "headerhashlist.txt")) { shutdownNow = true; breakWhile = true; } } else if(inputString.endsWith("hashlist.txt")) { inputString = getDataFileNameFromString(inputString); stringVector = data_manager.getHashList(inputString); if(!writeStreamData(stringVector, d_out, false, "")) { shutdownNow = true; breakWhile = true; } } else if(inputString.endsWith("hashlist.zip")) { inputString = getDataFileNameFromString(inputString); stringVector = data_manager.getHashList(inputString); if(!writeStreamData(stringVector, zos, true, "hashlist.txt")) { shutdownNow = true; breakWhile = true; } } else { //A hash or a hash span. hashZipped = inputString.contains(".zip/"); hashSpan = inputString.substring( inputString.lastIndexOf("/")+1,inputString.length()); inputString = getDataFileNameFromString(inputString); if(hashSpan.contains("-")) stringVector = data_manager.getDataEntries(inputString, hashSpan); else stringVector.addElement(data_manager.getDataEntry( inputString, hashSpan)); if(!hashZipped) { if(!writeStreamData(stringVector, d_out, false, "")) { shutdownNow = true; breakWhile = true; } } else { if(!writeStreamData(stringVector, zos, true, inputString+".txt")) { shutdownNow = true; breakWhile = true; } } } } } catch(Exception e) { System.err.println("Disconnect or error in server download thread. Exiting."); } try { theSocket.close(); isClosed = true; } catch(Exception e) { System.err.println( "Problem shutting down server outtake socket. Exiting."); } isClosed = true; setRunning(false); } //Does not provide the extension! //The string should be in the format of "GET /filename.ext/etc" private String getDataFileNameFromString(String inString) { return inString.substring(5, inString.indexOf(".")); } private boolean writeStreamData(Vector stringVector, OutputStream outstream, boolean isZipped, String filename) { String outputString; try{ if(isZipped) ((ZipOutputStream)outstream).putNextEntry( new ZipEntry(filename)); for(int count=0;count