Compare commits

..

14 Commits

Author SHA1 Message Date
Zlatin Balevsky
2825a8d9a4 Release 0.2.10 2019-06-19 17:18:30 +01:00
Zlatin Balevsky
8dcce9bda6 Merge branch 'connection-logic' 2019-06-19 17:16:13 +01:00
Zlatin Balevsky
d8d3e2cd58 update tests 2019-06-19 15:54:35 +01:00
Zlatin Balevsky
51d5dbe47e Prevent rare exception on changing trust when result tabs are open 2019-06-19 12:23:18 +01:00
Zlatin Balevsky
84cee0aa43 retry failed hosts after one hour 2019-06-19 08:35:31 +01:00
Zlatin Balevsky
162844787f explicitly set java versions 2019-06-19 02:11:00 +01:00
Zlatin Balevsky
d8a2b59055 tool to print out contents of files.json 2019-06-18 22:08:33 +01:00
Zlatin Balevsky
67a0939de4 Release 0.2.9 2019-06-18 20:15:53 +01:00
Zlatin Balevsky
37ca922a2c reduce default retry interval 2019-06-18 20:07:20 +01:00
Zlatin Balevsky
1d6781819b ignore CWSE if shutting down 2019-06-18 19:44:22 +01:00
Zlatin Balevsky
64d45da94a show version on title 2019-06-18 18:57:44 +01:00
Zlatin Balevsky
59c84d8a5e Release 0.2.8 2019-06-18 17:48:07 +01:00
Zlatin Balevsky
8b55021a4b fix 2019-06-18 17:23:18 +01:00
Zlatin Balevsky
8bd3ebfaf5 timestamp entries 2019-06-18 17:17:03 +01:00
19 changed files with 83 additions and 38 deletions

View File

