Skip to content

Instantly share code, notes, and snippets.

@pgaskin
Created September 4, 2022 00:54
Show Gist options
  • Save pgaskin/ef2a4ca33b760db2972b90604e020d21 to your computer and use it in GitHub Desktop.
Save pgaskin/ef2a4ca33b760db2972b90604e020d21 to your computer and use it in GitHub Desktop.
package net.pgaskin.kl125gesture;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
public class SimpleLinkieClient implements Closeable {
private InetSocketAddress addr;
private final int timeout;
private final DatagramSocket udp;
public SimpleLinkieClient(String host) throws SocketException {
this(host, 1000);
}
public SimpleLinkieClient(String host, int timeout) throws SocketException {
this.addr = new InetSocketAddress(host, 9999);
this.timeout = timeout;
this.udp = new DatagramSocket();
try {
this.udp.setTrafficClass(0x04 | 0x10);
} catch (Exception ex) {
// ignored
}
}
@Override
public void close() {
this.udp.close();
}
public InetSocketAddress getAddr() throws UnknownHostException {
if (this.addr.isUnresolved()) {
InetAddress addr = InetAddress.getByName(this.addr.getHostString());
this.addr = new InetSocketAddress(addr, 9999);
}
return this.addr;
}
public void send(JSONObject obj) throws IOException, UnknownHostException {
this.send(obj.toString());
}
public void send(String req) throws IOException, UnknownHostException {
this.send(req.getBytes(StandardCharsets.UTF_8));
}
private void send(byte[] req) throws IOException, UnknownHostException {
DatagramPacket pkt = new DatagramPacket(req, req.length, this.getAddr());
this.encrypt(req);
this.udp.send(pkt);
}
public JSONObject sendChecked(JSONObject req) throws IOException, UnknownHostException, JSONException {
return this.sendChecked(req.toString());
}
public JSONObject sendChecked(JSONObject req, int timeout) throws IOException, UnknownHostException, JSONException {
return this.sendChecked(req.toString(), timeout);
}
public JSONObject sendChecked(String req) throws IOException, UnknownHostException, JSONException {
return this.sendChecked(req.getBytes(StandardCharsets.UTF_8), this.timeout);
}
public JSONObject sendChecked(String req, int timeout) throws IOException, UnknownHostException, JSONException {
return this.sendChecked(req.getBytes(StandardCharsets.UTF_8), timeout);
}
private JSONObject sendChecked(byte[] req, int timeout) throws IOException, UnknownHostException, JSONException {
try (Socket tcp = new Socket()) {
tcp.connect(this.getAddr(), timeout);
try {
tcp.setTrafficClass(0x04 | 0x10);
} catch (Exception ex) {
// ignored
}
try {
tcp.setTcpNoDelay(true);
} catch (Exception ex) {
// ignored
}
DataOutputStream out = new DataOutputStream(tcp.getOutputStream());
this.encrypt(req);
byte[] enc = new byte[req.length + 4];
enc[0] = ((byte) ((req.length >> 24) & 0xFF));
enc[1] = ((byte) ((req.length >> 16) & 0xFF));
enc[2] = ((byte) ((req.length >> 8) & 0xFF));
enc[3] = ((byte) (req.length & 0xFF));
System.arraycopy(req, 0, enc, 4, req.length);
out.write(enc);
DataInputStream in = new DataInputStream(tcp.getInputStream());
tcp.setSoTimeout(this.timeout);
byte[] lenb = new byte[4];
in.readFully(lenb);
int len = lenb[3] | (lenb[2] << 8) | (lenb[1] << 16) | (lenb[0] << 24);
if (len < 0 || len > 16384)
throw new IOException("Invalid response length " + len);
byte[] buf = new byte[len];
in.readFully(buf);
this.decrypt(buf);
return new JSONObject(new String(buf, StandardCharsets.UTF_8));
}
}
private void encrypt(byte[] buf) {
byte key = (byte) 0xAB;
for (int i = 0; i < buf.length; i++) {
buf[i] = key = (byte) (buf[i] ^ key);
}
}
private void decrypt(byte[] buf) {
byte key = (byte) 0xAB;
for (int i = 0; i < buf.length; i++) {
byte x = buf[i];
buf[i] = (byte)(x^key);
key = x;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment