mirror of https://github.com/zlatinb/muwire
parsing of headers
parent
6d3d2d94dc
commit
822e07c243
|
@ -56,7 +56,6 @@ class FileManager {
|
|||
void onFileUnsharedEvent(FileUnsharedEvent e) {
|
||||
SharedFile sf = e.unsharedFile
|
||||
byte [] root = sf.getInfoHash().getRoot()
|
||||
Set<SharedFile> existing
|
||||
Set<SharedFile> existing = rootToFiles.get(root)
|
||||
if (existing != null) {
|
||||
existing.remove(sf)
|
||||
|
|
|
@ -1,16 +1,90 @@
|
|||
package com.muwire.core.upload
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import com.muwire.core.InfoHash
|
||||
|
||||
import groovy.util.logging.Log
|
||||
import net.i2p.data.Base64
|
||||
|
||||
@Log
|
||||
class Request {
|
||||
|
||||
private static final byte R = "\r".getBytes(StandardCharsets.US_ASCII)[0]
|
||||
private static final byte N = "\n".getBytes(StandardCharsets.US_ASCII)[0]
|
||||
|
||||
InfoHash infoHash
|
||||
Range range
|
||||
Map<String, String> headers
|
||||
|
||||
static Range parse(InfoHash infoHash, InputStream is) throws IOException {
|
||||
static Request parse(InfoHash infoHash, InputStream is) throws IOException {
|
||||
Map<String,String> headers = new HashMap<>()
|
||||
byte [] tmp = new byte[0x1 << 14]
|
||||
while(true) {
|
||||
boolean r = false
|
||||
boolean n = false
|
||||
int idx = 0
|
||||
while (true) {
|
||||
byte read = is.read()
|
||||
if (read == -1)
|
||||
throw new IOException("Stream closed")
|
||||
|
||||
if (!r && read == N)
|
||||
throw new IOException("Received N before R")
|
||||
if (read == R) {
|
||||
if (r)
|
||||
throw new IOException("double R")
|
||||
r = true
|
||||
continue
|
||||
}
|
||||
|
||||
if (r && !n) {
|
||||
if (read != N)
|
||||
throw new IOException("R not followed by N")
|
||||
n = true
|
||||
break
|
||||
}
|
||||
if (idx == 0x1 << 14)
|
||||
throw new IOException("Header too long")
|
||||
tmp[idx++] = read
|
||||
}
|
||||
|
||||
if (idx == 0)
|
||||
break
|
||||
|
||||
String header = new String(tmp, 0, idx, StandardCharsets.US_ASCII)
|
||||
log.fine("Read header $header")
|
||||
|
||||
int keyIdx = header.indexOf(":")
|
||||
if (keyIdx < 1)
|
||||
throw new IOException("Header key not found")
|
||||
if (keyIdx == header.length())
|
||||
throw new IOException("Header value not found")
|
||||
String key = header.substring(0, keyIdx)
|
||||
String value = header.substring(keyIdx + 1)
|
||||
headers.put(key, value)
|
||||
}
|
||||
|
||||
if (!headers.containsKey("Range"))
|
||||
throw new IOException("Range header not found")
|
||||
|
||||
String range = headers.get("Range").trim()
|
||||
String[] split = range.split("-")
|
||||
if (split.length != 2)
|
||||
throw new IOException("Invalid range header $range")
|
||||
long start
|
||||
long end
|
||||
try {
|
||||
start = Long.parseLong(split[0])
|
||||
end = Long.parseLong(split[1])
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new IOException(nfe)
|
||||
}
|
||||
|
||||
if (start < 0 || end < start)
|
||||
throw new IOException("Invalid range $start - $end")
|
||||
|
||||
new Request( infoHash : infoHash, range : new Range(start, end), headers : headers)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,8 +48,11 @@ public class UploadManager {
|
|||
Request request = Request.parse(new InfoHash(infoHashRoot), e.getInputStream())
|
||||
Uploader uploader = new Uploader(request, e)
|
||||
eventBus.publish(new UploadEvent(uploader))
|
||||
uploader.respond()
|
||||
eventBus.publish(new UploadFinishedEvent(uploader))
|
||||
try {
|
||||
uploader.respond()
|
||||
} finally {
|
||||
eventBus.publish(new UploadFinishedEvent(uploader))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
package com.muwire.core.upload
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
import com.muwire.core.InfoHash
|
||||
|
||||
class RequestParsingTest {
|
||||
|
||||
Request 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)
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
assert false
|
||||
} catch (IOException expected) {}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
request = null
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessful() {
|
||||
fromString("Range: 1-2\r\n\r\n")
|
||||
assert request != null
|
||||
assert request.getRange().start == 1
|
||||
assert request.getRange().end == 2
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRNMissing() {
|
||||
failed("Range: 1-2")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRNMissing2() {
|
||||
failed("Range: 1-2\r\n")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRR() {
|
||||
failed("Range: 1-2\r\r")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNR() {
|
||||
failed("Range: 1-2\n\r")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testR() {
|
||||
failed("Range: 1-2\r")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRX() {
|
||||
failed("Range: 1-2\rx")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoHeaders() {
|
||||
fromString("Range: 1-2\r\nA:B\r\n\r\n")
|
||||
assert request != null
|
||||
assert request.getRange().start == 1
|
||||
assert request.getRange().end == 2
|
||||
assert request.getHeaders().size() == 2
|
||||
assert request.getHeaders().get("Range").trim() == "1-2"
|
||||
assert request.getHeaders().get("A").trim() == "B"
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRangeMissing() {
|
||||
failed("A:B\r\n")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoHeaders() {
|
||||
failed("\r\n")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidRange() {
|
||||
failed("Range 1-2\r\n\r\n")
|
||||
failed("Range:\r\n\r\n")
|
||||
failed("Range: -1-2\r\n\r\n")
|
||||
failed("Range: 1-x\r\n\r\n")
|
||||
failed("Range: x")
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeaderTooLong() {
|
||||
StringBuilder sb = new StringBuilder()
|
||||
for (int i = 0; i < (0x1 << 14) + 1; i++)
|
||||
sb.append("x")
|
||||
failed(sb.toString())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue