2014-03-19 10:06:40 +01:00
|
|
|
package se.vidstige.jadb;
|
|
|
|
|
|
|
|
import java.io.*;
|
2018-08-06 12:51:24 +02:00
|
|
|
import java.nio.charset.StandardCharsets;
|
2014-03-19 10:06:40 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Created by vidstige on 2014-03-19.
|
|
|
|
*/
|
2014-03-25 15:46:54 +01:00
|
|
|
public class SyncTransport {
|
2014-03-19 10:06:40 +01:00
|
|
|
|
2014-03-25 15:46:54 +01:00
|
|
|
private final DataOutput output;
|
|
|
|
private final DataInput input;
|
2014-03-19 10:06:40 +01:00
|
|
|
|
2014-03-25 15:46:54 +01:00
|
|
|
public SyncTransport(DataOutput outputStream, DataInput inputStream) {
|
|
|
|
output = outputStream;
|
|
|
|
input = inputStream;
|
|
|
|
}
|
2016-03-20 09:13:30 +01:00
|
|
|
|
2014-03-19 10:06:40 +01:00
|
|
|
public void send(String syncCommand, String name) throws IOException {
|
|
|
|
if (syncCommand.length() != 4) throw new IllegalArgumentException("sync commands must have length 4");
|
|
|
|
output.writeBytes(syncCommand);
|
2018-12-25 07:12:51 +01:00
|
|
|
byte[] data = name.getBytes(StandardCharsets.UTF_8);
|
2018-12-09 01:04:18 +01:00
|
|
|
output.writeInt(Integer.reverseBytes(data.length));
|
|
|
|
output.write(data);
|
2014-03-19 10:06:40 +01:00
|
|
|
}
|
|
|
|
|
2014-03-19 21:15:40 +01:00
|
|
|
public void sendStatus(String statusCode, int length) throws IOException {
|
|
|
|
output.writeBytes(statusCode);
|
|
|
|
output.writeInt(Integer.reverseBytes(length));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void verifyStatus() throws IOException, JadbException {
|
|
|
|
String status = readString(4);
|
|
|
|
int length = readInt();
|
2016-03-20 09:13:30 +01:00
|
|
|
if ("FAIL".equals(status)) {
|
2014-03-19 21:15:40 +01:00
|
|
|
String error = readString(length);
|
|
|
|
throw new JadbException(error);
|
|
|
|
}
|
2016-03-20 09:13:30 +01:00
|
|
|
if (!"OKAY".equals(status)) {
|
2014-03-19 21:15:40 +01:00
|
|
|
throw new JadbException("Unknown error: " + status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-11 20:15:06 +02:00
|
|
|
private int readInt() throws IOException {
|
2014-03-19 10:06:40 +01:00
|
|
|
return Integer.reverseBytes(input.readInt());
|
|
|
|
}
|
|
|
|
|
2018-09-11 20:15:06 +02:00
|
|
|
private String readString(int length) throws IOException {
|
2014-03-19 10:06:40 +01:00
|
|
|
byte[] buffer = new byte[length];
|
2014-03-19 17:36:53 +01:00
|
|
|
input.readFully(buffer);
|
2018-08-06 12:51:24 +02:00
|
|
|
return new String(buffer, StandardCharsets.UTF_8);
|
2014-03-19 10:06:40 +01:00
|
|
|
}
|
|
|
|
|
2018-12-25 07:12:51 +01:00
|
|
|
public void sendDirectoryEntry(RemoteFile file) throws IOException {
|
|
|
|
output.writeBytes("DENT");
|
|
|
|
output.writeInt(Integer.reverseBytes(0666 | (file.isDirectory() ? (1 << 14) : 0)));
|
|
|
|
output.writeInt(Integer.reverseBytes(file.getSize()));
|
2019-02-19 15:28:13 +01:00
|
|
|
output.writeInt(Integer.reverseBytes(file.getLastModified()));
|
2018-12-25 07:12:51 +01:00
|
|
|
byte[] pathChars = file.getPath().getBytes(StandardCharsets.UTF_8);
|
|
|
|
output.writeInt(Integer.reverseBytes(pathChars.length));
|
|
|
|
output.write(pathChars);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void sendDirectoryEntryDone() throws IOException {
|
|
|
|
output.writeBytes("DONE");
|
|
|
|
output.writeBytes("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); // equivalent to the length of a "normal" dent
|
|
|
|
}
|
|
|
|
|
2014-03-20 11:33:03 +01:00
|
|
|
public RemoteFileRecord readDirectoryEntry() throws IOException {
|
2014-03-19 10:06:40 +01:00
|
|
|
String id = readString(4);
|
|
|
|
int mode = readInt();
|
|
|
|
int size = readInt();
|
|
|
|
int time = readInt();
|
2014-03-19 17:36:53 +01:00
|
|
|
int nameLength = readInt();
|
|
|
|
String name = readString(nameLength);
|
2014-03-19 10:06:40 +01:00
|
|
|
|
2014-03-20 11:33:03 +01:00
|
|
|
if (!"DENT".equals(id)) return RemoteFileRecord.DONE;
|
|
|
|
return new RemoteFileRecord(name, mode, size, time);
|
2014-03-19 10:06:40 +01:00
|
|
|
}
|
2014-03-19 21:15:40 +01:00
|
|
|
|
2014-03-20 10:10:35 +01:00
|
|
|
private void sendChunk(byte[] buffer, int offset, int length) throws IOException {
|
2014-03-19 21:15:40 +01:00
|
|
|
output.writeBytes("DATA");
|
|
|
|
output.writeInt(Integer.reverseBytes(length));
|
|
|
|
output.write(buffer, offset, length);
|
|
|
|
}
|
|
|
|
|
2014-03-20 21:31:25 +01:00
|
|
|
private int readChunk(byte[] buffer) throws IOException, JadbException {
|
2014-03-20 10:10:35 +01:00
|
|
|
String id = readString(4);
|
|
|
|
int n = readInt();
|
2016-03-20 09:13:30 +01:00
|
|
|
if ("FAIL".equals(id)) {
|
2014-03-20 21:31:25 +01:00
|
|
|
throw new JadbException(readString(n));
|
|
|
|
}
|
|
|
|
if (!"DATA".equals(id)) return -1;
|
2014-03-25 15:46:54 +01:00
|
|
|
input.readFully(buffer, 0, n);
|
|
|
|
return n;
|
2014-03-20 10:10:35 +01:00
|
|
|
}
|
|
|
|
|
2014-03-19 21:15:40 +01:00
|
|
|
public void sendStream(InputStream in) throws IOException {
|
|
|
|
byte[] buffer = new byte[1024 * 64];
|
|
|
|
int n = in.read(buffer);
|
|
|
|
while (n != -1) {
|
2014-03-20 10:10:35 +01:00
|
|
|
sendChunk(buffer, 0, n);
|
2014-03-19 21:15:40 +01:00
|
|
|
n = in.read(buffer);
|
|
|
|
}
|
|
|
|
}
|
2014-03-20 10:10:35 +01:00
|
|
|
|
2014-03-20 21:31:25 +01:00
|
|
|
public void readChunksTo(OutputStream stream) throws IOException, JadbException {
|
2014-03-20 10:10:35 +01:00
|
|
|
byte[] buffer = new byte[1024 * 64];
|
|
|
|
int n = readChunk(buffer);
|
|
|
|
while (n != -1) {
|
|
|
|
stream.write(buffer, 0, n);
|
|
|
|
n = readChunk(buffer);
|
|
|
|
}
|
|
|
|
}
|
2014-03-19 10:06:40 +01:00
|
|
|
}
|