Compare commits

..

13 Commits

Author SHA1 Message Date
Zlatin Balevsky
7bb5e5b632 Release 0.3.4 2019-06-20 21:07:50 +01:00
Zlatin Balevsky
b2e43f9765 update split pattern and add unit test 2019-06-20 21:06:39 +01:00
Zlatin Balevsky
2aa73c203a Release 0.3.3 2019-06-20 18:08:02 +01:00
Zlatin Balevsky
18d2b56563 fix indexing 2019-06-20 17:57:36 +01:00
Zlatin Balevsky
a455b4ad6e redirect exceptions in result sender to log 2019-06-20 17:22:59 +01:00
Zlatin Balevsky
761b683a81 Release 0.3.2 2019-06-20 16:04:46 +01:00
Zlatin Balevsky
1d41bcd825 prevent empty tokens in search index 2019-06-20 16:02:48 +01:00
Zlatin Balevsky
f1ac038b55 update split pattern 2019-06-20 15:47:00 +01:00
Zlatin Balevsky
396c636e42 prevent empty search terms 2019-06-20 15:29:27 +01:00
Zlatin Balevsky
e32c858e90 update README with quick FAQ 2019-06-20 14:18:37 +01:00
Zlatin Balevsky
821555f3f1 Release 0.3.1 2019-06-20 14:02:22 +01:00
Zlatin Balevsky
089ab4f0d9 do not retry downloads if core is shut(ting) down 2019-06-20 13:40:04 +01:00
Zlatin Balevsky
948b6292fe add shutdown hook to shutdown core on SIGTERM 2019-06-20 13:29:15 +01:00
12 changed files with 92 additions and 47 deletions

View File

@@ -31,3 +31,19 @@ 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
### Quick FAQ
* why is MuWire slow ?
- too few sources you're downloading from
- you can increse the number of tunnels by using more tunnels via Options->I2P Inbound/Outbound Quantity
the default is 4 and you could raise it and even can go up as high as 16 ( Caution !!!!)
* my search is not returning (enough) results !
- search is keyword or hash based
- keywords and hash(es) are NOT regexed or wildcarded so they have to be complete
so searching for 'musi' will not return results with 'music' - you have to search for 'music'
- ALL keywords have to match
- only use <SPACE> for keyword separation

View File

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

View File

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

View File

@@ -11,5 +11,5 @@ class Constants {
public static final float DOWNLOAD_SEQUENTIAL_RATIO = 0.8f public static final float DOWNLOAD_SEQUENTIAL_RATIO = 0.8f
public static final String SPLIT_PATTERN = "[\\.,_-]" public static final String SPLIT_PATTERN = "[\\+\\-,\\.:;\\(\\)=_/\\\\\\!\\\"\\\'\\\$%\\|]"
} }

View File

@@ -1,6 +1,7 @@
package com.muwire.core package com.muwire.core
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.util.concurrent.atomic.AtomicBoolean
import com.muwire.core.connection.ConnectionAcceptor import com.muwire.core.connection.ConnectionAcceptor
import com.muwire.core.connection.ConnectionEstablisher import com.muwire.core.connection.ConnectionEstablisher
@@ -74,6 +75,8 @@ public class Core {
private final DirectoryWatcher directoryWatcher private final DirectoryWatcher directoryWatcher
final FileManager fileManager final FileManager fileManager
final AtomicBoolean shutdown = new AtomicBoolean()
public Core(MuWireSettings props, File home, String myVersion) { public Core(MuWireSettings props, File home, String myVersion) {
this.home = home this.home = home
this.muOptions = props this.muOptions = props
@@ -241,6 +244,10 @@ public class Core {
} }
public void shutdown() { public void shutdown() {
if (!shutdown.compareAndSet(false, true)) {
log.info("already shutting down")
return
}
log.info("shutting down download manageer") log.info("shutting down download manageer")
downloadManager.shutdown() downloadManager.shutdown()
log.info("shutting down connection acceeptor") log.info("shutting down connection acceeptor")
@@ -277,7 +284,7 @@ public class Core {
} }
} }
Core core = new Core(props, home, "0.3.0") Core core = new Core(props, home, "0.3.4")
core.startServices() core.startServices()
// ... at the end, sleep or execute script // ... at the end, sleep or execute script

View File

@@ -11,6 +11,7 @@ import java.util.concurrent.Executor
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.ThreadFactory import java.util.concurrent.ThreadFactory
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import java.util.logging.Level
import java.util.stream.Collectors import java.util.stream.Collectors
import com.muwire.core.DownloadedFile import com.muwire.core.DownloadedFile
@@ -83,50 +84,54 @@ class ResultsSender {
@Override @Override
public void run() { public void run() {
byte [] tmp = new byte[InfoHash.SIZE]
JsonOutput jsonOutput = new JsonOutput()
Endpoint endpoint = null;
try { try {
endpoint = connector.connect(target) byte [] tmp = new byte[InfoHash.SIZE]
DataOutputStream os = new DataOutputStream(endpoint.getOutputStream()) JsonOutput jsonOutput = new JsonOutput()
os.write("POST $uuid\r\n\r\n".getBytes(StandardCharsets.US_ASCII)) Endpoint endpoint = null;
me.write(os) try {
os.writeShort((short)results.length) endpoint = connector.connect(target)
results.each { DataOutputStream os = new DataOutputStream(endpoint.getOutputStream())
byte [] name = it.getFile().getName().getBytes(StandardCharsets.UTF_8) os.write("POST $uuid\r\n\r\n".getBytes(StandardCharsets.US_ASCII))
def baos = new ByteArrayOutputStream() me.write(os)
def daos = new DataOutputStream(baos) os.writeShort((short)results.length)
daos.writeShort((short) name.length) results.each {
daos.write(name) byte [] name = it.getFile().getName().getBytes(StandardCharsets.UTF_8)
daos.flush() def baos = new ByteArrayOutputStream()
String encodedName = Base64.encode(baos.toByteArray()) def daos = new DataOutputStream(baos)
def obj = [:] daos.writeShort((short) name.length)
obj.type = "Result" daos.write(name)
obj.version = oobInfohash ? 2 : 1 daos.flush()
obj.name = encodedName String encodedName = Base64.encode(baos.toByteArray())
obj.infohash = Base64.encode(it.getInfoHash().getRoot()) def obj = [:]
obj.size = it.getFile().length() obj.type = "Result"
obj.pieceSize = it.getPieceSize() obj.version = oobInfohash ? 2 : 1
if (!oobInfohash) { obj.name = encodedName
byte [] hashList = it.getInfoHash().getHashList() obj.infohash = Base64.encode(it.getInfoHash().getRoot())
def hashListB64 = [] obj.size = it.getFile().length()
for (int i = 0; i < hashList.length / InfoHash.SIZE; i++) { obj.pieceSize = it.getPieceSize()
System.arraycopy(hashList, InfoHash.SIZE * i, tmp, 0, InfoHash.SIZE) if (!oobInfohash) {
hashListB64 << Base64.encode(tmp) byte [] hashList = it.getInfoHash().getHashList()
def hashListB64 = []
for (int i = 0; i < hashList.length / InfoHash.SIZE; i++) {
System.arraycopy(hashList, InfoHash.SIZE * i, tmp, 0, InfoHash.SIZE)
hashListB64 << Base64.encode(tmp)
}
obj.hashList = hashListB64
} }
obj.hashList = hashListB64
if (it instanceof DownloadedFile)
obj.sources = it.sources.stream().map({dest -> dest.toBase64()}).collect(Collectors.toSet())
def json = jsonOutput.toJson(obj)
os.writeShort((short)json.length())
os.write(json.getBytes(StandardCharsets.US_ASCII))
} }
os.flush()
if (it instanceof DownloadedFile) } finally {
obj.sources = it.sources.stream().map({dest -> dest.toBase64()}).collect(Collectors.toSet()) endpoint?.close()
def json = jsonOutput.toJson(obj)
os.writeShort((short)json.length())
os.write(json.getBytes(StandardCharsets.US_ASCII))
} }
os.flush() } catch (Exception e) {
} finally { log.log(Level.WARNING, "problem sending results",e)
endpoint?.close()
} }
} }
} }

