Speed issue fixed for TF NET installations.
Progress bar 'works' for NET installations.
Progress bar behavior changed for USB installations. Simplified (simpler code for decorations -> a bit faster files installations).
Minor changes to TF side.
master
Dmitry Isaenko 2019-03-26 03:30:55 +03:00
parent e4bd7802ce
commit 90a8ee47c6
5 changed files with 144 additions and 85 deletions

View File

@ -44,7 +44,7 @@ Set 'Security & Privacy' settings if needed.
* Click 'Options' and select 'List All Devices'
* Select NS in dropdown, select 'libusbK (v3.0.7.0)' (version may vary), click 'Install WCID Driver'
* Check that in device list of you system you have 'libusbK USB Devices' folder and your NS inside of it
* Download and install Java JRE (8+)
* Download and install Java JRE (8u60 or higher)
* Get this application (JAR file) double-click on on it (alternatively open 'cmd', go to place where jar located and execute via `java -jar thisAppName.jar`)
* Remember to have fun!
@ -71,7 +71,9 @@ There you can select checkbox for files that will be send to application (TF/GL)
##### Second tab.
Here you can configure settings for network file transmission. Usually you shouldn't change anything. But it you're cool hacker, go ahead! The most interesting option here is 'Don't serve requests'. Architecture of the TinFoil networking is working interesting way. When you select in TF network NSP transfer, application will wait at port 2000 for the information about where should it take files from. Like '192.168.1.5:6060/my_file.nsp'. Usually NS-USBloader serves requests by implementing simplified HTTP server and bringing it up and so on. But if this option selected, you can define path to remote location of the files. For example if you set in settings 'shared.lan:80/ROMS/NS/' and add in table file 'my file.nsp' then NS-USBloader will simply tell TinFoil "Hey, go take files from 'shared.lan:80/ROMS/NS/my+file.nsp' ". Of course you have to bring 'shared.lan' host up and make file accessible from such address. All this requires more investigation. BTW, the issue could be that NS-USBloader encodes 'space' char as '+' and some web-servers understand 'space' as '%20D'. It could be fixed in later versions of NS-USBloader if I go deeper in it or you leave me feedback with information/request. As I said, this feature is interesting, but I guess won't be popular.
Here you can configure settings for network file transmission. Usually you shouldn't change anything. But it you're cool hacker, go ahead! The most interesting option here is 'Don't serve requests'. Architecture of the TinFoil's NET part is working interesting way. When you select in TF network NSP transfer, application will wait at port 2000 for the information about where should it take files from. Like '192.168.1.5:6060/my file.nsp'. Usually NS-USBloader serves requests by implementing simplified HTTP server and bringing it up and so on. But if this option selected, you can define path to remote location of the files. For example if you set in settings '192.168.4.2:80/ROMS/NS/' and add in table file 'my file.nsp' then NS-USBloader will simply tell TinFoil "Hey, go take files from '192.168.4.2:80/ROMS/NS/my%20file.nsp' ". Of course you have to bring '192.168.4.2' host up and make file accessible from such address (just go install nginx). As I said, this feature is interesting, but I guess won't be popular.
Also here you can check 'Auto-check for updates' or click button to verify if new version released or not.
##### Third tab.

View File

@ -8,7 +8,7 @@
<name>NS-USBloader</name>
<artifactId>ns-usbloader</artifactId>
<version>0.3.1-SNAPSHOT</version>
<version>0.3.2-SNAPSHOT</version>
<url>https://github.com/developersu/ns-usbloader/</url>
<description>

View File

