backend for checking updates
This commit is contained in:
@@ -32,6 +32,7 @@ import com.muwire.core.search.SearchEvent
|
|||||||
import com.muwire.core.search.SearchManager
|
import com.muwire.core.search.SearchManager
|
||||||
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.upload.UploadManager
|
import com.muwire.core.upload.UploadManager
|
||||||
import com.muwire.core.util.MuWireLogManager
|
import com.muwire.core.util.MuWireLogManager
|
||||||
|
|
||||||
@@ -61,11 +62,12 @@ public class Core {
|
|||||||
private final HostCache hostCache
|
private final HostCache hostCache
|
||||||
private final ConnectionManager connectionManager
|
private final ConnectionManager connectionManager
|
||||||
private final CacheClient cacheClient
|
private final CacheClient cacheClient
|
||||||
|
private final UpdateClient updateClient
|
||||||
private final ConnectionAcceptor connectionAcceptor
|
private final ConnectionAcceptor connectionAcceptor
|
||||||
private final ConnectionEstablisher connectionEstablisher
|
private final ConnectionEstablisher connectionEstablisher
|
||||||
private final HasherService hasherService
|
private final HasherService hasherService
|
||||||
|
|
||||||
public Core(MuWireSettings props, File home) {
|
public Core(MuWireSettings props, File home, String myVersion) {
|
||||||
this.home = home
|
this.home = home
|
||||||
log.info "Initializing I2P context"
|
log.info "Initializing I2P context"
|
||||||
I2PAppContext.getGlobalContext().logManager()
|
I2PAppContext.getGlobalContext().logManager()
|
||||||
@@ -154,6 +156,9 @@ public class Core {
|
|||||||
log.info("initializing cache client")
|
log.info("initializing cache client")
|
||||||
cacheClient = new CacheClient(eventBus,hostCache, connectionManager, i2pSession, props, 10000)
|
cacheClient = new CacheClient(eventBus,hostCache, connectionManager, i2pSession, props, 10000)
|
||||||
|
|
||||||
|
log.info("initializing update client")
|
||||||
|
updateClient = new UpdateClient(eventBus, i2pSession, myVersion, props)
|
||||||
|
|
||||||
log.info("initializing connector")
|
log.info("initializing connector")
|
||||||
I2PConnector i2pConnector = new I2PConnector(socketManager)
|
I2PConnector i2pConnector = new I2PConnector(socketManager)
|
||||||
|
|
||||||
@@ -197,6 +202,7 @@ public class Core {
|
|||||||
connectionAcceptor.start()
|
connectionAcceptor.start()
|
||||||
connectionEstablisher.start()
|
connectionEstablisher.start()
|
||||||
hostCache.waitForLoad()
|
hostCache.waitForLoad()
|
||||||
|
updateClient.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
@@ -227,7 +233,7 @@ public class Core {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Core core = new Core(props, home)
|
Core core = new Core(props, home, "0.0.6")
|
||||||
core.startServices()
|
core.startServices()
|
||||||
|
|
||||||
// ... at the end, sleep or execute script
|
// ... at the end, sleep or execute script
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class MuWireSettings {
|
|||||||
final boolean isLeaf
|
final boolean isLeaf
|
||||||
boolean allowUntrusted
|
boolean allowUntrusted
|
||||||
int downloadRetryInterval
|
int downloadRetryInterval
|
||||||
|
int updateCheckInterval
|
||||||
String nickname
|
String nickname
|
||||||
File downloadLocation
|
File downloadLocation
|
||||||
String sharedFiles
|
String sharedFiles
|
||||||
@@ -25,6 +26,7 @@ class MuWireSettings {
|
|||||||
System.getProperty("user.home")))
|
System.getProperty("user.home")))
|
||||||
sharedFiles = props.getProperty("sharedFiles")
|
sharedFiles = props.getProperty("sharedFiles")
|
||||||
downloadRetryInterval = Integer.parseInt(props.getProperty("downloadRetryInterval","15"))
|
downloadRetryInterval = Integer.parseInt(props.getProperty("downloadRetryInterval","15"))
|
||||||
|
updateCheckInterval = Integer.parseInt(props.getProperty("updateCheckInterval","36"))
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(OutputStream out) throws IOException {
|
void write(OutputStream out) throws IOException {
|
||||||
@@ -35,6 +37,7 @@ class MuWireSettings {
|
|||||||
props.setProperty("nickname", nickname)
|
props.setProperty("nickname", nickname)
|
||||||
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))
|
||||||
if (sharedFiles != null)
|
if (sharedFiles != null)
|
||||||
props.setProperty("sharedFiles", sharedFiles)
|
props.setProperty("sharedFiles", sharedFiles)
|
||||||
props.store(out, "")
|
props.store(out, "")
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class CacheClient {
|
|||||||
options.setSendLeaseSet(true)
|
options.setSendLeaseSet(true)
|
||||||
CacheServers.getCacheServers().each {
|
CacheServers.getCacheServers().each {
|
||||||
log.info "Querying hostcache ${it.toBase32()}"
|
log.info "Querying hostcache ${it.toBase32()}"
|
||||||
session.sendMessage(it, ping, 0, ping.length, I2PSession.PROTO_DATAGRAM, 0, 0, options)
|
session.sendMessage(it, ping, 0, ping.length, I2PSession.PROTO_DATAGRAM, 1, 0, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.muwire.core.update
|
||||||
|
|
||||||
|
import com.muwire.core.Event
|
||||||
|
|
||||||
|
class UpdateAvailableEvent extends Event {
|
||||||
|
String version
|
||||||
|
String signer
|
||||||
|
}
|
||||||
132
core/src/main/groovy/com/muwire/core/update/UpdateClient.groovy
Normal file
132
core/src/main/groovy/com/muwire/core/update/UpdateClient.groovy
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
package com.muwire.core.update
|
||||||
|
|
||||||
|
import java.util.logging.Level
|
||||||
|
|
||||||
|
import com.muwire.core.EventBus
|
||||||
|
import com.muwire.core.MuWireSettings
|
||||||
|
|
||||||
|
import groovy.json.JsonOutput
|
||||||
|
import groovy.json.JsonSlurper
|
||||||
|
import groovy.util.logging.Log
|
||||||
|
import net.i2p.client.I2PSession
|
||||||
|
import net.i2p.client.I2PSessionMuxedListener
|
||||||
|
import net.i2p.client.SendMessageOptions
|
||||||
|
import net.i2p.client.datagram.I2PDatagramDissector
|
||||||
|
import net.i2p.client.datagram.I2PDatagramMaker
|
||||||
|
import net.i2p.util.VersionComparator
|
||||||
|
|
||||||
|
@Log
|
||||||
|
class UpdateClient {
|
||||||
|
final EventBus eventBus
|
||||||
|
final I2PSession session
|
||||||
|
final String myVersion
|
||||||
|
final MuWireSettings settings
|
||||||
|
|
||||||
|
private final Timer timer
|
||||||
|
|
||||||
|
private long lastUpdateCheckTime
|
||||||
|
|
||||||
|
UpdateClient(EventBus eventBus, I2PSession session, String myVersion, MuWireSettings settings) {
|
||||||
|
this.eventBus = eventBus
|
||||||
|
this.session = session
|
||||||
|
this.myVersion = myVersion
|
||||||
|
this.settings = settings
|
||||||
|
timer = new Timer("update-client",true)
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
session.addMuxedSessionListener(new Listener(), I2PSession.PROTO_DATAGRAM, 2)
|
||||||
|
timer.schedule({checkUpdate()} as TimerTask, 30000, 60 * 60 * 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
timer.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkUpdate() {
|
||||||
|
final long now = System.currentTimeMillis()
|
||||||
|
if (lastUpdateCheckTime > 0) {
|
||||||
|
if (now - lastUpdateCheckTime < settings.updateCheckInterval * 60 * 60 * 1000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastUpdateCheckTime = now
|
||||||
|
|
||||||
|
log.info("checking for update")
|
||||||
|
|
||||||
|
def ping = [version : 1, myVersion : myVersion]
|
||||||
|
ping = JsonOutput.toJson(ping)
|
||||||
|
def maker = new I2PDatagramMaker(session)
|
||||||
|
ping = maker.makeI2PDatagram(ping.bytes)
|
||||||
|
def options = new SendMessageOptions()
|
||||||
|
options.setSendLeaseSet(true)
|
||||||
|
session.sendMessage(UpdateServers.UPDATE_SERVER, ping, 0, ping.length, I2PSession.PROTO_DATAGRAM, 2, 0, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Listener implements I2PSessionMuxedListener {
|
||||||
|
|
||||||
|
final JsonSlurper slurper = new JsonSlurper()
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void messageAvailable(I2PSession session, int msgId, long size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void messageAvailable(I2PSession session, int msgId, long size, int proto, int fromport, int toport) {
|
||||||
|
if (proto != I2PSession.PROTO_DATAGRAM) {
|
||||||
|
log.warning "Received unexpected protocol $proto"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
def payload = session.receiveMessage(msgId)
|
||||||
|
def dissector = new I2PDatagramDissector()
|
||||||
|
try {
|
||||||
|
dissector.loadI2PDatagram(payload)
|
||||||
|
def sender = dissector.getSender()
|
||||||
|
if (sender != UpdateServers.UPDATE_SERVER) {
|
||||||
|
log.warning("received something not from update server " + sender.toBase32())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Received something from update server")
|
||||||
|
|
||||||
|
payload = dissector.getPayload()
|
||||||
|
payload = slurper.parse(payload)
|
||||||
|
|
||||||
|
if (payload.version == null) {
|
||||||
|
log.warning("version missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.signer == null) {
|
||||||
|
log.warning("signer missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VersionComparator.comp(myVersion, payload.version) >= 0) {
|
||||||
|
log.info("no new version available")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("new version $payload.version available, publishing event")
|
||||||
|
eventBus.publish(new UpdateAvailableEvent(version : payload.version, signer : payload.signer))
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.log(Level.WARNING,"Invalid datagram",e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reportAbuse(I2PSession session, int severity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnected(I2PSession session) {
|
||||||
|
log.severe("I2P session disconnected")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void errorOccurred(I2PSession session, String message, Throwable error) {
|
||||||
|
log.log(Level.SEVERE, message, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.muwire.core.update
|
||||||
|
|
||||||
|
import net.i2p.data.Destination
|
||||||
|
|
||||||
|
class UpdateServers {
|
||||||
|
static final Destination UPDATE_SERVER = new Destination("pSWieSRB3czCl3Zz4WpKp4Z8tjv-05zbogRDS7SEnKcSdWOupVwjzQ92GsgQh1VqgoSRk1F8dpZOnHxxz5HFy9D7ri0uFdkMyXdSKoB7IgkkvCfTAyEmeaPwSYnurF3Zk7u286E7YG2rZkQZgJ77tow7ZS0mxFB7Z0Ti-VkZ9~GeGePW~howwNm4iSQACZA0DyTpI8iv5j4I0itPCQRgaGziob~Vfvjk49nd8N4jtaDGo9cEcafikVzQ2OgBgYWL6LRbrrItwuGqsDvITUHWaElUYIDhRQYUq8gYiUA6rwAJputfhFU0J7lIxFR9vVY7YzRvcFckfr0DNI4VQVVlPnRPkUxQa--BlldMaCIppWugjgKLwqiSiHywKpSMlBWgY2z1ry4ueEBo1WEP-mEf88wRk4cFQBCKtctCQnIG2GsnATqTl-VGUAsuzeNWZiFSwXiTy~gQ094yWx-K06fFZUDt4CMiLZVhGlixiInD~34FCRC9LVMtFcqiFB2M-Ql2AAAA")
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import griffon.core.GriffonApplication
|
import griffon.core.GriffonApplication
|
||||||
|
import griffon.core.env.Metadata
|
||||||
import groovy.util.logging.Log
|
import groovy.util.logging.Log
|
||||||
|
|
||||||
import org.codehaus.griffon.runtime.core.AbstractLifecycleHandler
|
import org.codehaus.griffon.runtime.core.AbstractLifecycleHandler
|
||||||
@@ -20,6 +21,9 @@ import java.util.logging.Level
|
|||||||
|
|
||||||
@Log
|
@Log
|
||||||
class Ready extends AbstractLifecycleHandler {
|
class Ready extends AbstractLifecycleHandler {
|
||||||
|
|
||||||
|
@Inject Metadata metadata
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Ready(@Nonnull GriffonApplication application) {
|
Ready(@Nonnull GriffonApplication application) {
|
||||||
super(application)
|
super(application)
|
||||||
@@ -90,9 +94,10 @@ class Ready extends AbstractLifecycleHandler {
|
|||||||
props.write(it)
|
props.write(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Core core
|
Core core
|
||||||
try {
|
try {
|
||||||
core = new Core(props, home)
|
core = new Core(props, home, metadata["application.version"])
|
||||||
} catch (Exception bad) {
|
} catch (Exception bad) {
|
||||||
log.log(Level.SEVERE,"couldn't initialize core",bad)
|
log.log(Level.SEVERE,"couldn't initialize core",bad)
|
||||||
JOptionPane.showMessageDialog(null, "Couldn't connect to I2P router. Make sure I2P is running and restart MuWire",
|
JOptionPane.showMessageDialog(null, "Couldn't connect to I2P router. Make sure I2P is running and restart MuWire",
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class UpdateServer {
|
|||||||
// I don't think we care about the payload at this point
|
// I don't think we care about the payload at this point
|
||||||
def maker = new I2PDatagramMaker(session)
|
def maker = new I2PDatagramMaker(session)
|
||||||
def response = maker.makeI2PDatagram(json.bytes)
|
def response = maker.makeI2PDatagram(json.bytes)
|
||||||
session.sendMessage(sender, response, I2PSession.PROTO_DATAGRAM, 0, 0)
|
session.sendMessage(sender, response, I2PSession.PROTO_DATAGRAM, 0, 2)
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.log(Level.WARNING, "exception responding to update request",e)
|
log.log(Level.WARNING, "exception responding to update request",e)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user