View File

@@ -33,7 +33,10 @@ class SearchIndex {
private static String[] split(String source) { private static String[] split(String source) {
source = source.replaceAll(Constants.SPLIT_PATTERN, " ").toLowerCase() source = source.replaceAll(Constants.SPLIT_PATTERN, " ").toLowerCase()
source.split(" ") String [] split = source.split(" ")
def rv = []
split.each { if (it.length() > 0) rv << it }
rv.toArray(new String[0])
} }
String[] search(List<String> terms) { String[] search(List<String> terms) {

View File

@@ -83,4 +83,11 @@ class SearchIndexTest {
assert found.size() == 1 assert found.size() == 1
assert found.contains("b c.d") assert found.contains("b c.d")
} }
@Test
void testDuplicateTerm() {
initIndex(["MuWire-0.3.3.jar"])
def found = index.search(["muwire", "0", "3", "jar"])
assert found.size() == 1
}
} }

View File

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

View File

@@ -67,7 +67,9 @@ class MainFrameController {
// this can be improved a lot // this can be improved a lot
def replaced = search.toLowerCase().trim().replaceAll(Constants.SPLIT_PATTERN, " ") def replaced = search.toLowerCase().trim().replaceAll(Constants.SPLIT_PATTERN, " ")
def terms = replaced.split(" ") def terms = replaced.split(" ")
searchEvent = new SearchEvent(searchTerms : terms, uuid : uuid, oobInfohash: true) def nonEmpty = []
terms.each { if (it.length() > 0) nonEmpty << it }
searchEvent = new SearchEvent(searchTerms : nonEmpty, uuid : uuid, oobInfohash: true)
} }
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : true, core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : true,
replyTo: core.me.destination, receivedOn: core.me.destination, replyTo: core.me.destination, receivedOn: core.me.destination,

View File

@@ -98,6 +98,9 @@ class Ready extends AbstractLifecycleHandler {
"Can't connect to I2P router", JOptionPane.WARNING_MESSAGE) "Can't connect to I2P router", JOptionPane.WARNING_MESSAGE)
System.exit(0) System.exit(0)
} }
Runtime.getRuntime().addShutdownHook({
core.shutdown()
})
core.startServices() core.startServices()
application.context.put("muwire-settings", props) application.context.put("muwire-settings", props)
application.context.put("core",core) application.context.put("core",core)

View File

@@ -137,6 +137,8 @@ class MainFrameModel {
core.eventBus.register(FileUnsharedEvent.class, this) core.eventBus.register(FileUnsharedEvent.class, this)
timer.schedule({ timer.schedule({
if (core.shutdown.get())
return
int retryInterval = core.muOptions.downloadRetryInterval int retryInterval = core.muOptions.downloadRetryInterval
if (retryInterval > 0) { if (retryInterval > 0) {
retryInterval *= 60000 retryInterval *= 60000