@ -45,7 +45,7 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
// Collect and encode NSP files list
try {
for (File nspFile : filesList)
nspMap.put(URLEncoder.encode(nspFile.getName(), "UTF-8"), nspFile);
nspMap.put(URLEncoder.encode(nspFile.getName(), "UTF-8").replaceAll("\\+", "%20"), nspFile); // replace + to %20
}
catch (UnsupportedEncodingException uee){
isValid = false;
@ -63,21 +63,24 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
socket.connect(InetAddress.getByName("8.8.8.8"), 10002); // Google
hostIP = socket.getLocalAddress().getHostAddress();
socket.close();
} catch (SocketException | UnknownHostException e) {
}
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) {
}
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) {
}
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);
try {
@ -90,7 +93,8 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
logPrinter.print("Check for: " + i.getHostAddress(), EMsgType.INFO);
}
}
} catch (SocketException socketException) { // Good block.
}
catch (SocketException socketException) { // Good block.
logPrinter.print("Can't determine possible variants. Returned:\n\t"+socketException.getMessage(), EMsgType.FAIL);
}
isValid = false;
@ -107,33 +111,58 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
}
// Get port
if (hostPortNum.isEmpty()) {
Random portRandomizer = new Random();
for (int i = 0; i < 5; i++) {
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 = 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);
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 {
try {
this.hostPort = Integer.parseInt(hostPortNum);
serverSocket = new ServerSocket(hostPort);
logPrinter.print("NET: Using defined port number: " + hostPort, EMsgType.PASS);
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;
}
catch (NumberFormatException | IOException exeption){ // Literally never happens.
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);
@ -315,17 +344,54 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
* Send files.
* */
private boolean writeToSocket(File file, long start, long end){
logPrinter.print("NET: Responding to requested range: "+start+"-"+end, EMsgType.INFO);
currSockPW.write(NETPacket.getCode206(file.length(), start, end));
currSockPW.flush();
try{
long count = end - start;
long count = end - start + 1;
RandomAccessFile raf = new RandomAccessFile(file, "r");
raf.seek(start);
for (int i=0; i <= count; i++)
currSockOS.write(raf.read());
currSockOS.flush();
raf.close();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
int readPice = 8388608; // = 8Mb
byte[] byteBuf;
if (bis.skip(start) != start){
logPrinter.print("NET: Unable to skip requested range.", EMsgType.FAIL);
logPrinter.update(file, EFileStatus.FAILED);
return true;
}
long currentOffset = 0;
while (currentOffset < count){
if (isCancelled())
return true;
if ((currentOffset+readPice) >= count){
readPice = Math.toIntExact(count - currentOffset);
}
byteBuf = new byte[readPice];
if (bis.read(byteBuf) != readPice){
logPrinter.print("NET: Reading of file stream suddenly ended.", EMsgType.FAIL);
return true;
}
currSockOS.write(byteBuf);
//-----------------------------------------/
try {
logPrinter.updateProgress((currentOffset+readPice)/(count/100.0) / 100.0);
}catch (InterruptedException ie){
getException().printStackTrace(); // TODO: Do something with this
}
//-----------------------------------------/
currentOffset += readPice;
}
currSockOS.flush(); // TODO: check if this really needed.
bis.close();
//-----------------------------------------/
try{
logPrinter.updateProgress(1.0);
}
catch (InterruptedException ie){
getException().printStackTrace(); // TODO: Do something with this
}
//-----------------------------------------/
}
catch (IOException ioe){
logPrinter.print("NET: File transmission failed. Returned:\n\t"+ioe.getMessage(), EMsgType.FAIL);
@ -341,8 +407,10 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
if (isCancelled())
logPrinter.print("NET: Interrupted by user.", EMsgType.INFO);
try {
serverSocket.close();
logPrinter.print("NET: Closing server socket.", EMsgType.PASS);
if (serverSocket != null) {
serverSocket.close();
logPrinter.print("NET: Closing server socket.", EMsgType.PASS);
}
}
catch (IOException | NullPointerException ioe){
logPrinter.print("NET: Closing server socket failed. Sometimes it's not an issue.", EMsgType.WARNING);

View File

@ -12,7 +12,7 @@ import java.util.Locale;
import java.util.ResourceBundle;
public class NSLMain extends Application {
public static final String appVersion = "v0.3.1";
public static final String appVersion = "v0.3.2";
@Override
public void start(Stage primaryStage) throws Exception{

View File

@ -359,7 +359,7 @@ public class UsbCommunications extends Task<Void> {
BufferedInputStream bufferedInStream = new BufferedInputStream(new FileInputStream(nspMap.get(receivedRequestedNSP))); // TODO: refactor?
byte[] bufferCurrent ;//= new byte[1048576]; // eq. Allocate 1mb
int bufferLength;
if (bufferedInStream.skip(receivedRangeOffset) != receivedRangeOffset){
logPrinter.print("TF Requested skip is out of file size. Nothing to transmit.", EMsgType.FAIL);
return false;
@ -376,43 +376,35 @@ public class UsbCommunications extends Task<Void> {
readPice = Math.toIntExact(receivedRangeSize - currentOffset);
//System.out.println("CO: "+currentOffset+"\t\tEO: "+receivedRangeSize+"\t\tRP: "+readPice); // TODO: NOTE: DEBUG
// updating progress bar (if a lot of data requested) START BLOCK
if (isProgessBarInitiated){
try {
if (currentOffset+readPice == receivedRangeOffset){
logPrinter.updateProgress(1.0);
isProgessBarInitiated = false;
}
else
logPrinter.updateProgress((currentOffset+readPice)/(receivedRangeSize/100.0) / 100.0);
}catch (InterruptedException ie){
getException().printStackTrace(); // TODO: Do something with this
}
//-----------------------------------------/
try {
logPrinter.updateProgress((currentOffset+readPice)/(receivedRangeSize/100.0) / 100.0);
}catch (InterruptedException ie){
getException().printStackTrace(); // TODO: Do something with this
}
else {
if ((readPice == 8388608) && (currentOffset == 0))
isProgessBarInitiated = true;
}
// updating progress bar if needed END BLOCK
//-----------------------------------------/
bufferCurrent = new byte[readPice]; // TODO: not perfect moment, consider refactoring.
bufferLength = bufferedInStream.read(bufferCurrent);
if (bufferLength != -1){
//write to USB
if (!writeToUsb(bufferCurrent)) {
logPrinter.print("TF Failure during NSP transmission.", EMsgType.FAIL);
return false;
}
currentOffset += readPice;
}
else {
if (bufferedInStream.read(bufferCurrent) != readPice) { // changed since @ v0.3.2
logPrinter.print("TF Reading of stream suddenly ended.", EMsgType.WARNING);
return false;
}
//write to USB
if (!writeToUsb(bufferCurrent)) {
logPrinter.print("TF Failure during NSP transmission.", EMsgType.FAIL);
return false;
}
currentOffset += readPice;
}
bufferedInStream.close();
//-----------------------------------------/
try{
logPrinter.updateProgress(1.0);
}
catch (InterruptedException ie){
getException().printStackTrace(); // TODO: Do something with this
}
//-----------------------------------------/
} catch (FileNotFoundException fnfe){
logPrinter.print("TF FileNotFoundException:\n "+fnfe.getMessage(), EMsgType.FAIL);
fnfe.printStackTrace();
@ -422,7 +414,7 @@ public class UsbCommunications extends Task<Void> {
ioe.printStackTrace();
return false;
} catch (ArithmeticException ae){
logPrinter.print("TF ArithmeticException (can't cast end offset minus current to 'integer'):\n "+ae.getMessage(), EMsgType.FAIL);
logPrinter.print("TF ArithmeticException (can't cast 'offset end' - 'offsets current' to 'integer'):\n "+ae.getMessage(), EMsgType.FAIL);
ae.printStackTrace();
return false;
}
@ -653,26 +645,23 @@ public class UsbCommunications extends Task<Void> {
if (!writeToUsb(readBuf))
return false;
//-----------------------------------------/
if (isProgessBarInitiated){
try {
if (readFrom+readPice == realNcaSize){
logPrinter.updateProgress(1.0);
isProgessBarInitiated = false;
}
else
logPrinter.updateProgress((readFrom+readPice)/(realNcaSize/100.0) / 100.0);
}catch (InterruptedException ie){
getException().printStackTrace(); // TODO: Do something with this
}
}
else {
if ((readPice == 8388608) && (readFrom == 0))
isProgessBarInitiated = true;
try {
logPrinter.updateProgress((readFrom+readPice)/(realNcaSize/100.0) / 100.0);
}catch (InterruptedException ie){
getException().printStackTrace(); // TODO: Do something with this
}
//-----------------------------------------/
readFrom += readPice;
}
bufferedInStream.close();
//-----------------------------------------/
try{
logPrinter.updateProgress(1.0);
}
catch (InterruptedException ie){
getException().printStackTrace(); // TODO: Do something with this
}
//-----------------------------------------/
}
catch (IOException ioe){
logPrinter.print(" Failed to read NCA ID "+requestedNcaID+". IO Exception:\n "+ioe.getMessage(), EMsgType.FAIL);