From 267ffcf5d2384927a3d3a28be506905586622d59 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Fri, 10 Jul 2020 16:57:29 +0300 Subject: [PATCH] Add updated brazilian portuguese translation by @almircanella! #64 Refactor NETCommunications. Not it's readable :D A lot of small changes, code refactoring, updates and fixes. --- .../COM/NET/NETCommunications.java | 660 +++++++----------- .../COM/NET/NetworkSetupValidator.java | 205 ++++++ .../COM/{INSTask.java => NET/UniFile.java} | 28 +- .../java/nsusbloader/COM/USB/GoldLeaf_05.java | 7 +- .../java/nsusbloader/COM/USB/GoldLeaf_07.java | 9 +- .../java/nsusbloader/COM/USB/GoldLeaf_08.java | 9 +- .../java/nsusbloader/COM/USB/TinFoil.java | 7 +- .../nsusbloader/COM/USB/TransferModule.java | 5 +- .../COM/USB/UsbCommunications.java | 25 +- .../Controllers/FrontController.java | 20 +- .../Controllers/NxdtController.java | 6 +- .../Controllers/RcmController.java | 3 +- .../nsusbloader/ModelControllers/Log.java | 2 +- .../ModelControllers/LogPrinterGui.java | 2 +- .../Utilities/nxdumptool/NxdtTask.java | 22 +- .../Utilities/nxdumptool/NxdtUsbAbi1.java | 10 +- src/main/java/nsusbloader/cli/GoldLeaf.java | 3 +- src/main/java/nsusbloader/cli/TinfoilUsb.java | 3 +- src/main/resources/locale.properties | 3 +- src/main/resources/locale_por.properties | 44 +- src/main/resources/locale_rus.properties | 1 + src/main/resources/locale_ukr.properties | 1 + 22 files changed, 553 insertions(+), 522 deletions(-) create mode 100644 src/main/java/nsusbloader/COM/NET/NetworkSetupValidator.java rename src/main/java/nsusbloader/COM/{INSTask.java => NET/UniFile.java} (55%) diff --git a/src/main/java/nsusbloader/COM/NET/NETCommunications.java b/src/main/java/nsusbloader/COM/NET/NETCommunications.java index f349480..39fbfab 100644 --- a/src/main/java/nsusbloader/COM/NET/NETCommunications.java +++ b/src/main/java/nsusbloader/COM/NET/NETCommunications.java @@ -18,7 +18,6 @@ */ package nsusbloader.COM.NET; -import nsusbloader.COM.INSTask; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.ModelControllers.Log; @@ -32,305 +31,124 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.*; -public class NETCommunications implements INSTask { // todo: rewrite +public class NETCommunications implements Runnable { - private ILogPrinter logPrinter; + private final ILogPrinter logPrinter; - private String hostIP; - private int hostPort; - private String extras; + private final String switchIP; + private final static int SWITCH_PORT = 2000; + private final String hostIP; + private final int hostPort; + private final String extras; + private final boolean doNotServe; - private String switchIP; + private final HashMap files; - private HashMap nspMap; - private HashMap nspFileSizes; + private final ServerSocket serverSocket; + private Socket clientSocket; - private ServerSocket serverSocket; - - private boolean isValid; - private boolean doNotServeRequests; + private final boolean isValid; private OutputStream currSockOS; private PrintWriter currSockPW; - - private volatile boolean cancel; /** * Simple constructor that everybody uses * */ public NETCommunications(List filesList, String switchIP, - boolean doNotServeRequests, - String hostIPaddr, + boolean doNotServe, + String hostIP, String hostPortNum, - String extras) { - this.doNotServeRequests = doNotServeRequests; - if (doNotServeRequests) + String extras) + { + this.doNotServe = doNotServe; + if (doNotServe) this.extras = extras; else this.extras = ""; this.switchIP = switchIP; this.logPrinter = Log.getPrinter(EModule.USB_NET_TRANSFERS); - this.nspMap = new HashMap<>(); - this.nspFileSizes = new HashMap<>(); - // Filter and remove empty/incorrect split-files - filesList.removeIf(f -> { - if (f.isDirectory()){ - File[] subFiles = f.listFiles((file, name) -> name.matches("[0-9]{2}")); - if (subFiles == null || subFiles.length == 0) { - logPrinter.print("NET: Removing empty folder: " + f.getName(), EMsgType.WARNING); - return true; - } - else { - Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName()))); - for (int i = subFiles.length - 2; i > 0 ; i--){ - if (subFiles[i].length() < subFiles[i-1].length()) { - logPrinter.print("NET: Removing strange split file: "+f.getName()+ - "\n (Chunk sizes of the split file are not the same, but has to be.)", EMsgType.WARNING); - return true; - } - } - } - } - return false; - }); - // Collect and encode NSP files list - try { - for (File nspFile : filesList) - nspMap.put(URLEncoder.encode(nspFile.getName(), "UTF-8").replaceAll("\\+", "%20"), nspFile); // replace + to %20 - } - catch (UnsupportedEncodingException uee){ - isValid = false; - logPrinter.print("NET: Unsupported encoding for 'URLEncoder'. Internal issue you can't fix. Please report. Returned:\n\t"+uee.getMessage(), EMsgType.FAIL); - //for (File nspFile : filesList) - // nspMap.put(nspFile.getName(), nspFile); + NetworkSetupValidator validator = + new NetworkSetupValidator(filesList, doNotServe, hostIP, hostPortNum, logPrinter); + + this.hostIP = validator.getHostIP(); + this.hostPort = validator.getHostPort(); + this.files = validator.getFiles(); + this.serverSocket = validator.getServerSocket(); + this.isValid = validator.isValid(); + + if (! isValid) close(EFileStatus.FAILED); - return; - } - // Collect sizes since now we can have split-files support - for (Map.Entry entry : nspMap.entrySet()){ - File inFile = entry.getValue(); - long fSize = 0; - if (inFile.isDirectory()){ - File[] subFiles = inFile.listFiles((file, name) -> name.matches("[0-9]{2}")); - for (File subFile : subFiles) - fSize += subFile.length(); - nspFileSizes.put(entry.getKey(), fSize); - } - else - nspFileSizes.put(entry.getKey(), inFile.length()); - } - - - // Resolve IP - if (hostIPaddr.isEmpty()) { - DatagramSocket socket; - try { // todo: check other method if internet unavaliable - socket = new DatagramSocket(); - socket.connect(InetAddress.getByName("8.8.8.8"), 10002); // Google - hostIP = socket.getLocalAddress().getHostAddress(); - socket.close(); - } - catch (SocketException | UnknownHostException e) { - logPrinter.print("NET: Can't get your computer IP using Google DNS server. Returned:\n\t"+e.getMessage(), EMsgType.INFO); - try { - socket = new DatagramSocket(); - socket.connect(InetAddress.getByName("193.0.14.129"), 10002); // RIPE NCC - hostIP = socket.getLocalAddress().getHostAddress(); - socket.close(); - } - catch (SocketException | UnknownHostException e1) { - logPrinter.print("NET: Can't get your computer IP using RIPE NCC root server. Returned:\n\t"+e1.getMessage(), EMsgType.INFO); - try { - socket = new DatagramSocket(); - socket.connect(InetAddress.getByName("people.com.cn"), 10002); // Renmin Ribao - hostIP = socket.getLocalAddress().getHostAddress(); - socket.close(); - } - catch (SocketException | UnknownHostException e2) { - logPrinter.print("NET: Can't get your computer IP using Renmin Ribao server. Returned:\n\t"+e2.getMessage(), EMsgType.FAIL); - logPrinter.print("Try using 'Expert mode' and set IP manually.", EMsgType.INFO); - this.showAvalIpExamples(); - isValid = false; - close(EFileStatus.FAILED); - return; - } - } - } - // Say hello to MacOS Catalina - // Also this part could be used instead of what we have above. One day it has to be tested on all platforms and fixed (replace code above). - if (hostIP.equals("0.0.0.0")) { - Socket scoketK; - try { - scoketK = new Socket(); - scoketK.connect(new InetSocketAddress("google.com", 80)); - hostIP = scoketK.getLocalAddress().getHostAddress(); - scoketK.close(); - } catch (Exception scoketKex) { - scoketKex.printStackTrace(); - logPrinter.print("NET: Can't get your computer IP using Google server (InetSocketAddress). Returned:\n\t"+scoketKex.getMessage(), EMsgType.INFO); - try { - scoketK = new Socket(); - scoketK.connect(new InetSocketAddress("people.com.cn", 80)); - hostIP = scoketK.getLocalAddress().getHostAddress(); - scoketK.close(); - } catch (Exception scoketKexx) { - scoketKex.printStackTrace(); - logPrinter.print("NET: Can't get your computer IP using Renmin Ribao server (InetSocketAddress). Returned:\n\t"+scoketKexx.getMessage(), EMsgType.FAIL); - logPrinter.print("Try using 'Expert mode' and set IP manually.", EMsgType.INFO); - this.showAvalIpExamples(); - isValid = false; - close(EFileStatus.FAILED); - return; - } - } - } - logPrinter.print("NET: Your IP detected as: " + hostIP, EMsgType.PASS); - } - else { - this.hostIP = hostIPaddr; - logPrinter.print("NET: Your IP defined as: " + hostIP, EMsgType.PASS); - } - - // Get port - if (! doNotServeRequests) { - if (hostPortNum.isEmpty()) { - Random portRandomizer = new Random(); - for (int i = 0; i < 5; i++) { - try { - this.hostPort = portRandomizer.nextInt(999) + 6000; - serverSocket = new ServerSocket(hostPort); //System.out.println(serverSocket.getInetAddress()); 0.0.0.0 - logPrinter.print("NET: Your port detected as: " + hostPort, EMsgType.PASS); - break; - } - catch (IOException ioe) { - if (i == 4) { - logPrinter.print("NET: Can't find good port", EMsgType.FAIL); - logPrinter.print("Try using 'Expert mode' and set port by yourself.", EMsgType.INFO); - isValid = false; - close(EFileStatus.FAILED); - return; - } else - logPrinter.print("NET: Can't use port " + hostPort + "\nLooking for another one.", EMsgType.WARNING); - } - } - } else { - try { - this.hostPort = Integer.parseInt(hostPortNum); - serverSocket = new ServerSocket(hostPort); - logPrinter.print("NET: Using defined port number: " + hostPort, EMsgType.PASS); - } - catch (NumberFormatException nfe) { // Literally never happens. - logPrinter.print("NET: Can't use port defined in settings: " + hostPortNum + "\nIt's not a valid number!", EMsgType.FAIL); - isValid = false; - close(EFileStatus.FAILED); - return; - } - catch (IOException ioex){ - logPrinter.print("NET: Can't use port defined in settings: " + hostPortNum + "\n\t"+ioex.getMessage(), EMsgType.FAIL); - isValid = false; - close(EFileStatus.FAILED); - return; - } - } - } - else { - if (hostPortNum.isEmpty()){ - logPrinter.print("NET: Port must be defined if 'Don't serve requests' option selected!", EMsgType.FAIL); - isValid = false; - close(EFileStatus.FAILED); - return; - } - try { - this.hostPort = Integer.parseInt(hostPortNum); - } - catch (NumberFormatException fex){ - logPrinter.print("NET: Can't use port defined in settings: " + hostPortNum + "\nIt's not a valid number!", EMsgType.WARNING); - isValid = false; - close(EFileStatus.FAILED); - return; - } - } - isValid = true; - } - /** - * Show possible variants to log area - * */ - private void showAvalIpExamples(){ - try { - Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); - while (enumeration.hasMoreElements()) { - NetworkInterface n = enumeration.nextElement(); - Enumeration enumeration1 = n.getInetAddresses(); - while (enumeration1.hasMoreElements()) - logPrinter.print("Check for: " + enumeration1.nextElement().getHostAddress(), EMsgType.INFO); - } - } - catch (SocketException socketException) { // Good block. - logPrinter.print("Can't determine possible variants. Returned:\n\t"+socketException.getMessage(), EMsgType.FAIL); - } - } - @Override - public boolean isCancelled(){ - return cancel; - } - - @Override - public void cancel() { - cancel = true; } @Override public void run() { - - if (!isValid | isCancelled()) + if (! isValid || Thread.interrupted() ) return; + logPrinter.print("\tStart chain", EMsgType.INFO); - // Create string that we'll send to TF and which initiates chain - StringBuilder myStrBuilder; - myStrBuilder = new StringBuilder(); - for (String fileNameEncoded : nspMap.keySet()) { - myStrBuilder.append(hostIP); - myStrBuilder.append(':'); - myStrBuilder.append(hostPort); - myStrBuilder.append('/'); - myStrBuilder.append(extras); - myStrBuilder.append(fileNameEncoded); - myStrBuilder.append('\n'); - } + final String handshakeContent = buildHandshakeContent(); - byte[] nspListNames = myStrBuilder.toString().getBytes(StandardCharsets.UTF_8); // Follow the - byte[] nspListSize = ByteBuffer.allocate(Integer.BYTES).putInt(nspListNames.length).array(); // defining order + byte[] handshakeCommand = handshakeContent.getBytes(StandardCharsets.UTF_8); + byte[] handshakeCommandSize = ByteBuffer.allocate(Integer.BYTES).putInt(handshakeCommand.length).array(); - try { - Socket handShakeSocket = new Socket(InetAddress.getByName(switchIP), 2000); - OutputStream os = handShakeSocket.getOutputStream(); - - os.write(nspListSize); - os.write(nspListNames); - os.flush(); - - handShakeSocket.close(); - } - catch (IOException uhe){ - logPrinter.print("NET: Unable to connect to NS and send files list. Returned:\n\t"+uhe.getMessage(), EMsgType.FAIL); - close(EFileStatus.UNKNOWN); + if (sendHandshake(handshakeCommandSize, handshakeCommand)) return; - } + // Check if we should serve requests - if (this.doNotServeRequests){ - logPrinter.print("NET: List of files transferred. Replies won't be served.", EMsgType.PASS); + if (this.doNotServe){ + logPrinter.print("List of files transferred. Replies won't be served.", EMsgType.PASS); close(EFileStatus.UNKNOWN); return; } - logPrinter.print("NET: Initiation files list has been sent to NS.", EMsgType.PASS); + logPrinter.print("Initiation files list has been sent to NS.", EMsgType.PASS); // Go transfer - Socket clientSocket; - work_routine: - while (true){ - try { + serveRequestsLoop(); + } + /** + * Create string that we'll send to TF/AW and which initiates chain + * */ + private String buildHandshakeContent(){ + StringBuilder builder = new StringBuilder(); + + for (String fileNameEncoded : files.keySet()) { + builder.append(hostIP); + builder.append(':'); + builder.append(hostPort); + builder.append('/'); + builder.append(extras); + builder.append(fileNameEncoded); + builder.append('\n'); + } + + return builder.toString(); + } + + private boolean sendHandshake(byte[] handshakeCommandSize, byte[] handshakeCommand){ + try { + Socket handshakeSocket = new Socket(InetAddress.getByName(switchIP), SWITCH_PORT); + OutputStream os = handshakeSocket.getOutputStream(); + + os.write(handshakeCommandSize); + os.write(handshakeCommand); + os.flush(); + + handshakeSocket.close(); + } + catch (IOException uhe){ + logPrinter.print("Unable to connect to NS and send files list:\n " + + uhe.getMessage(), EMsgType.FAIL); + close(EFileStatus.UNKNOWN); + return true; + } + return false; + } + private void serveRequestsLoop(){ + try { + while (true){ clientSocket = serverSocket.accept(); BufferedReader br = new BufferedReader( new InputStreamReader(clientSocket.getInputStream()) @@ -345,8 +163,7 @@ public class NETCommunications implements INSTask { // todo: rewrite while ((line = br.readLine()) != null) { //System.out.println(line); // Debug if (line.trim().isEmpty()) { // If TCP packet is ended - if (handleRequest(tcpPacket)) // Proceed required things - break work_routine; + handleRequest(tcpPacket); // Proceed required things tcpPacket.clear(); // Clear data and wait for next TCP packet } else @@ -356,206 +173,219 @@ public class NETCommunications implements INSTask { // todo: rewrite // and reopen client sock clientSocket.close(); } - catch (IOException ioe){ // If server socket closed, then client socket also closed. - break; - } } - if ( ! isCancelled() ) + catch (Exception e){ + if (Thread.interrupted()) + logPrinter.print("Interrupted by user.", EMsgType.INFO); + else + logPrinter.print(e.getMessage(), EMsgType.INFO); close(EFileStatus.UNKNOWN); - return; + } } - - // 200 206 400 (inv range) 404 416 (Range Not Satisfiable ) /** * Handle requests * @return true if failed * */ - private boolean handleRequest(LinkedList packet){ - //private boolean handleRequest(LinkedList packet, OutputStreamWriter pw){ + private void handleRequest(LinkedList packet) throws Exception{ File requestedFile; String reqFileName = packet.get(0).replaceAll("(^[A-z\\s]+/)|(\\s+?.*$)", ""); - if (! nspFileSizes.containsKey(reqFileName)){ - currSockPW.write(NETPacket.getCode404()); - currSockPW.flush(); - logPrinter.print("NET: File "+reqFileName+" doesn't exists or have 0 size. Returning 404", EMsgType.FAIL); - return true; + if (! files.containsKey(reqFileName)){ + writeToSocket(NETPacket.getCode404()); + logPrinter.print("File "+reqFileName+" doesn't exists or have 0 size. Returning 404", EMsgType.FAIL); + return; } - long reqFileSize = nspFileSizes.get(reqFileName); - requestedFile = nspMap.get(reqFileName); + long reqFileSize = files.get(reqFileName).getSize(); + requestedFile = files.get(reqFileName).getFile(); if (! requestedFile.exists() || reqFileSize == 0){ // well.. tell 404 if file exists with 0 length is against standard, but saves time - currSockPW.write(NETPacket.getCode404()); - currSockPW.flush(); - logPrinter.print("NET: File "+requestedFile.getName()+" doesn't exists or have 0 size. Returning 404", EMsgType.FAIL); + writeToSocket(NETPacket.getCode404()); + logPrinter.print("File "+requestedFile.getName()+" doesn't exists or have 0 size. Returning 404", EMsgType.FAIL); logPrinter.update(requestedFile, EFileStatus.FAILED); - return true; + return; } if (packet.get(0).startsWith("HEAD")){ - currSockPW.write(NETPacket.getCode200(reqFileSize)); - currSockPW.flush(); - logPrinter.print("NET: Replying for requested file: "+requestedFile.getName(), EMsgType.INFO); - return false; + writeToSocket(NETPacket.getCode200(reqFileSize)); + logPrinter.print("Replying for requested file: "+requestedFile.getName(), EMsgType.INFO); + return; } if (packet.get(0).startsWith("GET")) { for (String line: packet) { - if (line.toLowerCase().startsWith("range")) { //todo: fix - try { - String[] rangeStr = line.toLowerCase().replaceAll("^range:\\s+?bytes=", "").split("-", 2); - if (!rangeStr[0].isEmpty() && !rangeStr[1].isEmpty()) { // If both ranges defined: Read requested - if (Long.parseLong(rangeStr[0]) > Long.parseLong(rangeStr[1])){ // If start bytes greater then end bytes - currSockPW.write(NETPacket.getCode400()); - currSockPW.flush(); - logPrinter.print("NET: Requested range for "+requestedFile.getName()+" is incorrect. Returning 400", EMsgType.FAIL); - logPrinter.update(requestedFile, EFileStatus.FAILED); - return true; - } - if (writeToSocket(reqFileName, Long.parseLong(rangeStr[0]), Long.parseLong(rangeStr[1]))) // DO WRITE - return true; + if (! line.toLowerCase().startsWith("range")) //todo: fix + continue; - } - else if (!rangeStr[0].isEmpty()) { // If only START defined: Read all - if (writeToSocket(reqFileName, Long.parseLong(rangeStr[0]), reqFileSize)) // DO WRITE - return true; - } - else if (!rangeStr[1].isEmpty()) { // If only END defined: Try to read last 500 bytes - if (reqFileSize > 500){ - if (writeToSocket(reqFileName, reqFileSize-500, reqFileSize)) // DO WRITE - return true; - } - else { // If file smaller than 500 bytes - currSockPW.write(NETPacket.getCode416()); - currSockPW.flush(); - logPrinter.print("NET: File size requested for "+requestedFile.getName()+" while actual size of it: "+reqFileSize+". Returning 416", EMsgType.FAIL); - logPrinter.update(requestedFile, EFileStatus.FAILED); - return true; - } - } - else { - currSockPW.write(NETPacket.getCode400()); // If Range not defined: like "Range: bytes=-" - currSockPW.flush(); - logPrinter.print("NET: Requested range for "+requestedFile.getName()+" is incorrect (empty start & end). Returning 400", EMsgType.FAIL); - logPrinter.update(requestedFile, EFileStatus.FAILED); - return true; - } - break; - } - catch (NumberFormatException nfe){ - currSockPW.write(NETPacket.getCode400()); - currSockPW.flush(); - logPrinter.print("NET: Requested range for "+requestedFile.getName()+" has incorrect format. Returning 400\n\t"+nfe.getMessage(), EMsgType.FAIL); - logPrinter.update(requestedFile, EFileStatus.FAILED); - return true; - } - } + parseGETrange(requestedFile, reqFileName, reqFileSize, line); + return; } } - return false; + } + + private void parseGETrange(File file, String fileName, long fileSize, String rangeDirective) throws Exception{ + try { + String[] rangeStr = rangeDirective.toLowerCase().replaceAll("^range:\\s+?bytes=", "").split("-", 2); + + if (! rangeStr[0].isEmpty() && ! rangeStr[1].isEmpty()) { // If both ranges defined: Read requested + long fromRange = Long.parseLong(rangeStr[0]); + long toRange = Long.parseLong(rangeStr[1]); + + if (fromRange > toRange){ // If start bytes greater then end bytes + writeToSocket(NETPacket.getCode400()); + logPrinter.print("Requested range for " + + file.getName() + + " is incorrect. Returning 400", EMsgType.FAIL); + logPrinter.update(file, EFileStatus.FAILED); + return; + } + writeToSocket(fileName, fromRange, toRange); + return; + } + + if (! rangeStr[0].isEmpty()) { // If only START defined: Read all + writeToSocket(fileName, Long.parseLong(rangeStr[0]), fileSize); + return; + } + + if (rangeStr[1].isEmpty()) { // If Range not defined: like "Range: bytes=-" + writeToSocket(NETPacket.getCode400()); + logPrinter.print("Requested range for " + + file.getName() + + " is incorrect (empty start & end). Returning 400", EMsgType.FAIL); + logPrinter.update(file, EFileStatus.FAILED); + return; + } + + if (fileSize > 500){ + writeToSocket(fileName, fileSize - 500, fileSize); + return; + } + // If file smaller than 500 bytes + writeToSocket(NETPacket.getCode416()); + logPrinter.print("File size requested for " + + file.getName() + + " while actual size of it: " + + fileSize+". Returning 416", EMsgType.FAIL); + logPrinter.update(file, EFileStatus.FAILED); + } + catch (NumberFormatException nfe){ + writeToSocket(NETPacket.getCode400()); + logPrinter.print("Requested range for " + + file.getName() + + " has incorrect format. Returning 400\n\t" + + nfe.getMessage(), EMsgType.FAIL); + logPrinter.update(file, EFileStatus.FAILED); + } + } + + private void writeToSocket(String string) { + currSockPW.write(string); + currSockPW.flush(); } /** * Send files. * */ - private boolean writeToSocket(String fileName, long start, long end){ - File reqFile = nspMap.get(fileName); - // Inform - logPrinter.print("NET: Responding to requested range: "+start+"-"+end, EMsgType.INFO); - // Reply - currSockPW.write(NETPacket.getCode206(nspFileSizes.get(fileName), start, end)); - currSockPW.flush(); - // Prepare transfer + private void writeToSocket(String fileName, long start, long end) throws Exception{ + File file = files.get(fileName).getFile(); + + logPrinter.print("Reply to range: "+start+"-"+end, EMsgType.INFO); + + writeToSocket(NETPacket.getCode206(files.get(fileName).getSize(), start, end)); + try{ + if (file.isDirectory()) + handleSplitFile(file, start, end); + else + handleRegularFile(file, start, end); + + logPrinter.updateProgress(1.0); + } + catch (Exception e){ + logPrinter.update(file, EFileStatus.FAILED); + throw new Exception("File transmission failed:\n "+e.getMessage()); + } + } + + private void handleSplitFile(File file, long start, long end) throws Exception{ long count = end - start + 1; - int readPice = 8388608; // = 8Mb + int readPice = 8388608; byte[] byteBuf; long currentOffset = 0; - try{ - //================================= SPLIT FILE ==================================== - if (reqFile.isDirectory()){ - NSSplitReader nsr = new NSSplitReader(reqFile, start); + NSSplitReader nsr = new NSSplitReader(file, start); - while (currentOffset < count){ - if (isCancelled()) - return true; - if ((currentOffset + readPice) >= count){ - readPice = Math.toIntExact(count - currentOffset); - } - byteBuf = new byte[readPice]; - - if (nsr.read(byteBuf) != readPice){ - logPrinter.print("NET: Reading of file stream suddenly ended.", EMsgType.FAIL); - return true; - } - currSockOS.write(byteBuf); - //-------/ - logPrinter.updateProgress((currentOffset+readPice)/(count/100.0) / 100.0); - //-------/ - currentOffset += readPice; - } - currSockOS.flush(); // TODO: check if this really needed. - nsr.close(); + while (currentOffset < count){ + if ((currentOffset + readPice) >= count){ + readPice = Math.toIntExact(count - currentOffset); } - //================================= REGULAR FILE ==================================== - else { - BufferedInputStream bis = new BufferedInputStream(new FileInputStream(reqFile)); + byteBuf = new byte[readPice]; - if (bis.skip(start) != start){ - logPrinter.print("NET: Unable to skip requested range.", EMsgType.FAIL); - logPrinter.update(reqFile, EFileStatus.FAILED); - return true; - } + if (nsr.read(byteBuf) != readPice) + throw new IOException("File stream suddenly ended."); - while (currentOffset < count){ - if (isCancelled()) - return true; - if ((currentOffset + readPice) >= count){ - readPice = Math.toIntExact(count - currentOffset); - } - byteBuf = new byte[readPice]; + currSockOS.write(byteBuf); + logPrinter.updateProgress((currentOffset+readPice)/(count/100.0) / 100.0); - if (bis.read(byteBuf) != readPice){ - logPrinter.print("NET: Reading of file stream suddenly ended.", EMsgType.FAIL); - return true; - } - currSockOS.write(byteBuf); - //-------/ - logPrinter.updateProgress((currentOffset+readPice)/(count/100.0) / 100.0); - //-------/ - currentOffset += readPice; - } - currSockOS.flush(); // TODO: check if this really needed. - bis.close(); + currentOffset += readPice; + } + currSockOS.flush(); // TODO: check if this really needed. + nsr.close(); + } + private void handleRegularFile(File file, long start, long end) throws Exception{ + long count = end - start + 1; + + int readPice = 8388608; + byte[] byteBuf; + long currentOffset = 0; + + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); + + if (bis.skip(start) != start) + throw new IOException("Unable to skip requested range."); + + while (currentOffset < count){ + + if ((currentOffset + readPice) >= count){ + readPice = Math.toIntExact(count - currentOffset); } - //-------/ - logPrinter.updateProgress(1.0); - //-------/ + byteBuf = new byte[readPice]; + + if (bis.read(byteBuf) != readPice){ + throw new IOException("File stream suddenly ended."); + } + currSockOS.write(byteBuf); + logPrinter.updateProgress((currentOffset+readPice)/(count/100.0) / 100.0); + currentOffset += readPice; } - catch (IOException | NullPointerException e){ - logPrinter.print("NET: File transmission failed. Returned:\n\t"+e.getMessage(), EMsgType.FAIL); - logPrinter.update(reqFile, EFileStatus.FAILED); - return true; - } - return false; + currSockOS.flush(); // TODO: check if this really needed. + bis.close(); + } + + public ServerSocket getServerSocket(){ + return serverSocket; + } + public Socket getClientSocket(){ + return clientSocket; } /** * Close when done * */ private void close(EFileStatus status){ - if (isCancelled()) - logPrinter.print("NET: Interrupted by user.", EMsgType.INFO); try { - if (serverSocket != null) { + if (serverSocket != null && ! serverSocket.isClosed()) { serverSocket.close(); - logPrinter.print("NET: Closing server socket.", EMsgType.PASS); + logPrinter.print("Closing server socket.", EMsgType.PASS); } } catch (IOException ioe){ - logPrinter.print("NET: Closing server socket failed. Sometimes it's not an issue.", EMsgType.WARNING); - } - if (status != null) { - logPrinter.update(nspMap, status); + logPrinter.print("Closing server socket failed. Sometimes it's not an issue.", EMsgType.WARNING); } + + HashMap tempMap = new HashMap<>(); + for (UniFile sf : files.values()) + tempMap.put(sf.getFile().getName(), sf.getFile()); + + logPrinter.update(tempMap, status); + logPrinter.print("\tEnd chain", EMsgType.INFO); logPrinter.close(); } diff --git a/src/main/java/nsusbloader/COM/NET/NetworkSetupValidator.java b/src/main/java/nsusbloader/COM/NET/NetworkSetupValidator.java new file mode 100644 index 0000000..edbf008 --- /dev/null +++ b/src/main/java/nsusbloader/COM/NET/NetworkSetupValidator.java @@ -0,0 +1,205 @@ +/* + Copyright 2019-2020 Dmitry Isaenko + + This file is part of NS-USBloader. + + NS-USBloader is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + NS-USBloader 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with NS-USBloader. If not, see . +*/ +package nsusbloader.COM.NET; + +import nsusbloader.ModelControllers.ILogPrinter; +import nsusbloader.NSLDataTypes.EMsgType; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.*; +import java.util.*; + +public class NetworkSetupValidator { + + private String hostIP; + private int hostPort; + private final HashMap files; + private ServerSocket serverSocket; + private final boolean valid; + private final ILogPrinter logPrinter; + + private final boolean doNotServe; + + NetworkSetupValidator(List filesList, + boolean doNotServe, + String hostIP, + String hostPortNum, + ILogPrinter logPrinter) { + this.files = new HashMap<>(); + this.logPrinter = logPrinter; + this.doNotServe = doNotServe; + + try { + validateFiles(filesList); + encodeAndAddFilesToMap(filesList); + resolveIp(hostIP); + resolvePort(hostPortNum); + } + catch (Exception e){ + logPrinter.print(e.getMessage(), EMsgType.FAIL); + valid = false; + return; + } + valid = true; + } + + private void validateFiles(List filesList) { + filesList.removeIf(f -> { + if (f.isFile()) + return false; + + File[] subFiles = f.listFiles((file, name) -> name.matches("[0-9]{2}")); + + if (subFiles == null || subFiles.length == 0) { + logPrinter.print("NET: Exclude folder: " + f.getName(), EMsgType.WARNING); + return true; + } + + Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName()))); + + for (int i = subFiles.length - 2; i > 0 ; i--){ + if (subFiles[i].length() < subFiles[i-1].length()) { + logPrinter.print("NET: Exclude split file: "+f.getName()+ + "\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING); + return true; + } + } + return false; + }); + } + + private void encodeAndAddFilesToMap(List filesList) throws UnsupportedEncodingException, FileNotFoundException { + for (File file : filesList){ + String encodedName = URLEncoder.encode(file.getName(), "UTF-8").replaceAll("\\+", "%20"); // replace '+' to '%20' + UniFile uniFile = new UniFile(file); + files.put(encodedName, uniFile); + } + + if (files.size() == 0) { + throw new FileNotFoundException("NET: No files to send."); + } + } + + private void resolveIp(String hostIPaddr) throws IOException{ + if (! hostIPaddr.isEmpty()){ + this.hostIP = hostIPaddr; + logPrinter.print("NET: Host IP defined as: " + hostIP, EMsgType.PASS); + return; + } + + if (findIpUsingHost("google.com")) + return; + + if (findIpUsingHost("people.com.cn")) + return; + + throw new IOException("Try using 'Expert mode' and set IP manually. " + getAvaliableIpExamples()); + } + + private boolean findIpUsingHost(String host) { + try { + Socket scoketK; + scoketK = new Socket(); + scoketK.connect(new InetSocketAddress(host, 80)); + hostIP = scoketK.getLocalAddress().getHostAddress(); + scoketK.close(); + + logPrinter.print("NET: Host IP detected as: " + hostIP, EMsgType.PASS); + return true; + } + catch (IOException e){ + logPrinter.print("NET: Can't get your computer IP using " + + host + + " server (InetSocketAddress). Returned:\n\t"+e.getMessage(), EMsgType.INFO); + return false; + } + } + + private String getAvaliableIpExamples(){ + try { + StringBuilder builder = new StringBuilder("Check for:\n"); + Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); + while (enumeration.hasMoreElements()) { + NetworkInterface n = enumeration.nextElement(); + Enumeration enumeration1 = n.getInetAddresses(); + while (enumeration1.hasMoreElements()){ + builder.append("- "); + builder.append(enumeration1.nextElement().getHostAddress()); + builder.append("\n"); + } + } + return builder.toString(); + } + catch (SocketException socketException) { + return ""; + } + } + + private void resolvePort(String hostPortNum) throws Exception{ + if (! hostPortNum.isEmpty()) { + parsePort(hostPortNum); + return; + } + + if (doNotServe) + throw new Exception("NET: Port must be defined if 'Don't serve requests' option selected!"); + + findPort(); + } + + private void findPort() throws Exception{ + Random portRandomizer = new Random(); + for (int i = 0; i < 5; i++) { + try { + this.hostPort = portRandomizer.nextInt(999) + 6000; + serverSocket = new ServerSocket(hostPort); //System.out.println(serverSocket.getInetAddress()); 0.0.0.0 + logPrinter.print("NET: Your port detected as: " + hostPort, EMsgType.PASS); + break; + } + catch (IOException ioe) { + if (i == 4) { + throw new Exception("NET: Can't find good port\n" + + "Set port by in settings ('Expert mode')."); + } + + logPrinter.print("NET: Can't use port " + hostPort + "\nLooking for another one.", EMsgType.WARNING); + } + } + } + + private void parsePort(String hostPortNum) throws Exception{ + try { + this.hostPort = Integer.parseInt(hostPortNum); + serverSocket = new ServerSocket(hostPort); + logPrinter.print("NET: Using defined port number: " + hostPort, EMsgType.PASS); + } + catch (IllegalArgumentException | IOException eee){ + throw new Exception("NET: Can't use port defined in settings: " + hostPortNum + "\n\t"+eee.getMessage()); + } + } + + String getHostIP() { return hostIP; } + int getHostPort() { return hostPort; } + HashMap getFiles() { return files; } + ServerSocket getServerSocket() { return serverSocket; } + boolean isValid() { return valid; } +} diff --git a/src/main/java/nsusbloader/COM/INSTask.java b/src/main/java/nsusbloader/COM/NET/UniFile.java similarity index 55% rename from src/main/java/nsusbloader/COM/INSTask.java rename to src/main/java/nsusbloader/COM/NET/UniFile.java index ac9a444..7aa5eb0 100644 --- a/src/main/java/nsusbloader/COM/INSTask.java +++ b/src/main/java/nsusbloader/COM/NET/UniFile.java @@ -16,9 +16,29 @@ You should have received a copy of the GNU General Public License along with NS-USBloader. If not, see . */ -package nsusbloader.COM; +package nsusbloader.COM.NET; -public interface INSTask extends Runnable { - void cancel(); - boolean isCancelled(); +import java.io.File; + +class UniFile { + private final long size; + private final File file; + + UniFile(File file) { + this.file = file; + + if (file.isFile()) { + size = file.length(); + } + else { + long fSize = 0; + File[] subFiles = file.listFiles((myFile, name) -> name.matches("[0-9]{2}")); + for (File subFile : subFiles) + fSize += subFile.length(); + size = fSize; + } + } + + public long getSize() { return size; } + public File getFile() { return file; } } diff --git a/src/main/java/nsusbloader/COM/USB/GoldLeaf_05.java b/src/main/java/nsusbloader/COM/USB/GoldLeaf_05.java index 1731b79..86dfeb7 100644 --- a/src/main/java/nsusbloader/COM/USB/GoldLeaf_05.java +++ b/src/main/java/nsusbloader/COM/USB/GoldLeaf_05.java @@ -18,7 +18,6 @@ */ package nsusbloader.COM.USB; -import nsusbloader.COM.INSTask; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EMsgType; @@ -53,7 +52,7 @@ public class GoldLeaf_05 extends TransferModule { private RandomAccessFile raf; // NSP File private NSSplitReader nsr; // It'a also NSP File - GoldLeaf_05(DeviceHandle handler, LinkedHashMap nspMap, INSTask task, ILogPrinter logPrinter){ + GoldLeaf_05(DeviceHandle handler, LinkedHashMap nspMap, Runnable task, ILogPrinter logPrinter){ super(handler, nspMap, task, logPrinter); status = EFileStatus.FAILED; @@ -335,7 +334,7 @@ public class GoldLeaf_05 extends TransferModule { IntBuffer writeBufTransferred = IntBuffer.allocate(1); int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint OUT = 0x01 switch (result){ @@ -368,7 +367,7 @@ public class GoldLeaf_05 extends TransferModule { IntBuffer readBufTransferred = IntBuffer.allocate(1); int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81 switch (result) { diff --git a/src/main/java/nsusbloader/COM/USB/GoldLeaf_07.java b/src/main/java/nsusbloader/COM/USB/GoldLeaf_07.java index 424a111..eafe07a 100644 --- a/src/main/java/nsusbloader/COM/USB/GoldLeaf_07.java +++ b/src/main/java/nsusbloader/COM/USB/GoldLeaf_07.java @@ -21,7 +21,6 @@ package nsusbloader.COM.USB; import javafx.application.Platform; import javafx.stage.FileChooser; import nsusbloader.COM.Helpers.NSSplitReader; -import nsusbloader.COM.INSTask; import nsusbloader.MediatorControl; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EMsgType; @@ -69,7 +68,7 @@ class GoldLeaf_07 extends TransferModule { // For using in CMD_SelectFile with SPEC:/ prefix private File selectedFile; - GoldLeaf_07(DeviceHandle handler, LinkedHashMap nspMap, INSTask task, ILogPrinter logPrinter, boolean nspFilter){ + GoldLeaf_07(DeviceHandle handler, LinkedHashMap nspMap, Runnable task, ILogPrinter logPrinter, boolean nspFilter){ super(handler, nspMap, task, logPrinter); final byte CMD_GetDriveCount = 0x00; @@ -993,7 +992,7 @@ class GoldLeaf_07 extends TransferModule { int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81 switch (result) { @@ -1023,7 +1022,7 @@ class GoldLeaf_07 extends TransferModule { int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81 switch (result) { @@ -1083,7 +1082,7 @@ class GoldLeaf_07 extends TransferModule { IntBuffer writeBufTransferred = IntBuffer.allocate(1); int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint OUT = 0x01 switch (result){ diff --git a/src/main/java/nsusbloader/COM/USB/GoldLeaf_08.java b/src/main/java/nsusbloader/COM/USB/GoldLeaf_08.java index caee81a..885b6ae 100644 --- a/src/main/java/nsusbloader/COM/USB/GoldLeaf_08.java +++ b/src/main/java/nsusbloader/COM/USB/GoldLeaf_08.java @@ -20,7 +20,6 @@ package nsusbloader.COM.USB; import javafx.application.Platform; import javafx.stage.FileChooser; -import nsusbloader.COM.INSTask; import nsusbloader.MediatorControl; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EMsgType; @@ -69,7 +68,7 @@ class GoldLeaf_08 extends TransferModule { // For using in CMD_SelectFile with SPEC:/ prefix private File selectedFile; - GoldLeaf_08(DeviceHandle handler, LinkedHashMap nspMap, INSTask task, ILogPrinter logPrinter, boolean nspFilter){ + GoldLeaf_08(DeviceHandle handler, LinkedHashMap nspMap, Runnable task, ILogPrinter logPrinter, boolean nspFilter){ super(handler, nspMap, task, logPrinter); final byte CMD_GetDriveCount = 1; @@ -1012,7 +1011,7 @@ class GoldLeaf_08 extends TransferModule { int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81 switch (result) { @@ -1042,7 +1041,7 @@ class GoldLeaf_08 extends TransferModule { int result; - while (! task.isCancelled()) { + while (! Thread.interrupted() ) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81 switch (result) { @@ -1102,7 +1101,7 @@ class GoldLeaf_08 extends TransferModule { IntBuffer writeBufTransferred = IntBuffer.allocate(1); int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint OUT = 0x01 switch (result){ diff --git a/src/main/java/nsusbloader/COM/USB/TinFoil.java b/src/main/java/nsusbloader/COM/USB/TinFoil.java index ec4d847..3e853d6 100644 --- a/src/main/java/nsusbloader/COM/USB/TinFoil.java +++ b/src/main/java/nsusbloader/COM/USB/TinFoil.java @@ -18,7 +18,6 @@ */ package nsusbloader.COM.USB; -import nsusbloader.COM.INSTask; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EMsgType; @@ -48,7 +47,7 @@ class TinFoil extends TransferModule { /* byte[] magic = new byte[4]; ByteBuffer bb = StandardCharsets.UTF_8.encode("TUC0").rewind().get(magic); // Let's rephrase this 'string' */ - TinFoil(DeviceHandle handler, LinkedHashMap nspMap, INSTask task, ILogPrinter logPrinter){ + TinFoil(DeviceHandle handler, LinkedHashMap nspMap, Runnable task, ILogPrinter logPrinter){ super(handler, nspMap, task, logPrinter); logPrinter.print("============= Tinfoil =============", EMsgType.INFO); @@ -305,7 +304,7 @@ class TinFoil extends TransferModule { IntBuffer writeBufTransferred = IntBuffer.allocate(1); int result; //int varVar = 0; //todo:remove - while (! task.isCancelled()) { + while (! Thread.interrupted() ) { /* if (varVar != 0) logPrinter.print("writeUsb() retry cnt: "+varVar, EMsgType.INFO); //NOTE: DEBUG @@ -345,7 +344,7 @@ class TinFoil extends TransferModule { // We can limit it to 32 bytes, but there is a non-zero chance to got OVERFLOW from libusb. IntBuffer readBufTransferred = IntBuffer.allocate(1); int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81 switch (result) { diff --git a/src/main/java/nsusbloader/COM/USB/TransferModule.java b/src/main/java/nsusbloader/COM/USB/TransferModule.java index c1d09e3..27a5f38 100644 --- a/src/main/java/nsusbloader/COM/USB/TransferModule.java +++ b/src/main/java/nsusbloader/COM/USB/TransferModule.java @@ -18,7 +18,6 @@ */ package nsusbloader.COM.USB; -import nsusbloader.COM.INSTask; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EMsgType; @@ -33,9 +32,9 @@ public abstract class TransferModule { LinkedHashMap nspMap; ILogPrinter logPrinter; DeviceHandle handlerNS; - INSTask task; + Runnable task; - TransferModule(DeviceHandle handler, LinkedHashMap nspMap, INSTask task, ILogPrinter printer){ + TransferModule(DeviceHandle handler, LinkedHashMap nspMap, Runnable task, ILogPrinter printer){ this.handlerNS = handler; this.nspMap = nspMap; this.task = task; diff --git a/src/main/java/nsusbloader/COM/USB/UsbCommunications.java b/src/main/java/nsusbloader/COM/USB/UsbCommunications.java index 3b5a249..e4f5ec3 100644 --- a/src/main/java/nsusbloader/COM/USB/UsbCommunications.java +++ b/src/main/java/nsusbloader/COM/USB/UsbCommunications.java @@ -18,7 +18,6 @@ */ package nsusbloader.COM.USB; -import nsusbloader.COM.INSTask; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.Log; import nsusbloader.NSLDataTypes.EFileStatus; @@ -31,14 +30,12 @@ import java.io.*; import java.util.*; // TODO: add filter option to show only NSP files -public class UsbCommunications implements INSTask { +public class UsbCommunications implements Runnable { - private ILogPrinter logPrinter; - private LinkedHashMap nspMap; - private String protocol; - private boolean nspFilterForGl; - - private volatile boolean cancel; + private final ILogPrinter logPrinter; + private final LinkedHashMap nspMap; + private final String protocol; + private final boolean nspFilterForGl; public UsbCommunications(List nspList, String protocol, boolean filterNspFilesOnlyForGl){ this.protocol = protocol; @@ -82,8 +79,6 @@ public class UsbCommunications implements INSTask { usbConnect.close(); close(module.getStatus()); - - return; } /** @@ -94,14 +89,4 @@ public class UsbCommunications implements INSTask { logPrinter.print("\tEnd", EMsgType.INFO); logPrinter.close(); } - - @Override - public boolean isCancelled() { - return cancel; - } - - @Override - public void cancel() { - cancel = true; - } } \ No newline at end of file diff --git a/src/main/java/nsusbloader/Controllers/FrontController.java b/src/main/java/nsusbloader/Controllers/FrontController.java index 1c70636..c0b7c04 100644 --- a/src/main/java/nsusbloader/Controllers/FrontController.java +++ b/src/main/java/nsusbloader/Controllers/FrontController.java @@ -30,7 +30,6 @@ import javafx.scene.layout.Region; import javafx.stage.DirectoryChooser; import javafx.stage.FileChooser; import nsusbloader.AppPreferences; -import nsusbloader.COM.INSTask; import nsusbloader.COM.NET.NETCommunications; import nsusbloader.COM.USB.UsbCommunications; import nsusbloader.MediatorControl; @@ -63,7 +62,7 @@ public class FrontController implements Initializable { private String previouslyOpenedPath; private Region btnUpStopImage; private ResourceBundle resourceBundle; - private INSTask usbNetCommunications; + private Runnable usbNetCommunications; private Thread workThread; @Override @@ -265,8 +264,11 @@ public class FrontController implements Initializable { SettingsController settings = MediatorControl.getInstance().getContoller().getSettingsCtrlr(); // If USB selected - if (getSelectedProtocol().equals("GoldLeaf") || ( getSelectedProtocol().equals("TinFoil") && getSelectedNetUsb().equals("USB") ) ){ - usbNetCommunications = new UsbCommunications(nspToUpload, getSelectedProtocol() + settings.getGlVer(), settings.getNSPFileFilterForGL()); + if (getSelectedProtocol().equals("GoldLeaf") ){ + usbNetCommunications = new UsbCommunications(nspToUpload, "GoldLeaf" + settings.getGlVer(), settings.getNSPFileFilterForGL()); + } + else if (( getSelectedProtocol().equals("TinFoil") && getSelectedNetUsb().equals("USB") )){ + usbNetCommunications = new UsbCommunications(nspToUpload, "TinFoil", settings.getNSPFileFilterForGL()); } else { // NET INSTALL OVER TINFOIL final String ipValidationPattern = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"; @@ -300,7 +302,15 @@ public class FrontController implements Initializable { * */ private void stopBtnAction(){ if (workThread != null && workThread.isAlive()){ - usbNetCommunications.cancel(); + workThread.interrupt(); + + if (usbNetCommunications instanceof NETCommunications){ + try{ + ((NETCommunications) usbNetCommunications).getServerSocket().close(); + ((NETCommunications) usbNetCommunications).getClientSocket().close(); + } + catch (Exception ignore){ } + } } } /** diff --git a/src/main/java/nsusbloader/Controllers/NxdtController.java b/src/main/java/nsusbloader/Controllers/NxdtController.java index 0b66515..459d77d 100644 --- a/src/main/java/nsusbloader/Controllers/NxdtController.java +++ b/src/main/java/nsusbloader/Controllers/NxdtController.java @@ -25,7 +25,6 @@ import javafx.scene.control.Label; import javafx.scene.layout.Region; import javafx.stage.DirectoryChooser; import nsusbloader.AppPreferences; -import nsusbloader.COM.INSTask; import nsusbloader.MediatorControl; import nsusbloader.NSLDataTypes.EModule; import nsusbloader.Utilities.nxdumptool.NxdtTask; @@ -45,7 +44,6 @@ public class NxdtController implements Initializable { private Region btnDumpStopImage; - private INSTask NxdtTask; private Thread workThread; @Override @@ -83,7 +81,7 @@ public class NxdtController implements Initializable { if ((workThread == null || ! workThread.isAlive())){ MediatorControl.getInstance().getContoller().logArea.clear(); - NxdtTask = new NxdtTask(saveToLocationLbl.getText()); + Runnable NxdtTask = new NxdtTask(saveToLocationLbl.getText()); workThread = new Thread(NxdtTask); workThread.setDaemon(true); workThread.start(); @@ -95,7 +93,7 @@ public class NxdtController implements Initializable { * */ private void stopBtnAction(){ if (workThread != null && workThread.isAlive()){ - NxdtTask.cancel(); + workThread.interrupt(); } } diff --git a/src/main/java/nsusbloader/Controllers/RcmController.java b/src/main/java/nsusbloader/Controllers/RcmController.java index a9feb05..df4fd56 100644 --- a/src/main/java/nsusbloader/Controllers/RcmController.java +++ b/src/main/java/nsusbloader/Controllers/RcmController.java @@ -194,7 +194,8 @@ public class RcmController implements Initializable { private void smash(){ statusLbl.setText(""); if (MediatorControl.getInstance().getTransferActive()) { - ServiceWindow.getErrorNotification(rb.getString("windowTitleError"), rb.getString("windowBodyPleaseFinishTransfersFirst")); + ServiceWindow.getErrorNotification(rb.getString("windowTitleError"), + rb.getString("windowBodyPleaseStopOtherProcessFirst")); return; } diff --git a/src/main/java/nsusbloader/ModelControllers/Log.java b/src/main/java/nsusbloader/ModelControllers/Log.java index 4f5e94a..e069671 100644 --- a/src/main/java/nsusbloader/ModelControllers/Log.java +++ b/src/main/java/nsusbloader/ModelControllers/Log.java @@ -21,7 +21,7 @@ package nsusbloader.ModelControllers; import nsusbloader.NSLDataTypes.EModule; import nsusbloader.NSLMain; -public class Log { +public abstract class Log { private Log(){} diff --git a/src/main/java/nsusbloader/ModelControllers/LogPrinterGui.java b/src/main/java/nsusbloader/ModelControllers/LogPrinterGui.java index 111ea34..a18d544 100644 --- a/src/main/java/nsusbloader/ModelControllers/LogPrinterGui.java +++ b/src/main/java/nsusbloader/ModelControllers/LogPrinterGui.java @@ -35,7 +35,7 @@ public class LogPrinterGui implements ILogPrinter { private final HashMap statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap private final AtomicBoolean oneLinerStatus; - public LogPrinterGui(EModule whoIsAsking){ + LogPrinterGui(EModule whoIsAsking){ this.msgQueue = new LinkedBlockingQueue<>(); this.progressQueue = new LinkedBlockingQueue<>(); this.statusMap = new HashMap<>(); diff --git a/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtTask.java b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtTask.java index 938eda9..f01428b 100644 --- a/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtTask.java +++ b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtTask.java @@ -18,7 +18,6 @@ */ package nsusbloader.Utilities.nxdumptool; -import nsusbloader.COM.INSTask; import nsusbloader.COM.USB.UsbConnect; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.Log; @@ -26,12 +25,10 @@ import nsusbloader.NSLDataTypes.EModule; import nsusbloader.NSLDataTypes.EMsgType; import org.usb4java.DeviceHandle; -public class NxdtTask implements INSTask { +public class NxdtTask implements Runnable { - private ILogPrinter logPrinter; - private String saveToLocation; - - private volatile boolean cancel; + private final ILogPrinter logPrinter; + private final String saveToLocation; public NxdtTask(String saveToLocation){ this.logPrinter = Log.getPrinter(EModule.NXDT); @@ -52,23 +49,12 @@ public class NxdtTask implements INSTask { DeviceHandle handler = usbConnect.getNsHandler(); - new NxdtUsbAbi1(handler, this, logPrinter, saveToLocation); + new NxdtUsbAbi1(handler, logPrinter, saveToLocation); logPrinter.print(".:: Complete ::.", EMsgType.PASS); usbConnect.close(); logPrinter.updateOneLinerStatus(true); logPrinter.close(); - return; - } - - @Override - public void cancel() { - cancel = true; - } - - @Override - public boolean isCancelled() { - return cancel; } } \ No newline at end of file diff --git a/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java index a55b17f..4d8ca3d 100644 --- a/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java +++ b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java @@ -18,7 +18,6 @@ */ package nsusbloader.Utilities.nxdumptool; -import nsusbloader.COM.INSTask; import nsusbloader.COM.USB.UsbErrorCodes; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EMsgType; @@ -35,7 +34,6 @@ import java.util.Arrays; class NxdtUsbAbi1 { private ILogPrinter logPrinter; private DeviceHandle handlerNS; - private INSTask task; private String saveToPath; private boolean isWindows; @@ -79,12 +77,10 @@ class NxdtUsbAbi1 { 0x00, 0x00, 0x00, 0x00 }; public NxdtUsbAbi1(DeviceHandle handler, - INSTask task, ILogPrinter logPrinter, String saveToPath ){ this.handlerNS = handler; - this.task = task; this.logPrinter = logPrinter; this.isWindows = System.getProperty("os.name").toLowerCase().contains("windows"); @@ -310,7 +306,7 @@ class NxdtUsbAbi1 { writeBuffer.put(message); IntBuffer writeBufTransferred = IntBuffer.allocate(1); - if ( task.isCancelled()) + if ( Thread.interrupted() ) throw new InterruptedException("Execution interrupted"); int result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, 5050); @@ -339,7 +335,7 @@ class NxdtUsbAbi1 { // We can limit it to 32 bytes, but there is a non-zero chance to got OVERFLOW from libusb. IntBuffer readBufTransferred = IntBuffer.allocate(1); int result; - while (! task.isCancelled()) { + while (! Thread.interrupted()) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81 switch (result) { @@ -368,7 +364,7 @@ class NxdtUsbAbi1 { IntBuffer readBufTransferred = IntBuffer.allocate(1); int result; int countDown = 0; - while (! task.isCancelled() && countDown < 5) { + while (! Thread.interrupted() && countDown < 5) { result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); switch (result) { diff --git a/src/main/java/nsusbloader/cli/GoldLeaf.java b/src/main/java/nsusbloader/cli/GoldLeaf.java index c8559e1..e6a1cd7 100644 --- a/src/main/java/nsusbloader/cli/GoldLeaf.java +++ b/src/main/java/nsusbloader/cli/GoldLeaf.java @@ -18,7 +18,6 @@ */ package nsusbloader.cli; -import nsusbloader.COM.INSTask; import nsusbloader.COM.USB.UsbCommunications; import nsusbloader.Controllers.SettingsController; @@ -125,7 +124,7 @@ public class GoldLeaf { } public void runGoldLeafBackend() throws InterruptedException { - INSTask task = new UsbCommunications(filesList, + Runnable task = new UsbCommunications(filesList, "GoldLeaf"+goldLeafVersion, filterForNsp); Thread thread = new Thread(task); diff --git a/src/main/java/nsusbloader/cli/TinfoilUsb.java b/src/main/java/nsusbloader/cli/TinfoilUsb.java index 41c9658..6b493f0 100644 --- a/src/main/java/nsusbloader/cli/TinfoilUsb.java +++ b/src/main/java/nsusbloader/cli/TinfoilUsb.java @@ -18,7 +18,6 @@ */ package nsusbloader.cli; -import nsusbloader.COM.INSTask; import nsusbloader.COM.USB.UsbCommunications; import java.io.File; @@ -61,7 +60,7 @@ public class TinfoilUsb { } private void runTinfoilBackend() throws InterruptedException{ - INSTask task = new UsbCommunications(filesList, "TinFoil", false); + Runnable task = new UsbCommunications(filesList, "TinFoil", false); Thread thread = new Thread(task); thread.start(); thread.join(); diff --git a/src/main/resources/locale.properties b/src/main/resources/locale.properties index ac3e419..d1fd9ea 100644 --- a/src/main/resources/locale.properties +++ b/src/main/resources/locale.properties @@ -67,4 +67,5 @@ windowBodyDownloadDrivers=Downloading drivers (libusbK v3.0.7.0)... btn_Cancel=Cancel btn_Close=Close tab2_Cb_GlVersion=GoldLeaf version -tab2_Cb_GLshowNspOnly=Show only *.nsp in GoldLeaf. \ No newline at end of file +tab2_Cb_GLshowNspOnly=Show only *.nsp in GoldLeaf. +windowBodyPleaseStopOtherProcessFirst=Please stop other active process before continuing. \ No newline at end of file diff --git a/src/main/resources/locale_por.properties b/src/main/resources/locale_por.properties index e384664..349f6e7 100644 --- a/src/main/resources/locale_por.properties +++ b/src/main/resources/locale_por.properties @@ -1,13 +1,13 @@ btn_OpenFile=Selecionar arquivos btn_Upload=Upar para o switch tab3_Txt_EnteredAsMsg1=Voc\u00EA logou como: -tab3_Txt_EnteredAsMsg2=Voc\u00EA precisa de permiss\u00F5es root ou ter configurado as regras 'udev' deste usu\u00E1rio para evitar poss\u00EDveis problemas. +tab3_Txt_EnteredAsMsg2=Voc\u00EA precisa de permiss\u00F5es root ou ter configurado as regras 'udev' deste usu\u00E1rio para evitar poss\u00EDveis problemas tab3_Txt_FilesToUploadTitle=Arquivos para upar: tab3_Txt_GreetingsMessage=Bem vindo ao NS-USBloader -tab3_Txt_NoFolderOrFileSelected=Nenhum arquivo selecionado. Nada para upar. +tab3_Txt_NoFolderOrFileSelected=Nenhum arquivo selecionado. Nada para upar windowBodyConfirmExit=Transfer\u00EAncia de dados em progresso: Fechar ir\u00E1 interromper.\nN\u00E3o \u00E9 aconselh\u00E1vel.\nInterromper processo e sair? windowTitleConfirmExit=N\u00E3o, n\u00E3o fa\u00E7a isso! -btn_Stop=Imterromper! +btn_Stop=Interromper! tab3_Txt_GreetingsMessage2=--\n\ Source: https://github.com/developersu/ns-usbloader/\n\ Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\ @@ -15,42 +15,43 @@ Dmitry Isaenko [developer.su] tab1_table_Lbl_Status=Status tab1_table_Lbl_FileName=Nome do arquivo tab1_table_Lbl_Size=Tamanho -tab1_table_Lbl_Upload=Upar +tab1_table_Lbl_Upload=Upar? tab1_table_contextMenu_Btn_BtnDelete=Remover tab1_table_contextMenu_Btn_DeleteAll=Remover todos tab2_Lbl_HostIP=Host IP tab1_Lbl_NSIP=NS IP: -tab2_Cb_ValidateNSHostName=Sempre validar o IP do switch. +tab2_Cb_ValidateNSHostName=Sempre validar o IP do switch windowBodyBadIp=Tem certeza que preencheu o endere\u00E7o IP corretamente? -windowTitleBadIp=Endere\u00E7o IP do switch provavelmente incorreto. +windowTitleBadIp=Endere\u00E7o IP do switch provavelmente incorreto tab2_Cb_ExpertMode=Modo Expert (Configura\u00E7\u00E3o NET) tab2_Lbl_HostPort=porta tab2_Cb_AutoDetectIp=Auto-detectar IP tab2_Cb_RandSelectPort=Usar porta aleat\u00F3ria tab2_Cb_DontServeRequests=n\u00E3o aceitar solicita\u00E7\u00F5es -tab2_Lbl_DontServeRequestsDesc=Se selecionado, Este computador n\u00E3o ir\u00E1 aceitar solicita\u00E7\u00F5es de arquivos .nsp vindos, atrav\u00E9s da rede, do seu switch. Isso ir\u00E1 usar as defini\u00E7\u00F5es do host para informar ao tinfoil onde qual caminho procurar pelos arquivos. +tab2_Lbl_DontServeRequestsDesc=Se selecionado, Este computador n\u00E3o ir\u00E1 aceitar solicita\u00E7\u00F5es de arquivos .nsp vindos, atrav\u00E9s da rede, do seu switch. Isso ir\u00E1 usar as defini\u00E7\u00F5es do host para informar ao tinfoil onde qual caminho procurar pelos arquivos tab2_Lbl_HostExtra=extra windowTitleErrorPort=Porta configurada incorretamente! -windowBodyErrorPort=Porta n\u00E3o pode ser 0 or maior que 65535. -tab2_Cb_AutoCheckForUpdates=Auto checar por atualiza\u00E7\u00F5es. -windowTitleNewVersionAval=Nova vers\u00E3o dispon\u00EDvel. -windowTitleNewVersionNOTAval=Nao h\u00E1 novas vers\u00F5es. -windowTitleNewVersionUnknown=Nao conseguimos checar por novas atualiza\u00E7\u00F5es. +windowBodyErrorPort=Porta n\u00E3o pode ser 0 or maior que 65535 +tab2_Cb_AutoCheckForUpdates=Auto checar por atualiza\u00E7\u00F5es +windowTitleNewVersionAval=Nova vers\u00E3o dispon\u00EDvel +windowTitleNewVersionNOTAval=Nao h\u00E1 novas vers\u00F5es +windowTitleNewVersionUnknown=Nao conseguimos checar por novas atualiza\u00E7\u00F5es windowBodyNewVersionUnknown=Algo deu errado...\nProblemas de conex\u00E3o ou com a p\u00E1gina do github, talvez? windowBodyNewVersionNOTAval=Voc\u00EA est\u00E1 na \u00FAltima vers\u00E3o! tab2_Cb_AllowXciNszXcz=permitir arquivos XCI / NSZ / XCZ para o tinfoil -tab2_Lbl_AllowXciNszXczDesc=Usado por aplica\u00E7\u00F5es que suportam XCI/NSZ/XCZ e utiliza protocolos de transfer\u00EAncia do Tinfoil. N\u00E3o mude o que n\u00E3o tem certeza. Ative para uso com o Awoo-Installer. +tab2_Lbl_AllowXciNszXczDesc=Usado por aplica\u00E7\u00F5es que suportam XCI/NSZ/XCZ e utiliza protocolos de transfer\u00EAncia do Tinfoil. N\u00E3o mude o que n\u00E3o tem certeza. Ative para uso com o Awoo-Installer tab2_Lbl_Language=Idioma -windowBodyRestartToApplyLang=Por favor, reinicie para aplicar as modifica\u00E7\u00F5es. -tab2_Cb_GLshowNspOnly=Mostrar apenas arquivos .nsp no GoldLeaf. +windowBodyRestartToApplyLang=Por favor, reinicie para aplicar as modifica\u00E7\u00F5es +tab2_Cb_GLshowNspOnly=Mostrar apenas arquivos .nsp no GoldLeaf +tab2_Cb_GlVersion=Vers\u00E3o do GoldLeaf. btn_OpenSplitFile=Selecionar arquivos .nsp fragmentados(splitted) tab2_Lbl_ApplicationSettings=Configura\u00E7\u00F5es principais -tabSplMrg_Lbl_SplitNMergeTitle=Ferramentas para fragmentar e juntar(merge) arquivos. +tabSplMrg_Lbl_SplitNMergeTitle=Ferramentas para fragmentar e mesclar(merge) arquivos tabSplMrg_RadioBtn_Split=Fragmentar(split) -tabSplMrg_RadioBtn_Merge=Juntar(merge) +tabSplMrg_RadioBtn_Merge=Mesclar(merge) tabSplMrg_Txt_File=File: tabSplMrg_Txt_Folder=Arquivo fragmentado (pasta): -tabSplMrg_Btn_SelectFile=Selecionar arquivo. +tabSplMrg_Btn_SelectFile=Selecionar arquivo tabSplMrg_Btn_SelectFolder=Selecionar pasta tabSplMrg_Lbl_SaveToLocation=Salvar em: tabSplMrg_Btn_ChangeSaveToLocation=Trocar @@ -61,6 +62,9 @@ done_txt=Feito! failure_txt=Falhou btn_Select=Selecionar btn_InjectPayloader=Injetar payload +tabNXDT_Btn_Start=Iniciar! +tab2_Btn_InstallDrivers=Baixar e instalar drivers +windowTitleDownloadDrivers=Baixar e Instalar Drivers +windowBodyDownloadDrivers=Baixando drivers (libusbK v3.0.7.0)... btn_Cancel=Cancelar -tab2_Cb_GlVersion=Vers\u00E3o do GoldLeaf. - +btn_Close=Fechar diff --git a/src/main/resources/locale_rus.properties b/src/main/resources/locale_rus.properties index 5c8e15b..8c62350 100644 --- a/src/main/resources/locale_rus.properties +++ b/src/main/resources/locale_rus.properties @@ -68,4 +68,5 @@ windowBodyDownloadDrivers=\u0421\u043A\u0430\u0447\u0438\u0432\u0430\u0435\u043C btn_Cancel=\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C btn_Close=\u0417\u0430\u043A\u0440\u044B\u0442\u044C tab2_Cb_GlVersion=\u0412\u0435\u0440\u0441\u0438\u044F GoldLeaf +windowBodyPleaseStopOtherProcessFirst=\u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u0434\u0440\u0443\u0433\u043E\u0439 \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u043F\u0440\u043E\u0446\u0435\u0441\u0441 \u043F\u0435\u0440\u0435\u0434 \u0442\u0435\u043C, \u043A\u0430\u043A \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C. diff --git a/src/main/resources/locale_ukr.properties b/src/main/resources/locale_ukr.properties index 64e4578..c387b9e 100644 --- a/src/main/resources/locale_ukr.properties +++ b/src/main/resources/locale_ukr.properties @@ -68,3 +68,4 @@ windowBodyDownloadDrivers=\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0443 btn_Cancel=\u0412\u0456\u0434\u043C\u0456\u043D\u0438\u0442\u0438 btn_Close=\u0417\u0430\u043A\u0440\u0438\u0442\u0438 tab2_Cb_GlVersion=\u0412\u0435\u0440\u0441\u0456\u044F GoldLeaf +windowBodyPleaseStopOtherProcessFirst=\u0411\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0437\u0443\u043F\u0438\u043D\u0456\u0442\u044C \u0456\u043D\u0448\u0438\u0439 \u0430\u043A\u0442\u0438\u0432\u043D\u0438\u0439 \u043F\u0440\u043E\u0446\u0435\u0441 \u043F\u0435\u0440\u0448 \u043D\u0456\u0436 \u043F\u0440\u043E\u0434\u043E\u0432\u0436\u0438\u0442\u0438.