Updated the TCP Handshake to also negotiate a protocol version. +Formatting etc.

This commit is contained in:
Maschell 2017-04-10 15:43:54 +02:00
parent 857c5d397d
commit 8197db4d86
9 changed files with 137 additions and 33 deletions

View File

@ -41,8 +41,6 @@ import lombok.Getter;
import net.ash.HIDToVPADNetworkClient.manager.ControllerManager;
import net.ash.HIDToVPADNetworkClient.network.NetworkManager;
import net.ash.HIDToVPADNetworkClient.util.Settings;
import java.awt.BorderLayout;
import java.awt.CardLayout;
public final class GuiInputControls extends JPanel {
private static final long serialVersionUID = 1L;
@ -132,7 +130,6 @@ public final class GuiInputControls extends JPanel {
add(Box.createRigidArea(new Dimension(1, 4)));
add(autoActivateWrap);
add(Box.createVerticalGlue());
add(Box.createVerticalGlue());

View File

@ -25,42 +25,47 @@ package net.ash.HIDToVPADNetworkClient.hid;
public interface HidDevice {
/**
* Opens the HidDevice for usage.
*
* @return true on success, false when it failed.
*/
boolean open();
/**
* Closes the HidDevice
*/
void close();
/**
* Returns the VendorID of the HidDevice
*
* @return vendorID
*/
short getVendorId();
/**
* Returns the ProductID of the HidDevice
*
* @return productID
*/
short getProductId();
/**
* Returns the latest data.
*
* @return An byte array containing the latest data. If no data is present, it'll return a empty byte array
*/
byte[] getLatestData();
/**
* Retuns the Usage of this HID-Device
*
* @return usage
*/
short getUsage();
/**
* Returns the path of this HidDevice
*
* @return path
*/
String getPath();

View File

@ -37,12 +37,13 @@ public class HidManager {
public static HidDevice getDeviceByPath(String path) throws IOException {
return backend.getDeviceByPath(path);
}
public static List<HidDevice> getAttachedControllers() {
List<HidDevice> connectedGamepads = new ArrayList<HidDevice>();
for (HidDevice info : backend.enumerateDevices()) {
if (isGamepad(info)) {
// Skip Xbox controller under windows. We should use XInput instead.
if (isXboxController(info) && Settings.isWindows()) {
continue;
@ -61,17 +62,17 @@ public class HidManager {
private static boolean isPlaystationController(HidDevice info) {
if (info == null) return false;
return (info.getVendorId() == 0x054c);
return (info.getVendorId() == (short) 0x054c);
}
private static boolean isNintendoController(HidDevice info) {
if (info == null) return false;
return (info.getVendorId() == 0x57e);
return (info.getVendorId() == (short) 0x57e);
}
private static boolean isXboxController(HidDevice info) {
if (info == null) return false;
return (info.getVendorId() == 0x045e) && ((info.getProductId() == 0x02ff) || (info.getProductId() == 0x02a1));
return (info.getVendorId() == (short) 0x045e) && ((info.getProductId() == (short) 0x02ff) || (info.getProductId() == (short) 0x02a1));
}
static {
@ -81,13 +82,13 @@ public class HidManager {
backend = new PureJavaHidManagerBackend();
} else if (Settings.isLinux()) {
backend = new Hid4JavaHidManagerBackend();
} else{
} else {
backend = null;
}
log.info("Plattform: " + System.getProperty("os.name"));
if(backend != null){
log.info("Backend: " + backend.getClass().getSimpleName());
}else{
if (backend != null) {
log.info("Backend: " + backend.getClass().getSimpleName());
} else {
log.info("No Backend loaded =(");
}
}

View File

@ -68,7 +68,7 @@ class Hid4JavaHidDevice implements HidDevice {
@Override
public String toString() {
return "Hid4JavaHidDevice [myDevice=" + myDevice + ", data=" + Arrays.toString(data) + "]";
return "Hid4JavaHidDevice [vid= " + getVendorId() + ", pid= " + getProductId() + ", data=" + Arrays.toString(data) + "]";
}
@Override

View File

@ -89,4 +89,10 @@ class PureJavaHidDevice implements HidDevice, InputReportListener {
public String getPath() {
return myDeviceInfo.getPath();
}
@Override
public String toString() {
return "PureJavaHidDevice [vid= " + String.format("%04X", getVendorId()) + ", pid= " + String.format("%04X", getProductId()) + ", path= " + getPath()
+ ", data=" + Arrays.toString(currentData) + "]";
}
}

View File

@ -31,6 +31,7 @@ import lombok.Synchronized;
import lombok.extern.java.Log;
import net.ash.HIDToVPADNetworkClient.controller.Controller;
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
import net.ash.HIDToVPADNetworkClient.network.Protocol.HandshakeReturnCode;
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
import net.ash.HIDToVPADNetworkClient.util.Settings;
@ -163,7 +164,7 @@ public final class NetworkManager implements Runnable {
try {
pong = tcpClient.recvByte();
if (pong == Protocol.TCP_CMD_PONG) {
log.info("Ping...Pong!");
if (Settings.DEBUG_TCP_PING_PONG) log.info("Ping...Pong!");
} else {
log.info("Got no valid response to a Ping. Disconnecting.");
disconnect();
@ -344,13 +345,18 @@ public final class NetworkManager implements Runnable {
boolean result = false;
log.info("Trying to connect to: " + ip);
try {
tcpClient.connect(ip);
log.info("TCP Connected!");
udpClient = UDPClient.createUDPClient(ip);
if (udpClient != null) {
result = true;
HandshakeReturnCode tcpresult = tcpClient.connect(ip);
if (tcpresult == HandshakeReturnCode.GOOD_HANDSHAKE) {
log.info("TCP Connected!");
udpClient = UDPClient.createUDPClient(ip);
if (udpClient != null) {
result = true;
}
} else {
String error = "Error while connecting.";
log.info(error);
}
} catch (Exception e) {
} catch (IOException e) {
String error = "Error while connecting: " + e.getMessage();
log.info(error);
MessageBoxManager.addMessageBox(error, MessageBox.MESSAGE_WARNING);

View File

@ -28,13 +28,22 @@ import java.nio.ByteBuffer;
import java.util.List;
import lombok.extern.java.Log;
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
@Log
final class Protocol {
private static ProtocolVersion currentProtocol = ProtocolVersion.MY_VERSION;
static final int TCP_PORT = 8112;
static final int UDP_PORT = 8113;
static final byte TCP_HANDSHAKE = 0x12;
static final byte TCP_HANDSHAKE_VERSION_1 = 0x12;
static final byte TCP_HANDSHAKE_VERSION_2 = 0x13;
static final byte TCP_HANDSHAKE_ABORT = 0x30;
static final byte TCP_HANDSHAKE = TCP_HANDSHAKE_VERSION_2; // default version.
static final byte TCP_SAME_CLIENT = 0x20;
static final byte TCP_NEW_CLIENT = 0x21;
@ -96,4 +105,85 @@ final class Protocol {
return bos.toByteArray();
}
public static HandshakeReturnCode doHandshake(TCPClient tcpClient) throws IOException {
Protocol.currentProtocol = ProtocolVersion.MY_VERSION;
HandshakeReturnCode resultHandshake = HandshakeReturnCode.BAD_HANDSHAKE;
ProtocolVersion wiiuProtocolVersion = ProtocolVersion.getEnumByValue(tcpClient.recvByte());
/**
* Handshake 1. At first the server (WiiU) sends his protocol version 2. The network clients answers with his preferred version (which needs to be
* equals or lower the version the server (WiiU) sent him) or an abort command. 3a. If the client sent a abort, close the connection and wait for
* another connection 3b. If the client sent his highest supported version, the server confirm that he is able to use this version (by sending the
* version back) or sending a abort command to disconnect.
**/
if (wiiuProtocolVersion == ProtocolVersion.UNKOWN) {
log.info("Connected to a WiiU with an unsupported protocol version. It may support an older though");
tcpClient.send(ProtocolVersion.MY_VERSION.getVersionByte());
} else if (wiiuProtocolVersion == ProtocolVersion.Version1) {
// Do nothing.
} else if (wiiuProtocolVersion == ProtocolVersion.Version2) {
// We want to do version 2!
tcpClient.send(ProtocolVersion.Version2.getVersionByte());
}
if (wiiuProtocolVersion == ProtocolVersion.Version1) {
Protocol.currentProtocol = ProtocolVersion.Version1;
resultHandshake = HandshakeReturnCode.GOOD_HANDSHAKE;
} else {
ProtocolVersion finalProtocolVersion = ProtocolVersion.getEnumByValue(tcpClient.recvByte());
if (finalProtocolVersion == ProtocolVersion.Abort) {
String message = "The HIDtoVPAD version is not supported. Try to use the newest version of HIDtoVPAD and this network client.";
log.info(message);
MessageBoxManager.addMessageBox(message, MessageBox.MESSAGE_ERROR);
resultHandshake = HandshakeReturnCode.BAD_HANDSHAKE;
} else if (finalProtocolVersion == ProtocolVersion.UNKOWN) {
String message = "Something stranged happend while connecting. Try to use the newest version of HIDtoVPAD and this network client.";
log.info(message);
MessageBoxManager.addMessageBox(message, MessageBox.MESSAGE_ERROR);
resultHandshake = HandshakeReturnCode.BAD_HANDSHAKE;
} else {
Protocol.currentProtocol = finalProtocolVersion;
resultHandshake = HandshakeReturnCode.GOOD_HANDSHAKE;
}
}
if (resultHandshake == HandshakeReturnCode.GOOD_HANDSHAKE) {
ActiveControllerManager.getInstance().attachAllActiveControllers();
log.info("Handshake was successful! Using protocol version " + (currentProtocol.getVersionByte() - TCP_HANDSHAKE_VERSION_1 + 1));
return resultHandshake;
} else {
log.info("[TCP] Handshaking failed");
return resultHandshake;
}
// return false;
}
public enum ProtocolVersion {
MY_VERSION((byte) TCP_HANDSHAKE), Version1((byte) TCP_HANDSHAKE_VERSION_1), Version2((byte) TCP_HANDSHAKE_VERSION_2), Abort(
(byte) TCP_HANDSHAKE_ABORT), UNKOWN((byte) 0x00);
private final byte versionByte;
private ProtocolVersion(byte versionByte) {
this.versionByte = versionByte;
}
public static ProtocolVersion getEnumByValue(byte value) {
switch (value) {
case TCP_HANDSHAKE_VERSION_1:
return ProtocolVersion.Version1;
case TCP_HANDSHAKE_VERSION_2:
return ProtocolVersion.Version2;
case TCP_HANDSHAKE_ABORT:
return ProtocolVersion.Abort;
default:
return ProtocolVersion.UNKOWN;
}
}
public byte getVersionByte() {
return versionByte;
}
}
}

View File

@ -33,7 +33,6 @@ import lombok.Getter;
import lombok.Setter;
import lombok.Synchronized;
import lombok.extern.java.Log;
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
import net.ash.HIDToVPADNetworkClient.network.Protocol.HandshakeReturnCode;
import net.ash.HIDToVPADNetworkClient.util.Settings;
@ -53,23 +52,18 @@ final class TCPClient {
}
@Synchronized("lock")
void connect(String ip) throws Exception {
HandshakeReturnCode connect(String ip) throws IOException {
sock = new Socket();
sock.connect(new InetSocketAddress(ip, Protocol.TCP_PORT), 2000);
in = new DataInputStream(sock.getInputStream());
out = new DataOutputStream(sock.getOutputStream());
HandshakeReturnCode resultHandshake = HandshakeReturnCode.GOOD_HANDSHAKE;
if (recvByte() != Protocol.TCP_HANDSHAKE) resultHandshake = HandshakeReturnCode.BAD_HANDSHAKE;
if (resultHandshake == HandshakeReturnCode.GOOD_HANDSHAKE) {
ActiveControllerManager.getInstance().attachAllActiveControllers();
HandshakeReturnCode result = Protocol.doHandshake(this);
if (result == HandshakeReturnCode.GOOD_HANDSHAKE) {
this.ip = ip;
shouldRetry = 0;
} else {
log.info("[TCP] Handshaking failed");
throw new Exception();
}
return result;
}
@Synchronized("lock")
@ -112,6 +106,10 @@ final class TCPClient {
send(ByteBuffer.allocate(4).putInt(value).array());
}
public void send(byte _byte) throws IOException {
send(ByteBuffer.allocate(1).put(_byte).array());
}
@Synchronized("lock")
byte recvByte() throws IOException {
return in.readByte();

View File

@ -49,6 +49,7 @@ public final class Settings {
public static boolean SCAN_AUTOMATICALLY_FOR_CONTROLLERS = true;
public static boolean DEBUG_UDP_OUTPUT = false;
public static boolean DEBUG_TCP_PING_PONG = false;
public static boolean SEND_DATA_ONLY_ON_CHANGE = false;
public static boolean AUTO_ACTIVATE_CONTROLLER = false;