@@ -35,7 +35,7 @@ class Cli {
Core core
try {
core = new Core(props, home, "0.2.7")
core = new Core(props, home, "0.2.10")
} catch (Exception bad) {
bad.printStackTrace(System.out)
println "Failed to initialize core, exiting"
@@ -73,7 +73,7 @@ class Cli {
Timer timer = new Timer("status-printer", true)
timer.schedule({
println "Connections $connectionsListener.connections Uploads $uploadsListener.uploads Shared $sharedListener.shared"
println String.valueOf(new Date()) + " Connections $connectionsListener.connections Uploads $uploadsListener.uploads Shared $sharedListener.shared"
} as TimerTask, 60000, 60000)
def latch = new CountDownLatch(1)
@@ -119,11 +119,11 @@ class Cli {
volatile int uploads
public void onUploadEvent(UploadEvent e) {
uploads++
println "Starting upload of ${e.uploader.file.getName()} to ${e.uploader.request.downloader.getHumanReadableName()}"
println String.valueOf(new Date()) + " Starting upload of ${e.uploader.file.getName()} to ${e.uploader.request.downloader.getHumanReadableName()}"
}
public void onUploadFinishedEvent(UploadFinishedEvent e) {
uploads--
println "Finished upload of ${e.uploader.file.getName()} to ${e.uploader.request.downloader.getHumanReadableName()}"
println String.valueOf(new Date()) + " Finished upload of ${e.uploader.file.getName()} to ${e.uploader.request.downloader.getHumanReadableName()}"
}
}

View File

@@ -53,7 +53,7 @@ class CliDownloader {
Core core
try {
core = new Core(props, home, "0.2.7")
core = new Core(props, home, "0.2.10")
} catch (Exception bad) {
bad.printStackTrace(System.out)
println "Failed to initialize core, exiting"

View File

@@ -0,0 +1,23 @@
package com.muwire.cli
import com.muwire.core.util.DataUtil
import groovy.json.JsonSlurper
import net.i2p.data.Base64
class FileList {
public static void main(String [] args) {
if (args.length < 1) {
println "pass files.json as argument"
System.exit(1)
}
def slurper = new JsonSlurper()
File filesJson = new File(args[0])
filesJson.eachLine {
def json = slurper.parseText(it)
String name = DataUtil.readi18nString(Base64.decode(json.file))
println "$name,$json.length,$json.pieceSize,$json.infoHash"
}
}
}

View File

@@ -277,7 +277,7 @@ public class Core {
}
}
Core core = new Core(props, home, "0.2.7")
Core core = new Core(props, home, "0.2.10")
core.startServices()
// ... at the end, sleep or execute script

View File

@@ -30,7 +30,7 @@ class MuWireSettings {
nickname = props.getProperty("nickname","MuWireUser")
downloadLocation = new File((String)props.getProperty("downloadLocation",
System.getProperty("user.home")))
downloadRetryInterval = Integer.parseInt(props.getProperty("downloadRetryInterval","15"))
downloadRetryInterval = Integer.parseInt(props.getProperty("downloadRetryInterval","5"))
updateCheckInterval = Integer.parseInt(props.getProperty("updateCheckInterval","36"))
shareDownloadedFiles = Boolean.parseBoolean(props.getProperty("shareDownloadedFiles","true"))

View File

@@ -5,6 +5,8 @@ import java.nio.file.FileSystems
import java.nio.file.Path
import java.nio.file.Paths
import static java.nio.file.StandardWatchEventKinds.*
import java.nio.file.ClosedWatchServiceException
import java.nio.file.WatchEvent
import java.nio.file.WatchKey
import java.nio.file.WatchService
@@ -79,7 +81,7 @@ class DirectoryWatcher {
}
key.reset()
}
} catch (InterruptedException e) {
} catch (InterruptedException|ClosedWatchServiceException e) {
if (!shutdown)
throw e
}

View File

@@ -5,9 +5,11 @@ import net.i2p.data.Destination
class Host {
private static final int MAX_FAILURES = 3
private static final int CLEAR_INTERVAL = 60 * 60 * 1000
final Destination destination
int failures,successes
long lastAttempt
public Host(Destination destination) {
this.destination = destination
@@ -16,11 +18,13 @@ class Host {
synchronized void onConnect() {
failures = 0
successes++
lastAttempt = System.currentTimeMillis()
}
synchronized void onFailure() {
failures++
successes = 0
lastAttempt = System.currentTimeMillis()
}
synchronized boolean isFailed() {
@@ -34,4 +38,8 @@ class Host {
synchronized void clearFailures() {
failures = 0
}
synchronized void canTryAgain() {
System.currentTimeMillis() - lastAttempt > CLEAR_INTERVAL
}
}

View File

@@ -109,6 +109,8 @@ class HostCache extends Service {
Host host = new Host(dest)
host.failures = Integer.valueOf(String.valueOf(entry.failures))
host.successes = Integer.valueOf(String.valueOf(entry.successes))
if (entry.lastAttempt != null)
host.lastAttempt = entry.lastAttempt
if (allowHost(host))
hosts.put(dest, host)
}
@@ -118,7 +120,7 @@ class HostCache extends Service {
}
private boolean allowHost(Host host) {
if (host.isFailed())
if (host.isFailed() && !host.canTryAgain())
return false
if (host.destination == myself)
return false
@@ -143,6 +145,7 @@ class HostCache extends Service {
map.destination = dest.toBase64()
map.failures = host.failures
map.successes = host.successes
map.lastAttempt = host.lastAttempt
def json = JsonOutput.toJson(map)
writer.println json
}

View File

@@ -15,7 +15,7 @@ class DownloadSessionTest {
private File source, target
private InfoHash infoHash
private Endpoint endpoint
private Pieces pieces, claimed
private Pieces pieces
private String rootBase64
private DownloadSession session
@@ -48,8 +48,7 @@ class DownloadSessionTest {
else
nPieces = size / pieceSize + 1
pieces = new Pieces(nPieces)
claimed = new Pieces(nPieces)
claimedPieces.each {claimed.markDownloaded(it)}
claimedPieces.each {pieces.claimed.set(it)}
fromDownloader = new PipedInputStream()
fromUploader = new PipedInputStream()
@@ -57,7 +56,7 @@ class DownloadSessionTest {
toUploader = new PipedOutputStream(fromDownloader)
endpoint = new Endpoint(null, fromUploader, toUploader, null)
session = new DownloadSession("",pieces, claimed, infoHash, endpoint, target, pieceSize, size)
session = new DownloadSession("",pieces, infoHash, endpoint, target, pieceSize, size)
downloadThread = new Thread( { session.request() } as Runnable)
downloadThread.setDaemon(true)
downloadThread.start()
@@ -154,7 +153,7 @@ class DownloadSessionTest {
int pieceSize = FileHasher.getPieceSize(1)
int size = (1 << pieceSize) * 10
initSession(size, [1,2,3,4,5,6,7,8,9])
assert !claimed.isMarked(0)
assert !pieces.claimed.get(0)
assert "GET $rootBase64" == readTillRN(fromDownloader)
String range = readTillRN(fromDownloader)
@@ -162,7 +161,7 @@ class DownloadSessionTest {
int start = Integer.parseInt(matcher[0][1])
int end = Integer.parseInt(matcher[0][2])
assert claimed.isMarked(0)
assert pieces.claimed.get(0)
assert start == 0 && end == (1 << pieceSize) - 1
}
}

View File

@@ -16,7 +16,7 @@ class PiecesTest {
public void testSinglePiece() {
pieces = new Pieces(1)
assert !pieces.isComplete()
assert pieces.getRandomPiece() == 0
assert pieces.claim() == 0
pieces.markDownloaded(0)
assert pieces.isComplete()
}
@@ -25,11 +25,11 @@ class PiecesTest {
public void testTwoPieces() {
pieces = new Pieces(2)
assert !pieces.isComplete()
int piece = pieces.getRandomPiece()
int piece = pieces.claim()
assert piece == 0 || piece == 1
pieces.markDownloaded(piece)
assert !pieces.isComplete()
int piece2 = pieces.getRandomPiece()
int piece2 = pieces.claim()
assert piece != piece2
pieces.markDownloaded(piece2)
assert pieces.isComplete()

View File

@@ -26,7 +26,7 @@ class FileHasherTest extends GroovyTestCase {
void testPieceSize() {
assert 17 == FileHasher.getPieceSize(1000000)
assert 17 == FileHasher.getPieceSize(100000000)
assert 27 == FileHasher.getPieceSize(FileHasher.MAX_SIZE)
assert 24 == FileHasher.getPieceSize(FileHasher.MAX_SIZE)
shouldFail IllegalArgumentException, {
FileHasher.getPieceSize(Long.MAX_VALUE)
}

View File

@@ -27,6 +27,7 @@ class HasherServiceTest {
hasher = new FileHasher()
service = new HasherService(hasher, eventBus, new FileManager(eventBus, new MuWireSettings()))
eventBus.register(FileHashedEvent.class, listener)
eventBus.register(FileSharedEvent.class, service)
service.start()
}

View File

@@ -78,7 +78,7 @@ class PersisterServiceLoadingTest {
persisted.write json
PersisterService ps = new PersisterService(persisted, eventBus, 100, null)
ps.start()
ps.onUILoadedEvent(null)
Thread.sleep(2000)
assert listener.publishedFiles.size() == 1
@@ -121,7 +121,7 @@ class PersisterServiceLoadingTest {
persisted.write json
PersisterService ps = new PersisterService(persisted, eventBus, 100, null)
ps.start()
ps.onUILoadedEvent(null)
Thread.sleep(2000)
assert listener.publishedFiles.size() == 1
@@ -163,7 +163,7 @@ class PersisterServiceLoadingTest {
persisted.append "$json2\n"
PersisterService ps = new PersisterService(persisted, eventBus, 100, null)
ps.start()
ps.onUILoadedEvent(null)
Thread.sleep(2000)
assert listener.publishedFiles.size() == 2
@@ -195,7 +195,7 @@ class PersisterServiceLoadingTest {
persisted.write json1
PersisterService ps = new PersisterService(persisted, eventBus, 100, null)
ps.start()
ps.onUILoadedEvent(null)
Thread.sleep(2000)
assert listener.publishedFiles.size() == 1

View File

@@ -58,7 +58,7 @@ class PersisterServiceSavingTest {
sf = new SharedFile(f, ih, 0)
ps = new PersisterService(persisted, eventBus, 100, fileSource)
ps.start()
ps.onUILoadedEvent(null)
Thread.sleep(1500)
JsonSlurper jsonSlurper = new JsonSlurper()
@@ -77,7 +77,7 @@ class PersisterServiceSavingTest {
sf = new DownloadedFile(f, ih, 0, new HashSet([dests.dest1, dests.dest2]))
ps = new PersisterService(persisted, eventBus, 100, fileSource)
ps.start()
ps.onUILoadedEvent(null)
Thread.sleep(1500)
JsonSlurper jsonSlurper = new JsonSlurper()

View File

@@ -9,18 +9,18 @@ import com.muwire.core.InfoHash
class RequestParsingTest {
Request request
ContentRequest request
private void fromString(String requestString) {
def is = new ByteArrayInputStream(requestString.getBytes(StandardCharsets.US_ASCII))
request = Request.parse(new InfoHash(new byte[InfoHash.SIZE]), is)
request = Request.parseContentRequest(new InfoHash(new byte[InfoHash.SIZE]), is)
}
private static void failed(String requestString) {
try {
def is = new ByteArrayInputStream(requestString.getBytes(StandardCharsets.US_ASCII))
Request.parse(new InfoHash(new byte[InfoHash.SIZE]), is)
Request.parseContentRequest(new InfoHash(new byte[InfoHash.SIZE]), is)
assert false
} catch (IOException expected) {}
}

View File

@@ -19,7 +19,7 @@ class UploaderTest {
InputStream is
OutputStream os
Request request
ContentRequest request
Uploader uploader
byte[] inFile
@@ -52,7 +52,7 @@ class UploaderTest {
}
private void startUpload() {
uploader = new Uploader(file, request, endpoint)
uploader = new ContentUploader(file, request, endpoint)
uploadThread = new Thread(uploader.respond() as Runnable)
uploadThread.setDaemon(true)
uploadThread.start()
@@ -77,7 +77,7 @@ class UploaderTest {
@Test
public void testSmallFile() {
fillFile(20)
request = new Request(range : new Range(0,19))
request = new ContentRequest(range : new Range(0,19))
startUpload()
assert "200 OK" == readUntilRN()
assert "Content-Range: 0-19" == readUntilRN()
@@ -92,7 +92,7 @@ class UploaderTest {
@Test
public void testRequestMiddle() {
fillFile(20)
request = new Request(range : new Range(5,15))
request = new ContentRequest(range : new Range(5,15))
startUpload()
assert "200 OK" == readUntilRN()
assert "Content-Range: 5-15" == readUntilRN()
@@ -108,7 +108,7 @@ class UploaderTest {
@Test
public void testOutOfRange() {
fillFile(20)
request = new Request(range : new Range(0,20))
request = new ContentRequest(range : new Range(0,20))
startUpload()
assert "416 Range Not Satisfiable" == readUntilRN()
assert "" == readUntilRN()
@@ -118,7 +118,7 @@ class UploaderTest {
public void testLargeFile() {
final int length = 0x1 << 14
fillFile(length)
request = new Request(range : new Range(0, length - 1))
request = new ContentRequest(range : new Range(0, length - 1))
startUpload()
readUntilRN()
readUntilRN()

View File

@@ -1,5 +1,8 @@
group = com.muwire
version = 0.2.7
version = 0.2.10
groovyVersion = 2.4.15
slf4jVersion = 1.7.25
spockVersion = 1.1-groovy-2.4
sourceCompatibility=1.8
targetCompatibility=1.8

View File

@@ -282,8 +282,10 @@ class MainFrameModel {
updateTablePreservingSelection("trusted-table")
updateTablePreservingSelection("distrusted-table")
results.values().each {
it.view.pane.getClientProperty("results-table")?.model.fireTableDataChanged()
results.values().each { MVCGroup group ->
if (group.alive) {
group.view.pane.getClientProperty("results-table")?.model.fireTableDataChanged()
}
}
}
}

View File

@@ -1,6 +1,7 @@
package com.muwire.gui
import griffon.core.artifact.GriffonView
import griffon.core.env.Metadata
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import net.i2p.data.Base64
@@ -37,6 +38,7 @@ import java.awt.event.MouseEvent
import java.nio.charset.StandardCharsets
import javax.annotation.Nonnull
import javax.inject.Inject
@ArtifactProviderFor(GriffonView)
class MainFrameView {
@@ -45,6 +47,8 @@ class MainFrameView {
@MVCMember @Nonnull
MainFrameModel model
@Inject Metadata metadata
def downloadsTable
def lastDownloadSortEvent
def lastSharedSortEvent
@@ -54,7 +58,7 @@ class MainFrameView {
builder.with {
application(size : [1024,768], id: 'main-frame',
locationRelativeTo : null,
title: application.configuration['application.title'],
title: application.configuration['application.title'] + " " + metadata["application.version"],
iconImage: imageIcon('/griffon-icon-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image,