Compare commits
5 Commits
muwire-0.1
...
muwire-0.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c81f963e0a | ||
![]() |
dc6b1199f3 | ||
![]() |
42621a2dfb | ||
![]() |
a7125963a7 | ||
![]() |
f39d7f4fa8 |
@@ -31,5 +31,4 @@ The first time you run MuWire it will ask you to select a nickname. This nickna
|
|||||||
### Known bugs and limitations
|
### Known bugs and limitations
|
||||||
|
|
||||||
* Many UI features you would expect are not there yet
|
* Many UI features you would expect are not there yet
|
||||||
* Downloads in progress do not get remembered between restarts
|
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ class Cli {
|
|||||||
|
|
||||||
Core core
|
Core core
|
||||||
try {
|
try {
|
||||||
core = new Core(props, home, "0.1.3")
|
core = new Core(props, home, "0.1.4")
|
||||||
} catch (Exception bad) {
|
} catch (Exception bad) {
|
||||||
bad.printStackTrace(System.out)
|
bad.printStackTrace(System.out)
|
||||||
println "Failed to initialize core, exiting"
|
println "Failed to initialize core, exiting"
|
||||||
|
@@ -53,7 +53,7 @@ class CliDownloader {
|
|||||||
|
|
||||||
Core core
|
Core core
|
||||||
try {
|
try {
|
||||||
core = new Core(props, home, "0.1.3")
|
core = new Core(props, home, "0.1.4")
|
||||||
} catch (Exception bad) {
|
} catch (Exception bad) {
|
||||||
bad.printStackTrace(System.out)
|
bad.printStackTrace(System.out)
|
||||||
println "Failed to initialize core, exiting"
|
println "Failed to initialize core, exiting"
|
||||||
|
@@ -191,8 +191,10 @@ public class Core {
|
|||||||
eventBus.register(ResultsEvent.class, searchManager)
|
eventBus.register(ResultsEvent.class, searchManager)
|
||||||
|
|
||||||
log.info("initializing download manager")
|
log.info("initializing download manager")
|
||||||
DownloadManager downloadManager = new DownloadManager(eventBus, i2pConnector, new File(home, "incompletes"), me)
|
DownloadManager downloadManager = new DownloadManager(eventBus, i2pConnector, home, me)
|
||||||
eventBus.register(UIDownloadEvent.class, downloadManager)
|
eventBus.register(UIDownloadEvent.class, downloadManager)
|
||||||
|
eventBus.register(UILoadedEvent.class, downloadManager)
|
||||||
|
eventBus.register(FileDownloadedEvent.class, downloadManager)
|
||||||
|
|
||||||
log.info("initializing upload manager")
|
log.info("initializing upload manager")
|
||||||
UploadManager uploadManager = new UploadManager(eventBus, fileManager)
|
UploadManager uploadManager = new UploadManager(eventBus, fileManager)
|
||||||
@@ -253,7 +255,7 @@ public class Core {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Core core = new Core(props, home, "0.1.3")
|
Core core = new Core(props, home, "0.1.4")
|
||||||
core.startServices()
|
core.startServices()
|
||||||
|
|
||||||
// ... at the end, sleep or execute script
|
// ... at the end, sleep or execute script
|
||||||
|
@@ -0,0 +1,4 @@
|
|||||||
|
package com.muwire.core
|
||||||
|
|
||||||
|
class UILoadedEvent extends Event {
|
||||||
|
}
|
@@ -1,12 +1,21 @@
|
|||||||
package com.muwire.core.download
|
package com.muwire.core.download
|
||||||
|
|
||||||
import com.muwire.core.connection.I2PConnector
|
import com.muwire.core.connection.I2PConnector
|
||||||
|
import com.muwire.core.files.FileDownloadedEvent
|
||||||
|
import com.muwire.core.files.FileHasher
|
||||||
|
import com.muwire.core.util.DataUtil
|
||||||
|
|
||||||
|
import groovy.json.JsonBuilder
|
||||||
|
import groovy.json.JsonOutput
|
||||||
|
import groovy.json.JsonSlurper
|
||||||
import net.i2p.data.Base64
|
import net.i2p.data.Base64
|
||||||
import net.i2p.data.Destination
|
import net.i2p.data.Destination
|
||||||
|
import net.i2p.util.ConcurrentHashSet
|
||||||
|
|
||||||
import com.muwire.core.EventBus
|
import com.muwire.core.EventBus
|
||||||
|
import com.muwire.core.InfoHash
|
||||||
import com.muwire.core.Persona
|
import com.muwire.core.Persona
|
||||||
|
import com.muwire.core.UILoadedEvent
|
||||||
|
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
@@ -16,13 +25,16 @@ public class DownloadManager {
|
|||||||
private final EventBus eventBus
|
private final EventBus eventBus
|
||||||
private final I2PConnector connector
|
private final I2PConnector connector
|
||||||
private final Executor executor
|
private final Executor executor
|
||||||
private final File incompletes
|
private final File incompletes, home
|
||||||
private final Persona me
|
private final Persona me
|
||||||
|
|
||||||
public DownloadManager(EventBus eventBus, I2PConnector connector, File incompletes, Persona me) {
|
private final Set<Downloader> downloaders = new ConcurrentHashSet<>()
|
||||||
|
|
||||||
|
public DownloadManager(EventBus eventBus, I2PConnector connector, File home, Persona me) {
|
||||||
this.eventBus = eventBus
|
this.eventBus = eventBus
|
||||||
this.connector = connector
|
this.connector = connector
|
||||||
this.incompletes = incompletes
|
this.incompletes = new File(home,"incompletes")
|
||||||
|
this.home = home
|
||||||
this.me = me
|
this.me = me
|
||||||
|
|
||||||
incompletes.mkdir()
|
incompletes.mkdir()
|
||||||
@@ -50,6 +62,8 @@ public class DownloadManager {
|
|||||||
def downloader = new Downloader(eventBus, this, me, e.target, size,
|
def downloader = new Downloader(eventBus, this, me, e.target, size,
|
||||||
infohash, pieceSize, connector, destinations,
|
infohash, pieceSize, connector, destinations,
|
||||||
incompletes)
|
incompletes)
|
||||||
|
downloaders.add(downloader)
|
||||||
|
persistDownloaders()
|
||||||
executor.execute({downloader.download()} as Runnable)
|
executor.execute({downloader.download()} as Runnable)
|
||||||
eventBus.publish(new DownloadStartedEvent(downloader : downloader))
|
eventBus.publish(new DownloadStartedEvent(downloader : downloader))
|
||||||
}
|
}
|
||||||
@@ -57,4 +71,53 @@ public class DownloadManager {
|
|||||||
void resume(Downloader downloader) {
|
void resume(Downloader downloader) {
|
||||||
executor.execute({downloader.download() as Runnable})
|
executor.execute({downloader.download() as Runnable})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onUILoadedEvent(UILoadedEvent e) {
|
||||||
|
File downloadsFile = new File(home, "downloads.json")
|
||||||
|
if (!downloadsFile.exists())
|
||||||
|
return
|
||||||
|
def slurper = new JsonSlurper()
|
||||||
|
downloadsFile.eachLine {
|
||||||
|
def json = slurper.parseText(it)
|
||||||
|
File file = new File(DataUtil.readi18nString(Base64.decode(json.file)))
|
||||||
|
def destinations = new HashSet<>()
|
||||||
|
json.destinations.each { destination ->
|
||||||
|
destinations.add new Destination(destination)
|
||||||
|
}
|
||||||
|
byte[] hashList = Base64.decode(json.hashList)
|
||||||
|
InfoHash infoHash = InfoHash.fromHashList(hashList)
|
||||||
|
def downloader = new Downloader(eventBus, this, me, file, (long)json.length,
|
||||||
|
infoHash, json.pieceSizePow2, connector, destinations, incompletes)
|
||||||
|
downloader.download()
|
||||||
|
eventBus.publish(new DownloadStartedEvent(downloader : downloader))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onFileDownloadedEvent(FileDownloadedEvent e) {
|
||||||
|
downloaders.remove(e.downloader)
|
||||||
|
persistDownloaders()
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistDownloaders() {
|
||||||
|
File downloadsFile = new File(home,"downloads.json")
|
||||||
|
downloadsFile.withPrintWriter { writer ->
|
||||||
|
downloaders.each { downloader ->
|
||||||
|
if (!downloader.cancelled) {
|
||||||
|
def json = [:]
|
||||||
|
json.file = Base64.encode(DataUtil.encodei18nString(downloader.file.getAbsolutePath()))
|
||||||
|
json.length = downloader.length
|
||||||
|
json.pieceSizePow2 = downloader.pieceSizePow2
|
||||||
|
def destinations = []
|
||||||
|
downloader.destinations.each {
|
||||||
|
destinations << it.toBase64()
|
||||||
|
}
|
||||||
|
json.destinations = destinations
|
||||||
|
|
||||||
|
json.hashList = Base64.encode(downloader.infoHash.hashList)
|
||||||
|
|
||||||
|
writer.println(JsonOutput.toJson(json))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,7 @@ public class Downloader {
|
|||||||
private final Set<Destination> destinations
|
private final Set<Destination> destinations
|
||||||
private final int nPieces
|
private final int nPieces
|
||||||
private final File piecesFile
|
private final File piecesFile
|
||||||
|
final int pieceSizePow2
|
||||||
private final Map<Destination, DownloadWorker> activeWorkers = new ConcurrentHashMap<>()
|
private final Map<Destination, DownloadWorker> activeWorkers = new ConcurrentHashMap<>()
|
||||||
|
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ public class Downloader {
|
|||||||
this.connector = connector
|
this.connector = connector
|
||||||
this.destinations = destinations
|
this.destinations = destinations
|
||||||
this.piecesFile = new File(incompletes, file.getName()+".pieces")
|
this.piecesFile = new File(incompletes, file.getName()+".pieces")
|
||||||
|
this.pieceSizePow2 = pieceSizePow2
|
||||||
this.pieceSize = 1 << pieceSizePow2
|
this.pieceSize = 1 << pieceSizePow2
|
||||||
|
|
||||||
int nPieces
|
int nPieces
|
||||||
@@ -88,8 +90,8 @@ public class Downloader {
|
|||||||
void readPieces() {
|
void readPieces() {
|
||||||
if (!piecesFile.exists())
|
if (!piecesFile.exists())
|
||||||
return
|
return
|
||||||
piecesFile.withReader {
|
piecesFile.eachLine {
|
||||||
int piece = Integer.parseInt(it.readLine())
|
int piece = Integer.parseInt(it)
|
||||||
downloaded.markDownloaded(piece)
|
downloaded.markDownloaded(piece)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,11 +165,18 @@ public class Downloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void resume() {
|
public void resume() {
|
||||||
activeWorkers.each { destination, worker ->
|
destinations.each { destination ->
|
||||||
if (worker.currentState == WorkerState.FINISHED) {
|
def worker = activeWorkers.get(destination)
|
||||||
def newWorker = new DownloadWorker(destination)
|
if (worker != null) {
|
||||||
activeWorkers.put(destination, newWorker)
|
if (worker.currentState == WorkerState.FINISHED) {
|
||||||
executorService.submit(newWorker)
|
def newWorker = new DownloadWorker(destination)
|
||||||
|
activeWorkers.put(destination, newWorker)
|
||||||
|
executorService.submit(newWorker)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
worker = new DownloadWorker(destination)
|
||||||
|
activeWorkers.put(destination, worker)
|
||||||
|
executorService.submit(worker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +214,8 @@ public class Downloader {
|
|||||||
if (downloaded.isComplete() && !eventFired) {
|
if (downloaded.isComplete() && !eventFired) {
|
||||||
piecesFile.delete()
|
piecesFile.delete()
|
||||||
eventFired = true
|
eventFired = true
|
||||||
eventBus.publish(new FileDownloadedEvent(downloadedFile : new DownloadedFile(file, infoHash, pieceSize, Collections.emptySet())))
|
eventBus.publish(new FileDownloadedEvent(downloadedFile : new DownloadedFile(file, infoHash, pieceSize, Collections.emptySet())),
|
||||||
|
downloader : Downloader.this)
|
||||||
}
|
}
|
||||||
endpoint?.close()
|
endpoint?.close()
|
||||||
}
|
}
|
||||||
|
@@ -2,10 +2,11 @@ package com.muwire.core.files
|
|||||||
|
|
||||||
import com.muwire.core.DownloadedFile
|
import com.muwire.core.DownloadedFile
|
||||||
import com.muwire.core.Event
|
import com.muwire.core.Event
|
||||||
|
import com.muwire.core.download.Downloader
|
||||||
|
|
||||||
import net.i2p.data.Destination
|
import net.i2p.data.Destination
|
||||||
|
|
||||||
class FileDownloadedEvent extends Event {
|
class FileDownloadedEvent extends Event {
|
||||||
|
Downloader downloader
|
||||||
DownloadedFile downloadedFile
|
DownloadedFile downloadedFile
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import com.muwire.core.EventBus
|
|||||||
import com.muwire.core.InfoHash
|
import com.muwire.core.InfoHash
|
||||||
import com.muwire.core.MuWireSettings
|
import com.muwire.core.MuWireSettings
|
||||||
import com.muwire.core.SharedFile
|
import com.muwire.core.SharedFile
|
||||||
|
import com.muwire.core.UILoadedEvent
|
||||||
import com.muwire.core.search.ResultsEvent
|
import com.muwire.core.search.ResultsEvent
|
||||||
import com.muwire.core.search.SearchEvent
|
import com.muwire.core.search.SearchEvent
|
||||||
import com.muwire.core.search.SearchIndex
|
import com.muwire.core.search.SearchIndex
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
group = com.muwire
|
group = com.muwire
|
||||||
version = 0.1.3
|
version = 0.1.4
|
||||||
groovyVersion = 2.4.15
|
groovyVersion = 2.4.15
|
||||||
slf4jVersion = 1.7.25
|
slf4jVersion = 1.7.25
|
||||||
spockVersion = 1.1-groovy-2.4
|
spockVersion = 1.1-groovy-2.4
|
||||||
|
@@ -7,6 +7,7 @@ import org.codehaus.griffon.runtime.core.AbstractLifecycleHandler
|
|||||||
|
|
||||||
import com.muwire.core.Core
|
import com.muwire.core.Core
|
||||||
import com.muwire.core.MuWireSettings
|
import com.muwire.core.MuWireSettings
|
||||||
|
import com.muwire.core.UILoadedEvent
|
||||||
import com.muwire.core.files.FileSharedEvent
|
import com.muwire.core.files.FileSharedEvent
|
||||||
|
|
||||||
import javax.annotation.Nonnull
|
import javax.annotation.Nonnull
|
||||||
@@ -117,6 +118,8 @@ class Ready extends AbstractLifecycleHandler {
|
|||||||
core.eventBus.publish(new FileSharedEvent(file : new File(it)))
|
core.eventBus.publish(new FileSharedEvent(file : new File(it)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core.eventBus.publish(new UILoadedEvent())
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String selectHome() {
|
private static String selectHome() {
|
||||||
|
Reference in New Issue
Block a user