From 4377808896e820a0c461129386f75f2c0d8c33a0 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 14 Sep 2014 23:58:42 -0700 Subject: [PATCH] Remove unnecessary byte buffer allocations in the input path --- .../nvstream/input/ControllerPacket.java | 21 +++++--- .../nvstream/input/ControllerStream.java | 52 +++++++++++++------ .../limelight/nvstream/input/InputPacket.java | 26 +++++++--- .../nvstream/input/KeyboardPacket.java | 20 ++++--- .../nvstream/input/MouseButtonPacket.java | 19 ++++--- .../nvstream/input/MouseMovePacket.java | 18 ++++--- .../nvstream/input/MouseScrollPacket.java | 18 ++++--- 7 files changed, 115 insertions(+), 59 deletions(-) diff --git a/moonlight-common/src/com/limelight/nvstream/input/ControllerPacket.java b/moonlight-common/src/com/limelight/nvstream/input/ControllerPacket.java index bf985d54..1b1b3152 100644 --- a/moonlight-common/src/com/limelight/nvstream/input/ControllerPacket.java +++ b/moonlight-common/src/com/limelight/nvstream/input/ControllerPacket.java @@ -68,12 +68,14 @@ public class ControllerPacket extends InputPacket { this.rightStickX = rightStickX; this.rightStickY = rightStickY; } - - public byte[] toWire() - { - ByteBuffer bb = ByteBuffer.allocate(PACKET_LENGTH).order(ByteOrder.LITTLE_ENDIAN); - - bb.put(toWireHeader()); + + @Override + public ByteOrder getPayloadByteOrder() { + return ByteOrder.LITTLE_ENDIAN; + } + + @Override + public void toWirePayload(ByteBuffer bb) { bb.put(HEADER); bb.putShort(buttonFlags); bb.put(leftTrigger); @@ -83,7 +85,10 @@ public class ControllerPacket extends InputPacket { bb.putShort(rightStickX); bb.putShort(rightStickY); bb.put(TAIL); - - return bb.array(); + } + + @Override + public int getPacketLength() { + return PACKET_LENGTH; } } \ No newline at end of file diff --git a/moonlight-common/src/com/limelight/nvstream/input/ControllerStream.java b/moonlight-common/src/com/limelight/nvstream/input/ControllerStream.java index a37f5759..215128b0 100644 --- a/moonlight-common/src/com/limelight/nvstream/input/ControllerStream.java +++ b/moonlight-common/src/com/limelight/nvstream/input/ControllerStream.java @@ -6,10 +6,10 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.Arrays; import java.util.Iterator; import java.util.concurrent.LinkedBlockingQueue; @@ -35,6 +35,10 @@ public class ControllerStream { private Thread inputThread; private LinkedBlockingQueue inputQueue = new LinkedBlockingQueue(); + private ByteBuffer littleEndianBuffer = ByteBuffer.allocate(128).order(ByteOrder.LITTLE_ENDIAN); + private ByteBuffer bigEndianBuffer = ByteBuffer.allocate(128).order(ByteOrder.BIG_ENDIAN); + private ByteBuffer sendBuffer = ByteBuffer.allocate(128).order(ByteOrder.BIG_ENDIAN); + public ControllerStream(InetAddress host, SecretKey riKey, int riKeyId, NvConnectionListener listener) { this.host = host; @@ -205,39 +209,53 @@ public class ControllerStream { return ((length + 15) / 16) * 16; } - private static byte[] padData(byte[] data) { + private static int inPlacePadData(byte[] data, int length) { // This implements the PKCS7 padding algorithm - if ((data.length % 16) == 0) { + if ((length % 16) == 0) { // Already a multiple of 16 - return data; + return length; } - byte[] padded = Arrays.copyOf(data, getPaddedSize(data.length)); - byte paddingByte = (byte)(16 - (data.length % 16)); + int paddedLength = getPaddedSize(length); + byte paddingByte = (byte)(16 - (length % 16)); - for (int i = data.length; i < padded.length; i++) { - padded[i] = paddingByte; + for (int i = length; i < paddedLength; i++) { + data[i] = paddingByte; } - return padded; + return paddedLength; } - private byte[] encryptAesInputData(byte[] data) throws Exception { - return riCipher.update(padData(data)); + private int encryptAesInputData(byte[] inputData, int inputLength, byte[] outputData, int outputOffset) throws Exception { + int encryptedLength = inPlacePadData(inputData, inputLength); + riCipher.update(inputData, 0, encryptedLength, outputData, outputOffset); + return encryptedLength; } private void sendPacket(InputPacket packet) throws IOException { - byte[] toWire = packet.toWire(); + ByteBuffer toWireBuffer; + + // Choose which byte order we'll be using for converting to wire form + if (packet.getPayloadByteOrder() == ByteOrder.BIG_ENDIAN) { + toWireBuffer = bigEndianBuffer; + } + else { + toWireBuffer = littleEndianBuffer; + } + + // Store the packet in wire form in the byte buffer + packet.toWire(toWireBuffer); + int packetLen = packet.getPacketLength(); // Pad to 16 byte chunks - int paddedLength = getPaddedSize(toWire.length); + int paddedLength = getPaddedSize(packetLen); // Allocate a byte buffer to represent the final packet - ByteBuffer bb = ByteBuffer.allocate(4 + paddedLength); - bb.putInt(paddedLength); + sendBuffer.rewind(); + sendBuffer.putInt(paddedLength); try { - bb.put(encryptAesInputData(toWire)); + encryptAesInputData(toWireBuffer.array(), packetLen, sendBuffer.array(), 4); } catch (Exception e) { // Should never happen e.printStackTrace(); @@ -245,7 +263,7 @@ public class ControllerStream { } // Send the packet - out.write(bb.array()); + out.write(sendBuffer.array(), 0, paddedLength + 4); out.flush(); } diff --git a/moonlight-common/src/com/limelight/nvstream/input/InputPacket.java b/moonlight-common/src/com/limelight/nvstream/input/InputPacket.java index dec3ff11..9798fbe8 100644 --- a/moonlight-common/src/com/limelight/nvstream/input/InputPacket.java +++ b/moonlight-common/src/com/limelight/nvstream/input/InputPacket.java @@ -13,14 +13,26 @@ public abstract class InputPacket { this.packetType = packetType; } - public abstract byte[] toWire(); + public abstract ByteOrder getPayloadByteOrder(); - public byte[] toWireHeader() + public abstract void toWirePayload(ByteBuffer bb); + + public abstract int getPacketLength(); + + public void toWireHeader(ByteBuffer bb) { - ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN); - - bb.putInt(packetType); - - return bb.array(); + // We don't use putInt() here because it will be subject to the byte order + // of the byte buffer. We just write it as a big endian int. + bb.put((byte)(packetType >> 24)); + bb.put((byte)(packetType >> 16)); + bb.put((byte)(packetType >> 8)); + bb.put((byte)(packetType & 0xFF)); + } + + public void toWire(ByteBuffer bb) + { + bb.rewind(); + toWireHeader(bb); + toWirePayload(bb); } } diff --git a/moonlight-common/src/com/limelight/nvstream/input/KeyboardPacket.java b/moonlight-common/src/com/limelight/nvstream/input/KeyboardPacket.java index 4c3a25ad..b28f1e64 100644 --- a/moonlight-common/src/com/limelight/nvstream/input/KeyboardPacket.java +++ b/moonlight-common/src/com/limelight/nvstream/input/KeyboardPacket.java @@ -5,7 +5,7 @@ import java.nio.ByteOrder; public class KeyboardPacket extends InputPacket { private static final int PACKET_TYPE = 0x0A; - private static final int PACKET_LENGTH = 14; + public static final int PACKET_LENGTH = 14; public static final byte KEY_DOWN = 0x03; public static final byte KEY_UP = 0x04; @@ -14,7 +14,6 @@ public class KeyboardPacket extends InputPacket { public static final byte MODIFIER_CTRL = 0x02; public static final byte MODIFIER_ALT = 0x04; - short keyCode; byte keyDirection; byte modifier; @@ -25,12 +24,14 @@ public class KeyboardPacket extends InputPacket { this.keyDirection = keyDirection; this.modifier = modifier; } - + @Override - public byte[] toWire() { - ByteBuffer bb = ByteBuffer.allocate(PACKET_LENGTH).order(ByteOrder.LITTLE_ENDIAN); - - bb.put(toWireHeader()); + public ByteOrder getPayloadByteOrder() { + return ByteOrder.LITTLE_ENDIAN; + } + + @Override + public void toWirePayload(ByteBuffer bb) { bb.put(keyDirection); bb.putShort((short)0); bb.putShort((short)0); @@ -38,7 +39,10 @@ public class KeyboardPacket extends InputPacket { bb.put(modifier); bb.put((byte)0); bb.put((byte)0); + } - return bb.array(); + @Override + public int getPacketLength() { + return PACKET_LENGTH; } } diff --git a/moonlight-common/src/com/limelight/nvstream/input/MouseButtonPacket.java b/moonlight-common/src/com/limelight/nvstream/input/MouseButtonPacket.java index 6852ec4a..c21166c3 100644 --- a/moonlight-common/src/com/limelight/nvstream/input/MouseButtonPacket.java +++ b/moonlight-common/src/com/limelight/nvstream/input/MouseButtonPacket.java @@ -31,13 +31,18 @@ public class MouseButtonPacket extends InputPacket { } @Override - public byte[] toWire() { - ByteBuffer bb = ByteBuffer.allocate(PACKET_LENGTH).order(ByteOrder.BIG_ENDIAN); - - bb.put(toWireHeader()); + public ByteOrder getPayloadByteOrder() { + return ByteOrder.BIG_ENDIAN; + } + + @Override + public void toWirePayload(ByteBuffer bb) { bb.put(buttonEventType); - bb.putInt(mouseButton); - - return bb.array(); + bb.putInt(mouseButton); + } + + @Override + public int getPacketLength() { + return PACKET_LENGTH; } } diff --git a/moonlight-common/src/com/limelight/nvstream/input/MouseMovePacket.java b/moonlight-common/src/com/limelight/nvstream/input/MouseMovePacket.java index a1faabeb..d0726b9f 100644 --- a/moonlight-common/src/com/limelight/nvstream/input/MouseMovePacket.java +++ b/moonlight-common/src/com/limelight/nvstream/input/MouseMovePacket.java @@ -1,6 +1,7 @@ package com.limelight.nvstream.input; import java.nio.ByteBuffer; +import java.nio.ByteOrder; public class MouseMovePacket extends InputPacket { @@ -29,14 +30,19 @@ public class MouseMovePacket extends InputPacket { } @Override - public byte[] toWire() { - ByteBuffer bb = ByteBuffer.allocate(PACKET_LENGTH); - - bb.put(toWireHeader()); + public ByteOrder getPayloadByteOrder() { + return ByteOrder.BIG_ENDIAN; + } + + @Override + public void toWirePayload(ByteBuffer bb) { bb.put(HEADER); bb.putShort(deltaX); bb.putShort(deltaY); - - return bb.array(); + } + + @Override + public int getPacketLength() { + return PACKET_LENGTH; } } diff --git a/moonlight-common/src/com/limelight/nvstream/input/MouseScrollPacket.java b/moonlight-common/src/com/limelight/nvstream/input/MouseScrollPacket.java index 0b0218af..630ee7b9 100644 --- a/moonlight-common/src/com/limelight/nvstream/input/MouseScrollPacket.java +++ b/moonlight-common/src/com/limelight/nvstream/input/MouseScrollPacket.java @@ -1,6 +1,7 @@ package com.limelight.nvstream.input; import java.nio.ByteBuffer; +import java.nio.ByteOrder; public class MouseScrollPacket extends InputPacket { public static final int PACKET_TYPE = 0xa; @@ -17,10 +18,12 @@ public class MouseScrollPacket extends InputPacket { } @Override - public byte[] toWire() { - ByteBuffer bb = ByteBuffer.allocate(PACKET_LENGTH); - - bb.put(toWireHeader()); + public ByteOrder getPayloadByteOrder() { + return ByteOrder.BIG_ENDIAN; + } + + @Override + public void toWirePayload(ByteBuffer bb) { bb.put((byte) 0x09); bb.put((byte) 0); bb.put((byte) 0); @@ -30,7 +33,10 @@ public class MouseScrollPacket extends InputPacket { bb.putShort(scroll); bb.putShort((short) 0); - - return bb.array(); + } + + @Override + public int getPacketLength() { + return PACKET_LENGTH; } }