Compare commits

..

8 Commits

Author SHA1 Message Date
Zlatin Balevsky
2f3d23bc34 fixes 2019-06-29 10:12:50 +01:00
Zlatin Balevsky
98dd80c4b8 fix 2019-06-29 10:03:58 +01:00
Zlatin Balevsky
d9edb2e128 ability to download updates automatically 2019-06-29 09:23:27 +01:00
Zlatin Balevsky
de04b40b86 Release 0.4.2 2019-06-29 07:17:45 +01:00
Zlatin Balevsky
7206a3d926 more i2p metrics 2019-06-29 07:07:48 +01:00
Zlatin Balevsky
98b98d8938 I2P status panel 2019-06-29 06:33:53 +01:00
Zlatin Balevsky
294b8fcc2f MW status window 2019-06-29 05:58:46 +01:00
Zlatin Balevsky
32f601a1b1 add ability to change i2p port 2019-06-28 23:53:22 +01:00
23 changed files with 558 additions and 38 deletions

View File

@@ -35,7 +35,7 @@ class Cli {
Core core Core core
try { try {
core = new Core(props, home, "0.4.1") core = new Core(props, home, "0.4.2")
} 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"

View File

@@ -53,7 +53,7 @@ class CliDownloader {
Core core Core core
try { try {
core = new Core(props, home, "0.4.1") core = new Core(props, home, "0.4.2")
} 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"

View File

@@ -39,6 +39,7 @@ import com.muwire.core.search.ResultsEvent
import com.muwire.core.search.ResultsSender import com.muwire.core.search.ResultsSender
import com.muwire.core.search.SearchEvent import com.muwire.core.search.SearchEvent
import com.muwire.core.search.SearchManager import com.muwire.core.search.SearchManager
import com.muwire.core.search.UIResultBatchEvent
import com.muwire.core.trust.TrustEvent import com.muwire.core.trust.TrustEvent
import com.muwire.core.trust.TrustService import com.muwire.core.trust.TrustService
import com.muwire.core.update.UpdateClient import com.muwire.core.update.UpdateClient
@@ -84,6 +85,7 @@ public class Core {
private final DownloadManager downloadManager private final DownloadManager downloadManager
private final DirectoryWatcher directoryWatcher private final DirectoryWatcher directoryWatcher
final FileManager fileManager final FileManager fileManager
final UploadManager uploadManager
private final Router router private final Router router
@@ -93,35 +95,6 @@ public class Core {
this.home = home this.home = home
this.muOptions = props this.muOptions = props
if (!props.embeddedRouter) {
log.info "Initializing I2P context"
I2PAppContext.getGlobalContext().logManager()
I2PAppContext.getGlobalContext()._logManager = new MuWireLogManager()
router = null
} else {
log.info("launching embedded router")
Properties routerProps = new Properties()
routerProps.setProperty("i2p.dir.config", home.getAbsolutePath())
routerProps.setProperty("i2np.inboundKBytesPerSecond", String.valueOf(props.inBw))
routerProps.setProperty("i2np.outboundKBytesPerSecond", String.valueOf(props.outBw))
routerProps.setProperty("i2cp.disableInterface", "true")
router = new Router(routerProps)
I2PAppContext.getGlobalContext().metaClass = new RouterContextMetaClass()
router.runRouter()
while(!router.isRunning())
Thread.sleep(100)
}
log.info("initializing I2P socket manager")
def i2pClient = new I2PClientFactory().createClient()
File keyDat = new File(home, "key.dat")
if (!keyDat.exists()) {
log.info("Creating new key.dat")
keyDat.withOutputStream {
i2pClient.createDestination(it, Constants.SIG_TYPE)
}
}
i2pOptions = new Properties() i2pOptions = new Properties()
def i2pOptionsFile = new File(home,"i2p.properties") def i2pOptionsFile = new File(home,"i2p.properties")
if (i2pOptionsFile.exists()) { if (i2pOptionsFile.exists()) {
@@ -140,8 +113,46 @@ public class Core {
i2pOptions["outbound.quantity"] = "4" i2pOptions["outbound.quantity"] = "4"
i2pOptions["i2cp.tcp.host"] = "127.0.0.1" i2pOptions["i2cp.tcp.host"] = "127.0.0.1"
i2pOptions["i2cp.tcp.port"] = "7654" i2pOptions["i2cp.tcp.port"] = "7654"
Random r = new Random()
int port = r.nextInt(60000) + 4000
i2pOptions["i2np.ntcp.port"] = String.valueOf(port)
i2pOptions["i2np.udp.port"] = String.valueOf(port)
i2pOptionsFile.withOutputStream { i2pOptions.store(it, "") }
} }
if (!props.embeddedRouter) {
log.info "Initializing I2P context"
I2PAppContext.getGlobalContext().logManager()
I2PAppContext.getGlobalContext()._logManager = new MuWireLogManager()
router = null
} else {
log.info("launching embedded router")
Properties routerProps = new Properties()
routerProps.setProperty("i2p.dir.config", home.getAbsolutePath())
routerProps.setProperty("i2np.inboundKBytesPerSecond", String.valueOf(props.inBw))
routerProps.setProperty("i2np.outboundKBytesPerSecond", String.valueOf(props.outBw))
routerProps.setProperty("i2cp.disableInterface", "true")
routerProps.setProperty("i2np.ntcp.port", i2pOptions["i2np.ntcp.port"])
routerProps.setProperty("i2np.udp.port", i2pOptions["i2np.udp.port"])
routerProps.setProperty("i2np.udp.internalPort", i2pOptions["i2np.udp.port"])
router = new Router(routerProps)
I2PAppContext.getGlobalContext().metaClass = new RouterContextMetaClass()
router.runRouter()
while(!router.isRunning())
Thread.sleep(100)
}
log.info("initializing I2P socket manager")
def i2pClient = new I2PClientFactory().createClient()
File keyDat = new File(home, "key.dat")
if (!keyDat.exists()) {
log.info("Creating new key.dat")
keyDat.withOutputStream {
i2pClient.createDestination(it, Constants.SIG_TYPE)
}
}
// options like tunnel length and quantity // options like tunnel length and quantity
I2PSession i2pSession I2PSession i2pSession
I2PSocketManager socketManager I2PSocketManager socketManager
@@ -223,7 +234,9 @@ public class Core {
cacheClient = new CacheClient(eventBus,hostCache, connectionManager, i2pSession, props, 10000) cacheClient = new CacheClient(eventBus,hostCache, connectionManager, i2pSession, props, 10000)
log.info("initializing update client") log.info("initializing update client")
updateClient = new UpdateClient(eventBus, i2pSession, myVersion, props) updateClient = new UpdateClient(eventBus, i2pSession, myVersion, props, fileManager, me)
eventBus.register(FileDownloadedEvent.class, updateClient)
eventBus.register(UIResultBatchEvent.class, updateClient)
log.info("initializing connector") log.info("initializing connector")
I2PConnector i2pConnector = new I2PConnector(socketManager) I2PConnector i2pConnector = new I2PConnector(socketManager)
@@ -247,7 +260,7 @@ public class Core {
eventBus.register(UIDownloadResumedEvent.class, downloadManager) eventBus.register(UIDownloadResumedEvent.class, downloadManager)
log.info("initializing upload manager") log.info("initializing upload manager")
UploadManager uploadManager = new UploadManager(eventBus, fileManager, meshManager, downloadManager) uploadManager = new UploadManager(eventBus, fileManager, meshManager, downloadManager)
log.info("initializing connection establisher") log.info("initializing connection establisher")
connectionEstablisher = new ConnectionEstablisher(eventBus, i2pConnector, props, connectionManager, hostCache) connectionEstablisher = new ConnectionEstablisher(eventBus, i2pConnector, props, connectionManager, hostCache)
@@ -339,7 +352,7 @@ public class Core {
} }
} }
Core core = new Core(props, home, "0.4.1") Core core = new Core(props, home, "0.4.2")
core.startServices() core.startServices()
// ... at the end, sleep or execute script // ... at the end, sleep or execute script

View File

@@ -13,6 +13,7 @@ class MuWireSettings {
boolean allowUntrusted boolean allowUntrusted
int downloadRetryInterval int downloadRetryInterval
int updateCheckInterval int updateCheckInterval
boolean autoDownloadUpdate
String nickname String nickname
File downloadLocation File downloadLocation
CrawlerResponse crawlerResponse CrawlerResponse crawlerResponse
@@ -37,6 +38,7 @@ class MuWireSettings {
System.getProperty("user.home"))) System.getProperty("user.home")))
downloadRetryInterval = Integer.parseInt(props.getProperty("downloadRetryInterval","1")) downloadRetryInterval = Integer.parseInt(props.getProperty("downloadRetryInterval","1"))
updateCheckInterval = Integer.parseInt(props.getProperty("updateCheckInterval","24")) updateCheckInterval = Integer.parseInt(props.getProperty("updateCheckInterval","24"))
autoDownloadUpdate = Boolean.parseBoolean(props.getProperty("autoDownloadUpdate","true"))
shareDownloadedFiles = Boolean.parseBoolean(props.getProperty("shareDownloadedFiles","true")) shareDownloadedFiles = Boolean.parseBoolean(props.getProperty("shareDownloadedFiles","true"))
downloadSequentialRatio = Float.valueOf(props.getProperty("downloadSequentialRatio","0.8")) downloadSequentialRatio = Float.valueOf(props.getProperty("downloadSequentialRatio","0.8"))
hostClearInterval = Integer.valueOf(props.getProperty("hostClearInterval","60")) hostClearInterval = Integer.valueOf(props.getProperty("hostClearInterval","60"))
@@ -62,6 +64,7 @@ class MuWireSettings {
props.setProperty("downloadLocation", downloadLocation.getAbsolutePath()) props.setProperty("downloadLocation", downloadLocation.getAbsolutePath())
props.setProperty("downloadRetryInterval", String.valueOf(downloadRetryInterval)) props.setProperty("downloadRetryInterval", String.valueOf(downloadRetryInterval))
props.setProperty("updateCheckInterval", String.valueOf(updateCheckInterval)) props.setProperty("updateCheckInterval", String.valueOf(updateCheckInterval))
props.setProperty("autoDownloadUpdate", String.valueOf(autoDownloadUpdate))
props.setProperty("shareDownloadedFiles", String.valueOf(shareDownloadedFiles)) props.setProperty("shareDownloadedFiles", String.valueOf(shareDownloadedFiles))
props.setProperty("downloadSequentialRatio", String.valueOf(downloadSequentialRatio)) props.setProperty("downloadSequentialRatio", String.valueOf(downloadSequentialRatio))
props.setProperty("hostClearInterval", String.valueOf(hostClearInterval)) props.setProperty("hostClearInterval", String.valueOf(hostClearInterval))

View File

@@ -3,7 +3,15 @@ package com.muwire.core.update
import java.util.logging.Level import java.util.logging.Level
import com.muwire.core.EventBus import com.muwire.core.EventBus
import com.muwire.core.InfoHash
import com.muwire.core.MuWireSettings import com.muwire.core.MuWireSettings
import com.muwire.core.Persona
import com.muwire.core.download.UIDownloadEvent
import com.muwire.core.files.FileDownloadedEvent
import com.muwire.core.files.FileManager
import com.muwire.core.search.QueryEvent
import com.muwire.core.search.SearchEvent
import com.muwire.core.search.UIResultBatchEvent
import groovy.json.JsonOutput import groovy.json.JsonOutput
import groovy.json.JsonSlurper import groovy.json.JsonSlurper
@@ -13,6 +21,7 @@ import net.i2p.client.I2PSessionMuxedListener
import net.i2p.client.SendMessageOptions import net.i2p.client.SendMessageOptions
import net.i2p.client.datagram.I2PDatagramDissector import net.i2p.client.datagram.I2PDatagramDissector
import net.i2p.client.datagram.I2PDatagramMaker import net.i2p.client.datagram.I2PDatagramMaker
import net.i2p.data.Base64
import net.i2p.util.VersionComparator import net.i2p.util.VersionComparator
@Log @Log
@@ -21,16 +30,24 @@ class UpdateClient {
final I2PSession session final I2PSession session
final String myVersion final String myVersion
final MuWireSettings settings final MuWireSettings settings
final FileManager fileManager
final Persona me
private final Timer timer private final Timer timer
private long lastUpdateCheckTime private long lastUpdateCheckTime
UpdateClient(EventBus eventBus, I2PSession session, String myVersion, MuWireSettings settings) { private volatile InfoHash updateInfoHash
private volatile String version, signer
private volatile boolean updateDownloading
UpdateClient(EventBus eventBus, I2PSession session, String myVersion, MuWireSettings settings, FileManager fileManager, Persona me) {
this.eventBus = eventBus this.eventBus = eventBus
this.session = session this.session = session
this.myVersion = myVersion this.myVersion = myVersion
this.settings = settings this.settings = settings
this.fileManager = fileManager
this.me = me
timer = new Timer("update-client",true) timer = new Timer("update-client",true)
} }
@@ -43,6 +60,24 @@ class UpdateClient {
timer.cancel() timer.cancel()
} }
void onUIResultBatchEvent(UIResultBatchEvent results) {
if (results.results[0].infohash != updateInfoHash)
return
if (updateDownloading)
return
updateDownloading = true
def file = new File(settings.downloadLocation, results.results[0].name)
def downloadEvent = new UIDownloadEvent(result: results.results[0], sources : results.results[0].sources, target : file)
eventBus.publish(downloadEvent)
}
void onFileDownloadedEvent(FileDownloadedEvent e) {
if (e.downloadedFile.infoHash != updateInfoHash)
return
updateDownloading = false
eventBus.publish(new UpdateDownloadedEvent(version : version, signer : signer))
}
private void checkUpdate() { private void checkUpdate() {
final long now = System.currentTimeMillis() final long now = System.currentTimeMillis()
if (lastUpdateCheckTime > 0) { if (lastUpdateCheckTime > 0) {
@@ -106,8 +141,25 @@ class UpdateClient {
return return
} }
if (!settings.autoDownloadUpdate) {
log.info("new version $payload.version available, publishing event") log.info("new version $payload.version available, publishing event")
eventBus.publish(new UpdateAvailableEvent(version : payload.version, signer : payload.signer, infoHash : payload.infoHash)) eventBus.publish(new UpdateAvailableEvent(version : payload.version, signer : payload.signer, infoHash : payload.infoHash))
} else {
log.info("new version $payload.version available")
updateInfoHash = new InfoHash(Base64.decode(payload.infoHash))
if (fileManager.rootToFiles.containsKey(updateInfoHash))
eventBus.publish(new UpdateDownloadedEvent(version : payload.version, signer : payload.signer))
else {
updateDownloading = false
version = payload.version
signer = payload.signer
log.info("starting search for new version hash $payload.infoHash")
def searchEvent = new SearchEvent(searchHash : updateInfoHash.getRoot(), uuid : UUID.randomUUID(), oobInfohash : true)
def queryEvent = new QueryEvent(searchEvent : searchEvent, firstHop : true, replyTo : me.destination,
receivedOn : me.destination, originator : me)
eventBus.publish(queryEvent)
}
}
} catch (Exception e) { } catch (Exception e) {
log.log(Level.WARNING,"Invalid datagram",e) log.log(Level.WARNING,"Invalid datagram",e)

View File

@@ -0,0 +1,8 @@
package com.muwire.core.update
import com.muwire.core.Event
class UpdateDownloadedEvent extends Event {
String version
String signer
}

View File

@@ -1,5 +1,5 @@
group = com.muwire group = com.muwire
version = 0.4.1 version = 0.4.2
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

View File

@@ -26,4 +26,14 @@ mvcGroups {
view = 'com.muwire.gui.OptionsView' view = 'com.muwire.gui.OptionsView'
controller = 'com.muwire.gui.OptionsController' controller = 'com.muwire.gui.OptionsController'
} }
"mu-wire-status" {
model = 'com.muwire.gui.MuWireStatusModel'
view = 'com.muwire.gui.MuWireStatusView'
controller = 'com.muwire.gui.MuWireStatusController'
}
'i-2-p-status' {
model = 'com.muwire.gui.I2PStatusModel'
view = 'com.muwire.gui.I2PStatusView'
controller = 'com.muwire.gui.I2PStatusController'
}
} }

View File

@@ -0,0 +1,40 @@
package com.muwire.gui
import griffon.core.artifact.GriffonController
import griffon.core.controller.ControllerAction
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import net.i2p.router.Router
import javax.annotation.Nonnull
import com.muwire.core.Core
@ArtifactProviderFor(GriffonController)
class I2PStatusController {
@MVCMember @Nonnull
I2PStatusModel model
@MVCMember @Nonnull
I2PStatusView view
@ControllerAction
void refresh() {
Core core = application.context.get("core")
Router router = core.router
model.networkStatus = router._context.commSystem().status.toStatusString()
model.ntcpConnections = router._context.commSystem().getTransports()["NTCP"].countPeers()
model.ssuConnections = router._context.commSystem().getTransports()["SSU"].countPeers()
model.participatingTunnels = router._context.tunnelManager().getParticipatingCount()
model.activePeers = router._context.profileOrganizer().countActivePeers()
model.receiveBps = router._context.bandwidthLimiter().getReceiveBps15s()
model.sendBps = router._context.bandwidthLimiter().getSendBps15s()
model.participatingBW = router._context.bandwidthLimiter().getCurrentParticipatingBandwidth()
}
@ControllerAction
void close() {
view.dialog.setVisible(false)
mvcGroup.destroy()
}
}

View File

@@ -0,0 +1,45 @@
package com.muwire.gui
import griffon.core.artifact.GriffonController
import griffon.core.controller.ControllerAction
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import javax.annotation.Nonnull
import com.muwire.core.Core
@ArtifactProviderFor(GriffonController)
class MuWireStatusController {
@MVCMember @Nonnull
MuWireStatusModel model
@MVCMember @Nonnull
MuWireStatusView view
@ControllerAction
void refresh() {
Core core = application.context.get("core")
int incoming = 0
int outgoing = 0
core.connectionManager.getConnections().each {
if (it.incoming)
incoming++
else
outgoing++
}
model.incomingConnections = incoming
model.outgoingConnections = outgoing
model.knownHosts = core.hostCache.hosts.size()
model.sharedFiles = core.fileManager.fileToSharedFile.size()
model.downloads = core.downloadManager.downloaders.size()
}
@ControllerAction
void close() {
view.dialog.setVisible(false)
mvcGroup.destroy()
}
}

View File

@@ -25,6 +25,7 @@ class OptionsController {
void save() { void save() {
String text String text
Core core = application.context.get("core") Core core = application.context.get("core")
MuWireSettings settings = application.context.get("muwire-settings")
def i2pProps = core.i2pOptions def i2pProps = core.i2pOptions
@@ -44,6 +45,17 @@ class OptionsController {
model.outboundLength = text model.outboundLength = text
i2pProps["outbound.length"] = text i2pProps["outbound.length"] = text
if (settings.embeddedRouter) {
text = view.i2pNTCPPortField.text
model.i2pNTCPPort = text
i2pProps["i2np.ntcp.port"] = text
text = view.i2pUDPPortField.text
model.i2pUDPPort = text
i2pProps["i2np.udp.port"] = text
}
File i2pSettingsFile = new File(core.home, "i2p.properties") File i2pSettingsFile = new File(core.home, "i2p.properties")
i2pSettingsFile.withOutputStream { i2pSettingsFile.withOutputStream {
i2pProps.store(it,"") i2pProps.store(it,"")
@@ -52,13 +64,16 @@ class OptionsController {
text = view.retryField.text text = view.retryField.text
model.downloadRetryInterval = text model.downloadRetryInterval = text
MuWireSettings settings = application.context.get("muwire-settings")
settings.downloadRetryInterval = Integer.valueOf(text) settings.downloadRetryInterval = Integer.valueOf(text)
text = view.updateField.text text = view.updateField.text
model.updateCheckInterval = text model.updateCheckInterval = text
settings.updateCheckInterval = Integer.valueOf(text) settings.updateCheckInterval = Integer.valueOf(text)
boolean autoDownloadUpdate = view.autoDownloadUpdateCheckbox.model.isSelected()
model.autoDownloadUpdate = autoDownloadUpdate
settings.autoDownloadUpdate = autoDownloadUpdate
boolean onlyTrusted = view.allowUntrustedCheckbox.model.isSelected() boolean onlyTrusted = view.allowUntrustedCheckbox.model.isSelected()
model.onlyTrusted = onlyTrusted model.onlyTrusted = onlyTrusted
settings.setAllowUntrusted(!onlyTrusted) settings.setAllowUntrusted(!onlyTrusted)

View File

@@ -0,0 +1,27 @@
package com.muwire.gui
import javax.annotation.Nonnull
import griffon.core.artifact.GriffonModel
import griffon.inject.MVCMember
import griffon.transform.Observable
import griffon.metadata.ArtifactProviderFor
@ArtifactProviderFor(GriffonModel)
class I2PStatusModel {
@MVCMember @Nonnull
I2PStatusController controller
@Observable int ntcpConnections
@Observable int ssuConnections
@Observable String networkStatus
@Observable int participatingTunnels
@Observable int activePeers
@Observable int receiveBps
@Observable int sendBps
@Observable int participatingBW
void mvcGroupInit(Map<String,String> args) {
controller.refresh()
}
}

View File

@@ -29,6 +29,7 @@ import com.muwire.core.search.UIResultEvent
import com.muwire.core.trust.TrustEvent import com.muwire.core.trust.TrustEvent
import com.muwire.core.trust.TrustService import com.muwire.core.trust.TrustService
import com.muwire.core.update.UpdateAvailableEvent import com.muwire.core.update.UpdateAvailableEvent
import com.muwire.core.update.UpdateDownloadedEvent
import com.muwire.core.upload.UploadEvent import com.muwire.core.upload.UploadEvent
import com.muwire.core.upload.UploadFinishedEvent import com.muwire.core.upload.UploadFinishedEvent
@@ -52,6 +53,7 @@ class MainFrameModel {
MainFrameController controller MainFrameController controller
@Inject @Nonnull GriffonApplication application @Inject @Nonnull GriffonApplication application
@Observable boolean coreInitialized = false @Observable boolean coreInitialized = false
@Observable boolean routerPresent
def results = new ConcurrentHashMap<>() def results = new ConcurrentHashMap<>()
def downloads = [] def downloads = []
@@ -76,7 +78,7 @@ class MainFrameModel {
private final Set<InfoHash> downloadInfoHashes = new HashSet<>() private final Set<InfoHash> downloadInfoHashes = new HashSet<>()
volatile Core core @Observable volatile Core core
private long lastRetryTime = System.currentTimeMillis() private long lastRetryTime = System.currentTimeMillis()
@@ -124,6 +126,7 @@ class MainFrameModel {
application.addPropertyChangeListener("core", {e -> application.addPropertyChangeListener("core", {e ->
coreInitialized = (e.getNewValue() != null) coreInitialized = (e.getNewValue() != null)
core = e.getNewValue() core = e.getNewValue()
routerPresent = core.router != null
me = core.me.getHumanReadableName() me = core.me.getHumanReadableName()
core.eventBus.register(UIResultEvent.class, this) core.eventBus.register(UIResultEvent.class, this)
core.eventBus.register(UIResultBatchEvent.class, this) core.eventBus.register(UIResultBatchEvent.class, this)
@@ -141,6 +144,7 @@ class MainFrameModel {
core.eventBus.register(FileUnsharedEvent.class, this) core.eventBus.register(FileUnsharedEvent.class, this)
core.eventBus.register(RouterDisconnectedEvent.class, this) core.eventBus.register(RouterDisconnectedEvent.class, this)
core.eventBus.register(AllFilesLoadedEvent.class, this) core.eventBus.register(AllFilesLoadedEvent.class, this)
core.eventBus.register(UpdateDownloadedEvent.class, this)
timer.schedule({ timer.schedule({
if (core.shutdown.get()) if (core.shutdown.get())
@@ -183,6 +187,14 @@ class MainFrameModel {
watched.each { core.eventBus.publish(new FileSharedEvent(file : new File(it))) } watched.each { core.eventBus.publish(new FileSharedEvent(file : new File(it))) }
} }
} }
void onUpdateDownloadedEvent(UpdateDownloadedEvent e) {
runInsideUIAsync {
JOptionPane.showMessageDialog(null, "MuWire $e.version has been downloaded. You can update now",
"Update Downloaded", JOptionPane.INFORMATION_MESSAGE)
}
}
void onUIResultEvent(UIResultEvent e) { void onUIResultEvent(UIResultEvent e) {
MVCGroup resultsGroup = results.get(e.uuid) MVCGroup resultsGroup = results.get(e.uuid)
resultsGroup?.model.handleResult(e) resultsGroup?.model.handleResult(e)

View File

@@ -0,0 +1,25 @@
package com.muwire.gui
import javax.annotation.Nonnull
import griffon.core.artifact.GriffonModel
import griffon.inject.MVCMember
import griffon.transform.Observable
import griffon.metadata.ArtifactProviderFor
@ArtifactProviderFor(GriffonModel)
class MuWireStatusModel {
@MVCMember @Nonnull
MuWireStatusController controller
@Observable int incomingConnections
@Observable int outgoingConnections
@Observable int knownHosts
@Observable int sharedFiles
@Observable int downloads
void mvcGroupInit(Map<String,String> args) {
controller.refresh()
}
}

View File

@@ -11,6 +11,7 @@ import griffon.metadata.ArtifactProviderFor
class OptionsModel { class OptionsModel {
@Observable String downloadRetryInterval @Observable String downloadRetryInterval
@Observable String updateCheckInterval @Observable String updateCheckInterval
@Observable boolean autoDownloadUpdate
@Observable boolean onlyTrusted @Observable boolean onlyTrusted
@Observable boolean shareDownloadedFiles @Observable boolean shareDownloadedFiles
@Observable String downloadLocation @Observable String downloadLocation
@@ -20,6 +21,8 @@ class OptionsModel {
@Observable String inboundQuantity @Observable String inboundQuantity
@Observable String outboundLength @Observable String outboundLength
@Observable String outboundQuantity @Observable String outboundQuantity
@Observable String i2pUDPPort
@Observable String i2pNTCPPort
// gui options // gui options
@Observable boolean showMonitor @Observable boolean showMonitor
@@ -38,6 +41,7 @@ class OptionsModel {
MuWireSettings settings = application.context.get("muwire-settings") MuWireSettings settings = application.context.get("muwire-settings")
downloadRetryInterval = settings.downloadRetryInterval downloadRetryInterval = settings.downloadRetryInterval
updateCheckInterval = settings.updateCheckInterval updateCheckInterval = settings.updateCheckInterval
autoDownloadUpdate = settings.autoDownloadUpdate
onlyTrusted = !settings.allowUntrusted() onlyTrusted = !settings.allowUntrusted()
shareDownloadedFiles = settings.shareDownloadedFiles shareDownloadedFiles = settings.shareDownloadedFiles
downloadLocation = settings.downloadLocation.getAbsolutePath() downloadLocation = settings.downloadLocation.getAbsolutePath()
@@ -47,6 +51,8 @@ class OptionsModel {
inboundQuantity = core.i2pOptions["inbound.quantity"] inboundQuantity = core.i2pOptions["inbound.quantity"]
outboundLength = core.i2pOptions["outbound.length"] outboundLength = core.i2pOptions["outbound.length"]
outboundQuantity = core.i2pOptions["outbound.quantity"] outboundQuantity = core.i2pOptions["outbound.quantity"]
i2pUDPPort = core.i2pOptions["i2np.udp.port"]
i2pNTCPPort = core.i2pOptions["i2np.ntcp.port"]
UISettings uiSettings = application.context.get("ui-settings") UISettings uiSettings = application.context.get("ui-settings")
showMonitor = uiSettings.showMonitor showMonitor = uiSettings.showMonitor

View File

@@ -0,0 +1,78 @@
package com.muwire.gui
import griffon.core.artifact.GriffonView
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import javax.swing.JDialog
import javax.swing.JPanel
import javax.swing.SwingConstants
import java.awt.BorderLayout
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent
import javax.annotation.Nonnull
@ArtifactProviderFor(GriffonView)
class I2PStatusView {
@MVCMember @Nonnull
FactoryBuilderSupport builder
@MVCMember @Nonnull
I2PStatusModel model
def mainFrame
def dialog
def panel
def buttonsPanel
void initUI() {
mainFrame = application.windowManager.findWindow("main-frame")
dialog = new JDialog(mainFrame, "I2P Status", true)
panel = builder.panel {
gridBagLayout()
label(text : "Network status", constraints : gbc(gridx:0, gridy:0))
label(text : bind {model.networkStatus}, constraints : gbc(gridx: 1, gridy:0))
label(text : "NTCP Connections", constraints : gbc(gridx:0, gridy:1))
label(text : bind {model.ntcpConnections}, constraints : gbc(gridx: 1, gridy:1))
label(text : "SSU Connections", constraints : gbc(gridx:0, gridy:2))
label(text : bind {model.ssuConnections}, constraints : gbc(gridx: 1, gridy:2))
label(text : "Participating Tunnels", constraints : gbc(gridx:0, gridy:3))
label(text : bind {model.participatingTunnels}, constraints : gbc(gridx: 1, gridy:3))
label(text : "Participating Bandwidth", constraints : gbc(gridx:0, gridy:4))
label(text : bind {model.participatingBW}, constraints : gbc(gridx: 1, gridy:4))
label(text : "Active Peers", constraints : gbc(gridx:0, gridy:5))
label(text : bind {model.activePeers}, constraints : gbc(gridx: 1, gridy:5))
label(text : "Receive Bps (15 seconds)", constraints : gbc(gridx:0, gridy:6))
label(text : bind {model.receiveBps}, constraints : gbc(gridx: 1, gridy:6))
label(text : "Send Bps (15 seconds)", constraints : gbc(gridx:0, gridy:7))
label(text : bind {model.sendBps}, constraints : gbc(gridx: 1, gridy:7))
}
buttonsPanel = builder.panel {
gridBagLayout()
button(text : "Refresh", constraints: gbc(gridx: 0, gridy: 0), refreshAction)
button(text : "Close", constraints : gbc(gridx : 1, gridy :0), closeAction)
}
}
void mvcGroupInit(Map<String,String> args) {
JPanel statusPanel = new JPanel()
statusPanel.setLayout(new BorderLayout())
statusPanel.add(panel, BorderLayout.CENTER)
statusPanel.add(buttonsPanel, BorderLayout.SOUTH)
dialog.getContentPane().add(statusPanel)
dialog.pack()
dialog.setLocationRelativeTo(mainFrame)
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)
dialog.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
mvcGroup.destroy()
}
})
dialog.show()
}
}

View File

@@ -22,6 +22,7 @@ import javax.swing.border.Border
import javax.swing.table.DefaultTableCellRenderer import javax.swing.table.DefaultTableCellRenderer
import com.muwire.core.Constants import com.muwire.core.Constants
import com.muwire.core.MuWireSettings
import com.muwire.core.download.Downloader import com.muwire.core.download.Downloader
import com.muwire.core.files.FileSharedEvent import com.muwire.core.files.FileSharedEvent
@@ -71,6 +72,11 @@ class MainFrameView {
menu (text : "Options") { menu (text : "Options") {
menuItem("Configuration", actionPerformed : {mvcGroup.createMVCGroup("Options")}) menuItem("Configuration", actionPerformed : {mvcGroup.createMVCGroup("Options")})
} }
menu (text : "Status") {
menuItem("MuWire", actionPerformed : {mvcGroup.createMVCGroup("mu-wire-status")})
MuWireSettings muSettings = application.context.get("muwire-settings")
menuItem("I2P", enabled : bind {model.routerPresent}, actionPerformed: {mvcGroup.createMVCGroup("i-2-p-status")})
}
} }
borderLayout() borderLayout()
panel (border: etchedBorder(), constraints : BorderLayout.NORTH) { panel (border: etchedBorder(), constraints : BorderLayout.NORTH) {

View File

@@ -0,0 +1,73 @@
package com.muwire.gui
import griffon.core.artifact.GriffonView
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import javax.swing.JDialog
import javax.swing.JPanel
import javax.swing.SwingConstants
import com.muwire.core.Core
import java.awt.BorderLayout
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent
import javax.annotation.Nonnull
@ArtifactProviderFor(GriffonView)
class MuWireStatusView {
@MVCMember @Nonnull
FactoryBuilderSupport builder
@MVCMember @Nonnull
MuWireStatusModel model
def mainFrame
def dialog
def panel
def buttonsPanel
void initUI() {
mainFrame = application.windowManager.findWindow("main-frame")
dialog = new JDialog(mainFrame, "MuWire Status", true)
panel = builder.panel {
gridBagLayout()
label(text : "Incoming connections", constraints : gbc(gridx:0, gridy:0))
label(text : bind {model.incomingConnections}, constraints : gbc(gridx:1, gridy:0))
label(text : "Outgoing connections", constraints : gbc(gridx:0, gridy:1))
label(text : bind {model.outgoingConnections}, constraints : gbc(gridx:1, gridy:1))
label(text : "Known hosts", constraints : gbc(gridx:0, gridy:2))
label(text : bind {model.knownHosts}, constraints : gbc(gridx:1, gridy:2))
label(text : "Shared files", constraints : gbc(gridx:0, gridy:3))
label(text : bind {model.sharedFiles}, constraints : gbc(gridx:1, gridy:3))
label(text : "Downloads", constraints : gbc(gridx:0, gridy:4))
label(text : bind {model.downloads}, constraints : gbc(gridx:1, gridy:4))
}
buttonsPanel = builder.panel {
gridBagLayout()
button(text : "Refresh", constraints: gbc(gridx: 0, gridy: 0), refreshAction)
button(text : "Close", constraints : gbc(gridx : 1, gridy :0), closeAction)
}
}
void mvcGroupInit(Map<String,String> args) {
JPanel statusPanel = new JPanel()
statusPanel.setLayout(new BorderLayout())
statusPanel.add(panel, BorderLayout.CENTER)
statusPanel.add(buttonsPanel, BorderLayout.SOUTH)
dialog.getContentPane().add(statusPanel)
dialog.pack()
dialog.setLocationRelativeTo(mainFrame)
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)
dialog.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
mvcGroup.destroy()
}
})
dialog.show()
}
}

View File

@@ -32,6 +32,7 @@ class OptionsView {
def retryField def retryField
def updateField def updateField
def autoDownloadUpdateCheckbox
def allowUntrustedCheckbox def allowUntrustedCheckbox
def shareDownloadedCheckbox def shareDownloadedCheckbox
@@ -39,6 +40,8 @@ class OptionsView {
def inboundQuantityField def inboundQuantityField
def outboundLengthField def outboundLengthField
def outboundQuantityField def outboundQuantityField
def i2pUDPPortField
def i2pNTCPPortField
def lnfField def lnfField
def monitorCheckbox def monitorCheckbox
@@ -70,15 +73,18 @@ class OptionsView {
updateField = textField(text : bind {model.updateCheckInterval }, columns : 2, constraints : gbc(gridx : 1, gridy: 1)) updateField = textField(text : bind {model.updateCheckInterval }, columns : 2, constraints : gbc(gridx : 1, gridy: 1))
label(text : "hours", constraints : gbc(gridx: 2, gridy : 1)) label(text : "hours", constraints : gbc(gridx: 2, gridy : 1))
label(text : "Allow only trusted connections", constraints : gbc(gridx: 0, gridy : 2)) label(text : "Download updates automatically", constraints: gbc(gridx :0, gridy : 2))
allowUntrustedCheckbox = checkBox(selected : bind {model.onlyTrusted}, constraints : gbc(gridx: 1, gridy : 2)) autoDownloadUpdateCheckbox = checkBox(selected : bind {model.autoDownloadUpdate}, constraints : gbc(gridx:1, gridy : 2))
label(text : "Share downloaded files", constraints : gbc(gridx : 0, gridy:3)) label(text : "Allow only trusted connections", constraints : gbc(gridx: 0, gridy : 3))
shareDownloadedCheckbox = checkBox(selected : bind {model.shareDownloadedFiles}, constraints : gbc(gridx :1, gridy:3)) allowUntrustedCheckbox = checkBox(selected : bind {model.onlyTrusted}, constraints : gbc(gridx: 1, gridy : 3))
label(text : "Save downloaded files to:", constraints: gbc(gridx:0, gridy:4)) label(text : "Share downloaded files", constraints : gbc(gridx : 0, gridy:4))
button(text : "Choose", constraints : gbc(gridx : 1, gridy:4), downloadLocationAction) shareDownloadedCheckbox = checkBox(selected : bind {model.shareDownloadedFiles}, constraints : gbc(gridx :1, gridy:4))
label(text : bind {model.downloadLocation}, constraints: gbc(gridx:0, gridy:5, gridwidth:2))
label(text : "Save downloaded files to:", constraints: gbc(gridx:0, gridy:5))
button(text : "Choose", constraints : gbc(gridx : 1, gridy:5), downloadLocationAction)
label(text : bind {model.downloadLocation}, constraints: gbc(gridx:0, gridy:6, gridwidth:2))
} }
i = builder.panel { i = builder.panel {
@@ -92,6 +98,15 @@ class OptionsView {
outboundLengthField = textField(text : bind {model.outboundLength}, columns : 2, constraints : gbc(gridx:1, gridy:3)) outboundLengthField = textField(text : bind {model.outboundLength}, columns : 2, constraints : gbc(gridx:1, gridy:3))
label(text : "Outbound Quantity", constraints : gbc(gridx:0, gridy:4)) label(text : "Outbound Quantity", constraints : gbc(gridx:0, gridy:4))
outboundQuantityField = textField(text : bind {model.outboundQuantity}, columns : 2, constraints : gbc(gridx:1, gridy:4)) outboundQuantityField = textField(text : bind {model.outboundQuantity}, columns : 2, constraints : gbc(gridx:1, gridy:4))
Core core = application.context.get("core")
if (core.router != null) {
label(text : "TCP Port", constraints : gbc(gridx :0, gridy: 5))
i2pNTCPPortField = textField(text : bind {model.i2pNTCPPort}, columns : 4, constraints : gbc(gridx:1, gridy:5))
label(text : "UDP Port", constraints : gbc(gridx :0, gridy: 6))
i2pUDPPortField = textField(text : bind {model.i2pUDPPort}, columns : 4, constraints : gbc(gridx:1, gridy:6))
}
} }
u = builder.panel { u = builder.panel {
gridBagLayout() gridBagLayout()

View File

@@ -0,0 +1,25 @@
package com.muwire.gui
import griffon.core.test.GriffonFestRule
import org.fest.swing.fixture.FrameFixture
import org.junit.Rule
import org.junit.Test
import static org.junit.Assert.fail
class I2PStatusIntegrationTest {
static {
System.setProperty('griffon.swing.edt.violations.check', 'true')
System.setProperty('griffon.swing.edt.hang.monitor', 'true')
}
@Rule
public final GriffonFestRule fest = new GriffonFestRule()
private FrameFixture window
@Test
void smokeTest() {
fail('Not implemented yet!')
}
}

View File

@@ -0,0 +1,25 @@
package com.muwire.gui
import griffon.core.test.GriffonFestRule
import org.fest.swing.fixture.FrameFixture
import org.junit.Rule
import org.junit.Test
import static org.junit.Assert.fail
class MuWireStatusIntegrationTest {
static {
System.setProperty('griffon.swing.edt.violations.check', 'true')
System.setProperty('griffon.swing.edt.hang.monitor', 'true')
}
@Rule
public final GriffonFestRule fest = new GriffonFestRule()
private FrameFixture window
@Test
void smokeTest() {
fail('Not implemented yet!')
}
}

View File

@@ -0,0 +1,21 @@
package com.muwire.gui
import griffon.core.test.GriffonUnitRule
import griffon.core.test.TestFor
import org.junit.Rule
import org.junit.Test
import static org.junit.Assert.fail
@TestFor(I2PStatusController)
class I2PStatusControllerTest {
private I2PStatusController controller
@Rule
public final GriffonUnitRule griffon = new GriffonUnitRule()
@Test
void smokeTest() {
fail('Not yet implemented!')
}
}

View File

@@ -0,0 +1,21 @@
package com.muwire.gui
import griffon.core.test.GriffonUnitRule
import griffon.core.test.TestFor
import org.junit.Rule
import org.junit.Test
import static org.junit.Assert.fail
@TestFor(MuWireStatusController)
class MuWireStatusControllerTest {
private MuWireStatusController controller
@Rule
public final GriffonUnitRule griffon = new GriffonUnitRule()
@Test
void smokeTest() {
fail('Not yet implemented!')
}
}